# MetaCore 材质系统与模型导入衔接设计 生成时间:2026-03-28 状态:草案 范围:M2 资源与模型导入循环、M3 场景编辑、材质与光照工作流 ## 目的 这份文档用于解决一个关键衔接问题: - 模型导入后,材质信息如何进入 MetaCore - MetaCore 内部材质资源应该长什么样 - 场景对象如何引用材质 - 第一阶段如何接入 `panda3d-simplepbr` 如果这条链不先设计清楚,后面模型导入、Inspector 编辑、场景保存、Player 渲染都会各做各的,最终一定返工。 ## 结论先说 MetaCore 第一阶段应采用下面这条链路: **源模型文件 -> 导入文档 -> 网格资源 / 材质资源 -> 场景对象 MeshRenderer -> simplepbr 参数映射 -> Player 渲染** 这里必须明确两件事: 1. 模型导入负责“生成 MetaCore 自己的资源” 2. 渲染后端只负责“消费 MetaCore 材质资源” 不能让模型文件直接决定运行时材质结构,也不能让 `simplepbr` 反向决定 MetaCore 材质资源长什么样。 ## 当前代码库现状 从当前仓库看,已经具备下面的基础: - 资产元数据与资产数据库骨架 - 导入服务接口与 cook 接口 - 包格式与二进制读写能力 - `MeshRenderer` 组件基础 - `MeshRenderer.BaseColor` - `MeshRenderer.Visible` 但当前还缺: - 正式的材质资源类型 - 正式的网格资源类型 - 模型导入后的材质槽映射定义 - 场景对象对材质资源的引用方式 - 材质 Inspector 与资源编辑流程 - 材质到 `simplepbr` 的统一映射层 因此当前最合理的做法不是直接继续加渲染效果,而是先把资源和组件关系定清楚。 ## 第一阶段总链路 ```mermaid flowchart LR A["源模型文件 (.glb/.gltf/.fbx)"] --> B["导入器"] B --> C["导入结果文档"] C --> D["网格资源 (.mcasset/.mcmesh)"] C --> E["材质资源 (.mcasset/.mcmat)"] D --> F["场景对象 MeshRenderer"] E --> F F --> G["MetaCore 渲染抽象层"] G --> H["simplepbr 参数映射"] H --> I["Player 渲染输出"] ``` ## 第一阶段资源分层 ### 1. 源资源 这是项目中由用户导入的原始文件: - `.glb` - `.gltf` - `.fbx` - 后续 `.obj` 这些文件是输入,不是 MetaCore 运行时直接消费的最终资源。 ### 2. 导入结果文档 导入器解析源文件后,生成一份导入结果文档,用于表达: - 导入得到几个网格资源 - 导入得到几个材质资源 - 每个网格默认使用哪个材质槽 - 原始节点层级如何映射 - 原始命名如何保留 这份文档属于导入中间层,主要为导入器、重导入和调试服务。 ### 3. MetaCore 正式资源 第一阶段至少应该落两类正式资源: - `Mesh Asset` - `Material Asset` 后续再扩: - `Texture Asset` - `Model Asset` - `Material Instance Asset` ## 第一阶段推荐资源模型 ### Mesh Asset `Mesh Asset` 第一阶段最少应包含: - 资源 GUID - Mesh 名称 - 顶点数据 - 索引数据 - 法线 - UV0 - 切线 - 包围盒 - SubMesh 列表 - 每个 SubMesh 对应的默认材质槽索引 如果一个模型含多个材质槽,应该通过 `SubMesh -> MaterialSlotIndex` 关系表达,而不是把整个模型强行压成一个材质。 ### Material Asset `Material Asset` 第一阶段最少应包含: - 资源 GUID - 材质名称 - 材质类型 - BaseColor - BaseColorTexture - NormalTexture - Metallic - Roughness - MetallicRoughnessTexture - EmissiveColor - EmissiveTexture - AoTexture - AlphaMode - AlphaCutoff - DoubleSided 第一阶段不要求复杂 shader graph,但必须保证这个资源结构已经是 MetaCore 自己的,不是 `simplepbr` 参数字典。 ### Texture Asset 如果当前阶段不想单独做完整纹理资源编辑器,也至少要有稳定纹理资源记录,用于: - BaseColorTexture - NormalTexture - MetallicRoughnessTexture - EmissiveTexture - AoTexture 第一阶段可以先把纹理当成辅助资源,由材质资源引用。 ## 模型导入后的材质映射规则 这是第一阶段最重要的设计点之一。 ### 规则 1:导入器保留源模型的材质槽 例如一个源模型含 3 个材质槽,导入后应保留: - `SubMesh 0 -> Material Slot 0` - `SubMesh 1 -> Material Slot 1` - `SubMesh 2 -> Material Slot 2` 不能在第一阶段就把它们合并掉。 ### 规则 2:每个源材质生成一个 MetaCore Material Asset 也就是说,导入器不只是读材质参数,而是正式创建: - `Valve_Body.mcmat` - `Valve_Handle.mcmat` 类似这样的材质资源。 这样后面 Inspector、资源浏览、复用和重导入才有稳定对象可操作。 ### 规则 3:导入器负责参数归一化 第一阶段推荐优先按 `glTF` 语义归一化: - BaseColor - BaseColorTexture - Metallic - Roughness - MetallicRoughnessTexture - NormalTexture - Emissive - DoubleSided - AlphaMode 对于 `FBX` 等不完全一致的格式,第一阶段允许做保守映射,但输出必须仍然变成同一套 MetaCore 材质结构。 ### 规则 4:重导入默认保留资源身份 重导入时应尽量保持: - 材质资源 GUID 不变 - 网格资源 GUID 不变 否则场景对象和 prefab 的引用会被打断。 ## 第一阶段推荐的组件模型 当前 `MeshRenderer` 只保存: - `BuiltinMesh` - `BaseColor` - `Visible` 这不足以支撑真实模型和材质工作流。 第一阶段应逐步演进为: - `MeshAssetGuid` - `MaterialAssetGuids` - `Visible` - 必要时保留调试型覆盖参数 ### 推荐结构 第一阶段建议 `MeshRenderer` 具备: - 一个 `MeshAssetGuid` - 一个 `std::vector` 用于材质槽引用 - 一个 `Visible` 如果 `SubMesh` 数量和 `MaterialAssetGuids` 数量不一致,应在 Editor 和 Cook 阶段报错或警告。 ### 不建议的做法 第一阶段不要继续把材质核心参数直接塞在 `MeshRenderer` 组件里。 `BaseColor` 作为调试或临时覆盖参数还能容忍,但长期必须迁回正式材质资源。 ## Inspector 工作流建议 第一阶段材质编辑工作流应分成两层: ### 1. 对象级 Inspector 用于编辑: - 当前对象引用哪个 Mesh - 当前对象每个材质槽引用哪个 Material - 是否可见 这一层主要做“资源指派”。 ### 2. 材质资源 Inspector 用于编辑: - BaseColor - 贴图槽 - Metallic / Roughness - Emissive - AlphaMode - DoubleSided 这一层主要做“资源参数编辑”。 不要把“对象引用”和“材质内容”全部混在同一个对象 Inspector 里。 ## 与 simplepbr 的衔接方式 第一阶段 `simplepbr` 应只出现在渲染映射层。 也就是: - `MetaCoreMaterialAsset` -> `MetaCoreRenderMaterialParams` -> Panda3D / `simplepbr` ### 第一阶段最小映射 应至少支持: - BaseColor - BaseColorTexture - NormalTexture - Metallic - Roughness - EmissiveColor - EmissiveTexture - DoubleSided ### 明确不要做 第一阶段不要把 `simplepbr` 的内部参数名、调用方式、配置细节直接暴露到: - 材质资源格式 - Editor Inspector - 场景组件结构 否则后面替换渲染后端时,整条链都要重写。 ## 首批格式建议 ### P0:glTF / .glb 这是第一阶段最应该优先打通的格式。 原因: - 现代 - 对 PBR 语义支持较清晰 - 与材质参数映射天然更顺 - 适合作为数字孪生模型导入起点 ### P1:FBX 可以作为第二优先级。 原因: - 现实项目里经常遇到 - 但材质与层级语义更杂 - 更容易出现导入归一化问题 ### P2:OBJ 只建议作为补充格式,不建议第一阶段主打。 原因: - 表达能力弱 - 对现代 PBR 工作流支撑差 ## 保存与打包建议 第一阶段推荐: - 项目内保留源文件 - 导入后生成材质/网格正式资源 - Scene 保存时只引用资源 GUID - 打包时由 cook 收集依赖资源 不要让 Scene 直接内嵌整份材质内容。 这对后面: - 资源复用 - 场景共享 - 材质统一替换 - 打包依赖分析 都更健康。 ## 错误与诊断要求 第一阶段至少要能发现这些问题: - 模型导入缺失材质槽 - 材质引用的纹理丢失 - 场景对象引用了不存在的 Mesh - 材质槽数量与 SubMesh 数量不匹配 - 材质参数无法映射到当前后端 这些问题应至少在: - 导入阶段 - Inspector - Cook 阶段 给出明确提示。 ## 推荐实现顺序 建议按下面顺序推进: 1. 定义 `Material Asset` 资源结构 2. 定义 `Mesh Asset` 资源结构 3. 扩展 `MeshRenderer`,让它引用资源 GUID 4. 先打通 `glTF/.glb -> Mesh/Material Asset` 5. 打通对象级 Mesh/Material 指派 6. 打通材质资源 Inspector 7. 建立 `Material -> simplepbr` 映射层 8. 验证 Editor 与 Player 一致性 9. 再考虑 `FBX` 与重导入增强 ## 与第一阶段主线的关系 这份设计属于: - `M2` 资源与模型导入循环 - `M3` 场景编辑、材质与光照工作流 它的意义是把这两段主线真正接起来。 如果没有这份衔接设计,M2 和 M3 会变成两个独立子系统: - M2 只能“导进来” - M3 只能“手工调颜色” 这不是一个真正可用的引擎工作流。 ## 最终建议 第一阶段最合理的策略不是: - 直接做完整 URP - 也不是继续把材质逻辑散落在 `MeshRenderer` 而是: **先建立 MetaCore 自己的 Mesh/Material 资源体系,再把模型导入和 `simplepbr` 渲染后端挂到这套资源体系两端。** 这是让 MetaCore 真正形成“模型导入 -> 材质编辑 -> 场景搭建 -> Player 渲染”闭环的关键一步。