Appearance
KTX2 与 Draco 压缩方案
Web 端 3D 的第一道生死线是下载体积:虚拟形象全套模型原始 22MB,4G 下首屏要等到用户流失完。用 KTX2 压纹理、Draco 压几何,全套压到 6MB,核心形象压进 3MB。
全套模型22MB → 6MB
纹理体积-60~80%
几何压缩率≈70%
背景
Web 端虚拟形象项目的资源分两块:纹理(PNG/JPEG)和几何(GLB 里的顶点、法线、UV)。传统 WebGL 管线里这两块各有一个结构性浪费:纹理要先 CPU 解码成 RGBA32 再上传 GPU,显存里存的是未压缩位图;几何数据按 float32 原样存储,传输量随模型精度线性膨胀。
问题
| 问题 | 量化表现 |
|---|---|
| 下载体积 | 全套模型 22MB,移动端首屏不可接受 |
| 显存占用 | PNG 解码成 RGBA32 上传,显存是文件体积的数倍 |
| 解压阻塞 | 几何解压放主线程会卡交互 |
方案
mermaid
flowchart TD
A["美术导出 GLB(原始 20MB+)"] --> B["纹理: PNG → KTX2<br>toktx --bcmp --zcmp"]
A --> C["几何: Draco level 10<br>gltf-pipeline"]
B --> D["运行时: GPU 原生解码<br>无需 CPU 解压成 RGBA32"]
C --> E["运行时: DRACOLoader<br>Web Worker 异步解压"]
D --> F["最终 GLB 3MB 以内"]
E --> F两条压缩路径互相独立、各自闭环:KTX2 解决「显存 + 体积」,Draco 解决「体积 + 传输」。
关键实现
KTX2:让 GPU 自己解压
传统流程是 PNG/JPEG → CPU 解码 → 未压缩格式上传 GPU → 显存爆炸。KTX2 的思路是把压缩格式一路送到 GPU,由硬件原生解码——BC7(Desktop)、ETC2(Android)、ASTC(iOS/新 Android)都是 GPU 直接支持的块压缩格式,显存里存的还是压缩态。
转换命令:
bash
# PNG → KTX2(Basis UASTC/ETC1S + zstd 超压缩)
toktx --t2 --bcmp --zcmp 16 output.ktx2 input.png代价是平台格式分裂,需要多份压缩格式加运行时检测:
| 平台 | BC7 | ETC2 | ASTC |
|---|---|---|---|
| Desktop | ✅ | — | — |
| Android | — | ✅ | ✅ |
| iOS | — | — | ✅ |
收益:纹理体积减少 60–80%,显存占用同比例下降,CPU 解码整个环节被删掉。
Draco:几何数据压到三成
Draco 是 Google 开源的 3D 几何压缩库,专为 Web 传输优化,对顶点位置、法线、UV 做量化和熵编码:
bash
# GLB → Draco GLB
gltf-pipeline -i input.glb -o output.glb --draco.compressionLevel=10Three.js 端用 DRACOLoader 异步解压。两个关键取舍:
- 压缩级别拉到 10(最高):解压略慢,但放在 Web Worker 里跑,不阻塞主线程,用户无感知;
- 机型分级:低端机跳过 Draco 解压直接用简化模型,高端机用最高压缩——解压算力和下载带宽哪个是瓶颈,按机型分别回答。
实测压缩效果
| 模型 | 原始 GLB | Draco 压缩 | 压缩率 |
|---|---|---|---|
| 虚拟形象身体 | 8MB | 2.5MB | 69% |
| 配件(头发) | 3MB | 0.9MB | 70% |
| 全套(含 5 个配件) | 22MB | 6MB | 73% |
叠加 KTX2 后,核心形象(身体 + 默认发型)压进 3MB 以内,达到移动端可秒开的量级。
指标
| 指标 | 优化前 | 优化后 |
|---|---|---|
| 全套模型体积 | 22MB | 6MB(-73%) |
| 核心形象体积 | 20MB+ | 3MB 以内 |
| 纹理体积/显存 | 基线 | -60~80% |
| 解压线程模型 | 主线程风险 | Web Worker 异步 |
复盘
- Web 端 3D 优化先砍体积再谈帧率——用户等不到渲染那一帧,压缩是投入产出比最高的一步。
- KTX2 的真正收益在显存而不是下载体积,低端机 OOM 崩溃里有一大半能被它消掉。
- Draco 级别 10 + Web Worker 是固定搭配;在主线程跑高级别解压等于把下载省下的时间还给白屏。
- 压缩方案必须配机型分级,低端机的瓶颈是解压算力,高端机的瓶颈是带宽,一套参数打两边必然有一边吃亏。