Issue with CascadedShadowMap + ShadowOnlyMaterial

I’m using CascadedShadowMap in my scene and it works like a charm with Standard and PBR materials. The problem is that when I try using the ShadowOnlyMaterial I get elongated bands

This occurs only when I enable autoCalcDepthBounds. I need this enabled to get crisp shadows.

I tried playing around with camera.maxZ and I’m calling the splitFrustum() function, but it doesn’t seem to help.

I created a playground scene for demonstration and I’m also attaching a screenshot of my scene:

pinging @Evgeni_Popov

I’m on it.

Fixed by:

The problem was that ShadowOnlyMaterial is flagged as transparent and so does not write into the depth buffer. However, autoCalcDepthBounds = true relies on the fact that the depth buffer is updated correctly because it retrieves the min / max z values to work.

Another problem was that the view matrix was not bound to the effect whereas CSM needs it.

Note that for your use case you should be able to use the regular shadow generator, CSM should normally not be beneficiable as long as you tweak the light position as well as the light frustum dimensions:

The colored volume is the light volume. You will get the best results when it fits well the object(s) for which you want to generate the shadows (as in the example PG).

Thanks @Evgeni_Popov for the quick response.

Unfortunately the solution doesn’t work for me because i’m change the light position with a slider in my project. I need the bounds to be calculated automatically for this to work well.

Before trying CSM I worked with usePercentageCloserFiltering. This was ok, but because the ground plane was big the shadow map size had to be set to 5120 for me to achieve chirps shadows.

The reason why I would like to stick to CSM is because it works on all the browsers that I tested on, including mobile. This is not true for usePCF.

CSM salved all my problems. The only issue remaining was to remove the artefacts from the shadowOnlyMaterial.

I will try to experiment with settings a bit more.

For directional lights, the light position does not matter regarding the shadows themselves, but is still relevant to generate the light frustum. So, you can move the position anywhere you want to make the light frustum as tight as possible.


The light direction is rotating, but the light position is such that the light frustum is always a good fit for the skull, so the shadows remain crisp. This PG is made with a standard shadow generator, not with CSM.

If the ground does not cast shadow, it should not be a shadow caster (as in the PG) and so won’t impact the shadow map size. Only shadow casters have to be rendered in the shadow map.

Note that percentage closer filtering (PCF) is a filtering method, not to be confused with the shadow rendering method, which is either the standard way (ShadowGenerator, a single shadow map is used) or CSM (multiple shadow maps are used). You can use PCF with both rendering methods. PCF is the default filtering method for CSM, whereas it is “none” for ShadowGenerator.

As explained above, PCF is the default filtering method for CSM, so if you didn’t change that, PCF should also work with ShadowGenerator.

CSM is WebGL2 only, contrary to ShadowGenerator that will also work in WebGL1. If you target mobiles, it’s likely that it won’t work for a number of people because they don’t support WebGL2 (all iPhones, for eg).

If your use case is like the PG with a single object casting shadows (or multiple objects but that don’t span a large area), then you should be able to achieve very good shadows with the standard shadow generator. Maybe your settings were not right?

Also, performance wise, a single shadow generator is a lot faster than CSM with autoCalcDepthBounds = true.

Thanks @Evgeni_Popov!

Removing the ground from the shadow caster list did the trick.

I ended up using Poisson Sampling. For some reason Percentage Closer Filtering brakes the scene on my Samsung tablet (Chrome). I red somewhere that it could be a driver issue on Samsung devices.

I really like Babylon.js, keep up the good work!