[dx9 HLSL] Shadow acne problem in cube shadow

Started by
3 comments, last by Dawoodoz 12 years, 8 months ago
hi all


i cannot get my cube shadow mapping to work cause it is having shadow acne and could not project the right shadow.
I could not seem to get the right BIAS value to solve the acne.


heres how i did it;

i created a cube texture with [font="Consolas"][font="Consolas"]D3DFMT_R32F as format.
[/font][/font]
with [font="Consolas"][font="Consolas"] D3DXMatrixPerspectiveFovLH( &matProj, (D3DX_PI / 2.0f), 1, 1.0f, 1024.0f );

[/font][/font]as

projection matrix for all sides of the cube


heres the shader;

generating the shadow depth map


[source lang="C"]

struct VSOUTPUT_SHADOW
{
float4 vPosition : POSITION;
float fDepth : TEXCOORD0;
};

VSOUTPUT_SHADOW VS_Shadow( float4 inPosition : POSITION )
{
// Output struct
VSOUTPUT_SHADOW OUT = (VSOUTPUT_SHADOW)0;

// Output the transformed position
OUT.vPosition = mul( inPosition, mul(matWorld,lightViewProject) );

// Output the scene depth
float4 vPosition = mul( inPosition, matWorld );
OUT.fDepth = length(lightPos.xyz-vPosition.xyz) + 0.5;

return OUT;
}

float4 PS_Shadow( VSOUTPUT_SHADOW IN ) : COLOR0
{
return float4( IN.fDepth, 0.0, 0.0, 1.0 );
}

[/source]


heres the rendering of the scene,

note other parts are removed since it is just for computation of worldPosition

in defered shading


[source lang="c"]
float4 BuildLight(float4 Position : POSITION,
float2 TexCoord : TEXCOORD0) : COLOR0

{

...

...

float3 lightDir = (lightPos.xyz - worldPos.xyz);
float distance = length(lightDir_me) ;
lightDir.xyz = lightDir.xyz / distance;

// Find color of pixel
float shadowMapDepth = texCUBE(cubeShadowMapSampler, float4(-(lightDir.xyz), 0.0f)).x;

//NOTE: check this line regarding comparison
if(distance < shadowMapDepth)
{
// we're in shadow, cut the light
finalColor = float4((diffuseColor * AmbientLightColor),1);
}

[/source]


this result to shadow acne and the shadow not producing the expected shadow in the wall.

-DO you have any idea on what is wrong on my shader?

-How to determine and compute the correct bias to solve shadow acne?

-WHere do i apply the bias? is it during the generation of depth map or duirng the actual distance?



thanks for any help in advance


Advertisement
A whole book could be written on the subject probably.

Adding the surface normal to the world space texel position before sending it to the shadowmap test works quite well, and also implicitly adds a bit of jitter to the calculated result.

Without the normal the next best choice is to pull the position toward the camera first.

Making the near plane on the shadowmap projection closer and intentionally making the shadowmap's z distribution worse can also help. Most of the depth values will land at the far end of the range and have similar step sizes, which can be fixed with a single offset amount of some kind.

Avoiding perspective shadowmap algorithms (which divide by y instead of z) will avoid a lot of pain and misery as well.
http://www.gearboxsoftware.com/
I've had this problem before. The first place to trouble shoot is the texture/surface format. Also the larger the texture the better the percission but this all comes at a price. I eventually scrapped cubed shadow maps with point lights and went with a directional light approach. Cubed Shadow Maps we're just not practical for me.



Good Luck!

Dj
A whole book could be written on the subject probably.Adding the surface normal to the world space texel position before sending it to the shadowmap test works quite well, and also implicitly adds a bit of jitter to the calculated result.


How can i add the normal to world space texel? refering to my original post

[source]
...
float3 lightDir = (lightPos.xyz - worldPos.xyz);
float distance = length(lightDir_me);
lightDir.xyz = lightDir.xyz / distance; 
...

[/source]

Will i add the surface normal on the 'lightDir' variable before it was normalize(divide by distance/length) or after? from the HLSL shader i posted 'lightDir' is my worldspace texel position.
This is my formula for setting the optimal offset:

OrthogonalShadowOffset = Max(Width / 2, Height / 2) * 7.5 / DepthMapWidthAndHeightInPixels
PerspectiveShadowOffset = Max(WidthSlope, HeightSlope) * 7.5 * Depth / DepthMapWidthAndHeightInPixels

To remove acne on extreme slopes, I use 2 different filters for sampling the depth map and take the brightest value.
The first filter is doing bilinear interpolation on the depth and just a boolean comparison after that.
The second filter is a 4 point nearest neighbour filter that make 4 comparisons and a bilinear interpolation on the intensity.

This topic is closed to new replies.

Advertisement