feat: ImGui docking Editor + 显示链/帧同步/输入语义重构
- App/editor: Hierarchy/Inspector/Viewport/Stats 四面板 + DockBuilder 默认布局,main.cpp 瘦身为场景搭建与生命周期 - 显示链: Tonemap→PresentTarget 经 ImGui::Image 呈现(零色偏),backbuffer 仅承载 ImGui;Direct/Viewport 双显示模式 + 面板分辨率上报 - 帧首同步 BeginFrameSync: resize/vsync/尺寸/模式意图统一帧首落定(修描述符悬垂);修复 vsync 意图未落 swapchain 导致的每帧重建交换链 - 输入: Editor 每帧判定键盘/鼠标归属(打字让位、Viewport hover/focus 放行、Fullscreen 全放行) - 材质: roughness 独立槽位 + 非 glTF 金属/粗糙贴图映射;透明队列 depthWrite=FALSE + translucent 独立 shader + scratch 清帧 - FBX: 非蒙皮网格烘焙节点链全局变换(Z-up 旋转/单位换算落顶点) - Hierarchy 行 ImGui ID 以 UUID 作用域(重名不冲突、改名不丢选中)
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/29.
|
||||
//
|
||||
// BlitPass:显示模式适配器(kDisplayDirect 专用)。
|
||||
// Direct 模式:vkCmdBlitImage 把 PresentTarget(tonemap 输出)拷进
|
||||
// backbuffer,ImGui 随后 loadOp=Load 叠加 —— 场景铺满窗口的游戏形态。
|
||||
// Viewport(Editor)模式:空转,backbuffer 由 ImGui 清屏独占,场景
|
||||
// 经 ImGui::Image 呈现。
|
||||
//
|
||||
// 用 vkCmdBlitImage 而非着色器:同格式全屏拷贝零 shader 成本(声明
|
||||
// TransferSrc/TransferDst use,layout/barrier 由 RG 推导)。Blit 不在
|
||||
// rendering scope 内,直接录在 cmd 上,合法。
|
||||
//
|
||||
// 注:Blit 只在 Direct 模式运行,此时 PresentTarget 与 backbuffer 同为
|
||||
// 目标尺寸(1:1),src/dst offset 均取本 pass 渲染区域即可。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_BLITPASS_H
|
||||
#define HELLOVULKAN_BLITPASS_H
|
||||
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h>
|
||||
#include <array>
|
||||
|
||||
namespace Engine::Passes {
|
||||
|
||||
class BlitPass final : public RenderPass {
|
||||
public:
|
||||
BlitPass(FrameSceneData& frame, RG::TextureHandle src,
|
||||
RG::TextureHandle dst)
|
||||
: m_Frame(frame), m_Src(src), m_Dst(dst) {}
|
||||
|
||||
void Register(RG::RenderGraph& rg) override
|
||||
{
|
||||
rg.AddPass("Blit", [this](RG::RenderGraphContext& ctx) {
|
||||
if (m_Frame.displayMode != kDisplayDirect) return; // Editor 模式空转
|
||||
|
||||
vk::ImageBlit region;
|
||||
region.setSrcSubresource({vk::ImageAspectFlagBits::eColor, 0, 0, 1})
|
||||
.setDstSubresource({vk::ImageAspectFlagBits::eColor, 0, 0, 1});
|
||||
// src/dst 各按自己附件的物理尺寸取 offset(Direct 模式下
|
||||
// 二者同为窗口尺寸;尺寸解耦时此写法也各自正确)
|
||||
const vk::Extent2D srcExt = ctx.Extent(m_Src);
|
||||
const vk::Extent2D dstExt = ctx.Extent(m_Dst);
|
||||
const std::array<vk::Offset3D, 2> srcSpan = {
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{static_cast<i32>(srcExt.width),
|
||||
static_cast<i32>(srcExt.height), 1}};
|
||||
const std::array<vk::Offset3D, 2> dstSpan = {
|
||||
vk::Offset3D{0, 0, 0},
|
||||
vk::Offset3D{static_cast<i32>(dstExt.width),
|
||||
static_cast<i32>(dstExt.height), 1}};
|
||||
region.setSrcOffsets(srcSpan).setDstOffsets(dstSpan);
|
||||
|
||||
ctx.cmd.blitImage(
|
||||
ctx.Image(m_Src), vk::ImageLayout::eTransferSrcOptimal,
|
||||
ctx.Image(m_Dst), vk::ImageLayout::eTransferDstOptimal,
|
||||
{region}, vk::Filter::eLinear);
|
||||
})
|
||||
.Read(m_Src, RG::ResourceUse::TransferSrc)
|
||||
.Write(m_Dst, RG::ResourceUse::TransferDst);
|
||||
}
|
||||
|
||||
private:
|
||||
FrameSceneData& m_Frame; // displayMode(帧契约)
|
||||
RG::TextureHandle m_Src; // PresentTarget(tonemap 输出)
|
||||
RG::TextureHandle m_Dst; // backbuffer
|
||||
};
|
||||
|
||||
} // namespace Engine::Passes
|
||||
|
||||
#endif //HELLOVULKAN_BLITPASS_H
|
||||
@@ -28,6 +28,12 @@ namespace Engine::Passes {
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
// 两段渲染共享的命令录制(shader/描述符绑定 + 几何/光栅/视口状态)。
|
||||
// translucent=true 绑定 gl_FragDepth=1.0 的透明 frag 变体;
|
||||
// 深度写与混合状态由各渲染实例作为初始态设置,见 ForwardPass.cpp
|
||||
void RecordSharedState(const RG::RenderGraphContext& ctx,
|
||||
vk::CommandBuffer cmd, bool translucent) const;
|
||||
|
||||
SceneGpu& m_Gpu;
|
||||
FrameSceneData& m_Frame;
|
||||
RG::TextureHandle m_HDRColor;
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Engine {
|
||||
kDebugIrradiance, // IBL 漫反射辐照度(32² 低频)
|
||||
kDebugPrefilter, // IBL pre-filter(纵向 = mip/roughness 分级)
|
||||
kDebugBrdfLut, // BRDF 积分 LUT(RG 双通道)
|
||||
kDebugTransparent, // 仅透明队列(Skybox/Forward 跳过绘制,看透明段内容)
|
||||
kDebugViewCount
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define HELLOVULKAN_IMGUIPASS_H
|
||||
|
||||
#include <Engine/Renderer/Passes/RenderPass.h>
|
||||
#include <Engine/Renderer/SceneTypes.h> // FrameSceneData(displayMode 帧契约)
|
||||
|
||||
namespace Engine {
|
||||
|
||||
@@ -21,15 +22,22 @@ namespace Engine {
|
||||
class ImGuiPass final : public RenderPass {
|
||||
public:
|
||||
// 二级指针:Renderer::SetImGuiLayer 在 Register 之后才可能被调
|
||||
//(EnableImGui 时机由派生类决定),执行期解引用取最新值
|
||||
ImGuiPass(ImGuiLayer** layer, RG::TextureHandle backbuffer)
|
||||
: m_Layer(layer), m_Backbuffer(backbuffer) {}
|
||||
//(EnableImGui 时机由派生类决定),执行期解引用取最新值。
|
||||
// presentTarget:ImGui::Image 采样的场景纹理(tonemap 输出)。
|
||||
// loadOp 按 displayMode 分支:Direct = Load(blit 已铺场景),
|
||||
// Viewport = Clear(唯一写入者,清"桌面底色")
|
||||
ImGuiPass(ImGuiLayer** layer, FrameSceneData& frame,
|
||||
RG::TextureHandle backbuffer, RG::TextureHandle presentTarget)
|
||||
: m_Layer(layer), m_Frame(frame), m_Backbuffer(backbuffer),
|
||||
m_PresentTarget(presentTarget) {}
|
||||
|
||||
void Register(RG::RenderGraph& rg) override;
|
||||
|
||||
private:
|
||||
ImGuiLayer** m_Layer;
|
||||
FrameSceneData& m_Frame; // displayMode(帧契约)
|
||||
RG::TextureHandle m_Backbuffer;
|
||||
RG::TextureHandle m_PresentTarget;
|
||||
};
|
||||
|
||||
} // namespace Passes
|
||||
|
||||
@@ -25,22 +25,36 @@ namespace Engine {
|
||||
class ShaderManager;
|
||||
class UniformBuffer;
|
||||
class Cubemap;
|
||||
class Buffer;
|
||||
class MemoryAllocator;
|
||||
|
||||
namespace Passes {
|
||||
|
||||
class SceneGpu {
|
||||
public:
|
||||
SceneGpu(Device& device, DescriptorManager& descriptors,
|
||||
SceneGpu(Device& device, MemoryAllocator& allocator,
|
||||
DescriptorManager& descriptors,
|
||||
ShaderManager& shaders,
|
||||
UniformBuffer& ubo, UniformBuffer& objectBuffer,
|
||||
UniformBuffer& prevObjectBuffer);
|
||||
UniformBuffer& prevObjectBuffer,
|
||||
UniformBuffer& skinOffsetBuffer,
|
||||
UniformBuffer& skinPaletteBuffer);
|
||||
~SceneGpu();
|
||||
|
||||
SceneGpu(const SceneGpu&) = delete;
|
||||
SceneGpu& operator=(const SceneGpu&) = delete;
|
||||
|
||||
// ---- MDI 间接绘制 ----
|
||||
// CPU 打包的命令/count 落进本槽位 ring(Renderer 在 fence
|
||||
// 等待后调用——与 UBO/SSBO 上传同一安全窗口)
|
||||
void UploadIndirect(u32 frameSlot, const FrameSceneData& frame);
|
||||
// 一次组绘制:bind 共享 megabuffer + drawIndexedIndirectCount
|
||||
void DrawIndirectGroup(vk::CommandBuffer cmd, u32 frameSlot,
|
||||
u32 viewIndex, const IndirectGroup& g);
|
||||
|
||||
// ---- set 布局(shader 契约,改绑定必须同步 shaders/)----
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer, PrevObjectBuffer}
|
||||
vk::DescriptorSetLayout uboSetLayout; // Set0 = {UBO, ObjectBuffer, PrevObjectBuffer,
|
||||
// SkinOffsets, SkinPalettes}
|
||||
vk::DescriptorSetLayout textureSetLayout; // Set1 = {材质 4 槽 + 参数 UBO}
|
||||
vk::DescriptorSetLayout shadowSetLayout; // Set2 = {级联 0/1/2 阴影图, irradiance cube}
|
||||
vk::PipelineLayout forwardLayout; // 3 sets,无 push(GPUDriven 经 SSBO)
|
||||
@@ -54,7 +68,16 @@ namespace Engine {
|
||||
//(省 shader 出界分支)
|
||||
vk::Sampler shadowSampler;
|
||||
|
||||
// ---- MDI per-slot ring ----
|
||||
// 布局:[main | cascade0 | cascade1 | cascade2],每区
|
||||
// kMaxInstances 条命令预算(每实例至多 1 条命令,必不越界)。
|
||||
// count buffer 同分区(每组一个 u32,下标 = 组首命令下标)
|
||||
std::array<Scope<Buffer>, kMaxFramesInFlight> indirectCmdBuffers;
|
||||
std::array<Scope<Buffer>, kMaxFramesInFlight> indirectCountBuffers;
|
||||
|
||||
vk::ShaderEXT forwardVert{}, forwardFrag{};
|
||||
// 透明变体:同 simple_shader + gl_FragDepth=1.0(见 frag 注释)
|
||||
vk::ShaderEXT translucentFrag{};
|
||||
vk::ShaderEXT shadowVert{}, shadowFrag{};
|
||||
|
||||
// RG 重编译后重绑阴影图(物理镜像按槽位各一份)
|
||||
@@ -66,6 +89,7 @@ namespace Engine {
|
||||
|
||||
private:
|
||||
Device& m_Device;
|
||||
MemoryAllocator& m_Allocator;
|
||||
DescriptorManager& m_Descriptors;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/23.
|
||||
//
|
||||
// TonemapPass:HDR(+bloom)→ 显示空间,全屏三角写 Backbuffer。
|
||||
// TonemapPass:HDR(+bloom)→ 显示空间,全屏三角写 PresentTarget。
|
||||
// 显示变换在此显式建模(对齐 UE/Unity:HDR SceneColor → tonemapper → UI)。
|
||||
// Backbuffer 从此只接收"显示空间"颜色:tonemap 直接写、ImGui 叠加。
|
||||
// PresentTarget 是 offscreen 可采样纹理:由 ImGui::Image 呈现(输出位置
|
||||
// 可自由摆放),backbuffer 不再接收场景画面。
|
||||
//
|
||||
|
||||
#ifndef HELLOVULKAN_TONEMAPPASS_H
|
||||
@@ -28,7 +29,8 @@ namespace Engine {
|
||||
PostProcessParams& params,
|
||||
FrameSceneData& frame,
|
||||
RG::TextureHandle hdrColor, RG::TextureHandle bloomA,
|
||||
RG::TextureHandle temporalDiff, RG::TextureHandle backbuffer,
|
||||
RG::TextureHandle temporalDiff,
|
||||
RG::TextureHandle presentTarget,
|
||||
RG::TextureHandle rawHdr, RG::TextureHandle velocity,
|
||||
RG::TextureHandle shadowMap0, RG::TextureHandle shadowMap1,
|
||||
RG::TextureHandle shadowMap2);
|
||||
@@ -46,7 +48,7 @@ namespace Engine {
|
||||
RG::TextureHandle m_HDR;
|
||||
RG::TextureHandle m_A;
|
||||
RG::TextureHandle m_TemporalDiff;
|
||||
RG::TextureHandle m_Backbuffer;
|
||||
RG::TextureHandle m_Target; // PresentTarget(offscreen,ImGui 采样呈现)
|
||||
// ---- 调试视图源(binding 3-7,Register 时声明读防止剔除)----
|
||||
// 注:TAAColor 视图直接用 binding0(主输入即 TAA 输出),无需重复绑
|
||||
RG::TextureHandle m_RawHDR; // Forward 直出(TAA 前)
|
||||
|
||||
Reference in New Issue
Block a user