Skip to main content
GameDev.net gamedev.net
🔒 Locked

NVidia style shadow mapping

Started by muhkuh Jul 14, 2004 at 10:15 AM 14 replies 3.6k views
Original Post
muhkuh
muhkuh
Hello, after reading a lot of papers and tutorials I finnally put some shadow mapping together in my D3D app. I use the nvidia style method with a depth texture. Can anyone tell me if the following steps are correct? 1.) I render from the light's point of view using the light's concatenated lightview*lightprojection matrix (M1) to the depth texture. The projection is orthogonal as I use a directional light.(I tested this and it looked quite as it should) 2.) I render from the camera with it's own transformation: camview*camprojection. In the vertex shader I generate 4D texture coordinates for the shadow map by transforming each vertex coordinates (world space) by a matrix M2 that is: M1*M_tex M_tex is the texture offset matrix from the nvidia shadow mapping paper: 0.5 0 0 0 0 -0.5 0 0 0 0 1 0 OffsetX OffsetY bias 1 In the pixel shader of step 2 I do a lookup into the shadow map and display the result as color to see what would be in shadow. The problem is that it looks totally scewed up. Am I missing something important? Thank you in advance. Markus
Thorris
Thorris
Hello,

the steps you do seem correct to me. I do it the same way.
You should maybe increase the depth bias to avoid z fighting in the
shadow map.

You should also take a look into second-depth shadow mapping.

Ciao, Thorris.
Aurora3D
Aurora3D
Screenshots?

Things its good to know about when playing with matrices:
1) DirectX vs. OpenGL - multiplication row wise vs. column wise (ie. transposed)
2) Cg vs. OpenGL - matrices are also transposed

Quote:
Original post by muhkuh
M_tex is the texture offset matrix from the nvidia shadow mapping paper:

0.5 0 0 0
0 -0.5 0 0
0 0 1 0
OffsetX OffsetY bias 1
Markus


This kind of looks like a DirectX Tex scale bias matrix, but it's built like an openGL tex scale bias. Which are you using?

An openGL TexScaleBias should look like this:
Quote:
0.5, 0.0, 0.0, 0.0
0.0, 0.5, 0.0, 0.0
0.0, 0.0, 0.5, 0.0
0.5, 0.5, 0.5, 1.0


Biasing on your near and far plane should be done either 1) using the glOrtho function on your texture matrix and biasing the near and far planes (or) 2) adding an epsilon to the matrix[10] slot (see "Game Programming Gems 1" p.361).

"The Cg Tutorial" by Kilgard has an excellent breakdown of the transformation pipeling for projective textures, and plenty can go wrong anywhere in the pipeline. For example, backface culling originally gave us headaches with shadow mapping because the glOrtho and glFrustum functions use different handed coordinate systems (we had to write our own version of glOrtho).

Hope this helps,
AndrewAurora Interactivewww.aurora3d.com
muhkuh
muhkuh
Mmmm, changing the bias just moves the messed up parts araound. Is it important how I l do the texture lookup into the shadow map? I create 4 texture coordinates but in HLSL I can do a tex2D or a tex3D.
Aurora3D
Aurora3D
Do you have a tex2Dproj as opposed to just a tex2D?
AndrewAurora Interactivewww.aurora3d.com
muhkuh
muhkuh
Quote:
Original post by Aurora3D
Screenshots?

Things its good to know about when playing with matrices:
1) DirectX vs. OpenGL - multiplication row wise vs. column wise (ie. transposed)
2) Cg vs. OpenGL - matrices are also transposed

Quote:
Original post by muhkuh
M_tex is the texture offset matrix from the nvidia shadow mapping paper:

0.5 0 0 0
0 -0.5 0 0
0 0 1 0
OffsetX OffsetY bias 1
Markus


This kind of looks like a DirectX Tex scale bias matrix, but it's built like an openGL tex scale bias. Which are you using?

An openGL TexScaleBias should look like this:
Quote:
0.5, 0.0, 0.0, 0.0
0.0, 0.5, 0.0, 0.0
0.0, 0.0, 0.5, 0.0
0.5, 0.5, 0.5, 1.0




Biasing on your near and far plane should be done either 1) using the glOrtho function on your texture matrix and biasing the near and far planes (or) 2) adding an epsilon to the matrix[10] slot (see "Game Programming Gems 1" p.361).

"The Cg Tutorial" by Kilgard has an excellent breakdown of the transformation pipeling for projective textures, and plenty can go wrong anywhere in the pipeline. For example, backface culling originally gave us headaches with shadow mapping because the glOrtho and glFrustum functions use different handed coordinate systems (we had to write our own version of glOrtho).

Hope this helps,


I'm using D3D and the D3DXMATRIX structure so all matrices should be row major. I know that matrices in the shader are column major order by default but since I set them by using the SetMatrix function of the ID3DXConstantTable interface D3D converts as needed.

I made a screenshot of the mess. It shows a sphere at the origin (0,0,0), viewport is 5 units back (0,0,-5) and the light direction is (1,0,1).


muhkuh
muhkuh
Quote:
Original post by mikeman
When rendering for light's POV,you must use culling.Do you do that?


As far as I understood shadow mapping culling will speed it up but it will work without it. I'm currently not culling anything in the shadow pass.
muhkuh
muhkuh
Quote:
Original post by Aurora3D
Do you have a tex2Dproj as opposed to just a tex2D?


I'm using ps 1.3 so tex2Dproj is not available. The NVidia shadow mapping exists since GF3 so there must be a way to do it in HLSL. Correct me if I'm wrong but I thought NVidia somehow tweaked the D3DFMT_D24X8 depth texture format so that it automaticalle compares the texel value at s,t with the third texture coordinate r and returns the result as some value between 0 and 1. I just havn't seen a HLSL sample of this.
muhkuh
muhkuh
Ok, I finally found an HLSL sample from NVidia and checked what they did and it seems my matrix transformations are correct. I just can't figure out what's wrong.

1.) I displaye the post perspective z values of the shadow map on screen and they seem to be OK.

2.) I use the texture matrix from the nV sample and exactly the same matrixes as when rendering from the light to get the shadow map texture coorsinates. The world space positions in the vertex shader must be correct because otherwise I would see corrupted geometry.

What's the hell is going wrong?
rept
rept
When rendering the shadowmap, the depth-texture and color target bitdepths must match.

for d24_s/x8, a8r8g8b8
for d16, r5g6b5

also, on gf3, only the former is available.
muhkuh
muhkuh
Quote:
Original post by rept
When rendering the shadowmap, the depth-texture and color target bitdepths must match.

for d24_s/x8, a8r8g8b8
for d16, r5g6b5

also, on gf3, only the former is available.


I'm using D3DFMT_D24S8 together with D3DFMT_A8R8G8B8. This seems to be working. I think there is something wrong with projective texturing in the second pass from the camera's POV. As ps 1.3 doesn't have a tex2dproj command in HLSL projective texturing has to be enabled by a:

SetTextureStageState(index,D3DTSS_TEXTURETRANSFORMFLAGS,D3DTTFF_PROJECTED);

What is strange is that it doesn't change anything if I enable or disable this flag.
muhkuh
muhkuh
Yeeeha. I think I got it. When rendering to a depth texture that represents the z buffer a rendertarget is needed (although color writes can be disabled). I already knew that and created a dummy render target by "CreateRenderTarget" with the correct format corresponding to the depth texture (D24S8, RGBA). This produced the strange resluts I posted above. In the NVidia sample I saw that they don't create their dummy render target by "CreateRenderTarget". They use "CreateTexture" with the D3DUSAGE_RENDERTARGET flag. After doing it that way too everything started working.

Can anybody tell me what's the difference and why one works and the other does not? D3D didn't produce any error messages when setting the "false" render target.

[Edited by - muhkuh on July 14, 2004 11:35:51 PM]
Aurora3D
Aurora3D
Grats on the fix!

Dunno about the render target. DX3D isn't one of my strong suits. If I had to guess...setting up a render target may give you the best (probably better than requested) hardware selection that supports your render target setup parameters (but not exact). Creating a texture may force the renderer to generate a texture that matches your parameters exactly...just a guess.
AndrewAurora Interactivewww.aurora3d.com
rept
rept
oh yeah, the createtexture thing, i forgot about it. they
don't explicitly state it in any of their docs, the debug
runtime doesn't complain, but still, this is the only way to
get it working. pretty confusing for the first time.
muhkuh
muhkuh
Quote:
Original post by rept
oh yeah, the createtexture thing, i forgot about it. they
don't explicitly state it in any of their docs, the debug
runtime doesn't complain, but still, this is the only way to
get it working. pretty confusing for the first time.


Indeed. May be this should be taken into the FAQ of the DirectX Forum. Top 3 pitfalls when doing shadow mapping on nv hardware:

1. Use CreateTexture for the render target too
2. Don't forget to turn projective texturing on
3. ranges of shadow map are 0..1 in DX9 now, not 0-2^bitdepth-1

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.