480 lines
9.5 KiB
Markdown
480 lines
9.5 KiB
Markdown
# MetaCore 材质资源与 MeshRenderer 数据结构设计
|
||
|
||
生成时间:2026-03-28
|
||
状态:草案
|
||
范围:M2 资源与模型导入循环、M3 场景编辑、材质与光照工作流
|
||
|
||
## 目的
|
||
|
||
这份文档用于把后续会真正落到代码里的几类核心结构定清楚:
|
||
|
||
- `Material Asset` 应该有哪些字段
|
||
- `Mesh Asset` 应该有哪些字段
|
||
- `MeshRenderer` 应该如何从当前简化结构演进
|
||
- 这些结构如何参与场景保存、资源引用和打包
|
||
|
||
这一步的目标不是讨论渲染效果,而是先锁定数据模型。
|
||
|
||
因为对引擎来说,数据结构一旦定错,后面:
|
||
|
||
- 模型导入
|
||
- Inspector
|
||
- Scene 保存
|
||
- Prefab
|
||
- Cook
|
||
- Player 渲染
|
||
|
||
都会一起返工。
|
||
|
||
## 当前代码现状
|
||
|
||
当前 `MeshRenderer` 组件大致是:
|
||
|
||
- `BuiltinMesh`
|
||
- `BaseColor`
|
||
- `Visible`
|
||
|
||
这适合原型验证,但不足以支撑真实模型与材质工作流。
|
||
|
||
当前仓库里还没有正式的:
|
||
|
||
- `Material Asset Document`
|
||
- `Mesh Asset Document`
|
||
- `Texture Asset Document`
|
||
- `MeshRenderer` 的资源引用结构
|
||
|
||
因此第一阶段必须先完成“从原型组件到正式资源引用组件”的演进设计。
|
||
|
||
## 设计目标
|
||
|
||
第一阶段数据结构要同时满足下面几个要求:
|
||
|
||
- 能支撑 `glTF/.glb` 首批导入
|
||
- 能支撑简单模型和多材质槽模型
|
||
- 能在 Scene 中稳定保存引用
|
||
- 能被 Editor Inspector 编辑
|
||
- 能被 Cook 和 Package 依赖分析
|
||
- 能接入 `simplepbr`
|
||
- 不锁死未来类 URP 的演进空间
|
||
|
||
## 资源与组件的关系
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A["Mesh Asset"] --> C["MeshRenderer Component"]
|
||
B["Material Asset (0..N)"] --> C
|
||
C --> D["Scene Document"]
|
||
A --> E["Cook / Package"]
|
||
B --> E
|
||
D --> F["Player Runtime"]
|
||
E --> F
|
||
```
|
||
|
||
含义是:
|
||
|
||
- `MeshRenderer` 不再直接保存完整材质内容
|
||
- `MeshRenderer` 只保存对资源的引用
|
||
- 资源本体由资产系统管理
|
||
|
||
## 第一阶段 Material Asset 结构
|
||
|
||
第一阶段建议定义正式的 `MetaCoreMaterialAssetDocument`。
|
||
|
||
### 核心字段
|
||
|
||
- `AssetGuid`
|
||
- `Name`
|
||
- `ShaderModel`
|
||
- `BaseColor`
|
||
- `BaseColorTexture`
|
||
- `NormalTexture`
|
||
- `Metallic`
|
||
- `Roughness`
|
||
- `MetallicRoughnessTexture`
|
||
- `AoTexture`
|
||
- `EmissiveColor`
|
||
- `EmissiveTexture`
|
||
- `AlphaMode`
|
||
- `AlphaCutoff`
|
||
- `DoubleSided`
|
||
|
||
### 字段说明
|
||
|
||
#### AssetGuid
|
||
|
||
材质资源的稳定身份。
|
||
|
||
这是 Scene、Prefab、Cook、重导入能够持续引用它的基础。
|
||
|
||
#### Name
|
||
|
||
材质资源名,主要用于:
|
||
|
||
- Project 面板显示
|
||
- Inspector 显示
|
||
- 调试与错误提示
|
||
|
||
#### ShaderModel
|
||
|
||
第一阶段建议不要设计成任意 shader 名字字符串,而是明确一个有限枚举,例如:
|
||
|
||
- `PbrMetalRough`
|
||
- `UnlitColor`
|
||
- `UnlitTexture`
|
||
|
||
第一阶段主打 `PbrMetalRough`。
|
||
|
||
这样做的好处是:
|
||
|
||
- 数据更稳定
|
||
- Inspector 更清楚
|
||
- 后续再映射到不同 render backend 更容易
|
||
|
||
#### BaseColor
|
||
|
||
基础颜色乘子。
|
||
|
||
#### BaseColorTexture
|
||
|
||
对纹理资源的引用。建议类型为:
|
||
|
||
- `std::optional<MetaCoreAssetGuid>`
|
||
|
||
不要在材质里直接存文件路径。
|
||
|
||
#### NormalTexture
|
||
|
||
法线贴图资源引用。
|
||
|
||
#### Metallic / Roughness
|
||
|
||
金属度与粗糙度标量参数。
|
||
|
||
#### MetallicRoughnessTexture
|
||
|
||
金属粗糙度复合图资源引用。
|
||
|
||
#### AoTexture
|
||
|
||
AO 贴图资源引用。
|
||
|
||
#### EmissiveColor / EmissiveTexture
|
||
|
||
自发光颜色和自发光贴图引用。
|
||
|
||
#### AlphaMode
|
||
|
||
第一阶段建议枚举化,例如:
|
||
|
||
- `Opaque`
|
||
- `Mask`
|
||
- `Blend`
|
||
|
||
#### AlphaCutoff
|
||
|
||
用于 `Mask` 模式。
|
||
|
||
#### DoubleSided
|
||
|
||
双面渲染开关。
|
||
|
||
### 第一阶段不建议直接放进去的内容
|
||
|
||
这些不要在第一阶段过早塞进正式材质结构:
|
||
|
||
- 任意 shader 参数字典
|
||
- 自定义 render feature 列表
|
||
- 任意 pass 配置
|
||
- 大而全的 keyword 系统
|
||
|
||
这些都会把第一阶段数据结构做得又重又不稳。
|
||
|
||
## 第一阶段 Mesh Asset 结构
|
||
|
||
第一阶段建议定义正式的 `MetaCoreMeshAssetDocument`。
|
||
|
||
### 核心字段
|
||
|
||
- `AssetGuid`
|
||
- `Name`
|
||
- `BoundsMin`
|
||
- `BoundsMax`
|
||
- `VertexCount`
|
||
- `IndexCount`
|
||
- `SubMeshes`
|
||
|
||
如果当前阶段还不想把大块几何数据直接暴露在文档结构里,也可以让文档描述元信息,而实际几何 buffer 落在 package payload。
|
||
|
||
### SubMesh 结构
|
||
|
||
第一阶段建议有明确的 `MetaCoreSubMeshDescriptor`:
|
||
|
||
- `Name`
|
||
- `IndexOffset`
|
||
- `IndexCount`
|
||
- `MaterialSlotIndex`
|
||
|
||
这个结构非常关键,因为它把:
|
||
|
||
- 一个网格中的多个几何段
|
||
- 和材质槽位的关系
|
||
|
||
固定了下来。
|
||
|
||
### 顶点流建议
|
||
|
||
第一阶段至少支持:
|
||
|
||
- Position
|
||
- Normal
|
||
- UV0
|
||
- Tangent
|
||
|
||
如果导入格式缺少某些数据,可以在导入阶段:
|
||
|
||
- 自动补全
|
||
- 或给出警告
|
||
|
||
但不要让运行时数据结构含糊不清。
|
||
|
||
## 第一阶段 Texture Asset 结构
|
||
|
||
即使暂时不做完整纹理编辑器,也建议正式定义 `MetaCoreTextureAssetDocument`,至少有:
|
||
|
||
- `AssetGuid`
|
||
- `Name`
|
||
- `Width`
|
||
- `Height`
|
||
- `Format`
|
||
- `ColorSpace`
|
||
- `Usage`
|
||
|
||
其中 `Usage` 第一阶段建议枚举化,例如:
|
||
|
||
- `BaseColor`
|
||
- `Normal`
|
||
- `LinearMask`
|
||
- `Emissive`
|
||
- `Ao`
|
||
|
||
这有利于:
|
||
|
||
- 导入校验
|
||
- Inspector 提示
|
||
- simplepbr 映射
|
||
|
||
## MeshRenderer 组件演进设计
|
||
|
||
这是最关键的组件演进点。
|
||
|
||
### 当前结构
|
||
|
||
- `BuiltinMesh`
|
||
- `BaseColor`
|
||
- `Visible`
|
||
|
||
### 第一阶段目标结构
|
||
|
||
建议演进为:
|
||
|
||
- `MeshSourceKind`
|
||
- `BuiltinMesh`
|
||
- `MeshAssetGuid`
|
||
- `MaterialAssetGuids`
|
||
- `Visible`
|
||
|
||
### 推荐字段解释
|
||
|
||
#### MeshSourceKind
|
||
|
||
建议新增一个枚举,明确当前对象使用的是:
|
||
|
||
- `Builtin`
|
||
- `Asset`
|
||
|
||
这样可以兼容当前已有的内置立方体、球体等原型对象,也可以平滑接入正式模型资源。
|
||
|
||
#### BuiltinMesh
|
||
|
||
保留现有字段,但只在 `MeshSourceKind == Builtin` 时生效。
|
||
|
||
这有利于:
|
||
|
||
- 继续保留最小原型能力
|
||
- 不阻塞后面正式资源化
|
||
|
||
#### MeshAssetGuid
|
||
|
||
当 `MeshSourceKind == Asset` 时,引用正式网格资源。
|
||
|
||
建议类型:
|
||
|
||
- `std::optional<MetaCoreAssetGuid>`
|
||
|
||
#### MaterialAssetGuids
|
||
|
||
一个数组,长度 ideally 对应 `SubMesh` 的材质槽数量。
|
||
|
||
建议类型:
|
||
|
||
- `std::vector<MetaCoreAssetGuid>`
|
||
|
||
第一阶段如果导入模型只有一个材质,也仍建议用数组,而不是单个字段。
|
||
|
||
因为多材质槽模型在工业场景里非常常见。
|
||
|
||
#### Visible
|
||
|
||
保留。
|
||
|
||
### 第一阶段允许保留的兼容字段
|
||
|
||
为了兼容已有原型代码,第一阶段可以短期保留:
|
||
|
||
- `BaseColor`
|
||
|
||
但需要明确它的定位只能是:
|
||
|
||
- 调试覆盖色
|
||
- RuntimeData 的临时驱动入口
|
||
|
||
它不应继续作为正式材质系统的核心字段。
|
||
|
||
也就是说,后续优先级应该是:
|
||
|
||
- 资源材质主导
|
||
- `BaseColor` 仅作为可选 override
|
||
|
||
## Scene 保存策略
|
||
|
||
Scene 中不应内嵌完整的网格和材质内容。
|
||
|
||
Scene 对 `MeshRenderer` 的保存应以“引用”为主:
|
||
|
||
- `MeshSourceKind`
|
||
- `BuiltinMesh`
|
||
- `MeshAssetGuid`
|
||
- `MaterialAssetGuids`
|
||
- `Visible`
|
||
|
||
这样好处是:
|
||
|
||
- 场景更轻
|
||
- 资源可复用
|
||
- 材质统一修改后能反映到多个对象
|
||
- Cook 更容易做依赖分析
|
||
|
||
## Prefab 保存策略
|
||
|
||
Prefab 与 Scene 一样,建议保存资源引用,而不是内嵌资源内容。
|
||
|
||
这样设备、阀门、管段、告警灯等 prefab 才能真正复用:
|
||
|
||
- 同一 Mesh
|
||
- 同一 Material
|
||
- 不同 Transform
|
||
- 不同业务逻辑组件
|
||
|
||
## Cook 与 Package 策略
|
||
|
||
Cook 阶段应能够从 Scene / Prefab 中追踪依赖:
|
||
|
||
- MeshRenderer -> MeshAssetGuid
|
||
- MeshRenderer -> MaterialAssetGuids
|
||
- MaterialAsset -> TextureAsset 引用
|
||
|
||
这样最终打包时,才能把真正运行所需资源闭包带全。
|
||
|
||
## Inspector 建议
|
||
|
||
### 对象 Inspector
|
||
|
||
第一阶段最少应支持:
|
||
|
||
- 切换 Builtin / Asset Mesh
|
||
- 选择 Mesh Asset
|
||
- 查看材质槽数量
|
||
- 为每个材质槽选择 Material Asset
|
||
- `Visible`
|
||
|
||
### 材质资源 Inspector
|
||
|
||
第一阶段最少应支持:
|
||
|
||
- BaseColor
|
||
- BaseColorTexture
|
||
- NormalTexture
|
||
- Metallic
|
||
- Roughness
|
||
- EmissiveColor
|
||
- EmissiveTexture
|
||
- AlphaMode
|
||
- DoubleSided
|
||
|
||
### 不建议的做法
|
||
|
||
不要让对象 Inspector 同时承担:
|
||
|
||
- 对象引用管理
|
||
- 材质参数完整编辑
|
||
|
||
这会让工作流非常乱。
|
||
|
||
## 与 RuntimeData 的关系
|
||
|
||
材质资源化之后,`RuntimeData` 仍然可以继续驱动:
|
||
|
||
- `MeshRenderer.Visible`
|
||
- 材质 override 颜色
|
||
- 灯光参数
|
||
|
||
但不建议第一阶段直接让 RuntimeData 去改材质资源本体。
|
||
|
||
更合理的做法是:
|
||
|
||
- Runtime 改对象实例级显示状态
|
||
- Asset 仍然由资源系统管理
|
||
|
||
## 推荐实现顺序
|
||
|
||
建议按下面顺序推进:
|
||
|
||
1. 定义 `Material Asset Document`
|
||
2. 定义 `Mesh Asset Document`
|
||
3. 定义 `Texture Asset Document`
|
||
4. 扩展 `MeshRenderer` 数据结构
|
||
5. 更新 Scene / Prefab 序列化
|
||
6. 更新 Inspector
|
||
7. 再接模型导入与材质映射
|
||
8. 最后接 `simplepbr` 参数映射
|
||
|
||
## 第一阶段 Definition of Done
|
||
|
||
当下面这些都成立时,可以认为这套数据结构设计已经真正落地:
|
||
|
||
- Scene 中的 `MeshRenderer` 不再只依赖 `BuiltinMesh`
|
||
- 导入模型能够生成正式 Mesh/Material 资源
|
||
- 对象可以引用 Mesh Asset 和多个 Material Asset
|
||
- Inspector 能指派和编辑材质
|
||
- Scene / Prefab 保存的是资源引用
|
||
- Cook 能正确追踪 Mesh/Material/Texture 依赖
|
||
- Player 能基于这些资源正确渲染
|
||
|
||
## 最终建议
|
||
|
||
第一阶段最关键的不是“效果做多炫”,而是先把结构做对。
|
||
|
||
所以最合理的方向是:
|
||
|
||
**把 Mesh、Material、Texture 正式变成 MetaCore 资源,把 MeshRenderer 正式变成资源引用组件,再让导入、Inspector、Cook 和 simplepbr 全部围绕这套结构协作。**
|
||
|
||
这一步一旦定稳,后续:
|
||
|
||
- 模型导入
|
||
- 材质编辑
|
||
- 场景保存
|
||
- 打包运行
|
||
- RuntimeData 显示驱动
|
||
|
||
都会顺很多。
|