#include "Rendering/CameraRenderer.h" #include "Rendering/Pipelines/BuiltinForwardPipeline.h" #include "Rendering/RenderPipelineAsset.h" #include "Rendering/RenderSurface.h" #include "Scene/Scene.h" namespace XCEngine { namespace Rendering { namespace { bool InitializePassSequence( RenderPassSequence* sequence, const RenderContext& context, bool& initialized) { if (sequence == nullptr) { initialized = false; return true; } initialized = sequence->Initialize(context); if (!initialized) { sequence->Shutdown(); } return initialized; } void ShutdownPassSequence(RenderPassSequence* sequence, bool initialized) { if (sequence != nullptr && initialized) { sequence->Shutdown(); } } std::shared_ptr CreateDefaultPipelineAsset() { static const std::shared_ptr s_defaultPipelineAsset = std::make_shared(); return s_defaultPipelineAsset; } std::unique_ptr CreatePipelineFromAsset( const std::shared_ptr& pipelineAsset) { if (pipelineAsset != nullptr) { std::unique_ptr pipeline = pipelineAsset->CreatePipeline(); if (pipeline != nullptr) { return pipeline; } } return std::make_unique(); } } // namespace CameraRenderer::CameraRenderer() : CameraRenderer(CreateDefaultPipelineAsset()) { } CameraRenderer::CameraRenderer(std::unique_ptr pipeline) : m_pipelineAsset(nullptr) { ResetPipeline(std::move(pipeline)); } CameraRenderer::CameraRenderer(std::shared_ptr pipelineAsset) : m_pipelineAsset(std::move(pipelineAsset)) { SetPipelineAsset(m_pipelineAsset); } CameraRenderer::~CameraRenderer() { if (m_pipeline) { m_pipeline->Shutdown(); } } void CameraRenderer::SetPipeline(std::unique_ptr pipeline) { m_pipelineAsset.reset(); ResetPipeline(std::move(pipeline)); } void CameraRenderer::SetPipelineAsset(std::shared_ptr pipelineAsset) { m_pipelineAsset = pipelineAsset != nullptr ? std::move(pipelineAsset) : CreateDefaultPipelineAsset(); ResetPipeline(CreatePipelineFromAsset(m_pipelineAsset)); } void CameraRenderer::ResetPipeline(std::unique_ptr pipeline) { if (m_pipeline != nullptr) { m_pipeline->Shutdown(); } m_pipeline = std::move(pipeline); if (m_pipeline == nullptr) { m_pipelineAsset = CreateDefaultPipelineAsset(); m_pipeline = CreatePipelineFromAsset(m_pipelineAsset); } } bool CameraRenderer::Render( const CameraRenderRequest& request) { if (!request.IsValid() || m_pipeline == nullptr) { return false; } if (request.surface.GetRenderAreaWidth() == 0 || request.surface.GetRenderAreaHeight() == 0) { return false; } RenderSceneData sceneData = m_sceneExtractor.ExtractForCamera( *request.scene, *request.camera, request.surface.GetRenderAreaWidth(), request.surface.GetRenderAreaHeight()); if (!sceneData.HasCamera()) { return false; } sceneData.cameraData.clearFlags = request.clearFlags; const RenderPassContext passContext = { request.context, request.surface, sceneData }; bool preScenePassesInitialized = false; if (!InitializePassSequence( request.preScenePasses, request.context, preScenePassesInitialized)) { return false; } if (request.preScenePasses != nullptr && !request.preScenePasses->Execute(passContext)) { ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized); return false; } if (!m_pipeline->Render(request.context, request.surface, sceneData)) { ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized); return false; } bool postScenePassesInitialized = false; if (!InitializePassSequence( request.postScenePasses, request.context, postScenePassesInitialized)) { ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized); return false; } if (request.postScenePasses != nullptr && !request.postScenePasses->Execute(passContext)) { ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized); ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized); return false; } ShutdownPassSequence(request.postScenePasses, postScenePassesInitialized); ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized); return true; } } // namespace Rendering } // namespace XCEngine