Add directional shadow request planning

This commit is contained in:
2026-04-04 20:03:23 +08:00
parent 781c3b9a78
commit a548e0d0a9
6 changed files with 251 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include <XCEngine/Components/CameraComponent.h>
#include <XCEngine/Components/LightComponent.h>
#include <XCEngine/Rendering/SceneRenderRequestPlanner.h>
#include <XCEngine/Scene/Scene.h>
@@ -126,3 +127,76 @@ TEST(SceneRenderRequestPlanner_Test, BuildsRequestsAndDropsZeroSizedViewportsWit
EXPECT_EQ(requests[1].camera, overlay);
EXPECT_EQ(requests[1].clearFlags, RenderClearFlags::Depth);
}
TEST(SceneRenderRequestPlanner_Test, BuildsDirectionalShadowPlanForBaseCameraWhenMainDirectionalLightCastsShadows) {
Scene scene("SceneRenderRequestPlannerDirectionalShadow");
GameObject* cameraObject = scene.CreateGameObject("Camera");
auto* camera = cameraObject->AddComponent<CameraComponent>();
camera->SetStackType(CameraStackType::Base);
camera->SetDepth(1.0f);
GameObject* shadowLightObject = scene.CreateGameObject("ShadowLight");
auto* shadowLight = shadowLightObject->AddComponent<LightComponent>();
shadowLight->SetLightType(LightType::Directional);
shadowLight->SetIntensity(2.5f);
shadowLight->SetCastsShadows(true);
SceneRenderRequestPlanner planner;
const std::vector<CameraRenderRequest> requests = planner.BuildRequests(
scene,
nullptr,
CreateValidContext(),
RenderSurface(640, 360));
ASSERT_EQ(requests.size(), 1u);
const CameraRenderRequest& request = requests[0];
EXPECT_EQ(request.camera, camera);
ASSERT_TRUE(request.directionalShadow.IsValid());
EXPECT_TRUE(request.directionalShadow.enabled);
EXPECT_EQ(request.directionalShadow.mapWidth, 1024u);
EXPECT_EQ(request.directionalShadow.mapHeight, 1024u);
EXPECT_EQ(request.directionalShadow.lightDirection, XCEngine::Math::Vector3::Back());
EXPECT_GT(request.directionalShadow.focusPoint.z, 0.0f);
EXPECT_TRUE(request.shadowCaster.hasCameraDataOverride);
EXPECT_EQ(request.shadowCaster.clearFlags, RenderClearFlags::Depth);
EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportWidth, 1024u);
EXPECT_EQ(request.shadowCaster.cameraDataOverride.viewportHeight, 1024u);
EXPECT_EQ(request.shadowCaster.cameraDataOverride.clearFlags, RenderClearFlags::Depth);
}
TEST(SceneRenderRequestPlanner_Test, SkipsDirectionalShadowPlanForOverlayCameraWhenBaseCameraExists) {
Scene scene("SceneRenderRequestPlannerOverlayShadow");
GameObject* baseCameraObject = scene.CreateGameObject("BaseCamera");
auto* baseCamera = baseCameraObject->AddComponent<CameraComponent>();
baseCamera->SetStackType(CameraStackType::Base);
baseCamera->SetDepth(1.0f);
GameObject* overlayCameraObject = scene.CreateGameObject("OverlayCamera");
auto* overlayCamera = overlayCameraObject->AddComponent<CameraComponent>();
overlayCamera->SetStackType(CameraStackType::Overlay);
overlayCamera->SetDepth(2.0f);
GameObject* shadowLightObject = scene.CreateGameObject("ShadowLight");
auto* shadowLight = shadowLightObject->AddComponent<LightComponent>();
shadowLight->SetLightType(LightType::Directional);
shadowLight->SetIntensity(3.0f);
shadowLight->SetCastsShadows(true);
SceneRenderRequestPlanner planner;
const std::vector<CameraRenderRequest> requests = planner.BuildRequests(
scene,
nullptr,
CreateValidContext(),
RenderSurface(640, 360));
ASSERT_EQ(requests.size(), 2u);
EXPECT_EQ(requests[0].camera, baseCamera);
EXPECT_TRUE(requests[0].directionalShadow.enabled);
EXPECT_TRUE(requests[0].shadowCaster.hasCameraDataOverride);
EXPECT_EQ(requests[1].camera, overlayCamera);
EXPECT_FALSE(requests[1].directionalShadow.enabled);
EXPECT_FALSE(requests[1].shadowCaster.hasCameraDataOverride);
}