Configure ACESFilmicToneMapping in Three.js for HDR

Achieving a cinematic, photorealistic look in Three.js requires proper color management and tone mapping. This article provides a direct guide on how to configure ACESFilmicToneMapping on the WebGLRenderer, adjust exposure settings, and set up your scene to leverage high-dynamic-range (HDR) rendering for realistic contrast and highlight roll-off.

Step 1: Enable ACESFilmicToneMapping on the Renderer

To apply the ACES (Academy Color Encoding System) filmic tone mapping curve, you must configure the properties of your WebGLRenderer. This maps the high-dynamic-range colors of your 3D scene into the low-dynamic-range monitor space (sRGB) while preserving highlights and shadows like a cinematic camera.

import * as THREE from 'three';

// Create the renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// Enable ACES Filmic Tone Mapping
renderer.toneMapping = THREE.ACESFilmicToneMapping;

Step 2: Adjust the Exposure

The default exposure value is 1.0. You can scale the overall brightness of your HDR scene by adjusting the toneMappingExposure property. Increasing this value brightens dark areas, while decreasing it prevents bright areas from clipping.

// Adjust the cinematic exposure (default is 1.0)
renderer.toneMappingExposure = 1.25; 

Step 3: Configure Output Color Space

For tone mapping to display colors accurately, the renderer’s output color space must be set to sRGB. In modern versions of Three.js, this is handled via the outputColorSpace property.

// Ensure correct color output
renderer.outputColorSpace = THREE.SRGBColorSpace;

Step 4: Use High-Intensity Lights and HDR Textures

ACES Filmic Tone Mapping works best when your scene contains color values that exceed the standard 0.0 to 1.0 range. To get the classic “filmic burn” on bright surfaces, use HDR environment maps or high-intensity lights:

// Example of a high-intensity light that utilizes HDR tone mapping
const directionalLight = new THREE.DirectionalLight(0xffffff, 8.0);
scene.add(directionalLight);