diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h
index e701b62fdcd82b343252915f5f02130d4f8ccfa7..b453b91e6740ac07edd39c07eb88629c9986a70c 100644
--- a/indra/llprimitive/llgltfmaterial.h
+++ b/indra/llprimitive/llgltfmaterial.h
@@ -98,7 +98,8 @@ class LLGLTFMaterial : public LLRefCount
 
     std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform;
 
-    // NOTE : initialize values to defaults according to the GLTF spec
+    // NOTE: initialize values to defaults according to the GLTF spec
+    // NOTE: these values should be in linear color space
     LLColor4 mBaseColor = LLColor4(1, 1, 1, 1);
     LLColor3 mEmissiveColor = LLColor3(0, 0, 0);
 
diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp
index 52118172c04bbdf40e28b157cb328c248e93fec9..ac48a633c721ec19866edcbc06625934b11fd9e9 100644
--- a/indra/llrender/llcubemaparray.cpp
+++ b/indra/llrender/llcubemaparray.cpp
@@ -122,7 +122,7 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, BOOL us
 
     bind(0);
 
-    U32 format = components == 4 ? GL_RGBA12 : GL_RGB10;
+    U32 format = components == 4 ? GL_RGBA12 : GL_RGB16F;
 
     U32 mip = 0;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index 6ab966ae01ae8c129d97afa22a4bb5014f292e1b..0b4a59c866eaef143d9e90e750233868c181359b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -396,7 +396,7 @@ vec3 pbrIbl(vec3 diffuseColor,
 
     specContrib = specular * ao;
 
-	return (diffuse + specular*0.5) * ao;  //reduce by half to place in appropriate color space for atmospherics
+	return (diffuse + specular) * ao;
 }
 
 vec3 pbrIbl(vec3 diffuseColor,
@@ -562,16 +562,13 @@ vec3 pbrBaseLight(vec3 diffuseColor, vec3 specularColor, float metallic, vec3 v,
     float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0);
     
     vec3 ibl_spec;
-    color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, 0.2, ibl_spec);
+    color += pbrIbl(diffuseColor, specularColor, radiance, irradiance, ao, NdotV, perceptualRoughness, ibl_spec);
     
     color += pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, norm, v, normalize(light_dir), specContrib) * sunlit * 2.75 * scol;
     specContrib *= sunlit * 2.75 * scol;
     specContrib += ibl_spec;
 
-    color += colorEmissive*0.5;
-
-    color = atmosFragLightingLinear(color, additive, atten);
-    color = scaleSoftClipFragLinear(color);
+    color += colorEmissive; //divide by two to correct for magical multiply by two in atmosFragLighting
 
     return color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index afe504743d0aab60c13c917f6f1b0cce8b24f8db..c406c669f2f2601e1cc22e16a452926c6fbd7666 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -88,8 +88,11 @@ void main()
 #endif
 
 #ifndef IS_HUD
+    color.rgb = fullbrightAtmosTransport(color.rgb);
+    color.rgb = fullbrightScaleSoftClip(color.rgb);
     color.rgb = srgb_to_linear(color.rgb);
 #endif
+
     frag_color.rgb = color.rgb;
     frag_color.a   = color.a;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index cc77712347a33d8c9dd10db356ae4b8df0498871..383fcaa9a721147aef702bd07816f1b6018189aa 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -44,9 +44,6 @@ 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
@@ -65,29 +62,6 @@ const mat3 ACESOutputMat = mat3
     -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)
@@ -128,13 +102,13 @@ vec3 toneMapACES_Hill(vec3 color)
 }
 
 uniform float exposure;
+uniform float gamma;
 
 vec3 toneMap(vec3 color)
 {
     color *= exposure;
 
 #ifdef TONEMAP_ACES_NARKOWICZ
-    color *= 0.8;
     color = toneMapACES_Narkowicz(color);
 #endif
 
@@ -146,11 +120,12 @@ vec3 toneMap(vec3 color)
     // 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.85/0.6;
+    color *= 1.0/0.6;
+    //color /= 0.6;
     color = toneMapACES_Hill(color);
 #endif
 
-    return linearTosRGB(color);
+    return linear_to_srgb(color);
 }
 
 //===============================================================
