Unify object id rendering with render passes

This commit is contained in:
2026-04-05 18:20:19 +08:00
parent a600e73fb2
commit 8ced88e847
7 changed files with 72 additions and 64 deletions

View File

@@ -440,7 +440,6 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/RenderResourceCache.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/CameraRenderer.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/ObjectIdEncoding.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/ObjectIdPass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestPlanner.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderRequestUtils.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderer.h

View File

@@ -1,7 +1,7 @@
#pragma once
#include <XCEngine/Rendering/CameraRenderRequest.h>
#include <XCEngine/Rendering/ObjectIdPass.h>
#include <XCEngine/Rendering/RenderPass.h>
#include <XCEngine/Rendering/RenderPipeline.h>
#include <memory>
@@ -25,19 +25,19 @@ public:
explicit CameraRenderer(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
CameraRenderer(
std::unique_ptr<RenderPipeline> pipeline,
std::unique_ptr<ObjectIdPass> objectIdPass,
std::unique_ptr<RenderPass> objectIdPass,
std::unique_ptr<RenderPass> depthOnlyPass = nullptr,
std::unique_ptr<RenderPass> shadowCasterPass = nullptr);
~CameraRenderer();
void SetPipeline(std::unique_ptr<RenderPipeline> pipeline);
void SetPipelineAsset(std::shared_ptr<const RenderPipelineAsset> pipelineAsset);
void SetObjectIdPass(std::unique_ptr<ObjectIdPass> objectIdPass);
void SetObjectIdPass(std::unique_ptr<RenderPass> objectIdPass);
void SetDepthOnlyPass(std::unique_ptr<RenderPass> depthOnlyPass);
void SetShadowCasterPass(std::unique_ptr<RenderPass> shadowCasterPass);
RenderPipeline* GetPipeline() const { return m_pipeline.get(); }
const RenderPipelineAsset* GetPipelineAsset() const { return m_pipelineAsset.get(); }
ObjectIdPass* GetObjectIdPass() const { return m_objectIdPass.get(); }
RenderPass* GetObjectIdPass() const { return m_objectIdPass.get(); }
RenderPass* GetDepthOnlyPass() const { return m_depthOnlyPass.get(); }
RenderPass* GetShadowCasterPass() const { return m_shadowCasterPass.get(); }
@@ -54,7 +54,7 @@ private:
RenderSceneExtractor m_sceneExtractor;
std::shared_ptr<const RenderPipelineAsset> m_pipelineAsset;
std::unique_ptr<RenderPipeline> m_pipeline;
std::unique_ptr<ObjectIdPass> m_objectIdPass;
std::unique_ptr<RenderPass> m_objectIdPass;
std::unique_ptr<RenderPass> m_depthOnlyPass;
std::unique_ptr<RenderPass> m_shadowCasterPass;
std::unique_ptr<DirectionalShadowSurfaceResources> m_directionalShadowSurface;

View File

@@ -1,24 +0,0 @@
#pragma once
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderSceneExtractor.h>
#include <XCEngine/Rendering/RenderSurface.h>
namespace XCEngine {
namespace Rendering {
class ObjectIdPass {
public:
virtual ~ObjectIdPass() = default;
virtual bool Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) = 0;
virtual void Shutdown() {
}
};
} // namespace Rendering
} // namespace XCEngine

View File

