How can I fix shadow edge swimming in CSM ?

I have successfully implement Cascaded Shadow Map and the result look very good in still shot.

But when the camera start moving , the shadow edge are start to flickering/swimming.

Right now I just want to fix the translation case first since my game is a 2.5d fighting game that doesn’t have much camera rotation.

After sometime of research on the Internet I found out the way to fix this issue in “Shadows & Decals: D3D10 Techniques in Frostbite (GDC’09)”.

They said you should “round light space translation to even texel increments” with the given code

float f = viewSize/(float)shadowMapSize;
translation.x = round(translation.x/f)*f;
translation.y = round(translation.x/f)*f;

My question is

  1. What is viewSize ? Is it the size of the frustum of selected slice (but why ignore the second dimension) ?

  2. is “translation” a fragment position after transform in to light space (the one you use to do shadow look up) ?

  3. where should I apply this fix (I guess it must be fragment shader) ?

ShaderX6: Stable Rendering of Cascaded Shadow Maps (Michal Valient) has a good description.

Basically, pick a world-space point as your “quantization origin”, project it to shadow space, and then subtract from it that shadow space position rounded to the nearest texel. This “correction” offset can be appended to the shadow matrix (used for shadow projection). Essentially this keeps the quantization origin on the corner of a shadow texel, effectively making your shadow map march along in one shadow texel increments.

Beware getting your quantization origin too far from your shadow map though (floating point precision issue).

Haven’t read his presentation, but looks like there’s a mode where shadow texel sizes can be multiples of the base shadow map resolution.

  1. where should I apply this fix (I guess it must be fragment shader) ?

No, you can just quantize your light-space frustum (built on the CPU) using this offset, with your shader remaining oblivious. Basically, just use the offset to scoot your light-space frustum over a tiny bit in XY in light space.