@@ -193,16 +168,26 @@ float noise(vec2 x) {
 
 //=============================
 
+
+vec3 legacyGamma(vec3 color)
+{
+    color = 1. - clamp(color, vec3(0.), vec3(1.));
+    color = 1. - pow(color, vec3(gamma)); // s/b inverted already CPU-side
+
+    return color;
+}
+
 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 = toneMap(diff.rgb);
-    vec2 tc = vary_fragcoord.xy*screen_res;
-
+    diff.rgb = legacyGamma(diff.rgb);
+    
+    vec2 tc = vary_fragcoord.xy*screen_res*4.0;
     vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
     vec3 nz = vec3(noise(seed.rg), noise(seed.gb), noise(seed.rb));
-    diff.rgb += nz*0.008;
+    diff.rgb += nz*0.003;
     //diff.rgb = nz;
     frag_color = diff;
 }
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index 16651dcdbcb11b873488d34d3ed1e14ba08bc366..e3a201c724407825f289e690198d565a046fc412 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -33,6 +33,7 @@ uniform float waterFogKS;
 vec3 getPositionEye();
 
 vec3 srgb_to_linear(vec3 col);
+vec3 linear_to_srgb(vec3 col);
 
 vec4 applyWaterFogView(vec3 pos, vec4 color)
 {
@@ -68,6 +69,7 @@ vec4 applyWaterFogView(vec3 pos, vec4 color)
     float D = pow(0.98, l*kd);
     
     color.rgb = color.rgb * D + kc.rgb * L;
+    color.a = kc.a + color.a;
 
     return color;
 }
@@ -120,7 +122,10 @@ vec4 applyWaterFogViewLinear(vec3 pos, vec4 color, vec3 sunlit)
         return color;
     }
 
-    return applyWaterFogViewLinearNoClip(pos, color, sunlit);
+    color.rgb = linear_to_srgb(color.rgb);
+    color = applyWaterFogView(pos, color);
+    color.rgb = srgb_to_linear(color.rgb);
+    return color;
 }
 
 vec4 applyWaterFogViewLinear(vec3 pos, vec4 color)
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index e2694e060e183be9d358f8d3477e7b0ec2adc2ca..ef35bf3fd740c60571167d40d086af9a0b31a415 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -250,6 +250,9 @@ void main()
 
     calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
 
+    vec3 sunlit_linear = srgb_to_linear(sunlit);
+    vec3 amblit_linear = amblit;
+
     vec3 irradiance;
     vec3 glossenv;
     vec3 legacyenv;
@@ -266,7 +269,7 @@ void main()
 
     color.a   = final_alpha;
 
-    vec3 sun_contrib = min(final_da, shadow) * sunlit;
+    vec3 sun_contrib = min(final_da, shadow) * sunlit_linear;
 
     color.rgb = max(amblit, irradiance);
 
@@ -274,8 +277,10 @@ void main()
 
     color.rgb *= diffuse_linear.rgb;
 
+    color.rgb = linear_to_srgb(color.rgb);
     color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
     color.rgb = scaleSoftClipFragLinear(color.rgb);
+    color.rgb = srgb_to_linear(color.rgb);
 
     vec4 light = vec4(0,0,0,0);
     
@@ -294,8 +299,9 @@ void main()
     color.rgb += light.rgb;
 #endif // !defined(LOCAL_LIGHT_KILL)
 
+
 #ifdef WATER_FOG
-    color = applyWaterFogViewLinear(pos.xyz, color, sunlit);
+    color = applyWaterFogViewLinear(pos.xyz, color, sunlit_linear);
 #endif // WATER_FOG
 
 #endif // #else // FOR_IMPOSTOR
@@ -303,6 +309,7 @@ void main()
 #ifdef IS_HUD
     color.rgb = linear_to_srgb(color.rgb);
 #endif
