Archive completed renderer closure plans

This commit is contained in:
2026-04-06 16:41:24 +08:00
parent be4c43f11e
commit eef5de7ee9
3 changed files with 0 additions and 0 deletions

View File

@@ -1,374 +0,0 @@
# Renderer 下一阶段: FinalColorPipeline 正式化计划
日期: `2026-04-06`
## 1. 阶段定位
上一阶段已经完成:
- `CameraPostProcess` 描述层正式化
- `SceneRenderer` 从相机描述层自动构建 post-process request
- manual path 与 formal scene path 都已测试闭环
下一阶段不再讨论“要不要继续往引擎里内置几个后处理特效”。
下一阶段真正要做的是:
-`Final Color Pipeline` 作为 renderer 主链的正式组成部分建立起来
- 并且从架构上明确对齐 Unity 风格的 SRP 演进方向
也就是把当前链路从:
`SceneColor -> CameraPostProcessStack -> Surface`
推进到:
`SceneColor -> CameraPostProcessStack -> FinalColorPipeline -> Output Surface`
其中:
- `CameraPostProcessStack` 是相机上的可扩展全屏效果链
- `FinalColorPipeline` 是 renderer 内置的最终出图规则
二者不是同一个概念。
## 2. 与 Unity/SRP 对齐的核心结论
如果目标是后续在这套 rendering 之上做 Unity 风格的 `SRP`,那这一步必须遵守下面这条主线:
### 2.1 FinalColor 不能只挂在 Camera 上
Unity 风格的渲染架构里最终出图规则不应该被设计成“Camera 私有特效配置”。
更合理的来源解析链应该是:
`Pipeline/Renderer defaults -> Camera override -> future Volume override -> resolved per-camera final color policy`
也就是说:
- 默认值来自 pipeline/renderer 级配置
- 相机只做少量 override
- 以后 volume 再覆盖部分结果
- renderer 最终对每个 camera 解析出一份正式的 final color policy
### 2.2 FinalColor 属于 renderer 主链,不属于任意 post-process stack
下面这些应被视为 renderer 正式内置能力:
- linear -> sRGB output transfer
- exposure
- tone mapping
- final color transform
而不是被混成“任意全屏效果链”里的普通 pass。
### 2.3 必须提前预留 SRP pass injection 点
如果以后要做 Unity 风格 SRP / RendererFeature / 自定义 pass:
- 现在就不能把 final color policy 写成一堆散落在 `SceneRenderer` 里的硬编码分支
- 必须明确 runtime 主链阶段
- 必须给 future renderer feature / custom fullscreen pass 预留稳定插入点
## 3. 当前问题
当前 renderer 虽然已经具备:
- forward runtime scene renderer
- shadow / skybox / multi-light
- camera post-process 描述层
- formal render request / final output stage 框架
但距离 SRP-ready 还差下面这些正式收口:
1. `FinalOutput` 还没有真正变成正式的 final color 执行层
2. `FinalColorPolicy` 还没有独立于 `CameraPostProcessStack`
3. pipeline 默认值、camera override、future volume override 还没有分层
4. 最终出图的颜色空间 contract 还没有制度化
5. 还没有给 future `RendererFeature / Pass injection` 明确主链挂点
## 4. 本阶段目标
本阶段完成后,应达到:
1. 引入正式的 `FinalColorSettings / FinalColorPolicy`
2. 形成明确的数据来源链:
- pipeline/renderer defaults
- camera override
- reserved future volume override
3. `SceneRenderer` 负责解析每个 camera 的最终 final color policy
4. `CameraRenderer``FinalOutput` stage 正式承担最终出图职责
5. `CameraPostProcessStack``FinalColorPipeline` 完全分层
6. 为 future `RendererFeature / Pass injection` 预留清晰的阶段和 contract
7. 三后端对 final color path 有稳定测试覆盖
## 5. 非目标
本阶段明确不做:
- bloom
- SSAO
- DOF
- motion blur
- 完整 LUT color grading 套件
- volume 系统完整落地
- renderer feature 全量系统
- render graph
- editor-only 特效
本阶段的重点是:
- 把最终出图主链做正式
而不是:
- 堆更多视觉效果
## 6. 设计原则
### 6.1 三层来源解析
第一层: `Pipeline / Renderer defaults`
这里放全局默认 final color 行为,例如:
- output transfer mode
- default exposure mode/value
- default tone mapping mode
- 是否启用 final color stage
第二层: `Camera override`
相机只做少量覆盖,例如:
- 是否允许 post-process/final color
- override exposure
- override final color transform
- 指定 renderer / pipeline variant
第三层: `Future Volume override`
当前阶段只预留 contract不完整落地但必须明确将来会从这里覆写:
- exposure
- tone mapping
- color adjustments
最终由 renderer 解析出:
- `ResolvedFinalColorPolicy`
### 6.2 PostProcess 与 FinalColor 必须分层
约定如下:
#### `CameraPostProcessStack`
职责:
- 相机上的可扩展 fullscreen effect chain
- 偏向“特效层”与“自定义效果层”
例子:
- color scale
- 以后可能的 edge effect / custom fullscreen effect
#### `FinalColorPipeline`
职责:
- renderer 正式最终出图
- 负责把线性 scene color 变成最终显示输出
例子:
- output transfer
- exposure
- tone mapping
- final color transform
### 6.3 FinalOutput 是正式主链阶段
这一阶段完成后,需要把 `FinalOutput` 明确成正式 runtime stage而不是“名义上存在、实际上只留空接口”的阶段。
主链应明确为:
`MainScene -> CameraPostProcess -> FinalColor -> Output`
### 6.4 先做 contract再做更多效果
第一版不追求效果数量,先把下面这些做对:
- 数据模型
- 来源解析
- 执行阶段
- 三后端一致性
## 7. 核心方案
### 7.1 引入 FinalColorSettings / ResolvedFinalColorPolicy
建议引入两层数据:
#### 配置层
- `FinalColorSettings`
来源:
- pipeline defaults
- camera override
- future volume override
#### 执行层
- `ResolvedFinalColorPolicy`
用途:
- renderer 在本帧、对这个 camera 最终真正执行的 final color 规则
### 7.2 第一版字段建议
第一版保持克制,建议只引入最小必要字段:
- output transfer mode
- disabled
- linear to sRGB
- exposure mode
- disabled
- fixed exposure
- exposure value
- tone mapping mode
- disabled
- reserved future enum
- final color scale
注意:
- tone mapping mode 可以先留枚举和数据入口
- 第一阶段不要求完整 tone mapping 实装
### 7.3 将 FinalOutput 接入正式工厂化执行
当前已有 post-process 的描述层和工厂翻译思路。
这一阶段要把同样的正式化思路用于 `FinalOutput`:
- `SceneRenderer` 负责根据 resolved final color policy 构建 final output request
- `CameraRenderer` 负责执行 final output stage
- final output 相关 pass 不再靠零散 if 分支拼装
### 7.4 预留 future RendererFeature / Pass injection 点
这一步必须把下面这些插入点概念固定下来:
- before main scene
- after main scene
- after camera post-process
- before final output
- after final output / before editor composite
当前阶段不要求把完整 feature 系统实现完,但必须在 plan 和 runtime stage 语义上先定好位置。
## 8. 执行阶段
### Phase A: SRP-ready FinalColor contract
目标:
- 定义 `FinalColorSettings`
- 定义 `ResolvedFinalColorPolicy`
- 明确三层来源解析
完成标准:
- pipeline defaults / camera override / future volume override 的职责写清楚
- 不破坏现有 `CameraPostProcess` 主链
### Phase B: FinalOutput 正式执行层
目标:
-`FinalOutput` 成为正式执行阶段
完成标准:
- `SceneRenderer` 能自动附加 final output request
- `CameraRenderer` 走正式 final-output chain
- 不再依赖零散条件分支
### Phase C: 最小 builtin final color 闭环
目标:
- 用最小 final color policy 验证 contract
建议首选:
- `LinearToSRGB / OutputTransfer`
可选再加:
- fixed exposure
- final color scale
完成标准:
- 三后端输出一致
- 与已有 `camera_post_process_scene` / `post_process_scene` 不冲突
### Phase D: 测试与文档收口
目标:
- 补足 unit / integration coverage
- 把这一步与 future SRP 承接关系写回文档
完成标准:
- 计划可归档到 `docs/used`
## 9. 测试策略
至少覆盖:
- `components_tests`
- `rendering_unit_tests`
- 一条新的 `final_color_scene` 集成测试
- `camera_post_process_scene`
- `post_process_scene`
- 必要时 `skybox_scene`
新的 `final_color_scene` 必须验证:
- `FinalOutput` stage 真的参与了最终出图
- 输出 transfer / exposure 等策略真的生效
- D3D12 / OpenGL / Vulkan 三后端一致
## 10. 收口判定
满足下面条件时,本阶段可视为完成:
1. `FinalColorSettings / ResolvedFinalColorPolicy` 已正式建模
2. `FinalOutput` 已成为正式 runtime stage
3. `CameraPostProcessStack``FinalColorPipeline` 已彻底分层
4. pipeline defaults / camera override / future volume override 的职责边界已写死
5. future renderer feature / pass injection 点已在架构上预留
6. 至少一条正式 final color path 完成三后端闭环
7. 现有 rendering 主线测试不回退
## 11. 本阶段之后再做什么
等这一步完成后,后续 SRP 方向的推进顺序才合理:
1. 扩更多 builtin final color policy
2. 再做 renderer feature / custom fullscreen pass
3. 再做 volume 系统正式接入
4. 再做 C# 层对 pipeline/camera/feature 的承接
也就是说:
如果你的目标是最终做 Unity 风格 SRP
那这一阶段就是把 renderer 从“能出图”推进到“能作为 SRP 底座”的关键收口阶段。

