Draco vs Meshopt Compression Compared
Two compression systems dominate the glTF ecosystem. This guide explains how each one works, where they differ, and which one fits your project based on real benchmarks and practical tradeoffs.
The Choice
You have a glTF or GLB model that needs to be smaller. Maybe it is a product viewer that takes five seconds to load on mobile. Maybe it is a batch of architectural assets eating through your CDN bandwidth. Either way, you need geometry compression.
Google's Draco and Arseny Kapoulkine's meshoptimizer are the two production options for glTF compression. They solve the same problem with fundamentally different approaches, and choosing the wrong one can cost you performance, compatibility, or both.
Why Compress 3D Geometry?
A raw 3D mesh stores every vertex position as three 32 bit floating point numbers. Normals, UV coordinates, and vertex colors add more. A 500,000 triangle model carries roughly 25 MB of vertex data before textures enter the picture.
On the web, file size translates directly to load time. A 25 MB geometry download takes over 6 seconds on a typical 4G connection. On slower networks, it becomes unusable. E-commerce platforms like Shopify recommend keeping entire 3D models under 5 MB, and Google Merchant Center caps GLB uploads at 15 MB.
Geometry compression reduces that data by encoding vertex attributes at lower precision and removing redundancy from index buffers. The two dominant systems for glTF files are Google's Draco and Arseny Kapoulkine's meshoptimizer. Both are open source, both are widely supported, and both produce dramatically smaller files. But they work in very different ways.
How Draco Works
Draco was released by Google's Chrome Media team in
January 2017 as an open source library for compressing
3D meshes and point clouds. It integrates into glTF files
through the KHR_draco_mesh_compression
extension, a Khronos Group ratified standard.
The compression pipeline has three stages. First, quantization reduces vertex attribute precision from 32 bit floats to a configurable number of bits. The default is 11 bits for positions, 8 bits for normals, and 10 bits for texture coordinates. Each attribute type can be tuned independently. Lower bit counts produce smaller files but introduce rounding artifacts.
Second, prediction schemes reduce entropy before encoding. The parallelogram predictor estimates each vertex position based on adjacent triangle geometry, then stores only the residual (the difference between the prediction and the actual value). Because neighboring vertices on a smooth surface are similar, these residuals tend to be small numbers that compress well.
Third, connectivity compression encodes the triangle index buffer. Draco's primary algorithm, EdgeBreaker, traverses the mesh in a deterministic spiral and assigns each triangle one of five symbols. On typical meshes, this achieves roughly 1 to 2 bits per triangle. The tradeoff is that EdgeBreaker reorders vertices during compression, which means the original vertex ordering is not preserved.
The final step applies entropy coding using rANS (range Asymmetric Numeral Systems) to produce the compressed bitstream.
What Draco compresses: vertex positions, normals, texture coordinates, vertex colors, and index buffers.
What Draco does not compress: texture
image data, morph targets (blend shapes), or animation
keyframes. The KHR_draco_mesh_compression
extension explicitly excludes these data types.
How Meshopt Works
Meshoptimizer was created by Arseny Kapoulkine, a game
technology engineer with over 15 years of experience in
rendering and performance optimization. The library is
written in C/C++ and released under the MIT license. It
integrates into glTF through the
EXT_meshopt_compression extension.
Where Draco prioritizes maximum compression ratio, meshoptimizer prioritizes decode speed and GPU efficiency. The approach has two phases: optimization and compression.
The optimization phase reorders triangles and vertices to improve GPU cache performance. Vertex cache optimization (based on the Forsyth algorithm) arranges triangles so the GPU can reuse recently processed vertices from its cache. Overdraw optimization reorders triangles to minimize redundant pixel shader work. Vertex fetch optimization rearranges the vertex buffer for better memory access locality. These optimizations are independent of compression and improve rendering performance even on uncompressed meshes.
The compression phase uses three codec modes. The attribute codec uses delta encoding across 16 element blocks, exploiting the fact that neighboring vertices have similar values. The triangle codec removes topological redundancy from index buffers. The index codec handles non-triangle primitives like line strips. All three codecs produce byte streams that compress exceptionally well under standard HTTP compression (gzip, Brotli, or Zstandard).
Meshopt also provides specialized filter codecs for different attribute types: octahedral encoding for normals, quaternion encoding for rotations, and exponential encoding for floating point data.
What Meshopt compresses: vertex positions, normals, texture coordinates, vertex colors, index buffers, morph targets, animation keyframes, and instance transforms.
What Meshopt does not compress: texture
image data. The companion tool gltfpack can
apply Basis Universal or WebP texture compression as a
separate step.
Side by Side Comparison
This table summarizes the practical differences that matter when choosing between the two systems.
| Feature | Draco | Meshopt |
|---|---|---|
| Developer | Google (Chrome Media team) | Arseny Kapoulkine |
| glTF extension | KHR_draco_mesh_compression | EXT_meshopt_compression |
| Extension status | Khronos ratified (KHR) | Khronos registered (EXT) |
| Standalone compression ratio | 70% to 95% reduction | 50% to 80% reduction |
| With HTTP compression (gzip/Brotli) | Marginal additional gain | Approaches Draco levels |
| Morph targets (blend shapes) | Not supported | Supported |
| Animation keyframes | Not supported | Supported |
| WASM decoder size (gzipped) | ~150 KB | ~7 KB |
| Decode speed | Moderate (CPU bound) | 1 to 3 GB/s (SIMD accelerated) |
| GPU rendering optimization | No | Yes (vertex cache, overdraw, fetch) |
| Vertex order preserved | No (EdgeBreaker reorders) | Yes |
| Point cloud support | Yes | No |
| three.js support | DRACOLoader (built in) | GLTFLoader.setMeshoptDecoder() |
| License | Apache 2.0 | MIT |
The compression ratio numbers above reflect geometry data only. Neither system compresses texture images, which often account for 60% to 90% of total file size. For texture compression strategies, see the file size reduction guide.
Real Benchmarks
These numbers come from published benchmarks and documented tests, not estimates. Compression ratios vary by model complexity, vertex count, and attribute configuration.
| Model | Original | Draco | Meshopt + gzip |
|---|---|---|---|
| Stanford Bunny (geometry only) | 2.9 MB | 46 KB (98%) | ~200 KB (93%) |
| NYC 3D Building Tileset | 738 MB | 149 MB (80%) | N/A (point cloud) |
| Quantized mesh (glTF Transform test) | 29 MB | ~2 MB (93%) | 2.5 MB (91%) |
| Cesium Buggy model | 7.6 MB | 824 KB (89%) | ~1.2 MB (84%) |
Key takeaway: Draco wins on standalone compression ratio, particularly on large static meshes. When HTTP compression is factored in, the gap narrows considerably. On the glTF Transform test model, the difference was just 2 percentage points.
Decode speed tells a different story. Meshopt's WASM decoder with SIMD processes data at 1 to 3 GB/s on modern desktop CPUs, with the latest version exceeding 5 GB/s on Apple Silicon. Draco's decoder is significantly slower because it must fully reconstruct the original geometry from the compressed bitstream before the GPU can use it.
For interactive web applications where the user is waiting for a model to appear, decode speed can matter more than a few percentage points of compression. For batch asset delivery where files are cached after the first load, raw compression ratio is more important.
When to Use Draco
Draco is the stronger choice in specific scenarios where its tradeoffs align with your requirements.
Large static meshes. If your model is geometry heavy (over 1 MB of vertex data) and has no morph targets or animation, Draco's higher compression ratio delivers meaningful file size savings. CAD visualizations, architectural models, and 3D scans fall into this category.
GIS and 3D Tiles. Cesium's 3D Tiles pipeline uses Draco extensively for compressing building datasets, terrain meshes, and point clouds. Google's own benchmark showed the NYC building tileset dropping from 738 MB to 149 MB with Draco, and load times improving from 18.9 seconds to 10.5 seconds. If you are working with geospatial data, Draco has the strongest ecosystem support.
Point clouds. Meshopt does not support point cloud compression. If your data is a point cloud (LiDAR scans, photogrammetry captures), Draco is the only option in the glTF ecosystem.
Maximum file size reduction is the top priority. When bandwidth cost or storage limits are the primary constraint and decode latency is acceptable, Draco's superior standalone compression ratio wins. Static product images stored in a CDN are a good example: the file is compressed once and downloaded many times.
When to Use Meshopt
Meshopt is the stronger choice when decode performance, animation support, or decoder footprint matter.
Animated models. If your glTF file contains skeletal animation, morph targets (blend shapes), or keyframe data, Meshopt is the only option. Draco's glTF extension does not support any of these data types. Character models, facial animation rigs, and product configurators with animated transitions all require Meshopt.
Fast initial display. Web applications where the user expects the model to appear instantly benefit from Meshopt's decode speed. At 1 to 3 GB/s with WebAssembly SIMD, a 10 MB compressed payload decodes in single digit milliseconds. Draco requires significantly more CPU time because it must fully reconstruct the vertex data. Product viewers, configurators, and interactive demos where perceived load time drives conversion rates should favor Meshopt.
Small models or many models. Draco's WebAssembly decoder adds roughly 150 KB (gzipped) to the initial page load. Meshopt's decoder is about 7 KB. If your page loads a single small model, the Draco decoder can outweigh the compression savings entirely. If your application loads many models progressively (a furniture catalog, an architectural walkthrough), the decoder cost is paid once, but the faster decode time per model still gives Meshopt an advantage.
HTTP compression is already in your pipeline. If your server delivers assets with gzip or Brotli (which most CDNs do by default), Meshopt's compressed output responds exceptionally well to these algorithms. The combination of Meshopt plus Brotli often matches Draco's standalone compression ratio while decoding significantly faster.
GPU performance matters. Meshopt's optimization passes (vertex cache, overdraw, vertex fetch) improve rendering performance after decode. Draco does not optimize for GPU efficiency. If your scene is rendering limited, Meshopt provides a measurable improvement at no extra cost.
KHR_meshopt_compression,
is under review by the Khronos Group as a full KHR
standard. The meshoptimizer ecosystem continues to grow
with tools like gltfpack providing complete
pipeline automation. If you are starting a new project,
Meshopt is the safer long term choice for most use
cases.
Tooling and Integration
Both compression systems have mature tooling. Here are the most common ways to apply each one.
gltfpack is the official command line tool for meshoptimizer. It applies vertex optimization, Meshopt compression, quantization, and optional texture compression (Basis Universal or WebP) in a single command. Example usage:
gltfpack -i model.glb -o compressed.glb -cc
The -cc flag enables
EXT_meshopt_compression. Adding -tc applies
Basis Universal texture compression alongside it.
glTF Transform is a JavaScript toolkit by Don McCurdy that supports both Draco and Meshopt as plugins. It provides fine grained control over compression settings and integrates into Node.js build pipelines. Example:
gltf-transform draco model.glb compressed.glb
Or for Meshopt:
gltf-transform meshopt model.glb compressed.glb
three.js supports both decoders out of
the box. For Draco, use the built in
DRACOLoader and point it at the Draco
decoder files (included in the three.js distribution).
For Meshopt, call
GLTFLoader.setMeshoptDecoder() with the
decoder module from the meshoptimizer npm package.
Babylon.js supports both extensions natively starting from version 5.0. No additional configuration is required beyond loading the standard glTF loader.
Unity supports Draco via the DracoUnity package and Meshopt via the meshopt.decompress package. Both handle decompression transparently when loading glTF assets.
Browser tools. Polyforge's optimizer applies Draco compression to GLB files directly in the browser. No installation, no command line, no file uploads to a server.
Understanding Quantization Settings
Both Draco and Meshopt use quantization to reduce vertex precision, but they handle it differently.
Draco quantization is built into the compression pipeline. You set bit depths per attribute type. The defaults are 11 bits for positions, 8 bits for normals, and 10 bits for texture coordinates. Each additional bit doubles the precision, so the choice involves balancing file size against geometric accuracy.
Meshopt quantization is a separate
preprocessing step. The
KHR_mesh_quantization extension converts
32 bit floats to 16 bit integers or half precision
floats before compression. Meshopt then compresses the
already quantized data. This two step approach gives you
explicit control over precision and makes the
quantization visible in the glTF file structure.
| Attribute | Draco default | Recommended minimum | Effect of too few bits |
|---|---|---|---|
| Positions | 11 bits | 11 to 14 bits | Visible staircasing on curved surfaces |
| Normals | 8 bits | 7 to 8 bits | Banded lighting, faceted appearance |
| Texture coordinates | 10 bits | 10 to 12 bits | Texture misalignment, seam artifacts |
For most web delivery use cases, the defaults work well. If you are compressing precision critical models (dental scans, mechanical parts with tight tolerances), increase position bits to 14 or higher. Always compare the compressed result visually against the original before distributing.
Common Misconceptions
These misunderstandings come up frequently in forums and documentation discussions. Getting them right saves time and prevents poor decisions.
- "Compression makes my model render faster." No. Neither Draco nor Meshopt reduces polygon count. They reduce file size and transfer time, not rendering cost. After decompression, the GPU processes exactly the same number of triangles. To improve frame rate, you need mesh simplification or level of detail. Meshopt's vertex reordering does improve GPU cache efficiency slightly, but this is an optimization, not compression.
- "I should use both for maximum compression." You cannot apply both to the same model. Both systems operate on glTF buffer views, and applying both would create conflicting decompression chains. Choose one. You can, however, combine either one with texture compression (KTX2, Basis Universal) since texture and geometry compression are independent.
- "Draco compresses textures too." Draco compresses texture coordinates (UV mapping data), not texture images. A model with a 20 MB texture will still be close to 20 MB after Draco compression if the geometry was small to begin with. Use texture optimization separately.
- "Meshopt compression is lossless." The Meshopt codec itself is lossless, but when combined with quantization (which is standard practice), the overall pipeline is lossy. The quantization step reduces vertex precision before the lossless codec is applied. Without quantization, Meshopt still compresses data, but with lower ratios.
- "The decoder size doesn't matter." It does for small models and multi-model pages. Draco's ~150 KB decoder on a page loading a 50 KB compressed mesh means 75% of the download is overhead. Meshopt's ~7 KB decoder makes this a non issue. For a single large model, both decoders are negligible relative to the payload.
Quick Decision Guide
Use this as a starting point. Every project has specific requirements that may override these general recommendations.
- Static model, large geometry, no animation → Draco
- Animated model or morph targets → Meshopt
- Point cloud data → Draco
- Many small models on one page → Meshopt (smaller decoder)
- Fastest perceived load time → Meshopt (faster decode)
- Smallest possible file on disk → Draco
- Server already uses gzip or Brotli → Meshopt (better combined ratio)
- GIS, 3D Tiles, or Cesium pipeline → Draco
- New project, unsure of requirements → Meshopt (broader data support, growing ecosystem)
Frequently Asked Questions
Can I use Draco and Meshopt together on the same model?
No. Both compression systems operate on the same buffer data in a glTF file, so applying both would create conflicting decompression chains. Choose one or the other for each model. You can, however, use either compression alongside separate texture compression like KTX2 or Basis Universal.
Which compression method produces smaller files?
Draco typically achieves higher standalone compression ratios, reducing geometry by 70% to 95%. Meshopt on its own achieves 50% to 80% reduction, but when paired with standard HTTP compression like gzip or Brotli, the final delivered size is often comparable. The real difference depends on the model and your delivery pipeline.
Does Draco or Meshopt compress textures?
Neither one compresses texture image data. Both operate only on geometry: vertex positions, normals, UV coordinates, and index buffers. For texture compression, use KTX2 with Basis Universal or convert textures to WebP. See the file size reduction guide for texture strategies.
Which should I use for animated models?
Meshopt. Draco's glTF extension does not support morph targets or animation keyframes. Meshopt's extension compresses geometry, morph targets, and animation data together. If your model has blend shapes or skeletal animation, Meshopt is the only option that compresses the full asset.
How large are the decompression libraries?
The Draco WebAssembly decoder is approximately 150 KB when gzipped. The Meshopt decoder is roughly 7 KB gzipped, making it about 20 times smaller. For applications loading many small models, the decoder overhead matters. For a single large model, the Draco decoder cost is negligible relative to the compression savings.
Do I need WebAssembly support to use these compression methods?
Both decoders rely on WebAssembly for best
performance. Over 99% of modern browsers support
WebAssembly, including Chrome 57+, Firefox 52+,
Safari 11.1+, and Edge 16+. Draco provides a
JavaScript fallback for older browsers. Meshopt's
gltfpack tool can produce uncompressed
fallback buffers with the -cf flag,
though this increases file size.