From ad66ef9ca6e74cf22b3b30a22f07e4a8bbb91839 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 6 Mar 2026 20:04:19 -0800 Subject: [PATCH] Fix shadow flicker: render every frame, tighten shadow frustum Remove frame throttling that skipped shadow updates in dense scenes, causing visible flicker on player and NPCs. Reduce shadow half-extent from 180 to 60 for 3x higher resolution on nearby shadows. --- src/rendering/renderer.cpp | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 0f1d7593..77b4c74a 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -3766,10 +3766,10 @@ void Renderer::renderHUD() { // in createPerFrameResources() as part of the Vulkan shadow infrastructure. glm::mat4 Renderer::computeLightSpaceMatrix() { - constexpr float kShadowHalfExtent = 180.0f; - constexpr float kShadowLightDistance = 280.0f; + constexpr float kShadowHalfExtent = 60.0f; + constexpr float kShadowLightDistance = 200.0f; constexpr float kShadowNearPlane = 1.0f; - constexpr float kShadowFarPlane = 600.0f; + constexpr float kShadowFarPlane = 450.0f; // Use active lighting direction so shadow projection matches main shading. // Fragment shaders derive lighting with `ldir = normalize(-lightDir.xyz)`, @@ -3920,18 +3920,7 @@ void Renderer::renderShadowPass() { if (!shadowsEnabled || shadowDepthImage == VK_NULL_HANDLE) return; if (currentCmd == VK_NULL_HANDLE) return; - const int baseInterval = std::max(1, envIntOrDefault("WOWEE_SHADOW_INTERVAL", 1)); - const int denseInterval = std::max(baseInterval, envIntOrDefault("WOWEE_SHADOW_INTERVAL_DENSE", 3)); - const uint32_t denseCharThreshold = static_cast(std::max(1, envIntOrDefault("WOWEE_DENSE_CHAR_THRESHOLD", 120))); - const uint32_t denseM2Threshold = static_cast(std::max(1, envIntOrDefault("WOWEE_DENSE_M2_THRESHOLD", 900))); - const bool denseScene = - (characterRenderer && characterRenderer->getInstanceCount() >= denseCharThreshold) || - (m2Renderer && m2Renderer->getInstanceCount() >= denseM2Threshold); - const int shadowInterval = denseScene ? denseInterval : baseInterval; - if (++shadowFrameCounter_ < static_cast(shadowInterval)) { - return; - } - shadowFrameCounter_ = 0; + // Shadows render every frame — throttling causes visible flicker on player/NPCs // Compute and store light space matrix; write to per-frame UBO lightSpaceMatrix = computeLightSpaceMatrix(); @@ -3984,9 +3973,7 @@ void Renderer::renderShadowPass() { vkCmdSetScissor(currentCmd, 0, 1, &sc); // Phase 7/8: render shadow casters - const float baseShadowCullRadius = static_cast(std::max(40, envIntOrDefault("WOWEE_SHADOW_CULL_RADIUS", 180))); - const float denseShadowCullRadius = static_cast(std::max(30, envIntOrDefault("WOWEE_SHADOW_CULL_RADIUS_DENSE", 90))); - const float shadowCullRadius = denseScene ? std::min(baseShadowCullRadius, denseShadowCullRadius) : baseShadowCullRadius; + const float shadowCullRadius = 80.0f; if (wmoRenderer) { wmoRenderer->renderShadow(currentCmd, lightSpaceMatrix, shadowCenter, shadowCullRadius); }