From 5e489b61d253d80a6db1fb70c82197ff1c3b86a7 Mon Sep 17 00:00:00 2001 From: ssdfasd <2156608475@qq.com> Date: Mon, 6 Apr 2026 03:35:33 +0800 Subject: [PATCH] Plan post-process and final-output closure --- ...段_PostProcess与FinalOutput收口计划_2026-04-06.md | 296 ++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100644 docs/plan/Renderer当前主线下一阶段_PostProcess与FinalOutput收口计划_2026-04-06.md diff --git a/docs/plan/Renderer当前主线下一阶段_PostProcess与FinalOutput收口计划_2026-04-06.md b/docs/plan/Renderer当前主线下一阶段_PostProcess与FinalOutput收口计划_2026-04-06.md new file mode 100644 index 00000000..ae646fca --- /dev/null +++ b/docs/plan/Renderer当前主线下一阶段_PostProcess与FinalOutput收口计划_2026-04-06.md @@ -0,0 +1,296 @@ +# Renderer 当前主线下一阶段:PostProcess 与 FinalOutput 收口计划 + +日期:`2026-04-06` + +## 1. 阶段结论 + +当前 Rendering 主线的下一个阶段,不应该跳去做: + +- `render graph` +- deferred / clustered +- GPU picking 替换 +- 更复杂的 editor-only 特效 + +现在真正还没收口的,是 **runtime 相机帧合成链路**。 + +更具体地说,就是把当前 renderer 从: + +`Scene -> 直接打到最终 surface` + +收口成: + +`Scene Color -> 可选 PostProcess -> Final Output` + +只有这一步补齐之后,现阶段的 renderer 才算真正具备了稳定的 runtime frame composition 能力,也才适合继续往 Unity 风格的 renderer feature / C# SRP 承接点推进。 + +## 2. 为什么现在必须先做这个 + +当前仓库已经具备: + +- 正式的 forward runtime scene renderer +- directional / point / spot 多光源 +- main directional shadow +- skybox +- object id +- editor overlay / gizmo / grid + +但真正缺的仍然是下面这条 runtime 正式主链: + +`Opaque -> Skybox -> Transparent -> PostProcess -> Final Output` + +现在的主要缺口是: + +- `CameraRenderRequest` 还没有正式的 post-process / final-output contract +- `CameraRenderer` 仍然以 `request.surface` 作为主场景直接输出目标 +- 没有 renderer 级别的 fullscreen pass 基础设施 +- 没有“只有需要时才分配 intermediate color target”的正式策略 +- 也没有一个专门验证 runtime 后处理闭环的 `post_process_scene` + +如果这个阶段不先收口,后续无论做 tone mapping、color grading、exposure、更多环境特性,都会继续以临时拼接的方式往上堆,架构会重新变脏。 + +## 3. 目标 + +本阶段只做一件事: + +**把 runtime 相机输出链路正式化。** + +完成后应达到: + +1. renderer 具备正式的 post-process 请求与执行入口。 +2. renderer 具备 backend-neutral 的 fullscreen pass 基础设施。 +3. 相机默认仍可直接渲染到最终目标,只有在确实需要后处理或最终合成时才切换 intermediate color target。 +4. final output 的 copy / blit / resolve 规则明确,不再隐式散落在具体 pass 中。 +5. object id 与 editor overlay 明确保持在 runtime final-color 主链之外。 +6. 增加 `post_process_scene` 集成测试,验证三后端一致性。 + +## 4. 非目标 + +本阶段明确不做: + +- `render graph` +- HDR 全量管线 +- bloom / SSAO / DOF / motion blur 等完整后处理套件 +- cubemap IBL / reflection probe +- GPU picking 替换 CPU picking +- editor SceneView 的额外视觉增强 +- 新一轮 renderer 大重构 + +## 5. 设计原则 + +### 5.1 继续遵循当前分层 + +- `RHI` 只提供资源、render target、pipeline、draw/dispatch 抽象。 +- `Renderer` 负责相机帧规划、runtime pass 调度、final output 规则。 +- `Editor` 仍然只是宿主与 overlay 使用方,不接管 runtime 后处理。 + +### 5.2 runtime 主链与 editor 辅助链继续隔离 + +下列内容不进入 runtime final-color 主链: + +- `ObjectId` +- grid +- gizmo +- selection outline +- scene icon + +它们仍然属于 editor 专用辅助链路。 + +### 5.3 默认直出,按需离屏 + +默认情况: + +- 没有 post-process +- 没有额外 final composition 需求 + +则继续允许相机直接渲染到最终 `surface`。 + +只有满足下面条件之一时,才启用 intermediate color target: + +- 存在 runtime post-process +- final output 需要一次 fullscreen copy / resolve / color transform +- 后续扩展的 runtime frame composition 明确要求 scene color 先落到中间目标 + +这个判断必须由 `CameraRenderer` 或 request planning 统一控制,不能散落到单个 pass 内部。 + +## 6. 核心方案 + +### 6.1 补齐 CameraRenderRequest 的正式 contract + +当前 `CameraRenderRequest` 已有: + +- `PreScenePasses` +- `ShadowCaster` +- `DepthOnly` +- `MainScene` +- `ObjectId` +- `PostScenePasses` +- `OverlayPasses` + +下一步要补的是“runtime final-color 链”的明确语义,而不是继续把 `PostScenePasses` 当一个模糊兜底桶。 + +建议演进方向: + +- 保留现有 stage 枚举兼容当前结构 +- 在 request 数据层新增更明确的 runtime 输出描述 +- 显式区分: + - scene color source + - post-process chain + - final output target + +换句话说,本阶段的重点不是改名字,而是把数据契约补完整。 + +### 6.2 增加 Fullscreen Pass 基础设施 + +需要新增 backend-neutral 的 fullscreen pass helper,用于: + +- 绑定 source color texture +- 绑定 sampler / descriptor set +- 设置 fullscreen triangle 或等价路径 +- 输出到指定 color target + +首版要求: + +- 三后端可复用同一套 renderer 侧调用方式 +- shader 输入输出约束简单、稳定、可测试 +- 不依赖 editor 私有绘制路径 + +### 6.3 Final Output 明确化 + +当前 main scene 直接打到 `request.surface` 的方式,需要升级成可判断的策略: + +1. 如果本帧不需要 post-process / final copy,则 direct-to-surface。 +2. 如果本帧需要 post-process,则: + - main scene 输出到 intermediate color target + - post-process 读取 intermediate + - final pass 输出到 `request.surface` + +这里要把以下规则写死: + +- intermediate 的格式、尺寸与生命周期 +- final blit / copy / fullscreen draw 由谁负责 +- MSAA / resolve 如果暂时没有正式支持,要在 contract 里先写清当前限制 + +### 6.4 第一阶段验证效果只做最小闭环 + +本阶段不追求复杂后处理效果。 + +第一阶段 builtin effect 建议只做一种确定性极强、三后端最容易对齐的效果: + +- `ColorScale` + +例如对 scene color 统一乘一个常量因子。 + +这样做的原因: + +- 易于写 GT +- 不依赖复杂数学或 LUT +- 不容易受不同后端精度差异影响 +- 能直接证明 post-process infrastructure 已闭环 + +## 7. 测试策略 + +### 7.1 新增集成测试 + +新增: + +- `tests/Rendering/integration/post_process_scene` + +建议测试场景: + +- 结构尽量简单 +- 使用确定性颜色块或单个模型 +- 主场景颜色在经过 `ColorScale` 后能明显与未处理版本区分 +- 三后端都输出 `*_d3d12.ppm` / `*_opengl.ppm` / `*_vulkan.ppm` +- 统一对比单张 `GT.ppm` + +### 7.2 必跑回归 + +本阶段至少回归: + +- `rendering_integration_skybox_scene` +- `rendering_integration_offscreen_scene` +- `rendering_integration_transparent_material_scene` +- `rendering_integration_camera_stack_scene` +- `rendering_integration_object_id_scene` + +必要时再补: + +- `material_state_scene` +- `depth_sort_scene` + +### 7.3 单测方向 + +建议补或增强的 unit coverage: + +- 何时启用 intermediate color target +- post-process chain 为空时的 direct path +- final output routing 决策 +- request contract 的默认行为与 fallback + +## 8. 分阶段执行 + +### Phase A:补齐 contract + +目标: + +- 明确 runtime post-process / final-output 所需的数据结构与决策入口 + +完成标准: + +- `CameraRenderRequest` / planner / `CameraRenderer` 层的数据语义清晰 +- 现有场景渲染不回退 + +### Phase B:引入 fullscreen pass 与 intermediate 策略 + +目标: + +- 跑通 scene color -> fullscreen pass -> final surface + +完成标准: + +- 三后端都能稳定执行最小 fullscreen pass +- direct path 仍然保留 + +### Phase C:接入最小 builtin post-process + +目标: + +- 用 `ColorScale` 验证 runtime 后处理闭环 + +完成标准: + +- `post_process_scene` GT 通过 +- `skybox_scene` / `offscreen_scene` / `transparent_material_scene` 不回退 + +### Phase D:文档与测试收口 + +目标: + +- 把当前阶段的 contract、测试矩阵、限制条件写回文档 + +完成标准: + +- `tests/TEST_SPEC.md` 如有必要同步更新 +- 当前计划可归档到 `docs/used` + +## 9. 收口判定 + +满足以下条件时,本阶段可以视为完成: + +1. runtime renderer 已具备正式 post-process 入口。 +2. final output 路径不再依赖隐式直写逻辑。 +3. intermediate color target 为按需启用,而不是一刀切常驻。 +4. `post_process_scene` 在 D3D12 / OpenGL / Vulkan 三后端通过。 +5. `skybox_scene`、`offscreen_scene`、`camera_stack_scene`、`transparent_material_scene` 不回退。 +6. object id 与 editor overlay 没有被错误卷入 runtime final-color 链。 + +## 10. 这一阶段之后再做什么 + +等这一阶段收口之后,renderer 主线再继续往下走,顺序才是合理的: + +1. 更正式的 shader / material runtime pass contract +2. 更成熟的 renderer feature / Unity 风格可扩展点 +3. GPU object id / picking 正式化 +4. 更复杂的 environment、tone mapping 与后处理能力 + +也就是说,**现在下一步不是做更多“效果”,而是先把相机输出主链做完整。**