Upcoming Events
Southwest Gaming Expo
11/20 - 11/22 @ Dallas, TX

Workshop on Network and Systems Support for Games (NetGames 2009)
11/23 - 11/25 @ Paris, France

ICIDS 2009 Interactive Storytelling
12/9 - 12/11 @ Guimarães, Portugal

Global Game Jam
1/29 - 1/31  

More events...


Quick Stats
1544 people currently visiting GDNet.
2341 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!



Link to us

Link to us

  Intel sponsors gamedev.net search:   

Soft-Edged Shadows


Step 1: Rendering the shadow map

First, we need to create a texture that can hold the scene depth. Since we need to use this as a render target, we will also need to create a surface that holds the texture's surface data. The texture must be a floating point one because of the large range of depth values. The R32F format has sufficient precision and so we use it. Here's the codelet that is used to create the texture.

// Create the shadow map
if( FAILED( g_pd3dDevice->CreateTexture( SHADOW_MAP_SIZE,
                     SHADOW_MAP_SIZE, 1, D3DUSAGE_RENDERTARGET,
                     D3DFMT_R32F, D3DPOOL_DEFAULT, &g_pShadowMap,
                     NULL ) ) )
{
   MessageBox( g_hWnd, "Unable to create shadow map!",
               "Error", MB_OK | MB_ICONERROR );
   return E_FAIL;
}

// Grab the texture's surface
g_pShadowMap->GetSurfaceLevel( 0, &g_pShadowSurf );

Now, to generate the shadow map, we need to render the scene's depth to the shadow map. To do this, we must render the scene with the light's world-view-projection matrix. Here's how we build that matrix.

// Ordinary view matrix
D3DXMatrixLookAtLH( &matView, &vLightPos, &vLightAim, &g_vUp );
// Projection matrix for the light
D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian(30.0f),
                            1.0f, 1.0f, 1024.0f );
// Concatenate the world matrix with the above
// two to get the required matrix
matLightViewProj = matWorld * matView * matProj;

Here are vertex and pixel shaders for rendering the scene depth.

// Shadow generation vertex shader
struct VSOUTPUT_SHADOW
{
   float4 vPosition    : POSITION;
   float  fDepth       : TEXCOORD0;
};

VSOUTPUT_SHADOW VS_Shadow( float4 inPosition : POSITION )
{
   // Output struct
   VSOUTPUT_SHADOW OUT = (VSOUTPUT_SHADOW)0;
   // Output the transformed position
   OUT.vPosition = mul( inPosition, g_matLightViewProj );
   // Output the scene depth
   OUT.fDepth = OUT.vPosition.z;
   return OUT;
}

Here, we multiply the position by the light's world-view-projection matrix (g_matLightViewProj) and use the transformed position's z-value as the depth. In the pixel shader, we output the depth as the color.

float4  PS_Shadow( VSOUTPUT_SHADOW IN ) : COLOR0
{
   // Output the scene depth
   return float4( IN.fDepth, IN.fDepth, IN.fDepth, 1.0f );
}

Voila! We have the shadow map. Below is a color coded version of the shadow map, dark blue indicates smaller depth values, whereas light blue indicates larger depth values.





Step 2


Contents
  Introduction
  Step 1
  Step 2
  Step 3
  Step 4

  Source code
  Printable version
  Discuss this article