Skip to main content
A tone mapping operator, or tone mapper, is responsible for compressing the dynamic range of the rendered scene to a dynamic range suitable for display.

Overview

In Filament, tone mapping is a color grading step. ToneMapper instances are created and passed to the ColorGrading::Builder to produce a 3D LUT that will be used during post-processing to prepare the final color buffer for display.

Base Interface

ToneMapper

The base interface for all tone mapping operators.
struct ToneMapper {
    virtual math::float3 operator()(math::float3 c) const noexcept = 0;
    virtual bool isOneDimensional() const noexcept { return false; }
    virtual bool isLDR() const noexcept { return false; }
};

operator()

Maps an open domain (“scene referred”) color value to display domain (“display referred”) color value. Both input and output are in the Rec.2020 color space with no transfer function applied (“linear Rec.2020”). Parameters:
  • c - Input color to tone map, in linear Rec.2020
Returns:
  • A tone mapped color in linear Rec.2020

isOneDimensional()

Returns true if the tone mapper operates independently on each channel: f(x) = vec3(f(x.r), f(x.g), f(x.b)) This indicates that the color grading LUT only requires a 1D texture instead of a 3D texture, potentially saving significant memory and generation time.

isLDR()

Returns true if this tone mapper only works in low-dynamic-range. This indicates that the color grading LUT doesn’t need to be log encoded.

Tone Mapper Categories

Filament provides tone mappers in three categories:

Configurable Tone Mappers

These provide parameters to customize the tone mapping curve.

GenericToneMapper

AgxToneMapper

Fixed-Aesthetic Tone Mappers

These provide specific looks without customization.

ACESToneMapper

ACESLegacyToneMapper

FilmicToneMapper

PBRNeutralToneMapper

GT7ToneMapper

Debug/Validation Tone Mappers

These are useful for debugging and exposure validation.

LinearToneMapper

DisplayRangeToneMapper

Tone Mapper Reference

LinearToneMapper

Linear tone mapping operator that returns the input color clamped to the 0..1 range. Mostly useful for debugging. Properties:
  • One-dimensional: true
  • LDR: true
LinearToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

ACESToneMapper

Implementation of the ACES Reference Rendering Transform (RRT) combined with the Output Device Transform (ODT) for sRGB monitors (dim surround, 100 nits). Properties:
  • One-dimensional: false
  • LDR: false
ACESToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

ACESLegacyToneMapper

ACES tone mapping operator modified to match the perceived brightness of FilmicToneMapper. Applies a brightness multiplier of ~1.6 to the input color value to target brighter viewing environments. This is the default tone mapper in Filament. Properties:
  • One-dimensional: false
  • LDR: false
ACESLegacyToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

FilmicToneMapper

“Filmic” tone mapping operator designed to approximate the aesthetics of the ACES RRT + ODT for Rec.709. Historically Filament’s default tone mapping operator. Exists only for backward compatibility and is not otherwise recommended. Properties:
  • One-dimensional: true
  • LDR: false
FilmicToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

PBRNeutralToneMapper

Khronos PBR Neutral tone mapping operator. Designed to preserve the appearance of materials across lighting conditions while avoiding artifacts in the highlights in high dynamic range conditions. Properties:
  • One-dimensional: false
  • LDR: false
PBRNeutralToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

GT7ToneMapper

Gran Turismo 7 tone mapping operator. Designed to preserve material appearance across lighting conditions while avoiding highlight artifacts in HDR conditions. Targets an SDR paper white value of 250 nits, with a reference luminance of 100 cd/m² (a value of 1.0 in the HDR framebuffer). Properties:
  • One-dimensional: false
  • LDR: false
GT7ToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

AgxToneMapper

AgX tone mapping operator with optional creative looks. Properties:
  • One-dimensional: false
  • LDR: false

AgxLook

Optional creative adjustments to contrast and saturation:
  • NONE - Base contrast with no look applied
  • PUNCHY - A punchy and more chroma laden look for sRGB displays
  • GOLDEN - A golden tinted, slightly washed look for BT.1886 displays
AgxToneMapper toneMapper(AgxToneMapper::AgxLook::PUNCHY);
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

GenericToneMapper

Configurable tone mapping operator that gives control over the tone mapping curve. Can be used to control the aesthetics of the final image and the dynamic range of scene referred values. Properties:
  • One-dimensional: true
  • LDR: false

Constructor Parameters

GenericToneMapper(
    float contrast = 1.55f,
    float midGrayIn = 0.18f,
    float midGrayOut = 0.215f,
    float hdrMax = 10.0f
);
  • contrast - Controls the contrast of the curve (must be > 0.0, recommended range: 0.5 to 2.0)
  • midGrayIn - Sets the input middle gray (range: 0.0 to 1.0)
  • midGrayOut - Sets the output middle gray (range: 0.0 to 1.0)
  • hdrMax - Defines the maximum input value that maps to output white (must be >= 1.0)
Default values approximate an ACES tone mapping curve with maximum input value of 10.0.

Methods

float getContrast() const noexcept;
float getMidGrayIn() const noexcept;
float getMidGrayOut() const noexcept;
float getHdrMax() const noexcept;

void setContrast(float contrast) noexcept;
void setMidGrayIn(float midGrayIn) noexcept;
void setMidGrayOut(float midGrayOut) noexcept;
void setHdrMax(float hdrMax) noexcept;
Example:
GenericToneMapper toneMapper(1.8f, 0.18f, 0.25f, 16.0f);
toneMapper.setContrast(2.0f);

ColorGrading::Builder()
    .toneMapper(&toneMapper)
    .build(engine);

DisplayRangeToneMapper

Debug tone mapper that converts HDR RGB color into one of 16 debug colors representing the pixel’s exposure. When the output is cyan, the input represents middle gray (18% exposure). Properties:
  • One-dimensional: false
  • LDR: false

Exposure to Color Mapping

  • -5 EV - Black
  • -4 EV - Darkest blue
  • -3 EV - Darker blue
  • -2 EV - Dark blue
  • -1 EV - Blue
  • 0 EV - Cyan (middle gray)
  • +1 EV - Dark green
  • +2 EV - Green
  • +3 EV - Yellow
  • +4 EV - Yellow-orange
  • +5 EV - Orange
  • +6 EV - Bright red
  • +7 EV - Red
  • +8 EV - Magenta
  • +9 EV - Purple
  • +10 EV - White
This tone mapper is useful to validate and tweak scene lighting.
DisplayRangeToneMapper toneMapper;
ColorGrading::Builder().toneMapper(&toneMapper).build(engine);

Custom Tone Mappers

You can create custom tone mapping operators by subclassing ToneMapper and implementing the required virtual methods.
struct MyCustomToneMapper : public ToneMapper {
    math::float3 operator()(math::float3 c) const noexcept override {
        // Your custom tone mapping implementation
        return c; // Example: pass-through
    }
    
    bool isOneDimensional() const noexcept override {
        return true; // If your mapping is per-channel
    }
};

MyCustomToneMapper customMapper;
ColorGrading::Builder().toneMapper(&customMapper).build(engine);

See Also

  • ColorGrading - Color grading and post-processing
  • View - Apply color grading to a view

Build docs developers (and LLMs) love