9.5 KiB
MetaCore 材质资源与 MeshRenderer 数据结构设计
生成时间:2026-03-28
状态:草案
范围:M2 资源与模型导入循环、M3 场景编辑、材质与光照工作流
目的
这份文档用于把后续会真正落到代码里的几类核心结构定清楚:
Material Asset应该有哪些字段Mesh Asset应该有哪些字段MeshRenderer应该如何从当前简化结构演进- 这些结构如何参与场景保存、资源引用和打包
这一步的目标不是讨论渲染效果,而是先锁定数据模型。
因为对引擎来说,数据结构一旦定错,后面:
- 模型导入
- Inspector
- Scene 保存
- Prefab
- Cook
- Player 渲染
都会一起返工。
当前代码现状
当前 MeshRenderer 组件大致是:
BuiltinMeshBaseColorVisible
这适合原型验证,但不足以支撑真实模型与材质工作流。
当前仓库里还没有正式的:
Material Asset DocumentMesh Asset DocumentTexture Asset DocumentMeshRenderer的资源引用结构
因此第一阶段必须先完成“从原型组件到正式资源引用组件”的演进设计。
设计目标
第一阶段数据结构要同时满足下面几个要求:
- 能支撑
glTF/.glb首批导入 - 能支撑简单模型和多材质槽模型
- 能在 Scene 中稳定保存引用
- 能被 Editor Inspector 编辑
- 能被 Cook 和 Package 依赖分析
- 能接入
simplepbr - 不锁死未来类 URP 的演进空间
资源与组件的关系
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。
核心字段
AssetGuidNameShaderModelBaseColorBaseColorTextureNormalTextureMetallicRoughnessMetallicRoughnessTextureAoTextureEmissiveColorEmissiveTextureAlphaModeAlphaCutoffDoubleSided
字段说明
AssetGuid
材质资源的稳定身份。
这是 Scene、Prefab、Cook、重导入能够持续引用它的基础。
Name
材质资源名,主要用于:
- Project 面板显示
- Inspector 显示
- 调试与错误提示
ShaderModel
第一阶段建议不要设计成任意 shader 名字字符串,而是明确一个有限枚举,例如:
PbrMetalRoughUnlitColorUnlitTexture
第一阶段主打 PbrMetalRough。
这样做的好处是:
- 数据更稳定
- Inspector 更清楚
- 后续再映射到不同 render backend 更容易
BaseColor
基础颜色乘子。
BaseColorTexture
对纹理资源的引用。建议类型为:
std::optional<MetaCoreAssetGuid>
不要在材质里直接存文件路径。
NormalTexture
法线贴图资源引用。
Metallic / Roughness
金属度与粗糙度标量参数。
MetallicRoughnessTexture
金属粗糙度复合图资源引用。
AoTexture
AO 贴图资源引用。
EmissiveColor / EmissiveTexture
自发光颜色和自发光贴图引用。
AlphaMode
第一阶段建议枚举化,例如:
OpaqueMaskBlend
AlphaCutoff
用于 Mask 模式。
DoubleSided
双面渲染开关。
第一阶段不建议直接放进去的内容
这些不要在第一阶段过早塞进正式材质结构:
- 任意 shader 参数字典
- 自定义 render feature 列表
- 任意 pass 配置
- 大而全的 keyword 系统
这些都会把第一阶段数据结构做得又重又不稳。
第一阶段 Mesh Asset 结构
第一阶段建议定义正式的 MetaCoreMeshAssetDocument。
核心字段
AssetGuidNameBoundsMinBoundsMaxVertexCountIndexCountSubMeshes
如果当前阶段还不想把大块几何数据直接暴露在文档结构里,也可以让文档描述元信息,而实际几何 buffer 落在 package payload。
SubMesh 结构
第一阶段建议有明确的 MetaCoreSubMeshDescriptor:
NameIndexOffsetIndexCountMaterialSlotIndex
这个结构非常关键,因为它把:
- 一个网格中的多个几何段
- 和材质槽位的关系
固定了下来。
顶点流建议
第一阶段至少支持:
- Position
- Normal
- UV0
- Tangent
如果导入格式缺少某些数据,可以在导入阶段:
- 自动补全
- 或给出警告
但不要让运行时数据结构含糊不清。
第一阶段 Texture Asset 结构
即使暂时不做完整纹理编辑器,也建议正式定义 MetaCoreTextureAssetDocument,至少有:
AssetGuidNameWidthHeightFormatColorSpaceUsage
其中 Usage 第一阶段建议枚举化,例如:
BaseColorNormalLinearMaskEmissiveAo
这有利于:
- 导入校验
- Inspector 提示
- simplepbr 映射
MeshRenderer 组件演进设计
这是最关键的组件演进点。
当前结构
BuiltinMeshBaseColorVisible
第一阶段目标结构
建议演进为:
MeshSourceKindBuiltinMeshMeshAssetGuidMaterialAssetGuidsVisible
推荐字段解释
MeshSourceKind
建议新增一个枚举,明确当前对象使用的是:
BuiltinAsset
这样可以兼容当前已有的内置立方体、球体等原型对象,也可以平滑接入正式模型资源。
BuiltinMesh
保留现有字段,但只在 MeshSourceKind == Builtin 时生效。
这有利于:
- 继续保留最小原型能力
- 不阻塞后面正式资源化
MeshAssetGuid
当 MeshSourceKind == Asset 时,引用正式网格资源。
建议类型:
std::optional<MetaCoreAssetGuid>
MaterialAssetGuids
一个数组,长度 ideally 对应 SubMesh 的材质槽数量。
建议类型:
std::vector<MetaCoreAssetGuid>
第一阶段如果导入模型只有一个材质,也仍建议用数组,而不是单个字段。
因为多材质槽模型在工业场景里非常常见。
Visible
保留。
第一阶段允许保留的兼容字段
为了兼容已有原型代码,第一阶段可以短期保留:
BaseColor
但需要明确它的定位只能是:
- 调试覆盖色
- RuntimeData 的临时驱动入口
它不应继续作为正式材质系统的核心字段。
也就是说,后续优先级应该是:
- 资源材质主导
BaseColor仅作为可选 override
Scene 保存策略
Scene 中不应内嵌完整的网格和材质内容。
Scene 对 MeshRenderer 的保存应以“引用”为主:
MeshSourceKindBuiltinMeshMeshAssetGuidMaterialAssetGuidsVisible
这样好处是:
- 场景更轻
- 资源可复用
- 材质统一修改后能反映到多个对象
- 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 仍然由资源系统管理
推荐实现顺序
建议按下面顺序推进:
- 定义
Material Asset Document - 定义
Mesh Asset Document - 定义
Texture Asset Document - 扩展
MeshRenderer数据结构 - 更新 Scene / Prefab 序列化
- 更新 Inspector
- 再接模型导入与材质映射
- 最后接
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 显示驱动
都会顺很多。