I'm reading luna directx11 book,i want to implement shadow mapping using it but i'v got a problem with it here is the image from my scene(at bottom right you can see shadow map,why is it in red color?
and here is my Shadow map load function:
this->m_viewPort.Height = height;
this->m_viewPort.MaxDepth = 1.0f;
this->m_viewPort.MinDepth = 0.0f;
this->m_viewPort.TopLeftX = 0.0f;
this->m_viewPort.TopLeftY = 0.0f;
this->m_viewPort.Width = width;
D3D11_TEXTURE2D_DESC desc;
desc.ArraySize = 1;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL;
desc.CPUAccessFlags = 0;
//Why? Because this format will interpet SRV as TYPELESS and DSV as UNORM,we don't know the type at the moment!
desc.Format = DXGI_FORMAT_R24G8_TYPELESS;
desc.Height = height;
desc.MipLevels = 1;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Width = width;
ID3D11Texture2D * depthMap;
HRESULT hr = device->CreateTexture2D(&desc, nullptr, &depthMap);
D3D11_DEPTH_STENCIL_VIEW_DESC dsvdesc;
dsvdesc.Format =DXGI_FORMAT_D24_UNORM_S8_UINT;
dsvdesc.Texture2D.MipSlice = 0;
dsvdesc.Flags = 0;
dsvdesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
device->CreateDepthStencilView(depthMap, &dsvdesc, &this->m_DSV);
D3D11_SHADER_RESOURCE_VIEW_DESC srvdesc;
srvdesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvdesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
srvdesc.Texture2D.MipLevels = desc.MipLevels;
srvdesc.Texture2D.MostDetailedMip = 0;
hr = device->CreateShaderResourceView(depthMap, &srvdesc, &this->m_SRV);
this->m_shader = ref new Shader();
D3D11_RASTERIZER_DESC shadowRenderStateDesc;
ZeroMemory(&shadowRenderStateDesc, sizeof(D3D11_RASTERIZER_DESC));
shadowRenderStateDesc.CullMode = D3D11_CULL_NONE;
shadowRenderStateDesc.FillMode = D3D11_FILL_SOLID;
shadowRenderStateDesc.DepthClipEnable = true;
DX::ThrowIfFailed(
GDevice.m_d3dDevice->CreateRasterizerState(
&shadowRenderStateDesc,
&m_shadowRenderState
)
);
And also here is shadow map rendering function:
ID3D11RenderTargetView *nullRenderTarget[1] = { 0 };
deviceContext->OMSetRenderTargets(1, nullRenderTarget, this->m_DSV);
deviceContext->RSSetState(m_shadowRenderState.Get());
deviceContext->RSSetViewports(1, &this->m_viewPort);
deviceContext->ClearDepthStencilView(this->m_DSV, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0.0f);
below i construct my View and projection and Shadow Transform matrices and pass them to shader WITHOUT TRANSPOSING THEM(Is it alright?):
XMVECTOR lightDir = XMVectorSet(20.0f,0.0f,0.0f,0.0f);
XMVECTOR lightPos = XMVectorSet(x, y, z, 0.0f);
XMVECTOR lightTarget = XMLoadFloat3(&XMFLOAT3(20.0f, 0.0f, 0.0f));
XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
XMMATRIX V = XMMatrixLookAtLH(lightPos, lightTarget, lightUp);
XMFLOAT3 targetPositionLightSpace;
XMStoreFloat3(&targetPositionLightSpace, XMVector3TransformCoord(lightTarget, V));
float fieldOfView = (float)3.14f;
float screenAspect = 1.0f;
XMFLOAT3 sphereCenterLS;
XMStoreFloat3(&sphereCenterLS ,XMVector3TransformCoord(lightTarget, V));
int l = sphereCenterLS.x - 200.0f;
int b = sphereCenterLS.y - 200.0f;
int n = sphereCenterLS.z - 200.0f;
int r = sphereCenterLS.x + 200.0f;
int t = sphereCenterLS.y + 200.0f;
int f = sphereCenterLS.z + 200.0f;
// Create the projection matrix for the light.
XMMATRIX P = XMMatrixOrthographicOffCenterLH(l, r, l, t, n, f);
XMMATRIX T(0.5f, 0.0f, 0.0f, 0.0f,
0.0f, -0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f);
XMMATRIX S = V*P*T;
XMStoreFloat4x4(&this->m_lightView, V);
XMStoreFloat4x4(&this->m_lightProj, P);
XMStoreFloat4x4(&this->m_lightShadowTransform, S);
after that i set projection and view matrices to light view and projection matrices and call render scene depth function and then reset back the view projection matrices to be camera view and projection.
below is my shader code for shadow mapping(Some of it's code):
Texture2D depthMap : register(t1);
SamplerComparisonState samShadow
{
Filter = COMPARISON_MIN_MAG_LINEAR_MIP_POINT;
AddressU = BORDER;
AddressV = BORDER;
AddressW = BORDER;
BorderColor = float4(0.0f, 0.0f, 0.0f, 0.0f);
ComparisonFunc = LESS;
};
float ShadowAmount = CalcShadowFactor(samShadow, depthMap, IN.shadowPosH);
float CalcShadowFactor(SamplerComparisonState samShadow,
Texture2D shadowMap,
float4 shadowPosH)
{
// Complete projection by doing division by w.
shadowPosH.xyz /= shadowPosH.w;
// Depth in NDC space.
float depth = shadowPosH.z;
// Texel size.
const float dx = SMAP_DX;
float percentLit = 0.0f;
const float2 offsets[9] =
{
float2(-dx, -dx), float2(0.0f, -dx), float2(dx, -dx),
float2(-dx, 0.0f), float2(0.0f, 0.0f), float2(dx, 0.0f),
float2(-dx, +dx), float2(0.0f, +dx), float2(dx, +dx)
};
[unroll]
for (int i = 0; i < 9; ++i)
{
percentLit += shadowMap.SampleCmpLevelZero(samShadow,
shadowPosH.xy + offsets[i], depth).r;
}
return percentLit /= 9.0f;
}
lighting calculation:
toLight = -light[i].direction;
TempAmbient = Mat.ambient * light[i].color;
toLight = normalize(toLight);
diffuseAmount = dot(toLight, IN.normal);
if (diffuseAmount > 0.0f)
{
TempDiffuse = diffuseAmount;
}
and at last:
TotalDiffuse += TempDiffuse*ShadowAmount;
TotalAmbient += TempAmbient;
In my vertex shader i multiply all vertices by ShaderTransform Matrix and store in ShaderPosH. But as you can see in the image that no shadow is here and i find out that shadow amount return from function is always 1.0!! also i have to mention two things first is that the shader code is from pixel shader and second is i'm using Direct3D 11.1 for rendering on windows 8.1. what is the problem with it? if you need more information tell me ;)