Sign in to follow this  
ekba89

Shadow map problem

Recommended Posts

I'm using deferred shading and trying to create shadows but there is a little problem. Problem is if camera is in front of the light it works correct but when i move camera behind the light everywhere in the lights projection becomes shadow. I think it is easier to tell with images so here some screenshots. Also shadow area is smaller than light it is for testing purposes so don't worry about it. And here is the code for creating shadow. "position" variable is the world position and i'm sure it's true because everything where i use it works fine other than this. Also shadow_epsilon is 0.0005f. Thanks for replies.

[code]
float4x4 lightViewProjection = mul(xLightView, xLightProjection);
float4 projectedLightPosition = mul(position, lightViewProjection);
projectedLightPosition.x = (projectedLightPosition.x / projectedLightPosition.w) / 2 + 0.5f;
projectedLightPosition.y = -(projectedLightPosition.y / projectedLightPosition.w) / 2 + 0.5f;
projectedLightPosition.z /= projectedLightPosition.w;

if((saturate(projectedLightPosition).x == projectedLightPosition.x) && (saturate(projectedLightPosition).y == projectedLightPosition.y))
{
float depthInShadowMap = tex2D(ShadowMapSampler, projectedLightPosition.xy).r;
if(projectedLightPosition.z - SHADOW_EPSILON > depthInShadowMap)
{
return 0;
}
}
[/code]

Share this post


Link to post
Share on other sites
I try to debug with pix and i found there is a problem with projectedLightPosition calculation. Actually it is a weird problem because everything other than w value of it is true and w is always 0.077. So any ideas why there is a problem with w value?

Share this post


Link to post
Share on other sites
[font="Arial"]I was trying to debug again and i saw [size="2"]depthInShadowMap is always 0 and projectedLightPosition.z is not between 0-1. I don't know if i'm using pix right i'm very new to it. As far as i understood gpu doesn't calculate values until it needs it so if it doesn't need it for some reason i see wrong results in pix. So don't rely on my debugging capabilities :D if you have any other opinion.[/size][/font]

Share this post


Link to post
Share on other sites
Ok i'm not at home right now i'm going to post more code when i got home. Also thanks for reply i'm really frustrated because of this. I'm trying to solve it for 2 days.

Share this post


Link to post
Share on other sites
Are you sure the error is not in this line?
[code]
if((saturate(projectedLightPosition).x == projectedLightPosition.x) && (saturate(projectedLightPosition).y == projectedLightPosition.y))
[/code]

You should also post the shadow creating shader and the lighting shader

Share this post


Link to post
Share on other sites
Ok i'm going to post that when i got home also i think there shouldn't be any problem because i tried to check if values are between 0 and 1 myself and got same result. Also i used shadow mapping with same "if" code before but not with deferred shading. And i'm sure position variable is true. I think there is something wrong with projection i mean i tried to multiply same position value that i got from pix with light's view projection matrices in cpu and they are different. Interesting thing is it can work according to my camera position although it should have nothing to do with my camera position. I'll post all related code in few hours i hope then we can find a solution. Thanks for reply by the way.

Share this post


Link to post
Share on other sites
Before i post all the code i tried to not rendering terrain in light's shadow map and it is kinda better than before. So maybe i shouldn't draw terrain in my shadow map should i? Here is all the related code and if you need to know other than these you can ask. Thanks.

[code]
void GetPositionAndNormal(out float4 position, out float3 normal, float2 texCoords)
{
float depth = tex2D(DepthMapSampler, texCoords).r;

// this is a special condition for skybox to not effected from lights. i make depth 0 in the depth map(g buffer's) when drawing skybox.
if(depth == 0)
{
position = float4(-1, -1, -1, -1);
return;
}

position.x = (texCoords.x * 2) - 1;
position.y = -((texCoords.y * 2) - 1);
position.z = depth;
position.w = 1.0f;

position = mul(position, xViewProjectionInv);
position /= position.w;

normal = tex2D(NormalMapSampler, texCoords).rgb;
normal = normalize((normal * 2) - 1);
}

