# 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` 不要在材质里直接存文件路径。 #### 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` #### MaterialAssetGuids 一个数组,长度 ideally 对应 `SubMesh` 的材质槽数量。 建议类型: - `std::vector` 第一阶段如果导入模型只有一个材质,也仍建议用数组,而不是单个字段。 因为多材质槽模型在工业场景里非常常见。 #### 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 显示驱动 都会顺很多。