summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRye Mutt <rye@lindenlab.com>2024-08-30 12:49:05 -0700
committerGitHub <noreply@github.com>2024-08-30 14:49:05 -0500
commit5b832291a8ea1f100e2caaffef3d162dd96bee50 (patch)
treef101fad72d8641aeb3aa2c018012b1c8adc236f4
parent7ab6144c0046338053019283f1f1ed75575b3496 (diff)
Introduce Khronos Neutral tonemapper as new default along with debug options to control tonemap mix (#2464) (#2468)
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl52
-rw-r--r--indra/newview/pipeline.cpp10
4 files changed, 70 insertions, 16 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d2c3c96317..a52d21edb5 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -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>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index 0673159ab7..befd2ae6da 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -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;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
index c16ab2f9c4..fc6d4d7727 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl
@@ -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)
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 91ade0eef1..3b1da8668b 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -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);