MetaCore/docs/designs/metacore-material-meshrenderer-data-structure-design.md

9.5 KiB
Raw Blame History

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 的演进空间

资源与组件的关系

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 显示驱动

都会顺很多。