用 Blender 批量把 STL 变成游戏资产
2026-10-19 · 3D 管线
买到手的核桃模型是 STL:只有三角面,没有材质、没有 UV。 要在应用里用,得把它变成带贴图的 GLB:UV 展开 → 烘焙颜色和 AO → 减面 → 导出。
管线
整个流程跑在 Blender 的 headless 模式里,一条命令处理一个文件:
blender -b -P tools/stl_to_glb.py -- 核桃.stl 输出目录 20000 1.6
脚本里做的事:
- 导入 STL,合并重复顶点(有些 STL 是逐面导出的,顶点翻倍)
- 用位移增强纹路(unsharp mask 的思路,让浮雕更明显)
- 用球面投影生成 UV
- 烘焙 BaseColor / AO / Roughness 三张图
- 把 AO 乘进 BaseColor(省一张贴图,也避免渲染时漏掉)
- 去饱和并提亮成"白茬"的骨白色
- 减面到 2 万,导出 GLB
问题:四分钟一个
第一批十个模型,每个 48 万面。跑完一个要 231 秒,十个就是四十分钟。 慢的地方是 AO 烘焙:96 采样,每个采样都要和 48 万个三角面求交。
但最终资产只有 2 万面。也就是说,**有 46 万面在烘焙之后就被丢掉了**, 而它们让烘焙慢了二十多倍。
改一行顺序,快 15 倍
把减面挪到烘焙之前:
# 之前
bake(obj, tex_size, out_dir)
decimate(obj, target_faces)
# 之后
if len(obj.data.polygons) > 60000:
decimate(obj, target_faces) # 先减面
bake(obj, tex_size, out_dir) # 再烘焙
decimate(obj, target_faces) # 幂等:已达标就跳过
| 顺序 | 单个耗时 |
|---|---|
| 烘焙 → 减面 | 231 秒 |
| 减面 → 烘焙 | 15 秒 |
代价是 AO 的精度略降。但贴图只有 512²,而且最终也就是 2 万面, 这点差别在 220 像素的桌宠窗口里完全看不出来。
贴图格式:PNG 换 WebP
第一版把 1024² 的贴图存成 PNG,单个 GLB 有 2.2 MB,其中 1.75 MB 是贴图。 核桃在界面上最多显示 220 像素,1024² 是 4 倍超采样。
改成 512² WebP 之后:
- 单模型:2.2 MB → 0.48 MB
- 十二个品种合计:26 MB → 5.8 MB
两个小坑
非 ASCII 路径。 Blender 在中文路径下处理大文件偶尔会出问题, 更普遍的是打包出来的 Electron 应用放在中文路径下会直接崩。现在构建产物一律复制到 ASCII 路径再测。
脚本编码。 Windows PowerShell 5.1 读脚本时按 ANSI 解码, 脚本里带中文就是语法错误。要么存成带 BOM 的 UTF-8,要么把中文参数放进 JSON。