Hello all,
I've run into some problems implementing Shadow Mapping.
I am able to Create a seperate render target, depthBuffer, shaderResourceView
I then render all the depth on a first pass from the objects (from the perspective of the one light source) and put it into a texture.
I then use THAT texture as input into the next shader. My problem? No Shadows are appearing on the screen :(
Ill post the code pertaining to the shadow Mapping below and maybe you guys can see something I can't. (I am following the Rastertek tutorials)
//Create Shadow Map Texture
///////////////////////////////////////////////////
D3D11_TEXTURE2D_DESC textureDesc;
HRESULT result;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
D3D11_TEXTURE2D_DESC depthBufferDesc;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
// Initialize the render target texture description.
ZeroMemory(&textureDesc, sizeof(textureDesc));
// Setup the render target texture description.
textureDesc.Width = 1024;
textureDesc.Height = 1024;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
textureDesc.SampleDesc.Count = 1;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
// Create the render target texture.
bro->dev->CreateTexture2D(&textureDesc, NULL, &renderTargetTexture);
// Setup the description of the render target view.
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
renderTargetViewDesc.Texture2D.MipSlice = 0;
// Create the render target view.
bro->dev->CreateRenderTargetView(renderTargetTexture, &renderTargetViewDesc, &renderTargetView);
// Setup the description of the shader resource view.
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
// Create the shader resource view.
bro->dev->CreateShaderResourceView(renderTargetTexture, &shaderResourceViewDesc, &shaderResourceView);
// Initialize the description of the depth buffer.
ZeroMemory(&depthBufferDesc, sizeof(depthBufferDesc));
// Set up the description of the depth buffer.
depthBufferDesc.Width = 1024;
depthBufferDesc.Height = 1024;
depthBufferDesc.MipLevels = 1;
depthBufferDesc.ArraySize = 1;
depthBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDesc.SampleDesc.Count = 1;
depthBufferDesc.SampleDesc.Quality = 0;
depthBufferDesc.Usage = D3D11_USAGE_DEFAULT;
depthBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDesc.CPUAccessFlags = 0;
depthBufferDesc.MiscFlags = 0;
// Create the texture for the depth buffer using the filled out description.
bro->dev->CreateTexture2D(&depthBufferDesc, NULL, &depthStencilBuffer);
// Initailze the depth stencil view description.
ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));
// Set up the depth stencil view description.
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
// Create the depth stencil view.
bro->dev->CreateDepthStencilView(depthStencilBuffer, &depthStencilViewDesc, &depthStencilView);
// Setup the viewport for rendering.
viewPort.Width = (float)1024;
viewPort.Height = (float)1024;
viewPort.MinDepth = 0.0f;
viewPort.MaxDepth = 1.0f;
viewPort.TopLeftX = 0.0f;
viewPort.TopLeftY = 0.0f;
// Setup the projection matrix. //lProj == lightProjection
lProj.lightProj = XMMatrixPerspectiveFovLH(((float)3.12f / 2.0f), 1.0f, 0.1f, 600.0f);
// Create an orthographic projection matrix for 2D rendering.
//lProj.lightProj = XMMatrixOrthographicLH((float)1024, (float)1024, 0.1f, 600.0f);
/////////////////////////////////////////////
//
Thats the code to create the textures for the shadow map and the additonal renderTarget, DepthBuffer, and viewport
//RenderToTexture
/////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////
bro->devcon->OMSetRenderTargets(1, &renderTargetView, depthStencilView);
// Set the viewport.
float clearColor2[] = {0.0f, 0.0f, 0.0f, 0.0f};
bro->devcon->RSSetViewports(1, &viewPort);
XMFLOAT3 position;
position.x = lightCB.light[5].pos.x;
position.y = lightCB.light[5].pos.y;
position.z = lightCB.light[5].pos.z;
XMFLOAT3 lookat;
lookat.x = 0.0f;
lookat.y = 0.0f;
lookat.z = 0.0f;
XMFLOAT3 up;
up.x = 0.0f;
up.y = -1.0f;
up.z = 0.0f;
lView.lightView = XMMatrixLookAtLH(XMLoadFloat3(&position), XMLoadFloat3(&lookat), XMLoadFloat3(&up));
float fieldOfView, screenAspect;
// Setup field of view and screen aspect for a square light source.
fieldOfView = (float)3.12 / 2.0f;
screenAspect = 1.0f;
// Create the projection matrix for the light.
lProj.lightProj = XMMatrixPerspectiveFovLH(fieldOfView, screenAspect, 0.1f, 600.0f);
depthSh.RenderToTexture(bro, 6, &worldMat, &lView.lightView, &lProj.lightProj, vertexBuffer, indexBuffer,
worldCB, lightViewCB, lightProjCB, x, y, 0.0f, 1.57f, 0.0f, 0.0f);
bro->devcon->OMSetRenderTargets(1, &bro->backBuffer, bro->depthBuffer);
bro->devcon->RSSetViewports(1, &bro->view);
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
bro->devcon->UpdateSubresource(lightC, 0, 0, lightCB.light, 0, 0);
unsigned int stride = 0;
stride = sizeof(Verts);
unsigned int offset = 0;
bro->devcon->IASetInputLayout(bro->shadowL);
bro->devcon->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, offset);
bro->devcon->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
bro->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
bro->devcon->VSSetShader(bro->shadowVS, 0, 0);
bro->devcon->PSSetShader(bro->shadowPS, 0, 0);
bro->devcon->PSSetShaderResources(0, 3, bro->colorMap);
bro->devcon->PSSetShaderResources(1, 1, &shaderResourceView);
bro->devcon->PSSetSamplers(0, 1, &bro->colorSampler);
bro->devcon->PSSetSamplers(1, 1, &clamp);
bro->rotMat = XMMatrixRotationRollPitchYaw(1.57f, 0.0f, 0.0f);
bro->transMat = XMMatrixTranslation(x * xOffset - 0.0f, 0.0f, y * yOffset - 0.0f);
worldMat = bro->rotMat * bro->transMat;
worldMat = XMMatrixTranspose(worldMat);
bro->devcon->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
bro->devcon->UpdateSubresource(bro->viewCB, 0, 0, &bro->viewMat, 0, 0);
bro->devcon->UpdateSubresource(bro->projCB, 0, 0, &bro->projMat, 0, 0);
bro->devcon->UpdateSubresource(lightViewCB, 0, 0, &lView.lightView, 0, 0);
bro->devcon->UpdateSubresource(lightProjCB, 0, 0, &lProj.lightProj, 0, 0);
bro->devcon->UpdateSubresource(lightC, 0, 0, lightCB.light, 0, 0);
bro->devcon->VSSetConstantBuffers(0, 1, &worldCB);
bro->devcon->VSSetConstantBuffers(1, 1, &bro->viewCB);
bro->devcon->VSSetConstantBuffers(2, 1, &bro->projCB);
bro->devcon->VSSetConstantBuffers(3, 1, &lightViewCB);
bro->devcon->VSSetConstantBuffers(4, 1, &lightProjCB);
bro->devcon->PSSetConstantBuffers(0, 1, &lightC);
bro->devcon->DrawIndexed(6, 0, 0);
Above is the code to switch the render target view, viewport and to render to the shader resource view through the depthShader Class
After I render the texture through the depthShader Class (whose code Ill post below). I use the texture created as input into the next shader
unsigned int stride = sizeof(Verts);
unsigned int offset = 0;
bro->devcon->IASetInputLayout(bro->depthL);
bro->devcon->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R16_UINT, offset);
bro->devcon->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
bro->devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
bro->devcon->VSSetShader(bro->depthVS, 0, 0);
bro->devcon->PSSetShader(bro->depthPS, 0, 0);
bro->transMat = XMMatrixTranslation((x * 2.0f) + xOffset, offsetY, y * -2.0f);
bro->rotMat = XMMatrixRotationRollPitchYaw(rotationX, rotationY, rotationZ);
*worldMat = bro->transMat * bro->rotMat;
*worldMat = XMMatrixTranspose(*worldMat);
*lightView = XMMatrixTranspose(*lightView);
*lightProj = XMMatrixTranspose(*lightProj);
bro->devcon->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
bro->devcon->UpdateSubresource(viewCB, 0, 0, &lightView, 0, 0);
bro->devcon->UpdateSubresource(projCB, 0, 0, &lightProj, 0, 0);
bro->devcon->VSSetConstantBuffers(0, 1, &worldCB);
bro->devcon->VSSetConstantBuffers(1, 1, &viewCB);
bro->devcon->VSSetConstantBuffers(2, 1, &projCB);
bro->devcon->DrawIndexed(drawC, 0, 0);
And the corresponding depth shader that I use to render to texture
cbuffer world : register(b0)
{
matrix worldMat;
};
cbuffer view : register(b1)
{
matrix viewMat;
};
cbuffer proj : register(b2)
{
matrix projMat;
};
struct VS_Input
{
float4 position : POSITION;
};
struct PS_Input
{
float4 position : SV_POSITION;
float4 depthPosition : TEXTURE0;
};
////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PS_Input VS(VS_Input input)
{
PS_Input output = (PS_Input)0;
// Change the position vector to be 4 units for proper matrix calculations.
// input.position.w = 1.0f;
// Calculate the position of the vertex against the world, view, and projection matrices.
output.position = mul(input.position, worldMat);
output.position = mul(output.position, viewMat);
output.position = mul(output.position, projMat);
// Store the position value in a second input value for depth value calculations.
output.depthPosition = output.position;
return output;
}
float4 PS(PS_Input input) : SV_TARGET
{
float depthValue;
float4 color;
// Get the depth value of the pixel by dividing the Z pixel depth by the homogeneous W coordinate.
depthValue = input.depthPosition.z / input.depthPosition.w;
color = float4(depthValue, depthValue, depthValue, 1.0f);
return color;
}
And below is the final shader that takes the rendered to texture image as input and performs the calculations and projective texturing
//Load three textures into GPU Register(t0) for one pixel
//////////////////////////////////////////////////////////////////
Texture2D colorMap[3] : register(t0);
Texture2D depthMTexture : register(t1);
//Load Unused Sampler into GPU Register(s0)
//////////////////////////////////////////////////////////////////
SamplerState colorSampler : register(s0);
SamplerState sampleTypeClamp : register(s1);
//CONSTANT BUFFERS=========================
//CB's for Matrices, allows C++ Code to send constants
//to the shader and bind them into Registers (b0, b1, b2 respectively)
//===========================================================
cbuffer world : register(b0)
{
matrix worldMat;
}
cbuffer view : register(b1)
{
matrix viewMat;
}
cbuffer proj : register(b2)
{
matrix projMat;
}
cbuffer lView : register(b3)
{
matrix lightViewMat;
}
cbuffer lProj : register(b4)
{
matrix lightProjMat;
}
//==================================================
//Structure for Light
struct Light
{
float3 dir;
float3 att;
float range;
float4 diffuse;
float4 ambient;
float specularPower;
float4 specularColor;
float4 isLight;
};
struct Shadow
{
float4 ambient;
float4 diffuse;
float4 specular;
};
//Load the main light into the shader and bind it to register b0
cbuffer LightCB : register(b0)
{
Light light[6];
}
//Structures for Vertex and Pixel
/////////////////////////////////////////
struct VS_Input
{
float4 pos : POSITION;
float2 tex : TEXCOORD;
float3 norm : NORMAL;
float3 binorm : BINORMAL;
float3 tang : TANGENT;
};
struct PS_Input
{
float4 pos : SV_POSITION;
float4 wPos : POSITION;
float2 tex : TEXCOORD;
float3 norm : NORMAL;
float3 binorm : BINORMAL;
float3 tang : TANGENT;
float4 lightViewP : TEXCOORD1;
float3 lightPos : TEXCOORD2;
};
///////////////////////////////////////////
PS_Input VS(VS_Input vertex)
{
PS_Input vsOut = (PS_Input)0;
float4 cameraPos = 0.0f;
vsOut.pos = mul(vertex.pos, worldMat);
vsOut.pos = mul(vsOut.pos , viewMat);
vsOut.pos = mul(vsOut.pos , projMat);
vsOut.lightViewP = mul(vertex.pos, worldMat);
vsOut.lightViewP = mul(vsOut.lightViewP, lightViewMat);
vsOut.lightViewP = mul(vsOut.lightViewP, lightProjMat);
vsOut.norm = mul(vertex.norm, worldMat);
vsOut.norm = normalize(vsOut.norm);
vsOut.binorm = mul(vertex.binorm, worldMat);
vsOut.binorm = normalize(vsOut.binorm);
vsOut.tang = mul(vertex.tang, worldMat);
vsOut.tang = normalize(vsOut.tang);
vsOut.wPos = mul(vertex.pos, worldMat);
cameraPos = mul(vsOut.pos, worldMat);
cameraPos = mul(cameraPos, viewMat);
vsOut.tex = vertex.tex;
return vsOut;
}
float4 PS(PS_Input texel) : SV_TARGET
{
float3 finalColor = float3(0.0f, 0.0f, 0.0f);
float4 textureMap = colorMap[0].Sample(colorSampler, texel.tex);
float4 bumpMap = float4(0.0f, 0.0f, 0.0f, 0.0f);
float3 lightToPixelVec[6];
float d[6];
float3 finalAmbient = 0.0f;
float4 color = 0.0f;
float4 color2 = 0.0f;
float4 color3 = 0.0f;
bool isCloseEnough = false;
float lightIntensity = 0.0f;
float lightIntensity2 = 0.0f;
float bumpNormal = 0.0f;
float lightClose = 0.0f;
bool bumpHit = false;
color = textureMap;
//Shadow Map Variables
////////////////////////////////////
float bias = 0.001f;
float2 projTexCoord = float2(0.0f, 0.0f);
float depthValue = 0.0f;
float lightDepthValue = 0.0f;
////////////////////////////////////
bias = 0.001f;
projTexCoord.x = texel.lightViewP.x / texel.lightViewP.w / 2.0f + 0.5f;
projTexCoord.y = -texel.lightViewP.y / texel.lightViewP.w / 2.0f + 0.5f;
if((saturate(projTexCoord.x) == projTexCoord.x) && (saturate(projTexCoord.y) == projTexCoord.y))
{
depthValue = depthMTexture.Sample(sampleTypeClamp, projTexCoord).r;
lightDepthValue = texel.lightViewP.z / texel.lightViewP.w;
lightDepthValue -= bias;
if (lightDepthValue < depthValue)
{
lightIntensity = saturate(dot(texel.norm, texel.lightPos));
if (lightIntensity > 0.0f)
{
bumpMap = colorMap[1].Sample(colorSampler, texel.tex);
bumpMap = (bumpMap * 2.0f) - 1.0f;
bumpNormal = texel.norm + bumpMap.x * texel.tang + bumpMap.y * texel.binorm;
lightIntensity = saturate(dot(bumpNormal, -2.0f));
lightIntensity2 = saturate(dot(texel.norm, -2.0f));
color2 = lightIntensity * light[5].diffuse; // light[0].diffuse
color3 = lightIntensity2 * light[5].diffuse;
color = saturate(color2);
bumpHit = true;
//return color;
}
}
}
color = light[5].ambient;
color *= textureMap;
return color;
}
I know it's a lot of code. But if someone could just take a quick glance at my code and tell me what i am overlooking. Am I missing something from the tutorial?
Maybe my texture creation and the arguments I feed to it are off.
Any response is appreciated, I work a bunch so I may not be able to respond swiftly.
-Marcus