It seems there is something wrong with the calculation of the cascaded shadow generator’s matrices in some situation, as it get negative depth in the shadow map.
Notice cascade 1 works well, cascade 0 and cascade 2 has negative depths, and cascadeBlendPercentage cause the self shadow, cascade 3 should works well but it have depth over 1.
Regarding the playground, the z-fighting is expected because of the very small depth range: you can either lower the blend percentage or raise the bias to fix it.
What’s not expected are the negative depth values. Your screenshot shows that the texture is RGBA, but by default it should be just RED: did you change some settings in the PG before taking the screenshot with RenderDoc?
Actually bias helps little, that’s why I say it is a “serious” one, the noise is because I’m not using PCF so that I can see shadow map, it is expected, sorry I don’t make it clear.
The question is cascade 2 have depth values equal 0(it is not expected I think) so it will have shadow all the time in this perspective, when cascade 1 blend with cascade 2, the error shadow of cascade 2 is blended, so there will be self shadow.
My renderdoc screenshot is just the calculation of the depth result but not the final output depth, the output depth is clamped to zero when calculated as negative, which is as what you expected, sorry for the misunderstanding.
My bad, I was looking at the depth texture, not the color texture with depth values!
There are negative values for depth because of depth clamping, which isn’t a problem per see, but we did have a problem when calculating the minZ/maxZ of the cascade when depth clamping is enabled, here’s the PG that fixes it:
I still have a question, if a depth value is calculated as negative, it means it is out of range. But after saturate, the negative will be clamped to 0, however a 0 depth will cast shadow. So I think when the depth value is negative, it should be 1 to avoid casting shadow.
No, negative values mean an object is behind the near plane of the cascade frustum, but it’s still shadowing other objects of the scene, so the value in the shadow map should be 0. It’s the purpose of depth clamping: tighten the [near,far] range of the frustum to improve shadow map accuracy, and by doing so, some shadow casters will be behind the near plane and will produce negative depth values (clamped to 0 afterwards). Note that objects further away than the far plane will produce depth values greater than 1 and will be clamped to 1 (again, only when depth clamping is enabled).
Without depth clamping, the near plane must be lowered so that all the casters are in front of it. With depth clamping, we can have a near plane with a higher value, but at the cost of all values in the shadow map being 0 for the casters behind it. It can produce artifacts, as in your example, because the casters behind the near plane are basically “flat projected” into the shadow map: they all generate 0 values in the shadow map.
However, your example is a bit contrieved, as you shouldn’t be using a 100% cascade blend, as this could produce rendering artifacts even when depth clamping isn’t being used. If you really must use such high cascade blend percentages, you can simply disable depth clamping to remove the artifacts.
Here’s a scene that fails with your change:
If you uncomment line 137 and comment line 138, you will see that the shadow disappears.
Thanks for the detailed explainations! I dig into shadows these days and learned a lot!
I found the reason is that we use LESS rather than LEQUAL for the depth stencil texture of the shadow generator as the default value. So when using the PCF, it will display different from none filter, I was wondering why we use LESS as the default value?
Edit: I just realized it will cause a similar problem when the next cascade should cast shadow when using LEQUAL. So the problem is actually the range of depth, not really sure but it seems using a color channel with negative values to store the depth can get rid of the problem.
No, during my tests, I tried to keep negative values in the depth map, but in some cases, this also produced artifacts. I don’t think there is a definitive answer. Shadow generation can create artifacts, and you will have to adjust the settings to try to get rid of them.