Shadow Mapping HEELLLPPP !!!

Started by
0 comments, last by matches81 18 years, 3 months ago
Hello. I'm currently trying to implement ShadowMapping into my engine. And i have some enormous problems. I render my scene thru the light point of view into a floatting point texture, and store the depth. The result looks good: http://clementvidal.ifrance.com/Sable/Captures/Depth.jpg After i use this texture into a shader to compute which are the lit pixel (from the camera point of view). And here, the result is UGLY !!! http://clementvidal.ifrance.com/Sable/Captures/Shadow.jpg Black pixel are unlited and gray pixel are. - Here is the shader used to render the second step: VSOUTPUT_UNLIT VS_Unlit( float3 inPosition : POSITION ) { // Output struct VSOUTPUT_UNLIT OUT = (VSOUTPUT_UNLIT)0; // Output the transformed position OUT.vPosition = mul( float4(inPosition,1), CamViewProj ); // Output the projective texture coordinates OUT.vTexCoord = mul( float4(inPosition,0), TextureMat ); // Output the scene depth float3 WorldPos = mul(float4(inPosition,1),WorldMat); float3 LightVect = Light[0].Pos - WorldPos; float LengthToLight = length(LightVect); OUT.fDepth = (LengthToLight - ZNear) /(ZFar - ZNear ); return OUT; } float4 PS_Unlit( VSOUTPUT_UNLIT IN , uniform sampler2D DepthSmp) : COLOR0 { float4 vTexCoords = IN.vTexCoord; float A = tex2Dproj( DepthSmp, vTexCoords ).r; float B = (IN.fDepth -0.1f); // Texel is shadowed float fShadowTerms = A < B ? 0.0f : 0.5f; return fShadowTerms; } - and the texture projection matrix is computed as folow: TextureMat = pObj->GetWorldMatrix() * LightView * LightProj * OffSetMatrix; - and OffSetMatrix: float fTexOffs = 0.5 + (0.5 / (float)DepthMapSize); OffSetMatrix.SetLine(0, CVector4(0.5f, 0.0f, 0.0f, 0.0f)); OffSetMatrix.SetLine(1, CVector4(0.0f, -0.5f, 0.0f, 0.0f)); OffSetMatrix.SetLine(2, CVector4(0.0f, 0.0f, 1.0f, 0.0f)); OffSetMatrix.SetLine(3, CVector4(fTexOffs, fTexOffs, 0.0f, 1.0f)); In fact i do not understand the math behind the texture projection, i think my mistakes come from that ... :) If anybody can help me in any way (explain the math of texture projections ... :) Or if you know where my bug come from, please let me know ! Thanks a lot !! Clément Vidal
Advertisement
As far as I understand shadow mapping, you do the following:
First you render the scene from the camera´s point of view and store the depth of this render in the shadow map(as you did). After that you render the scene from the camera´s point of view and compare the resulting depth with the depth from the shadow map.
To do that, you need the point´s depth in projection space of the camera and the point´s depth in projection space of the light (which you already have in your shadow map).

Your texture matrix does nothing else but 'move' your point from object space to the light´s projection space (the same you rendered the shadow map in).

The result of this projection is a set of coordinates in the range [-1,1].
The offset matrix is used to scale and bias these coordinates, because you need them to be in the range [0,1] for the texture lookup from the shadow map. The offset matrix in your code scales the x and y components of the multiplied vector by 0.5 and should adds fTexOffs to both of them (if w-component is 1).

So, your texture matrix should look something like this:
mat_Texture = mat_World * mat_LView * mat_LProj * mat_Offset
In fact, your texture matrix does look like this. The only thing I don´t understand in your code is the following line:

 OUT.vTexCoord = mul( float4(inPosition,0), TextureMat );

I assume it should be float4(inPosition,1), otherwise the fTexOffs values from the offset matrix, the translation component of the world matrix and perhaps other components of the view and projection matrix (don´t know those two too well, I have to admit) will be ignored.
So, you could try that.

In case that doesn´t help you could try the following:
Instead of "including" the offset matrix into the texture matrix you could do the scale and bias manually: You use a matrix for projecting from world to the light´s projection space (mat_LView * mat_LProj), let´s call that mat_LViewProj.
After that you get the point´s position vector in the light´s projection space by multiplying the point´s world coordinate vector with that matrix.
Finally you multiply this vector by 0.5 and add 0.5 to the x and y component of it.
For the texture look-up it should suffice to only use the x and y component of the vector and do a normal tex2D()-lookup using those. I might be wrong there, though, I don´t know what tex2Dproj() does.

In code:
float4 WorldPos = mul(float4(inPosition,1), mat_World); //the same as your WorldPosfloat4x4 mat_lViewProj = mul(mat_LView, mat_LProj); //matrix to transform from world to light´s projection spacefloat4 LightProjPos = mul(WorldPos, mat_LViewProj);LightProjPos = LightProjPos * 0.5  + float4(0.5, 0.5, 0, 0); //scale and biasfloat2 vTexCoords = LightProjPos.xy; //TexCoords to use for tex2D lookup from shadow map


Please note that I have not implemented shadow mapping myself and my math skills aren´t that great either, so if anybody spots an error in my post, feel free to correct me. Hope it is correct and helps, though ;)


[edit]
had to remove my precious ASCII diagram, as the backslashes totally tore it apart :-(
[/edit]

This topic is closed to new replies.

Advertisement