From b419cc1148dc8fced9bd98a6ad820421a902f0fe Mon Sep 17 00:00:00 2001 From: hydrogendeuteride Date: Mon, 13 Oct 2025 23:19:28 +0900 Subject: [PATCH] EDIT: Forward-Z cascaded shadow map --- shaders/deferred_lighting.frag | 9 ++++++--- src/render/vk_renderpass_shadow.cpp | 10 +++++----- src/scene/vk_scene.cpp | 4 +++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/shaders/deferred_lighting.frag b/shaders/deferred_lighting.frag index f6523ee..54e3cf0 100644 --- a/shaders/deferred_lighting.frag +++ b/shaders/deferred_lighting.frag @@ -80,8 +80,11 @@ float calcShadowVisibility(vec3 worldPos, vec3 N, vec3 L) float mapD = texture(shadowTex[ci], suv + off).r; - // Standard depth shadow map: occluded when current > mapD + bias - float occ = step(current + bias, mapD); + // Forward-Z depth shadow map: + // - Occluded when current + bias > mapD + // - Unoccluded otherwise + // Use step(edge, x): returns 1 when x >= edge. Make occ=1 for occluded. + float occ = step(mapD + bias, current); occluded += occ * w; wsum += w; @@ -161,7 +164,7 @@ void main(){ vec3 kD = (1.0 - kS) * (1.0 - metallic); float NdotL = max(dot(N, L), 0.0); - // Shadowing (directional, reversed-Z shadow map) + // Shadowing (directional, forward-Z shadow map) float visibility = calcShadowVisibility(pos, N, L); vec3 irradiance = sceneData.sunlightColor.rgb * sceneData.sunlightColor.a * NdotL * visibility; diff --git a/src/render/vk_renderpass_shadow.cpp b/src/render/vk_renderpass_shadow.cpp index d5f68ca..cc0cf95 100644 --- a/src/render/vk_renderpass_shadow.cpp +++ b/src/render/vk_renderpass_shadow.cpp @@ -45,11 +45,11 @@ void ShadowPass::init(EngineContext *context) b.set_cull_mode(VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE); b.set_multisampling_none(); b.disable_blending(); - // Reverse-Z depth test for shadow maps (clear=0.0, GREATER_OR_EQUAL) - b.enable_depthtest(true, VK_COMPARE_OP_GREATER_OR_EQUAL); + // Forward-Z for shadow maps only (engine uses reversed-Z elsewhere) + // We clear depth to 1.0 and use LESS_OR_EQUAL so the nearest depth wins. + b.enable_depthtest(true, VK_COMPARE_OP_LESS_OR_EQUAL); b.set_depth_format(VK_FORMAT_D32_SFLOAT); - // Static depth bias to help with surface acne (tune later) b._rasterizer.depthBiasEnable = VK_TRUE; b._rasterizer.depthBiasConstantFactor = 2.0f; b._rasterizer.depthBiasSlopeFactor = 2.0f; @@ -85,8 +85,8 @@ void ShadowPass::register_graph(RenderGraph *graph, std::span cas RGPassType::Graphics, [shadowDepth](RGPassBuilder &builder, EngineContext *ctx) { - // Reverse-Z depth clear to 0.0 - VkClearValue clear{}; clear.depthStencil = {0.f, 0}; + // Forward-Z in shadow pass: clear depth to 1.0 (far) + VkClearValue clear{}; clear.depthStencil = {1.f, 0}; builder.write_depth(shadowDepth, true, clear); // Ensure index/vertex buffers are tracked as reads (like Geometry) diff --git a/src/scene/vk_scene.cpp b/src/scene/vk_scene.cpp index ad2238c..03f691a 100644 --- a/src/scene/vk_scene.cpp +++ b/src/scene/vk_scene.cpp @@ -110,7 +110,9 @@ void SceneManager::update_scene() { using namespace glm; const vec3 camPos = vec3(inverse(view)[3]); - vec3 L = normalize(-vec3(sceneData.sunlightDirection)); + // Use light-ray direction (from light to scene). + // Shaders compute per-fragment L as -sunlightDirection (vector to light). + vec3 L = normalize(vec3(sceneData.sunlightDirection)); if (!glm::all(glm::isfinite(L)) || glm::length2(L) < 1e-10f) L = glm::vec3(0.0f, -1.0f, 0.0f);