Geometry compression (Draco or meshoptimizer)
Shrinking a mesh's vertex data so a fat GLB downloads fast: quantize the numbers, reorder them, compress. Draco and meshopt do this.
See it
What it is
Raw mesh data is mostly wasted bits. Every vertex carries a position, a normal, UVs, maybe tangents and skin weights, and the common ones usually arrive as 32-bit floats carrying far more precision than a model a few meters across will ever use. (Not all of it is floats: indices and joint indices are integers, and some exporters already write normalized shorts or bytes.) Geometry compression quantizes those numbers down (positions to 14 bits, normals to 10, UVs to 12), reorders vertices and triangles so similar values sit next to each other, then entropy codes the result. On a mesh-heavy file that can take an order of magnitude off the geometry. How much it takes off the whole GLB depends entirely on how much of the file is mesh data: compression does nothing for embedded textures, and in plenty of product models the textures are the bigger half.
Two contenders. Draco compresses hardest but ships a wasm decoder of a few hundred KB and takes real CPU time to unpack. That is not automatically a frozen main thread, since loaders can and commonly do decode it in a worker, but it is CPU you spend either way. meshoptimizer (EXT_meshopt_compression) produces slightly bigger files that decode almost instantly with a tiny decoder, and it also reorders indices for the GPU vertex cache. For most web scenes meshopt is the better default; Draco wins when bandwidth is the hard constraint. Run either through gltf-transform or gltfpack, and remember the loader needs the matching decoder wired up or the model silently fails.
Gotcha, and it's the big one: compression is not simplification. A two million triangle mesh is still two million triangles after decoding, with the same draw cost and the same VRAM. If the framerate is the problem, you want decimation or LODs, not Draco. Quantizing too aggressively also cracks seams and makes normals wobble, so bump position bits back up if edges start splitting apart.
Ask AI for it
Compress this glTF/GLB for web delivery using gltf-transform. Run dedup, weld, and prune first, then quantize (positions 14 bits, normals 10, UVs 12), then apply EXT_meshopt_compression. Wire up MeshoptDecoder on the three.js GLTFLoader via setMeshoptDecoder. Print the before and after file size plus triangle count, and do not reduce triangle count as part of this: if edges crack or seams split, raise the position quantization bits until they don't.