docs: audit material inspector shader property plan

This commit is contained in:
2026-04-07 21:26:52 +08:00
parent fe00aa1305
commit 253d6bbf85

View File

@@ -0,0 +1,387 @@
# Material Inspector与Shader属性面板收口计划
日期2026-04-07
## 1. 背景
当前 Rendering / Shader / Material 主线已经基本建立起正式架构:
- Shader 侧已经具备统一的 authoring/schema 能力。
- Material 运行时与 artifact 路径已经逐步从旧兼容逻辑中收口。
- Editor 中的 Material Inspector 仍然没有完全切换到“由 Shader schema 驱动”的正式工作流。
当前最突出的实际问题有两类:
1. Material 选择 Shader 后Shader 中声明的属性没有被正式暴露到 Inspector 面板上。
2. Material 面板上还残留了一些历史字段或临时 UI用户无法清晰判断哪些是正式能力哪些只是过渡产物。
此外,当前工程条件已经允许做更彻底的清理:
- `project/` 中旧材质资产可直接编辑。
- 当前不存在必须长期兼容的历史材质资产包袱。
因此,这一阶段的目标不是“继续兼容旧面板”,而是把 Material 编辑链路彻底切换到正式路径,并为后续 Shader/Material 编辑器扩展打好基础。
## 2. 本阶段目标
本阶段要完成以下目标:
1. 让 Material Inspector 成为 Shader schema 驱动的正式编辑入口。
2. 让材质面板只暴露当前正式架构中的概念,不再混入旧字段和误导性配置。
3. 保证 Editor 面板、运行时 `Material`、源资产、artifact、reimport 之间的数据一致性。
4. 用单测和必要的编辑器验证把这条链路收口,而不是停留在“能显示”层面。
## 3. 不在本阶段处理的内容
以下内容不属于本阶段主目标,避免范围失控:
- 自定义 Material Drawer 系统。
- Shader Graph / 节点式材质编辑器。
- 面向美术工作流的复杂 Material 预设库。
- SRP 层级的材质检查器定制机制。
- 完整的 Shader GUI 仿 Unity 高级扩展体系。
这些能力后续可以做,但必须建立在当前正式链路已经稳定收口的前提上。
## 4. 当前已确认的问题
### 4.1 Inspector 没有正式反射 Shader 属性
当前 Material Inspector 还没有完整读取 Shader schema 并按类型生成属性控件,导致:
- Shader 中声明的属性无法完整暴露。
- 用户无法直接编辑当前材质真正生效的参数。
- 材质默认值、覆盖值、纹理槽与资源引用状态之间关系不清晰。
### 4.2 材质面板仍存在历史路径残留
之前材质层面曾承担过一些本不应由材质承担的职责,例如:
- 材质自己选择 builtin pass。
- Inspector 里出现与当前正式架构不一致的旧字段。
这类逻辑已经开始清理,但 Editor 面板仍需同步彻底收口。
### 4.3 Editor 与运行时 Material 状态可能脱节
如果面板的编辑状态不是直接围绕正式 `Material` 数据模型建立,就容易出现:
- Inspector 显示值与运行时实际值不一致。
- 资源重载后 UI 状态失真。
- artifact / reimport 后材质参数丢失或回退异常。
### 4.4 缺少围绕正式工作流的测试闭环
仅靠手工点 Inspector 验证不足以支撑后续迭代。必须补足以下覆盖:
- Shader 切换后属性集合重建。
- 默认值与显式覆盖值的切换。
- Texture 属性与资源引用链路。
- Keyword 与 Render State 的持久化。
- artifact/reimport 后数据一致性。
## 5. 设计原则
本阶段严格遵循以下原则:
### 5.1 Shader 定义什么Material 就暴露什么
Material 不是独立定义属性结构的地方。属性结构必须由 Shader schema 决定Inspector 只是将其可视化并允许编辑。
### 5.2 Material 只承载实例数据,不承载管线选择策略
材质应承载:
- Shader 引用
- Shader schema 对应的属性值
- Keyword 状态
- 合法的 render state 覆盖
材质不应再承载:
- 独立指定 builtin pass 的旧路径
- 与 Shader metadata 冲突的临时策略字段
### 5.3 Editor 不发明第二套数据模型
Inspector 的中间态必须服务于正式数据模型,而不是绕开 `Material` 自己维护一套平行逻辑。
### 5.4 面板必须可验证
每一步改动都必须能通过测试或明确的编辑器验证闭环证明正确,不接受只靠目测“看起来差不多”。
## 6. 分阶段执行计划
## Phase 1现状审查与残留路径清点
### 目标
彻底梳理当前 Material Inspector、Material 资源、Shader schema、artifact 序列化之间的实际数据流。
### 任务
- 审查 `InspectorPanel` 当前 Material 面板的数据来源和写回路径。
- 审查 `Material` 当前正式字段与历史遗留字段。
- 审查 `MaterialLoader``AssetDatabase`、artifact schema 当前是否仍保留不必要兼容路径。
- 识别 Material 面板中哪些字段是正式路径,哪些属于旧方案残留。
### 完成标准
- 列清楚当前正式数据流。
- 列清楚必须删除的旧字段/旧 UI。
- 列清楚缺失的 schema 反射入口。
## Phase 2Material Inspector 数据模型收口
### 目标
让 Material 面板的数据模型只围绕正式架构组织。
### 任务
- 移除 Material 层面的旧 pass 选择 UI 与残余兼容路径。
- 整理 Inspector 内部状态结构,只保留:
- Shader 资源引用
- Shader schema 对应属性
- Keywords
- Render Queue / Render State
- Tags仅保留当前正式允许暴露的部分
- 避免 Inspector 保存与运行时 `Material` 不一致的冗余字段。
### 完成标准
- 面板字段与正式 `Material` 模型一一对应。
- 旧字段彻底不再出现在材质编辑界面和保存链路中。
## Phase 3Shader schema 驱动的属性面板生成
### 目标
Material Inspector 能基于 Shader schema 动态生成属性编辑 UI。
### 任务
- 读取 Shader 声明的属性定义与默认值。
- 按属性类型渲染控件:
- `float`
- `int`
- `bool`
- `float2/3/4`
- `texture`
- 正确显示每个属性的:
- 属性名
- 显示名
- 默认值
- 当前覆盖值
- 纹理槽绑定状态
- 资源引用路径/AssetRef 状态
- 明确“未覆盖时使用 Shader 默认值”的表现形式。
### 完成标准
- 选定 Shader 后Inspector 中能稳定暴露该 Shader 的正式属性集合。
- 面板能正确编辑并持久化这些属性。
## Phase 4Editor 与运行时一致性收口
### 目标
保证 Material Inspector 编辑结果与运行时 `Material`、artifact、reimport 行为一致。
### 任务
- 对齐 Inspector 写回逻辑与 `Material` 正式 API。
- 验证 Shader 切换时属性重建、默认值回退、无效属性清理。
- 验证纹理属性在源资产、artifact、异步资源加载中的一致性。
- 验证关键词与 render state 在 reload/reimport 后不丢失。
### 完成标准
- Inspector 改动能被运行时正确读取。
- Reload / Reimport / Artifact Round Trip 后材质数据不漂移。
## Phase 5测试补齐与阶段验收
### 目标
为正式工作流建立可持续回归验证。
### 任务
- 补充或更新 `material_tests`
- 补充或更新 `asset_tests`
- 若材质解析或 builtin pass 匹配受影响,补充必要的 `rendering_unit_tests`
- 重新编译 `XCEditor`,执行人工冒烟验证。
### 验收项
- `material_tests` 全绿。
- `asset_tests` 全绿。
- 必要的 `rendering_unit_tests` 全绿。
- `XCEditor` 编译通过。
- Material Inspector 中 Shader 属性暴露、编辑、保存、重载行为正确。
## 7. 预期交付结果
本阶段完成后,工程应达到以下状态:
1. Material 面板正式切换为 Shader schema 驱动。
2. 材质不再承担旧 pass 选择职责。
3. Inspector 中只剩下当前正式架构允许存在的字段。
4. 材质属性、纹理槽、关键词、render state 都能稳定编辑并正确持久化。
5. Shader / Material 后续扩展拥有清晰入口,不再建立在旧兼容逻辑之上。
## 8. 风险与注意事项
### 8.1 Shader 切换会触发属性重建
必须定义清楚以下规则:
- 与新 Shader schema 匹配的属性如何保留。
- 不匹配的旧属性如何移除。
- 默认值何时回退,何时保留用户覆盖。
### 8.2 Texture 属性不仅是 UI 问题
Texture 属性同时涉及:
- Inspector 显示
- AssetRef
- 资源路径
- artifact 存储
- 延迟加载
因此不能只改面板显示,必须连同资源路径一起验证。
### 8.3 Render State 需要坚持“正式最小集”
Material 面板不应再次演化成随意堆字段的临时入口。所有 render state 暴露都必须建立在当前正式支持的能力之上。
## 9. 建议执行顺序
建议严格按以下顺序落地:
1. 先完成旧字段与旧路径清点。
2. 再重构 Inspector 数据模型。
3. 再接 Shader schema 驱动属性 UI。
4. 再收口 Editor 与运行时一致性。
5. 最后统一补测与验收。
不能反过来先堆 UI再回头补数据模型否则很容易再次生成新的临时方案。
## 10. 阶段结论
当前最应该推进的不是继续增加 Material 编辑功能花样,而是把 Material Inspector 这条正式链路做对、做稳、做干净。
只要这一阶段收口完成,后续无论是:
- 更完整的 Shader authoring
- Material 默认面板
- 针对 Renderer/SRP 的材质体系扩展
- 更接近 Unity 的 Shader/Material 编辑工作流
都会建立在清晰、稳定、可验证的基础之上。
## 11. Phase 1 审查结果
状态:已完成
本阶段已对当前 Material Inspector、运行时 `Material`、Shader schema、material source/artifact 路径进行了实际代码审查,结论如下。
### 11.1 当前 Inspector 数据模型先天不完整
当前 `InspectorPanel::MaterialAssetState` 只维护了以下内容:
- `shaderPath`
- `renderQueue`
- `renderState`
- `tags`
它没有正式承载以下关键数据:
- Shader schema 属性列表
- 材质属性当前值
- 纹理槽与贴图引用
- 关键词状态
- Render State Override 开关本身
这意味着当前 Inspector 不是“少画了几个控件”,而是其内部状态模型本身就无法表示正式的材质编辑数据。
### 11.2 当前 Inspector 保存链路会丢失材质的正式内容
当前 `BuildMaterialAssetFileText()` 仅写出:
- `shader`
- `renderQueue`
- `tags`
- `renderState`
它不会写出:
- `properties`
- `textures`
- `keywords`
因此,只要一个材质已经拥有 Shader 属性、纹理槽或关键词,若用户通过当前 Inspector 保存一次,该材质源文件就可能被覆盖成一个严重简化后的版本,导致正式材质数据丢失。
### 11.3 当前 Inspector 的实时写回同样不完整
当前 `ApplyResolvedMaterialStateToResource()` 仅把面板状态写回到运行时 `Material` 的以下部分:
- `SetShader`
- `SetRenderQueue`
- `SetRenderState`
- `ClearTags` / `SetTag`
它不会写回:
- Shader schema 属性值
- 纹理绑定
- 关键词
因此 Inspector 当前即使支持继续加控件,如果不先重构数据模型,运行时同步仍然会不完整。
### 11.4 Render State Override 当前没有被正式建模
运行时 `Material::SetRenderState()` 会自动把 `HasRenderStateOverride` 置为 `true`
但当前 Inspector
- 没有暴露 “是否启用 Render State Override”
- 保存时始终写出完整 `renderState`
- 应用时始终调用 `SetRenderState`
这意味着只要用户通过当前材质面板保存,材质就会被强制推进到显式 Render State Override 路径。这个行为不符合正式设计,必须在下一阶段一起修正。
### 11.5 运行时底层能力其实已经基本齐备
当前 runtime/resource 层已经具备正式所需的大部分能力:
- `ShaderPropertyDesc` 已包含 `name / displayName / type / defaultValue / semantic`
- `Shader` 已提供 `GetProperties()` / `FindProperty()` / keyword declaration 能力
- `Material` 已提供完整的 `SetFloat/SetInt/SetBool/SetTexture...`
- `Material` 已支持 Shader schema 默认值同步
- `MaterialLoader` 已支持解析 `properties / textures / keywords / tags / renderState`
- material artifact 当前已支持这些正式数据的持久化
也就是说,当前问题的主要矛盾不在资源系统,而在 Editor 侧没有接入正式模型。
### 11.6 当前阶段的根本性结论
下一阶段不能直接在现有材质面板上继续堆控件。
必须先完成:
1. `MaterialAssetState` 的正式重构
2. Save/Reload/Apply 链路对 `properties / textures / keywords / renderState override` 的建模
3. Inspector 与运行时 `Material` 之间的一致性重建
只有先做完这些,后续的 Shader schema 驱动属性 UI 才不会继续建立在错误基础上。
### 11.7 Phase 2 的直接执行范围
基于本阶段审查结果,下一阶段将直接进入以下工作:
1. 扩展 `MaterialAssetState`,让其正式承载属性、纹理槽、关键词与 render state override。
2. 重构 `Populate / Apply / Save / Reload` 这四条关键链路。
3. 彻底消除当前“保存一次就丢属性”的结构性问题。