Fix scene selection outline mask path

This commit is contained in:
2026-04-09 05:16:04 +08:00
parent c48311eaaf
commit 2084412010
29 changed files with 1250 additions and 56 deletions

View File

@@ -1,5 +1,7 @@
#include "Passes/SceneViewportSelectionOutlinePass.h"
#include "Viewport/ViewportHostRenderTargets.h"
namespace XCEngine {
namespace Editor {
@@ -9,11 +11,11 @@ class SceneViewportSelectionOutlinePass final : public Rendering::RenderPass {
public:
SceneViewportSelectionOutlinePass(
SceneViewportSelectionOutlinePassRenderer& renderer,
RHI::RHIResourceView* objectIdTextureView,
ViewportRenderTargets* targets,
std::vector<uint64_t> selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style)
: m_renderer(renderer)
, m_objectIdTextureView(objectIdTextureView)
, m_targets(targets)
, m_selectedObjectIds(std::move(selectedObjectIds))
, m_style(style) {
}
@@ -26,14 +28,15 @@ public:
return m_renderer.Render(
context.renderContext,
context.surface,
m_objectIdTextureView,
context.sceneData,
*m_targets,
m_selectedObjectIds,
m_style);
}
private:
SceneViewportSelectionOutlinePassRenderer& m_renderer;
RHI::RHIResourceView* m_objectIdTextureView = nullptr;
ViewportRenderTargets* m_targets = nullptr;
std::vector<uint64_t> m_selectedObjectIds = {};
SceneViewportSelectionOutlineStyle m_style = {};
};
@@ -41,35 +44,51 @@ private:
} // namespace
SceneViewportSelectionOutlinePassRenderer::SceneViewportSelectionOutlinePassRenderer()
: m_outlinePass() {
: m_selectionMaskPass()
, m_outlinePass() {
}
void SceneViewportSelectionOutlinePassRenderer::Shutdown() {
m_selectionMaskPass.Shutdown();
m_outlinePass.Shutdown();
}
bool SceneViewportSelectionOutlinePassRenderer::Render(
const Rendering::RenderContext& renderContext,
const Rendering::RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView,
const Rendering::RenderSceneData& sceneData,
ViewportRenderTargets& targets,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style) {
Rendering::RenderSurface selectionMaskSurface = BuildViewportSelectionMaskSurface(targets);
selectionMaskSurface.SetRenderArea(surface.GetRenderArea());
if (!m_selectionMaskPass.Render(
renderContext,
selectionMaskSurface,
sceneData,
selectedObjectIds)) {
return false;
}
targets.selectionMaskState = RHI::ResourceStates::PixelShaderResource;
return m_outlinePass.Render(
renderContext,
surface,
objectIdTextureView,
selectedObjectIds,
targets.selectionMaskShaderView,
targets.depthShaderView,
ToBuiltinSceneViewportSelectionOutlineStyle(style));
}
std::unique_ptr<Rendering::RenderPass> CreateSceneViewportSelectionOutlinePass(
SceneViewportSelectionOutlinePassRenderer& renderer,
RHI::RHIResourceView* objectIdTextureView,
ViewportRenderTargets* targets,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style) {
return std::make_unique<SceneViewportSelectionOutlinePass>(
renderer,
objectIdTextureView,
targets,
selectedObjectIds,
style);
}

View File

@@ -2,7 +2,8 @@
#include "Viewport/SceneViewportPassSpecs.h"
#include <XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h>
#include <XCEngine/Rendering/Passes/BuiltinSelectionMaskPass.h>
#include <XCEngine/Rendering/Passes/BuiltinSelectionOutlinePass.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderPass.h>
#include <XCEngine/Rendering/RenderSurface.h>
@@ -14,6 +15,8 @@
namespace XCEngine {
namespace Editor {
struct ViewportRenderTargets;
class SceneViewportSelectionOutlinePassRenderer {
public:
SceneViewportSelectionOutlinePassRenderer();
@@ -24,17 +27,19 @@ public:
bool Render(
const Rendering::RenderContext& renderContext,
const Rendering::RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView,
const Rendering::RenderSceneData& sceneData,
ViewportRenderTargets& targets,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style);
private:
Rendering::Passes::BuiltinObjectIdOutlinePass m_outlinePass;
Rendering::Passes::BuiltinSelectionMaskPass m_selectionMaskPass;
Rendering::Passes::BuiltinSelectionOutlinePass m_outlinePass;
};
std::unique_ptr<Rendering::RenderPass> CreateSceneViewportSelectionOutlinePass(
SceneViewportSelectionOutlinePassRenderer& renderer,
RHI::RHIResourceView* objectIdTextureView,
ViewportRenderTargets* targets,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportSelectionOutlineStyle& style);

View File

@@ -3,7 +3,7 @@
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Rendering/Passes/BuiltinInfiniteGridPass.h>
#include <XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h>
#include <XCEngine/Rendering/Passes/BuiltinSelectionOutlinePass.h>
namespace XCEngine {
namespace Editor {
@@ -41,9 +41,9 @@ struct SceneViewportSelectionOutlineStyle {
bool debugSelectionMask = false;
};
inline Rendering::Passes::ObjectIdOutlineStyle ToBuiltinSceneViewportSelectionOutlineStyle(
inline Rendering::Passes::SelectionOutlineStyle ToBuiltinSceneViewportSelectionOutlineStyle(
const SceneViewportSelectionOutlineStyle& style) {
Rendering::Passes::ObjectIdOutlineStyle builtinStyle = {};
Rendering::Passes::SelectionOutlineStyle builtinStyle = {};
builtinStyle.outlineColor = style.outlineColor;
builtinStyle.outlineWidthPixels = style.outlineWidthPixels;
builtinStyle.debugSelectionMask = style.debugSelectionMask;

View File

@@ -10,7 +10,7 @@ void SceneViewportRenderPassBundle::Shutdown() {
}
SceneViewportRenderPlanBuildResult SceneViewportRenderPassBundle::BuildRenderPlan(
const ViewportRenderTargets& targets,
ViewportRenderTargets& targets,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportOverlayFrameData& editorOverlayFrameData,
@@ -24,12 +24,12 @@ SceneViewportRenderPlanBuildResult SceneViewportRenderPassBundle::BuildRenderPla
return CreateSceneViewportGridPass(m_gridRenderer, data);
},
[this](
RHI::RHIResourceView* objectIdTextureView,
ViewportRenderTargets* outlineTargets,
const std::vector<uint64_t>& selectionIds,
const SceneViewportSelectionOutlineStyle& style) {
return CreateSceneViewportSelectionOutlinePass(
m_selectionOutlineRenderer,
objectIdTextureView,
outlineTargets,
selectionIds,
style);
},

View File

@@ -15,7 +15,7 @@ public:
void Shutdown();
SceneViewportRenderPlanBuildResult BuildRenderPlan(
const ViewportRenderTargets& targets,
ViewportRenderTargets& targets,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportOverlayFrameData& editorOverlayFrameData,

View File

@@ -37,7 +37,7 @@ using SceneViewportOverlayPassFactory =
using SceneViewportGridPassFactory =
std::function<std::unique_ptr<Rendering::RenderPass>(const SceneViewportGridPassData&)>;
using SceneViewportSelectionOutlinePassFactory = std::function<std::unique_ptr<Rendering::RenderPass>(
RHI::RHIResourceView*,
ViewportRenderTargets*,
const std::vector<uint64_t>&,
const SceneViewportSelectionOutlineStyle&)>;
@@ -47,7 +47,7 @@ struct SceneViewportRenderPlanBuildResult {
};
inline SceneViewportRenderPlanBuildResult BuildSceneViewportRenderPlan(
const ViewportRenderTargets& targets,
ViewportRenderTargets& targets,
const SceneViewportOverlayData& overlay,
const std::vector<uint64_t>& selectedObjectIds,
const SceneViewportOverlayFrameData& editorOverlayFrameData,
@@ -69,18 +69,21 @@ inline SceneViewportRenderPlanBuildResult BuildSceneViewportRenderPlan(
}
if (!selectedObjectIds.empty()) {
if (targets.objectIdShaderView != nullptr &&
if (targets.selectionMaskView != nullptr &&
targets.selectionMaskShaderView != nullptr &&
targets.depthView != nullptr &&
targets.depthShaderView != nullptr &&
selectionOutlinePassFactory != nullptr) {
std::unique_ptr<Rendering::RenderPass> selectionOutlinePass =
selectionOutlinePassFactory(
targets.objectIdShaderView,
&targets,
selectedObjectIds,
BuildSceneViewportSelectionOutlineStyle(debugSelectionMask));
if (selectionOutlinePass != nullptr) {
result.plan.postScenePasses.AddPass(std::move(selectionOutlinePass));
}
} else if (!debugSelectionMask) {
result.warningStatusText = "Scene object id shader view is unavailable";
result.warningStatusText = "Scene selection outline resources are unavailable";
}
}

View File

@@ -152,7 +152,7 @@ inline void ApplySceneViewportRenderRequestSetup(
request.postScenePasses = postPasses;
}
if (targets.objectIdView == nullptr) {
if (targets.objectIdView == nullptr || targets.objectIdDepthView == nullptr) {
return;
}
@@ -165,6 +165,7 @@ inline void MarkSceneViewportRenderSuccess(
const Rendering::CameraRenderRequest& request) {
targets.colorState = RHI::ResourceStates::PixelShaderResource;
targets.objectIdState = RHI::ResourceStates::PixelShaderResource;
targets.selectionMaskState = RHI::ResourceStates::PixelShaderResource;
targets.hasValidObjectIdFrame = request.objectId.IsRequested();
}

View File

@@ -18,14 +18,21 @@ struct ViewportRenderTargets {
RHI::RHIResourceView* colorView = nullptr;
RHI::RHITexture* depthTexture = nullptr;
RHI::RHIResourceView* depthView = nullptr;
RHI::RHIResourceView* depthShaderView = nullptr;
RHI::RHITexture* objectIdTexture = nullptr;
RHI::RHITexture* objectIdDepthTexture = nullptr;
RHI::RHIResourceView* objectIdDepthView = nullptr;
RHI::RHIResourceView* objectIdView = nullptr;
RHI::RHIResourceView* objectIdShaderView = nullptr;
RHI::RHITexture* selectionMaskTexture = nullptr;
RHI::RHIResourceView* selectionMaskView = nullptr;
RHI::RHIResourceView* selectionMaskShaderView = nullptr;
D3D12_CPU_DESCRIPTOR_HANDLE imguiCpuHandle = {};
D3D12_GPU_DESCRIPTOR_HANDLE imguiGpuHandle = {};
::XCEngine::UI::UITextureHandle textureHandle = {};
RHI::ResourceStates colorState = RHI::ResourceStates::Common;
RHI::ResourceStates objectIdState = RHI::ResourceStates::Common;
RHI::ResourceStates selectionMaskState = RHI::ResourceStates::Common;
bool hasValidObjectIdFrame = false;
};
@@ -44,9 +51,15 @@ inline ViewportHostResourceReuseQuery BuildViewportRenderTargetsReuseQuery(
query.resources.hasColorView = targets.colorView != nullptr;
query.resources.hasDepthTexture = targets.depthTexture != nullptr;
query.resources.hasDepthView = targets.depthView != nullptr;
query.resources.hasDepthShaderView = targets.depthShaderView != nullptr;
query.resources.hasObjectIdTexture = targets.objectIdTexture != nullptr;
query.resources.hasObjectIdDepthTexture = targets.objectIdDepthTexture != nullptr;
query.resources.hasObjectIdDepthView = targets.objectIdDepthView != nullptr;
query.resources.hasObjectIdView = targets.objectIdView != nullptr;
query.resources.hasObjectIdShaderView = targets.objectIdShaderView != nullptr;
query.resources.hasSelectionMaskTexture = targets.selectionMaskTexture != nullptr;
query.resources.hasSelectionMaskView = targets.selectionMaskView != nullptr;
query.resources.hasSelectionMaskShaderView = targets.selectionMaskShaderView != nullptr;
query.resources.hasTextureDescriptor = targets.textureHandle.IsValid();
return query;
}
@@ -65,10 +78,19 @@ inline Rendering::RenderSurface BuildViewportObjectIdSurface(const ViewportRende
targets.width,
targets.height,
targets.objectIdView,
targets.depthView,
targets.objectIdDepthView,
targets.objectIdState);
}
inline Rendering::RenderSurface BuildViewportSelectionMaskSurface(const ViewportRenderTargets& targets) {
return BuildViewportRenderSurface(
targets.width,
targets.height,
targets.selectionMaskView,
targets.depthView,
targets.selectionMaskState);
}
namespace Detail {
template <typename ResourceType>
@@ -111,7 +133,17 @@ inline bool CreateViewportDepthResources(
const RHI::ResourceViewDesc depthViewDesc =
BuildViewportTextureViewDesc(RHI::Format::D24_UNorm_S8_UInt);
targets.depthView = device->CreateDepthStencilView(targets.depthTexture, depthViewDesc);
return targets.depthView != nullptr;
if (targets.depthView == nullptr) {
return false;
}
RHI::ResourceViewDesc depthShaderViewDesc = {};
depthShaderViewDesc.dimension = RHI::ResourceViewDimension::Texture2D;
depthShaderViewDesc.mipLevel = 0;
targets.depthShaderView = device->CreateShaderResourceView(
targets.depthTexture,
depthShaderViewDesc);
return targets.depthShaderView != nullptr;
}
inline bool CreateViewportObjectIdResources(
@@ -136,7 +168,48 @@ inline bool CreateViewportObjectIdResources(
targets.objectIdShaderView = device->CreateShaderResourceView(
targets.objectIdTexture,
objectIdViewDesc);
return targets.objectIdShaderView != nullptr;
if (targets.objectIdShaderView == nullptr) {
return false;
}
const RHI::TextureDesc objectIdDepthDesc =
BuildViewportTextureDesc(targets.width, targets.height, RHI::Format::D24_UNorm_S8_UInt);
targets.objectIdDepthTexture = device->CreateTexture(objectIdDepthDesc);
if (targets.objectIdDepthTexture == nullptr) {
return false;
}
const RHI::ResourceViewDesc objectIdDepthViewDesc =
BuildViewportTextureViewDesc(RHI::Format::D24_UNorm_S8_UInt);
targets.objectIdDepthView = device->CreateDepthStencilView(
targets.objectIdDepthTexture,
objectIdDepthViewDesc);
return targets.objectIdDepthView != nullptr;
}
inline bool CreateViewportSelectionMaskResources(
RHI::RHIDevice* device,
ViewportRenderTargets& targets) {
const RHI::TextureDesc selectionMaskDesc =
BuildViewportTextureDesc(targets.width, targets.height, RHI::Format::R8G8B8A8_UNorm);
targets.selectionMaskTexture = device->CreateTexture(selectionMaskDesc);
if (targets.selectionMaskTexture == nullptr) {
return false;
}
const RHI::ResourceViewDesc selectionMaskViewDesc =
BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm);
targets.selectionMaskView = device->CreateRenderTargetView(
targets.selectionMaskTexture,
selectionMaskViewDesc);
if (targets.selectionMaskView == nullptr) {
return false;
}
targets.selectionMaskShaderView = device->CreateShaderResourceView(
targets.selectionMaskTexture,
selectionMaskViewDesc);
return targets.selectionMaskShaderView != nullptr;
}
inline bool CreateViewportTextureDescriptor(
@@ -170,7 +243,13 @@ inline void DestroyViewportRenderTargets(
Detail::ShutdownAndDelete(targets.objectIdView);
Detail::ShutdownAndDelete(targets.objectIdShaderView);
Detail::ShutdownAndDelete(targets.objectIdDepthView);
Detail::ShutdownAndDelete(targets.objectIdDepthTexture);
Detail::ShutdownAndDelete(targets.objectIdTexture);
Detail::ShutdownAndDelete(targets.selectionMaskView);
Detail::ShutdownAndDelete(targets.selectionMaskShaderView);
Detail::ShutdownAndDelete(targets.selectionMaskTexture);
Detail::ShutdownAndDelete(targets.depthShaderView);
Detail::ShutdownAndDelete(targets.depthView);
Detail::ShutdownAndDelete(targets.depthTexture);
Detail::ShutdownAndDelete(targets.colorView);
@@ -183,6 +262,7 @@ inline void DestroyViewportRenderTargets(
targets.textureHandle = {};
targets.colorState = RHI::ResourceStates::Common;
targets.objectIdState = RHI::ResourceStates::Common;
targets.selectionMaskState = RHI::ResourceStates::Common;
targets.hasValidObjectIdFrame = false;
}
@@ -204,7 +284,8 @@ inline bool CreateViewportRenderTargets(
if (!Detail::CreateViewportColorResources(device, targets) ||
!Detail::CreateViewportDepthResources(device, targets) ||
(ViewportRequiresObjectIdResources(kind) &&
!Detail::CreateViewportObjectIdResources(device, targets)) ||
(!Detail::CreateViewportObjectIdResources(device, targets) ||
!Detail::CreateViewportSelectionMaskResources(device, targets))) ||
!Detail::CreateViewportTextureDescriptor(backend, device, targets)) {
DestroyViewportRenderTargets(backend, targets);
return false;
@@ -212,6 +293,7 @@ inline bool CreateViewportRenderTargets(
targets.colorState = RHI::ResourceStates::Common;
targets.objectIdState = RHI::ResourceStates::Common;
targets.selectionMaskState = RHI::ResourceStates::Common;
targets.hasValidObjectIdFrame = false;
return true;
}

View File

@@ -19,9 +19,15 @@ struct ViewportHostResourcePresence {
bool hasColorView = false;
bool hasDepthTexture = false;
bool hasDepthView = false;
bool hasDepthShaderView = false;
bool hasObjectIdTexture = false;
bool hasObjectIdDepthTexture = false;
bool hasObjectIdDepthView = false;
bool hasObjectIdView = false;
bool hasObjectIdShaderView = false;
bool hasSelectionMaskTexture = false;
bool hasSelectionMaskView = false;
bool hasSelectionMaskShaderView = false;
bool hasTextureDescriptor = false;
};
@@ -70,8 +76,14 @@ inline bool CanReuseViewportResources(const ViewportHostResourceReuseQuery& quer
}
return query.resources.hasObjectIdTexture &&
query.resources.hasObjectIdDepthTexture &&
query.resources.hasObjectIdDepthView &&
query.resources.hasObjectIdView &&
query.resources.hasObjectIdShaderView;
query.resources.hasObjectIdShaderView &&
query.resources.hasDepthShaderView &&
query.resources.hasSelectionMaskTexture &&
query.resources.hasSelectionMaskView &&
query.resources.hasSelectionMaskShaderView;
}
inline RHI::TextureDesc BuildViewportTextureDesc(