+
     frag_color = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
index 2a093827cb8fc607a898d38c5fe24382fc1aaded..fb76db99a043320c7dc5bc9e21720689fc6b1cd8 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -82,6 +82,8 @@ vec3 srgb_to_linear(vec3 c);
 vec3 linear_to_srgb(vec3 c);
 
 void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec3 atmosFragLightingLinear(vec3 color, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFragLinear(vec3 color);
 
 void calcHalfVectors(vec3 lv, vec3 n, vec3 v, out vec3 h, out vec3 l, out float nh, out float nl, out float nv, out float vh, out float lightDist);
 float calcLegacyDistanceAttenuation(float distance, float falloff);
@@ -196,6 +198,8 @@ void main()
     vec3 atten;
     calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
 
+    vec3 sunlit_linear = srgb_to_linear(sunlit);
+
     vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
 
 #ifdef HAS_SUN_SHADOW
@@ -229,9 +233,14 @@ void main()
     vec3 v = -normalize(pos.xyz);
 
     vec3 spec;
-    color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec);
+    color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten, spec);
     glare += max(max(spec.r, spec.g), spec.b);
 
+    color.rgb = linear_to_srgb(color.rgb);
+    color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
+    color.rgb = scaleSoftClipFragLinear(color.rgb);
+    color.rgb = srgb_to_linear(color.rgb);
+
     vec3 light = vec3(0);
 
     // Punctual lights
diff --git a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
index 5fa53c374b6c6f2a567bcc0c4a3174f5a4e8f449..080f622155544c5ce0b058a6919f949fe4a37056 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/reflectionProbeF.glsl
@@ -47,7 +47,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness)
 {
     sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness);
-    glossenv *= 8.0;
 }
 
 vec4 sampleReflectionProbesDebug(vec3 pos)
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index 6668a0084107821773c55723ddc4c3271f6b87a5..1d024982090f94892b909348d09be92fdfdd6f2d 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -33,8 +33,8 @@ vec3 linear_to_srgb(vec3 col);
 vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
 { 
     light *= atten.r;
-    light += additive;
-    return light * 2.0;
+    light += additive * 2.0;
+    return light;
 }
 
 vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten)
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
index f9f625ecdbd1cb5e4ba8a21a574308cce7fa669b..768f42206083988cae6602db7dea10afaaf6c4fc 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
@@ -137,8 +137,8 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
     additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb);
 
     // brightness of surface both sunlight and ambient
-    sunlit = sunlight.rgb;
-    amblit = tmpAmbient.rgb;
+    sunlit = sunlight.rgb * 0.7;
+    amblit = tmpAmbient.rgb * 0.25;
     additive *= vec3(1.0 - combined_haze);
 }
 
@@ -150,21 +150,22 @@ vec3 srgb_to_linear(vec3 col);
 float ambientLighting(vec3 norm, vec3 light_dir)
 {
     float ambient = min(abs(dot(norm.xyz, light_dir.xyz)), 1.0);
-    ambient *= 0.56;
+    ambient *= 0.5;
     ambient *= ambient;
     ambient = (1.0 - ambient);
     return ambient;
 }
 
 
