From 131d116ffd21ef1e726e21c8fe2e6b7068c6c3d9 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 21 Feb 2023 15:40:20 -0600
Subject: [PATCH] SL-19239 Day after three day quality pass - add ACES tone
 mapping to address "haziness" (and also fix banding in emissive materials)

---
 .../deferred/postDeferredGammaCorrect.glsl    | 118 +++++++++++++++++-
 indra/newview/pipeline.cpp                    |   2 +-
 2 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index 987b2d1fe80..e0e975faf01 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -41,6 +41,122 @@ uniform float display_gamma;
 
 vec3 linear_to_srgb(vec3 cl);
 
+//===============================================================
+// tone mapping taken from Khronos sample implementation
+//===============================================================
+const float GAMMA = 2.2;
+const float INV_GAMMA = 1.0 / GAMMA;
+
+
+// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
+const mat3 ACESInputMat = mat3
+(
+    0.59719, 0.07600, 0.02840,
+    0.35458, 0.90834, 0.13383,
+    0.04823, 0.01566, 0.83777
+);
+
+
+// ODT_SAT => XYZ => D60_2_D65 => sRGB
+const mat3 ACESOutputMat = mat3
+(
+    1.60475, -0.10208, -0.00327,
+    -0.53108,  1.10813, -0.07276,
+    -0.07367, -0.00605,  1.07602
+);
+
+
+// linear to sRGB approximation
+// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+vec3 linearTosRGB(vec3 color)
+{
+    return pow(color, vec3(INV_GAMMA));
+}
+
+
+// sRGB to linear approximation
+// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+vec3 sRGBToLinear(vec3 srgbIn)
+{
+    return vec3(pow(srgbIn.xyz, vec3(GAMMA)));
+}
+
+
+vec4 sRGBToLinear(vec4 srgbIn)
+{
+    return vec4(sRGBToLinear(srgbIn.xyz), srgbIn.w);
+}
+
+
+// ACES tone map (faster approximation)
+// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
+vec3 toneMapACES_Narkowicz(vec3 color)
+{
+    const float A = 2.51;
+    const float B = 0.03;
+    const float C = 2.43;
+    const float D = 0.59;
+    const float E = 0.14;
+    return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
+}
+
+
+// ACES filmic tone map approximation
+// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
+vec3 RRTAndODTFit(vec3 color)
+{
+    vec3 a = color * (color + 0.0245786) - 0.000090537;
+    vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
+    return a / b;
+}
+
+
+// tone mapping 
+vec3 toneMapACES_Hill(vec3 color)
+{
+    color = ACESInputMat * color;
+
+    // Apply RRT and ODT
+    color = RRTAndODTFit(color);
+
+    color = ACESOutputMat * color;
+
+    // Clamp to [0, 1]
+    color = clamp(color, 0.0, 1.0);
+
+    return color;
+}
+
+
+#define TONEMAP_ACES_NARKOWICZ
+//#define TONEMAP_ACES_HILL_EXPOSURE_BOOST
+float u_Exposure = 1;
+
+vec3 toneMap(vec3 color)
+{
+    color *= u_Exposure;
+
+#ifdef TONEMAP_ACES_NARKOWICZ
+    color = toneMapACES_Narkowicz(color);
+#endif
+
+#ifdef TONEMAP_ACES_HILL
+    color = toneMapACES_Hill(color);
+#endif
+
+#ifdef TONEMAP_ACES_HILL_EXPOSURE_BOOST
+    // boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621
+    // this factor is based on the exposure correction of Krzysztof Narkowicz in his
+    // implemetation of ACES tone mapping
+    color /= 0.6;
+    color = toneMapACES_Hill(color);
+#endif
+
+    return linearTosRGB(color);
+}
+
+//===============================================================
+
 //=================================
 // borrowed noise from:
 //	<https://www.shadertoy.com/view/4dS3Wd>
@@ -83,7 +199,7 @@ void main()
 {
     //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
     vec4 diff = texture2D(diffuseRect, vary_fragcoord);
-    diff.rgb = linear_to_srgb(diff.rgb);
+    diff.rgb = toneMap(diff.rgb);
     vec2 tc = vary_fragcoord.xy*screen_res;
 
     vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index e814b777251..69b149f82da 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -354,7 +354,7 @@ bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
     bool valid = true
         && target.addColorAttachment(GL_RGBA) // frag-data[1] specular OR PBR ORM
         && target.addColorAttachment(GL_RGBA16F)                              // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight
-        && target.addColorAttachment(GL_RGBA);                  // frag_data[3] PBR emissive
+        && target.addColorAttachment(GL_RGB16);                  // frag_data[3] PBR emissive
     return valid;
 }
 
-- 
GitLab