From f2eebfc842c09b645e936864bfa91e506d06de0f Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Wed, 15 Apr 2026 21:28:02 +0800 Subject: [PATCH] refactor(rendering): move scene data policy into render pipelines --- engine/CMakeLists.txt | 1 + .../XCEngine/Rendering/RenderPipeline.h | 5 ++ .../Rendering/Execution/CameraRenderer.cpp | 41 +------------ engine/src/Rendering/RenderPipeline.cpp | 58 +++++++++++++++++++ .../unit/test_camera_scene_renderer.cpp | 48 +++++++++++++++ 5 files changed, 115 insertions(+), 38 deletions(-) create mode 100644 engine/src/Rendering/RenderPipeline.cpp diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index af6cdbeb..2afc62df 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -600,6 +600,7 @@ add_library(XCEngine STATIC ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Features/BuiltinGaussianSplatPass.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Features/BuiltinVolumetricPass.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Features/Internal/BuiltinGaussianSplatPassResources.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderPipeline.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderPipelineAsset.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderSurface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/SceneRenderFeaturePass.cpp diff --git a/engine/include/XCEngine/Rendering/RenderPipeline.h b/engine/include/XCEngine/Rendering/RenderPipeline.h index 202ebd0c..7e416628 100644 --- a/engine/include/XCEngine/Rendering/RenderPipeline.h +++ b/engine/include/XCEngine/Rendering/RenderPipeline.h @@ -18,6 +18,7 @@ namespace XCEngine { namespace Rendering { class RenderGraphBuilder; +struct CameraFramePlan; struct RenderPipelineStageRenderGraphContext { RenderGraphBuilder& graphBuilder; @@ -84,6 +85,10 @@ public: ~RenderPipeline() override = default; + virtual void ConfigureRenderSceneData( + const CameraFramePlan& plan, + RenderSceneData& sceneData) const; + void SetCameraFrameStandalonePass( CameraFrameStage stage, std::unique_ptr pass) { diff --git a/engine/src/Rendering/Execution/CameraRenderer.cpp b/engine/src/Rendering/Execution/CameraRenderer.cpp index 4a352b09..f7cc1753 100644 --- a/engine/src/Rendering/Execution/CameraRenderer.cpp +++ b/engine/src/Rendering/Execution/CameraRenderer.cpp @@ -31,41 +31,6 @@ std::unique_ptr CreatePipelineFromAsset( return std::make_unique(); } -Resources::ShaderKeywordSet BuildSceneGlobalShaderKeywords( - const RenderSceneData& sceneData) { - Resources::ShaderKeywordSet keywords = {}; - if (sceneData.lighting.HasMainDirectionalShadow()) { - keywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS"); - } - - Resources::NormalizeShaderKeywordSetInPlace(keywords); - return keywords; -} - -RenderEnvironmentData BuildEnvironmentData(const CameraFramePlan& plan) { - RenderEnvironmentData environment = {}; - const RenderSurface& mainSceneSurface = plan.GetMainSceneSurface(); - if (plan.request.camera == nullptr || - mainSceneSurface.GetDepthAttachment() == nullptr || - !HasRenderClearFlag(plan.request.clearFlags, RenderClearFlags::Color) || - !plan.request.camera->IsSkyboxEnabled() || - plan.request.camera->GetProjectionType() != Components::CameraProjectionType::Perspective) { - return environment; - } - - if (const Resources::Material* skyboxMaterial = plan.request.camera->GetSkyboxMaterial()) { - environment.mode = RenderEnvironmentMode::MaterialSkybox; - environment.materialSkybox.material = skyboxMaterial; - return environment; - } - - environment.mode = RenderEnvironmentMode::ProceduralSkybox; - environment.skybox.topColor = plan.request.camera->GetSkyboxTopColor(); - environment.skybox.horizonColor = plan.request.camera->GetSkyboxHorizonColor(); - environment.skybox.bottomColor = plan.request.camera->GetSkyboxBottomColor(); - return environment; -} - } // namespace CameraRenderer::CameraRenderer() @@ -127,10 +92,10 @@ bool CameraRenderer::BuildSceneDataForPlan( } outSceneData.lighting.mainDirectionalShadow = shadowState.shadowData; - outSceneData.globalShaderKeywords = BuildSceneGlobalShaderKeywords(outSceneData); - outSceneData.cameraData.clearFlags = plan.request.clearFlags; - outSceneData.environment = BuildEnvironmentData(plan); + if (m_pipeline != nullptr) { + m_pipeline->ConfigureRenderSceneData(plan, outSceneData); + } if (plan.request.hasClearColorOverride) { outSceneData.cameraData.clearColor = plan.request.clearColorOverride; } diff --git a/engine/src/Rendering/RenderPipeline.cpp b/engine/src/Rendering/RenderPipeline.cpp new file mode 100644 index 00000000..2315ac90 --- /dev/null +++ b/engine/src/Rendering/RenderPipeline.cpp @@ -0,0 +1,58 @@ +#include + +#include "Components/CameraComponent.h" +#include "Rendering/Execution/CameraFramePlan.h" + +namespace XCEngine { +namespace Rendering { + +namespace { + +Resources::ShaderKeywordSet BuildDefaultSceneGlobalShaderKeywords( + const RenderSceneData& sceneData) { + Resources::ShaderKeywordSet keywords = {}; + if (sceneData.lighting.HasMainDirectionalShadow()) { + keywords.enabledKeywords.PushBack("XC_MAIN_LIGHT_SHADOWS"); + } + + Resources::NormalizeShaderKeywordSetInPlace(keywords); + return keywords; +} + +RenderEnvironmentData BuildDefaultEnvironmentData(const CameraFramePlan& plan) { + RenderEnvironmentData environment = {}; + const RenderSurface& mainSceneSurface = plan.GetMainSceneSurface(); + if (plan.request.camera == nullptr || + mainSceneSurface.GetDepthAttachment() == nullptr || + !HasRenderClearFlag(plan.request.clearFlags, RenderClearFlags::Color) || + !plan.request.camera->IsSkyboxEnabled() || + plan.request.camera->GetProjectionType() != Components::CameraProjectionType::Perspective) { + return environment; + } + + if (const Resources::Material* skyboxMaterial = plan.request.camera->GetSkyboxMaterial()) { + environment.mode = RenderEnvironmentMode::MaterialSkybox; + environment.materialSkybox.material = skyboxMaterial; + return environment; + } + + environment.mode = RenderEnvironmentMode::ProceduralSkybox; + environment.skybox.topColor = plan.request.camera->GetSkyboxTopColor(); + environment.skybox.horizonColor = plan.request.camera->GetSkyboxHorizonColor(); + environment.skybox.bottomColor = plan.request.camera->GetSkyboxBottomColor(); + return environment; +} + +} // namespace + +void RenderPipeline::ConfigureRenderSceneData( + const CameraFramePlan& plan, + RenderSceneData& sceneData) const { + sceneData.globalShaderKeywords = + BuildDefaultSceneGlobalShaderKeywords(sceneData); + sceneData.environment = + BuildDefaultEnvironmentData(plan); +} + +} // namespace Rendering +} // namespace XCEngine diff --git a/tests/Rendering/unit/test_camera_scene_renderer.cpp b/tests/Rendering/unit/test_camera_scene_renderer.cpp index 33d9f821..3611e82f 100644 --- a/tests/Rendering/unit/test_camera_scene_renderer.cpp +++ b/tests/Rendering/unit/test_camera_scene_renderer.cpp @@ -50,6 +50,7 @@ CameraFrameStageSourceBinding ResolveStageSourceBinding( struct MockPipelineState { int initializeCalls = 0; int shutdownCalls = 0; + int configureRenderSceneDataCalls = 0; int renderCalls = 0; int recordMainSceneCalls = 0; int executeRecordedMainSceneCalls = 0; @@ -84,6 +85,7 @@ struct MockPipelineState { bool lastBlackboardMainSceneDepthValid = false; bool lastBlackboardMainDirectionalShadowValid = false; bool lastBlackboardObjectIdColorValid = false; + std::function configureRenderSceneData = {}; std::vector renderedCameras; std::vector renderedClearFlags; std::vector renderedClearColors; @@ -439,6 +441,18 @@ public: return true; } + void ConfigureRenderSceneData( + const CameraFramePlan& plan, + RenderSceneData& sceneData) const override { + ++m_state->configureRenderSceneDataCalls; + if (m_state->configureRenderSceneData) { + m_state->configureRenderSceneData(plan, sceneData); + return; + } + + RenderPipeline::ConfigureRenderSceneData(plan, sceneData); + } + void Shutdown() override { ++m_state->shutdownCalls; ShutdownCameraFrameStandalonePasses(); @@ -1205,6 +1219,40 @@ TEST(CameraRenderer_Test, PromotesSkyboxMaterialIntoEnvironmentFrameData) { EXPECT_EQ(state->lastSkyboxMaterial, &skyboxMaterial); } +TEST(CameraRenderer_Test, UsesPipelineSceneDataConfigurationHook) { + Scene scene("CameraRendererSceneDataHookScene"); + + GameObject* cameraObject = scene.CreateGameObject("Camera"); + auto* camera = cameraObject->AddComponent(); + camera->SetPrimary(true); + camera->SetSkyboxEnabled(true); + + XCEngine::Resources::Material skyboxMaterial; + camera->SetSkyboxMaterial(&skyboxMaterial); + + auto state = std::make_shared(); + state->configureRenderSceneData = []( + const CameraFramePlan&, + RenderSceneData& sceneData) { + sceneData.environment = {}; + sceneData.globalShaderKeywords = {}; + }; + CameraRenderer renderer(std::make_unique(state)); + + CameraRenderRequest request; + request.scene = &scene; + request.camera = camera; + request.context = CreateValidContext(); + request.surface = RenderSurface(320, 200); + request.surface.SetDepthAttachment(reinterpret_cast(1)); + + ASSERT_TRUE(renderer.Render(CameraFramePlan::FromRequest(request))); + EXPECT_EQ(state->configureRenderSceneDataCalls, 1); + EXPECT_FALSE(state->lastHasSkybox); + EXPECT_EQ(state->lastEnvironmentMode, RenderEnvironmentMode::None); + EXPECT_EQ(state->lastSkyboxMaterial, nullptr); +} + TEST(CameraRenderer_Test, ExecutesInjectedPreAndPostPassSequencesAroundPipelineRender) { Scene scene("CameraRendererPassScene");