Three.js LOD Tutorial: Optimize 3D Performance

In this article, you will learn how to implement a Level-of-Detail (LOD) system in Three.js to automatically swap high-polygon models for low-polygon ones based on their distance from the camera. We will cover the core mechanics of the THREE.LOD class, provide a practical step-by-step code implementation, and share key optimization tips to keep your web-based 3D applications running smoothly.

Understanding the Three.js LOD Class

Rendering high-polygon models that are far away from the camera wastes valuable GPU resources because the fine details are invisible at a distance. The THREE.LOD (Level of Detail) class solves this by holding multiple versions of a 3D object—each simplified to a different degree—and automatically rendering the appropriate version based on its distance from the active camera.

Step-by-Step Implementation

To implement LOD in Three.js, you need to create an instance of THREE.LOD, define your meshes representing different detail levels, register those meshes with specific distance thresholds, and add the LOD object to your scene.

Here is the complete code implementation:

import * as THREE from 'three';

// 1. Initialize the LOD Object
const lod = new THREE.LOD();

// 2. Create Geometries of Varying Complexity
// High-detail version (Used when close to the camera)
const highGeometry = new THREE.IcosahedronGeometry(1, 6); 
const highMaterial = new THREE.MeshStandardMaterial({ color: 0xff5555, flatShading: true });
const highMesh = new THREE.Mesh(highGeometry, highMaterial);

// Medium-detail version (Used at moderate distances)
const mediumGeometry = new THREE.IcosahedronGeometry(1, 3);
const mediumMaterial = new THREE.MeshStandardMaterial({ color: 0xff5555, flatShading: true });
const mediumMesh = new THREE.Mesh(mediumGeometry, mediumMaterial);

// Low-detail version (Used when far away)
const lowGeometry = new THREE.IcosahedronGeometry(1, 1);
const lowMaterial = new THREE.MeshStandardMaterial({ color: 0xff5555, flatShading: true });
const lowMesh = new THREE.Mesh(lowGeometry, lowMaterial);

// 3. Add Levels to the LOD Object
// The second parameter is the minimum distance from the camera at which this level displays.
lod.addLevel(highMesh, 0);     // Display high-poly mesh from 0 to 15 units of distance
lod.addLevel(mediumMesh, 15);  // Display mid-poly mesh from 15 to 30 units of distance
lod.addLevel(lowMesh, 30);     // Display low-poly mesh beyond 30 units of distance

// 4. Add the LOD Object to the Scene
scene.add(lod);

Updating the LOD in the Render Loop

By default, Three.js automatically updates the active LOD level for all LOD objects in the scene during the standard render call. You only need to ensure your camera and scene are passed to the renderer inside your animation loop:

function animate() {
    requestAnimationFrame(animate);

    // Optional: Rotate the LOD object to see the performance in action
    lod.rotation.y += 0.01;

    // The WebGLRenderer automatically calculates camera distance and updates LOD levels
    renderer.render(scene, camera);
}
animate();

Best Practices for Three.js LOD

To get the most out of your LOD setup, keep the following performance considerations in mind: