Sign in to follow this  
ZeRaW

Shadow Maps

Recommended Posts

I have been trying to use shadow maps in my game. I followed the D3D sample (Dx9) as my game is using dx9. I am doing a flight sim. so my world is mostly outdoors. I am still in early stages of shadow implementation, so i am having some bugs, the rendering of the plane using the same way of the sample works, fine, but if i try with other big models (ex: the terrain), the rendering becomes messed up as it seems the textures are inside each other or something. As i said before i am new to shadow mapping, can it be that the shadow surface buffer is too small?

Share this post


Link to post
Share on other sites
Could you post some screenshots and maybe even some code too? I'm not sure exactly what you mean by "textures are inside each other or something."

Share this post


Link to post
Share on other sites
sorry about the earlier post, i was a bit in a hurry so here is more explanation about my program:

1st initializing the light:

Lights.push_back(new LightStruct());
D3DXVECTOR3 vecDir;
ZeroMemory( &(Lights[0]->lt), sizeof(D3DLIGHT9) );
Lights[0]->lt.Type = D3DLIGHT_SPOT ;
//Lights[0]->lt.Position = D3DXVECTOR3( 0, 1000.0f, -780 );
Lights[0]->lt.Position = D3DXVECTOR3( -150, 100, -780 );

Lights[0]->lt.Direction = D3DXVECTOR3( 1, -1, 0 );
Lights[0]->lt.Range = 10000;
//Lights[0]->lt.Attenuation0 =1;
Lights[0]->lt.Diffuse.a = 1.0f;
Lights[0]->lt.Diffuse.r = 1.0;
Lights[0]->lt.Diffuse.g = 1.0f;
Lights[0]->lt.Diffuse.b = 1.0f;
Lights[0]->lt.Ambient = Lights[0]->lt.Specular = Lights[0]->lt.Diffuse;

Lights[0]->lt.Theta = 1;
Lights[0]->lt.Phi = 1;

Game::g_pd3dDevice->SetLight( 0, &(Lights[0]->lt) );
Game::g_pd3dDevice->LightEnable( 0, TRUE );
Game::g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );



