diff --git a/editor/CMakeLists.txt b/editor/CMakeLists.txt index 2a443691..cb057923 100644 --- a/editor/CMakeLists.txt +++ b/editor/CMakeLists.txt @@ -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 diff --git a/editor/src/Viewport/ViewportHostService.h b/editor/src/Viewport/ViewportHostService.h index 9b3e3534..a3f69e9b 100644 --- a/editor/src/Viewport/ViewportHostService.h +++ b/editor/src/Viewport/ViewportHostService.h @@ -8,7 +8,6 @@ #include "SceneViewportCameraController.h" #include "SceneViewportInfiniteGridPass.h" #include "SceneViewportPostPassPlan.h" -#include "SceneViewportSelectionOutlinePass.h" #include "UI/ImGuiBackendBridge.h" #include @@ -19,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -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 m_entries = {}; SceneViewCameraState m_sceneViewCamera; SceneViewportInfiniteGridPass m_sceneGridPass; - SceneViewportSelectionOutlinePass m_sceneSelectionOutlinePass; + Rendering::Passes::BuiltinObjectIdOutlinePass m_sceneSelectionOutlinePass; }; } // namespace Editor diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index a90f0f74..94b601ac 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -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 diff --git a/editor/src/Viewport/SceneViewportSelectionOutlinePass.h b/engine/include/XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h similarity index 67% rename from editor/src/Viewport/SceneViewportSelectionOutlinePass.h rename to engine/include/XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h index ac3ec470..2558b8a5 100644 --- a/editor/src/Viewport/SceneViewportSelectionOutlinePass.h +++ b/engine/include/XCEngine/Rendering/Passes/BuiltinObjectIdOutlinePass.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -17,33 +18,40 @@ #include 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& 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 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 diff --git a/editor/src/Viewport/SceneViewportSelectionOutlinePass.cpp b/engine/src/Rendering/Passes/BuiltinObjectIdOutlinePass.cpp similarity index 88% rename from editor/src/Viewport/SceneViewportSelectionOutlinePass.cpp rename to engine/src/Rendering/Passes/BuiltinObjectIdOutlinePass.cpp index a981a4d7..7e55bea3 100644 --- a/editor/src/Viewport/SceneViewportSelectionOutlinePass.cpp +++ b/engine/src/Rendering/Passes/BuiltinObjectIdOutlinePass.cpp @@ -1,23 +1,22 @@ -#include "SceneViewportSelectionOutlinePass.h" +#include "Rendering/Passes/BuiltinObjectIdOutlinePass.h" -#include -#include -#include +#include "Rendering/ObjectIdEncoding.h" +#include "RHI/RHICommandList.h" +#include "RHI/RHIDevice.h" #include #include 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& 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(surface.GetHeight()), surface.GetWidth() > 0 ? 1.0f / static_cast(surface.GetWidth()) : 0.0f, surface.GetHeight() > 0 ? 1.0f / static_cast(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(selectedObjectIds.size()), kMaxSelectedObjectCount); constants.selectedInfo = Math::Vector4( static_cast(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(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