I am adding shadow mapping to my renderer.
Algorithm overview:
- Render shadow map(one directional light for now) -->
DXGI_FORMAT_D32_FLOATdepth buffer - Render gbuffer
- Bind (1) as an
DXGI_FORMAT_R32_FLOATSRV and perform deferred lighting using (2)
Doing so, I get this:
When I expect more something like this (rendered by raytracing):
The depth/shadow map as rendered from the light POV. Looks fine to me:
Depth seems to look good, but there is something wrong with the orientation of the final render.
For testing I decided to set the light transform to the camera view projection matrix.
XMStoreFloat4x4(&dx12Light.transform, scene.getCamera()->getDirectXTransposedVP());
Result: https://youtu.be/cgt6F5CEh80
There is definitely something wrong.
When I check the depth inside PIX, I get this if the format is let at R32_FLOAT:
And if I set it to D32_FLOAT, the expected result:
This is strange to me, but still I don't think that's the issue.
So, the code:
Render shadow map VS
#include "MeshGroup.hlsli"
#include "Light.hlsli"
struct VS_INPUT
{
float3 position : POSITION;
float3 normal : NORMAL;
float3 tangent : TANGENT;
float3 bitangent : BITANGENT;
float2 texCoord : TEXCOORD;
};
struct VS_OUTPUT
{
float4 position : SV_POSITION;
};
// LightMainCB is b1
cbuffer LightStructCB : register(b2)
{
LightStruct light;
};
VS_OUTPUT main(VS_INPUT input, uint instanceID : SV_InstanceID)
{
VS_OUTPUT output;
const float4x4 modelMat = meshGroupDatas[instanceID].transform;
const float4 worldPosition = mul(float4(input.position, 1.0f), modelMat);
output.position = mul(worldPosition, light.transform);
return output;
}
Render shadow map PS
struct VS_OUTPUT
{
float4 position: SV_POSITION;
};
float4 main(VS_OUTPUT input) : SV_TARGET
{
return float4(0.0f, 0.0f, 0.0f, 0.0f);
}
Shadow mapping calculation during deferred shading
// @See : https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
float ShadowMapping(LightStruct light, float3 P)
{
const float4 homogenous = mul(float4(P, 1.0f), light.transform);
const float3 NDC = homogenous.xyz/ homogenous.w;
const float3 projCoords = NDC * 0.5f + 0.5f;
const float closestDepth = shadowMap.Sample(tSampler, saturate(projCoords.xy)).x;
const float currentDepth = projCoords.z;
const float shadow = currentDepth > closestDepth ? 0.0 : 1.0f;
return shadow;
}
What am I doing wrong? My feeling is that the shadow map is properly rendered but sampling is broken.
Additional information
This is how getDirectXTransposedVP is computed:
inline DirectX::XMMATRIX getDirectXTransposedVP() const
{
return getDirectXTransposedVP(m_nearZ, m_farZ);
}
inline DirectX::XMMATRIX getDirectXTransposedVP(float nearZ, float farZ) const
{
const DirectX::XMMATRIX projMat = getDirectXPerspectiveMatrix(nearZ, farZ);
const DirectX::XMMATRIX viewMat = getDirectXViewMatrix();
const DirectX::XMMATRIX vpMat = viewMat * projMat;
return XMMatrixTranspose(vpMat);
}
inline DirectX::XMMATRIX getDirectXPerspectiveMatrix() const
{
return getDirectXPerspectiveMatrix(m_nearZ, m_farZ);
}
inline DirectX::XMMATRIX getDirectXPerspectiveMatrix(float nearZ, float farZ) const
{
return DirectX::XMMatrixPerspectiveFovRH(m_fovY.getValue(), m_aspectRatio,
nearZ, farZ);
}
inline DirectX::XMMATRIX getDirectXViewMatrix() const
{
const DirectX::XMVECTOR cPos = DirectX::XMVectorSet(m_position.x, m_position.y, m_position.z, 0.0f);
const auto target = computeTarget();
const DirectX::XMVECTOR cTarg = DirectX::XMVectorSet(target.x, target.y, target.z, 0.0f);
const DirectX::XMVECTOR cUp = DirectX::XMVectorSet(s_UP.x, s_UP.y, s_UP.z, 0.0f);
return DirectX::XMMatrixLookAtRH(cPos, cTarg, cUp);
}
Here the minimalist deferred shading implementation:
float4 main(VS_OUTPUT input) : SV_TARGET
{
const float4 wsPos = positionWsOccludedTex[input.position.xy];
if (wsPos.w == 0.0f)
discard;
const float3 P = wsPos.xyz;
float3 N = normalWsTex[input.position.xy];
float3 V = EyePosition.xyz - P;
if (dot(N, V) < 0.0f)
{
N *= float3(-1.0f, -1.0f, -1.0f);
}
const float4 albedo = albedoTexture[input.position.xy];
const LightStruct light = Lights[0];// We only use the first directional light for the test:)
const float3 L = -light.direction.xyz;
const float NoL = max(0.0f, dot(N, L));
float4 color = light.color * albedo * InvPI;
color *= NoL;
color *= ShadowMapping(light, P);
return color;
}
The world position AOV(positionWsOccludedTex)
[
The albedo AOV(albedoTexture):





