8.4 KiB
8.4 KiB
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指定) - UVPackmaster 4(可选,UV 排布质量更好:Blender 扩展
uvpackmaster4+ 独立引擎,引擎路径经注册表自动发现;已装则 Blender 展开路径(seam/smart)的排布自动启用,未装自动回退内置 pack_islands) - 系统 Python 3.x(标准库 + Pillow——仅
model_decimate.py绘 UV 观察图用;pip install Pillow)
用法
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 引用。
减面与高低模烘焙(可选前置工具)
高面数模型先减面、再把细节烘到低模贴图,产物直接作为上面转换器的输入:
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;减面前清理网格(按局部包围盒对角线相对焊接重合点 + 去退化面,给后端更干净的流形、减少被迫加的 seam);按
--reducer后端减到--tris(默认 Quad Remesher,失败自动回退 Decimate collapse;collapse 后端为 ±3%,最多 2 轮修正);旧 UV 全删后重展——默认锐边 seam 整岛展开(SLIM 展开后minimize_stretch松弛 +average_islands_scale纹素均衡),质量门不达标(翻转 >2% 或重叠 >8%)先按更低 seam 角度扫描(55/45/35°)取过门且岛数最少者抢救,全失败才回退 Smart UV Project,--unwrap smart可直接选投影式展开;--max-overlap 0.15放宽重叠门限,让更高 seam 角度(岛更少)能过门被选中——岛数优先、可接受略高重叠时用(翻转门限始终严格);排布默认用 UVPackmaster 4 重排(只在最终选定 UV 上跑一次,旋转步进调细到 15° 以利薄斜条对齐提升利用率;UVPM 启发式搜索在 headless 下会随机崩溃引擎故未启用),UVPM4 不可用自动沿用内置 pack_islands 布局;输出<名>_low.fbx(-o改目录)与<名>_low_uv.png(UV 线框观察图,便于人工查阅切分/排布/碎岛——Blender 抽 UV 几何,系统 Python 用 Pillow 绘制,因 headless 无 GPU 无法用 Blender 直接出 PNG),日志报 UV 岛数/利用率与实际生效的 seam 角度 --reducer collapse|quad(默认quad):减面后端。quad用 Quad Remesher 出规整四边拓扑(针对 collapse 的碎三角/UV 展开难痛点),headless 下直接调Engine/xremesh.exe引擎子进程(导出选中 mesh → 写 RetopoSettings.txt → 阻塞轮询 progress.txt → 导回 retopo.fbx),绕开插件的 modal 操作符(modal 在blender -b后台不执行,直接调操作符必然失败)。面数按--tris ÷ 2换算为目标四边形数,用ExactQuadCount=1尊重目标数(自适应模式在高细节硬表面模型上会把面数炸开数倍并连带 UV 重叠爆炸,故禁用);输出为近似面数(约 ±20%)。任何失败——引擎缺失/超时/引擎报错/无有效输出/导回失败——都记警告并自动回退 collapse,摘要reducer字段标quad->collapse,绝不中断。升级流程:quad 后端先把高密度输入预 collapse 到中等密度(--qr-input-cap,默认 50000——高密度网格直接 QR 必破洞),再 QR,导回后fill_holes补掉薄部位小洞,最后软水密门(补洞后仍比输入多出超容忍的破损才判灾难性、回退 collapse)。quad 成功时保留四边、不三角化导出(FBX/烘焙/Unity 均支持四边;这修掉了旧版 quad 被三角化的问题)。QR_ENGINE环境变量可覆盖引擎路径(权威:显式设了就以它为准,无效即视同缺失走回退)。QR 输出为近似面数(约 ±20%,四边口径--tris÷2);实测有机角色可保四边(如 100 万面 supergirl → 约 5000 四边、开边≤3),硬表面直边仍会被 QR 波动化(那类模型用 collapse)- model_bake.py:Cycles selected-to-active 烘焙。normal(切线空间 OpenGL +Y)/ao 直接烘;color/metallic/roughness 把高模 Principled 对应输入接 Emission 烘 EMIT。
--size默认 2048,--samplesAO 采样默认 64;射线距离auto(默认)按实测低↔高分离距离自适应(分离 P99×1.5,夹在包围盒对角线 0.05%~1%),比旧的固定 2% 小很多,避免薄部件(如裙子)射线穿透打到背/内面产生深色脏斑——尤其 QR 四边低模偏离高模处(实测 supergirl 穿透面 7%→3.2%);测量失败回退固定 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 同目录识别整套贴图——
<前缀>_<token>.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 原样导出,不做处理
- 外置贴图文件丢失时打警告并退化为常量,不中断转换
开发
python -m unittest tests.test_unity_assets # Unity 模板/GUID 测试
"<blender>" -b --factory-startup --python tests/bl_test_encode.py # 法线编码 round-trip