Bringing HDR from WebGPU onto the screen

Played around more with the tonemapper, got it to a really good state where I’m happy with how it looks and feels.

Here’s my full shader in case anyone is interested, feel free to steal

    // scene color in linear Rec. 709
    var color = textureLoad(input_color, vec2i(coord.xy), 0).rgb;
    
    // Apply exposure
    color *= settings.exposure;
    
    // Finally tonemap
    color = tonemap_gt7(color, settings.peak_nits, settings.paper_white_nits);
    
    // NOTE: no dithering, colorspace is wide
    
    // output in p3 color space
    let color_2020 = CRM_FROM_REC709_TO_REC2020 * color;
    let color_p3 = CRM_FROM_REC2020_TO_P3 * color_2020;
    
    // apply gamma. Note that gamma is the same same for "Display P3" and "sRGB"
    let color_gamma = sRGBTransferOETF(color_p3);
    
    return vec4(color_gamma, 1.0);

Needs a bit of cleanup, and my tonemapper works in Rec2020 instead of Rec709, which is what the rest of the pipeline works in, but hopefully this is enough to give you an idea on what to do.

The context configuration is as follows:

{
    format: "rgba16float",
    colorSpace: "display-p3",
    toneMapping: {
        mode: "extended" 
    }
}

If you can’t use p3, that’s fine, generally the visual difference will be minimal and you can skip p3 conversion, outputting Rec709


Here’s a demo
Screenshot 2025-12-21 225243

If you have an HDR display that’s properly set up - the content will render in HDR.

3 Likes