diff --git a/engine/src/Rendering/SceneRenderer.cpp b/engine/src/Rendering/SceneRenderer.cpp index 3d7cd0b8..97f7fd9f 100644 --- a/engine/src/Rendering/SceneRenderer.cpp +++ b/engine/src/Rendering/SceneRenderer.cpp @@ -1,6 +1,8 @@ #include "Rendering/SceneRenderer.h" #include "Components/CameraComponent.h" +#include "Components/GameObject.h" +#include "Scene/Scene.h" #include @@ -17,6 +19,13 @@ bool CompareCameraRenderRequest(const CameraRenderRequest& lhs, const CameraRend return lhs.camera < rhs.camera; } +bool IsUsableCamera(const Components::CameraComponent* camera) { + return camera != nullptr && + camera->IsEnabled() && + camera->GetGameObject() != nullptr && + camera->GetGameObject()->IsActiveInHierarchy(); +} + } // namespace SceneRenderer::SceneRenderer() = default; @@ -44,19 +53,45 @@ std::vector SceneRenderer::BuildRenderRequests( const RenderSurface& surface) const { std::vector requests; - Components::CameraComponent* camera = m_sceneExtractor.SelectCamera(scene, overrideCamera); - if (camera == nullptr) { - return requests; + std::vector cameras; + if (IsUsableCamera(overrideCamera)) { + cameras.push_back(overrideCamera); + } else { + cameras = scene.FindObjectsOfType(); + cameras.erase( + std::remove_if( + cameras.begin(), + cameras.end(), + [](const Components::CameraComponent* camera) { + return !IsUsableCamera(camera); + }), + cameras.end()); + } + + std::stable_sort( + cameras.begin(), + cameras.end(), + [](const Components::CameraComponent* lhs, const Components::CameraComponent* rhs) { + if (lhs->GetDepth() != rhs->GetDepth()) { + return lhs->GetDepth() < rhs->GetDepth(); + } + + return lhs < rhs; + }); + + for (size_t cameraIndex = 0; cameraIndex < cameras.size(); ++cameraIndex) { + Components::CameraComponent* camera = cameras[cameraIndex]; + + CameraRenderRequest request; + request.scene = &scene; + request.camera = camera; + request.context = context; + request.surface = surface; + request.cameraDepth = camera->GetDepth(); + request.clearFlags = cameraIndex == 0 ? RenderClearFlags::All : RenderClearFlags::Depth; + requests.push_back(request); } - CameraRenderRequest request; - request.scene = &scene; - request.camera = camera; - request.context = context; - request.surface = surface; - request.cameraDepth = camera->GetDepth(); - request.clearFlags = RenderClearFlags::All; - requests.push_back(request); return requests; } diff --git a/tests/Rendering/unit/test_camera_scene_renderer.cpp b/tests/Rendering/unit/test_camera_scene_renderer.cpp index 52f84571..5c6b21a6 100644 --- a/tests/Rendering/unit/test_camera_scene_renderer.cpp +++ b/tests/Rendering/unit/test_camera_scene_renderer.cpp @@ -275,7 +275,7 @@ TEST(CameraRenderer_Test, ShutsDownSequencesWhenPostPassInitializationFails) { "shutdown:pre" })); } -TEST(SceneRenderer_Test, BuildsSingleExplicitRequestFromSelectedCamera) { +TEST(SceneRenderer_Test, BuildsSortedRequestsForAllUsableCamerasAndHonorsOverrideCamera) { Scene scene("SceneRendererRequestScene"); GameObject* lowCameraObject = scene.CreateGameObject("LowCamera"); @@ -294,17 +294,21 @@ TEST(SceneRenderer_Test, BuildsSingleExplicitRequestFromSelectedCamera) { const std::vector defaultRequests = renderer.BuildRenderRequests(scene, nullptr, context, surface); - ASSERT_EQ(defaultRequests.size(), 1u); - EXPECT_EQ(defaultRequests[0].camera, highCamera); - EXPECT_EQ(defaultRequests[0].cameraDepth, 5.0f); + ASSERT_EQ(defaultRequests.size(), 2u); + EXPECT_EQ(defaultRequests[0].camera, lowCamera); + EXPECT_EQ(defaultRequests[0].cameraDepth, 1.0f); EXPECT_EQ(defaultRequests[0].clearFlags, RenderClearFlags::All); EXPECT_EQ(defaultRequests[0].surface.GetWidth(), 320u); EXPECT_EQ(defaultRequests[0].surface.GetHeight(), 180u); + EXPECT_EQ(defaultRequests[1].camera, highCamera); + EXPECT_EQ(defaultRequests[1].cameraDepth, 5.0f); + EXPECT_EQ(defaultRequests[1].clearFlags, RenderClearFlags::Depth); const std::vector overrideRequests = renderer.BuildRenderRequests(scene, lowCamera, context, surface); ASSERT_EQ(overrideRequests.size(), 1u); EXPECT_EQ(overrideRequests[0].camera, lowCamera); + EXPECT_EQ(overrideRequests[0].clearFlags, RenderClearFlags::All); } TEST(SceneRenderer_Test, ForwardsPipelineLifetimeAndRenderCallsToCameraRenderer) {