Decompress CompressedTexture

My project is a 3d editor there is some functionality to export gltf file, but i’ve noticed that CompressedTextures are not showing well in gltf. Wanna try decompression before creating glft.
I used KTX2Loader to compress textures.
Are there any ways to decompress CompressedTexture?

Do you mind explaining in more detail what you mean by that?

map property not applying correctly and envMap makes me scared

The screenshot clarified things. The three.js editor does not supported compressed textures since this type of textures does not support serialization/deserialization yet, see:

There is no tool in the repository that can decompress a KTX2 texture into raw RGBA textures. At least KTX2Loader will always produce some sort of compressed texture.

@donmccurdy What do you recommend for such a use case.

If @Dmitry-Romanchuk-Unilimes is building a 3D editor, the best thing would be to keep the original uncompressed textures around somewhere. KTX2 compression is lossy, so going from PNG → KTX2 → PNG is not ideal.

If you do need to decompress a KTX2 texture though, libktx.js can do it (I haven’t used this before), or you can always create a WebGLRenderer with the same dimensions as the texture, draw the texture to a plane with MeshBasicMaterial, and save the result. I’ve done that to render small preview tiles for KTX2 images in the past.


Hey @donmccurdy
Thx for ideas, will try something tomorrow.
Also i’ve found this thread, looks like somebody tried to add decompression to three.js texture utils.

And diff: GLTFExporter: export from compressed texture data by hybridherbst · Pull Request #23321 · mrdoob/three.js · GitHub
Have you seen this?

Yes, I think the code you see in that PR under examples/jsm/utils/TextureUtils.js is a good way to decompress textures from KTX2 to traditional image formats using THREE.WebGLRenderer. :+1:

Hey @donmccurdy
I’ve tried to use decompress function, but result was strange.
What do you think of this code (not as a clean code, but as an idea):

nextElement.traverse((innerObj) => {
  if(innerObj.isMesh) {
    if(innerObj.material) {
      if( instanceof THREE.CompressedTexture) {
        const compressed =;
        const decompressed = decompress(compressed, compressed.image.width); = decompressed;

Here’s how it looks in gltf (i use gltf viewer):

And how this models with compression look in my editor (so expected result was something like this):

Anyway thanks for your help.

btw does CompressedTexture, created with KTX2, contain any links to original texture image or links to texture before compression?

No, since the KTX2 file itself is compressed and does not hold the original, raw image data.

@Mugen87 The problem is we have glb files on a bucket and they are already compressed themselves with Meshopt and have compressed textures with KTX2, so to load them i use this stuff:

const dracoLoader = new DRACOLoader();

const ktx2Loader = new KTX2Loader();

const __GLTFLoader = new GLTFLoader()
  .setDRACOLoader( dracoLoader )
  .setKTX2Loader( ktx2Loader.detectSupport( new THREE.WebGLRenderer() ) )
  .setMeshoptDecoder( MeshoptDecoder );

Not sure I have access to original image in this case (will be very happy if i’m wrong).
I’ve used decompression functionality like it’s on my previous post, but it didn’t work as expected for me (also will be very happy if it’s my mistake).
Are there any other ideas? Thx!

As the PR you linked to is still open and under review, I can’t offer you a working solution. That PR is the most complete code I have seen for the purpose.

We could also provide a way to configure KTX2Loader so that it always transcodes to RGBA8, instead of using a GPU compression format, perhaps. Then GLTFExporter should be able to handle the rest, with some minor changes?

Also note that GLTFExporter will not be able to export files that have been previously Meshopt-compressed, until the next three.js release. It requires features added in GLTFExporter: Add support for signed data types. by spearwolf · Pull Request #25297 · mrdoob/three.js · GitHub.

So when pull request will be approved this problem with Meshopt+KTX can be solved with basic functionality of three.js?

I have no estimate for that, sorry. In the meantime I would recommend using the code as a reference.