@@ -1,7 +1,7 @@
#pragma once
#include <XCEngine/Rendering/ObjectIdPass.h>
#include <XCEngine/Rendering/ObjectIdEncoding.h>
#include <XCEngine/Rendering/RenderPass.h>
#include <XCEngine/Rendering/RenderMaterialUtility.h>
#include <XCEngine/Rendering/RenderResourceCache.h>
#include <XCEngine/Core/Asset/ResourceHandle.h>
@@ -14,16 +14,16 @@ namespace XCEngine {
namespace Rendering {
namespace Passes {
class BuiltinObjectIdPass final : public ObjectIdPass {
class BuiltinObjectIdPass final : public RenderPass {
public:
~BuiltinObjectIdPass() override;
static RHI::InputLayoutDesc BuildInputLayout();
bool Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) override;
const char* GetName() const override;
bool Initialize(const RenderContext& context) override;
bool Execute(const RenderPassContext& context) override;
void Shutdown() override;

View File

@@ -167,6 +167,27 @@ bool ExecuteScenePassRequest(
return pass->Execute(passContext);
}
bool ExecuteStandalonePass(
RenderPass* pass,
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) {
if (pass == nullptr) {
return false;
}
if (!InitializeStandalonePass(pass, context)) {
return false;
}
const RenderPassContext passContext = {
context,
surface,
sceneData
};
return pass->Execute(passContext);
}
RenderDirectionalShadowData BuildDirectionalShadowData(
const DirectionalShadowRenderPlan& plan,
RHI::RHIResourceView* shadowMapView) {
@@ -202,7 +223,7 @@ CameraRenderer::CameraRenderer(std::unique_ptr<RenderPipeline> pipeline)
CameraRenderer::CameraRenderer(
std::unique_ptr<RenderPipeline> pipeline,
std::unique_ptr<ObjectIdPass> objectIdPass,
std::unique_ptr<RenderPass> objectIdPass,
std::unique_ptr<RenderPass> depthOnlyPass,
std::unique_ptr<RenderPass> shadowCasterPass)
: m_pipelineAsset(nullptr)
@@ -254,7 +275,7 @@ void CameraRenderer::SetPipelineAsset(std::shared_ptr<const RenderPipelineAsset>
ResetPipeline(CreatePipelineFromAsset(m_pipelineAsset));
}
void CameraRenderer::SetObjectIdPass(std::unique_ptr<ObjectIdPass> objectIdPass) {
void CameraRenderer::SetObjectIdPass(std::unique_ptr<RenderPass> objectIdPass) {
if (m_objectIdPass != nullptr) {
m_objectIdPass->Shutdown();
}
@@ -471,8 +492,11 @@ bool CameraRenderer::Render(
}
if (request.objectId.IsRequested() &&
(m_objectIdPass == nullptr ||
!m_objectIdPass->Render(request.context, request.objectId.surface, sceneData))) {
!ExecuteStandalonePass(
m_objectIdPass.get(),
request.context,
request.objectId.surface,
sceneData)) {
ShutdownPassSequence(request.preScenePasses, preScenePassesInitialized);
return false;
}

View File

@@ -8,6 +8,8 @@
#include "RHI/RHIPipelineState.h"
#include "Rendering/Detail/ShaderVariantUtils.h"
#include "Rendering/RenderMaterialUtility.h"
#include "Rendering/RenderSceneExtractor.h"
#include "Rendering/RenderSurface.h"
#include "Resources/BuiltinResources.h"
#include "Resources/Mesh/Mesh.h"
@@ -95,6 +97,10 @@ BuiltinObjectIdPass::~BuiltinObjectIdPass() {
Shutdown();
}
const char* BuiltinObjectIdPass::GetName() const {
return "BuiltinObjectIdPass";
}
RHI::InputLayoutDesc BuiltinObjectIdPass::BuildInputLayout() {
RHI::InputLayoutDesc inputLayout = {};
@@ -125,39 +131,42 @@ RHI::InputLayoutDesc BuiltinObjectIdPass::BuildInputLayout() {
return inputLayout;
}
bool BuiltinObjectIdPass::Render(
const RenderContext& context,
const RenderSurface& surface,
const RenderSceneData& sceneData) {
if (!context.IsValid()) {
bool BuiltinObjectIdPass::Initialize(const RenderContext& context) {
return EnsureInitialized(context);
}
bool BuiltinObjectIdPass::Execute(const RenderPassContext& context) {
if (!context.renderContext.IsValid()) {
return false;
}
const std::vector<RHI::RHIResourceView*>& colorAttachments = surface.GetColorAttachments();
if (colorAttachments.empty() || colorAttachments[0] == nullptr || surface.GetDepthAttachment() == nullptr) {
const std::vector<RHI::RHIResourceView*>& colorAttachments = context.surface.GetColorAttachments();
if (colorAttachments.empty() ||
colorAttachments[0] == nullptr ||
context.surface.GetDepthAttachment() == nullptr) {
return false;
}
const Math::RectInt renderArea = surface.GetRenderArea();
const Math::RectInt renderArea = context.surface.GetRenderArea();
if (renderArea.width <= 0 || renderArea.height <= 0) {
return false;
}
if (!EnsureInitialized(context)) {
if (!EnsureInitialized(context.renderContext)) {
return false;
}
RHI::RHICommandList* commandList = context.commandList;
RHI::RHICommandList* commandList = context.renderContext.commandList;
RHI::RHIResourceView* renderTarget = colorAttachments[0];
if (surface.IsAutoTransitionEnabled()) {
if (context.surface.IsAutoTransitionEnabled()) {
commandList->TransitionBarrier(
renderTarget,
surface.GetColorStateBefore(),
context.surface.GetColorStateBefore(),
RHI::ResourceStates::RenderTarget);
}
commandList->SetRenderTargets(1, &renderTarget, surface.GetDepthAttachment());
commandList->SetRenderTargets(1, &renderTarget, context.surface.GetDepthAttachment());
const RHI::Viewport viewport = {
static_cast<float>(renderArea.x),
@@ -179,21 +188,21 @@ bool BuiltinObjectIdPass::Render(
commandList->SetViewport(viewport);
commandList->SetScissorRect(scissorRect);
commandList->ClearRenderTarget(renderTarget, clearColor, 1, clearRects);
commandList->ClearDepthStencil(surface.GetDepthAttachment(), 1.0f, 0, 1, clearRects);
commandList->ClearDepthStencil(context.surface.GetDepthAttachment(), 1.0f, 0, 1, clearRects);
commandList->SetPrimitiveTopology(RHI::PrimitiveTopology::TriangleList);
commandList->SetPipelineState(m_pipelineState);
for (const VisibleRenderItem& visibleItem : sceneData.visibleItems) {
DrawVisibleItem(context, sceneData, visibleItem);
for (const VisibleRenderItem& visibleItem : context.sceneData.visibleItems) {
DrawVisibleItem(context.renderContext, context.sceneData, visibleItem);
}
commandList->EndRenderPass();
if (surface.IsAutoTransitionEnabled()) {
if (context.surface.IsAutoTransitionEnabled()) {
commandList->TransitionBarrier(
renderTarget,
RHI::ResourceStates::RenderTarget,
surface.GetColorStateAfter());
context.surface.GetColorStateAfter());
}
return true;