Frostbyte style tonemap color processing

share shaders here
  • Author
  • Message
Offline
User avatar
Posts: 99
Joined: 11 May 2014, 10:48

Frostbyte style tonemap color processing

This here is the style of tonemap color processing as described in this presentation: https://www.ea.com/frostbite/news/high- ... -frostbite
It's not something to do tonemapping by itself, but it's a way of altering the effect the tonemap has on the colors in your image.
You have to provide your own tonemapping function, but the processing is tonemapping curve agnostic, and should work fine with any curve.
What it does is give you control over the amount of hueshift and desaturation that occurs during the tonemap, allowing for hues to be more accurately preserved in highlights while retaining their perceived brightness.

You will need this helper file:
ictcp_colorspaces.fx
(3.93 KiB) Downloaded 594 times
There's a number of variables you will need to define as UI parameters or as static consts:

Code: Select all

float Desaturation:
     Changes the amount of pre-tonemap desaturation to apply to the image.
     Min: 0.0, Max: 1.0, Default: 0.7
float HueShift:
     Changes the amount of hueshift allowed.
     Min: 0.0, Max: 1.0, Default: 0.4
float Resaturation:
     A midrange saturation boost that happens post-tonemapping.
     Min: 0.0, Max: 1.0+, Default: 0.3
float Saturation:
    Just a standard saturation control, might as well add it here to enjoy the quality saturation of ICtCp
    Min: 0.0, Max: 2.0+, Default: 1.0

To match standard tonemapping (essentially disabling the effect), set the parameters to the following:
    Desaturation = 0
    HueShift = 1
    Resaturation = 0
The actual code:

Code: Select all

float3 applyTonemap(float3 color)
{
    // insert your tonemapping here
}

#include "ictcp_colorspaces.fx"
float3 frostbyteTonemap(float3 color)
{
    float3 ictcp = rgb2ictcp(color.xyz);
    float saturation = pow(smoothstep(1.0, 1.0 - Desaturation, ictcp.x), 1.3);
    color.xyz = ictcp2rgb(ictcp * float3(1.0, saturation.xx));

    float3 perChannel = applyTonemap(color.xyz);

    float peak = max(color.x, max(color.y, color.z));
    color.xyz *= rcp(peak + 1e-6);
    color.xyz *= applyTonemap(peak);

    color.xyz = lerp(color.xyz, perChannel, HueShift);

    color.xyz = rgb2ictcp(color.xyz);
    float saturationBoost = Resaturation * smoothstep(1.0, 0.5, ictcp.x);
    color.yz = lerp(color.yz, ictcp.yz * color.x / max(1e-3, ictcp.x), saturationBoost);
    color.yz *= Saturation;
    color.xyz = ictcp2rgb(color.xyz);

    return color;
}
If you would like to match the Frostbyte tonemapper exactly, this is the tonemapping function you'll want:

Code: Select all

float naturalShoulder(float x)
{
    return 1.0 - exp(-x);
}


float naturalShoulder(float x, float t)
{
    float v1 = x;
    float v2 = t + (1.0 - t) * naturalShoulder((x - t) / (1.0 - t));
    return x < t ? v1 : v2;
}


float3 naturalShoulder(float3 x, float t)
{
    return float3(
        naturalShoulder(x.x, t),
        naturalShoulder(x.y, t),
        naturalShoulder(x.z, t)
    );
}


float3 applyTonemap(float3 color)
{
    // TODO: Add parameters or consts for LinearSection and Whitepoint.
    // Try 0.25 for LinearSection and 4.0 for Whitepoint as a start
    return naturalShoulder(color.xyz, LinearSection) * rcp(naturalShoulder(Whitepoint, LinearSection));
}
Before:
Image

After:
Image

Another comparison: http://www.screenshotcomparison.com/comparison/130281
Last edited by SandvichDISH on 07 Apr 2020, 21:40, edited 2 times in total.
_________________
Reforged ENB for Dragon's Dogma, The Witcher 2, Kingdom Come: Deliverance

Offline
Posts: 3
Joined: 24 Oct 2016, 19:56

Re: Frostbyte style tonemap color processing

Very interesting. I'm usually not a fan of the frostbite engine really. But this is very impressive. Is this for SSE/FO4?

Offline
User avatar
Posts: 99
Joined: 11 May 2014, 10:48

