Any3DAny3D
·Any3D Team

不同平台不同命:压缩方案选型指南

3d-compressiontexture-compressionvertex-compressionoptimizationpipeline

前 4 篇分别讲了顶点压缩和纹理压缩的工具。但工具会用是一回事,该用哪个、在什么场景下用是另一回事。这篇就是来回答这个问题的——而且尽量让你看完就能直接拍板。

读完这一篇你应该能回答:我的项目跑在什么平台,首屏瓶颈是下载还是显存,纹理和顶点各该上哪套方案。

先定调:场景驱动,不是工具驱动

整篇文章只有一条核心原则,也是这个系列反复强调的:

没有「最好的」压缩方案,只有「最匹配场景」的方案。

影响选择的三个变量:

  1. 平台/设备:桌面 PC、移动浏览器、VR 头显、小程序——能力天差地别
  2. 使用方式:是一次性展示(电商产品页),还是长时间沉浸(VR 游戏)
  3. 首要瓶颈:是下载速度慢,还是显存不够,还是解码卡首屏

先把瓶颈想清楚,再回来选工具。下面这张矩阵就是把这套思路固化下来。

核心决策矩阵:平台 × 推荐方案

这是全文最重要的一张表。按平台分,给出纹理和顶点各自的推荐方案,以及理由。

平台 / 场景纹理方案顶点方案主要瓶颈关键理由
桌面 Web(PC 浏览器)KTX2 或 WebPMeshOpt / 量化下载速度显存宽裕,重点是文件小、加载快
移动 Web(手机浏览器)KTX2(必上)MeshOpt显存手机显存紧,纹理必须块压缩
WebXR / VR 头显KTX2(必上)MeshOpt + LOD显存 + 帧率显存爆炸会崩,掉帧会眩晕
微信小程序KTX2 / WebPMeshOpt / 纯量化包体 + 兼容性包大小受限,避免重型解码器
电商产品展示WebP(轻)/ KTX2(精)MeshOpt首屏速度要求秒开,体积换速度
大型场景 / 数字孪生KTX2(必上)MeshOpt + Draco + LOD显存 + draw call纹理多、模型大,全方位压

几个值得记住的判断:

  • 只要显存是瓶颈,KTX2 就必上(移动、VR、大场景都是)
  • 下载速度是瓶颈、显存宽裕时,WebP 也够用(桌面、电商)
  • 小程序这类对包体敏感的环境,优先 MeshOpt 而不是 Draco——解码器小、兼容好
  • 超大模型才考虑 Draco,绝大多数中小模型 MeshOpt 更均衡

纹理格式全维度对比

光知道「上 KTX2」还不够。具体到纹理格式,把所有维度摊开看:

格式文件大小显存占用上传速度兼容性画质适用场景
PNG大(解压后)极广无损需要精确数值/透明,或老平台兜底
JPG极小大(解压后)极广有损颜色贴图、网络传输优先
WebP很小大(解压后)较广桌面 Web、追求下载速度
AVIF更小大(解压后)渐进新平台、极致压缩
KTX2 (ETC1S)极小需转码中(颜色够用)颜色贴图、移动/VR
KTX2 (UASTC)需转码法线/数据贴图

注意前三行(PNG/JPG/WebP/AVIF)的显存占用都是「大」——无论磁盘多小,进了显存都得解压回原始像素。这是传统格式的根本限制。

混合策略很常见:关键的颜色贴图用 KTX2 保证显存,次要贴图(比如一个小 emissive)用 WebP 省事。不必一刀切全 KTX2,按瓶颈分配。

决策流程图:一步步选

矩阵是结果,流程图告诉你怎么走到那个结果。

你的项目跑在哪?
│
├─ 桌面 Web(显存宽裕)
│   └─ 首屏慢吗?
│       ├─ 慢 → WebP(或 AVIF)+ MeshOpt  [追求下载速度]
│       └─ 不慢,但模型多 → KTX2 + MeshOpt [为未来留余地]
│
├─ 移动 Web / VR / 大场景(显存紧)
│   └─ 纹理必上 KTX2(颜色 ETC1S,数据 UASTC)
│       └─ 模型顶点超密?
│           ├─ 是 → + Draco [极限压缩,能接受慢解码]
│           └─ 否 → + MeshOpt [均衡]
│
└─ 小程序 / 受限运行时
    └─ 包体敏感吗?
        ├─ 敏感 → 纯量化或 MeshOpt + WebP [零/小解码器]
        └─ 还行 → MeshOpt + KTX2 [常规组合]

顶点压缩 vs 纹理压缩:该投哪个

