Jump to content
  • Advertisement
Sign in to follow this  
skyemaidstone

Struggling with Cascaded Shadow Mapping

This topic is 840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

I've been adding bits and pieces to my 3d engine like deferred lighting and soft particles and shadow mapping and I wanted to use CSM since it seems a standard way of giving good quality shadows across my whole terrain.

 

I THINK I understand the concept after devouring everything I could find on it (the msdn article, dangerzone, Jcoluna and some other bits and pieces) but unfortunately every piece of example code I find has endless extra options which (for me) make it too hard to follow or just large sections with no comment that I have no clue what they do.

 

Anyway I've got as far as making an orthographic projection for my "sunlight camera" and I can make it huge enough to cover the whole map in a horribly blocky camera.

 

Like so:

 

 

csm1.jpg

 

If I draw from the sunlights camera (using the orthographic projection) it looks like this: 

 

csm2.jpg

 

 

Now I can make the Orthographic projection box smaller and the quality improves but then the whole world isn't shadowed and what's worse the player can move out of the area it covers so he's not even self shadowed anymore.

 

I'm clearly missing something.

 

1. How do I make the orthographic projection cover the area around the player?

 

2. How do I slice it up in the direction of the sun light source if that's even correct?

 

3. Some samples seem to use linear depth (z/farclip). Do I need to switch all over my model/terrain shaders and render-to-shadow-map shaders to start writing the depth out like that rather than z/w?

 

Hopefully someone can point me in the right direction. Apologies if any of the questions are meaningless/dumb, as I said I'm struggling with CSM for some reason.

 

Thanks

 

Share this post


Link to post
Share on other sites
Advertisement

Well I'm making some progress anyway. I'm getting one large "cascade" covering the whole world (it's very blocky obviously).

 

I'm stuck again though. Is there some obvious reason my Orthographic camera seems to be kinda sliding sideways as my player rotates?

 

I've got lots of shimmering going on too but I think I read something about stabilising somewhere.

 

Here's the bit that makes my Ortho projections for the shadow casting sunlight style light source:

 

Any help would be greatly appreciated. Or if someone could tell me if I'm using this forum incorrectly that would do, I'm not getting any answers to anything so far. :unsure: .

                    Vector3[] frustumCornersWS = new Vector3[8];
                    Vector3[] frustumCornersLS = new Vector3[8];
                    BoundingFrustum viewFrustum = new BoundingFrustum(_Camera.CameraView * _Camera.CameraProjection);
                    frustumCornersWS = viewFrustum.GetCorners();


                    Vector3 frustumCentroid = new Vector3(0, 0, 0);
                    for (int i = 0; i < 8; i++)
                        frustumCentroid += frustumCornersWS[i];
                    frustumCentroid /= 8;

                    Vector3 sunlightdirection = new Vector3(0.21f, 0.11f, -0.9f);
                    ShadowLightPos = frustumCentroid + (sunlightdirection * 5);
                    ShadowLookAt = frustumCentroid;

                    ShadowLightView = Matrix.CreateLookAt(ShadowLightPos, ShadowLookAt, new Vector3(0, 1, 0));

                    Vector3.Transform(frustumCornersWS, ref ShadowLightView, frustumCornersLS);

                    Vector3 mins = frustumCornersLS[0];
                    Vector3 maxes = frustumCornersLS[0];
                    for (int i = 0; i < 8; i++)
                    {
                        if (frustumCornersLS[i].X > maxes.X)
                            maxes.X = frustumCornersLS[i].X;
                        else if (frustumCornersLS[i].X < mins.X)
                            mins.X = frustumCornersLS[i].X;
                        if (frustumCornersLS[i].Y > maxes.Y)
                            maxes.Y = frustumCornersLS[i].Y;
                        else if (frustumCornersLS[i].Y < mins.Y)
                            mins.Y = frustumCornersLS[i].Y;
                        if (frustumCornersLS[i].Z > maxes.Z)
                            maxes.Z = frustumCornersLS[i].Z;
                        else if (frustumCornersLS[i].Z < mins.Z)
                            mins.Z = frustumCornersLS[i].Z;
                    }

                    ShadowLightProjection = Matrix.CreateOrthographicOffCenter(mins.X, maxes.X, mins.Y, maxes.Y, -maxes.Z - 5f, -mins.Z);

Thanks

Share this post


Link to post
Share on other sites

The point behind cascading shadows is to have multiple cascades, but you are on the right track with your math. The next bit is to split the camera frustum along its z-depth. This yields a smaller frustum closer to the camera, and a larger frustum further away. Render out a shadow map for each cascade, and when sampling, take the sample from the first cascade that the pixel falls inside of.

There was a presentation by Crytek on Ryse thats worth checking out.

Edit:

regarding the shimmering, you want to do rounding on the mins/maxes for stabilization based on the resolution of the shadowmap - basically only ever move the shadow projection in multiples of the size of a pixel.

Edited by Digitalfragment

Share this post


Link to post
Share on other sites

Thanks Digitalfragment.

 

I'm trying to get it working for just one big cascade initially if that makes sense so I can get my head around how an orthogonal shadow casting-light would work. I think I understand how to render them into a divided up render target or texture array and sample from the proper one depending on depth. At least I think I understand that bit...

 

Currently I don't quite get why rotating my player camera is making the sunlight/shadow casting orthogonal slide left/right with rotating the camera view. Hopefully i'll get it soon.

Share this post


Link to post
Share on other sites

Wouldn't that just be the visual side effect caused by the dimensions of the camera frustum changing relative to the shadow direction?
If you are facing toward/away from the light, the frustum will yield a smaller min/max. If you are facing perpendicular, it will be much larger.
 

Share this post


Link to post
Share on other sites

Yep you're right. The problem was that my near Z needed to be moved back towards the direction of the light to include things nearer the light that could potentially cast a shadow.

 

Now by adjusting the far clip I can make multiple shadow maps, A high quality one with the far clip near(ish) the player, a medium quality one with the far clip about halfway to the cameras far clip and a giant bad quality one to cover the entire scene.

 

Not sure if ithat's entirely how it's supposed to work but at least it looks sensible. I think I just need to sample from the correct map in my "combine everything" shader and I'm there.

 

Thanks for the help Digitalfragment.

 

Hopefully someone will tell me if what I'm doing is a big no-no in some way.

Share this post


Link to post
Share on other sites

I would think you need to move near also, so each shadowmap is covering a split segment of the world?

Like: Shadowmap1.near = Shadowmap0.far and so on..

Share this post


Link to post
Share on other sites

I'm just keeping all of my cascades with the same near so they hugely overlap for now. It's all very crude and inefficient but I just want to get it working at all at first then optimise later.

Share this post


Link to post
Share on other sites


Not sure if ithat's entirely how it's supposed to work but at least it looks sensible.


That's pretty much it. There's a little bit of work in tuning it to get rid of artifacts between cascades etc and stabilization, but otherwise the technique is rather simple as you described. If you have framerate issues with recalculating every cascade every frame, you can always stagger updates of the medium/far cascades too.

 

From a tuning point of view it really is dependent on the type of scene you are rendering, for example distances aren't a good metric if your game design suddenly calls for a very tight FOV for zooming (as i discovered the hard way when our artists were given complete control over cutscenes)

Depending on how large your scene is, it might be worthwhile to use a different shadowing technique for the furthest detail, then composite that in with the cascade shadows. For example, using calculating ESM for a mountainous terrain, while using CSM w/PCF for all of the objects on the terrain.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!