I've been trying to implement Shadow Mapping on Direct3D11 for a few days and I've got the algoritm so far but it seems like I'm having some problem with the Render To Texture part.
What happens is that everythins shows OK (gray) if I render my first Shadow Mapping pass to the screen (for debugging) but the entire map is WHITE if I render to my Depth Stencil View. I mean, there's no Shadow or any color change in my scene as if the entire texture was white or as if the sampler wout not be working.
My personal suspicions are:
- The sampler state creation code is messed up;
- The texture is not being (property) bound to the pipeline.
- Some depth buffer clearing problem
- Some depth testing problem when writing to the texture;
But I don't know since I've never done Shadow Mapping before .........
I would really appreciate if anyone would help me find what's wrong with this thing.
TIA
The following part is just about code.
My hobbyst game code is available in Google Code if anyone wanna see it:
http://code.google.com/p/game-code/ (Yeah, bad name .. I know!)
This project is made of a Static Library project where all the Direct3D11 stuff is and an EXE where I test it on a very simple Pong game.
I will post pieces of code from both below but here are the most relevant files:
The Direct3DManager Class
http://code.google.c...CodeInternals.h
http://code.google.c...sManagement.cpp
This is my main Direct3D class which tracks my shadow mapping resources long many others. This class starts on line 168 of the .h file and all around the .cpp file.
My shaders are all in this file:
http://code.google.c...ers/standard.fx
OK, the important parts of the CPP file IMHO are:
#pragma region Shadow Mapping Initialization
// Create depth stencil texture
D3D11_TEXTURE2D_DESC dtd =
{
width,//UINT Width;
height,//UINT Height;
1,//UINT MipLevels;
1,//UINT ArraySize;
DXGI_FORMAT_R32_TYPELESS,//DXGI_FORMAT Format;
1,//DXGI_SAMPLE_DESC SampleDesc;
0,
D3D11_USAGE_DEFAULT,//D3D11_USAGE Usage;
D3D11_BIND_DEPTH_STENCIL|D3D11_BIND_SHADER_RESOURCE,//UINT BindFlags;
0,//UINT CPUAccessFlags;
0//UINT MiscFlags;
};
hr = _pd3dDevice->CreateTexture2D( &dtd, NULL, &_pShadowMapTexture );
if( FAILED( hr ) )
return false;
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd =
{
DXGI_FORMAT_D32_FLOAT,
D3D11_DSV_DIMENSION_TEXTURE2D,
0
};
hr = _pd3dDevice->CreateDepthStencilView(_pShadowMapTexture, &dsvd, &_pShadowMapDSV);
if( FAILED( hr ) )
return false;
D3D11_SHADER_RESOURCE_VIEW_DESC dsrvd =
{
DXGI_FORMAT_R32_FLOAT,
D3D11_SRV_DIMENSION_TEXTURE2D,
0,
0
};
dsrvd.Texture2D.MipLevels = 1;
hr = _pd3dDevice->CreateShaderResourceView(_pShadowMapTexture, &dsrvd, &_pShadowMapView);
if( FAILED( hr ) )
return false;
#pragma endregion
For some reason I've placed the SamplerState creation code down below:
D3D11_SAMPLER_DESC SamDescShad =
{
D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT,// D3D11_FILTER Filter;
D3D11_TEXTURE_ADDRESS_BORDER, //D3D11_TEXTURE_ADDRESS_MODE AddressU;
D3D11_TEXTURE_ADDRESS_BORDER, //D3D11_TEXTURE_ADDRESS_MODE AddressV;
D3D11_TEXTURE_ADDRESS_BORDER, //D3D11_TEXTURE_ADDRESS_MODE AddressW;
0,//FLOAT MipLODBias;
0,//UINT MaxAnisotropy;
D3D11_COMPARISON_LESS , //D3D11_COMPARISON_FUNC ComparisonFunc;
0.0,0.0,0.0,0.0,//FLOAT BorderColor[ 4 ];
0,//FLOAT MinLOD;
0//FLOAT MaxLOD;
};
/*SamDescShad.MaxAnisotropy = 15;
SamDescShad.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
SamDescShad.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
SamDescShad.Filter = D3D11_FILTER_ANISOTROPIC;
SamDescShad.ComparisonFunc = D3D11_COMPARISON_NEVER;*/
hr = _pd3dDevice->CreateSamplerState( &sampDesc, &_pShadowMapSampler );
if( FAILED( hr ) )
return false;
My Light -> Object -> Projection code is in this function:
void Direct3DManager::setShadowMapTarget(XMFLOAT3& objectPos)
{
if(_light.position.x || _light.position.y || _light.position.z)
{
XMVECTOR eye = XMVectorSet( _light.position.x, _light.position.y, _light.position.z, 0);
XMVECTOR at = XMVectorSet( objectPos.x, objectPos.y, objectPos.z, 0);
//at = XMVectorSet(0, 0, 0, 0);
const XMVECTOR up = XMVectorSet(0,1,0,0);
XMMATRIX projectionMatrix = XMMatrixPerspectiveFovLH( XM_PIDIV2, 1, 1, 1000);
_shaderGlobals.LightViewProjection = XMMatrixTranspose (
XMMatrixLookAtLH(eye, at, up) * projectionMatrix
);
}
}
And finally my Shadow Map is setup in these functions:
void Direct3DManager::beginShadowMapping()
{
_previousWorld = _worldMatrix;
_previousProj = _projectionMatrix;
_previousView = _viewMatrix;
ID3D11ShaderResourceView* nullSRV = 0;
_pImmediateContext->PSSetShaderResources(1, 1, &nullSRV);
_pImmediateContext->ClearDepthStencilView( _pShadowMapDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );
_pImmediateContext->ClearDepthStencilView( _pDepthStencilView, D3D11_CLEAR_DEPTH, 1, 0);
ID3D11RenderTargetView* nullView = 0;
_pImmediateContext->OMSetRenderTargets( 1, &nullView, _pShadowMapDSV );
setTechnique(SHADER_TECHNIQUES_SHADOW_MAP);
}
void Direct3DManager::endShadowMapping()
{
ID3D11RenderTargetView* pNullView = 0;
_pImmediateContext->OMSetRenderTargets( 1, &pNullView, 0 );
setTechnique(SHADER_TECHNIQUES_DEFAULT);
_pImmediateContext->OMSetRenderTargets( 1, &_pRenderTargetView, _pDepthStencilView );
_pImmediateContext->ClearDepthStencilView( _pDepthStencilView, D3D11_CLEAR_DEPTH, 1, 0);
_pImmediateContext->PSSetShaderResources(1, 1, &_pShadowMapView);
_pImmediateContext->PSSetSamplers(1, 1, &_pShadowMapSampler);
updateWorld(_previousWorld);
updateView(_previousView);
updateProjection(_previousProj);
}