Cascaded Shadow Maps

It’s been a while since CSM has been removed from THREE (R66 i guess) and we still are stuck with limited and manual shadows (directional light / sun) while it’s a requirement for scenes bigger than a single spot.

CSM is basically a LOD technique for shadows, without dealing with the actual boundary/frustum of the lights manually. The camera frustum is splitted into sections using the resolution on the actual section most effective for its boundary only, it allows automatic shadows for the entire scene, especially required for any large scenes/landscapes.

I delayed the topic myself for a while as i thought it could get restored soon, but it doesnt seem to get anytime soon. I only tested a naive geoclipping approach as experiment outside the core. I looked into the old implementation now. An old example can be seen here:

I doubt it is worth just reimplementing it, since i see some issues in it, such as more far sections not properly covering the frustum (could have been not an issue back then), the seams require a smooth transition and i’m not sure if the frustums splits are made optimally. Did anyone fiddled with CSM with THREE yet? Asides of the old implementation and some sources about CSM, i’d appericate if someone has an experiment on it to quickly get to the best result.


I want to mention how very much I want this.

I fiddled a bit with CSM, but I found that my usecase is served quite well with automated shadow-camera management on a directional light fitting the shadow camera frustum into the view frustum. One problem I see with CSM is that it requires several passes over the geometry, namely as many as you have cascades, if your scene has a lot of geometry or a lot of draw-calls - this can degrade your performance quite a lot. That being said - when I played with CSM in three.js years ago - seams were fine, and in fact - if you pay close attention to some of the modern AAA games - you will see much the same. You generally don’t notice them, unless you’re really looking for them.

The approach of a single, managed shadow camera only works for top-down kinds of views, when you have a horizon line you really need that CSM goodness.


Yes efficient CSM requires a faster scene management for culling and other optimizations, but rendering depth only isn’t too costly for the fragment part. For large+rich worlds some LOD is required anyway, additionally i use a auto-impostor system which will basically only render quads/silhouettes of most objects for the larger/more distant sections.

I’m not sure if the demo has more issues than the wrong frustum and if it was different years ago, but the seams are quiet noticeable, mostly by the low resolution, as mentioned i don’t think the sections are optimally. I will implement it outside the core soon, i need some more improvements such as brightness for translucent materials and reducing pixelation.

1 Like

I’ve been recently playing with the old r65 and tried to debug, but it’s hard to find since there has been changed a lot since those ~40 other releases.

Actually CSM is quiet more efficient than having just one directional light constantly covering the entire scene, additionally it frustum checks every single object even though you might intent to render all anyway. Each cascade only renders a section of the camera frustum, in a large scene where CSM gets a requirement for shadows a spatial index would come in anyway.

I can’t really see those in engines like Unreal or Unity, but even though i agree since the screen pixel ratio will make the transition not disturbing, the split distances in the old implementation by far aren’t ideal.

Regarding soft shadows, it seems from tests i did the best shadow result can be archived by anti-aliasing/blurring it in screenspace, since the depth buffer is required anyway for this it even makes contact hardening possible. I don’t think this would be ever implemented like this in THREE though.

Hey @Fyrestar,

I don’t think we really disagree on much. I think CSM is brilliant, though I do believe it adds extra complexity to the implementation in order to do right. The extra passes I mentioned were at the boundaries, you will have some objects in more than 1 frusta typically, which means you end up submitting it to the GPU several times.

I agree that if you are serious about using CSM in real projects where performance matters - you pretty much have to use a spatial index, otherwise you’re doing 4 culling loops over your scene objects (for 3 cascades + the main render pass).

I think reviving CSM would be a boon to the three.js community. I wish you best of luck in your endeavor! :dolphin:

1 Like

Technically it isn’t too complex since it is almost just the frustum management, but in detail there are some challenging things.

Yes you’ll also often render objects outside the frustum since they overlap with the cascade frustum, but that isn’t really too costly, rendering depth alone in general (what shadow cameras does) isn’t expensive as the main render pass and with a lower resolution with texture fetches and a lot per pixel code.

btw regarding cost: a sinlge point light already can be more costly, since it renders the scene 6 times with a perspective camera, depending on it’s range. But since there is no scene management it will test against the entire scene 6 times.

Thanks, i didn’t really had much time for this yet

1 Like