From 72914b38651807e474057192498b659929e3e166 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Tue, 14 Apr 2026 00:43:55 +0800 Subject: [PATCH] Keep shadow execution state out of scene planner --- .../Planning/SceneRenderRequestPlanner.cpp | 5 -- .../test_scene_render_request_planner.cpp | 59 ++++++++++++++++--- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/engine/src/Rendering/Planning/SceneRenderRequestPlanner.cpp b/engine/src/Rendering/Planning/SceneRenderRequestPlanner.cpp index e96cec13..54dd2850 100644 --- a/engine/src/Rendering/Planning/SceneRenderRequestPlanner.cpp +++ b/engine/src/Rendering/Planning/SceneRenderRequestPlanner.cpp @@ -95,11 +95,6 @@ std::vector SceneRenderRequestPlanner::BuildRequests( *mainDirectionalLight, effectiveShadowSettings, viewportAspect); - if (request.directionalShadow.IsValid()) { - request.shadowCaster.clearFlags = RenderClearFlags::Depth; - request.shadowCaster.hasCameraDataOverride = true; - request.shadowCaster.cameraDataOverride = request.directionalShadow.cameraData; - } } } diff --git a/tests/Rendering/unit/test_scene_render_request_planner.cpp b/tests/Rendering/unit/test_scene_render_request_planner.cpp index d5229411..cdcd9c37 100644 --- a/tests/Rendering/unit/test_scene_render_request_planner.cpp +++ b/tests/Rendering/unit/test_scene_render_request_planner.cpp @@ -175,11 +175,8 @@ TEST(SceneRenderRequestPlanner_Test, BuildsDirectionalShadowPlanForBaseCameraWhe EXPECT_EQ(request.directionalShadow.mapHeight, 2048u); EXPECT_EQ(request.directionalShadow.lightDirection, XCEngine::Math::Vector3::Back()); EXPECT_GT(request.directionalShadow.focusPoint.z, 0.0f); - EXPECT_TRUE(request.shadowCaster.hasCameraDataOverride); + EXPECT_FALSE(request.shadowCaster.hasCameraDataOverride); EXPECT_EQ(request.shadowCaster.clearFlags, RenderClearFlags::Depth); - EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportWidth, 2048u); - EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportHeight, 2048u); - EXPECT_EQ(request.shadowCaster.cameraDataOverride.clearFlags, RenderClearFlags::Depth); } TEST(SceneRenderRequestPlanner_Test, SkipsDirectionalShadowPlanForOverlayCameraWhenBaseCameraExists) { @@ -211,7 +208,7 @@ TEST(SceneRenderRequestPlanner_Test, SkipsDirectionalShadowPlanForOverlayCameraW ASSERT_EQ(requests.size(), 2u); EXPECT_EQ(requests[0].camera, baseCamera); EXPECT_TRUE(requests[0].directionalShadow.enabled); - EXPECT_TRUE(requests[0].shadowCaster.hasCameraDataOverride); + EXPECT_FALSE(requests[0].shadowCaster.hasCameraDataOverride); EXPECT_EQ(requests[1].camera, overlayCamera); EXPECT_FALSE(requests[1].directionalShadow.enabled); @@ -259,8 +256,7 @@ TEST(SceneRenderRequestPlanner_Test, AppliesConfiguredDirectionalShadowPlanningS ASSERT_TRUE(request.directionalShadow.IsValid()); EXPECT_EQ(request.directionalShadow.mapWidth, 2048u); EXPECT_EQ(request.directionalShadow.mapHeight, 2048u); - EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportWidth, 2048u); - EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportHeight, 2048u); + EXPECT_FALSE(request.shadowCaster.hasCameraDataOverride); EXPECT_GE(request.directionalShadow.focusPoint.z, 6.0f); EXPECT_LE(request.directionalShadow.focusPoint.z, 6.3f); EXPECT_FLOAT_EQ(request.directionalShadow.sampling.receiverDepthBias, 0.0025f); @@ -300,7 +296,7 @@ TEST(SceneRenderRequestPlanner_Test, SanitizesInvalidDirectionalShadowPlanningSe EXPECT_FLOAT_EQ(settings.perspectiveFocusFactor, 1.0f); EXPECT_FLOAT_EQ(settings.orthographicFocusFactor, 2.0f); EXPECT_FLOAT_EQ(settings.minDepthRange, 20.0f); - EXPECT_FLOAT_EQ(settings.boundsPadding, 1.0f); + EXPECT_FLOAT_EQ(settings.boundsPadding, 0.5f); EXPECT_FLOAT_EQ(settings.minDepthPadding, 2.0f); EXPECT_FLOAT_EQ(settings.sampling.receiverDepthBias, 0.0010f); EXPECT_FLOAT_EQ(settings.sampling.normalBiasScale, 2.0f); @@ -309,6 +305,53 @@ TEST(SceneRenderRequestPlanner_Test, SanitizesInvalidDirectionalShadowPlanningSe EXPECT_EQ(settings.casterBias.depthBiasUnits, 4); } +TEST(SceneRenderRequestPlanner_Test, UsesDirectionalLightShadowOverridesWhenEnabled) { + Scene scene("SceneRenderRequestPlannerDirectionalShadowOverrides"); + + GameObject* cameraObject = scene.CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + camera->SetStackType(CameraStackType::Base); + camera->SetDepth(1.0f); + camera->SetProjectionType(CameraProjectionType::Perspective); + camera->SetNearClipPlane(0.3f); + camera->SetFarClipPlane(100.0f); + + GameObject* shadowLightObject = scene.CreateGameObject("ShadowLight"); + auto* shadowLight = shadowLightObject->AddComponent(); + shadowLight->SetLightType(LightType::Directional); + shadowLight->SetCastsShadows(true); + shadowLight->SetOverridesDirectionalShadowSettings(true); + shadowLight->SetDirectionalShadowReceiverDepthBias(0.0035f); + shadowLight->SetDirectionalShadowNormalBiasScale(1.25f); + shadowLight->SetDirectionalShadowStrength(0.6f); + shadowLight->SetDirectionalShadowDepthBiasFactor(3.25f); + shadowLight->SetDirectionalShadowDepthBiasUnits(7); + + SceneRenderRequestPlanner planner; + DirectionalShadowPlanningSettings settings = {}; + settings.sampling.receiverDepthBias = 0.0010f; + settings.sampling.normalBiasScale = 2.0f; + settings.sampling.shadowStrength = 0.85f; + settings.casterBias.depthBiasFactor = 2.5f; + settings.casterBias.depthBiasUnits = 4; + planner.SetDirectionalShadowPlanningSettings(settings); + + const std::vector requests = planner.BuildRequests( + scene, + nullptr, + CreateValidContext(), + RenderSurface(640, 360)); + + ASSERT_EQ(requests.size(), 1u); + const CameraRenderRequest& request = requests[0]; + ASSERT_TRUE(request.directionalShadow.IsValid()); + EXPECT_FLOAT_EQ(request.directionalShadow.sampling.receiverDepthBias, 0.0035f); + EXPECT_FLOAT_EQ(request.directionalShadow.sampling.normalBiasScale, 1.25f); + EXPECT_FLOAT_EQ(request.directionalShadow.sampling.shadowStrength, 0.6f); + EXPECT_FLOAT_EQ(request.directionalShadow.casterBias.depthBiasFactor, 3.25f); + EXPECT_EQ(request.directionalShadow.casterBias.depthBiasUnits, 7); +} + TEST(SceneRenderRequestPlanner_Test, IgnoresReceiveOnlyMeshesWhenFittingDirectionalShadowBounds) { Scene scene("SceneRenderRequestPlannerReceiveOnlyShadowBounds");