Sign in to follow this  
REF_Cracker

Cascade Stability

Recommended Posts

Hey all,

I've got a basic cascaded shadow map up and working but I'm having stability problems. My implementation is closely following the ShaderX6 article by Michal Valient. I was able to achieve perfect stability in the first and closest cascade as described in this post [url="http://www.gamedev.net/topic/497259-stable-cascaded-shadow-maps/"]http://www.gamedev.n...ed-shadow-maps/[/url]. My problem is that the other 3 further cascades shimmer quite awfully now.

The 4 cascade view projection matricies are calculated as

ShadowMat = LightLookAt * OrthoProjection * RoundingMat

where the rounding mat is as mention in the previous post. (pasted here)

//--------------------------
[left]// xShadowMatrix is the light view projection matrix[/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]D3DXVECTOR3 ptOriginShadow(0,0,0);[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]D3DXVec3TransformCoord(&ptOriginShadow, &ptOriginShadow, &xShadowMatrix);[/size][/font][/color][/left]


[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// Find nearest shadow map texel. The 0.5f is because x,y are in the [/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// range -1 .. 1 and we need them in the range 0 .. 1[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float texCoordX = ptOriginShadow.x * SHADOW_MAP_SIZE * 0.5f;[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float texCoordY = ptOriginShadow.y * SHADOW_MAP_SIZE * 0.5f;[/size][/font][/color][/left]


[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// Round to the nearest 'whole' texel [/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float texCoordRoundedX = round(texCoordX);[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float texCoordRoundedY = round(texCoordY);[/size][/font][/color][/left]


[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// The difference between the rounded and actual tex coordinate is the [/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// amount by which we need to translate the shadow matrix in order to[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// cancel sub-texel movement[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float dx = texCoordRoundedX - texCoordX;[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]float dy = texCoordRoundedY - texCoordY;[/size][/font][/color][/left]


[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]// Transform dx, dy back to homogenous light space[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]dx /= SHADOW_MAP_SIZE * 0.5f;[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]dy /= SHADOW_MAP_SIZE * 0.5f;[/size][/font][/color][/left]


[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]D3DXMATRIX xRounding;[/size][/font][/color][/left]

[left][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3]D3DXMatrixTranslation(&xRounding, dx, dy, 0); [/size][/font][/color][/left]

//--------------------------

This gives me a perfectly stable result for the first cascade. The remaining 3 cascades are being looked-up in the shadow map atlas via an offset and scale passed to the pixel shader.

float3 offset[n] = ShadowMat[0] * lookat[n].translation
float scale[n] = splitRadius[0] / splitRadius[n]

I'm missing something here and can't figure it out. Seems to me that even though I'm using the properly rounded shadow matrix for each cascade caster rendering, I'm disregarding it in the lookup because I'm scaling and offseting in a fractional pixel way. Is there a way to derive the scale and offset purely from the set of cascade shadow matricies? I'm probably getting it wrong by using the projection of the nth lookat's translation as it's before the rounding adjustment.

Thanks in advance,
ref_cracker

Share this post


Link to post
Share on other sites
Solved:

There is a way to calculate the proper scale and offset directly form your cascade shadow viewproj matricies. It's right in the article but wasn't working due to a bug in my matrix inversion code.

The way to get the scale remains

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left]float scale[n] = splitRadius[0] / splitRadius[n][/left][/size][/font][/color]

The offset is calculated as

[color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left]float4 offset[n] = float4(0.0f,0.0f,0.0f,1.0f) * Inverse([/left][/size][/font][/color][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left]ShadowMat[n]) * [/left][/size][/font][/color][color=#282828][font=helvetica, arial, verdana, tahoma, sans-serif][size=3][left]ShadowMat[0];[/left][/size][/font][/color]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this