feat: HitProxy GPU 拾取 + UE 选中描边 + 编辑器拾取交互
- HitProxy 拾取:RG 管线渲染实体 id → host readback,点击帧 PickEntity 精确命中;拾取按视觉几何(Model 联合包围球射线求交), 与 Collider 解耦(UE/Unity 编辑器语义),命中打印实体名+碰撞体参数 - 选中描边(UE 语义):SelectionMask pass(R8Unorm 完整投影轮廓, 无深度测试透墙可见)→ Outline pass(边缘检测 + alpha 叠加, 必须注册在 Tonemap 后);edgeCut 贴视口边缘;widthPx=6 可调 - shader object 实证修复:VUID-08879 同程序 set layouts 超集一致、 VUID-10065 push block 4×float 平铺、新 pass 析构销毁 VkShaderEXT - RG:SideEffect() 保活"产出无 RG 内消费者"的 pass 链 - Editor:层次面板点击选中、Inspector 姿态编辑、Stats 面板拾取信息 - 相机 Update 改 const(姿态写入 Transform 引用,Camera 本身无状态变更)
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// HitProxyPass:UE 式 GPU 拾取(像素级 id pass + 点击 readback)。
|
||||
//
|
||||
// 两个 RG pass:
|
||||
// "HitProxy" —— 拾取请求帧把不透明 + 透明 batch 用 id 管线画进
|
||||
// R32Uint 目标(片元值 = 实体位模式)。深度自测自写
|
||||
// (重清主深度):遮挡语义 = 可见表面胜出;运行在
|
||||
// Forward/ForwardTrans/PhysicsDebug 之后的 WAW 链尾,
|
||||
// 主链下游无人再读深度,下帧 Forward 照常重新 Clear
|
||||
// "HitProxyCopy" —— 请求像素 1×1 CopyImageToBuffer 进 host-visible
|
||||
// 暂存。TransferSrc use 让 RG 自动完成
|
||||
// eColorAttachmentOptimal → eTransferSrcOptimal 迁移
|
||||
//
|
||||
// 无请求帧零绘制零拷贝(barrier 照常插入,GPU 无实际工作)。
|
||||
// 结果流:Renderer::TakePickResult(waitIdle 保证提交完成)→ 映射暂存。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_HITPROXYPASS_H
|
||||
#define HELLOVULKAN_HITPROXYPASS_H
|
||||
|
||||
#include <Engine/Core/Types.h>
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/Buffer.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
class Device;
|
||||
class ShaderManager;
|
||||
class DescriptorManager;
|
||||
|
||||
namespace Passes {
|
||||
|
||||
class SceneGpu;
|
||||
|
||||
class HitProxyPass final : public RenderPass {
|
||||
public:
|
||||
HitProxyPass(Device& device, MemoryAllocator& allocator,
|
||||
ShaderManager& shaders, DescriptorManager& descriptors,
|
||||
SceneGpu& gpu, FrameSceneData& frame,
|
||||
RG::TextureHandle idTarget, RG::TextureHandle depth);
|
||||
~HitProxyPass();
|
||||
|
||||
HitProxyPass(const HitProxyPass&) = delete;
|
||||
HitProxyPass& operator=(const HitProxyPass&) = delete;
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
|
||||
// 有待取结果(拷贝已录制进当帧命令缓冲)
|
||||
bool HasPendingResult() const { return m_ResultValid; }
|
||||
// 取走拷贝结果(一次性)。调用方保证 GPU 已 idle
|
||||
//(Renderer::TakePickResult 内 waitIdle)
|
||||
bool TakeResult(u32& outBits);
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
SceneGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_IdTarget;
|
||||
RG::TextureHandle m_Depth;
|
||||
|
||||
vk::PipelineLayout m_Layout; // Set0 = uboSetLayout,无 push
|
||||
vk::ShaderEXT m_Vert{}, m_Frag{};
|
||||
|
||||
// 1×1 像素暂存(host visible,持久映射);拷贝录制时置位
|
||||
Scope<Buffer> m_Staging;
|
||||
bool m_ResultValid = false;
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
} // namespace Engine
|
||||
|
||||
#endif //HELLOVULKAN_HITPROXYPASS_H
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// OutlinePass:选中描边后处理(UE 编辑器选中轮廓语义)。
|
||||
//
|
||||
// 对 SelectionMask 做边缘检测,alpha 混合叠加在 Tonemap 之后的
|
||||
// PresentTarget 上——描边是恒定 LDR UI 色,不进 bloom/曝光/TAA。
|
||||
// 无选中帧跳过绘制(SideEffect 保活,见 HitProxy 教训)。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_OUTLINEPASS_H
|
||||
#define HELLOVULKAN_OUTLINEPASS_H
|
||||
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
namespace Passes {
|
||||
|
||||
class FullscreenGpu;
|
||||
|
||||
class OutlinePass final : public RenderPass {
|
||||
public:
|
||||
// color:描边色(LDR);widthPx:描边宽度(物理像素)
|
||||
OutlinePass(Device& device, FullscreenGpu& gpu, ShaderManager& shaders,
|
||||
FrameSceneData& frame,
|
||||
RG::TextureHandle mask, RG::TextureHandle present,
|
||||
const glm::vec3& color = glm::vec3(1.0f, 0.62f, 0.05f),
|
||||
f32 widthPx = 6.0f);
|
||||
~OutlinePass() override;
|
||||
|
||||
OutlinePass(const OutlinePass&) = delete;
|
||||
OutlinePass& operator=(const OutlinePass&) = delete;
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
void OnTargetsRebuilt(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
FullscreenGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_Mask;
|
||||
RG::TextureHandle m_Present;
|
||||
glm::vec3 m_Color;
|
||||
f32 m_WidthPx;
|
||||
ShaderObject m_Frag{};
|
||||
std::vector<vk::DescriptorSet> m_Sets; // per-frame slot
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
} // namespace Engine
|
||||
|
||||
#endif //HELLOVULKAN_OUTLINEPASS_H
|
||||
@@ -38,7 +38,8 @@ namespace Engine {
|
||||
UniformBuffer& ubo, UniformBuffer& objectBuffer,
|
||||
UniformBuffer& prevObjectBuffer,
|
||||
UniformBuffer& skinOffsetBuffer,
|
||||
UniformBuffer& skinPaletteBuffer);
|
||||
UniformBuffer& skinPaletteBuffer,
|
||||
UniformBuffer& entityIdBuffer);
|
||||
~SceneGpu();
|
||||
|
||||
SceneGpu(const SceneGpu&) = delete;
|
||||
@@ -54,7 +55,7 @@ namespace Engine {
|
||||
|
||||
// ---- set 布局(shader 契约,改绑定必须同步 shaders/)----
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer, PrevObjectBuffer,
|
||||
// SkinOffsets, SkinPalettes}
|
||||
// SkinOffsets, SkinPalettes, EntityIds}
|
||||
vk::DescriptorSetLayout textureSetLayout; // Set1 = {材质 4 槽 + 参数 UBO}
|
||||
vk::DescriptorSetLayout shadowSetLayout; // Set2 = {级联 0/1/2 阴影图, irradiance cube}
|
||||
vk::PipelineLayout forwardLayout; // 3 sets,无 push(GPUDriven 经 SSBO)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// SelectionMaskPass:选中描边 mask pass(UE CustomStencil 语义)。
|
||||
//
|
||||
// 只绘制选中实体(FrameSceneData.selectionDraws,BuildFrame 从实例表
|
||||
// 筛出)到 R8Unorm mask:复用 SceneGpu 的 forwardVert(静态/蒙皮同源
|
||||
// 变换)+ 恒 1 片元。无深度测试 → mask = 完整投影轮廓(透墙可见,
|
||||
// 且前方遮挡物不会在 mask 上挖洞——挖洞会让边缘检测把洞描出来)。
|
||||
//
|
||||
// 无选中帧只 clear mask 不绘制(SideEffect 保活——拷贝终点在 RG 外
|
||||
// 的 pass 会被引用计数剔除,见 HitProxy 教训)。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_SELECTIONMASKPASS_H
|
||||
#define HELLOVULKAN_SELECTIONMASKPASS_H
|
||||
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <Engine/Vulkan/ShaderManager.h>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
namespace Passes {
|
||||
|
||||
class SceneGpu;
|
||||
|
||||
class SelectionMaskPass final : public RenderPass {
|
||||
public:
|
||||
SelectionMaskPass(Device& device, ShaderManager& shaders,
|
||||
SceneGpu& gpu, FrameSceneData& frame,
|
||||
RG::TextureHandle mask);
|
||||
~SelectionMaskPass() override;
|
||||
|
||||
SelectionMaskPass(const SelectionMaskPass&) = delete;
|
||||
SelectionMaskPass& operator=(const SelectionMaskPass&) = delete;
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
void OnTargetsRebuilt(RG::RenderGraph& rg) override {}
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
SceneGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_Mask;
|
||||
ShaderObject m_Frag{};
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
} // namespace Engine
|
||||
|
||||
#endif //HELLOVULKAN_SELECTIONMASKPASS_H
|
||||
Reference in New Issue
Block a user