经常有人问:预算有限,先优化哪头?看模型构成:

模型特征投入重点原因
PBR 角色/产品(贴图多)纹理压缩纹理占 80%+,投顶点回报低
CAD/扫描模型(顶点超密、贴图少)顶点压缩顶点是主要体积
动画角色(骨骼+蒙皮)两头都投,但顶点优先 Draco 之外动画数据也占体积,Draco 对动画支持弱
建筑/场景(大、中等贴图)纹理 + LOD纹理省显存,LOD 省 draw call

一个粗略的收益排序:纹理 KTX2 > 顶点 MeshOpt/量化 > 几何简化(LOD) > 顶点 Draco。先做收益高的。

混合策略:关键贴图 KTX2,次要贴图 WebP

不是所有贴图都值得压成 KTX2。一个典型的 PBR 材质有 5-6 张贴图,全压 KTX2 工程量大,有时也不必要。

实用分法:

  • 必 KTX2:albedo(大、颜色)、normal(精度敏感)、roughness/metallic(影响光照)
  • 可 WebP/JPG:emissive(通常小)、AO(中低频)、细节法线(如果有的话)

判断标准:贴图大不大、是不是高频细节、会不会频繁采样。三者都中 → KTX2;都不中 → 传统格式省事。

自动化选型:gltf-transform 一键搞定

gltf-transformoptimize 命令是绝大多数场景的银弹——它会自动判断贴图类型、按推荐策略压缩纹理、可选地处理顶点。

# 安装
npm install -g @gltf-transform/cli

# 标准优化:纹理 KTX2 + 顶点 MeshOpt + 去冗余
gltf-transform optimize model.glb model-optimized.glb \
  --texture-compress basisu \
  --meshopt

参数说明:

参数作用默认
--texture-compress basisu纹理压成 KTX2(自动选 ETC1S/UASTC)
--meshopt顶点启用 MeshOpt 压缩
--simplify几何简化(减少顶点,有损)
--weld合并重复顶点
--prune移除未使用的节点/材质

一个适合移动端的「强力压缩」组合:

gltf-transform optimize model.glb model-mobile.glb \
  --texture-compress basisu \
  --meshopt \
  --simplify --simplify-ratio 0.5 \
  --prune --weld

桌面端「温和」组合(保留细节,只压纹理和顶点):

gltf-transform optimize model.glb model-desktop.glb \
  --texture-compress webp \
  --meshopt

编写成可复用脚本

把上面封装成按平台产出多个版本的脚本:

// compress.mjs —— 按 target 输出不同压缩版本
import { optimize } from "@gltf-transform/functions";
import { NodeIO } from "@gltf-transform/core";
import { KHRONOS_EXTENSIONS } from "@gltf-transform/extensions";

const io = new NodeIO().registerExtensions(KHRONOS_EXTENSIONS);

const targets = {
  // 移动端:KTX2 + MeshOpt + 简化
  mobile: { texture: "basisu", meshopt: true, simplify: 0.5 },
  // VR:KTX2 + MeshOpt,不简化(VR 近距离观看)
  vr: { texture: "basisu", meshopt: true, simplify: null },
  // 桌面:WebP + MeshOpt,温和
  desktop: { texture: "webp", meshopt: true, simplify: null },
};

const input = process.argv[2];
const doc = await io.read(input);

for (const [name, cfg] of Object.entries(targets)) {
  const out = doc.clone(); // 每个目标独立副本
  await optimize(out, {
    textureCompression: cfg.texture,
    meshCompression: cfg.meshopt ? "meshopt" : null,
    simplify: cfg.simplify != null ? { ratio: cfg.simplify } : null,
  });
  await io.write(`model-${name}.glb`, out);
  console.log(`✓ model-${name}.glb`);
}
node compress.mjs model.glb
# 输出 model-mobile.glb / model-vr.glb / model-desktop.glb

运行时按设备加载对应版本(用 UA 或 WebGL 能力探测区分),首屏体验最优。下一篇的端到端实战会把这套完整串起来。

一句话备忘

  • 显存是瓶颈 → KTX2,没得选
  • 下载是瓶颈、显存宽裕 → WebP/AVIF 也行
  • 解码器体积敏感 → MeshOpt > 纯量化 > Draco
  • 超大模型 → 才考虑 Draco
  • 拿不准 → gltf-transform optimize 一键跑,错了再调

下一步

选型框架有了,最后一篇收官:从一个真实模型出发,走完 Blender 导出、纹理压缩、顶点压缩、引擎加载的全流程,并附上完整自动化脚本和系列速查表。

赞助支持