4.5 KiB
4.5 KiB
ModelTranslator 工具设计文档
日期:2026-07-15 状态:已确认
目标
Tools/ModelTranslator/ 下的 Python 工具:用 headless Blender 把带 PBR 贴图的 FBX(如 src/tong.fbx)转换为:
- 纯模型 FBX(剥离贴图,保留材质名/槽位)
- XPbr shader 所需贴图(每材质一套,≤2048×2048):
- 基础贴图:RGB=颜色,A=透明 > AO > 255(自动判定)
- 混合贴图:RG=球面编码法线,B=金属度,A=粗糙度
- Unity 开箱即用资产:贴图/材质/FBX 的
.meta与.mat全部预生成,拷入Client/Assets/即可直接使用
环境
- Blender:
D:\tools\blender-5.0.0-windows-x64\blender.exe(5.0),查找顺序:--blender参数 → 环境变量BLENDER_EXE→ 上述默认路径 → PATH - 外层 CLI 用系统 Python 3.12;图像处理在 Blender 内用 bpy + 自带 numpy,不引第三方依赖
文件结构
Tools/ModelTranslator/
model_translator.py # CLI 入口:找 blender、组命令行、汇报结果
bl_convert.py # Blender 内运行的转换脚本
README.md # 用法说明
src/ # 源 FBX(已存在)
out/<模型名>/ # 输出(git 忽略)
CLI
python model_translator.py src/tong.fbx # 单文件
python model_translator.py src/ # 目录批量(*.fbx)
[-o out] [--max-size 2048] [--blender <exe>]
bl_convert.py 流程(每个 FBX)
- 空场景导入 FBX,解包全部内嵌贴图
- 逐材质找 Principled BSDF,沿连线识别贴图:Base Color、Alpha、Normal(穿过 Normal Map 节点)、Metallic、Roughness;AO 按贴图名匹配(含
ao/occlusion/ambient,不区分大小写) - 目标尺寸 = min(max-size, 各源贴图最大边),所有参与贴图缩放到统一尺寸(
image.scale()) - 基础贴图:RGB=颜色贴图(无则 Principled 常量色);A=透明贴图 > AO 贴图 > 255
- 混合贴图:
- RG=法线球面编码:切线法线
n = rgb*2-1归一化后enc = n.xy/√(2(1+n.z)) × 0.5 + 0.5;无法线贴图填 (0.5, 0.5) - B=金属度贴图(取 R 通道)或 Principled 常量
- A=粗糙度贴图(取 R 通道)或 Principled 常量
- RG=法线球面编码:切线法线
- 保存 RGBA PNG 到
out/<模型名>/ - 删除材质中所有贴图节点,
path_mode='NONE'导出纯模型 FBX - 打印 JSON 摘要(stdout 标记行),runner 转为可读日志
Unity 资产生成(model_translator.py 内完成,纯文本模板)
每材质:
| 文件 | 要点 |
|---|---|
<模型>_<材质>_base.png.meta |
TextureImporter:sRGB 开,maxTextureSize 2048 |
<模型>_<材质>_mix.png.meta |
TextureImporter:sRGB 关(线性),maxTextureSize 2048 |
<模型>_<材质>.mat |
shader 引用 XPbr GUID(见下);_MainTex/_MixTex 引用预分配贴图 GUID;透明模式时写 keyword _ALPHATEST_ON 且 _AlphaTest=1;_Metallic/_Roughness/_AO=1.0 |
<模型>_<材质>.mat.meta |
NativeFormatImporter,mainObjectFileID 2100000 |
- XPbr shader GUID:
cab897163f45445fa34263d6670bfc9e(Client/Assets/Game/shader/XShader/XPbr.shader.meta,若该 meta 变更需同步工具常量) - 模型 FBX 生成
.meta(ModelImporter):externalObjects按材质名重映射到生成的.matGUID,模型拖进场景直接生效 - 所有 GUID 用
uuid4().hex预分配;同一模型重复转换时复用已存在 meta 里的 GUID(避免拷入 Unity 后再次转换导致引用断裂)
配套 shader 修改
Client/Assets/Game/shader/XShader/XPbr_Base.hlsl 的 DecodeSphereMap 入口加 encoded = encoded * 2 - 1;:现编码只能表示 xy≥0 的法线(无符号 rg),重映射后可表示全半球。只影响 XPbr(无存量资源),不动 XTex。
错误处理
- 找不到 Blender → 明确报错并提示
--blender - 材质无 Principled BSDF → 警告,用全常量兜底(灰色、平面法线、金属 0、粗糙 0.5)
- 贴图输入是程序纹理/复杂节点 → 警告,用该输入的默认常量
- Blender 退出码非 0 → runner 透传 stderr 摘要
不做(YAGNI)
合并图集/UV 重排、Cycles 烘焙、法线绿通道翻转选项(README 说明现状)、动画/骨骼处理(FBX 原样导出)。
验证
- 实跑
src/tong.fbx与src/woodcar.fbx - 输出文件齐全,贴图尺寸 ≤2048
- 法线 round-trip 校验:按 shader 公式解码生成贴图的 RG,与源法线角度误差 < 2°
- 拷入 Unity 工程验证材质/模型开箱可用(人工步骤)