I have followed the sample in the Sample Browser to a tee as far as I can tell, but I must have missed something. I am fairly sure it has only to do with the depth texture itself, since I can confirm that the framework for shadow mapping is fine (setting of the light’s projection matrix, gathering objects the light can see, etc.) because it works in OpenGL, and obviously all of that code is the same between both builds.
This is the correct result via OpenGL:
In Direct3D 9, it is all just white, indicating either I didn’t draw anything to it, or I am not reading from it properly when I try to show it on my screen (less likely).
(By the way I do take measures to ensure it is not bound as both a texture and a render target.)
So, here is my code, which replicates the sample exactly as far as I can see.
Create the texture:
/**
* Creates a Direct3D 9 depth texture.
*
* \return Returns true if the creation of the texture succeeds. False indicates a resource error.
*/
LSBOOL LSE_CALL CDirectX9FloatTexture::CreateApiTexture() {
CDirectX9::SafeRelease( m_pd3tTexture );
CDirectX9::SafeRelease( m_pd3dsDepthSurface );
if ( FAILED( CDirectX9::GetDirectX9Device()->CreateTexture( m_ui32Width, m_ui32Height,
1UL, D3DUSAGE_RENDERTARGET,
D3DFMT_R32F,
D3DPOOL_DEFAULT,
&m_pd3tTexture,
NULL ) ) ) { return false; }
// Create a depth/stencil buffer of the same size.
if ( FAILED( CDirectX9::GetDirectX9Device()->CreateDepthStencilSurface( m_ui32Width, m_ui32Height,
CDirectX9::GetPresentParms().AutoDepthStencilFormat,
D3DMULTISAMPLE_NONE,
0,
TRUE,
&m_pd3dsDepthSurface,
NULL ) ) ) {
CDirectX9::SafeRelease( m_pd3tTexture );
return false;
}
return true;
}
Set it as a render target (makes a back-up of the existing render target).
/**
* Activate this texture as a render target.
*
* \return Returns true if the texture is ready to be used as a render target.
*/
LSBOOL LSE_CALL CDirectX9FloatTexture::SetAsRenderTarget() const {
if ( !m_pd3tTexture ) { return false; }
// Back up the current render targets.
if ( !m_pd3d9sPrevSurface.GetRenderTarget( true, 0UL ) ) { return false; }
if ( !m_pd3d9sPrevDepthSurface.GetRenderTarget( false, 0UL ) ) { return false; } // false = get the depth surface.
// Set the float buffer.
IDirect3DSurface9 * pd3dsSurface;
if ( FAILED( m_pd3tTexture->GetSurfaceLevel( 0, &pd3dsSurface ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetRenderTarget( 0, pd3dsSurface ) ) ) {
CDirectX9::SafeRelease( pd3dsSurface );
return false;
}
CDirectX9::SafeRelease( pd3dsSurface );
// Set the depth/stencil buffer.
if ( FAILED( CDirectX9::GetDirectX9Device()->SetDepthStencilSurface( m_pd3dsDepthSurface ) ) ) {
// Put the old render target back too.
m_pd3d9sPrevSurface.ReApply();
return false;
}
CFnd::SaveViewPort();
CFnd::SetViewport( 0, 0, GetWidth(), GetHeight() );
return true;
}
Render render render.
Then stop being a render target.
/**
* End its term as a render target.
*/
LSVOID LSE_CALL CDirectX9FloatTexture::EndAsRenderTarget() const {
// Puts the old surfaces back. One render target and one depth/stencil.
m_pd3d9sPrevSurface.ReApply();
m_pd3d9sPrevDepthSurface.ReApply();
CFnd::RestoreViewPort();
}
Apparently the error is in there, but perhaps I fail at displaying it on the screen, so here is how it is shown on the screen.
Activate it into a texture slot.
/**
* Activate this texture in a given slot.
*
* \param _ui32Slot Slot in which to place this texture.
* \return Returns true if the texture is activated successfully.
*/
LSBOOL LSE_CALL CDirectX9FloatTexture::Activate( LSUINT32 _ui32Slot ) {
if ( !m_pd3tTexture ) { return false; }
CCriticalSection::CLocker lLock( m_csBaseCrit );
if ( m_ui32LastTextures[_ui32Slot] != m_ui32Id ) {
m_ui32LastTextures[_ui32Slot] = m_ui32Id;
if ( m_ui32LastSlot != ~0UL ) {
// If we were bound to another slot, unbind from there.
m_ui32LastTextures[m_ui32LastSlot] = 0UL;
if ( FAILED( CDirectX9::GetDirectX9Device()->SetTexture( m_ui32LastSlot, NULL ) ) ) { return false; }
}
m_ui32LastSlot = _ui32Slot;
if ( FAILED( CDirectX9::GetDirectX9Device()->SetTexture( _ui32Slot, m_pd3tTexture ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_MAGFILTER, D3DTEXF_POINT ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_MINFILTER, D3DTEXF_POINT ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_MIPFILTER, D3DTEXF_NONE ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_MAXANISOTROPY, 1UL ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP ) ) ) { return false; }
if ( FAILED( CDirectX9::GetDirectX9Device()->SetSamplerState( _ui32Slot, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP ) ) ) { return false; }
}
return true;
}
And it can’t be bound and a render target, so I unbind it as follows.
/**
* Remove this texture from the last slot in which it was placed.
*/
LSVOID LSE_CALL CDirectX9FloatTexture::DeActivate() {
if ( m_ui32LastSlot != ~0UL ) {
CDirectX9::GetDirectX9Device()->SetTexture( m_ui32LastSlot, NULL );
m_ui32LastTextures[m_ui32LastSlot] = 0UL;
m_ui32LastSlot = ~0UL;
}
}
I render to to screen by accessing its .z and copying it into the .x and .y, and setting .w to 1.0f.
Did I miss something?
L. Spiro