I implemented cascaded shadow maps, where shadow maps for each cascade is rendered to one canvas:
The light projections for each cascade are calculated from the bounding spheres of camera sub-frustums:
The code for calculation visibility value:
for (int i = 0; i < 3; i++) {
v_shadowCoord[i] = u_lightVPshifted[i] * vec4(a_WolrdPosition, 1);
}
highp float zTocompare = v_shadowCoord[iCascade].z - bias;
return texture(u_shadowMap, vec3(v_shadowCoord[iCascade].xy, zTocompare));
where v_shadowCoord for first cascade are in (0, 1), (0, 0.33) ranges, for second (0, 1), (0.33, 0.66), third (0, 1), (0.66, 1).
The problem is that I get seams between cascades when anisotropic filtering is enabled. Here is the explanation of problem and suggested fix at the bottom of the page: link
As I understand, for cascade borders the wrong mipmap is selected - the smallest. Because the texels for two neighboring vertices on scene come from different cascades and therefore screen-space derivatives are large. I tried the suggested fix from the site, still have same seam:
highp vec2 uv = v_shadowCoord[iCascade].xy;
highp vec2 dx = dFdx (uv) / u_cascadeScales[iCascade];
highp vec2 dy = dFdy (uv) / u_cascadeScales[iCascade];
highp float zTocompare = (v_shadowCoord[iCascade].z) - bias;
return textureGradOffset(u_shadowMap, vec3(uv, zTocompare), dx, dy, ivec2(0, 0));
I suppose I don't use the right input there. v_shadowCoord I described above, u_cascadeScales are scales of projection sizes in light view space relative to first one: I have (1.0, 14.0, 300.0). Could you please explain how just scaling the derivatives will help selecting right mipmap and suggest what is wrong in the code? I expect that even with that scaling, values on the border will still be mapped to distant texels and wrong mipmap will be used.