API

In-Depth layerMask

layerMask is a property you can find on many objects and may be a bit difficult to grasp at first. This page should give you a good understanding of how it works across Babylon.js objects.

layerMask meaning

layerMask is a value that can be assigned to different objects (like meshes, cameras, layers, particle systems, etc.) and is used to determine the visibility of one object from another (for example, whether a mesh is visible from a camera or whether a layer should be displayed after a given camera is processed).

The only two things to understand with layerMask are that:

  • it can be any number from 0 to 0xFFFFFFFF (or 4294967295, but it’s easier to write 0xFFFFFFFF)
  • when computing a visibility flag, two values of layerMask are ANDed and if the result is different from 0 the flag is true

So, for example, if camera.layerMask = 35 and mesh.layerMask = 2, 35 & 2 == 2 != 0, so the mesh is visible from this camera. We often show these numbers in hexadecimal because doing the AND as a mental calculation is easier that way: 35=0x23 and 2=0x02 and 35 & 2 == 0x23 & 0x02, and from this latter representation it’s easier to see that the result is 2 (well, at least when you are a bit comfortable with hexadecimal!).

Usage in Babylon.js

In Babylon, by default all layerMask properties are 0x0FFFFFFF (for Camera, Mesh, Layer, …). So, when it comes to determining visibility, 0x0FFFFFFF & 0x0FFFFFFF != 0 and everything is always visible (at least from the standpoint of the layerMask test).

As you can see, there are 4 bits not set by default in the layerMask (the leading 0 before the first F). This makes layerMask easier to use, as a common use case is to hide some meshes from a camera. To achieve that, you need to set a layerMask on the meshes so that the AND operation with the layerMask of the camera (0x0FFFFFFF by default) is 0: you can use 0x10000000, 0x20000000, 0x40000000 or 0x80000000. Now you can see why showing these numbers in hexadecimal helps: it’s a lot easier to see that 0x10000000 & 0x0FFFFFFF = 0 than 268435456 & 268435455!

If the default value for layerMask was 0xFFFFFFFF, you would also need to update the layerMask of your camera to have your meshes invisible from it because 0xFFFFFFFF is an all-one 32 bit value. So the 0x0FFFFFFF value is simply a default value that can help make your life a little easier, but in all generality you can put any value in the layerMask property of cameras, meshes, layers, etc (as in the 35 & 2 example above) and simply understand how it is used to compute visibility.

Layers and Skeleton Animations

If the active camera in a scene is using a layerMask to hide meshes that are animated with skeletons, then other cameras that do show the meshes will not show the animation because the skeletons are not being updated. A solution is to prepare the skeleton before each frame is rendered.

import type { AbstractMesh } from "@babylonjs/core/Meshes/abstractMesh";
import type { TransformNode } from "@babylonjs/core/Meshes/transformNode";
import type { EventState } from "@babylonjs/core/Misc/observable";
import type { Scene } from "@babylonjs/core/scene";
let scene: Scene;
let avatar: TransformNode;
scene.onBeforeRenderObservable.add(onBeforeRender);
function onBeforeRender(scene: Scene, eventState: EventState) {
const meshes = avatar.getChildMeshes(false);
meshes.forEach(prepareSkeleton);
}
function prepareSkeleton(mesh: AbstractMesh) {
const skeleton = mesh.skeleton;
if (!skeleton)
return;
skeleton.prepare();
}