diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 4f42b91..dde24a6 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -46,13 +46,16 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target { uint cascadeIndex = 0; for (uint c = 0; c < NUM_CASCADES - 1; ++c) { - if (params.position_VS.z > pShadowMapping.cascadeSplits[c]) { + if (-params.position_VS.z > pShadowMapping.cascadeSplits[c]) { cascadeIndex = c + 1; } } float4 lightSpacePos = mul(pShadowMapping.lightSpaceMatrices[cascadeIndex][i], float4(params.position_WS, 1)); - lightSpacePos = float4(lightSpacePos.xy * 0.5 + 0.5, lightSpacePos.zw); + // Negate Y to compensate for orthographic projection's Y negation + viewport Y-flip double-inversion + lightSpacePos = float4(lightSpacePos.x * 0.5 + 0.5, -lightSpacePos.y * 0.5 + 0.5, lightSpacePos.zw); float4 shadowCoord = lightSpacePos; + // Convert NDC z to viewport depth space (inverse depth: near=1, far=0) + float currentDepth = 1.0 - shadowCoord.z; int3 texDim; pShadowMapping.shadowMaps[cascadeIndex].GetDimensions(texDim.x, texDim.y, texDim.z); float scale = 1.5f; @@ -65,10 +68,10 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target //for (int x = -range; x <= range; ++x) { // for (int y = -range; y <= range; ++y) { float shadow = 1.0f; - if (shadowCoord.z > 0.0 && shadowCoord.z < 1.0) + if (currentDepth > 0.0 && currentDepth < 1.0) { float dist = pShadowMapping.shadowMaps[cascadeIndex].Sample(pShadowMapping.shadowSampler, float3(shadowCoord.xy, i)).r; - if (shadowCoord.w > 0 && dist < shadowCoord.z) + if (shadowCoord.w > 0 && currentDepth < dist) { shadow = 0; } diff --git a/src/Engine/Graphics/RenderPass/ShadowPass.cpp b/src/Engine/Graphics/RenderPass/ShadowPass.cpp index 1e5cc6b..b7c3430 100644 --- a/src/Engine/Graphics/RenderPass/ShadowPass.cpp +++ b/src/Engine/Graphics/RenderPass/ShadowPass.cpp @@ -64,7 +64,7 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr float uniform = minZ + range * p; float d = cascadeSplitLambda * (log - uniform) + uniform; cascadeSplits[i] = (d - nearClip) / clipRange; - splitDepths[i] = farClip - cascadeSplits[i] * clipRange; + splitDepths[i] = d; cascades[i].viewParams.clear(); } cascadeSplitsBuffer->updateContents(0, sizeof(float) * NUM_CASCADES, splitDepths); @@ -76,8 +76,8 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr float splitDist = cascadeSplits[i]; Array frustumCorners = { - Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f), Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f), + Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f), }; for (auto& c : frustumCorners) { @@ -111,7 +111,7 @@ void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Tr Vector cameraPos = frustumCenter - lightDir * -minExtents.z; Matrix4 viewMatrix = glm::lookAt(cameraPos, frustumCenter, Vector(0, 1, 0)); Matrix4 projectionMatrix = - orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, maxExtents.z - minExtents.z, 0.0f); + orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z); Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix; viewParams = { .viewMatrix = viewMatrix, @@ -194,7 +194,7 @@ void ShadowPass::render() { .rasterizationState = { .cullMode = Gfx::SE_CULL_MODE_NONE, - .depthBiasEnable = false, + .depthBiasEnable = true, .depthBiasConstantFactor = depthBiasConstant, .depthBiasSlopeFactor = depthBiasSlope, },