Formalize imported mesh materials
This commit is contained in:
523
docs/plan/Renderer阶段收口_旧兼容路径清理与正式化计划_2026-04-08.md
Normal file
523
docs/plan/Renderer阶段收口_旧兼容路径清理与正式化计划_2026-04-08.md
Normal file
@@ -0,0 +1,523 @@
|
||||
# Renderer阶段收口:旧兼容路径清理与正式化计划
|
||||
|
||||
日期:`2026-04-08`
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前 `Rendering` 模块的主执行架构已经基本成型:
|
||||
|
||||
- `RenderSceneExtractor`
|
||||
- `SceneRenderRequestPlanner`
|
||||
- `SceneRenderer / CameraRenderer`
|
||||
- built-in forward / shadow / object-id / outline / final-color / skybox
|
||||
|
||||
这些主链路已经能稳定支撑:
|
||||
|
||||
- runtime 场景渲染
|
||||
- editor scene/game viewport
|
||||
- 多光源、阴影、object-id、outline、skybox 等现有能力
|
||||
|
||||
因此,当前 Rendering 的主要问题已经不再是“能不能画出来”,而是:
|
||||
|
||||
- 还残留一些旧路线兼容代码
|
||||
- 一些 built-in 运行契约仍然依赖隐式推断
|
||||
- 少量路径仍然带有明显的过渡期实现痕迹
|
||||
|
||||
如果这些问题不在当前阶段彻底收口,后续继续推进:
|
||||
|
||||
- Renderer 模块扩展
|
||||
- Material / Shader editor
|
||||
- Unity 风格 SRP 底层承接
|
||||
|
||||
就会持续建立在一层“虽然能跑,但不是正式规则”的兼容逻辑之上。
|
||||
|
||||
这不符合当前阶段的目标。
|
||||
|
||||
当前阶段的正确方向不是新增更多渲染功能,而是:
|
||||
|
||||
- 清理旧兼容路径
|
||||
- 去掉运行时语义猜测
|
||||
- 把 built-in shader / material / pass contract 进一步正式化
|
||||
|
||||
---
|
||||
|
||||
## 2. 当前已确认的问题
|
||||
|
||||
基于本轮对 `engine/include/XCEngine/Rendering`、`engine/src/Rendering`、`engine/src/Resources/Shader`、`engine/src/Resources/Mesh` 的代码审查,当前确认存在以下问题。
|
||||
|
||||
### 2.1 Mesh 导入仍可生成“无 shader / 无 schema”的旧材质路线
|
||||
|
||||
当前 `MeshLoader` 导入子材质时,仍然直接写入:
|
||||
|
||||
- `baseColor`
|
||||
- `baseColorTexture`
|
||||
- `opacity`
|
||||
- `twoSided`
|
||||
|
||||
而不是直接落到正式 shader schema 对应的属性名与纹理槽位。
|
||||
|
||||
这导致 runtime 渲染阶段仍然需要兜底兼容这些旧名字。
|
||||
|
||||
典型位置:
|
||||
|
||||
- `engine/src/Resources/Mesh/MeshLoader.cpp`
|
||||
- `engine/include/XCEngine/Rendering/Materials/RenderMaterialResolve.h`
|
||||
|
||||
### 2.2 Rendering 仍通过属性别名表推断 built-in 材质语义
|
||||
|
||||
当前 `RenderMaterialResolve.h` 中,仍然保留了大量 builtin 属性/纹理别名表,例如:
|
||||
|
||||
- `baseColor`
|
||||
- `_BaseColor`
|
||||
- `color`
|
||||
- `_Color`
|
||||
- `baseColorTexture`
|
||||
- `_BaseColorTexture`
|
||||
- `_MainTex`
|
||||
- `texture`
|
||||
|
||||
这意味着 runtime 当前并不是“按 shader schema 正式解析”,而是:
|
||||
|
||||
- 优先找 semantic
|
||||
- 找不到就继续按一批旧属性名字猜
|
||||
|
||||
这属于典型过渡兼容逻辑,不应成为正式长期实现。
|
||||
|
||||
### 2.3 BuiltinForward / Depth / Shadow 仍存在 per-material fallback constant 路线
|
||||
|
||||
当前如果材质没有正式 schema constant layout,管线仍会临时构造:
|
||||
|
||||
- `FallbackPerMaterialConstants`
|
||||
|
||||
并继续提交 draw。
|
||||
|
||||
这说明 runtime 仍允许“非正式材质实例”继续进入正式绘制链路。
|
||||
|
||||
这条路径虽然提高了兼容性,但本质上绕开了已经建立的 shader/material 正式模型。
|
||||
|
||||
### 2.4 Built-in pass resource binding 仍依赖隐式硬编码
|
||||
|
||||
当前 builtin shader pass 如果未显式声明 `resources`,运行时仍会通过:
|
||||
|
||||
- `TryBuildImplicitBuiltinPassResourceBindings`
|
||||
|
||||
自动补一套绑定布局。
|
||||
|
||||
这意味着资源绑定契约并不完全存在于 shader 资产中,而是仍有一部分硬编码在 C++ 中。
|
||||
|
||||
这会带来两个问题:
|
||||
|
||||
1. shader 资产与 runtime 存在双份真相
|
||||
2. 后续继续演进 shader/material/editor 时,容易再次产生隐式规则
|
||||
|
||||
### 2.5 HLSL register 重写仍保留 legacy alias
|
||||
|
||||
当前 `ShaderVariantUtils.h` 仍保留:
|
||||
|
||||
- `ResolveLegacyHlslBindingDeclarationAlias`
|
||||
|
||||
以及基于 `gBaseColorTexture` / `gLinearSampler` 一类旧命名的重写逻辑。
|
||||
|
||||
这说明 shader runtime 编译阶段仍在兼容旧命名风格。
|
||||
|
||||
这属于典型“过渡兼容层”,应在 built-in shader 显式资源契约完成后清掉。
|
||||
|
||||
### 2.6 Built-in pass 选择仍存在隐式默认规则
|
||||
|
||||
当前如果 shader 没有显式 builtin metadata,`MatchesBuiltinPass(...)` 仍会把它默认当成:
|
||||
|
||||
- `ForwardLit`
|
||||
|
||||
这意味着 shader 即使没有明确声明自己属于哪个 built-in pass,也有可能继续进入主几何管线。
|
||||
|
||||
这不利于长期正式化。
|
||||
|
||||
### 2.7 Shader artifact 仍兼容多代旧 schema
|
||||
|
||||
当前 shader artifact loader 仍兼容:
|
||||
|
||||
- `XCSHD01`
|
||||
- `XCSHD02`
|
||||
- `XCSHD03`
|
||||
- `XCSHD04`
|
||||
- 当前 schema
|
||||
|
||||
但 shader artifact 本质上是 `Library` 中的可重建中间产物,不属于必须长期 runtime 兼容的用户资产格式。
|
||||
|
||||
如果继续保留多代 schema 分支,会让 shader 资源链路长期背着历史包袱。
|
||||
|
||||
---
|
||||
|
||||
## 3. 本阶段设计原则
|
||||
|
||||
本计划执行时,必须严格遵守以下原则。
|
||||
|
||||
### 3.1 正式路径只能有一条
|
||||
|
||||
对 built-in shader / material / pass 来说,正式路径必须是:
|
||||
|
||||
`导入/authoring -> shader schema -> material instance -> explicit pass contract -> render pipeline`
|
||||
|
||||
不能继续允许 runtime 依赖旧命名、旧别名、旧格式去自动猜测。
|
||||
|
||||
### 3.2 兼容应尽量前移到导入/重建阶段,而不是留在 runtime
|
||||
|
||||
如果确实存在历史资产问题,应优先采用:
|
||||
|
||||
- 重新导入
|
||||
- 重新生成 artifact
|
||||
- 一次性迁移
|
||||
|
||||
而不是继续在 runtime loader / renderer 中保留长期兼容分支。
|
||||
|
||||
### 3.3 Built-in shader 契约必须显式写进 shader 资产
|
||||
|
||||
以下内容必须属于 shader/pass 资产本身,而不是 runtime 猜出来:
|
||||
|
||||
- pass 类型
|
||||
- pass metadata
|
||||
- resource binding
|
||||
- property semantic
|
||||
|
||||
### 3.4 Rendering 不再为“无正式 shader/schema 的材质”兜底渲染
|
||||
|
||||
当前阶段的目标是“收口”,不是“继续最大化兼容”。
|
||||
|
||||
因此:
|
||||
|
||||
- 非正式材质应尽快在导入层修正
|
||||
- runtime 应逐步拒绝无 schema 的正式绘制路径
|
||||
|
||||
### 3.5 每一步都必须可验证
|
||||
|
||||
每个阶段完成后必须配套:
|
||||
|
||||
- unit test
|
||||
- 必要的 integration test
|
||||
- editor 编译/回归
|
||||
|
||||
不能只凭画面“看起来没问题”判断完成。
|
||||
|
||||
---
|
||||
|
||||
## 4. 本阶段目标
|
||||
|
||||
本阶段完成后,Rendering 模块应达到以下状态:
|
||||
|
||||
1. Mesh 导入出来的材质直接走正式 shader/material 体系
|
||||
2. runtime 不再依赖 `baseColor` / `_MainTex` 等别名表去维持 built-in 主链
|
||||
3. built-in pass resource binding 由 shader 资产显式声明,不再依赖隐式硬编码补全
|
||||
4. built-in pass 分类必须显式声明,不再存在“默认 ForwardLit”
|
||||
5. shader artifact runtime loader 不再长期兼容多代旧 schema
|
||||
6. 对应测试体系同步升级,保证收口后功能不回退
|
||||
|
||||
---
|
||||
|
||||
## 5. 明确不在本阶段处理的内容
|
||||
|
||||
以下内容不属于本阶段目标:
|
||||
|
||||
- render graph
|
||||
- deferred renderer
|
||||
- 新一轮后处理功能扩展
|
||||
- C# SRP 脚本侧 API
|
||||
- ShaderGraph
|
||||
- 高级材质编辑器功能扩展
|
||||
|
||||
这些方向都依赖本阶段先把底层 contract 收紧。
|
||||
|
||||
---
|
||||
|
||||
## 6. 分阶段执行计划
|
||||
|
||||
## Phase 1:建立基线与目标测试
|
||||
|
||||
### 目标
|
||||
|
||||
先把当前遗留兼容路径的行为边界用测试钉住,并同步写出“目标行为”的新测试。
|
||||
|
||||
### 任务
|
||||
|
||||
- 审查并整理当前覆盖以下行为的测试:
|
||||
- `RenderMaterialResolve`
|
||||
- builtin forward pipeline resource binding
|
||||
- mesh material import
|
||||
- shader artifact load
|
||||
- 新增/调整测试,使其明确区分:
|
||||
- 当前历史兼容行为
|
||||
- 本阶段目标正式行为
|
||||
- 对以下目标先写失败测试或待切换测试:
|
||||
- imported mesh material 必须绑定正式 builtin shader
|
||||
- imported material property 必须落到正式 schema 名称
|
||||
- builtin pass 若无显式 metadata,不得进入主 pipeline
|
||||
- builtin shader 若无显式 resources,不得依赖隐式 binding 补全
|
||||
|
||||
### 验收标准
|
||||
|
||||
- 能清楚列出哪些测试在保护旧行为,哪些测试在保护目标行为
|
||||
- 后续每个阶段都能基于这些测试判断是否真正收口
|
||||
|
||||
---
|
||||
|
||||
## Phase 2:收口 Mesh 导入材质到正式 shader/material 路径
|
||||
|
||||
### 目标
|
||||
|
||||
彻底去掉 imported mesh material 的“无 shader / 裸属性名”旧路线。
|
||||
|
||||
### 任务
|
||||
|
||||
- 调整 `MeshLoader` 导入逻辑:
|
||||
- imported material 直接绑定正式 builtin shader
|
||||
- 默认按现有主线落到 builtin lit/forward 合同
|
||||
- 导入属性与纹理时,直接写正式 property name / texture slot:
|
||||
- 例如 `_BaseColor`
|
||||
- `_MainTex`
|
||||
- `_Cutoff`
|
||||
- 其他已正式声明的 builtin 属性
|
||||
- 不再向 imported material 写入仅靠 runtime 别名识别的裸字段:
|
||||
- `baseColor`
|
||||
- `baseColorTexture`
|
||||
- `color`
|
||||
- `texture`
|
||||
- 更新 mesh import 相关测试、render extractor 测试、相关 integration 资源测试
|
||||
|
||||
### 验收标准
|
||||
|
||||
- mesh import 结果中的材质都带有正式 shader 引用
|
||||
- mesh import 结果中的属性/纹理绑定名称与 shader schema 对齐
|
||||
- 不再需要 runtime 靠旧别名才能让导入材质正常渲染
|
||||
|
||||
---
|
||||
|
||||
## Phase 3:移除 runtime builtin 材质语义别名与 fallback 常量路径
|
||||
|
||||
### 目标
|
||||
|
||||
让 built-in pipeline 只吃正式 schema 材质,不再继续兼容旧材质命名。
|
||||
|
||||
### 任务
|
||||
|
||||
- 清理 `RenderMaterialResolve.h` 中的旧别名解析表:
|
||||
- base color property alias
|
||||
- base texture alias
|
||||
- skybox texture alias
|
||||
- alpha cutoff alias
|
||||
- 保留并强化基于 `shader property semantic` 的正式解析路径
|
||||
- 移除 `FallbackPerMaterialConstants` 路线
|
||||
- 当材质未携带正式 schema constant layout 时:
|
||||
- 显式报错 / 记录诊断
|
||||
- 拒绝进入需要正式材质常量的绘制路径
|
||||
- 调整 forward / depth / shadow / skybox 相关单测
|
||||
|
||||
### 验收标准
|
||||
|
||||
- builtin pipeline 不再依赖属性别名表维持主链
|
||||
- builtin pipeline 不再手工构造 per-material fallback constant 继续绘制
|
||||
- runtime 只接受正式 shader/material 契约
|
||||
|
||||
---
|
||||
|
||||
## Phase 4:显式化 builtin pass resource binding contract
|
||||
|
||||
### 目标
|
||||
|
||||
让 builtin shader pass 的资源绑定契约完全存在于 shader 资产中,而不是藏在 runtime 硬编码里。
|
||||
|
||||
### 任务
|
||||
|
||||
- 为所有 builtin shader pass 补齐显式 `resources` 描述
|
||||
- 覆盖至少以下 shader:
|
||||
- `forward-lit.shader`
|
||||
- `depth-only.shader`
|
||||
- `shadow-caster.shader`
|
||||
- `object-id.shader`
|
||||
- `skybox.shader`
|
||||
- `final-color.shader`
|
||||
- 其他当前仍在主链中的 builtin shader
|
||||
- 清理 `TryBuildImplicitBuiltinPassResourceBindings`
|
||||
- 清理 `ShaderVariantUtils.h` 中围绕 implicit/legacy binding 的兼容逻辑:
|
||||
- legacy alias register rewrite
|
||||
- 依赖 `gXxx` 名称重写的分支
|
||||
- 调整 shader loader / rendering pipeline / builtin pass 单测
|
||||
|
||||
### 验收标准
|
||||
|
||||
- builtin shader pass 缺少显式资源绑定时,构建或运行应明确失败
|
||||
- runtime 不再替 shader 资产自动补 binding layout
|
||||
- HLSL runtime 编译不再依赖 legacy alias register 重写
|
||||
|
||||
---
|
||||
|
||||
## Phase 5:显式化 builtin pass metadata 与 pass 选择规则
|
||||
|
||||
### 目标
|
||||
|
||||
去掉“默认 ForwardLit”一类隐式 pass 归类规则。
|
||||
|
||||
### 任务
|
||||
|
||||
- 收紧 `BuiltinPassMetadataUtils`:
|
||||
- built-in pass 匹配必须依赖显式 pass name / tag
|
||||
- 删除“无 metadata 默认归 ForwardLit”的逻辑
|
||||
- 审查并统一 builtin shader 的 pass metadata:
|
||||
- `Name`
|
||||
- `LightMode`
|
||||
- 其它当前正式要求的 tag
|
||||
- 对进入 builtin 主线的 shader 建立硬约束:
|
||||
- 没有显式 builtin metadata 的 shader,不得继续被当作主几何 shader 使用
|
||||
- 更新 pass 匹配测试和 shader authoring 测试
|
||||
|
||||
### 验收标准
|
||||
|
||||
- builtin pass 选择全部基于显式 metadata
|
||||
- 不存在 runtime 默认猜一个 pass 类型的行为
|
||||
|
||||
---
|
||||
|
||||
## Phase 6:清理旧 shader artifact schema 兼容
|
||||
|
||||
### 目标
|
||||
|
||||
让 shader artifact runtime loader 与 material artifact 一样,收口到 current schema。
|
||||
|
||||
### 任务
|
||||
|
||||
- 清理 `ShaderArtifactLoader.cpp` 中对旧 schema 的分支兼容:
|
||||
- `XCSHD01`
|
||||
- `XCSHD02`
|
||||
- `XCSHD03`
|
||||
- `XCSHD04`
|
||||
- 将旧 `Library` artifact 的处理方式改为:
|
||||
- 识别为过期
|
||||
- 触发重新导入 / 重新生成
|
||||
- 或直接报错要求重建 `Library`
|
||||
- 更新 asset database / shader load 相关测试
|
||||
- 明确记录此阶段会带来的影响:
|
||||
- 旧 `Library` 无法直接沿用
|
||||
- 需要一次性刷新或重建
|
||||
|
||||
### 验收标准
|
||||
|
||||
- shader artifact loader 只接受 current schema
|
||||
- 对旧 artifact 的处理边界清晰且可测试
|
||||
|
||||
---
|
||||
|
||||
## Phase 7:全量验证与阶段收口
|
||||
|
||||
### 目标
|
||||
|
||||
确认 Rendering 在去掉旧兼容层之后没有破坏现有功能。
|
||||
|
||||
### 任务
|
||||
|
||||
- 编译并运行:
|
||||
- `material_tests`
|
||||
- `rendering_unit_tests`
|
||||
- `asset_tests`
|
||||
- `editor_tests`
|
||||
- 受影响的 mesh/shader 资源测试
|
||||
- 重新编译 `XCEditor`
|
||||
- 重点回归:
|
||||
- scene viewport
|
||||
- game viewport
|
||||
- object-id picking
|
||||
- selection outline
|
||||
- skybox
|
||||
- 阴影
|
||||
- 多光源
|
||||
- backpack / sphere / quad 等 integration scene
|
||||
- 形成阶段收口报告
|
||||
|
||||
### 验收标准
|
||||
|
||||
- 所有直接相关测试通过
|
||||
- editor 编译通过
|
||||
- 关键 integration scene 渲染行为不回退
|
||||
- 能明确宣告 runtime 旧兼容路径已移除
|
||||
|
||||
---
|
||||
|
||||
## 7. 风险与注意事项
|
||||
|
||||
### 7.1 这是一次“切正式路径”的收口,不是小修小补
|
||||
|
||||
本计划一旦执行,就会主动删除一部分兼容逻辑。
|
||||
|
||||
因此不能以“尽量少改代码”为目标,而应以:
|
||||
|
||||
- 正式路径唯一
|
||||
- contract 清晰
|
||||
- 后续 SRP 可承接
|
||||
|
||||
为目标。
|
||||
|
||||
### 7.2 `Library` 重建属于预期影响
|
||||
|
||||
一旦收掉旧 shader artifact schema 兼容,旧 `Library` 里的 shader artifact 失效是正常现象。
|
||||
|
||||
这不应被视为回归,而应被视为阶段性收口的合理代价。
|
||||
|
||||
### 7.3 必须避免引入新的“临时兼容层”
|
||||
|
||||
执行过程中需要特别警惕以下错误做法:
|
||||
|
||||
- 新加一层 alias 表,试图“先兼容一下”
|
||||
- 把 runtime fallback 换个名字继续保留
|
||||
- 在 editor 或 import 层再次引入一套过渡数据模型
|
||||
|
||||
如果遇到结构性问题,正确做法是:
|
||||
|
||||
- 直接改到正式模型
|
||||
- 同步补测试
|
||||
|
||||
而不是再加一层短期兜底。
|
||||
|
||||
---
|
||||
|
||||
## 8. 建议执行顺序
|
||||
|
||||
建议严格按以下顺序推进:
|
||||
|
||||
1. `Phase 1` 测试基线整理
|
||||
2. `Phase 2` mesh 导入材质正式化
|
||||
3. `Phase 3` runtime 材质别名与 fallback 常量清理
|
||||
4. `Phase 4` builtin pass 显式资源绑定
|
||||
5. `Phase 5` builtin pass metadata 显式化
|
||||
6. `Phase 6` shader artifact schema 收口
|
||||
7. `Phase 7` 全量验证
|
||||
|
||||
原因是:
|
||||
|
||||
- 如果不先把 imported material 拉回正式路径
|
||||
- 后面的 runtime alias / fallback 清理就一定会打断现有资源链路
|
||||
|
||||
---
|
||||
|
||||
## 9. 本阶段完成后的预期状态
|
||||
|
||||
本计划完成后,Rendering 模块应达到以下状态:
|
||||
|
||||
1. built-in shader/material/pass contract 全部走正式显式路径
|
||||
2. runtime 不再依赖旧命名猜测材质语义
|
||||
3. runtime 不再替非正式材质拼接 fallback 常量布局
|
||||
4. builtin shader 资源绑定契约完全由 shader 资产声明
|
||||
5. builtin pass 类型选择完全依赖显式 metadata
|
||||
6. shader artifact runtime loader 不再背负旧 schema 包袱
|
||||
7. 整个 Rendering 模块更适合作为后续 Unity 风格 SRP 的底层承接
|
||||
|
||||
---
|
||||
|
||||
## 10. 一句话总结
|
||||
|
||||
当前 Rendering 真正需要的不是继续加功能,而是把残留的旧兼容路径彻底拔干净。
|
||||
|
||||
这一阶段的本质,是把:
|
||||
|
||||
- imported material
|
||||
- built-in shader binding
|
||||
- pass metadata
|
||||
- shader artifact
|
||||
|
||||
全部拉回到同一套正式 contract 上,为后续 Renderer / Material / Shader / SRP 的继续推进打地基。
|
||||
Reference in New Issue
Block a user