-// return colors in linear space
+// return lit amblit in linear space, leave sunlit and additive in sRGB space
 void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive,
                          out vec3 atten)
 {
     calcAtmosphericVars(inPositionEye, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-    sunlit = srgb_to_linear(sunlit);
-    additive = srgb_to_linear(additive);
-    amblit = ambient_linear;
+
+    sunlit *= 2.0;
+    amblit *= 2.0;
 
     amblit *= ambientLighting(norm, light_dir);
+    amblit = srgb_to_linear(amblit);
 }
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index 9a9b179e6a7ac5a1c724084142b67d74fe534c8f..027bfb866f42d0e5ef57a5cf60eb62ccd921491e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -22,43 +22,34 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
-uniform float gamma;
 
-vec3 getAtmosAttenuation();
-vec3 getAdditiveColor();
+ // DEPRECATED
 
-vec3 srgb_to_linear(vec3 col);
-vec3 linear_to_srgb(vec3 col);
+//soft clip effect has been moved to postDeferredGammaCorrect legacyGamma, this file is effectively dead
+// but these functions need to be removed from all existing shaders before removing this file
 
-vec3 scaleSoftClipFragLinear(vec3 light)
-{ // identical to non-linear version and that's probably close enough
-    //soft clip effect:
-    light = 1. - clamp(light, vec3(0.), vec3(1.));
-    light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
+vec3 scaleSoftClipFrag(vec3 light)
+{
     return light;
 }
 
-vec3 scaleSoftClipFrag(vec3 light)
-{
-    //soft clip effect:
-    light = 1. - clamp(light, vec3(0.), vec3(1.));
-    light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
+vec3 scaleSoftClipFragLinear(vec3 light)
+{ // identical to non-linear version and that's probably close enough
     return light;
 }
 
 vec3 scaleSoftClip(vec3 light)
 {
-    return scaleSoftClipFrag(light);
+    return light;
 }
 
 vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 add, vec3 atten)
 {
-    //return mix(scaleSoftClipFrag(light.rgb), add, atten);
-    return scaleSoftClipFrag(light.rgb);
+    return light;
 }
 
 vec3 fullbrightScaleSoftClip(vec3 light)
 {
-    return fullbrightScaleSoftClipFrag(light, getAdditiveColor(), getAtmosAttenuation());
+    return light;
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index c509d865baca4a54a2612d5f68cf80f91a1ff636..6aa719d2001239e848d902e759b47e40f8496e6d 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -48,23 +48,27 @@ vec3 atmosTransport(vec3 light)
 vec3 fullbrightAtmosTransportFragLinear(vec3 light, vec3 additive, vec3 atten)
 {
     // same as non-linear version, probably fine
-    float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;    
-    return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+    //float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;    
+    //return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+    return atmosTransportFrag(light, additive, atten);
 }
 
 vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
 {
-    float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;    
-    return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+    //float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;    
+    //return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+    return atmosTransportFrag(light, additive, atten);
 }
 
 vec3 fullbrightAtmosTransport(vec3 light)
 {
-    return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
+    //return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
+    return atmosTransport(light);
 }
 
 vec3 fullbrightShinyAtmosTransport(vec3 light)
 {
-    float brightness = dot(light.rgb, vec3(0.33333));
-    return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
+    //float brightness = dot(light.rgb, vec3(0.33333));
+    //return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
+    return atmosTransport(light);
 }
diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
index 49529860be3e6f2d386a340ff5e4f727b161195b..add1cb2a377b948c4c718977873db32462378ffd 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl
@@ -334,16 +334,19 @@ void main()
     vec3 atten;
     calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
     
+    vec3 sunlit_linear = srgb_to_linear(sunlit);
+    vec3 amblit_linear = amblit;
+
     vec3 ambenv;
     vec3 glossenv;
     vec3 legacyenv;
     sampleReflectionProbesLegacy(ambenv, glossenv, legacyenv, pos.xy*0.5+0.5, pos.xyz, norm.xyz, glossiness, env);
     
     // use sky settings ambient or irradiance map sample, whichever is brighter
-    color = max(amblit, ambenv);
+    color = max(amblit_linear, ambenv);
 
     float da          = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
-    vec3 sun_contrib = min(da, shadow) * sunlit;
+    vec3 sun_contrib = min(da, shadow) * sunlit_linear;
     color.rgb += sun_contrib;
     color *= diffcol.rgb;
 
@@ -354,7 +357,7 @@ void main()
     if (glossiness > 0.0)  // specular reflection
     {
         float sa        = dot(normalize(refnormpersp), light_dir.xyz);
-        vec3  dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r);
+        vec3  dumbshiny = sunlit_linear * shadow * (texture2D(lightFunc, vec2(sa, glossiness)).r);
 
         // add the two types of shiny together
         vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -379,8 +382,10 @@ void main()
         glare += cur_glare;
     }
 
-    color.rgb = mix(atmosFragLightingLinear(color.rgb, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), emissive); 
+    color.rgb = linear_to_srgb(color.rgb);
+    color.rgb = atmosFragLightingLinear(color.rgb, additive, atten); 
     color.rgb = scaleSoftClipFragLinear(color.rgb);
+    color.rgb = srgb_to_linear(color.rgb);
 
     vec3 npos = normalize(-pos.xyz);
     vec3 light = vec3(0, 0, 0);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 23c6f4d5ae889d56a44de2220b0a0f26121bc95f..c6d649086adb8c22b3b2a1cb668acd54f176b399 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -458,28 +458,24 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da, int i
 // dir - pixel normal
 //  w - weight of sample (distance and angular attenuation)
 //  dw - weight of sample (distance only)
-// vi - return value of intersection point with influence volume
-// wi - return value of approximate world space position of sampled pixel
-// lod - which mip to bias towards (lower is higher res, sharper reflections)
+// lod - which mip to sample (lower is higher res, sharper reflections)
 // c - center of probe
 // r2 - radius of probe squared
 // i - index of probe 
-vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
+vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, float lod, vec3 c, int i)
 {
-    //lod = max(lod, 1);
     // parallax adjustment
-
     vec3 v;
 
     if (refIndex[i].w < 0)
-    {
+    {  // box probe
         float d = 0;
         v = boxIntersect(pos, dir, i, d);
 
         w = max(d, 0.001);
     }
     else
-    {
+    { // sphere probe
         float r = refSphere[i].w;
 
         float rr = r * r;
@@ -491,16 +487,12 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, out vec3 vi, out v
         w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25, i, dw);
     }
 
-    vi = v;
-
     v -= c;
     vec3 d = normalize(v);
 
     v = env_mat * v;
     
-    vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod);
-
-    wi = d * ret.a * 256.0+c;
+    vec4 ret = textureLod(reflectionProbes, vec4(v.xyz, refIndex[i].x), lod) * refParams[i].y;
 
     return ret.rgb;
 }
@@ -568,12 +560,11 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod)
 
         float w = 0;
         float dw = 0;
