Store textures as KTX2 with Basis Universal supercompression, ship them small over the network, then transcode in the browser to a block-compressed format the GPU supports (ASTC, ETC, BC) before uploading – this shrinks both download size and GPU memory, since WebGL keeps compressed textures compressed in VRAM instead of expanding them.
At a glance
| Fact | Value | Source |
|---|---|---|
| KTX2 container purpose | reduce size + GPU memory | khronos.org |
| glTF extension for KTX2 Basis textures | KHR_texture_basisu | github.com |
| WebGL never decompresses compressed textures itself | must be pre-compressed | developer.mozilla.org |
Encode your textures as KTX2 with Basis Universal supercompression, then transcode them in the browser to a GPU-native block-compressed format (ASTC, ETC2, BC7 etc.) before upload. The point of KTX2 is exactly this two-stage benefit: a small download, then a small GPU-resident texture, because “KTX (Khronos Texture) is an efficient, lightweight container format supported by glTF for reliably distributing GPU textures to a diverse range of platforms to reduce asset file size and GPU memory usage”. To test builds with these textures, Playgama MCP lets an agent publish a sandbox directly from Claude Code, Cursor or VS Code.
Why this actually saves GPU memory, not just download size
A plain JPEG or PNG texture has to be fully decoded to pixels before the GPU can use it – that decoded RGBA buffer is what eats VRAM. A KTX2/Basis texture is transcoded once, at load time, into a block-compressed format that the GPU reads directly, so it stays compressed in memory. This matters because WebGL “makes no functionality available to compress or decompress textures: they must already be in a compressed format and can then be directly uploaded to video memory” – the transcode step (via the Basis Universal WASM transcoder) is what produces that already-compressed data.
- Author or bake textures into KTX2 with the Basis Universal supercompression (via
basisuorgltfpack -tc, which requiresKHR_texture_basisusupport). - Load the KTX2 file in-browser and transcode with the Basis Universal WebAssembly transcoder to whatever compressed format the current GPU/browser combo supports.
- Check the target format is actually available – WebGL exposes compressed formats only through extensions, and support varies by device, so query the extension before assuming ASTC or BC7 is present.
- For glTF-based pipelines, confirm your loader (three.js r111+, Babylon.js 4.1+) declares
KHR_texture_basisusupport before relying on it.
Sources
- glTF – Runtime 3D Asset Delivery
- KHR_texture_basisu glTF Extension Specification
- KTX File Format Specification – Version 2.0.4
- BinomialLLC/basis_universal: Basis Universal GPU Texture Codec
- filament/third_party/meshoptimizer/gltf/README.md
- Compressed texture formats – MDN
- Playgama for developers
Related questions
Does KTX2 reduce download size as well as GPU memory?
Yes – Basis Universal supercompression shrinks the file for transfer, and the same data transcodes at load time into a GPU-native compressed format, cutting VRAM use too.
Do I need a special extension to use KTX2 textures in glTF?
Yes, the KHR_texture_basisu extension, which points a texture’s source at a KTX v2 image using Basis Universal supercompression instead of PNG or JPEG.
Can WebGL decompress a KTX2 texture itself?
No – WebGL never compresses or decompresses textures; the browser must transcode the Basis Universal data to an already-compressed format before uploading it to the GPU.
Last updated: 30 September 2026