How to Adjust toneMappingExposure in Three.js
This article explains how to properly use the
toneMappingExposure property in Three.js to control the
brightness of physically rendered scenes. You will learn how to enable
tone mapping on the renderer, adjust the exposure values to brighten or
darken your scene, and implement best practices for realistic lighting
and high-dynamic-range (HDR) rendering.
To adjust the exposure of a physically rendered scene in Three.js,
you must interact with the WebGLRenderer. The
toneMappingExposure property scales the exposure of the
color tones, but it only works if a tone mapping algorithm is actively
applied to the renderer.
Step 1: Enable Tone Mapping on the Renderer
By default, the renderer’s toneMapping property is set
to THREE.NoToneMapping. For exposure adjustments to take
effect, you must change this to a dynamic tone mapping option, such as
THREE.ACESFilmicToneMapping (which mimics cinematic film)
or THREE.LinearToneMapping.
import * as THREE from 'three';
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Enable tone mapping (ACES Filmic is highly recommended for physical rendering)
renderer.toneMapping = THREE.ACESFilmicToneMapping;Step 2: Adjust the toneMappingExposure Property
Once tone mapping is enabled, you can adjust the
toneMappingExposure property. The default value is
1.0.
- To brighten the scene: Increase the value above
1.0(e.g.,1.5,2.0). - To darken the scene: Decrease the value below
1.0(e.g.,0.5,0.2).
// Brighten the entire scene
renderer.toneMappingExposure = 1.5;
// Darken the entire scene
renderer.toneMappingExposure = 0.6;Step 3: Changing Exposure Dynamically
You can update this value in real-time inside your animation loop or via user interface controls (like lil-gui) to simulate eyes adjusting to darkness, camera exposure changes, or day-night transitions.
function animate() {
requestAnimationFrame(animate);
// Example: Slowly adjust exposure over time
// renderer.toneMappingExposure = Math.sin(Date.now() * 0.001) + 1.0;
renderer.render(scene, camera);
}
animate();Best Practices for Physically-Based Rendering (PBR)
When working with physically-based materials
(MeshStandardMaterial or MeshPhysicalMaterial)
and HDR environment maps, do not boost individual light intensities to
extreme levels to make the scene brighter. Instead, set realistic,
physically accurate light intensities and use
renderer.toneMappingExposure as a global camera lens
control to balance the overall brightness of the frame.