• Advertisement
Sign in to follow this  

[XNA] HLSL Deferred Shadows Problem

This topic is 2677 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

I'm implementing a deferred shading engine following Riemers Recipes.
With illumination there is no problem.
But there is a small issue with the shadows:

Shadow Issue

From the light's view, i reder de depth map (position.z / position.w) and use against the distance between light and pixel to determine if it is shadowed or not.

Here's the code of Depth Render

DepthVertexToPixel DepthVertexShader(DepthVertexShaderInput VSIn)
DepthVertexToPixel Output = (DepthVertexToPixel)0;

float4x4 preWorldViewProjection = mul(xWorld, xViewProjection);

Output.Position = mul(VSIn.Position, preWorldViewProjection);
Output.ScreePos = Output.Position;

return Output;

float4 DepthPixelShader(DepthVertexToPixel PSIn) : COLOR0

return float4(PSIn.ScreePos.z/PSIn.ScreePos.w, 1.0f, 1.0f, 1.0f);


And the code for calculate Shading and Shadows:

ShadingPixelToFrame Output = (ShadingPixelToFrame)0;

float3 normal = tex2D(NormalMapSampler, PSIn.TexCoord).rgb;
normal = 2.0*normal-1.0f;
normal = normalize(normal);

float depth = tex2D(DepthMapSampler, PSIn.TexCoord).r;

float4 screenPos;
screenPos.x = PSIn.TexCoord.x*2.0f-1.0f;
screenPos.y = -(PSIn.TexCoord.y*2.0f-1.0f);
screenPos.z = depth;
screenPos.w = 1.0f;

float4 worldPos = mul(screenPos, xViewProjectionInv);
worldPos /= worldPos.w;

float4 lightScreenPos = mul(worldPos, xLightViewProjection);
lightScreenPos /= lightScreenPos.w;

float2 lightSamplePos;
lightSamplePos = 0.5 * lightScreenPos.xy / lightScreenPos.w + float2(0.5f, 0.5f);
lightSamplePos.y = 1.0f - lightSamplePos.y;

lightSamplePos -= halfPixel;

float realDistanceToLight = lightScreenPos.z / lightScreenPos.w;
float distanceStoredInDepthMap = tex2D(ShadowMapSampler, lightSamplePos).r;
bool shadowCondition = distanceStoredInDepthMap <= realDistanceToLight - 1.0f / 1000.0f;

float3 lightDirection = worldPos - xLightPosition;
float decay = length(lightDirection);
float4 shading = 0;

float coneDot = dot(normalize(lightDirection), normalize(xConeDirection));
if (coneDot >= xConeAngle && !shadowCondition)
float coneAttenuation = pow(coneDot, xConeDecay);
shading = max(0,dot(normal, normalize(lightDirection)));
shading *= xLightStrength / decay;
shading *= coneAttenuation;
shading = xLightColor * max(0,dot(normal, normalize(lightDirection)));
shading *= xLightStrength / decay;

float4 previous = tex2D(PreviousSampler, PSIn.TexCoord);
Output.Color.rgb = previous + shading;

return Output;


I need the help of experts eyes. Thanks very Much!!

[Edited by - Brolo on October 25, 2010 4:31:23 AM]

Share this post

Link to post
Share on other sites
The problem there appears to be that your bias is too large, causing what's commonly known as "peter-panning" (where a shadow doesn't connect with its occluder). The bias is the value that you add to your light depth value (1.0f / 1000.0f in your case), and it is used to compensate for inadequate precision in the shadow map texture in order to avoid "shadow acne" artifacts. Your particular scene is actually a very nasty case for shadow maps...the fact that the shadow casting light is nearly parallel with the ground plane makes it difficult to get the biasing right without artifacts.

I would suggest that instead of hard-coding your bias, you make it a parameter for your shader that you can set per-light. That way when you add a shadow-casting light source, you can tweak the bias to make it look right for your scene.

Oh and if you want the source code box with syntax highlighting, use the "source" tags. You can look at the FAQ for more details.

Share this post

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

  • Advertisement