Blog · Deep dives
Draco compression explained
Draco is the reason a 100 MB raw 3D model can load on a phone over 4G in under a second. It's an open-source geometry compression library Google published in 2017, now baked into the glTF spec and used by Sketchfab, Google Maps, e-commerce viewers, and most production WebXR. Here's what it does, how it does it, and when it's the right tool.
The problem Draco solves
Uncompressed 3D geometry is huge. A million-triangle mesh with positions, normals and UV coordinates takes around 35 MB in the standard glTF/GLB binary layout. That's fine if it's loading from disk, painful over the web.
General-purpose compression like gzip helps a little but not a lot — typically 1.5–2x reduction on already-binary 3D data, because the byte patterns don't repeat the way text does. You need something that understands what the bytes mean.
What Draco does
Draco is a specialised codec for triangle meshes. It exploits things general compressors can't:
Vertex prediction from neighbours
Adjacent vertices on a smooth surface are usually close to each other in space. Instead of storing each vertex's absolute position, Draco stores it as a delta from a prediction made from already-decoded neighbours. The deltas are smaller numbers than the absolutes, so they encode in fewer bits.
Quantisation with controllable precision
Floating point positions usually carry far more precision than the model needs. A character model that's 2 metres tall doesn't need sub-micrometre vertex accuracy. Draco quantises positions to a configurable bit depth — 14 bits is the typical default, giving roughly 16 000 distinct positions along each axis (about 0.01% of the bounding box). That alone halves the bits before any other compression kicks in.
Normals, UVs, vertex colours all quantise too, with different defaults — 10 bits for normals, 12 bits for UVs.
Connectivity compression
The triangle index list is compressed using a corner-table representation and Edgebreaker — a 1998 algorithm that encodes triangle connectivity as a sequence of letters describing how each triangle attaches to its neighbours. Very efficient on real-world manifold meshes.
Entropy coding
The final pass is range coding (related to arithmetic coding), which squeezes out residual redundancy in the quantised, predicted, connectivity-compressed stream.
Real-world numbers
Typical compression ratios on production glTF models:
- 5–15x smaller bytes for geometry buffers vs. uncompressed glTF.
- The textures, which often dominate file size for textured models, are unaffected — Draco only compresses geometry. Use KTX2/Basis for textures.
- A 50 MB raw GLB with both geometry and 4K textures typically becomes 8–12 MB with Draco + KTX2 — the textures are usually the bigger remaining chunk.
The cost — decode time
Draco is asymmetric — encode is slow, decode is fast but not free. On a desktop, decoding a million-triangle Draco mesh takes 100–300 ms. On mobile, 300–800 ms. For most use cases that's fine, but it does mean for very small meshes Draco isn't worth it — the decode overhead can exceed the bytes you save.
Three.js and most loaders run Draco decode in a worker so it doesn't block the main thread.
When to use Draco
- Web delivery — almost always worth it. Network is slower than decode.
- Mobile — worth it for the bandwidth save, especially on 4G/5G.
- Models over ~1 MB raw — savings comfortably exceed decode cost.
When to skip it
- Tiny models (under 200 KB) — decode overhead exceeds bandwidth save.
- Editing workflows that need to round-trip through DCC tools — Draco-encoded models lose tiny amounts of vertex precision per round trip.
- Slicers for 3D printing — they don't read Draco GLB anyway; export uncompressed STL instead.
How to apply Draco
With glTF-Transform CLI:
npm install -g @gltf-transform/cli gltf-transform draco model.glb model-draco.glb
With Blender: in the glTF export dialog, tick "Compression" — Blender applies Draco automatically.
With three.js: nothing changes on your side. The standard GLTFLoader reads Draco automatically as long as you've registered the DRACOLoader with the decoder path.
Draco vs Meshopt
Meshopt is a newer alternative compression scheme (Arseny Kapoulkine, 2020). Trade-offs:
- Draco compresses slightly tighter, especially for large meshes.
- Meshopt decodes 5–10x faster and uses less memory during decode.
- Meshopt streams better — you can render before fully decoded.
For modern projects starting fresh, Meshopt is increasingly preferred for the decode performance. For maximum file size reduction, Draco still wins by a small margin.