refactor: move scene view post passes into rendering

This commit is contained in:
2026-04-02 04:42:35 +08:00
parent c080890c9d
commit 0d3851204f
6 changed files with 383 additions and 198 deletions

View File

@@ -13,13 +13,13 @@
#include <XCEngine/Components/CameraComponent.h>
#include <XCEngine/Components/GameObject.h>
#include <XCEngine/Core/Asset/ResourceManager.h>
#include <XCEngine/RHI/RHIDevice.h>
#include <XCEngine/RHI/RHIEnums.h>
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/Rendering/Passes/BuiltinInfiniteGridPass.h>
#include <XCEngine/Rendering/Passes/BuiltinSceneViewPostPassPlan.h>
#include <XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h>
#include <XCEngine/Rendering/Passes/BuiltinSceneViewPostPassSequenceBuilder.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderSurface.h>
#include <XCEngine/Rendering/SceneRenderer.h>
@@ -27,10 +27,8 @@
#include <array>
#include <cstdint>
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include <vector>
namespace XCEngine {
@@ -40,35 +38,6 @@ namespace {
constexpr bool kDebugSceneSelectionMask = false;
class LambdaRenderPass final : public Rendering::RenderPass {
public:
using ExecuteCallback = std::function<bool(const Rendering::RenderPassContext&)>;
LambdaRenderPass(std::string name, ExecuteCallback executeCallback)
: m_name(std::move(name))
, m_executeCallback(std::move(executeCallback)) {
}
const char* GetName() const override {
return m_name.c_str();
}
bool Execute(const Rendering::RenderPassContext& context) override {
return m_executeCallback != nullptr && m_executeCallback(context);
}
private:
std::string m_name;
ExecuteCallback m_executeCallback;
};
template <typename Callback>
std::unique_ptr<Rendering::RenderPass> MakeLambdaRenderPass(const char* name, Callback&& callback) {
return std::make_unique<LambdaRenderPass>(
name,
LambdaRenderPass::ExecuteCallback(std::forward<Callback>(callback)));
}
Rendering::Passes::InfiniteGridPassData BuildInfiniteGridPassData(
const SceneViewportOverlayData& overlay) {
Rendering::Passes::InfiniteGridPassData data = {};
@@ -123,8 +92,7 @@ public:
m_sceneViewLastRenderContext = {};
m_device = nullptr;
m_backend = nullptr;
m_sceneGridPass.Shutdown();
m_sceneSelectionOutlinePass.Shutdown();
m_sceneViewPostPassBuilder.Shutdown();
m_sceneRenderer.reset();
}
@@ -444,176 +412,32 @@ private:
policy.clearColor.a);
}
void AddSceneColorToRenderTargetPass(
ViewportEntry& entry,
Rendering::RenderPassSequence& outPostPasses) {
outPostPasses.AddPass(MakeLambdaRenderPass(
"SceneColorToRenderTarget",
[&entry](const Rendering::RenderPassContext& context) {
context.renderContext.commandList->TransitionBarrier(
entry.renderTargets.colorView,
context.surface.GetColorStateAfter(),
RHI::ResourceStates::RenderTarget);
entry.renderTargets.colorState = RHI::ResourceStates::RenderTarget;
return true;
}));
}
void AddSceneInfiniteGridPass(
ViewportEntry& entry,
const SceneViewportOverlayData& overlay,
Rendering::RenderPassSequence& outPostPasses) {
outPostPasses.AddPass(MakeLambdaRenderPass(
"SceneInfiniteGrid",
[this, overlay, &entry](const Rendering::RenderPassContext& context) {
const bool rendered = m_sceneGridPass.Render(
context.renderContext,
context.surface,
BuildInfiniteGridPassData(overlay));
if (!rendered) {
SetViewportStatusIfEmpty(entry.statusText, "Scene grid pass failed");
}
return rendered;
}));
}
void AddSceneSelectionOutlinePass(
ViewportEntry& entry,
const std::vector<uint64_t>& selectedObjectIds,
Rendering::RenderPassSequence& outPostPasses) {
outPostPasses.AddPass(MakeLambdaRenderPass(
"SceneSelectionOutline",
[this, &entry, selectedObjectIds](const Rendering::RenderPassContext& context) {
const bool rendered = m_sceneSelectionOutlinePass.Render(
context.renderContext,
context.surface,
entry.renderTargets.objectIdShaderView,
selectedObjectIds,
Rendering::Passes::ObjectIdOutlineStyle{
Math::Color(1.0f, 0.4f, 0.0f, 1.0f),
2.0f,
false
});
if (!rendered) {
SetViewportStatusIfEmpty(entry.statusText, "Scene selection outline pass failed");
}
return rendered;
}));
}
void AddSceneColorToShaderResourcePass(
ViewportEntry& entry,
Rendering::RenderPassSequence& outPostPasses) {
outPostPasses.AddPass(MakeLambdaRenderPass(
"SceneColorToShaderResource",
[&entry](const Rendering::RenderPassContext& context) {
context.renderContext.commandList->TransitionBarrier(
entry.renderTargets.colorView,
RHI::ResourceStates::RenderTarget,
context.surface.GetColorStateAfter());
entry.renderTargets.colorState = context.surface.GetColorStateAfter();
return true;
}));
}
void AddSceneSelectionMaskDebugPass(
ViewportEntry& entry,
const std::vector<uint64_t>& selectedObjectIds,
Rendering::RenderPassSequence& outPostPasses) {
outPostPasses.AddPass(MakeLambdaRenderPass(
"SceneSelectionMaskDebug",
[this, &entry, selectedObjectIds](
const Rendering::RenderPassContext& context) {
const float debugClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
RHI::RHIResourceView* colorView = entry.renderTargets.colorView;
context.renderContext.commandList->SetRenderTargets(
1,
&colorView,
entry.renderTargets.depthView);
context.renderContext.commandList->ClearRenderTarget(colorView, debugClearColor);
const bool rendered = m_sceneSelectionOutlinePass.Render(
context.renderContext,
context.surface,
entry.renderTargets.objectIdShaderView,
selectedObjectIds,
Rendering::Passes::ObjectIdOutlineStyle{
Math::Color(1.0f, 0.4f, 0.0f, 1.0f),
2.0f,
true
});
if (!rendered) {
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask debug pass failed");
}
return rendered;
}));
}
void AddSceneViewPostPassStep(
Rendering::Passes::BuiltinSceneViewPostPassStep step,
ViewportEntry& entry,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
Rendering::RenderPassSequence& outPostPasses) {
switch (step) {
case Rendering::Passes::BuiltinSceneViewPostPassStep::ColorToRenderTarget:
AddSceneColorToRenderTargetPass(entry, outPostPasses);
break;
case Rendering::Passes::BuiltinSceneViewPostPassStep::InfiniteGrid:
AddSceneInfiniteGridPass(entry, overlay, outPostPasses);
break;
case Rendering::Passes::BuiltinSceneViewPostPassStep::SelectionOutline:
AddSceneSelectionOutlinePass(entry, selectedObjectIds, outPostPasses);
break;
case Rendering::Passes::BuiltinSceneViewPostPassStep::ColorToShaderResource:
AddSceneColorToShaderResourcePass(entry, outPostPasses);
break;
case Rendering::Passes::BuiltinSceneViewPostPassStep::SelectionMaskDebug:
AddSceneSelectionMaskDebugPass(
entry,
selectedObjectIds,
outPostPasses);
break;
default:
break;
}
}
bool BuildSceneViewPostPassSequence(
ViewportEntry& entry,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
Rendering::RenderPassSequence& outPostPasses) {
const bool hasSelection = !selectedObjectIds.empty();
const bool hasObjectIdShaderView = entry.renderTargets.objectIdShaderView != nullptr;
Rendering::Passes::ObjectIdOutlineStyle outlineStyle = {};
outlineStyle.outlineColor = Math::Color(1.0f, 0.4f, 0.0f, 1.0f);
outlineStyle.outlineWidthPixels = 2.0f;
outlineStyle.debugSelectionMask = kDebugSceneSelectionMask;
if (hasSelection &&
!kDebugSceneSelectionMask &&
!hasObjectIdShaderView) {
const Rendering::Passes::BuiltinSceneViewPostPassSequenceBuildResult result =
m_sceneViewPostPassBuilder.Build(
{
BuildInfiniteGridPassData(overlay),
entry.renderTargets.objectIdShaderView,
selectedObjectIds,
outlineStyle
},
outPostPasses);
if (result.missingObjectIdTextureViewForSelection &&
!kDebugSceneSelectionMask) {
SetViewportStatusIfEmpty(entry.statusText, "Scene object id shader view is unavailable");
}
const Rendering::Passes::BuiltinSceneViewPostPassPlan plan =
Rendering::Passes::BuildBuiltinSceneViewPostPassPlan({
overlay.valid,
hasSelection,
kDebugSceneSelectionMask,
hasObjectIdShaderView
});
if (!plan.valid) {
return false;
}
for (const Rendering::Passes::BuiltinSceneViewPostPassStep step : plan.steps) {
AddSceneViewPostPassStep(
step,
entry,
overlay,
selectedObjectIds,
outPostPasses);
}
return true;
return result.valid;
}
void BuildSceneViewportRenderState(
@@ -693,6 +517,10 @@ private:
}
MarkSceneViewportRenderSuccess(entry.renderTargets, requests[0]);
const Core::uint32 pendingAsyncLoads = Resources::ResourceManager::Get().GetAsyncPendingCount();
if (pendingAsyncLoads > 0) {
entry.statusText = "Loading scene assets... (" + std::to_string(pendingAsyncLoads) + ")";
}
return true;
}
@@ -829,8 +657,7 @@ private:
Rendering::RenderContext m_sceneViewLastRenderContext = {};
std::array<ViewportEntry, 2> m_entries = {};
SceneViewCameraState m_sceneViewCamera;
Rendering::Passes::BuiltinInfiniteGridPass m_sceneGridPass;
Rendering::Passes::BuiltinObjectIdOutlinePass m_sceneSelectionOutlinePass;
Rendering::Passes::BuiltinSceneViewPostPassSequenceBuilder m_sceneViewPostPassBuilder;
};
} // namespace Editor