c++hlsldirectx-9shadows

Shadow Mapping Issue with DirectX9 and HLSL


I am attempting to teach myself shadow mapping to integrate it into my game, and I am currently using this tutorial (without the soft shaders for now):

http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/soft-edged-shadows-r2193

I have successfully implemented most of the code into my game. I can form the matrix needed to create the depth buffer for the shadow map, and have it render so I know it looks correct. Then I enter that into the final render loop and that is where I have run into my issues. I cannot seem to implement the final matrix calculation correctly, or I have have done something wrong along the way. I am basically one step away from this working hopefully, but my matrix calculations do not seem to be correct, I am hoping that is the case and it is not something that is in another part of the implementation.

Here is the initialization code (no known issues here): (removed for simplification)

Here is the initialization code to setup for the depth buffer render (no known issues here): (removed for simplification)

All of this code successfully created a depth map and puts it into g_pShadowMap

Here is the HLSL Code used to render the depth map (no known problems here): (removed for simplification)

I save the image of the depth map out into a file and look at it, since the values are 0.5 and larger the image is white, however if I divide the depth value by 100, I see the depth image more accurately, and it is correctly rendering a top-down light source from 20 units above the character, facing in the +x direction as planned. I am not sure if the z-distances stored within the map need to be a certain scale, but again, the image is white unless I divide the z values by 100 in order to see my "blue" depth map. (I do not use the divided values as my final image).

Here is the code for the final render of my terrain (this is where there is most likely a problem):

// Restore the render target and depth buffer
g_pd3dDevice->SetRenderTarget( 0, g_pOldColorRT );
g_pd3dDevice->SetDepthStencilSurface( g_pOldDepthRT );
SAFE_RELEASE( g_pOldColorRT );
SAFE_RELEASE( g_pOldDepthRT );

// Compute the texture matrix
float fTexOffs = 0.5 + (0.5 / (float)VGlobal::SHADOW_MAP_SIZE);
D3DXMATRIX matTexAdj( 0.5f,     0.0f,   0.0f,   0.0f,
                          0.0f,    -0.5f,   0.0f,   0.0f,
                          0.0f,     0.0f,   1.0f,   0.0f,
                          fTexOffs, fTexOffs,  0.0f, 1.0f );

D3DXMATRIX matTexture = matLightViewProj * matTexAdj;
g_pEffect->SetMatrix( "g_matTexture", &matTexture );
g_pEffect->SetTexture( "tShadowMap", g_pShadowMap );

// Begin the scene
// g_pd3dDevice->BeginScene();

// Setup the world, view, and projection matrices
SetupMatrices();

// Extract the 6 Viewing Frustrum planes for culling calculations
D3DXMATRIX tWorld, tView, tProj, tFinal;
g_pd3dDevice->GetTransform( D3DTS_PROJECTION, &tProj );
g_pd3dDevice->GetTransform( D3DTS_VIEW, &tView );
D3DXMatrixMultiply( &tFinal, &tView, &tProj);
gFrustrum.ExtractPlanesD3D( gFrustrum.frPlanes, tFinal, true );


D3DXMATRIX tempMat = matInfo.ReturnWorld() * matInfo.ReturnView() * matInfo.ReturnProj();
D3DXMatrixTranspose( &tempMat, &tempMat );

g_pEffect->SetMatrix( "worldViewProj", &tempMat );
g_pEffect->SetTechnique( "Technique0" );

//The main render code continues from here, and renders the non-shaded aspects correctly

Now for the final HLSL render code, I am assuming I am not dealing with the Shadow Map's matrix correctly...

fragment TerrainVS( vertex IN )
{
    fragment OUT;

    OUT.hposition = mul( worldViewProj, float4(IN.position, 1) );

    //Removed non-relevant code (textures/color calculation)
    //...

    //Shadow mapping
    // Output the projective texture coordinates
    OUT.vProjCoord = mul( g_matTexture, float4(IN.position, 1) );

return OUT;
}

pixel TerrainPS( fragment IN )
{
    pixel OUT;

    //Removed non-relevant code (normal/lighting/color calculations)
    //...

    // Grab the shadow term
    float fShadowTerm = 0.0f;
    fShadowTerm = tex2Dproj( ShadowSampler, IN.vProjCoord ) < (IN.vProjCoord.z - 0.001f) ? 0.1f : 1.0f;


    OUT.color = max( normColor1, normColor2 ) * fShadowTerm;

    OUT.color.a = 1.0f;

    return OUT;
}

Any help would be greatly appreciated. I can only assume that I am not calculating a matrix upon the Shadow Map correctly. The example uses LH Projection, while I use RH projections. Also, since I already had my game's matrices already set up, I did not use the examples's D3DXMatrixOrthoLH() call to calculate my final matLightViewProj and I am not sure if i needed to. I believe I have posted all the relevant code for this issue. Again I would greatly appreciate any help, it has been stumping me for several days now.


Solution

  • I have found the answer, apparently I needed to reverse my multiplication of the position and modified light matrix, using the code OUT.vProjCoord = mul( float4(IN.position, 1), g_matTexture );

    It confused me since I multiply it in the opposite order for the normal rendering of the scene.