# ModelTranslator 用 headless Blender 把带 PBR 贴图的 FBX 转换为 **XPbr shader**(`Test/XPbr`)可用的资源: - 纯模型 FBX(剥离全部贴图,保留材质名/槽位) - 每材质一套贴图(≤2048×2048): - **基础贴图** `<模型>_<材质>_base.png`:RGB=颜色,A=透明或 AO - **混合贴图** `<模型>_<材质>_mix.png`:RG=球面编码法线,B=金属度,A=粗糙度 - Unity 开箱即用:`.mat`(已挂 XPbr、已连贴图)与全部 `.meta`(含 sRGB 设置、FBX 材质重映射)都预生成 ## 依赖 - Blender 5.0(默认路径 `D:\tools\blender-5.0.0-windows-x64\blender.exe`;也可用 `--blender` 参数或环境变量 `BLENDER_EXE` 指定) - 系统 Python 3.x(仅标准库) ## 用法 ```bash cd Tools/ModelTranslator python model_translator.py src/tong.fbx # 单文件 python model_translator.py src/ # 目录批量(*.fbx) python model_translator.py src/tong.fbx -o out --max-size 2048 --blender "D:\...\blender.exe" ``` 输出到 `out/<模型名>/`: ``` out/tong/ tong.fbx (+.meta) # 纯模型,材质槽已重映射到下面的 .mat tong_Material_base.png (+.meta) # sRGB 开 tong_Material_mix.png (+.meta) # sRGB 关(线性数据,勿改) tong_Material.mat (+.meta) # Test/XPbr ``` **把整个 `out/<模型名>/` 文件夹拷进 `Client/Assets/` 任意位置即可**,模型拖进场景直接生效。重复转换会复用已有 `.meta` 里的 GUID,不会破坏 Unity 引用。 ## 减面与高低模烘焙(可选前置工具) 高面数模型先减面、再把细节烘到低模贴图,产物直接作为上面转换器的输入: ```bash cd Tools/ModelTranslator python model_decimate.py src/well1500.fbx --tris 5000 # -> src/well1500_low.fbx python model_bake.py src/well1500.fbx src/well1500_low.fbx # -> out_bake/well1500/ python model_translator.py out_bake/well1500/well1500.fbx # -> out/well1500/(Unity 资源) ``` - **model_decimate.py**:多 mesh 自动 join;三角化后 Decimate(collapse) 减到 `--tris`(±3%,最多 2 轮修正);旧 UV 全删后重展——默认锐边标 seam + MINIMUM_STRETCH 整岛展开(碎岛少、接缝落在硬边),质量不达标(翻转 >2% 或重叠 >8%)自动回退 Smart UV Project,`--unwrap smart` 可强制旧行为;输出 `<名>_low.fbx`(`-o` 改目录),日志报 UV 岛数/利用率 - **model_bake.py**:Cycles selected-to-active 烘焙。normal(切线空间 OpenGL +Y)/ao 直接烘;color/metallic/roughness 把高模 Principled 对应输入接 Emission 烘 EMIT。`--size` 默认 2048,`--samples` AO 采样默认 64,射线距离默认低模包围盒对角线 2%(`--ray-distance` 覆盖);低模无 UV 会报错,高低模包围盒差超 10% 打警告;导入后自动应用物体变换——未应用缩放的 FBX(如 cm 单位导出的 scale=0.01)会把射线距离缩到近零导致大面积烘空(脏色);固定 `-t 1` 单线程跑 Blender——5.0 的 selected-to-active 射线求交多线程有竞争,会随机 EXCEPTION_ACCESS_VIOLATION 崩溃 - 输出命名 `<名>_color/normal/metallic/roughness/ao.png`,正好命中转换器的纯网格贴图命名约定 ## 转换规则 - 贴图识别:沿材质 Principled BSDF 连线找 Base Color / Alpha / Normal / Metallic / Roughness;内嵌与外置贴图(FBX 旁的松散文件)均支持 - AO 按贴图名匹配(含 `ao`/`occlusion`/`ambient`):先找材质内引用的贴图;FBX 未引用时自动搜索 FBX 同目录的图片文件,多候选优先与颜色贴图同前缀(`xxx_color.png` → `xxx_ao.png`) - **纯网格 FBX**(无材质或材质无贴图,常见于烘焙工具导出):自动以模型名新建材质,并按命名约定从 FBX 同目录识别整套贴图——`<前缀>_.png`,token 支持 `color/basecolor/albedo/diffuse`、`normal/nrm`、`metallic/metalness/metal`、`roughness/rough`、`ao/occlusion/ambient`、`alpha/opacity`;多套前缀时取与模型同名的一组 - 基础贴图 A 通道自动判定:**透明贴图 > 颜色贴图自带 alpha > AO 贴图 > 填白(255)**;判定为透明时 `.mat` 自动勾选 `Alpha As Transparency`(AlphaTest 裁剪) - 无对应贴图的通道用 Principled 常量值填充(会在日志中标注 `(常量)`) - 目标尺寸 = min(2048, 源贴图最大边),所有贴图缩放到统一尺寸 - 法线编码:`enc = n.xy / sqrt(2*(1+n.z)) * 0.5 + 0.5`,与 `XPbr_Base.hlsl` 的 `DecodeSphereMap` 配对 ## 局限 - 材质必须是贴图直连 Principled BSDF 的标准 PBR;程序纹理/复杂混合节点无法识别(会打警告并退化为常量) - 法线按 OpenGL 约定(+Y 向上)处理,不提供绿通道翻转 - 不做多材质图集合并/UV 重排;每材质一套贴图 - 动画/骨骼随 FBX 原样导出,不做处理 - 外置贴图文件丢失时打警告并退化为常量,不中断转换 ## 开发 ```bash python -m unittest tests.test_unity_assets # Unity 模板/GUID 测试 "" -b --factory-startup --python tests/bl_test_encode.py # 法线编码 round-trip ```