-        vec3 vi, wi;
         vec3 refcol;
 
         
         {
-            refcol = tapRefMap(pos, dir, w, dw, vi, wi, lod, refSphere[i].xyz, i);
+            refcol = tapRefMap(pos, dir, w, dw, lod, refSphere[i].xyz, i);
 
             col[p] += refcol.rgb*w;
             wsum[p] += w;
@@ -665,7 +656,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness)
 {
     // TODO - don't hard code lods
-    float reflection_lods = max_probe_lod;
+    float reflection_lods = max_probe_lod-1;
     preProbeSample(pos);
 
     vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
@@ -690,6 +681,7 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,
         vec2 tc, vec3 pos, vec3 norm, float glossiness)
 {
     sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness);
+    glossenv *= 0.25;
 }
 
 void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 8d48e6f59628087d3d9b90f89c48cbf2e9a829b0..dfd1d47b3ec4baec154756d28eb0581a6b0777e4 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -85,6 +85,8 @@ float getDepth(vec2 pos_screen);
 vec3 linear_to_srgb(vec3 c);
 vec3 srgb_to_linear(vec3 c);
 
+uniform vec4 waterPlane;
+
 #ifdef WATER_FOG
 vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
 #endif
@@ -153,6 +155,24 @@ void main()
 
     calcAtmosphericVarsLinear(pos.xyz, norm.xyz, light_dir, sunlit, amblit, additive, atten);
 
