How to Use Draco Compression in Three.js

Loading large 3D meshes in web applications often results in high bandwidth consumption and sluggish page response times. This article provides a direct, step-by-step guide on how to integrate Google’s Draco compression into a Three.js project to drastically reduce GLTF/GLB file sizes and accelerate asset loading. You will learn how to configure the DRACOLoader, link it to the GLTFLoader, and handle the decoder libraries efficiently.

1. Prepare Your Compressed Model

Before writing any code, you must compress your 3D model. When exporting a GLTF or GLB file from 3D modeling software like Blender, or when using command-line tools like gltf-pipeline, ensure that Draco compression is enabled. This packages the geometric data (vertices, normals, texture coordinates) into a highly compressed format.

2. Locate the Draco Decoder Files

Because Draco-compressed models cannot be read out of the box by standard parser APIs, Three.js requires a separate WebAssembly (WASM) decoder to unpack the data on the client side.

You need to host these decoder files on your server. You can find them in your project’s directory under: node_modules/three/examples/jsm/libs/draco/

Copy the entire draco folder to your public directory (e.g., /public/draco/ or /assets/draco/). Alternatively, you can use a verified CDN.

3. Implement the Loaders in JavaScript

To load the model, you must import both GLTFLoader and DRACOLoader. Instantiate the DRACOLoader, point it to your decoder files, and then inject it into your GLTFLoader instance.

Here is the complete implementation code:

import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';

// Initialize the Three.js scene
const scene = new THREE.Scene();

// 1. Instantiate the DRACOLoader
const dracoLoader = new DRACOLoader();

// 2. Set the path to the folder containing the WASM/JS decoding libraries
// This can be a local path or a CDN URL
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.6/'); 

// 3. Instantiate the GLTFLoader
const gltfLoader = new GLTFLoader();

// 4. Pass the DRACOLoader instance to the GLTFLoader
gltfLoader.setDRACOLoader(dracoLoader);

// 5. Load your compressed .gltf or .glb model
gltfLoader.load(
    'path/to/your/compressed-model.glb',
    (gltf) => {
        // Add the loaded model to the scene
        scene.add(gltf.scene);
        
        // Optional: Release decoding thread memory once loading is finished
        dracoLoader.dispose();
    },
    (xhr) => {
        console.log((xhr.loaded / xhr.total * 100) + '% loaded');
    },
    (error) => {
        console.error('An error occurred while loading the model:', error);
    }
);

4. Important Performance Considerations

While Draco dramatically reduces file transfer sizes, the client’s CPU must spend time decompressing the model once it arrives. For very simple models, the overhead of loading the WASM decoder and decompressing the data might outweigh the network savings. Draco compression is highly recommended for models with complex geometries (high polygon counts) where network transfer is the primary bottleneck.