Use LightProbe Spherical Harmonics in Three.js
This article explains how to utilize spherical harmonics (SH)
coefficients within a Three.js LightProbe to create
realistic, low-frequency ambient lighting in a 3D scene. You will learn
how to instantiate a light probe, populate its spherical harmonics data
from an environmental source using the LightProbeGenerator,
and apply this light to illuminate your scene’s materials
efficiently.
Understanding LightProbes and Spherical Harmonics
In Three.js, a LightProbe is an alternative way of
adding light to a 3D scene. Instead of emitting light from a single
point or direction, it uses Spherical Harmonics (SH) to approximate
diffuse indirect light from all directions. This is highly efficient
because it represents complex global illumination using just 9 color
coefficients (3rd-order SH), providing realistic ambient shading with
minimal performance cost.
Implementing a LightProbe in Three.js
To use spherical harmonics to illuminate your scene, follow these steps:
1. Create the Light Probe
First, instantiate the LightProbe object and add it to
your scene.
import * as THREE from 'three';
const lightProbe = new THREE.LightProbe();
scene.add(lightProbe);2. Generate Spherical Harmonics Coefficients
While you can manually set the SH coefficients if you have raw data,
the most common approach is to generate them from an envmap (such as a
CubeTexture) using the LightProbeGenerator
utility.
import { LightProbeGenerator } from 'three/addons/lights/LightProbeGenerator.js';
// Load an environment cube texture
const cubeTextureLoader = new THREE.CubeTextureLoader();
cubeTextureLoader.load([
'px.png', 'nx.png',
'py.png', 'ny.png',
'pz.png', 'nz.png'
], (cubeTexture) => {
// Generate the spherical harmonics and copy them to the light probe
const generatedProbe = LightProbeGenerator.fromCubeTexture(cubeTexture);
lightProbe.copy(generatedProbe);
});3. Manually Setting Coefficients (Optional)
If you already have pre-calculated SH coefficients from an external
baking tool, you can pass them directly into the light probe’s
sh property. The sh.coefficients array
contains 9 THREE.Vector3 objects representing the RGB
channels of the 9 spherical harmonic bases.
// Setting coefficients from a flat array of 27 floats (9 vectors * 3 RGB channels)
const rawCoefficients = [
// 27 float values representing your 9 Vector3s
];
lightProbe.sh.fromArray(rawCoefficients);Adjusting Influence and Materials
Once the light probe has its spherical harmonics coefficients set,
any physically-based materials in your scene (such as
MeshStandardMaterial or MeshPhysicalMaterial)
will automatically detect and use this data for diffuse indirect
lighting.
You can control the overall contribution of the light probe using its
intensity property:
lightProbe.intensity = 1.2; // Adjust to match the desired ambient brightness