Skip to content

DRACO Loader

Video Lecture

DRACO Loader DRACO Loader

Description

The DRACO loader is used to load geometry compressed with the Draco library.

Draco is an open source library for compressing and decompressing 3D meshes and point clouds.

glTF files can also be compressed using the DRACO library, and they can also be loaded using the glTF loader. We can configure the glTF loader to use the DRACOLoader to decompress the file in such cases.

Caveat, compressing a file doesn't necessarily mean that the file will be presented in the scene faster. While compressed geometry can result in a significantly smaller file size, the client browsers CPU will use more time decoding the file, and also need to download additional libraries into a web worker to run the decompression process.

See below example showing that the compressed file appears later in the scene than the uncompressed version.

All files and applications are different, you will need to test using compression or not if you want to know if compression will benefit your application or not.

Compressed (DRACO)
<>
Uncompressed
<>

Resources

The 3D models used in this lesson can be easily created using Blender. If you don't want to use blender to create the models, then you can download them from the zip file named models4.zip. Extract the models4.zip contents into the ./dist/client/models/ folder.

models4.zip

Note

Since Three release 148, you will find the Draco libraries in the .\node_modules\three\examples\jsm\libs\draco\ folder.

Tip

Instead of hosting the Draco decoder libs yourself, you may find it easier to download them from a CDN.

E.g.,

const draco = new DRACOLoader();
draco.setDecoderConfig({ type: 'js' });
draco.setDecoderPath('https://www.gstatic.com/draco/v1/decoders/');

Lesson Script

./src/client/client.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import Stats from 'three/examples/jsm/libs/stats.module'

const scene = new THREE.Scene()
scene.add(new THREE.AxesHelper(5))

const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
)
camera.position.z = 2

const renderer = new THREE.WebGLRenderer()
// renderer.physicallyCorrectLights = true //deprecated
// renderer.useLegacyLights = false //deprecated
renderer.shadowMap.enabled = true
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

const controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true

// Note that since Three release 148, you will find the Draco libraries in the `.\node_modules\three\examples\jsm\libs\draco\` folder.
const draco = new DRACOLoader()
draco.setDecoderPath('/js/libs/draco/')

const loader = new GLTFLoader()
loader.setDRACOLoader(draco)
loader.load(
    'models/monkey_compressed.glb',
    function (gltf) {
        gltf.scene.traverse(function (child) {
            if ((child as THREE.Mesh).isMesh) {
                const m = child as THREE.Mesh
                m.receiveShadow = true
                m.castShadow = true
            }
            if ((child as THREE.Light).isLight) {
                const l = child as THREE.SpotLight
                l.castShadow = true
                l.shadow.bias = -0.003
                l.shadow.mapSize.width = 2048
                l.shadow.mapSize.height = 2048
            }
        })
        scene.add(gltf.scene)
    },
    (xhr) => {
        console.log((xhr.loaded / xhr.total) * 100 + '% loaded')
    },
    (error) => {
        console.log(error)
    }
)

window.addEventListener('resize', onWindowResize, false)
function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
    render()
}

const stats = new Stats()
document.body.appendChild(stats.dom)

function animate() {
    requestAnimationFrame(animate)

    controls.update()

    render()

    stats.update()
}

function render() {
    renderer.render(scene, camera)
}

animate()

DRACO 3D Data Compression

DRACOLoader (Official Documentation)

WebAssembly (MDN)

WebAssembly (Official)

Comments