Sign in to follow this  

projected shadow

Recommended Posts

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. !!!

Share this post

Link to post
Share on other sites

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.tex0
vOut.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]


Share this post

Link to post
Share on other sites
Guest Anonymous Poster
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?


Share this post

Link to post
Share on other sites
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 ...


Share this post

Link to post
Share on other sites

First thanks for your help !!

I have again a problem with projection, look at

the texture is not well projected on the plane

here is my code :

//texture coordinate correction

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

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

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

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->SetStreamSource(0, gFloor, 0, sizeof(VertexPT));
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. !!!

Share this post

Link to post
Share on other sites

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.


@Anonymous Poster:

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


Share this post

Link to post
Share on other sites
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. !!!

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