Files
XCEngine/docs/plan/Nahida Unity式Model导入与Genshin卡通渲染正式化计划_2026-04-11.md

7.0 KiB
Raw Permalink Blame History

Nahida Unity式Model导入与Genshin卡通渲染正式化计划

日期2026-04-11

1. 目标

这一轮不再按“静态拆件预览”推进,而是正式切到更接近 Unity 的方案:

  • FBX/OBJ 等外部模型统一作为 Model 主资产导入
  • 场景侧通过 Model -> GameObject hierarchy 实例化恢复节点层级
  • Mesh 继续只负责底层几何与 section/material slot
  • Nahida 的卡通渲染改为“对齐 Unity 旧工程 Genshin.shader 语义”,而不是继续维持近似版 shader

本轮仍然明确不做:

  • 骨骼动画
  • GPU skinning
  • SkinnedMeshRenderer 运行时
  • BlendShape
  • Animator / AnimationClip 播放系统

2. 当前判断

2.1 Model链路已经具备的能力

代码里已经有以下基础设施:

  • ResourceType::Model
  • Model / ModelLoader
  • xcmodel artifact
  • AssimpModelImporter
  • AssetDatabaseModelImporterModel 为主资产导入
  • sub-asset manifest 与 LocalID -> artifact path 解析

这说明“Unity式 Model 主资产”不是从零开始,而是缺最后几段关键闭环。

2.2 当前最主要的缺口

真正还没闭环的是:

  1. Model 还不能正式实例化成场景层级
  2. MeshFilter/MeshRenderer 还缺稳定的 sub-asset AssetRef 绑定入口
  3. 编辑器侧还没有把模型资产当成“可实例化层级对象”来用
  4. Nahida 当前 XCCharacterToon.shader 不是 Unity 旧工程 Genshin.shader 的等价移植
  5. FBX 导入后的静态 mesh 目前丢失了 Unity shader 依赖的顶点语义,尤其是 vertex colorUV1/backUV

2.3 关于当前 shader 的明确结论

当前使用的是:

  • project/Assets/Shaders/XCCharacterToon.shader

Unity 参考原件是:

  • docs/reference/NahidaUnity/Shaders/Genshin.shader
  • docs/reference/NahidaUnity/Shaders/GenshinInput.hlsl
  • docs/reference/NahidaUnity/Shaders/GenshinForwardPass.hlsl
  • docs/reference/NahidaUnity/Shaders/GenshinOutlinePass.hlsl

当前 shader 只是第一版近似实现,不是原 shader 原样移植。当前效果发怪,核心原因不是简单调参,而是语义缺口:

  1. 没有按 Unity 的 _IS_FACE / _SPECULAR / _RIM / _NORMAL_MAP / _DOUBLE_SIDED 关键字分支工作
  2. 面部阴影没有按 _FaceDirection + _FaceLightMap + _FaceShadow + _FaceShadowOffset 的逻辑算
  3. 阴影 ramp 还没有按 Unity 的 material ID 分层抽样
  4. specular 还不是 Unity 那套 lightMap + metalMap + matcap 路径
  5. rim 不是基于 scene depth 的 URP 风格边缘检测
  6. outline pass 还没有正式接回 Nahida_Body_Smooth.mesh 与 outline color 分档逻辑
  7. Unity 里还有 MaterialUpdater.cs 在运行时写 _FaceDirection,当前引擎里这条驱动链不存在
  8. 更关键的是,当前引擎导入出的 Nahida mesh 只有 Position/Normal/Tangent/Bitangent/UV0,缺 Color/UV1
  9. Unity 的 GenshinForwardPass.hlsl 明确依赖 input.color.rbackUV
  10. 这会直接破坏 body/hair 分支的 aoFactor = lightMap.g * input.color.r 与双面材质背面采样,因此“脸基本对、身体和头发大面积偏色”是符合代码现状的结果

所以它现在看起来不像原工程,是正常结果。

3. 本轮正式范围

Phase 1Model实例化基础链路

目标:

  • Model 正式实例化为场景 GameObject 层级