Re: Frostbyte style tonemap color processing

It should be usable in any version of ENB, since it's HLSL code that works in both DX9 and DX11, and isn't reliant on any specific features.
_________________
Reforged ENB for Dragon's Dogma, The Witcher 2, Kingdom Come: Deliverance

Offline
User avatar
*blah-blah-blah maniac*
Posts: 836
Joined: 10 Dec 2017, 17:10

Re: Frostbyte style tonemap color processing

Hmm.. on my 10bit monitor the difference on these screenshots is very subtle.
(on the other images from the given link it is more visible though)
What does it do that ENB can't ? Better FPS ? Just asking.

Where is this place on your screenshots ? What mod ?

Offline
User avatar
Posts: 99
Joined: 11 May 2014, 10:48

Re: Frostbyte style tonemap color processing

@Anubis

The difference is subtle although plenty noticable ingame, I set it up in the screenshots with the defaults from the presentation but you could make the effect more pronounced.
One noteworthy part that can be tweaked but I didn't mention is that inside ictcp_colorspaces.fx, you will find these functions:

Code: Select all

float3 rgb2ictcp(float3 col)
{
    col = rgb2lms(col);
    col = linear2pq(max(0.0, col), 100.0);
    col = lms2ictcp(col);

    return col;
}


float3 ictcp2rgb(float3 col)
{
    col = ictcp2lms(col);
    col = pq2linear(col, 100.0);
    col = lms2rgb(col);

    return col;
}
The hardcoded 100.0 in the pq function calls determines the range of brightness of the ictcp colorspace. If you reduce this number the sensitivity of the effect will be greater.

As for what it can do that ENB can't, it's a slightly confusing question. If you mean what this code can do that Boris's default enbeffect.fx that's bundled with ENB can't do, the answer is just that this effect does not exist inside the default enbeffect. The tonemapping Boris generally includes simply applies per channel as is usual, and will cause all the same hue shifts that happen when applying tonemapping this way.

This code is meant to add on to your existing tonemapping, and what this effect does is give you control over the amount of hue shift you allow tonemapping to cause, and then adds a desaturation factor so that colors still retain their perceived brightness (this is what a hue preserving tonemap looks like without any desaturation effect).

The screenshot is from Enderal, a total conversion mod for Skyrim LE, and the screenshotcomparison one is somewhere in Fallout 4.
_________________
Reforged ENB for Dragon's Dogma, The Witcher 2, Kingdom Come: Deliverance

Offline
User avatar
*blah-blah-blah maniac*
Posts: 836
Joined: 10 Dec 2017, 17:10

Re: Frostbyte style tonemap color processing

Thanks. Now i get it.

Offline
User avatar
Posts: 56
Joined: 02 Aug 2017, 13:30

Re: Frostbyte style tonemap color processing

Neat stuff ;) Definitely an improvement to my setup

Offline
Posts: 1
Joined: 21 Mar 2020, 21:02

Re: Frostbyte style tonemap color processing

Sorry to revive this.
@SandvichDISH I'd like to get in touch with you. Need to ask you a few questions regarding this method as I'm trying to build a LUT for FIFA (Frostbite), but I'm facing some gamma/brightness inconsistencies between what I see in the software I use (either DaVinci Resolve and/or Photoshop) and the final result in-game. And it's driving me crazy.

Please let me know how to contact you!
Thank you very much.

Offline
User avatar
Posts: 99
Joined: 11 May 2014, 10:48

Re: Frostbyte style tonemap color processing

@Chuny, I don't really know what exactly you're doing, but this effect has nothing to do with applying LUTs so I'm not sure how it relates. Are you trying to make an HDR LUT? Or just a LDR one applied after tonemapping?
_________________
Reforged ENB for Dragon's Dogma, The Witcher 2, Kingdom Come: Deliverance

Offline
Posts: 86
Joined: 24 Jan 2012, 05:49

Re: Frostbyte style tonemap color processing

thx for uploading such a nice addon for shader!

btw I read whole ppt that you linked.
If I understand correctly, the ppt means normal tonemapping method cause hue shifting in very bright area and It looks unnatural on HDR display.

but I don't understand what is role of your file.
it has four different parameters: Desaturation, HueShift, Resaturation, Saturation

what does it means exactly and why those things needed?

I currently use GT tonemapping on Skyrim LE imported from shadertoy.
Post Reply