How to Use LUTPass for Three.js Color Grading

Achieving a cinematic look in 3D web graphics requires effective post-processing, and lookup tables (LUTs) are the industry standard for professional color grading. This article provides a step-by-step guide on how to integrate and use the LUTPass in Three.js to apply rich, cinematic color grading to your 3D scenes using .cube or .3dl LUT files.

Step 1: Import the Required Modules

To use LUTPass, you need to set up the Three.js post-processing pipeline. This requires importing the EffectComposer, RenderPass, ShaderPass, LUTPass, and a LUT loader (such as LUTCubeLoader) from the Three.js examples directory.

import * as THREE from 'three';
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
import { LUTPass } from 'three/addons/postprocessing/LUTPass.js';
import { LUTCubeLoader } from 'three/addons/loaders/LUTCubeLoader.js';

Step 2: Set Up the EffectComposer

Initialize the standard EffectComposer and add a RenderPass to render your base 3D scene before applying any post-processing effects.

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

const composer = new EffectComposer(renderer);
const renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);

Step 3: Load the LUT Texture

LUT files mapping colors are typically distributed in .cube or .3dl formats. Use the LUTCubeLoader to load your color-grading file. Once loaded, the resulting texture must be assigned to the LUTPass.

const lutPass = new LUTPass();
composer.addPass(lutPass);

const loader = new LUTCubeLoader();
loader.load('path/to/your/cinematic-lut.cube', function (result) {
    // Assign the loaded 3D texture and size to the LUTPass
    lutPass.lut = result.texture3D;
    lutPass.intensity = 1.0; // Adjust the strength of the effect (0.0 - 1.0)
    lutPass.enabled = true;
});

Step 4: Adjust Renderer Settings for Color Accuracy

For color grading to look correct, you must configure the renderer to use the proper color space. Modern Three.js uses SRGBColorSpace by default, but ensuring your renderer and composer settings match is vital for avoiding washed-out colors.

renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.0;

Step 5: Update the Render Loop

Finally, replace your standard renderer.render(scene, camera) call inside your animation loop with composer.render() to render the scene with the applied LUT post-processing.

function animate() {
    requestAnimationFrame(animate);

    // Render through the composer instead of the renderer
    composer.render();
}
animate();