Files
XCEngine/docs/used/Renderer当前主线下一阶段_PostProcess与FinalOutput收口计划_完成归档_2026-04-06.md

8.5 KiB
Raw Blame History

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_sceneoffscreen_scenecamera_stack_scenetransparent_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 与后处理能力

也就是说,现在下一步不是做更多“效果”,而是先把相机输出主链做完整。