2nd the models and textures are loaded correctly, i tested them with
Drawsubset dx function, in my structure, i have a plane object
and static objects (a bsp is built for these but for now lets say they are objects inside an instance called map.
so normal rendering calling:
mymap->Update();
plane->Render();
gives:
normal dx render

so now i started implementing the shadow map.
on initialization, i create the shadow map and surface:

DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;
#ifdef DEBUG_VS
dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif


D3DXCreateEffectFromFile( Game::g_pd3dDevice, "shadowmap.fx", NULL, NULL, dwShaderFlags,
NULL, &g_pEffect, NULL );


g_pEffect->SetVector( "g_vLightDiffuse", (D3DXVECTOR4 *)&Lights[0]->lt.Diffuse ) ;
g_pEffect->SetFloat( "g_fCosTheta", cosf( Lights[0]->lt.Theta ));

// Create the shadow map texture
Game::g_pd3dDevice->CreateTexture( 512, 512,
1, D3DUSAGE_RENDERTARGET,
D3DFMT_R32F,
D3DPOOL_DEFAULT,
&g_pShadowMap,
NULL );

// Create the depth-stencil buffer
Game::g_pd3dDevice->CreateDepthStencilSurface( 512,
512,
D3DFMT_D16, D3DMULTISAMPLE_NONE,
0,
TRUE,
&g_pDSShadow,
NULL );



// Initialize the shadow projection matrix
float g_fLightFov = 3.1415f/ 2.0f;
D3DXMatrixPerspectiveFovLH( &g_mShadowProj, g_fLightFov, 1, 0.01f, 100.0f);




on rendering:

//get the view matrix of the light:
D3DXMATRIXA16 mLightView;
D3DXVECTOR3 vPos = Lights[0]->lt.Position;
D3DXVECTOR3 vDir = Lights[0]->lt.Direction;
mLightView._41 = mLightView._42 = mLightView._43 = 0.0f;
D3DXVec3Normalize( &vDir, &vDir );
vDir.x += vPos.x; // vDir denotes the look-at point
vDir.y += vPos.y;
vDir.z += vPos.z;
D3DXVECTOR3 vUp( 1.0f, 0.0f, 0.0f ); /*assumption!*/
D3DXMatrixLookAtLH( &mLightView, &vPos, &vDir, &vUp );


// Render the shadow map
LPDIRECT3DSURFACE9 pOldRT = NULL;
Game::g_pd3dDevice->GetRenderTarget( 0, &pOldRT );
LPDIRECT3DSURFACE9 pShadowSurf;
if( SUCCEEDED( g_pShadowMap->GetSurfaceLevel( 0, &pShadowSurf ) ) )
{
Game::g_pd3dDevice->SetRenderTarget( 0, pShadowSurf );
SAFE_RELEASE( pShadowSurf );
}
LPDIRECT3DSURFACE9 pOldDS = NULL;
if( SUCCEEDED( Game::g_pd3dDevice->GetDepthStencilSurface( &pOldDS ) ) )
Game::g_pd3dDevice->SetDepthStencilSurface( g_pDSShadow );

{
RenderScene(true,&mLightView, &g_mShadowProj );
}

if( pOldDS )
{
Game::g_pd3dDevice->SetDepthStencilSurface( pOldDS );
pOldDS->Release();
}
Game::g_pd3dDevice->SetRenderTarget( 0, pOldRT );
SAFE_RELEASE( pOldRT );


D3DXMATRIX *pmView = &Game::GameCam.FinalView;
g_pEffect->SetTexture( "g_txShadow", g_pShadowMap );
// Compute the matrix to transform from view space to
// light projection space. This consists of
// the inverse of view matrix * view matrix of light * light projection matrix
D3DXMATRIXA16 mViewToLightProj;
mViewToLightProj = *pmView;
D3DXMatrixInverse( &mViewToLightProj, NULL, &mViewToLightProj );
D3DXMatrixMultiply( &mViewToLightProj, &mViewToLightProj, &mLightView );
D3DXMatrixMultiply( &mViewToLightProj, &mViewToLightProj, &g_mShadowProj );
g_pEffect->SetMatrix( "g_mViewToLightProj", &mViewToLightProj );

//same as D3DTS_PROJECTION set to device?
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveRH(&matProj, 1, 1, 1.0f, 100000.0f);
RenderScene(false, pmView, &matProj);
g_pEffect->SetTexture( "g_txShadow", NULL );



the render scene function:

g_pEffect->SetMatrix( "g_mProj", pmProj );
D3DXVECTOR3 v = Lights[0]->lt.Position;
D3DXVECTOR4 v4;
D3DXVec3Transform( &v4, &v, pmView );
g_pEffect->SetVector( "g_vLightPos", &v4 );
*(D3DXVECTOR3*)&v4 = Lights[0]->lt.Direction;
v4.w = 0.0f; // Set w 0 so that the translation part doesn't come to play
D3DXVec4Transform( &v4, &v4, pmView ); // Direction in view space
D3DXVec3Normalize( (D3DXVECTOR3*)&v4, (D3DXVECTOR3*)&v4 );
g_pEffect->SetVector( "g_vLightDir", &v4 );



bRenderShadow = false;
if( bRenderShadow )
g_pEffect->SetTechnique("RenderShadow");
else
g_pEffect->SetTechnique("RenderScene");

//render the objects:
for(int o =0; o < (int)mymap->staticObjects.size(); ++o)
{
Object * obj = mymap->staticObjects[o];
D3DXMATRIXA16 mWorldView = obj->matWorld;
D3DXMatrixMultiply( &mWorldView, &mWorldView, pmView );
g_pEffect->SetMatrix( "g_mWorldView", &mWorldView );

LPD3DXMESH pMesh = obj->g_pMesh;
UINT cPass;
g_pEffect->Begin( &cPass, 0 );
for( UINT p = 0; p < cPass; ++p )
{
g_pEffect->BeginPass( p );

for( DWORD i = 0; i < obj->g_dwNumMaterials; ++i )
{
D3DXVECTOR4 vDif( obj->g_pMeshMaterials[i].Diffuse.r,
obj->g_pMeshMaterials[i].Diffuse.g,
obj->g_pMeshMaterials[i].Diffuse.b,
obj->g_pMeshMaterials[i].Diffuse.a );
g_pEffect->SetVector( "g_vMaterial", &vDif );
if( obj->g_pMeshTextures[i] )
g_pEffect->SetTexture( "g_txScene", obj->g_pMeshTextures[i] );

g_pEffect->CommitChanges() ;
pMesh->DrawSubset( i ) ;
}
g_pEffect->EndPass();
}
g_pEffect->End();
}

Object * obj = plane;
D3DXMATRIXA16 mWorldView = obj->matWorld;
D3DXMatrixMultiply( &mWorldView, &mWorldView, pmView );
g_pEffect->SetMatrix( "g_mWorldView", &mWorldView );

LPD3DXMESH pMesh = obj->g_pMesh;
UINT cPass;
g_pEffect->Begin( &cPass, 0 );
for( UINT p = 0; p < cPass; ++p )
{
g_pEffect->BeginPass( p );

for( DWORD i = 0; i < obj->g_dwNumMaterials; ++i )
{
D3DXVECTOR4 vDif( obj->g_pMeshMaterials[i].Diffuse.r,
obj->g_pMeshMaterials[i].Diffuse.g,
obj->g_pMeshMaterials[i].Diffuse.b,
obj->g_pMeshMaterials[i].Diffuse.a );
g_pEffect->SetVector( "g_vMaterial", &vDif );
if( obj->g_pMeshTextures[i] )
g_pEffect->SetTexture( "g_txScene", obj->g_pMeshTextures[i] );
g_pEffect->CommitChanges() ;
pMesh->DrawSubset( i ) ;
}
g_pEffect->EndPass();
}
g_pEffect->End();



please note that the dx clear and begin are called before the rendering process and end is called after it.

so as you can see, i followed the dx sample by word. and results were not very satisfactory, some more screen shots:

Applying shadow map to plane only:
plane

Applying it to road only:
road

Applying it to all the scene 1:
scene1

all the scene 2: (camera moved)
scene2

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