View File

@@ -1,412 +0,0 @@
# Renderer 下一阶段Skybox 环境与 Frame Composition 正式化计划
日期:`2026-04-05`
## 1. 阶段定位
多光源 forward runtime 这一阶段已经闭环:
- `Directional / Point / Spot` 已接入正式 lighting contract
- `main directional shadow` 已保持稳定
- 三后端 lighting integration 已有完整回归矩阵
- Scene / Game View 已复用同一条 runtime renderer 主链
因此 renderer 主线现在不应该继续停留在“补光照地基”,而应该进入下一阶段:
**把当前 renderer 从“单次场景绘制”推进成“正式的相机帧合成框架”,先补齐 `Opaque -> Skybox -> Transparent -> PostProcess -> Final Output` 这条主链。**
这一步完成后rendering 主线才算真正具备继续承接:
- skybox / environment
- 正式后处理入口
- 更稳定的 camera output composition
- 后续 Unity 风格 renderer feature / C# SRP 对接
## 2. 为什么现在必须先做这个
当前 renderer 虽然已经能稳定画出 lit / unlit / shadow / object-id / editor overlay但它还不是完整的相机帧合成体系
- `BuiltinForwardPipeline` 目前本质上还是“一次场景遍历直接打到最终目标”
- 没有正式 `Skybox` 阶段
- 没有正式 `Environment` 数据入口
- 没有 runtime 级别的 `PostProcess` 输入 / 输出约定
- 还没有“只在需要时启用 intermediate color target”的相机合成策略
如果这个阶段不先做,后面不管是:
- 天空盒
- 环境贴图
- 曝光 / 色调映射
- 颜色调整
- 屏幕空间效果
都会继续以临时 pass 拼接的方式往上叠,最后会把当前已经比较干净的 renderer 主链重新拉乱。
## 3. 与 Unity / SRP 对齐的原则
这一阶段继续严格遵守当前工程的核心分层:
- `RHI` 只负责 GPU 抽象,不知道 skybox / environment / post-process 语义
- `Renderer` 负责相机帧规划、scene extraction、frame composition、runtime pass orchestration
- `Editor` 仍然只是 renderer 的宿主和 overlay 使用方
与 Unity 风格保持对齐时,本阶段遵守以下原则:
1. `Skybox / Environment / PostProcess` 都属于 runtime renderer 正式能力,不是 editor 特供逻辑
2. editor 的 grid / gizmo / icon / selection outline 不进入 runtime frame composition 主链
3. 不引入 `render graph`
4. 不直接跳到 deferred / clustered / HDRP 级复杂度
5. 先建立正式 `frame composition seam`,再谈更复杂的 renderer feature
## 4. 当前真实状态
### 4.1 已经具备的基础
- `CameraRenderer` 已有明确的请求装配入口
- `SceneRenderer -> CameraRenderer -> RenderPipeline` 主链稳定
- 已支持:
- `shadowCaster`
- `depthOnly`
- `main pipeline`
- `objectId`
- `overlayPasses`
- `RenderSceneExtractor` 已有稳定的:
- visible item 提取与排序
- main light / additional lights 提取
- `transparent_material_scene``depth_sort_scene``offscreen_scene` 已证明当前透明与离屏基础可用
### 4.2 还没正式化的缺口
- 没有 renderer 级 `Skybox` pass contract
- 没有 `RenderEnvironmentData`
- `BuiltinForwardPipeline` 还没有正式拆分成 `Opaque / Transparent`
- 没有“需要 post-process 时自动切到 intermediate color target”的约定
- 没有 runtime fullscreen pass 基础设施
- 没有证明 `Skybox + Transparent + PostProcess` 同时存在时仍然稳定的 integration coverage
## 5. 本阶段总目标
本阶段只做一件事:
**建立一条正式、稳定、三后端一致、可测试的 camera frame composition 主链。**
收口后应达到:
1. 场景绘制正式分为 `Opaque -> Skybox -> Transparent`
2. renderer 有正式 `Environment` 数据入口
3. renderer 有正式 `PostProcess` 输入 / 输出入口
4. 只在确实需要时才分配 intermediate color target
5. Scene / Game View 继续复用同一条 runtime frame composition 主链
6. 为后续 Unity 风格 renderer feature / C# SRP 留出清晰承接点
## 6. 非目标
本阶段明确不做:
- `render graph`
- deferred rendering
- clustered / tiled lighting
- IBL / reflection probe / light probe
- point / spot shadow
- 全量 post-process 套件
- 完整 HDR pipeline
- editor-only 视觉效果继续扩张
## 7. 设计方案
### 7.1 正式化 Camera Frame Composition
建议把相机级 runtime composition 明确写成固定阶段:
1. `shadowCaster`
2. `depthOnly`(按需求)
3. `opaque scene`
4. `skybox`
5. `transparent scene`
6. `post-process`
7. `final output resolve / blit`
8. `objectId`
9. `overlay`
关键原则:
- `objectId` 继续独立,不混入 runtime final color 主链
- `overlay` 继续是宿主级 / editor 级最后附加层
- runtime 的 `Skybox / PostProcess` 是相机帧的一部分,不应再伪装成 editor overlay
### 7.2 拆分 BuiltinForwardPipeline 的 scene 阶段
当前 `BuiltinForwardPipeline` 虽然能依赖 render queue 正确排序,但 skybox 正式接入后,必须让 runtime scene path 至少具备:
- `OpaquePass`
- `TransparentPass`
原因很直接:
- skybox 必须有正式插入点
- transparent 需要在 skybox 之后
- 以后 post-process 输入也需要明确“scene color 到哪里结束”
这里不需要推翻现有 forward lit / unlit 合约,只需要把当前单次遍历拆成正式两个阶段,并保持现有材质状态和排序行为不回退。
### 7.3 正式化 Environment 数据入口
建议新增 renderer 级环境数据模型,例如:
- `RenderEnvironmentData`
- `clearMode`
- `skyboxMaterial`
- `skyboxEnabled`
- 后续可扩展环境颜色 / 曝光 / cubemap 引用
第一版原则:
1. 先解决“环境如何进入 renderer”
2. 不在这一阶段强行上完整 IBL
3. 不把 environment 设计成 editor 专属状态
### 7.4 Skybox 首版策略
首版建议优先做 **builtin procedural skybox**,而不是一开始就把阶段拖进 cubemap / probe / importer 链路。
理由:
- 目标是先打通正式 `skybox pass`
- procedural skybox 更容易稳定三后端一致
- 更容易写 GT 和像素断言
- 不依赖 cubemap 资源导入闭环
首版可以支持:
- top / horizon / bottom color
- 视线方向驱动的渐变
后续再扩成 cubemap skybox不会推翻本阶段的 frame composition 设计。
### 7.5 Post-Process 正式入口的最小闭环
本阶段不追求“后处理功能多”,只追求“后处理入口正式化”。
建议最小闭环:
1. 建立 fullscreen pass 基础设施
2. 建立 `post-process source -> destination` 约定
3. 建立 intermediate color target 的按需分配策略
4. 用一个简单、稳定、三后端一致的 builtin fullscreen effect 做验证
验证 effect 不需要复杂,建议:
- `ColorTint`
- `GammaAdjust`
- `FinalCopy + optional color scale`
关键不是效果本身,而是证明:
- scene color 能被正式读回
- fullscreen pass 能稳定写到目标
- camera final output 路径已具备后续扩展能力
### 7.6 Intermediate Color Target 策略
不能把所有相机都默认改成“永远先画离屏再 blit”否则会徒增复杂度和性能成本。
建议规则:
- 默认直接渲染到最终目标
- 当存在 `Skybox / PostProcess / 特定 composition 需求` 时,按需启用 intermediate color target
- 这个判断应由 `CameraRenderer` 或 request planner 明确控制,而不是散落在具体 pass 内部
### 7.7 与 Unity 风格 SRP 的承接关系
这一阶段完成后renderer 主链会更接近 Unity/URP 的基本心智模型:
- scene opaque
- skybox
- transparent
- post-process
- final target
这一步不是为了机械模仿 Unity而是为了给以后 C# 层 SRP / renderer feature 建立正确的宿主结构。
## 8. 实施分阶段
## 8.1 Phase AFrame Composition 合约正式化
### 目标
把相机级帧合成顺序从“隐式拼接”改成正式 contract。
### 工作项
- 明确 runtime frame composition 阶段枚举 / 顺序
- 调整 `CameraRenderer` 的 orchestration 结构
- 明确 `objectId``overlay` 与 runtime frame composition 的边界
### 验收标准
- 相机帧阶段顺序明确且可追踪
- 现有 `multi_light / transparent / offscreen` 不回退
## 8.2 Phase BOpaque / Skybox / Transparent 正式分段
### 目标
让 builtin forward runtime scene path 具备正式 `Opaque / Transparent` 结构,并为 skybox 提供插入点。
### 工作项
- 拆分 `BuiltinForwardPipeline`
- 保持现有 render queue 语义
- 保持透明排序与材质状态回归不破坏
### 验收标准
- `transparent_material_scene`
- `depth_sort_scene`
- `material_state_scene`
三后端继续通过
## 8.3 Phase CSkybox / Environment 首版闭环
### 目标
让 renderer 正式支持 runtime skybox。
### 工作项
- 新增 `RenderEnvironmentData`
- 新增 builtin procedural skybox pass / shader
- 将 skybox 接入 camera frame composition
- 保持 clear color fallback 行为可控
### 验收标准
- 新增 `skybox_scene`
- 同时存在 opaque + skybox + transparent 时顺序正确
- 三后端 GT 稳定
## 8.4 Phase DPost-Process 入口闭环
### 目标
建立正式 fullscreen post-process 入口,而不是继续依赖临时 pass。
### 工作项
- fullscreen pass helper
- intermediate color target 按需分配
- final blit / resolve 规则
- 一个最小 builtin post-process 验证效果
### 验收标准
- 新增 `post_process_scene`
- `offscreen_scene` 不回退
- 三后端 GT 稳定
## 8.5 Phase E测试与文档收口
### 目标
让本阶段收口后,`docs/plan` 的主线入口与真实实现再次一致。
### 工作项
- 更新 `tests/TEST_SPEC.md`
- 输出 renderer frame composition 阶段说明
- 将本阶段完成计划归档到 `docs/used`
### 验收标准
- 文档、实现、测试矩阵三者口径一致
## 9. 测试策略
### 9.1 Unit
- frame composition 阶段决策
- intermediate target 启用条件
- skybox / post-process request 装配
### 9.2 Integration
新增:
- `skybox_scene`
- `post_process_scene`
回归:
- `multi_light_scene`
- `spot_light_scene`
- `directional_shadow_scene`
- `camera_stack_scene`
- `transparent_material_scene`
- `cull_material_scene`
- `depth_sort_scene`
- `material_state_scene`
- `offscreen_scene`
### 9.3 Editor Runtime Smoke
- SceneView / GameView 继续复用同一条 runtime frame composition
- object-id picking 不因 frame composition 改造回退
- editor overlay 不污染 runtime skybox / post-process
## 10. 风险与控制
### 风险 1为了接 skybox 强行把所有相机都改成离屏
后果:
- 复杂度和成本无意义上升
- 调试链路变长
控制策略:
- intermediate target 只按需启用
### 风险 2skybox 设计一开始就绑死 cubemap / IBL
后果:
- 阶段再次失焦
- 资源链路耦合过早
控制策略:
- 首版先做 builtin procedural skybox
### 风险 3post-process 入口继续走 editor 旧路径
后果:
- runtime / editor 边界重新混乱
控制策略:
- runtime post-process 必须是 renderer 正式阶段
- editor overlay 继续留在最后
## 11. 阶段完成判定
满足以下条件时,本阶段可视为收口:
1. renderer 具备正式 `Opaque -> Skybox -> Transparent -> PostProcess -> Final Output` 结构
2. skybox 有正式 runtime 数据入口与首版实现
3. post-process 有正式 fullscreen 入口与最小闭环
4. `skybox_scene``post_process_scene` 三后端通过
5. 现有 lighting / transparency / offscreen / camera stack 回归不破坏
## 12. 本阶段之后的正确下一步
当这一步收口后renderer 主线的下一阶段才应该考虑:
1. cubemap skybox / environment map
2. 曝光 / tone mapping / color grading 正式化
3. 更高阶的 renderer feature / C# SRP 承接层
而不是现在就跳去:
- `render graph`
- deferred
- editor-only 特效堆叠

View File

@@ -1,296 +0,0 @@
# 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 与后处理能力
也就是说,**现在下一步不是做更多“效果”,而是先把相机输出主链做完整。**