压缩纹理
「导出」暂不支持压缩纹理格式
简介
KTX2 (Khronos Texture Container version 2.0) 是 Khronos 推出的现代纹理容器格式。KTX2 会根据设备平台支持,在运行时转码到对应格式的压缩纹理(ASTC/ETC/BC/PVRTC等)。压缩纹理在移动设备上的内存占用比传统图片格式低很多。glTF 中使用 KTX2 需要包含 KHR_texture_basisu 扩展。Galacean Effects 自 2.8.0 版本开始支持 KTX2。
考虑到 ASTC 4×4 格式在移动设备上的广泛支持度(覆盖几乎所有现代移动设备),Galacean Effects 采用 UASTC 编码存储在 KTX2 容器中,在运行时转码为 ASTC 4×4 压缩纹理。这种方案简化了集成复杂度并保证了最佳兼容性。
原始图片 → UASTC 编码 → KTX2 容器 → Runtime 转码 → ASTC 4×4 → GPU使用
1. 动效制作发布
在发布时,使用极速发布并勾选“使用压缩纹理”:

推荐使用体积更小策略
2. 插件引入
需要额外接入插件(请确保插件版本号与
@galcean/effects 版本号一致)。
安装依赖
$ npm i @galacean/effects-plugin-ktx2 --save代码引入
import { Player } from '@galacean/effects';
// 确保在 @galacean/effects 引入之后再引入插件, 插件版本保持和 @galacean/effects 一致
import '@galacean/effects-plugin-ktx2';3. 运行时使用
a. 方案 A:使用 AssetManager 预加载(推荐)
创建AssetManager和loadScene 时设置 useCompressedTexture: true
const assetManager = new AssetManager({ useCompressedTexture: true }); // ✅ 启用 KTX2
const loadedScene = await assetManager.loadScene(sceneData, player.renderer);
await player.loadScene(loadedScene, {
useCompressedTexture: true,
});b. 方案 B:直接加载场景
loadScene 时设置 useCompressedTexture: true
await player.loadScene('xx.json', {
useCompressedTexture: true,
});Runtime 会默认使用主线程解析 KTX2 文件,如若想使用 WebWorker 解析,可先注销后再注册:
import { unregisterKTX2Loader, registerKTX2Loader }
from '@galacean/effects-plugin-ktx2';
// 先注销 KTX2 加载器
unregisterKTX2Loader();
// 使用 WebWorker,worker 数为 2 个
registerKTX2Loader(2);💡小知识
- Worker 的装载有一定的耗时,因设备而异,经真机测试,图片资源较少时(如:支付宝 2025 年度账单),使用主线程解析加载耗时收益较高。如资源非常多,可使用 Worker 解析对比尝试。在实际使用中,建议根据项目实际资源量进行性能对比测试再做选择。
注意事项
- KTX2 转码使用到了
WebAssembly技术,需要保证使用 Chrome 57+,和 iOS 11.3+(11.0 ~ 11.2 以下的 WebAssembly 存在 bug)。 - 使用 Worker 解析,需知晓:iOS 16 以下系统在通过 Worker 加载必要的 KTX2 解析文件时会概率发生无返回的情况。
为什么选择 KTX2 ?
传统纹理格式
以下图为例:前端习惯叫做雪碧图,在游戏界一般叫做 Atlas 图集,原始分辨率为 1024 × 1024,文件大小为 1.7 MB。

一般情况下,浏览器会将 JPEG/PNG 图片文件解压,并解码成显卡可识别的 RGB(A) 位图格式纹理。若图片带有 Alpha 通道,则需要占用 1024 × 1024 × 4 = 4 MB 的内存,这 4MB 的数据同时也需要加载到 GPU 缓存中。
关键点: 无论将图片的存储体积压缩得多么小,其显存开销始终是固定的——引擎运行时纹理占用的显存大小,与图片本身的磁盘大小无关,只与图片的宽度和高度相关。
因此,使用 JPEG/PNG 文件作为纹理时,存在以下问题:
- 🕐 解码耗时:浏览器解压图片存在耗时,图片越大,耗时越长
- 💾 内存占用高:除原始文件的存储外,浏览器和 GPU 还会各自保存一份位图数据(见图示 1)

