Three.js Bounding Sphere Margin and Frustum Culling

This article explains the concept of the bounding sphere margin in Three.js and its role in frustum culling. You will learn how frustum culling determines object visibility, why animated or deformed meshes sometimes disappear prematurely at the edges of the screen, and how expanding the bounding sphere acts as a margin to prevent this issue.

Understanding Frustum Culling in Three.js

To maintain high performance, Three.js uses a technique called frustum culling. The viewing frustum is the pyramid-shaped region of 3D space that is currently visible to the camera. Before rendering a frame, Three.js checks whether each object’s bounding volume—usually a bounding sphere—intersects with this frustum.

If an object’s bounding sphere is completely outside the camera’s view, Three.js skips rendering that object entirely. This saves valuable CPU and GPU resources.

Why Do Objects Disappear Prematurely?

Objects often disappear or flicker out of view too early at the edges of the screen due to a mismatch between the static bounding sphere and the dynamic mesh.

When Three.js calculates a bounding sphere, it does so based on the initial, static positions of the geometry’s vertices. However, many 3D applications deform meshes dynamically using: * Skeletal animations (skinning) * Morph targets * Custom vertex shaders that move vertices in real-time

Because these deformations happen on the GPU or during runtime, the CPU-calculated bounding sphere remains static and unchanged. If an animation causes a character’s arm or a flag’s fabric to wave far outside the original bounding sphere, the camera might see the static sphere go off-screen. Three.js then culls the object, causing the visible, deformed parts of the mesh to suddenly pop out of existence.

What is the Bounding Sphere Margin?

The “bounding sphere margin” is not a built-in property in Three.js, but rather a conceptual solution to this culling problem. It refers to artificially expanding the radius of an object’s bounding sphere to create a safety buffer or “margin” around the mesh.

By adding a margin to the bounding sphere, you ensure that the sphere remains large enough to contain the mesh even during its most extreme animations or deformations. As long as any part of this expanded sphere is within the camera’s view, Three.js will continue to render the object.

How to Apply a Bounding Sphere Margin in Three.js

To implement a bounding sphere margin, you must manually calculate the geometry’s bounding sphere and then increase its radius.

Here is how you can do this in code:

// 1. Ensure the bounding sphere is calculated
mesh.geometry.computeBoundingSphere();

// 2. Access the bounding sphere
const boundingSphere = mesh.geometry.boundingSphere;

// 3. Apply a margin by increasing the radius (e.g., by 50%)
const marginFactor = 1.5; 
boundingSphere.radius *= marginFactor;

If you know the exact maximum distance your vertices will displace (for example, in a vertex shader), you can add a flat value instead of multiplying:

const maxDisplacement = 5.0; // Units in 3D space
mesh.geometry.boundingSphere.radius += maxDisplacement;

The Alternative: Disabling Frustum Culling

If performance is not a bottleneck, or if you have a highly unpredictable dynamic mesh, you can disable frustum culling entirely for a specific object:

mesh.frustumCulled = false;

Setting frustumCulled to false forces Three.js to render the object in every frame, regardless of where the camera is pointing. While this completely solves the premature disappearance issue, it should be used sparingly, as disabling culling on complex or numerous meshes can significantly lower your application’s frame rate. Using a bounding sphere margin is the preferred, performance-friendly compromise.