Skip to main content

Polyforge

Learn

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.

14 min read
By Polyforge · Published Mar 23, 2026 · Updated Mar 28, 2026
LEARN
Compression Guide

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.

$ contents
$ why_compress

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.

$ draco_internals

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.

$ meshopt_internals

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.

$ comparison

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.

$ benchmarks

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.

Neither compression system replaces mesh simplification. Compression reduces how much space the data takes to store. It does not reduce the polygon count or improve rendering frame rate. If your model renders slowly, you need decimation or level of detail, not compression. Polyforge's optimizer handles both polygon reduction and compression.
$ use_draco

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.

$ use_meshopt

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.

The industry is shifting toward Meshopt. A newer extension, 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

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.

$ quantization

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.

$ misconceptions

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.
$ decision

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)
$ faq

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.

$ related

Related Guides and Tools