可以看出,在大体量纹理应用场景下,上述第二个问题的瓶颈会越来越明显,在移动设备上很容易造成 OOM(内存溢出)。
硬件压缩纹理格式
压缩纹理是游戏领域常用的纹理压缩技术,依赖特定硬件实现。经过特定算法压缩后的纹理可直接存储在 GPU 中,只有当 Shader 进行纹理查询(Texture Lookup)时才会触发解压操作,GPU 通常会对解压过程进行优化以提升性能。
相比 JPEG/PNG,压缩纹理在内存上具有质的优势:
- ✅ 显存占用极低:GPU 直接保存压缩后的纹理数据,无需解码为完整位图(见图示 2)
- ✅ 省去解码耗时:无需像 JPEG/PNG 那样进行完整的图片解码
- ✅ 内存可控:如图示 2 所示,JS Heap 中的占用可以手动控制释放

约束与代价
压缩纹理并非没有限制,使用时需注意以下几点:
约束项 | 说明 |
有损压缩 | 压缩纹理属于有损压缩,会对图片质量造成一定损失 |
传输体积 | 压缩纹理的传输体积可能比 JPG/PNG 高 1~4 倍 |
平台差异 | 不同平台支持的压缩纹理格式不同,若需降级兼容,可能需要准备多份资源 |
尺寸要求 | 压缩纹理要求 POT(Power Of Two),即长宽均为 2 的幂次;PVRTC 格式还额外要求长宽相等 |
KTX2 的优势
尽管压缩纹理有着显著的性能优势,但其平台差异性始终是工程实践中的一大难题:
- iOS 设备普遍支持 PVRTC / ASTC
- Android 设备普遍支持 ETC / ASTC
- PC 端 普遍支持 BC 系列格式
不同平台需要分别打包对应格式的压缩纹理资源,若要做到全平台兼容,通常需要维护多套资源,这极大地增加了资源管理和发布的复杂度。
需要维护多套资源:
├─ iOS 设备 → texture.pvr (PVRTC)
├─ 高端 Android → texture.astc (ASTC)
├─ 老 Android → texture.ktx (ETC2)
├─ PC/WebGL → texture.dds (BC7)
└─ 兜底方案 → texture.png
构建脚本:
if (platform === 'ios') {
compile('pvrtc');
} else if (isModernAndroid) {
compile('astc');
} // ...复杂的判断逻辑
发布产物:
resources/
├─ texture.png
├─ texture.pvr
├─ texture.astc
└─ texture.etc2 KTX2 正是为了解决这一问题而生。 它以 UASTC 作为统一的中间格式存储在 KTX2 容器中,在运行时根据当前设备的硬件能力动态转码为对应的压缩纹理格式。它有以下优势:
- 🗜️ 超级压缩:传统压缩纹理(如ASTC/ETC 文件)虽然节省了显存,但其传输体积往往比普通纹理格式还要大。KTX2 在此基础上引入了超级压缩机制,在 GPU 压缩格式之上额外套一层通用压缩,大幅减小文件的传输体积。
- 📦 一份资源,全平台适配:无需为不同平台单独维护多套压缩纹理资源,研发侧只需关注 KTX2 一种格式,无需处理繁琐的平台分支逻辑,降低集成复杂度。
- ✅ 保持压缩纹理的全部优势:传输体积显著小于传统压缩纹理格式,CPU 解压速度快,不影响运行时性能,GPU 侧依然使用原始压缩格式,显存优势完全保留。
- 📋 标准化容器:相比各厂商私有格式(.dds/.pvr 等),KTX2 是 Khronos 制定的开放标准,元数据更丰富,
Mipmap 支持统一,工具链一致(toktx/ktxtools)。 - 🔗 glTF 生态集成:KTX2 已被 glTF 2.0 官方扩展采用(KHR_texture_basisu),Three.js、Babylon.js 等主流 Web 引擎均已内置支持。
在 Galacean Effects 中,考虑到 ASTC 4×4 格式在现代移动设备上的广泛覆盖,运行时统一将 KTX2 转码为 ASTC 4×4 格式,再不支持的设备上会自动降级为 WebP 格式,在保证兼容性的同时实现最佳的内存与性能表现。