I’ve implemented standard variance shadow mapping and it works as expected if I use an unfiltered 32-bit floating-point render target during the shadow pass:
[ATTACH=CONFIG]1363[/ATTACH]
However, if I setup a render target with linear, bilinear or trilinear filtering instead, all fragments that lie behind a certain distance from the camera are in shadow:
[ATTACH=CONFIG]1364[/ATTACH]
Here I have moved a little closer:
[ATTACH=CONFIG]1365[/ATTACH]
What’s happening here?!
Common vertex shader:
void main() {
vec4 objectSpacePosition = in_position;
vec4 worldSpacePosition = in_modelMatrix*objectSpacePosition;
vec4 cameraSpacePosition = in_viewMatrix*worldSpacePosition;
#ifdef LIGHT_COUNT
#if LIGHT_COUNT > 0
for (int i = 0; i < LIGHT_COUNT; i++) {
Light light = in_lights[i];
v_lightSpacePosition[i] = light.viewMatrix * worldSpacePosition;
}
#endif
#endif
vec4 screenSpacePosition = in_projectionMatrix*cameraSpacePosition;
gl_Position = screenSpacePosition;
}
Shadow pass shader:
void main() {
#ifdef LIGHT_COUNT
#if LIGHT_COUNT > 0
Light light = in_lights[0];
vec4 lightSpacePosition = v_lightSpacePosition[0];
vec4 lightProjection = light.projectionMatrix * lightSpacePosition;
vec2 shadowMapCoords = (lightProjection.xy/lightProjection.w)*0.5+0.5;
float depth = lightProjection.z;
gl_FragColor = vec4(depth, depth*depth, depth, depth*depth);
#endif
#endif
}
Fragment shader:
float shadowMapping(sampler2D shadowMap, vec2 texCoords, float lightDistance, int shadowIndex, float varianceOffset){
vec4 shadow = texture2D(shadowMap, texCoords);
vec2 moments = vec2(1.0, 1.0);
if (shadowIndex == 0) {
moments = shadow.rg;
} else if (shadowIndex == 1) {
moments = shadow.ba;
}
float variance = moments.y - (moments.x*moments.x);
variance = max(variance, varianceOffset);
float difference = lightDistance - moments.x;
float upperBound = variance / (variance + difference*difference);
return max(upperBound, step(lightDistance, moments.x));
}
void main() {
vec3 totalDiffuseColor = vec3(0.0);
#ifdef LIGHT_COUNT
#if LIGHT_COUNT > 0
for (int i = 0; i < LIGHT_COUNT; i++) {
Light light = in_lights[i];
vec4 lightSpacePosition = v_lightSpacePosition[i];
vec4 lightProjection = light.projectionMatrix * lightSpacePosition;
vec2 shadowMapCoords = (lightProjection.xy/lightProjection.w)*0.5+0.5;
vec3 diffuse_color = 1.0;
/* fresnel term, attenuation, etc. */
#ifdef SHADOW_MAPPING
diffuse_color *= shadowMapping(shadowMap, shadowMapCoords, lightProjection.z, light.shadowIndex, in_varianceOffset);
#endif
totalDiffuseColor += diffuse_color;
}
#endif
#endif
gl_FragColor = vec4(totalDiffuseColor, 1.0);
}