任务:

  • MeshFilterComponent 增加 mesh sub-asset AssetRef 绑定入口
  • MeshRendererComponent 增加 material sub-asset AssetRef 绑定入口
  • 保证这些 sub-asset 引用能被场景序列化稳定保存
  • 新增 Model -> Scene hierarchy 实例化工具
  • 恢复节点本地 TRS
  • 恢复 mesh binding 与 material slot binding

验收:

  • 导入一个 OBJ/FBX Model 后,可以在场景里创建出层级对象
  • 场景存盘后 sub-asset 引用不丢
  • 不需要把 FBX 拆成手工摆放的多个静态对象

Phase 2编辑器侧 Model使用工作流

目标:

  • 让编辑器把 Model 当成 Unity 式模型资产使用

任务:

  • 增加“从模型资产创建场景对象”的命令入口
  • 后续接到 Project/Hierarchy/Viewport 的拖拽放置链路
  • 让 Nahida 预览场景切到 Model 驱动的实例化路径

验收:

  • 编辑器里不再主要依赖“手工往 MeshFilter 塞 FBX 路径”
  • Nahida 预览对象结构来自 Model 实例化,而不是手工拆件

Phase 3Genshin shader 语义对齐

目标:

  • 让 Nahida 使用更接近 Unity 旧工程的卡通渲染语义

任务:

  • 先补齐静态 mesh 顶点语义链路:ColorUV1/backUV
  • 让前向渲染输入布局与 XCCharacterToon.shader 能真正接到 COLORTEXCOORD1
  • 恢复 body/hair 分支里的 lightMap.g * input.color.r
  • 恢复双面材质对 backUV 的切换采样
  • 按 Unity 原 shader 拆分 forward / outline 两条主路径
  • _IS_FACE / _SPECULAR / _RIM / _NORMAL_MAP / _DOUBLE_SIDED 语义
  • 补 face shadow 正式逻辑
  • 补 outline pass 与 Nahida_Body_Smooth.mesh
  • 视情况补一个轻量 _FaceDirection 运行时驱动

验收:

  • 角色明暗分层、面部阴影、描边、头发高光接近 Unity 参考

4. 执行顺序

这一轮按下面顺序推进:

  1. 先补 Model 实例化与 sub-asset 引用闭环
  2. 再把 Nahida 预览场景切到 Model 路径
  3. 再补 FBX 静态 mesh 的 Color/UV1 导入、artifact 保存、渲染输入布局与 shader 接线
  4. 再做 shader 语义对齐
  5. 最后做画面调参与残余语义收口

不能反过来做。因为当前 shader 再怎么调,只要场景组织和资源绑定语义不对,结果都不稳定。

5. 当前这一刀

这一轮立刻执行的第一刀是:

  • 补齐 FBX 静态 mesh 的 vertex colorUV1/backUV 导入
  • BuiltinForwardPipelineXCCharacterToon.shader 真正吃到 COLOR/TEXCOORD1
  • 补 Nahida 集成诊断与回归验证,先把 body/hair 的基础色输入纠正
  • 在这个基础上继续向 Unity 式 Model -> hierarchy 与完整 shader 语义收口推进

这是 Nahida 当前从“基础贴图都不稳定”切回“先保证静态基础颜色正确”的前置条件,也是后续继续 Unity 式正式方案的必要补丁。

6. 2026-04-11 新发现补充

在实际跑 tests/Rendering/integration/nahida_preview_scene 之后,问题又进一步收窄了:

  • Nahida 的 Body_Mesh0 运行时已经有 uv1 数值,且当前实现会在缺少第二套 UV 时回填 uv1 = uv0
  • 但导入器只在 mesh.HasTextureCoords(1) 为真时才打 VertexAttribute::UV1 标记
  • 结果就是:数据层面有 fallback uv1,语义层面却仍被当成“没有 UV1”
  • 这会导致后续依赖 backUV 的 shader / 诊断逻辑继续走错分支

因此当前这一刀的执行重点再精确一步,变成:

  1. 修复 AssimpModelImporter / MeshLoader 中“fallback uv1 已写入但 UV1 flag 未置位”的不一致
  2. 提升 ModelImporter 版本,强制 Nahida 现有 .xcmodel artifact 重导
  3. 补针对 Nahida FBX 的导入回归测试,确保 UV1 fallback 与 Color 语义不会再次退化
  4. 再继续跑 Nahida 集成图验证 body/hair 基础色是否进一步收敛