Manage Object Visibility in Three.js with Layers

Published on 16 Sep, 2024 | ~3 min read | Demo

There are many ways to control the visibility of a scene's objects, and using layers is one of the most effective methods. In some cases, it can save you a lot of time and effort that would otherwise be spent on workarounds.

So What Are Layers?

Every object in a Three.js scene belongs to one or more of 32 available layers, numbered from 0 to 31.

By default, all objects belong to layer 0, but we can change that. For example, we can assign a gridHelper to layer 2 only, or a mesh to layers 0, 1, and 2.

Layers
Layers

The most important thing to remember, and the primary reason layers exist, is that an object will not appear in a scene unless it shares at least one layer with the camera.

Only the light is invisible because it does not share a common layer with the camera
Only the light is invisible because it does not share a common layer with the camera

That being said, all of these objects would be displayed except for the light. Although the light belongs to two layers, neither of these layers is shared with the camera.

How to Use Layers

I assume you have a Three.js project set up. If not, you can use my Three.js boilerplate to get started.

Next, create a couple of spheres.

Full Code:

import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

const renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);

renderer.setClearColor(0xa3a3a3);

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

const orbit = new OrbitControls(camera, renderer.domElement);

camera.position.set(0, 0, -14);
orbit.update();

const greenSphere = new THREE.Mesh(
  new THREE.SphereGeometry(2, 50, 50),
  new THREE.MeshBasicMaterial({
    color: 0x00ff33,
  })
);
greenSphere.position.x = 4;
scene.add(greenSphere);

const redSphere = new THREE.Mesh(
  new THREE.SphereGeometry(2, 50, 50),
  new THREE.MeshBasicMaterial({
    color: 0xff3322,
  })
);
redSphere.position.x = -4;
scene.add(redSphere);

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

renderer.setAnimationLoop(animate);

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

To remove an object from all layers and set it to only one, use the .layers.set() method.

redSphere.layers.set(5);

By doing this, the red sphere will no longer be visible because the camera is not a member of layer 5.

Next, we have the .layers.enable() method, which assigns an object to a layer without removing its membership from the layers it is already part of.

camera.layers.enable(5);

Now the red sphere is visible again because it shares a common layer with the camera.

We also have the .layers.enableAll() method, which assigns an object to all layers."

greenSphere.layers.enableAll();

To test if two objects share at least one common layer, use the .layers.test() method.

// true
console.log(camera.layers.test(greenSphere.layers));

Finally, you can create a Layers object, which is useful for checking if an object belongs to a specific layer.

const testingLayers = new THREE.Layers();
testingLayers.set(6);

// Test whether the redSphere has membership in layer 6.
// false
console.log(testingLayers.test(redSphere.layers));

Wrap Up

Despite being simple to understand and use, layers are often underrated for their effectiveness in managing object visibility. In fact, you'll see this in practice in a couple of my upcoming articles.

Until next time.

Credits and Resources

Related Content