#include "Rendering/Execution/SceneRenderer.h" #include "Components/CameraComponent.h" #include "Rendering/Caches/FullscreenPassSurfaceCache.h" #include "Rendering/Passes/BuiltinColorScalePostProcessPass.h" #include "Rendering/Planning/SceneRenderRequestUtils.h" namespace XCEngine { namespace Rendering { SceneRenderer::SceneRenderer() = default; SceneRenderer::SceneRenderer(std::unique_ptr pipeline) : m_cameraRenderer(std::move(pipeline)) { } SceneRenderer::SceneRenderer(std::shared_ptr pipelineAsset) : m_cameraRenderer(std::move(pipelineAsset)) { } SceneRenderer::~SceneRenderer() = default; void SceneRenderer::SetPipeline(std::unique_ptr pipeline) { m_cameraRenderer.SetPipeline(std::move(pipeline)); } void SceneRenderer::SetPipelineAsset(std::shared_ptr pipelineAsset) { m_cameraRenderer.SetPipelineAsset(std::move(pipelineAsset)); } std::vector SceneRenderer::BuildRenderRequests( const Components::Scene& scene, Components::CameraComponent* overrideCamera, const RenderContext& context, const RenderSurface& surface) { std::vector requests = m_requestPlanner.BuildRequests(scene, overrideCamera, context, surface); AttachCameraPostProcessRequests(context, requests); return requests; } bool SceneRenderer::Render(const CameraRenderRequest& request) { return m_cameraRenderer.Render(request); } bool SceneRenderer::Render(const std::vector& requests) { if (requests.empty()) { return false; } for (const CameraRenderRequest& request : requests) { if (!request.IsValid()) { return false; } } std::vector sortedRequests = requests; SceneRenderRequestUtils::SortCameraRenderRequests(sortedRequests); bool rendered = false; for (const CameraRenderRequest& request : sortedRequests) { if (!m_cameraRenderer.Render(request)) { return false; } rendered = true; } return rendered; } bool SceneRenderer::Render( const Components::Scene& scene, Components::CameraComponent* overrideCamera, const RenderContext& context, const RenderSurface& surface) { return Render(BuildRenderRequests(scene, overrideCamera, context, surface)); } void SceneRenderer::PrepareOwnedCameraPostProcessState(size_t requestCount) { m_ownedPostProcessSequences.clear(); m_ownedPostProcessSequences.resize(requestCount); if (m_ownedPostProcessSourceSurfaces.size() < requestCount) { m_ownedPostProcessSourceSurfaces.resize(requestCount); } for (size_t index = 0; index < requestCount; ++index) { if (m_ownedPostProcessSourceSurfaces[index] == nullptr) { m_ownedPostProcessSourceSurfaces[index] = std::make_unique(); } } } void SceneRenderer::AttachCameraPostProcessRequests( const RenderContext& context, std::vector& requests) { PrepareOwnedCameraPostProcessState(requests.size()); for (size_t index = 0; index < requests.size(); ++index) { CameraRenderRequest& request = requests[index]; if (request.camera == nullptr || !request.camera->IsColorScalePostProcessEnabled() || request.context.device == nullptr || !HasValidColorTarget(request.surface)) { continue; } const std::vector& colorAttachments = request.surface.GetColorAttachments(); const RHI::Format colorFormat = colorAttachments[0]->GetFormat(); if (colorFormat == RHI::Format::Unknown) { continue; } FullscreenPassSurfaceCache* sourceSurfaceCache = m_ownedPostProcessSourceSurfaces[index].get(); if (sourceSurfaceCache == nullptr || !sourceSurfaceCache->EnsureSurfaces( context, request.surface.GetWidth(), request.surface.GetHeight(), colorFormat, 1u)) { continue; } const FullscreenPassSurfaceCache::SurfaceEntry* sourceEntry = sourceSurfaceCache->GetSurfaceEntry(0u); if (sourceEntry == nullptr || sourceEntry->shaderResourceView == nullptr) { continue; } std::unique_ptr postProcessSequence = std::make_unique(); postProcessSequence->AddPass(std::make_unique( request.camera->GetColorScalePostProcessScale())); RenderSurface sourceSurface = sourceEntry->surface; sourceSurface.SetDepthAttachment(request.surface.GetDepthAttachment()); sourceSurface.SetColorStateBefore(RHI::ResourceStates::Common); sourceSurface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource); if (request.surface.HasCustomRenderArea()) { sourceSurface.SetRenderArea(request.surface.GetRenderArea()); } else { sourceSurface.ResetRenderArea(); } if (request.surface.HasClearColorOverride()) { sourceSurface.SetClearColorOverride(request.surface.GetClearColorOverride()); } request.postProcess.sourceSurface = sourceSurface; request.postProcess.sourceColorView = sourceEntry->shaderResourceView; request.postProcess.destinationSurface = request.surface; m_ownedPostProcessSequences[index] = std::move(postProcessSequence); request.postProcess.passes = m_ownedPostProcessSequences[index].get(); } } } // namespace Rendering } // namespace XCEngine