Toggle Lights in Three.js Without Removing Them

Dynamically controlling illumination is essential for creating interactive 3D environments and optimizing performance in WebGL applications. This article explains how to toggle the visibility of specific lights in a Three.js scene without removing them from the scene graph. You will learn the two primary methods for achieving this—using the .visible property and manipulating light .intensity—along with the performance implications of each approach.

Method 1: Using the .visible Property

The most straightforward way to turn a light on or off in Three.js is by toggling its boolean visible property. Inherited from the Object3D base class, this property determines whether the object is rendered and processed in the scene.

// Create a point light
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
scene.add(pointLight);

// Turn the light off
pointLight.visible = false;

// Turn the light back on
pointLight.visible = true;

// Toggle the light state dynamically (e.g., on a button click)
function toggleLight() {
    pointLight.visible = !pointLight.visible;
}

Performance Consideration: Shader Recompilation

While modifying visible is simple, toggling this property changes the number of active lights in the scene. When the number of active lights changes, Three.js may need to recompile the WebGL materials/shaders of objects illuminated by that light. This recompilation can cause a temporary frame rate drop (a “stutter” or “jank”) during gameplay or interaction.


Method 2: Setting .intensity to Zero

To avoid shader recompilation and ensure smooth performance, you can toggle a light’s visibility by setting its intensity property to 0.

Because the light technically remains “active” within the scene graph, Three.js does not need to recompile the shaders; it simply calculates the light’s contribution as zero.

// Store the default intensity of your light
const defaultIntensity = 1.5;
const directionalLight = new THREE.DirectionalLight(0xffffff, defaultIntensity);
scene.add(directionalLight);

// Turn the light "off"
directionalLight.intensity = 0;

// Turn the light "on"
directionalLight.intensity = defaultIntensity;

// Toggle the light state dynamically
function toggleLightSmoothly() {
    if (directionalLight.intensity > 0) {
        directionalLight.intensity = 0;
    } else {
        directionalLight.intensity = defaultIntensity;
    }
}

Advantages of the Intensity Method


Summary: Which Method Should You Use?