refactor: move object id outline pass into renderer

This commit is contained in:
2026-04-01 17:47:49 +08:00
parent b85571d9d4
commit 12b1081dd0
5 changed files with 65 additions and 43 deletions

View File

@@ -79,7 +79,6 @@ add_executable(${PROJECT_NAME} WIN32
src/Viewport/SceneViewportScaleGizmo.cpp
src/Viewport/SceneViewportGrid.cpp
src/Viewport/SceneViewportInfiniteGridPass.cpp
src/Viewport/SceneViewportSelectionOutlinePass.cpp
src/Viewport/SceneViewportOrientationGizmo.cpp
src/Viewport/SceneViewportOverlayRenderer.cpp
src/panels/GameViewPanel.cpp

View File

@@ -8,7 +8,6 @@
#include "SceneViewportCameraController.h"
#include "SceneViewportInfiniteGridPass.h"
#include "SceneViewportPostPassPlan.h"
#include "SceneViewportSelectionOutlinePass.h"
#include "UI/ImGuiBackendBridge.h"
#include <XCEngine/Components/CameraComponent.h>
@@ -19,6 +18,7 @@
#include <XCEngine/RHI/RHIResourceView.h>
#include <XCEngine/RHI/RHITexture.h>
#include <XCEngine/Rendering/ObjectIdEncoding.h>
#include <XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h>
#include <XCEngine/Rendering/RenderContext.h>
#include <XCEngine/Rendering/RenderSurface.h>
#include <XCEngine/Rendering/SceneRenderer.h>
@@ -615,7 +615,11 @@ private:
context.surface,
entry.objectIdShaderView,
selectedObjectIds,
false);
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");
}
@@ -656,7 +660,11 @@ private:
context.surface,
entry.objectIdShaderView,
selectedObjectIds,
true);
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");
}
@@ -998,7 +1006,7 @@ private:
std::array<ViewportEntry, 2> m_entries = {};
SceneViewCameraState m_sceneViewCamera;
SceneViewportInfiniteGridPass m_sceneGridPass;
SceneViewportSelectionOutlinePass m_sceneSelectionOutlinePass;
Rendering::Passes::BuiltinObjectIdOutlinePass m_sceneSelectionOutlinePass;
};
} // namespace Editor

View File

@@ -345,9 +345,11 @@ add_library(XCEngine STATIC
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/ObjectIdPass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/SceneRenderer.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Passes/BuiltinObjectIdPass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h
${CMAKE_CURRENT_SOURCE_DIR}/include/XCEngine/Rendering/Pipelines/BuiltinForwardPipeline.h
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/CameraRenderer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinObjectIdPass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/Passes/BuiltinObjectIdOutlinePass.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderSurface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderSceneExtractor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Rendering/RenderResourceCache.cpp

View File

@@ -1,5 +1,6 @@
#pragma once
#include <XCEngine/Core/Math/Color.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Vector4.h>
#include <XCEngine/Rendering/RenderContext.h>
@@ -17,33 +18,40 @@
#include <vector>
namespace XCEngine {
namespace Editor {
namespace Rendering {
namespace Passes {
class SceneViewportSelectionOutlinePass {
struct ObjectIdOutlineStyle {
Math::Color outlineColor = Math::Color(1.0f, 0.4f, 0.0f, 1.0f);
float outlineWidthPixels = 2.0f;
bool debugSelectionMask = false;
};
class BuiltinObjectIdOutlinePass {
public:
~SceneViewportSelectionOutlinePass() = default;
~BuiltinObjectIdOutlinePass() = default;
static constexpr uint32_t kMaxSelectedObjectCount = 256u;
void Shutdown();
bool Render(
const Rendering::RenderContext& renderContext,
const Rendering::RenderSurface& surface,
const RenderContext& renderContext,
const RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView,
const std::vector<uint64_t>& selectedObjectIds,
bool debugSelectionMask = false);
const ObjectIdOutlineStyle& style = {});
private:
struct OutlineConstants {
Math::Vector4 viewportSizeAndTexelSize = Math::Vector4::Zero();
Math::Vector4 outlineColorAndWidth = Math::Vector4::Zero();
Math::Vector4 outlineColor = Math::Vector4::Zero();
Math::Vector4 selectedInfo = Math::Vector4::Zero();
std::array<Math::Vector4, kMaxSelectedObjectCount> selectedObjectColors = {};
};
bool EnsureInitialized(const Rendering::RenderContext& renderContext);
bool CreateResources(const Rendering::RenderContext& renderContext);
bool EnsureInitialized(const RenderContext& renderContext);
bool CreateResources(const RenderContext& renderContext);
void DestroyResources();
RHI::RHIDevice* m_device = nullptr;
@@ -56,5 +64,6 @@ private:
RHI::RHIDescriptorSet* m_textureSet = nullptr;
};
} // namespace Editor
} // namespace Passes
} // namespace Rendering
} // namespace XCEngine

View File

@@ -1,23 +1,22 @@
#include "SceneViewportSelectionOutlinePass.h"
#include "Rendering/Passes/BuiltinObjectIdOutlinePass.h"
#include <XCEngine/Rendering/ObjectIdEncoding.h>
#include <XCEngine/RHI/RHICommandList.h>
#include <XCEngine/RHI/RHIDevice.h>
#include "Rendering/ObjectIdEncoding.h"
#include "RHI/RHICommandList.h"
#include "RHI/RHIDevice.h"
#include <algorithm>
#include <cstring>
namespace XCEngine {
namespace Editor {
namespace Rendering {
namespace Passes {
namespace {
constexpr float kOutlineWidthPixels = 2.0f;
const char kSelectionOutlineCompositeHlsl[] = R"(
const char kBuiltinObjectIdOutlineHlsl[] = R"(
cbuffer OutlineConstants : register(b0) {
float4 gViewportSizeAndTexelSize;
float4 gOutlineColorAndWidth;
float4 gOutlineColor;
float4 gSelectedInfo;
float4 gSelectedObjectColors[256];
};
@@ -85,7 +84,7 @@ float4 MainPS(VSOutput input) : SV_TARGET {
discard;
}
const int outlineWidth = max((int)gOutlineColorAndWidth.w, 1);
const int outlineWidth = max((int)gSelectedInfo.z, 1);
float outline = 0.0;
[loop]
for (int y = -2; y <= 2; ++y) {
@@ -113,22 +112,22 @@ float4 MainPS(VSOutput input) : SV_TARGET {
discard;
}
return float4(gOutlineColorAndWidth.rgb, outline);
return float4(gOutlineColor.rgb, gOutlineColor.a * outline);
}
)";
} // namespace
void SceneViewportSelectionOutlinePass::Shutdown() {
void BuiltinObjectIdOutlinePass::Shutdown() {
DestroyResources();
}
bool SceneViewportSelectionOutlinePass::Render(
const Rendering::RenderContext& renderContext,
const Rendering::RenderSurface& surface,
bool BuiltinObjectIdOutlinePass::Render(
const RenderContext& renderContext,
const RenderSurface& surface,
RHI::RHIResourceView* objectIdTextureView,
const std::vector<uint64_t>& selectedObjectIds,
bool debugSelectionMask) {
const ObjectIdOutlineStyle& style) {
if (!renderContext.IsValid() ||
renderContext.backendType != RHI::RHIType::D3D12 ||
objectIdTextureView == nullptr ||
@@ -151,19 +150,23 @@ bool SceneViewportSelectionOutlinePass::Render(
static_cast<float>(surface.GetHeight()),
surface.GetWidth() > 0 ? 1.0f / static_cast<float>(surface.GetWidth()) : 0.0f,
surface.GetHeight() > 0 ? 1.0f / static_cast<float>(surface.GetHeight()) : 0.0f);
constants.outlineColorAndWidth = Math::Vector4(1.0f, 0.4f, 0.0f, kOutlineWidthPixels);
constants.outlineColor = Math::Vector4(
style.outlineColor.r,
style.outlineColor.g,
style.outlineColor.b,
style.outlineColor.a);
const uint32_t selectedCount = (std::min)(
static_cast<uint32_t>(selectedObjectIds.size()),
kMaxSelectedObjectCount);
constants.selectedInfo = Math::Vector4(
static_cast<float>(selectedCount),
debugSelectionMask ? 1.0f : 0.0f,
0.0f,
style.debugSelectionMask ? 1.0f : 0.0f,
style.outlineWidthPixels,
0.0f);
for (uint32_t index = 0; index < selectedCount; ++index) {
constants.selectedObjectColors[index] =
Rendering::EncodeObjectIdToColor(selectedObjectIds[index]);
EncodeObjectIdToColor(selectedObjectIds[index]);
}
m_constantSet->WriteConstant(0, &constants, sizeof(constants));
@@ -199,7 +202,7 @@ bool SceneViewportSelectionOutlinePass::Render(
return true;
}
bool SceneViewportSelectionOutlinePass::EnsureInitialized(const Rendering::RenderContext& renderContext) {
bool BuiltinObjectIdOutlinePass::EnsureInitialized(const RenderContext& renderContext) {
if (m_pipelineLayout != nullptr &&
m_pipelineState != nullptr &&
m_constantPool != nullptr &&
@@ -215,7 +218,7 @@ bool SceneViewportSelectionOutlinePass::EnsureInitialized(const Rendering::Rende
return CreateResources(renderContext);
}
bool SceneViewportSelectionOutlinePass::CreateResources(const Rendering::RenderContext& renderContext) {
bool BuiltinObjectIdOutlinePass::CreateResources(const RenderContext& renderContext) {
if (!renderContext.IsValid() || renderContext.backendType != RHI::RHIType::D3D12) {
return false;
}
@@ -311,15 +314,15 @@ bool SceneViewportSelectionOutlinePass::CreateResources(const Rendering::RenderC
pipelineDesc.depthStencilState.depthFunc = static_cast<uint32_t>(RHI::ComparisonFunc::Always);
pipelineDesc.vertexShader.source.assign(
kSelectionOutlineCompositeHlsl,
kSelectionOutlineCompositeHlsl + std::strlen(kSelectionOutlineCompositeHlsl));
kBuiltinObjectIdOutlineHlsl,
kBuiltinObjectIdOutlineHlsl + std::strlen(kBuiltinObjectIdOutlineHlsl));
pipelineDesc.vertexShader.sourceLanguage = RHI::ShaderLanguage::HLSL;
pipelineDesc.vertexShader.entryPoint = L"MainVS";
pipelineDesc.vertexShader.profile = L"vs_5_0";
pipelineDesc.fragmentShader.source.assign(
kSelectionOutlineCompositeHlsl,
kSelectionOutlineCompositeHlsl + std::strlen(kSelectionOutlineCompositeHlsl));
kBuiltinObjectIdOutlineHlsl,
kBuiltinObjectIdOutlineHlsl + std::strlen(kBuiltinObjectIdOutlineHlsl));
pipelineDesc.fragmentShader.sourceLanguage = RHI::ShaderLanguage::HLSL;
pipelineDesc.fragmentShader.entryPoint = L"MainPS";
pipelineDesc.fragmentShader.profile = L"ps_5_0";
@@ -333,7 +336,7 @@ bool SceneViewportSelectionOutlinePass::CreateResources(const Rendering::RenderC
return true;
}
void SceneViewportSelectionOutlinePass::DestroyResources() {
void BuiltinObjectIdOutlinePass::DestroyResources() {
if (m_pipelineState != nullptr) {
m_pipelineState->Shutdown();
delete m_pipelineState;
@@ -374,5 +377,6 @@ void SceneViewportSelectionOutlinePass::DestroyResources() {
m_backendType = RHI::RHIType::D3D12;
}
} // namespace Editor
} // namespace Passes
} // namespace Rendering
} // namespace XCEngine