THREE.GLTFExporter causing huge size difference

hey everyone, has anyone got any ideas about working with THREE.GLTFExporter to export out three.js scene as gltf or glb ? I am trying to implement an export as gltf option currently but I noticed that the exported gltf or glb file is much bigger than the objects in the scene, for example if the scene contained only a gltf model of size 1 mb (including bin and all texture files), the exported gltf (or the glb file by setting the binary option to true) comes out to be over 4mb, I noticed that the exported gltf file has the base64 inside itself for the textures etc which were outside the original gltf file). Is the size increase solely due to the fact that base64 is used ? And can this be reduced in any way ?

gltf is a json file. glb is a binary file with a json section. In a json file you can’t just write binary, you need to encode it. Encoding is not free in terms of space. Also, bear in mind that a giant json file (gltf with embedded buffers) will take some time to decode also. Overall - gltf is not what you want if you want 1 file. If you want a neat separation between texture files, metadata, buffers - gltf is great, otherwise - stick to glb, that would be my advice.

I think the embedded buffers or images in .gltf tend to add about 25–30% to your file size, so .glb (the {binary:true} option on GLTFExporter) is probably better for a single file as @Usnul says. But I’m surprised you’re seeing results 4X larger — that sounds like this bug, maybe the textures are being converted from JPG to PNG on export?

1 Like

I’ve also encountered this problem, been meaning to explore it further and raise a bug for a month or so now. It’s definitely images being saved in a much larger format than the original file.

Same here.

I thought it might be related to three-js resizing images that aren’t power of 2 but that’s not it.

Here are to same maps (occlusion, roughness, metallic) before:

wire_088144225_occlusionRoughnessMetallic

And after:

1

Both are 2048X2048 PNG files.

The first is 509KB and the second is 1.28MB.

BTW total model was 4.6MB and after the Export it’s 13.3MB.

I’ve tried to use tinypng and both files has been reduced bu the same exact amount of KB (431.9 KB).

The bin file was 961KB and the base64 octet-stream under {buffers {uri: "base64 . . ."}} is 1.44MB.

On Firefox it is working much better.

Terns out chrome increases the images size when using canvas.toDataURL( mimeType ).

More details here.

Tried to open an issue on chromium but after I wrote all of the details I got this message The page you asked for does not exist.

The only solution is to use the embedImages: false options parameter when using the exporter.

That way you will have the location of the original image instead of the base64 newer and bigger one.

Not a good solution but it looks like a chrome bug so three-js community probably wont solve this one.

1 Like

Just to confirm @ranbuch — using binary: true is giving you the expected file sizes, but binary: false with embedded images (as Data URIs) is much larger in Chrome than in Firefox? Or is binary: true inflating textures too?

There are some pretty easy tools to pack and unpack GLB<->GLTF so if GLB is working for you, those may be helpful.

If I understood correctly binary: true => GLB and binary: false is glTF.
One way or the other doesn’t effect the images sizes.

If however you will use embedImages: false, instead of base64 embedded images you’ll get the images src (actual URL) from whatever server they came from.

That way the images size obviously won’t change but you are depending on the images availability.

If they will be deleted or in case of no network coverage you won’t get you’re textures.

That’s correct.

One way or the other doesn’t effect the images sizes.

I’m surprised by that part … GLB should not be using Data URIs, so either Chrome has the same bug with toBlob(), or GLTFExporter is accidentally putting the data through a Data URI when writing to GLB.

When using binary: true file size was ‘10.0MB’ and when using ‘binary: false’ file size was 13.3MB.

Either way it’s much bigger then the original 4.6MB file.

After using binary: true with embedImages: true again and loading the 10MB GLB to three-js I’ve saved (via chrome web-tools) the same (occlusion, roughness, metallic) map and the size is exactly the same - 1.28MB (instead of 509KB as I have stated above).

Even if Chrome is saving all of the images and data in a binary format the images are still to big.

Yes, that’s a bug in chrome because it’s not reproducible on Firefox.

Problem still exists. The problem is probably with canvas.toBlob here three.js/GLTFExporter.js at 3eaed95151df934d72ec2534883971a6a997244e · mrdoob/three.js · GitHub in three.js/examples/jsm/exporters/GLTFExporter.js toBlob accepts third parameter which is quality, but changing it has no effect on chrome or Firefox.

GLTFExporter does not have access to the original image, and must re-compress it. With that limitation, the size of the output is certainly going to change. If the original was compressed much better than the browser achieves (entirely possible) then the new output will become larger. If you need a lossless roundtrip for textures, it would be necessary to keep track of the original texture data separately.