#include #include #include #include #include using namespace XCEngine::Components; using namespace XCEngine::Rendering; namespace { RenderContext CreateValidContext() { RenderContext context; context.device = reinterpret_cast(1); context.commandList = reinterpret_cast(1); context.commandQueue = reinterpret_cast(1); return context; } } // namespace TEST(SceneRenderRequestUtils_Test, RejectsNullDisabledAndInactiveCameras) { Scene scene("SceneRenderRequestUtilsUsableCameraScene"); GameObject* activeObject = scene.CreateGameObject("ActiveCamera"); auto* activeCamera = activeObject->AddComponent(); GameObject* disabledObject = scene.CreateGameObject("DisabledCamera"); auto* disabledCamera = disabledObject->AddComponent(); disabledCamera->SetEnabled(false); GameObject* inactiveObject = scene.CreateGameObject("InactiveCamera"); auto* inactiveCamera = inactiveObject->AddComponent(); inactiveObject->SetActive(false); EXPECT_FALSE(SceneRenderRequestUtils::IsUsableCamera(nullptr)); EXPECT_TRUE(SceneRenderRequestUtils::IsUsableCamera(activeCamera)); EXPECT_FALSE(SceneRenderRequestUtils::IsUsableCamera(disabledCamera)); EXPECT_FALSE(SceneRenderRequestUtils::IsUsableCamera(inactiveCamera)); } TEST(SceneRenderRequestUtils_Test, SortsSceneCamerasByStackDepthAndKeepsStableTieOrder) { Scene scene("SceneRenderRequestUtilsSortSceneCameras"); GameObject* lateBaseObject = scene.CreateGameObject("LateBase"); auto* lateBase = lateBaseObject->AddComponent(); lateBase->SetDepth(10.0f); lateBase->SetStackType(CameraStackType::Base); GameObject* firstTieObject = scene.CreateGameObject("FirstTie"); auto* firstTie = firstTieObject->AddComponent(); firstTie->SetDepth(2.0f); firstTie->SetStackType(CameraStackType::Base); GameObject* secondTieObject = scene.CreateGameObject("SecondTie"); auto* secondTie = secondTieObject->AddComponent(); secondTie->SetDepth(2.0f); secondTie->SetStackType(CameraStackType::Base); GameObject* overlayObject = scene.CreateGameObject("Overlay"); auto* overlay = overlayObject->AddComponent(); overlay->SetDepth(-50.0f); overlay->SetStackType(CameraStackType::Overlay); std::vector cameras = { overlay, lateBase, secondTie, firstTie }; SceneRenderRequestUtils::SortSceneCamerasForRendering(cameras); ASSERT_EQ(cameras.size(), 4u); EXPECT_EQ(cameras[0], secondTie); EXPECT_EQ(cameras[1], firstTie); EXPECT_EQ(cameras[2], lateBase); EXPECT_EQ(cameras[3], overlay); } TEST(SceneRenderRequestUtils_Test, SortsRequestsByPriorityAndKeepsStableTieOrder) { Scene scene("SceneRenderRequestUtilsSortRequests"); GameObject* firstObject = scene.CreateGameObject("First"); auto* firstCamera = firstObject->AddComponent(); GameObject* secondObject = scene.CreateGameObject("Second"); auto* secondCamera = secondObject->AddComponent(); CameraRenderRequest overlayRequest; overlayRequest.scene = &scene; overlayRequest.camera = secondCamera; overlayRequest.context = CreateValidContext(); overlayRequest.surface = RenderSurface(320, 180); overlayRequest.cameraDepth = 100.0f; overlayRequest.cameraStackOrder = 1; CameraRenderRequest secondTieRequest = overlayRequest; secondTieRequest.camera = secondCamera; secondTieRequest.cameraDepth = 5.0f; secondTieRequest.cameraStackOrder = 0; CameraRenderRequest firstTieRequest = overlayRequest; firstTieRequest.camera = firstCamera; firstTieRequest.cameraDepth = 5.0f; firstTieRequest.cameraStackOrder = 0; std::vector requests = { overlayRequest, secondTieRequest, firstTieRequest }; SceneRenderRequestUtils::SortCameraRenderRequests(requests); ASSERT_EQ(requests.size(), 3u); EXPECT_EQ(requests[0].camera, secondCamera); EXPECT_EQ(requests[1].camera, firstCamera); EXPECT_EQ(requests[2].camera, secondCamera); EXPECT_EQ(requests[2].cameraStackOrder, 1u); } TEST(SceneRenderRequestUtils_Test, ResolvesClearFlagsForExplicitAndAutoModes) { Scene scene("SceneRenderRequestUtilsClearFlags"); GameObject* baseObject = scene.CreateGameObject("Base"); auto* baseCamera = baseObject->AddComponent(); baseCamera->SetStackType(CameraStackType::Base); GameObject* overlayObject = scene.CreateGameObject("Overlay"); auto* overlayCamera = overlayObject->AddComponent(); overlayCamera->SetStackType(CameraStackType::Overlay); baseCamera->SetClearMode(CameraClearMode::ColorAndDepth); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*baseCamera, 0u, 0u), RenderClearFlags::All); baseCamera->SetClearMode(CameraClearMode::DepthOnly); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*baseCamera, 0u, 0u), RenderClearFlags::Depth); baseCamera->SetClearMode(CameraClearMode::None); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*baseCamera, 0u, 0u), RenderClearFlags::None); baseCamera->SetClearMode(CameraClearMode::Auto); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*baseCamera, 0u, 0u), RenderClearFlags::All); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*baseCamera, 1u, 1u), RenderClearFlags::Depth); overlayCamera->SetClearMode(CameraClearMode::Auto); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*overlayCamera, 0u, 0u), RenderClearFlags::All); EXPECT_EQ( SceneRenderRequestUtils::ResolveClearFlags(*overlayCamera, 0u, 1u), RenderClearFlags::Depth); } TEST(SceneRenderRequestUtils_Test, ComposesCameraViewportWithinNestedSurfaceRenderArea) { Scene scene("SceneRenderRequestUtilsViewport"); GameObject* cameraObject = scene.CreateGameObject("Camera"); auto* camera = cameraObject->AddComponent(); camera->SetViewportRect(XCEngine::Math::Rect(0.25f, 0.1f, 0.5f, 0.4f)); RenderSurface surface(800, 600); surface.SetRenderArea(XCEngine::Math::RectInt(100, 50, 400, 300)); const XCEngine::Math::RectInt renderArea = SceneRenderRequestUtils::ResolveCameraRenderArea(*camera, surface); EXPECT_EQ(renderArea.x, 200); EXPECT_EQ(renderArea.y, 80); EXPECT_EQ(renderArea.width, 200); EXPECT_EQ(renderArea.height, 120); } TEST(SceneRenderRequestUtils_Test, BuildsRequestMetadataAndRejectsZeroSizedRenderAreas) { Scene scene("SceneRenderRequestUtilsBuildRequest"); GameObject* cameraObject = scene.CreateGameObject("Camera"); auto* camera = cameraObject->AddComponent(); camera->SetDepth(3.0f); camera->SetStackType(CameraStackType::Overlay); camera->SetClearMode(CameraClearMode::Auto); camera->SetViewportRect(XCEngine::Math::Rect(0.25f, 0.5f, 0.5f, 0.25f)); CameraRenderRequest request; ASSERT_TRUE(SceneRenderRequestUtils::BuildCameraRenderRequest( scene, *camera, CreateValidContext(), RenderSurface(800, 600), 1u, 1u, request)); EXPECT_EQ(request.scene, &scene); EXPECT_EQ(request.camera, camera); EXPECT_FLOAT_EQ(request.cameraDepth, 3.0f); EXPECT_EQ(request.cameraStackOrder, 1u); EXPECT_EQ(request.clearFlags, RenderClearFlags::Depth); EXPECT_EQ(request.surface.GetRenderArea().x, 200); EXPECT_EQ(request.surface.GetRenderArea().y, 300); EXPECT_EQ(request.surface.GetRenderArea().width, 400); EXPECT_EQ(request.surface.GetRenderArea().height, 150); camera->SetViewportRect(XCEngine::Math::Rect(0.5f, 0.5f, 0.0f, 1.0f)); EXPECT_FALSE(SceneRenderRequestUtils::BuildCameraRenderRequest( scene, *camera, CreateValidContext(), RenderSurface(800, 600), 0u, 0u, request)); }