Files
XCEngine/docs/api/_guides/Editor/Scene-Viewport-Render-Plan-And-Failure-Flow.md

153 lines
6.7 KiB
Markdown
Raw Normal View History

2026-04-08 16:07:03 +08:00
# Scene View Render Plan And Failure Flow
## 先建立正确心智模型
当前 Scene View 不是“把活动场景直接交给 `SceneRenderer`”这么简单。
它真实的工作方式更接近商业引擎编辑器常见的两层结构:
1. 运行时渲染层
- 负责把场景和相机变成基础 `CameraRenderRequest`
2. 编辑器附加层
- 负责网格、selection outline、editor overlay、object-id 与状态文案
`SceneViewportRenderPlan` 正是第二层里的一个关键中间件,而当前 `ViewportHostService` 与它之间还多了一层 [SceneViewportRenderPassBundle](../../XCEngine/Editor/Viewport/SceneViewportRenderPassBundle/SceneViewportRenderPassBundle.md),专门负责持有 grid / outline / overlay renderer 并提供 factory。
## 当前主调用链
`ViewportHostService.h` 当前实现Scene View 一帧渲染大致是:
1. `RenderRequestedViewports(...)` 遍历本帧请求过的视口。
2. `RenderViewportEntry(...)` 检查 `colorView` / `depthView` 是否存在。
3. 如果是 Scene 视口,进入 `RenderSceneViewportEntry(...)`
4. 检查隐藏编辑器 Scene View 相机是否可用。
5. 检查活动场景是否存在。
6. `BuildSceneViewportRenderState(...)`
- 读取 `SceneViewportOverlayData`
- 读取当前选中对象列表
- 读取 `SceneViewportOverlayFrameData`
- 调用 `m_sceneViewportRenderPassBundle.BuildRenderPlan(...)`
- bundle 内部再调用 `BuildSceneViewportRenderPlan(...)`
7. `SceneRenderer::BuildRenderRequests(...)` 生成基础 request。
8. `ApplySceneViewportRenderPlan(...)` 把 editor 附加项写回 request。
9. `SceneRenderer::Render(requests)` 执行真正的场景渲染。
10. `MarkSceneViewportRenderSuccess(...)` 回写颜色状态、object-id 状态和有效标记。
## `SceneViewportRenderPlan` 到底负责什么
它当前只负责三类附加项:
- `postScenePasses`
- 无限网格
- selection outline
- `overlayPasses`
- editor overlay
- clear-color override
- 默认 Scene View 背景色是 `(0.27, 0.27, 0.27, 1.0)`
这意味着它不是 Scene View 的全部流程,只是“把 Scene View 专属附加能力组织成一个可应用的 plan”。
## 为什么要有默认 clear-color override
因为 Scene View 的定位不是游戏运行结果,而是编辑工作台。
如果完全复用场景相机自己的 clear 语义,编辑体验会出现两个问题:
- 背景风格可能随场景内容波动,不稳定
- 编辑器 overlay、gizmo、网格失去统一视觉基底
当前默认灰色背景,是典型的编辑器视图设计:优先保证工作环境一致性,再叠加运行时内容。
## 为什么 warning 不直接终止渲染
一个很典型的例子是:
- 选中了对象
- 需要 selection outline
-`objectIdShaderView` 不可用
这时当前实现不会直接让 Scene View 失败,而是:
- 返回 warning `Scene object id shader view is unavailable`
- 继续保留网格、主场景和 overlay 的正常渲染
这是编辑器设计里非常关键的原则:**局部能力缺口优先降级,而不是整页黑屏**。
## 失败回退是怎么接进来的
Scene View 的失败回退不在 `SceneViewportRenderPlan` 自己内部处理,而是交给:
- [ViewportHostRenderFlowUtils](../../XCEngine/Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md)
其中最关键的策略包括:
- `BuildSceneViewportRenderFailurePolicy(...)`
- `ApplyViewportFailureStatus(...)`
- `InvalidateViewportObjectIdFrame(...)`
- `MarkSceneViewportRenderSuccess(...)`
也就是说:
- render plan 负责“本帧附加画什么”
- flow utils 负责“失败时怎么退、成功后怎么收尾”
这样的分工会让 Scene View 主链更稳。
## 为什么要把 Build 和 Apply 分开
如果把 plan 构建和 request 写回混成一个函数,短期看代码会少一些,但长期会带来三个问题:
1. 很难单独测试规划逻辑
2. 很容易在复用 `CameraRenderRequest` 时留下脏指针
3. `ViewportHostService` 会重新变成一大段条件拼装代码
当前拆成:
- `BuildSceneViewportRenderPlan(...)`
- `ApplySceneViewportRenderPlan(...)`
本质上是在把“决策”和“接线”分离。这种拆法在商业引擎里很常见,因为它更容易维护,也更适合持续往 Scene View 里加新能力。
## Game View 为什么不用这套 plan
Game View 的目标是尽量忠实呈现运行时相机结果,所以它没有:
- editor 私有背景
- 网格
- selection outline
- gizmo overlay
因此它直接走 `SceneRenderer`,成功后只做最基本的颜色状态回写与 object-id 失效处理。
## 当前最重要的设计收益
现在这套链路真正带来的收益不是“代码更优雅”,而是三个更现实的好处:
- Scene View 可以在局部能力缺失时尽量继续工作
- 编辑器附加渲染和运行时场景渲染保持分层
- 每一层都可以被单独测试和文档化
这正是商业级编辑器最需要的特征:稳定、可诊断、可扩展。
## 建议阅读顺序
1. [ViewportHostService](../../XCEngine/Editor/Viewport/ViewportHostService/ViewportHostService.md)
2. [ViewportHostService::RenderRequestedViewports](../../XCEngine/Editor/Viewport/ViewportHostService/RenderRequestedViewports.md)
3. [SceneViewportRenderPassBundle](../../XCEngine/Editor/Viewport/SceneViewportRenderPassBundle/SceneViewportRenderPassBundle.md)
4. [SceneViewportRenderPlan](../../XCEngine/Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md)
5. [BuildSceneViewportRenderPlan](../../XCEngine/Editor/Viewport/SceneViewportRenderPlan/BuildSceneViewportRenderPlan.md)
6. [ApplySceneViewportRenderPlan](../../XCEngine/Editor/Viewport/SceneViewportRenderPlan/ApplySceneViewportRenderPlan.md)
7. [ViewportHostRenderFlowUtils](../../XCEngine/Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md)
8. [ApplySceneViewportRenderRequestSetup](../../XCEngine/Editor/Viewport/ViewportHostRenderFlowUtils/ApplySceneViewportRenderRequestSetup.md)
9. [MarkSceneViewportRenderSuccess](../../XCEngine/Editor/Viewport/ViewportHostRenderFlowUtils/MarkSceneViewportRenderSuccess.md)
## 相关文档
- [Editor Architecture And Workflow](Editor-Architecture-And-Workflow.md)
- [SceneView Interaction And Gizmo Model](SceneView-Interaction-And-Gizmo-Model.md)
- [Viewport](../../XCEngine/Editor/Viewport/Viewport.md)
- [ViewportHostService](../../XCEngine/Editor/Viewport/ViewportHostService/ViewportHostService.md)
- [SceneViewportRenderPassBundle](../../XCEngine/Editor/Viewport/SceneViewportRenderPassBundle/SceneViewportRenderPassBundle.md)
- [SceneViewportRenderPlan](../../XCEngine/Editor/Viewport/SceneViewportRenderPlan/SceneViewportRenderPlan.md)
- [ViewportHostRenderFlowUtils](../../XCEngine/Editor/Viewport/ViewportHostRenderFlowUtils/ViewportHostRenderFlowUtils.md)