KTX2 实战:纹理压缩的正确打开方式
上一篇把 GPU 纹理格式、Basis Universal、KTX2 的关系讲清楚了。道理懂了,这篇全是动手:ETC1S 和 UASTC 怎么选、用什么工具、命令怎么敲、引擎里怎么加载。
可以照着抄,边看边做。
先解决最重要的一个选择:ETC1S 还是 UASTC
Basis 提供两种中间编码,选错了不是「不够好」的问题,而是法线贴图直接糊掉。先把这张表记住:
| ETC1S | UASTC | |
|---|---|---|
| 压缩率 | 极高(类似 JPG) | 中等(类似高质量 PNG) |
| 画质 | 颜色类贴图够用 | 接近原始质量 |
| 显存(转码后) | 通常 4bpp(约 1/8 原始) | 通常 8bpp(约 1/4 原始) |
| 编码速度 | 慢(可调级别) | 较快 |
| 适用 | albedo/漫反射、emissive | normal、metalness-roughness、数据贴图 |
| 不适用 | normal、需要精确数值的图 | 颜色贴图(杀鸡用牛刀,体积偏大) |
为什么法线贴图不能用 ETC1S?因为法线贴图存的是方向向量,每个像素的 RGB 三个通道互相约束(向量长度 ≈ 1)。ETC1S 是为「颜色看起来对」设计的块压缩,它对单通道精度不敏感,压完之后向量方向会偏,光照立刻显得不对——尤其是高光位置和高频细节。UASTC 对数值保留得更好,能扛住这种精度要求。
实用规则:
- 颜色贴图(albedo、emissive)→ ETC1S
- 数据贴图(normal、roughness、metallic、AO、thickness)→ UASTC
- 拿不准、又想省体积 → 先试 ETC1S,特写下糊了再换 UASTC
同一张图,四种格式比一比
用一张 2048×2048 的 albedo 贴图做基准(数据为社区典型值,仅供参考):
| 格式 | 磁盘大小 | 显存占用(含 mipmap) | 上传到 GPU | 跨平台 |
|---|---|---|---|---|
| PNG | ~5MB | ~22MB | 慢 | ✅ |
| WebP | ~1MB | ~22MB | 慢 | ✅ |
| KTX2 (ETC1S) | ~0.5-0.8MB | ~2.8MB | 快 | ✅ |
| KTX2 (UASTC) | ~3-4MB | ~5.6MB | 快 | ✅ |
注意 WebP 的显存占用和 PNG 一样——它只是磁盘小,进了显存照样解压成原始像素。KTX2 的 ETC1S 把磁盘和显存同时打到很低,这就是它值钱的地方。
工具链:三条路都通
压缩 KTX2 的工具不止一个,按「顺手程度」排:
1. toktx(官方、最强大)
Khronos 官方工具,参数最全,适合单独处理纹理。
# 把 PNG 转成 ETC1S 编码的 KTX2
toktx --bcmp --uastc 0 albedo.ktx2 albedo.png
# 把 PNG 转成 UASTC 编码的 KTX2
toktx --uastc 1 normal.ktx2 normal.png
常用参数:
# ETC1S + 质量档位(1-255,默认 128,越高画质越好体积越大)
toktx --bcmp --uastc 0 --qlevel 200 albedo.ktx2 albedo.png
# UASTC + 超级压缩(Zstandard,进一步缩小磁盘体积)
toktx --uastc 1 --zcmp 19 normal.ktx2 normal.png
# 自动生成 mipmap(强烈建议加)
toktx --bcmp --genmipmap albedo.ktx2 albedo.png
# 指定 sRGB 色彩空间(颜色贴图必须)
toktx --bcmp --srgb albedo.ktx2 albedo.png
--bcmp是 ETC1S 模式的开关(Basis Universal 的基础模式),--uastc 1是 UASTC 模式。两者互斥。
2. gltf-transform(最省事,强烈推荐)
如果你手上是整个 glTF/GLB 模型,用 gltf-transform 一条命令把里面所有纹理换成 KTX2,按贴图用途自动选 ETC1S/UASTC。
# 安装
npm install -g @gltf-transform/cli
# 一键压缩整个模型
gltf-transform optimize model.glb model-optimized.glb \
--texture-compress basisu
它内部会判断贴图用途:颜色类用 ETC1S,数据类用 UASTC,并自动写好 KHR_texture_basisu 扩展。这是 90% 场景的最佳选择,不用一个个手动敲 toktx。
3. 在线工具(最快上手)
不想装环境时,直接用浏览器工具:gltf.report(在线版 gltf-transform)、KTX2 Converter 等。上传,下载,完事。适合早期试验或一次性任务。
完整 pipeline:从源文件到上线
整理一下标准流程(流程图):
源文件(PNG/JPG/PSD/TGA)
│
├── [整模型] gltf-transform optimize model.glb → 自动识别贴图类型
│ └─ 颜色贴图 → ETC1S
│ └─ 数据贴图 → UASTC
│ └─ 写入 KHR_texture_basisu 扩展
│
└── [单张贴图] toktx → 手动指定 ETC1S/UASTC + 色彩空间 + mipmap
│
▼
压缩后的 KTX2 / GLB
│
▼
引擎加载(Three.js / Babylon.js)── 运行时转码 → GPU 原生格式
Three.js 里加载 KTX2
Three.js 从 r129 起原生支持 KTX2:把 KTX2Loader(指定 basis transcoder wasm 路径、探测 GPU 能力)挂到 GLTFLoader,之后加载含 KTX2 纹理的 glTF 会自动转码。
const ktx2Loader = new KTX2Loader().setTranscoderPath("/basis/").detectSupport(renderer);
gltfLoader.setKTX2Loader(ktx2Loader); // 模型若同时用 Draco/MeshOpt,记得一并挂 DRACOLoader / MeshoptDecoder
detectSupport(renderer) 必须调——它决定运行时转码成哪种原生格式。另外颜色贴图要设 texture.colorSpace = THREE.SRGBColorSpace,漏设就是经典的「整张图发灰」坑(normal/roughness 等数据贴图保持线性)。
Babylon.js 里加载 KTX2
Babylon 更省心——GLTFFileLoader 默认开启 KHR_texture_basisu,并自动从 CDN 拉取 basis transcoder,加载含 KTX2 的 glTF 开箱即用。离线/内网环境需手动配置 BASISFileLoader.TranscoderModule。
压缩参数调优:质量与体积的平衡
ETC1S 的核心参数是 --qlevel(1-255)。它怎么影响结果:
| qlevel | 体积 | 画质 | 编码耗时 | 适用 |
|---|---|---|---|---|
| 128(默认) | 小 | 够用 | 中 | 多数情况 |
| 200-255 | 偏大 | 接近无损 | 长(数倍) | 高质量要求 |
| 60-100 | 很小 | 有可见块状 | 快 | 远景/小贴图 |
UASTC 体积相对固定,主要靠 --zcmp(Zstandard 超级压缩)调磁盘大小,不影响显存(解压后还是 8bpp)。
调优顺序建议:
- 先用默认参数压一遍,看体积和画质
- 不满意 → 调
--qlevel(ETC1S)或加--zcmp(UASTC) - 法线贴图糊了 → 确认用的是 UASTC,不是 ETC1S
- 颜色偏暗 → 检查色彩空间设置(sRGB 标志、引擎里的 colorSpace)
常见问题排查
转码失败 / 加载报错
- 检查 transcoder wasm 路径是否正确(Three.js 要
setTranscoderPath) - 检查引擎版本是否支持当前 KTX2 版本(旧版 basis 编码不被新版 transcoder 支持)
- 控制台通常会有具体错误,按关键词搜
颜色偏暗 / 偏亮
- 颜色贴图(albedo)没设 sRGB,或设反了
- toktx 时漏了
--srgb(颜色贴图要加) - 数据贴图(normal)误加了 sRGB
mipmap 缺失,远处闪烁
- 压缩时没加
--genmipmap - 引擎里
texture.generateMipmaps没开(Three.js 里 KTX2 默认随文件,但仍需材质minFilter用 mipmap 模式)
特写下法线方向不对
- 法线贴图用了 ETC1S,换 UASTC
- 确认法线贴图是 OpenGL 风格(绿色通道朝上),DirectX 风格在某些引擎里要翻转 G 通道
文件反而变大了
- 小尺寸贴图(< 128×128)用 KTX2 不划算,块压缩有固定开销,会占满整个块
- 纯色贴图别压 KTX2,直接用材质色值更省
下一步
纹理压缩这块到这就基本通关了。但「会用工具」不等于「会用对工具」——下一篇把前 4 篇的所有知识汇总成一个选型框架:桌面、移动、VR、小程序,每种场景到底该用哪种组合。