+    vec3 sunlit_linear = srgb_to_linear(sunlit);
+    vec3 amblit_linear = amblit;
+
+    bool do_atmospherics = false;
+
+#ifndef WATER_FOG
+    // when above water, mask off atmospherics below water
+    if (dot(pos.xyz, waterPlane.xyz) + waterPlane.w > 0.0)
+    {
+        do_atmospherics = true;
+    }
+#else
+    do_atmospherics = true;
+#endif
+
+    vec3  irradiance = vec3(0);
+    vec3  radiance  = vec3(0);
+
     if (GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_PBR))
     {
         vec3 orm = texture2D(specularRect, tc).rgb; 
@@ -161,23 +181,32 @@ void main()
         float ao = orm.r * ambocc;
 
         vec3 colorEmissive = texture2D(emissiveRect, tc).rgb;
-
         // PBR IBL
         float gloss      = 1.0 - perceptualRoughness;
-        vec3  irradiance = vec3(0);
-        vec3  radiance  = vec3(0);
+        
         sampleReflectionProbes(irradiance, radiance, tc, pos.xyz, norm.xyz, gloss);
         
         // Take maximium of legacy ambient vs irradiance sample as irradiance
         // NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
-        irradiance       = max(amblit,irradiance);
+        irradiance       = max(amblit_linear,irradiance);
 
         vec3 diffuseColor;
         vec3 specularColor;
         calcDiffuseSpecular(baseColor.rgb, metallic, diffuseColor, specularColor);
 
         vec3 v = -normalize(pos.xyz);
-        color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
+        color = vec3(1,0,1);
+        color = pbrBaseLight(diffuseColor, specularColor, metallic, v, norm.xyz, perceptualRoughness, light_dir, sunlit_linear, scol, radiance, irradiance, colorEmissive, ao, additive, atten);
+
+        
+        if (do_atmospherics)
+        {
+            color = linear_to_srgb(color);
+            color = atmosFragLightingLinear(color, additive, atten);
+            color = srgb_to_linear(color);
+        }
+        
+        
     }
     else if (!GET_GBUFFER_FLAG(GBUFFER_FLAG_HAS_ATMOS))
     {
@@ -199,12 +228,12 @@ void main()
         sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, tc, pos.xyz, norm.xyz, spec.a, envIntensity);
         
         // use sky settings ambient or irradiance map sample, whichever is brighter
-        irradiance = max(amblit, irradiance);
+        irradiance = max(amblit_linear, irradiance);
 
         // apply lambertian IBL only (see pbrIbl)
         color.rgb = irradiance * ambocc;
 
-        vec3 sun_contrib = min(da, scol) * sunlit;
+        vec3 sun_contrib = min(da, scol) * sunlit_linear;
         color.rgb += sun_contrib;
         color.rgb *= baseColor.rgb;
         
@@ -230,9 +259,16 @@ void main()
             applyLegacyEnv(color, legacyenv, spec, pos.xyz, norm.xyz, envIntensity);
         }
 
-        color = mix(atmosFragLightingLinear(color, additive, atten), fullbrightAtmosTransportFragLinear(color, additive, atten), baseColor.a);
-        color = scaleSoftClipFragLinear(color);
-    }
+        
+        if (do_atmospherics)
+        {
+            color = linear_to_srgb(color);
+            color = atmosFragLightingLinear(color, additive, atten);
+            color = srgb_to_linear(color);
+        }
+   }
+
+    
 
     #ifdef WATER_FOG
         vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
index a87682affb258312f4196b729d9b4463a71551a5..991079e77a12c4132aab11ac6a787c056d5cb1df 100644
--- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -114,6 +114,7 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
 }
 
 vec3 srgb_to_linear(vec3 col);
+vec3 linear_to_srgb(vec3 col);
 
 vec3 vN, vT, vB;
 
@@ -200,6 +201,8 @@ void main()
 
     calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
 
+    vec3 sunlit_linear = srgb_to_linear(sunlit);
+
 #ifdef TRANSPARENT_WATER
     vec4 fb = texture2D(screenTex, distort2);
     float depth = texture2D(screenDepth, distort2).r;
@@ -216,9 +219,10 @@ void main()
 
     fb = applyWaterFogViewLinear(refPos, fb, sunlit);
 #else
