# NewEditor 3D渲染主链正式接入计划 日期: `2026-04-12` ## 1. 文档定位 这份计划替代此前那份偏宽泛的《NewEditor 对标旧 Editor 迁移重建计划》。 当前主线已经很明确: - `new_editor` 的 UI 基础壳已经足够继续往上承接。 - 真正卡住后续重建编辑器的,不再是普通面板样式或 tab/dock 行为。 - 当前最大的主阻塞,是 `Scene / Game` 还没有接上旧 `editor` 里已经跑通的真实 3D 渲染主链。 因此,接下来要先做的不是继续铺业务面板,而是: 1. 先把 `new_editor` 的宿主渲染链补齐。 2. 再把旧 `editor` 的 viewport/rendering 主链正式迁入 `new_editor`。 3. 等 `Scene / Game` 真正稳定输出真实 3D 画面后,再继续后续编辑器业务迁移。 ## 2. 当前事实与根因判断 ### 2.1 旧 editor 当前的真实可用主链 旧 `editor` 的 Scene/Game viewport 不是面板里临时拼的,它已经形成了明确主链: `Application -> D3D12WindowRenderer -> ViewportHostService -> SceneRenderer -> ViewportRenderTargets -> ImGui texture presentation` 当前关键代码入口: - `editor/src/Application.cpp` - `editor/src/Platform/D3D12WindowRenderer.h` - `editor/src/Viewport/ViewportHostService.h` - `editor/src/panels/SceneViewPanel.cpp` - `editor/src/panels/GameViewPanel.cpp` ### 2.2 new_editor 当前的真实状态 `new_editor` 现在已经有: - `XCEditor` UI 基础层 - Win32 + `NativeRenderer` 宿主层 - `Hierarchy / Inspector / Console / Project` 这些 hosted content 面板外壳 但 `Scene / Game` 这条线并没有真正接上旧 editor 的 render path。 当前缺口是结构性的: 1. `new_editor/app/Shell/ProductShellAsset.cpp` 里,`scene` 和 `game` 仍然只是 `HostedContent`,还没有切到正式的 `ViewportShell` 主线。 2. `new_editor/app/Workspace/ProductEditorWorkspace.cpp` 里,没有真正的 viewport service owner,也没有 scene/game render request 生命周期。 3. `new_editor/app/Host/NativeRenderer.h/.cpp` 当前是 Direct2D/DirectWrite 宿主,只支持它自己的位图纹理路径。 4. `engine/include/XCEngine/UI/Types.h` 虽然已经有 `UITextureHandleKind::ShaderResourceView`,但 `NativeRenderer` 目前并没有真正消费这类引擎 render target。 ### 2.3 根因结论 当前问题的根因不是“Scene 面板还没抄过来”,而是: - `new_editor` 宿主层还没有与引擎 `Rendering + RHI` 建立正式的 viewport 纹理桥接。 - `XCEditor` 的 viewport 壳层虽然已经存在,但 `new_editor` 还没把它真正接到 GPU viewport frame 上。 所以这件事必须从宿主渲染架构开始修,不能从面板层糊。 ## 3. 不可违背的执行原则 ### 3.1 根因优先 - 禁止 CPU 截图回读后再贴回 UI。 - 禁止用 PNG/中间 bitmap/调试贴图冒充正式 viewport 输出。 - 禁止在 `Scene` 或 `Game` 面板内部偷偷持有一套临时渲染路径。 ### 3.2 旧 editor 只作为基线,不照搬 ImGui 壳 - 要复用旧 editor 已经验证过的 render host、viewport service、render target、object id、overlay 这些真实主链能力。 - 但不要把 `ImGui panel` 那一层硬抄到 `new_editor`。 - 迁移时要抽出“引擎桥接能力”,接回 `XCEditor` 的 viewport shell。 ### 3.3 Scene/Game 必须统一走正式 viewport 子系统 - `Scene` 和 `Game` 不能继续当普通 hosted content 面板处理。 - 它们必须切到同一套 `ViewportShell -> ViewportService -> RenderTargets -> RenderFrame` 路径。 - Scene/Game 的差异只能体现在 camera / overlay / input policy,不应该体现在宿主渲染基础设施层。 ### 3.4 每阶段都能独立验证 每一阶段结束都必须满足: - 能编译 `XCUIEditorApp` - 能运行 exe - 能给出明确的人工检查点 ## 4. 目标架构 ## 4.1 new_editor 最终应形成的 viewport 主链 目标主链: `Win32 Application -> Host Window Renderer -> XCEditor ViewportShell -> ProductViewportHostService -> SceneRenderer -> RHI RenderTargets -> Viewport Texture Bridge -> XCEditor Compose -> Window Present` 分层责任: - `Host` - 管窗口、swapchain、command queue、command list、descriptor heap、present - `XCEditor` - 管 viewport 壳层布局、top bar、bottom bar、input bridge、状态显示 - `new_editor/app/Viewport` - 管 Scene/Game viewport 请求、render target 生命周期、editor scene camera、input 解释、selection/picking/overlay - `Rendering + RHI` - 管真正的 scene render requests 和 GPU 输出 ## 4.2 宿主层方向 `NativeRenderer` 当前的 D2D-only `HwndRenderTarget` 不能作为长期正式宿主。 新的宿主方向应当是: - 以 D3D12/RHI swapchain 作为主呈现链 - 在这个主呈现链上承接 `XCEditor` UI 组合与 engine viewport 纹理 关于 2D UI 绘制策略,允许按实际情况调整实现,但边界必须固定: - 可以保留 D2D/DWrite 作为 2D 绘制后端,但它只能作为从属 UI compositor,不能继续做整个窗口的唯一主呈现链 - 如果 D2D 与 D3D12 的互操作复杂度失控,就切换为更直接的 GPU UI compositor - 无论选择哪条实现路径,都不能回退到 CPU 回读/贴图绕路 ## 5. 执行阶段 ## 阶段 A: 宿主渲染基础设施对齐 目标: - 先把 `new_editor` 宿主从“D2D-only 窗口绘制器”升级为“真正的窗口 render host” 主要工作: 1. 在 `new_editor/app/Host` 下建立正式的 window renderer 2. 对齐旧 `editor/src/Platform/D3D12WindowRenderer.h` 的能力边界 3. 让 `Application` 能拿到: - `RHIDevice` - `RHICommandQueue` - `RHICommandList` - swapchain backbuffer surface - shader-visible descriptor heap - 每帧 begin/present 生命周期 4. 保留并接回现有 DPI / resize / cursor / screenshot 生命周期 验收: - `XCUIEditor.exe` 能用新宿主稳定打开 - 调整窗口尺寸时不会再出现位图式整体拉伸 - 空窗口 clear/present 稳定,无闪烁、无明显 resize 延迟 ## 阶段 B: Viewport 纹理桥接正式化 目标: - 让 `XCEditor` viewport slot 真正能展示来自引擎 RHI 的 render target 主要工作: 1. 明确 `UITextureHandle` 在 `new_editor` 中的正式 viewport 语义 2. 补齐 `ShaderResourceView` 路径,而不是继续只支持文件位图 3. 建立 render target -> UI texture handle 的生命周期管理 4. 处理 descriptor/state/resize/recreate 规则 建议测试: - 在 `tests/UI/Editor/integration` 下新增专门的 viewport GPU 纹理验证用例 - 先用一个最小 GPU clear/checkerboard 纹理跑通 `ViewportShell` 验收: - `ViewportShell` 可显示真实 GPU render target - viewport 尺寸变化时,纹理尺寸和显示内容立即同步 - 整个链路不含 readback / screenshot / 中间文件 ## 阶段 C: Scene/Game 从 HostedContent 切到 ViewportShell 目标: - 让 `scene` 和 `game` 不再是伪面板,而是正式 viewport panel 主要工作: 1. 修改 `ProductShellAsset` 中 `scene/game` 的 presentation 模型 2. 在 `new_editor/app` 建立正式的 viewport panel 装配点 3. 建立 viewport request/response 数据模型: - requested size - presented frame - status text - capture/focus/input state 验收: - `Scene` 和 `Game` 面板进入统一 viewport 壳层 - 可以显示“真实 viewport frame”,不再是纯 placeholder/调试文案 ## 阶段 D: Scene 真实渲染最小闭环 目标: - 先让 `Scene` 面板输出旧 editor 那条真实 3D 场景渲染 主要工作: 1. 在 `new_editor/app/Viewport` 下建立 `ProductViewportHostService` 2. 先迁移旧 `ViewportHostService` 的最小 spine: - scene editor camera state - scene viewport render targets - `SceneRenderer` 调用 - status/failure policy 3. 只先做“能稳定渲染”的最小闭环 4. 暂时不带 gizmo,不带复杂 overlay,不带过多面板业务联动 验收: - `Scene` 面板显示真实 3D 场景 - resize 时 render target 立即更新 - 画面不是占位实现,不是 2D 假画面 ## 阶段 E: Game 真实渲染闭环 目标: - 接上 `Game` 面板的真实 camera render path 主要工作: 1. 对齐旧 editor 的 game viewport 请求方式 2. 使用 active scene camera 或旧 editor 当前约定的 camera 选择规则 3. 接上 game viewport 状态显示和 resize 规则 验收: - `Game` 面板显示真实场景相机输出 - 与 `Scene` 共享宿主基础设施,但 camera 语义独立 ## 阶段 F: Scene 输入、导航、拾取 目标: - 在真实 3D 画面已经稳定的前提下,补回 Scene 交互 主要工作: 1. 迁移 scene camera navigation 2. 迁移 focus selection 3. 迁移 object id picking 4. 接回 selection 路由 验收: - 右键看、平移、缩放、聚焦等基础导航恢复 - 点击对象能正确选中 ## 阶段 G: Overlay / Gizmo / Editor 辅助渲染 目标: - 继续对齐旧 editor 的 editor-only viewport 叠加能力 主要工作: 1. overlay frame cache 2. overlay builder 3. selection outline / orientation / transform gizmo 4. Scene/Game 差异化 overlay policy 验收: - Scene overlay 与 gizmo 基本达到旧 editor 可用水平 - 不因 overlay 引入新的渲染路径分叉 ## 6. 并行切分策略 这条主线不是完全串行,但前两阶段有明显关键路径。 ### 必须串行的部分 1. 阶段 A 宿主 render host 2. 阶段 B viewport 纹理桥接 这两步没完成,后面的 Scene/Game 真渲染都只能是假接入。 ### 可以并行的部分 在 A/B 基本定型后,可并行拆为 3 组: 1. `Host` - window renderer - present/frame lifecycle - viewport texture bridge 2. `app/Viewport` - render targets - scene/game render request owner - status/failure policy 3. `XCEditor` / `app/Shell` - scene/game 切换到 `ViewportShell` - viewport 状态展示 - 相关 integration tests ## 7. 明确不做的事 这份计划期间,不做以下偏移主线的工作: - 不继续优先铺新的业务面板细节 - 不先做 inspector/component editor 的深层业务联动 - 不把 runtime UI 主题资源机制重新塞回 editor UI - 不用临时截图/静态贴图假装 viewport ## 8. 收口标准 满足以下条件,才算 `new_editor` 的 3D 渲染基础层正式收口: 1. `Scene` 和 `Game` 都显示真实 3D GPU 输出 2. resize、DPI、focus、capture 行为稳定 3. viewport 纹理链路不依赖 ImGui 4. Scene 基础导航和 picking 恢复 5. 后续继续重建 `new_editor` 时,不需要再回头推倒宿主渲染基础层 ## 9. 旧计划归档说明 本轮归档: - `docs/plan/used/NewEditor对标旧Editor迁移重建计划_2026-04-12.md` 保留为参考文档,不归档: - `docs/plan/Editor架构说明.md` 原因: - 它仍然是旧 editor 分层与边界的有效参考 - 但当前主线已经从“泛迁移计划”切换为“viewport / rendering 主链正式接入计划”