float4 DSSpotLightPixel(DSVertexToPixel Input) : COLOR0
{
float4 OutputColor = 0;

float4 position;
float3 normal;
GetPositionAndNormal(position, normal, Input.TexCoords);
if(position.z == -1)
{
return 1;
}

float4x4 lightViewProjection = mul(xLightView, xLightProjection);
float4 projectedLightPosition = mul(position, lightViewProjection);
projectedLightPosition.x = ((projectedLightPosition.x / projectedLightPosition.w)) / 2.0f + 0.5f;
projectedLightPosition.y = -((projectedLightPosition.y / projectedLightPosition.w) / 2.0f) + 0.5f;
projectedLightPosition.z /= projectedLightPosition.w;

if(saturate(projectedLightPosition).x == projectedLightPosition.x && saturate(projectedLightPosition).y == projectedLightPosition.y)
{
float depthInShadowMap = tex2D(ShadowMapSampler, projectedLightPosition.xy).r;
if(projectedLightPosition.z - SHADOW_EPSILON > depthInShadowMap)
{
return 0;
}
}

float LightVal = max(0, dot(normal, -xLightDirection));

float3 lightDir = position.xyz - xLightPosition.xyz;

lightDir = normalize(lightDir);

float coneDot = dot(lightDir, xLightDirection);

if(coneDot >= cos(xLightAngle))
{
float coneAttenuation = pow(coneDot, xConeDecay);
OutputColor = LightVal * xLightPower * coneAttenuation * xLightColor;
}

return OutputColor;
}
[/code]

[code]
//in the light class constructor.
D3DXCreateTexture(device->GetDevice(), device->GetBufferWidth(), device->GetBufferHeight(), 0, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &shadowMapTexture);
shadowMapTexture->GetSurfaceLevel(0, &shadowMapSurface);

//direction is now (0, -1, 0) for testing purposes so up vector is (1, 0, 0)
D3DXMatrixLookAtLH(&lightView, &position, &(position + direction), &D3DXVECTOR3(1, 0, 0));
D3DXMatrixPerspectiveFovLH(&lightProjection, angle, 1, 0.1f, 100.0f);
[/code]

[code]
dxDevice->SetRenderTarget(sLight.shadowMapSurface, 0);
dxDevice->SetRenderTarget(NULL, 1);
dxDevice->SetRenderTarget(NULL, 2);
dxDevice->Clear();

effect->SetMatrix("xView", &sLight.lightView);
effect->SetMatrix("xProjection", &sLight.lightProjection);
terrain->DrawDepth(dxDevice, effect);
player->DrawDepth(dxDevice, effect);

/////HLSL
DepthVSToPixel DepthVS(float4 inPos : POSITION)
{
DepthVSToPixel Output = (DepthVSToPixel)0;

float4x4 preViewProjection = mul(xView, xProjection);
float4x4 preWorldViewProjection = mul(xWorld, preViewProjection);

Output.Position = mul(inPos, preWorldViewProjection);

Output.ScreenPosition = Output.Position;

return Output;
}

float4 DepthPS(DepthVSToPixel Input) : COLOR0
{
float4 Color = 0;

Color.r = Input.ScreenPosition.z / Input.ScreenPosition.w;

return Color;
}
[/code]

Share this post


Link to post
Share on other sites
I'll check it out but i think something other than my shading code is wrong. Because i found there is a sample in [url="http://www.riemers.net/eng/recipes30.php"]Riemer's site[/url] (Chapter 6). I copied same shader code and got exact same result with before. So there can be something wrong with shadow map. Is there a way to see values in r32f texture? It looks plain white when you open it.

Share this post


Link to post
Share on other sites
I [font="Arial"]debugged in pix again my depthInShadowMap value is always either 0 or 1. [/font]Also i added some from pix.First one is the result of shading map. Second is when i debug black pixels at the top of the picture. Second one is when i debug red pixels. And last one is when i debug skeleton's shadow.

Share this post


Link to post
Share on other sites
I tried to give different variable name for everything in shader to see in pix. Everything other than depth value in the shadow map is true. It is 0.589 that's why it acts like there should be shadow. But isn't 0.589 too small for depth value it is generally between 0.9 and 1.

Share this post


Link to post
Share on other sites
I found that there is a problem when drawing terrain depth. I don't understand why it is happening but here what happens. I tried to change depth pixel shader that it always return 1.0f so there shouldn't be shadows. When i don't render terrain it works as expexted but when i render terrain it is same as i mentioned in the first post.
And smasherprog i checked example code but as i mentioned i know how shadow maps works i used them before but not with deferred shading. I think there is something wrong other than my shadowing shader code. If you guys have any ideas please share. Thanks.

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