Skip to content

Wrong filters applied when switching shadow map types #25835

@digitalArt3DTobias

Description

@digitalArt3DTobias

Description

Related PR:
#24223 ("Ensures VSM can not just be used when enabling it at application start but also if someone switched from another shadow mapping type like PCF to VSM.").

Problem:
The mapPass bug was fixed with that PR, but the shadow.map.texture filters are not switched.

Reproduction steps

In my little demo app below, VSM shadows are correct (even after switching forth and back) if and only if the type was already set to VSM initially. They are wrong if the initial type was something else.

In this code line it appears that the default filter (LinearFilter) is meant to be applied to VSM shadow map textures, and NearestFilter for the other types.

But these filters are only applied initially (if (shadow.map === null), so switching the shadow type doesn't have an effect on the filters.

Code

My suggestion would be to not only check for null, but also if there has been a recent switch from or to VSM (disposing the previous map before creating a new one):

...

let _previousType = this.type;

this.render = function ( lights, scene, camera ) {

  ...

  const switchedToVSM = _previousType !== VSMShadowMap && this.type === VSMShadowMap;
  const switchedFromVSM = _previousType === VSMShadowMap && this.type !== VSMShadowMap;

  if ( shadow.map === null || switchedToVSM || switchedFromVSM ) {

    const pars = ( this.type !== VSMShadowMap ) ? { minFilter: NearestFilter, magFilter: NearestFilter } : {};

    shadow.map?.dispose();
    shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
    shadow.map.texture.name = light.name + '.shadowMap';

    shadow.camera.updateProjectionMatrix();

  }

  _previousType = this.type;

  ...

BTW:

Is the different treatment of the shadow types even necessary? To me, the non-VSM shadows look the same, no matter whether they have NearestFilters applied or not. And since VSM shadows don't work with NearestFilters, why not just omit the NearestFilters at all? - But it may very well be that I overlooked something(?)

Live example

Here is a small demo app showing the reported issue (comment/uncomment code line 21 and select VSM in the app to see the difference):

jsfiddle demo

Screenshots

Here are two screenshots from the fiddle, showing a VSM shadow with a directional light.

  1. Correct VSM shadow (if VSM was applied initially - even after switching forth and back between different types):

vsm-correct

  1. Wrong VSM shadow (if a different shadow type was applied initially):

vsm-wrong

Version

r151

Device

No response

Browser

No response

OS

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions