projected shadow

Started by
7 comments, last by r@ph 19 years, 2 months ago
Hi everybody! I'm trying to implement projected shadow in directX I have a black and white texture of my object wiht render to texture but I dont know how to project this texture on my scene ?? Do you know any exemple that implement projected texture or how to do that ?? Thank you very much in advance. !!!
Advertisement
Hi,

you should use projective texture mapping to map your shadow map onto your 3d-models. If you are using vertex shader, just generate your texture coordinates from your (world-)position data like this:

[...]vOut.pos = vWorldPos;vOut.tex0 = vIn.tex0vOut.tex1 = mul(vWorldPos, matTextureTransform); // <---!![...]


Note that the texture coordinate set for your vertex shader output must have a W component (must be 4D) for the shadow map coordinates (vOut.tex1 in the code fragment).

The matrix for the texture coordinate generation (matTextureTransform) must be equal to the matrix you use when you render your shadow map. Just like you've used a view and projection matrix to calculate 2d shadowmap coordinates from 3d world coordinates during rendering the shadow map, you can use (nearly) the same matrices to map the texture onto your model.

"Nearly the same matrices", because the view&projection matrix for rendering generates coordinats within the range [-1,-1]-[+1,+1] (render target coordinates) while your texture has coordinates between [0,0]-[+1,+1]. So you have to make a correction to your that matrix.

In addition to the transformation you have to divide by W (like you do it when you've rendered to the screen) to get your final texture coordinates. This divide must be per pixel and cannot be done by the vertex shader.

If you use the fixed function pixel pipeline or pixel shader below version 1.4, set the texturetransformflags for the shadow map stage to projected:
pd3dDevice->SetTextureStageState(1, D3DTSS_PROJECTED);



if you use ps_1_4 you can use the following instruction (_dw means divide by W)
texld r1, t1_dw.xyw



if you use ps_2_0 or above use
texldp r0, t1, s1



if you use HLSL you can use
tex2Dproj(sampler, texcoord)



hope that helps [smile]

------
dma
Very nice explanation dma. Could you extend it a little further though and explain the use of a Bias factor to avoid self-shadowing artifacts? How can I properly add a slight bias to the approach below?

Thanks.
the depth bias comes into play, when you use shadow maps that store depth values for yor scene. (Actually I didn't implement that myself, but I'll try to explain).

While rendering the shadow map you can write a depth value of the scene (between 0 and 1) to the alpha channel of the render target (the shadow map).

When you use the shadow map to render the scene, this depth information helps to determine whether a Pixel of an object lies in the shadow or not. You just have to compare the distance between the rendered pixel and the light source with the value stored in the alpha channel of the shadow map. If the distance is less or equal is greater, the pixel is lighted.

When you use a 32 bit texture as shadow map you'll have the problem that the alpha channel has just 256 different values - which might cause artefacts: It may happen, that some surfaces lie in their own shadow, becaus 8 bit are just not accurate enough.
Thats the reason, why you should use a depth bias. All you have to do is add a value to the depth value in the shadow map, so that the shadows will begin slightly behind the surfaces ...

-------
dma
ps:
there is also a shadow map sample in the directx sdk
(SDK root)\Samples\C++\Direct3D\ShadowMap
Hi,

First thanks for your help !!

I have again a problem with projection, look at
http://r.nury.free.fr/image/pb-projection.jpg

the texture is not well projected on the plane

here is my code :

//texture coordinate correction

D3DXMATRIX InvV;
D3DXMatrixInverse( &InvV, NULL, &gCamera->view() );

D3DXMATRIX matTex;
D3DXMATRIX matTexScale;
D3DXMATRIX matTexTrans;
D3DXMatrixTranslation(&matTexTrans, 0.5f, 0.5f, 1.0f);
D3DXMatrixScaling(&matTexScale, 0.5f, -0.5f, 0.0f);
ZeroMemory( &matTex, sizeof( D3DXMATRIX ) );
matTex = matTexScale * matTexTrans;

D3DXMATRIX mat, mat2, mat3;
D3DXMatrixMultiply( &mat, &g_matLightProj, &matTex );
D3DXMatrixMultiply( &mat2, &g_matLightView, &mat );
D3DXMatrixMultiply( &mat3, &InvV, &mat2);
d3d::gd3dDevice->SetTransform( D3DTS_TEXTURE1, &mat3);

/***********************************************************************/

// floor render
d3d::gd3dDevice->SetRenderState(D3DRS_LIGHTING, false);

D3DXMatrixIdentity(&T);
d3d::gd3dDevice->SetTransform(D3DTS_WORLD, &T);

d3d::gd3dDevice->SetMaterial(&gFloorMtrl);
d3d::gd3dDevice->SetTexture(0, g_pShadowMap);
d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );
d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_CURRENT );
d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION );
d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED | D3DTTFF_COUNT3 );

d3d::gd3dDevice->SetStreamSource(0, gFloor, 0, sizeof(VertexPT));
d3d::gd3dDevice->SetVertexDeclaration(VertexPT::GetDecl());
d3d::gd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);



/***********************************************************************/


I looked at the ati tutorial for projective shadow
They don't use vertex shader to generate texture coordinates and i would like not use too

I can't find where is the problem

If you see something wrong in my code, make me know :-)


Thank you very much in advance. !!!
Don't forget to ask about how to deal with back projection :)
@r@ph:

Looks like your shadow map UVs aren't divided by W.
The reason may be, that you set the texture transform flags to D3DTTFF_COUNT3, so the output of the transform stage will be 3D (XYZ). If you use D3DTTFF_COUNT4 instead, you'll get XYZW.

d3d::gd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED | D3DTTFF_COUNT4 );


@Anonymous Poster:

the problem of back projection should be solved if you use depth shadow maps.

----
dma
Yes !!!

You are right i modify D3DTTFF_COUNT3 to D3DTTFF_COUNT4 and it works :-)
thank you very much !!

Do you know where I can find more info on depth shadow maps ???

Thank you very much in advance. !!!

This topic is closed to new replies.

Advertisement