-    vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0), sunlit);
+    vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0), sunlit_linear);
 #endif
 
+    fb.rgb *= 0.75;
     float metallic = 0.0;
     float perceptualRoughness = 0.05;
     float gloss      = 1.0 - perceptualRoughness;
@@ -247,10 +251,7 @@ void main()
 
     vec3 punctual = pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir));
 
-    vec3 color = punctual * sunlit * 2.75 * scol;
-
-    color = atmosFragLightingLinear(color, additive, atten);
-    color = scaleSoftClipFragLinear(color);
+    vec3 color = punctual * sunlit_linear * 2.75 * scol;
 
     vec3 ibl = pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0);
 
@@ -274,6 +275,12 @@ void main()
 
     color = mix(color, fb.rgb, f);
 
+    color.rgb = linear_to_srgb(color.rgb);
+    color = atmosFragLightingLinear(color, additive, atten);
+    color = scaleSoftClipFragLinear(color);
+    color.rgb = srgb_to_linear(color.rgb);
+
+
     float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
     
     frag_color = vec4(color, spec); //*sunAngle2);
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 9962d0c10cb4511a6219b17859ce7e70497018a1..61d87564901923661872f0bc85135a52a8fc35e2 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -814,7 +814,7 @@ void LLReflectionMapManager::updateUniforms()
     F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance(cloud_shadow_scale);
 
     F32 ambscale = gCubeSnapshot && !isRadiancePass() ? 0.f : 1.f;
-    
+    F32 radscale = gCubeSnapshot && !isRadiancePass() ? 0.5f : 1.f;
 
     for (auto* refmap : mReflectionMaps)
     {
@@ -852,7 +852,7 @@ void LLReflectionMapManager::updateUniforms()
             rpd.refIndex[count][3] = -rpd.refIndex[count][3];
         }
 
-        rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, 0.f, 0.f, 0.f);
+        rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, 0.f, 0.f);
 
         S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors
         {
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 1752b2494f20e70340a64f659862cd58e565f465..ac5bde7b9b4704392c4468dc10dddddd60f6459c 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -716,15 +716,15 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
 
     LLColor3 ambient(getTotalAmbient());
 
-    shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
-
     if (radiance_pass)
     { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue)
         shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV);
+        shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3::zero.mV);
     }
     else
     {
         shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT
+        shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
     }
 
     shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index f4f20ee7a64c52cbb5cc664ecb275c93e4b54abf..31c71aac2af686c00e46ff9b8175466c52bae576 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -235,7 +235,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderLevel(SHADER_COUNT, 0),
 	mMaxAvatarShaderLevel(0)
 {   
-    /// Make sure WL Sky is the first program
     //ONLY shaders that need WL Param management should be added here
 	mShaderList.push_back(&gAvatarProgram);
 	mShaderList.push_back(&gWaterProgram);
@@ -291,6 +290,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
     mShaderList.push_back(&gDeferredPBRAlphaProgram);
     mShaderList.push_back(&gHUDPBRAlphaProgram);
     mShaderList.push_back(&gDeferredSkinnedPBRAlphaProgram);
+    mShaderList.push_back(&gDeferredPostGammaCorrectProgram); // for gamma
 
 }
 
@@ -2524,6 +2524,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         else if (tonemapper == 2)
         {
             gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_ACES_HILL_EXPOSURE_BOOST", "1");
+        }
+        else
+        {
+            gDeferredPostGammaCorrectProgram.addPermutation("TONEMAP_LINEAR", "1");
         }
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER));
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index b5b5d9ef7fabd500f6accf076662571eeb4ea30a..fffccc72ea8029f794969d118deaf2c5d533c08a 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8119,6 +8119,8 @@ void LLPipeline::renderDeferredLighting()
             soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
             soften_shader.uniform3fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
 
+            soften_shader.uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, LLDrawPoolAlpha::sWaterPlane.mV);
+
             {
                 LLGLDepthTest depth(GL_FALSE);
                 LLGLDisable   blend(GL_BLEND);