Tone Mapping

Overview

In the Tone Mapping Pass, UE mainly implements the following functionalities:

  • View Exposure: Corrects the exposure of the image.
  • Vignette: Adds a vignette effect to the image.
  • Grain: Adds a grainy texture to the image.
  • Tone Map: Maps the linear color to the final output color.

The main calculation process is shown in the following diagram:

image

Additionally, here is the official documentation regarding Tone Mapping:

Vignette

Unreal Engine achieves vignette effect through a series of transformations.

Regardless of the aspect ratio of the screen, it can achieve a vignette-free area located in the center of the screen, and the area does not change with the variation of the aspect ratio.

image

This image shows the vignetting effect under different aspect ratios, simulated using Python.

Grain

This part of the implementation is relatively simple and achieved by generating a pseudo-random noise using UV as a seed.

Tone Map Look Up Table

The process of querying LUT and outputting the final color is not complicated, as shown in the following figure. Currently, the Linear Color is subjected to some transformations and Gamma correction, and directly used as the UVW coordinates to sample this 3D texture.

image

The key to the problem lies in how the Look Up Table (LUT) texture used for querying, called Combine LUTs, is constructed. The answer is that there is a separate pass dedicated to generating this image.

Why we need a seperate LUT texture?

If we do not consider the custom Tone Map calculation method, theoretically, we can directly perform Tone Mapping calculation on each screen pixel.

I cannot determine the exact reason, but my speculation is that when using LUT Texture, it is necessary to pre-calculate 32 * 32 * 32 = 32768 pixels. However, if we calculate each pixel on the screen independently, we would need to compute 1920 * 1080 = 2073600 pixels.

LUT Texture Build

The overall process of building an LUT Texture is as follows. The details will be discussed next.

image

ACES Filmic Tone Map

The Filmic tonemapper that is used in UE4 matches the industry standard set by the Academy Color Encoding System (ACES) for television and film. This ensures that consistent color is preserved across multiple formats and displays while also as a way to future proof the source material since it will not have to be adjusted for each medium that comes along. The filmic tonemapper also uses the same global tonemapper that was previously used in UE4, with the exception that there is now a filmic response meaning that the S-curve shape now better simulates film stock for a better overall look. From https://docs.unrealengine.com/4.27/en-US/RenderingAndGraphics/PostProcessEffects/ColorGrading/

Color Space Convert

From one color space to another color space, if it is a linear mapping, it can be achieved through matrix operations.Therefore, a portion of color space conversions are given in matrix form.

The various matrices for color space conversion are provided on the following pages in ACES:

And this shadertoy also can be a reference.

Implementation Detail: Geometry Shader

When rendering this 3D Lookup Table, a Geometry Shader is used to output the rendering result to different slices of the 3D LUT.

Specifically, the rendering process is as follows:

image

Check this page if you want to know more: