Shadow map problem

Started by
11 comments, last by ekba89 12 years, 9 months ago
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.


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;
}
}
Advertisement
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?
[font="Arial"]I was trying to debug again and i saw 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.[/font]
Post more code. It is difficult to tell what is happening.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
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.
Are you sure the error is not in this line?

if((saturate(projectedLightPosition).x == projectedLightPosition.x) && (saturate(projectedLightPosition).y == projectedLightPosition.y))


You should also post the shadow creating shader and the lighting shader
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.
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.


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;
}



//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);



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;
}
For example code on shadow mapping, check out this

http://www.d3dcoder.net/d3d10.htm

Download PartII, open chater 13 for the source.
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
I'll check it out but i think something other than my shading code is wrong. Because i found there is a sample in Riemer's site (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.

This topic is closed to new replies.

Advertisement