Cascading shadow mapping and ESM.

I implemented shadow cascades today. Below is a screenshot of the current shadows, using two cascades. Note the artifacts that I’ve highlighted with green arrows.

1 tap ESM filtering, 2 cascades encoded into a 512x512 shadow map, and 5x5 box blur prefiltering of shadow map. Shadow map is rendered using 4xMSAA.

About 1/3 of the depth range is represented by the first cascade (and 2/3 in the second cascade). The difference in shadow size between these two cascades is much bigger than expected.

To reduce the artifacts, we can linearly interpolate between the cascades. This article suggests this method (look at figure 9). A region where blending will be done is marked below in light red.

Blend region where shadow cascades will be linearly interpolated.

I use a conditional shader branch so that samples from both cascades are only taken in the blend region. This means that reducing the blend region in screen space will reduce computation time. Two ways to reduce the blend region are:

  • Reduce the blend region width.
  • Increase the cascade split distance from the camera.

Note that increasing the cascade split distance will also reduce the resolution difference between cascades, and therefore make the cascade discontinuity smaller.

Blending between shadow cascades is performed on the previously shown blend region. Blending artifacts are highlighted with green arrows.

Click the above image to enlarge it. The middle green arrow highlights a particularly bad case, where a very long shadow is in the blend region. Increasing the blend region would make the artifact larger, but less noticeable.

Without modifying the cascades, blending between cascades can result in seams at the blend region:

A seam results from selection between both cascades.

Thankfully though, these seams can be avoided by making the cascades overlap (i.e their depth bounds should overlap with one another).

This entry was posted in Coding, XNA and tagged , , , , , . Bookmark the permalink.

3 Responses to Cascading shadow mapping and ESM.

  1. CC Ricers says:

    How much overlap would you recommend for reducing seam artifacts? When I use CSM I use the a small amount, like a 0.1 – o.2% difference between the far plane of the closest cascade and the near plane of the one behind it. For example if the closest cascade has a far distance of 1000 units I would set the near plane of the next one at 998. I typically use 3 cascades so the shadow artifacts are already smaller.

  2. olhovsky says:

    How much overlap you choose depends on your scene, the number of cascades you choose, and the split size of the cascades (different cascades may prefer different sized blend regions).

    I don’t know of a simple formula for choosing the overlap, so I recommend that you experiment.

    Larger blend regions result in lower performance, and less visible seams. As you can see from the following image, I chose a blend region that makes the seams relatively obvious (if you are far enough away and the scene is simple like this one is).

    As with everything in real time graphics, you have to tune the parameters to your application — trading visible artifacts for higher performance and better rendering quality in your other effects.

  3. Laurent says:

    The fundamental reason you are seeing a discontinuity when switching cascade level is because your shadow map is blurred with a constant size kernel in image space, therefore the blur kernel changes size in world space between one cascade level and the next. A cheaper and simpler solution is to scale your blur kernel so your blur is a constant size in light space for all cascade levels. This is a simple divide on the cpu side so it is free as far as your shader is concerned.
    It makes the discontinuity almost invisible (at least in all cases I’ve used it in) and has the advantage of making your blur pass cheaper for far away cascade levels since the kernel becomes smaller.

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>