Introduce Khronos Neutral tonemapper as new default along with debug options to control tonemap mix (#2464) (#2468)
parent
7ab6144c00
commit
5b832291a8
|
|
@ -9832,6 +9832,28 @@
|
|||
<key>Value</key>
|
||||
<real>0.4</real>
|
||||
</map>
|
||||
<key>RenderTonemapMix</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Mix between linear and tonemapped colors (0.0(Linear) - 1.0(Tonemapped)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>F32</string>
|
||||
<key>Value</key>
|
||||
<real>1.0</real>
|
||||
</map>
|
||||
<key>RenderTonemapType</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>What tonemapper to use: 0 = Khronos Neutral, 1 = ACES</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>ReplaySession</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -29,9 +29,7 @@ out vec4 frag_color;
|
|||
|
||||
uniform sampler2D diffuseRect;
|
||||
|
||||
uniform float exposure;
|
||||
uniform float gamma;
|
||||
uniform float aces_mix;
|
||||
uniform vec2 screen_res;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
|
|
|
|||
|
|
@ -95,9 +95,33 @@ vec3 toneMapACES_Hill(vec3 color)
|
|||
return color;
|
||||
}
|
||||
|
||||
// Khronos Neutral tonemapping
|
||||
// https://github.com/KhronosGroup/ToneMapping/tree/main
|
||||
// Input color is non-negative and resides in the Linear Rec. 709 color space.
|
||||
// Output color is also Linear Rec. 709, but in the [0, 1] range.
|
||||
vec3 PBRNeutralToneMapping( vec3 color )
|
||||
{
|
||||
const float startCompression = 0.8 - 0.04;
|
||||
const float desaturation = 0.15;
|
||||
|
||||
float x = min(color.r, min(color.g, color.b));
|
||||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
|
||||
color -= offset;
|
||||
|
||||
float peak = max(color.r, max(color.g, color.b));
|
||||
if (peak < startCompression) return color;
|
||||
|
||||
const float d = 1. - startCompression;
|
||||
float newPeak = 1. - d * d / (peak + d - startCompression);
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
|
||||
return mix(color, newPeak * vec3(1, 1, 1), g);
|
||||
}
|
||||
|
||||
uniform float exposure;
|
||||
uniform float gamma;
|
||||
uniform float aces_mix;
|
||||
uniform float tonemap_mix;
|
||||
uniform int tonemap_type;
|
||||
|
||||
vec3 toneMap(vec3 color)
|
||||
{
|
||||
|
|
@ -106,8 +130,20 @@ vec3 toneMap(vec3 color)
|
|||
|
||||
color *= exposure * exp_scale;
|
||||
|
||||
// mix ACES and Linear here as a compromise to avoid over-darkening legacy content
|
||||
color = mix(toneMapACES_Hill(color), color, aces_mix);
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
|
|
@ -125,14 +161,6 @@ void debugExposure(inout vec3 color)
|
|||
}
|
||||
}
|
||||
|
||||
vec3 legacyGamma(vec3 color)
|
||||
{
|
||||
vec3 c = 1. - clamp(color, vec3(0.), vec3(1.));
|
||||
c = 1. - pow(c, vec3(gamma)); // s/b inverted already CPU-side
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
|
||||
|
|
|
|||
|
|
@ -7087,10 +7087,16 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst)
|
|||
F32 e = llclamp(exposure(), 0.5f, 4.f);
|
||||
|
||||
static LLStaticHashedString s_exposure("exposure");
|
||||
static LLStaticHashedString aces_mix("aces_mix");
|
||||
static LLStaticHashedString tonemap_mix("tonemap_mix");
|
||||
static LLStaticHashedString tonemap_type("tonemap_type");
|
||||
|
||||
shader.uniform1f(s_exposure, e);
|
||||
shader.uniform1f(aces_mix, gEXRImage.notNull() ? 0.f : 0.3f);
|
||||
|
||||
static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U);
|
||||
shader.uniform1i(tonemap_type, tonemap_type_setting);
|
||||
|
||||
static LLCachedControl<F32> tonemap_mix_setting(gSavedSettings, "RenderTonemapMix", 1.f);
|
||||
shader.uniform1f(tonemap_mix, tonemap_mix_setting);
|
||||
|
||||
mScreenTriangleVB->setBuffer();
|
||||
mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
|
||||
|
|
|
|||
Loading…
Reference in New Issue