Keep shadow execution state out of scene planner

This commit is contained in:
2026-04-14 00:43:55 +08:00
parent e6950fa704
commit 72914b3865
2 changed files with 51 additions and 13 deletions

View File

@@ -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<CameraComponent>();
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<LightComponent>();
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<CameraRenderRequest> 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");