refactor: drive scene view outline from object id
This commit is contained in:
@@ -8,9 +8,7 @@
|
||||
#include "SceneViewportCameraController.h"
|
||||
#include "SceneViewportInfiniteGridPass.h"
|
||||
#include "SceneViewportPostPassPlan.h"
|
||||
#include "SceneViewportSelectionMaskPass.h"
|
||||
#include "SceneViewportSelectionOutlinePass.h"
|
||||
#include "SceneViewportSelectionUtils.h"
|
||||
#include "UI/ImGuiBackendBridge.h"
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
@@ -128,7 +126,6 @@ public:
|
||||
m_device = nullptr;
|
||||
m_backend = nullptr;
|
||||
m_sceneGridPass.Shutdown();
|
||||
m_sceneSelectionMaskPass.Shutdown();
|
||||
m_sceneSelectionOutlinePass.Shutdown();
|
||||
m_sceneRenderer.reset();
|
||||
}
|
||||
@@ -309,16 +306,13 @@ private:
|
||||
RHI::RHIResourceView* colorView = nullptr;
|
||||
RHI::RHITexture* depthTexture = nullptr;
|
||||
RHI::RHIResourceView* depthView = nullptr;
|
||||
RHI::RHITexture* selectionMaskTexture = nullptr;
|
||||
RHI::RHIResourceView* selectionMaskView = nullptr;
|
||||
RHI::RHIResourceView* selectionMaskShaderView = nullptr;
|
||||
RHI::RHITexture* objectIdTexture = nullptr;
|
||||
RHI::RHIResourceView* objectIdView = nullptr;
|
||||
RHI::RHIResourceView* objectIdShaderView = nullptr;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE imguiCpuHandle = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE imguiGpuHandle = {};
|
||||
ImTextureID textureId = {};
|
||||
RHI::ResourceStates colorState = RHI::ResourceStates::Common;
|
||||
RHI::ResourceStates selectionMaskState = RHI::ResourceStates::Common;
|
||||
RHI::ResourceStates objectIdState = RHI::ResourceStates::Common;
|
||||
bool hasValidObjectIdFrame = false;
|
||||
std::string statusText;
|
||||
@@ -333,8 +327,7 @@ private:
|
||||
struct SceneViewportRenderState {
|
||||
SceneViewportOverlayData overlay = {};
|
||||
Rendering::RenderPassSequence postPasses;
|
||||
Rendering::RenderCameraData cameraData = {};
|
||||
std::vector<Rendering::VisibleRenderItem> selectionRenderables;
|
||||
std::vector<uint64_t> selectedObjectIds;
|
||||
};
|
||||
|
||||
ViewportEntry& GetEntry(EditorViewportKind kind) {
|
||||
@@ -465,29 +458,6 @@ private:
|
||||
return entry.depthView != nullptr;
|
||||
}
|
||||
|
||||
bool CreateSceneViewportSelectionMaskResources(ViewportEntry& entry) {
|
||||
const RHI::TextureDesc selectionMaskDesc =
|
||||
BuildViewportTextureDesc(entry.width, entry.height, RHI::Format::R8G8B8A8_UNorm);
|
||||
entry.selectionMaskTexture = m_device->CreateTexture(selectionMaskDesc);
|
||||
if (entry.selectionMaskTexture == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const RHI::ResourceViewDesc selectionMaskViewDesc =
|
||||
BuildViewportTextureViewDesc(RHI::Format::R8G8B8A8_UNorm);
|
||||
entry.selectionMaskView = m_device->CreateRenderTargetView(
|
||||
entry.selectionMaskTexture,
|
||||
selectionMaskViewDesc);
|
||||
if (entry.selectionMaskView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.selectionMaskShaderView = m_device->CreateShaderResourceView(
|
||||
entry.selectionMaskTexture,
|
||||
selectionMaskViewDesc);
|
||||
return entry.selectionMaskShaderView != nullptr;
|
||||
}
|
||||
|
||||
bool CreateSceneViewportObjectIdResources(ViewportEntry& entry) {
|
||||
const RHI::TextureDesc objectIdDesc =
|
||||
BuildViewportTextureDesc(entry.width, entry.height, RHI::Format::R8G8B8A8_UNorm);
|
||||
@@ -501,7 +471,14 @@ private:
|
||||
entry.objectIdView = m_device->CreateRenderTargetView(
|
||||
entry.objectIdTexture,
|
||||
objectIdViewDesc);
|
||||
return entry.objectIdView != nullptr;
|
||||
if (entry.objectIdView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entry.objectIdShaderView = m_device->CreateShaderResourceView(
|
||||
entry.objectIdTexture,
|
||||
objectIdViewDesc);
|
||||
return entry.objectIdShaderView != nullptr;
|
||||
}
|
||||
|
||||
bool CreateViewportTextureDescriptor(ViewportEntry& entry) {
|
||||
@@ -537,11 +514,9 @@ private:
|
||||
entry.depthTexture != nullptr &&
|
||||
entry.depthView != nullptr &&
|
||||
(entry.kind != EditorViewportKind::Scene ||
|
||||
(entry.selectionMaskTexture != nullptr &&
|
||||
entry.selectionMaskView != nullptr &&
|
||||
entry.selectionMaskShaderView != nullptr &&
|
||||
entry.objectIdTexture != nullptr &&
|
||||
entry.objectIdView != nullptr)) &&
|
||||
(entry.objectIdTexture != nullptr &&
|
||||
entry.objectIdView != nullptr &&
|
||||
entry.objectIdShaderView != nullptr)) &&
|
||||
entry.textureId != ImTextureID{}) {
|
||||
return true;
|
||||
}
|
||||
@@ -561,12 +536,6 @@ private:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.kind == EditorViewportKind::Scene &&
|
||||
!CreateSceneViewportSelectionMaskResources(entry)) {
|
||||
DestroyViewportResources(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry.kind == EditorViewportKind::Scene &&
|
||||
!CreateSceneViewportObjectIdResources(entry)) {
|
||||
DestroyViewportResources(entry);
|
||||
@@ -578,7 +547,6 @@ private:
|
||||
return false;
|
||||
}
|
||||
entry.colorState = RHI::ResourceStates::Common;
|
||||
entry.selectionMaskState = RHI::ResourceStates::Common;
|
||||
entry.objectIdState = RHI::ResourceStates::Common;
|
||||
entry.hasValidObjectIdFrame = false;
|
||||
return true;
|
||||
@@ -593,15 +561,6 @@ private:
|
||||
return surface;
|
||||
}
|
||||
|
||||
Rendering::RenderSurface BuildSelectionMaskSurface(const ViewportEntry& entry) const {
|
||||
Rendering::RenderSurface surface(entry.width, entry.height);
|
||||
surface.SetColorAttachment(entry.selectionMaskView);
|
||||
surface.SetDepthAttachment(entry.depthView);
|
||||
surface.SetColorStateBefore(entry.selectionMaskState);
|
||||
surface.SetColorStateAfter(RHI::ResourceStates::PixelShaderResource);
|
||||
return surface;
|
||||
}
|
||||
|
||||
Rendering::RenderSurface BuildObjectIdSurface(const ViewportEntry& entry) const {
|
||||
Rendering::RenderSurface surface(entry.width, entry.height);
|
||||
surface.SetColorAttachment(entry.objectIdView);
|
||||
@@ -611,45 +570,6 @@ private:
|
||||
return surface;
|
||||
}
|
||||
|
||||
void AddSceneSelectionMaskPass(
|
||||
ViewportEntry& entry,
|
||||
const Rendering::RenderSurface& selectionMaskSurface,
|
||||
const Rendering::RenderCameraData& cameraData,
|
||||
const std::vector<Rendering::VisibleRenderItem>& selectionRenderables,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionMask",
|
||||
[this, &entry, selectionMaskSurface, &cameraData, &selectionRenderables](
|
||||
const Rendering::RenderPassContext& context) mutable {
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.selectionMaskView,
|
||||
entry.selectionMaskState,
|
||||
RHI::ResourceStates::RenderTarget);
|
||||
entry.selectionMaskState = RHI::ResourceStates::RenderTarget;
|
||||
|
||||
const float maskClearColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
RHI::RHIResourceView* maskView = entry.selectionMaskView;
|
||||
context.renderContext.commandList->SetRenderTargets(1, &maskView, entry.depthView);
|
||||
context.renderContext.commandList->ClearRenderTarget(maskView, maskClearColor);
|
||||
|
||||
const bool rendered = m_sceneSelectionMaskPass.Render(
|
||||
context.renderContext,
|
||||
selectionMaskSurface,
|
||||
cameraData,
|
||||
selectionRenderables);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask pass failed");
|
||||
}
|
||||
|
||||
context.renderContext.commandList->TransitionBarrier(
|
||||
entry.selectionMaskView,
|
||||
entry.selectionMaskState,
|
||||
RHI::ResourceStates::PixelShaderResource);
|
||||
entry.selectionMaskState = RHI::ResourceStates::PixelShaderResource;
|
||||
return rendered;
|
||||
}));
|
||||
}
|
||||
|
||||
void AddSceneColorToRenderTargetPass(
|
||||
ViewportEntry& entry,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
@@ -685,14 +605,17 @@ private:
|
||||
|
||||
void AddSceneSelectionOutlinePass(
|
||||
ViewportEntry& entry,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionOutline",
|
||||
[this, &entry](const Rendering::RenderPassContext& context) {
|
||||
[this, &entry, selectedObjectIds](const Rendering::RenderPassContext& context) {
|
||||
const bool rendered = m_sceneSelectionOutlinePass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
entry.selectionMaskShaderView);
|
||||
entry.objectIdShaderView,
|
||||
selectedObjectIds,
|
||||
false);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection outline pass failed");
|
||||
}
|
||||
@@ -717,23 +640,23 @@ private:
|
||||
|
||||
void AddSceneSelectionMaskDebugPass(
|
||||
ViewportEntry& entry,
|
||||
const Rendering::RenderCameraData& cameraData,
|
||||
const std::vector<Rendering::VisibleRenderItem>& selectionRenderables,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
outPostPasses.AddPass(MakeLambdaRenderPass(
|
||||
"SceneSelectionMaskDebug",
|
||||
[this, &entry, &cameraData, &selectionRenderables](
|
||||
[this, &entry, selectedObjectIds](
|
||||
const Rendering::RenderPassContext& context) {
|
||||
const float debugClearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
RHI::RHIResourceView* colorView = entry.colorView;
|
||||
context.renderContext.commandList->SetRenderTargets(1, &colorView, entry.depthView);
|
||||
context.renderContext.commandList->ClearRenderTarget(colorView, debugClearColor);
|
||||
|
||||
const bool rendered = m_sceneSelectionMaskPass.Render(
|
||||
const bool rendered = m_sceneSelectionOutlinePass.Render(
|
||||
context.renderContext,
|
||||
context.surface,
|
||||
cameraData,
|
||||
selectionRenderables);
|
||||
entry.objectIdShaderView,
|
||||
selectedObjectIds,
|
||||
true);
|
||||
if (!rendered) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask debug pass failed");
|
||||
}
|
||||
@@ -745,19 +668,9 @@ private:
|
||||
SceneViewportPostPassStep step,
|
||||
ViewportEntry& entry,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const Rendering::RenderSurface& selectionMaskSurface,
|
||||
const Rendering::RenderCameraData& cameraData,
|
||||
const std::vector<Rendering::VisibleRenderItem>& selectionRenderables,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
switch (step) {
|
||||
case SceneViewportPostPassStep::SelectionMask:
|
||||
AddSceneSelectionMaskPass(
|
||||
entry,
|
||||
selectionMaskSurface,
|
||||
cameraData,
|
||||
selectionRenderables,
|
||||
outPostPasses);
|
||||
break;
|
||||
case SceneViewportPostPassStep::ColorToRenderTarget:
|
||||
AddSceneColorToRenderTargetPass(entry, outPostPasses);
|
||||
break;
|
||||
@@ -765,7 +678,7 @@ private:
|
||||
AddSceneInfiniteGridPass(entry, overlay, outPostPasses);
|
||||
break;
|
||||
case SceneViewportPostPassStep::SelectionOutline:
|
||||
AddSceneSelectionOutlinePass(entry, outPostPasses);
|
||||
AddSceneSelectionOutlinePass(entry, selectedObjectIds, outPostPasses);
|
||||
break;
|
||||
case SceneViewportPostPassStep::ColorToShaderResource:
|
||||
AddSceneColorToShaderResourcePass(entry, outPostPasses);
|
||||
@@ -773,8 +686,7 @@ private:
|
||||
case SceneViewportPostPassStep::SelectionMaskDebug:
|
||||
AddSceneSelectionMaskDebugPass(
|
||||
entry,
|
||||
cameraData,
|
||||
selectionRenderables,
|
||||
selectedObjectIds,
|
||||
outPostPasses);
|
||||
break;
|
||||
default:
|
||||
@@ -785,43 +697,33 @@ private:
|
||||
bool BuildSceneViewPostPassSequence(
|
||||
ViewportEntry& entry,
|
||||
const SceneViewportOverlayData& overlay,
|
||||
const Rendering::RenderCameraData& cameraData,
|
||||
const std::vector<Rendering::VisibleRenderItem>& selectionRenderables,
|
||||
const std::vector<uint64_t>& selectedObjectIds,
|
||||
Rendering::RenderPassSequence& outPostPasses) {
|
||||
const bool hasSelection = !selectionRenderables.empty();
|
||||
const bool hasSelectionMaskRenderTarget = entry.selectionMaskView != nullptr;
|
||||
const bool hasSelectionMaskShaderView = entry.selectionMaskShaderView != nullptr;
|
||||
const bool hasSelection = !selectedObjectIds.empty();
|
||||
const bool hasObjectIdShaderView = entry.objectIdShaderView != nullptr;
|
||||
|
||||
if (hasSelection &&
|
||||
!kDebugSceneSelectionMask &&
|
||||
(!hasSelectionMaskRenderTarget || !hasSelectionMaskShaderView)) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene selection mask target is unavailable");
|
||||
!hasObjectIdShaderView) {
|
||||
SetViewportStatusIfEmpty(entry.statusText, "Scene object id shader view is unavailable");
|
||||
}
|
||||
|
||||
const SceneViewportPostPassPlan plan = BuildSceneViewportPostPassPlan({
|
||||
overlay.valid,
|
||||
hasSelection,
|
||||
kDebugSceneSelectionMask,
|
||||
hasSelectionMaskRenderTarget,
|
||||
hasSelectionMaskShaderView
|
||||
hasObjectIdShaderView
|
||||
});
|
||||
if (!plan.valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Rendering::RenderSurface selectionMaskSurface = {};
|
||||
if (plan.usesSelectionMaskSurface) {
|
||||
selectionMaskSurface = BuildSelectionMaskSurface(entry);
|
||||
}
|
||||
|
||||
for (const SceneViewportPostPassStep step : plan.steps) {
|
||||
AddSceneViewPostPassStep(
|
||||
step,
|
||||
entry,
|
||||
overlay,
|
||||
selectionMaskSurface,
|
||||
cameraData,
|
||||
selectionRenderables,
|
||||
selectedObjectIds,
|
||||
outPostPasses);
|
||||
}
|
||||
|
||||
@@ -833,27 +735,18 @@ private:
|
||||
IEditorContext& context,
|
||||
const Components::Scene& scene,
|
||||
SceneViewportRenderState& outState) {
|
||||
(void)scene;
|
||||
outState.overlay = GetSceneViewOverlayData();
|
||||
if (!outState.overlay.valid) {
|
||||
return;
|
||||
}
|
||||
|
||||
outState.selectionRenderables = CollectSceneViewportSelectionRenderables(
|
||||
scene,
|
||||
context.GetSelectionManager().GetSelectedEntities(),
|
||||
outState.overlay.cameraPosition);
|
||||
if (!outState.selectionRenderables.empty()) {
|
||||
outState.cameraData = BuildSceneViewportCameraData(
|
||||
*m_sceneViewCamera.camera,
|
||||
entry.width,
|
||||
entry.height);
|
||||
}
|
||||
outState.selectedObjectIds = context.GetSelectionManager().GetSelectedEntities();
|
||||
|
||||
BuildSceneViewPostPassSequence(
|
||||
entry,
|
||||
outState.overlay,
|
||||
outState.cameraData,
|
||||
outState.selectionRenderables,
|
||||
outState.selectedObjectIds,
|
||||
outState.postPasses);
|
||||
}
|
||||
|
||||
@@ -1046,30 +939,18 @@ private:
|
||||
m_backend->FreeTextureDescriptor(entry.imguiCpuHandle, entry.imguiGpuHandle);
|
||||
}
|
||||
|
||||
if (entry.selectionMaskShaderView != nullptr) {
|
||||
entry.selectionMaskShaderView->Shutdown();
|
||||
delete entry.selectionMaskShaderView;
|
||||
entry.selectionMaskShaderView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.selectionMaskView != nullptr) {
|
||||
entry.selectionMaskView->Shutdown();
|
||||
delete entry.selectionMaskView;
|
||||
entry.selectionMaskView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.selectionMaskTexture != nullptr) {
|
||||
entry.selectionMaskTexture->Shutdown();
|
||||
delete entry.selectionMaskTexture;
|
||||
entry.selectionMaskTexture = nullptr;
|
||||
}
|
||||
|
||||
if (entry.objectIdView != nullptr) {
|
||||
entry.objectIdView->Shutdown();
|
||||
delete entry.objectIdView;
|
||||
entry.objectIdView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.objectIdShaderView != nullptr) {
|
||||
entry.objectIdShaderView->Shutdown();
|
||||
delete entry.objectIdShaderView;
|
||||
entry.objectIdShaderView = nullptr;
|
||||
}
|
||||
|
||||
if (entry.objectIdTexture != nullptr) {
|
||||
entry.objectIdTexture->Shutdown();
|
||||
delete entry.objectIdTexture;
|
||||
@@ -1106,7 +987,6 @@ private:
|
||||
entry.imguiGpuHandle = {};
|
||||
entry.textureId = {};
|
||||
entry.colorState = RHI::ResourceStates::Common;
|
||||
entry.selectionMaskState = RHI::ResourceStates::Common;
|
||||
entry.objectIdState = RHI::ResourceStates::Common;
|
||||
entry.hasValidObjectIdFrame = false;
|
||||
}
|
||||
@@ -1118,7 +998,6 @@ private:
|
||||
std::array<ViewportEntry, 2> m_entries = {};
|
||||
SceneViewCameraState m_sceneViewCamera;
|
||||
SceneViewportInfiniteGridPass m_sceneGridPass;
|
||||
SceneViewportSelectionMaskPass m_sceneSelectionMaskPass;
|
||||
SceneViewportSelectionOutlinePass m_sceneSelectionOutlinePass;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user