From d614bf11357d9ff1fef59c7ff11eff73b211dcac Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Fri, 9 Nov 2018 21:11:37 +0000
Subject: [PATCH] Yes, Maurice, baby steps.

---
 indra/llrender/llshadermgr.cpp                |  19 ++-
 .../shaders/class1/avatar/avatarSkinV.glsl    |   7 -
 .../shaders/class1/avatar/objectSkinV.glsl    |   7 -
 .../shaders/class1/deferred/pointLightV.glsl  |   2 +-
 .../shaders/class3/deferred/cloudsF.glsl      |  77 +++++++---
 .../shaders/class3/deferred/cloudsV.glsl      | 136 ++----------------
 .../class3/deferred/multiSpotLightF.glsl      |  13 +-
 .../shaders/class3/deferred/skyF.glsl         |  13 +-
 .../shaders/class3/deferred/skyV.glsl         |   8 +-
 .../shaders/class3/deferred/softenLightF.glsl | 107 ++++++++------
 .../shaders/class3/deferred/softenLightV.glsl |  12 +-
 .../shaders/class3/deferred/spotLightF.glsl   |  13 +-
 .../shaders/class3/deferred/sunLightF.glsl    |  22 +--
 .../class3/deferred/sunLightSSAOF.glsl        |  89 +-----------
 14 files changed, 168 insertions(+), 357 deletions(-)

diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index d6fe35e2ca5..e128979a765 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -171,6 +171,8 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	// Attach Fragment Shader Features Next
 	///////////////////////////////////////
 
+// NOTE order of shader object attaching is VERY IMPORTANT!!!
+
 	if(features->calculatesAtmospherics)
 	{
 		if (features->hasWaterFog)
@@ -194,7 +196,22 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
-	// NOTE order of shader object attaching is VERY IMPORTANT!!!
+    if (features->isDeferred || features->hasShadows)
+	{
+		if (!shader->attachObject("deferred/deferredUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->hasIndirect)
+	{
+		if (!shader->attachObject("deferred/indirect.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
 	if (features->hasGamma)
 	{
 		if (!shader->attachObject("windlight/gammaF.glsl"))
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
index 767fad016c9..c4caed4d719 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
@@ -38,12 +38,5 @@ mat4 getSkinnedTransform()
 	ret[1] = mix(matrixPalette[i+15],matrixPalette[i+16], x);
 	ret[2] = mix(matrixPalette[i+30],matrixPalette[i+31], x);
 	ret[3] = vec4(0,0,0,1);
-
 	return ret;
-
-#ifdef IS_AMD_CARD
-	// If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
-	vec4 dummy1 = matrixPalette[0];
-	vec4 dummy2 = matrixPalette[44];
-#endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
index 90bf2851c9e..94de2f7b539 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -61,12 +61,5 @@ mat4 getObjectSkinnedTransform()
 	ret[3] = vec4(trans, 1.0);
 				
 	return ret;
-
-#ifdef IS_AMD_CARD
-   // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
-   mat3x4 dummy1 = matrixPalette[0];
-   mat3x4 dummy2 = matrixPalette[MAX_JOINTS_PER_MESH_OBJECT-1];
-#endif
-
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index a5625fbc16e..3da85314428 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file pointLightF.glsl
+ * @file pointLightV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
index 9f06319da31..f8373215f09 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLCloudsF.glsl
+ * @file class3/deferred/cloudsF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,9 +24,9 @@
  */
  
 #ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
+out vec4 frag_data[3];
 #else
-#define frag_color gl_FragColor
+#define frag_data gl_FragData
 #endif
 
 /////////////////////////////////////////////////////////////////////////
@@ -36,20 +36,37 @@ out vec4 frag_color;
 VARYING vec4 vary_CloudColorSun;
 VARYING vec4 vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+VARYING vec3 vary_pos;
 
 uniform sampler2D cloud_noise_texture;
 uniform sampler2D cloud_noise_texture_next;
 uniform float blend_factor;
 uniform vec4 cloud_pos_density1;
 uniform vec4 cloud_pos_density2;
-uniform vec4 gamma;
+uniform vec4 sunlight_color;
+uniform vec4 cloud_color;
+uniform float cloud_shadow;
 uniform float cloud_scale;
 uniform float cloud_variance;
-
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
+uniform vec3 ambient;
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
 
 /// Soft clips the light with a gamma correction
 vec3 scaleSoftClip(vec3 light);
@@ -67,11 +84,9 @@ void main()
 	// Set variables
 	vec2 uv1 = vary_texcoord0.xy;
 	vec2 uv2 = vary_texcoord1.xy;
-
-	vec4 cloudColorSun = vary_CloudColorSun;
-	vec4 cloudColorAmbient = vary_CloudColorAmbient;
-	float cloudDensity = vary_CloudDensity;
 	vec2 uv3 = vary_texcoord2.xy;
+	float cloudDensity = 2.0 * (cloud_shadow - 0.25);
+
 	vec2 uv4 = vary_texcoord3.xy;
 
     vec2 disturbance = vec2(cloudNoise(uv1 / 16.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
@@ -82,33 +97,53 @@ void main()
 	uv3 += cloud_pos_density2.xy + disturbance;	//small texture, visible density
 	uv4 += cloud_pos_density2.xy;	//small texture, self shadow
 
+    float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0));
 
-	// Compute alpha1, the main cloud opacity
+    cloudDensity *= 1.0 - (density_variance * density_variance);
 
+	// Compute alpha1, the main cloud opacity
 	float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
-	alpha1 = min(max(alpha1 + cloudDensity, 0.) * (10. + disturbance.y) * cloud_pos_density1.z, 1.);
+	alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
 
 	// And smooth
 	alpha1 = 1. - alpha1 * alpha1;
 	alpha1 = 1. - alpha1 * alpha1;	
 
+    if (alpha1 < 0.001f)
+    {
+        discard;
+    }
 
 	// Compute alpha2, for self shadowing effect
 	// (1 - alpha2) will later be used as percentage of incoming sunlight
 	float alpha2 = (cloudNoise(uv2).x - 0.5);
-	alpha2 = min(max(alpha2 + cloudDensity, 0.) * (2.5 + disturbance.x) * cloud_pos_density1.z, 1.);
+	alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
 
 	// And smooth
 	alpha2 = 1. - alpha2;
 	alpha2 = 1. - alpha2 * alpha2;	
 
+    vec3 view_ray = vary_pos.xyz + camPosLocal;
+
+    vec3 view_direction = normalize(view_ray);
+    vec3 sun_direction  = normalize(sun_dir);
+    vec3 earth_center   = vec3(0, 0, -6360.0f);
+    vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
+
+    vec3 transmittance;
+    vec3 radiance_sun  = GetSkyLuminance(camPos, view_direction, 1.0 - alpha1, sun_direction, transmittance);
+
+    vec3 sun_color = vec3(1.0) - exp(-radiance_sun * 0.0001);
+
 	// Combine
 	vec4 color;
-	color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
-	color *= 2.;
 
-	/// Gamma correct for WL (soft clip effect).
-	frag_color.rgb = scaleSoftClip(color.rgb);
-	frag_color.a = alpha1;
+    color.rgb = sun_color * cloud_color.rgb * (1. - alpha2);
+    color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
+    color.rgb += ambient;
+
+	frag_data[0] = vec4(color.rgb, alpha1);
+	frag_data[1] = vec4(0);
+	frag_data[2] = vec4(0,1,0,1);
 }
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
index c1dd45cd672..53b6d88ef5e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
@@ -24,6 +24,7 @@
  */
 
 uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
 
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec2 texcoord0;
@@ -33,158 +34,37 @@ ATTRIBUTE vec2 texcoord0;
 ///////////////////////////////////////////////////////////////////////////////
 
 // Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
-VARYING float vary_CloudDensity;
 VARYING vec2 vary_texcoord0;
 VARYING vec2 vary_texcoord1;
 VARYING vec2 vary_texcoord2;
 VARYING vec2 vary_texcoord3;
+VARYING vec3 vary_pos;
 
 // Inputs
-uniform vec3 camPosLocal;
-
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
-
-uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float max_y;
-
-uniform vec4 glow;
-
-uniform vec4 cloud_color;
-
 uniform float cloud_scale;
+uniform vec4  lightnorm;
+uniform vec3  camPosLocal;
 
 void main()
 {
+    vary_pos = position;
 
 	// World / view / projection
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
 
-	vary_texcoord0 = texcoord0;
-
-	// Get relative position
-	vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
-	// Set altitude
-	if (P.y > 0.)
-	{
-		P *= (max_y / P.y);
-	}
-	else
-	{
-		P *= (-32000. / P.y);
-	}
-
-	// Can normalize then
-	vec3 Pn = normalize(P);
-	float  Plen = length(P);
-
-	// Initialize temp variables
-	vec4 temp1 = vec4(0.);
-	vec4 temp2 = vec4(0.);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	vec4 sunlight = sunlight_color;
-	vec4 light_atten;
-
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
-
-	// Calculate relative weights
-	temp1 = blue_density + haze_density;
-	blue_weight = blue_density / temp1;
-	haze_weight = haze_density / temp1;
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Distance
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z);
-
-
-	// Compute haze glow
-	temp2.x = dot(Pn, lightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .001);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.x *= glow.x;
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.x = pow(temp2.x, glow.z);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-	// Add "minimum anti-solar illumination"
-	temp2.x += .25;
-
-	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient;
-	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
-
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1. - cloud_shadow);
-
-	// Haze color below cloud
-	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-			 );	
-
-	// CLOUDS
-
-	sunlight = sunlight_color;
-	temp2.y = max(0., lightnorm.y * 2.);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Cloud color out
-	vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
-	vary_CloudColorAmbient = tmpAmbient * cloud_color;
-	
-	// Attenuate cloud color by atmosphere
-	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
-	vary_CloudColorSun *= temp1;
-	vary_CloudColorAmbient *= temp1;
-	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
-
-	// Make a nice cloud density based on the cloud_shadow value that was passed in.
-	vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
-
 	// Texture coords
 	vary_texcoord0 = texcoord0;
 	vary_texcoord0.xy -= 0.5;
-	vary_texcoord0.xy /= cloud_scale;
-	vary_texcoord0.xy += 0.5;
+    vary_texcoord0.xy /= cloud_scale;
+    vary_texcoord0.xy += 0.5;
 
 	vary_texcoord1 = vary_texcoord0;
 	vary_texcoord1.x += lightnorm.x * 0.0125;
-	vary_texcoord1.y += lightnorm.z * 0.0125;
+    vary_texcoord1.y += lightnorm.z * 0.0125;
 
 	vary_texcoord2 = vary_texcoord0 * 16.;
 	vary_texcoord3 = vary_texcoord1 * 16.;
 
-	// Combine these to minimize register use
-	vary_CloudColorAmbient += oHazeColorBelowCloud;
-
-	// needs this to compile on mac
-	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
 	// END CLOUDS
 }
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
index 864ba4859da..0848adba730 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
@@ -133,18 +133,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
index 2073fc066f6..d0514f7d234 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file class3/skyF.glsl
+ * @file class3/deferred/skyF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -44,6 +44,7 @@ uniform sampler3D single_mie_scattering_texture;
 uniform sampler2D irradiance_texture;
 uniform sampler2D rainbow_map;
 uniform sampler2D halo_map;
+uniform vec4 gamma;
 
 uniform float moisture_level;
 uniform float droplet_radius;
@@ -53,6 +54,7 @@ vec3 GetSolarLuminance();
 vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
 vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
 
+vec3 ColorFromRadiance(vec3 radiance);
 vec3 rainbow(float d)
 {
    float rad = (droplet_radius - 5.0f) / 1024.0f;
@@ -93,18 +95,15 @@ void main()
     }
     s = smoothstep(0.9, 1.0, s) * 16.0f;
 
-    vec3 color = vec3(1.0) - exp(-radiance_sun * 0.0001);
+    vec3 color = ColorFromRadiance(radiance_sun);
 
     float optic_d = dot(view_direction, sun_direction);
-
     vec3 halo_22 = halo22(optic_d);
 
-    if (optic_d <= 0)
-    color.rgb += rainbow(optic_d);
-
+    color.rgb += rainbow(optic_d) * optic_d;
     color.rgb += halo_22;
 
-    color = pow(color, vec3(1.0 / 2.2));
+    color = pow(color, vec3(1.0/2.2));
 
     frag_data[0] = vec4(color, 1.0 + s);
     frag_data[1] = vec4(0.0);
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
index a5cc49ca300..2eb222ada4a 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file advancedAtmoV.glsl
+ * @file class3/deferred/skyV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,12 +23,6 @@
  * $/LicenseInfo$
  */
  
-uniform vec3 cameraPosLocal;
-uniform mat4 modelview_projection_matrix;
-uniform mat4 modelview_matrix;
-uniform mat4 inv_proj;
-uniform mat4 inv_modelview;
-
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec2 texcoord0;
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index 2615400e52b..ecf6858136e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -38,30 +38,21 @@ uniform sampler2DRect specularRect;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 uniform sampler2DRect depthMap;
-uniform samplerCube environmentMap;
-uniform sampler2D	  lightFunc;
+uniform sampler2D     lightFunc;
 
 uniform float blur_size;
+uniform samplerCube environmentMap;
+
 uniform float blur_fidelity;
 
 // Inputs
 uniform vec4 morphFactor;
 uniform vec3 camPosLocal;
-//uniform vec4 camPosWorld;
 uniform vec4 gamma;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
-uniform float haze_horizon;
-uniform float haze_density;
 uniform float cloud_shadow;
-uniform float density_multiplier;
-uniform float distance_multiplier;
 uniform float max_y;
 uniform vec4 glow;
 uniform float global_gamma;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
 uniform vec4 shadow_clip;
 uniform mat3 ssao_effect_mat;
@@ -74,28 +65,29 @@ uniform mat4 inv_modelview;
 
 uniform vec2 screen_res;
 
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+vec3 GetSunAndSkyIrradiance(vec3 camPos, vec3 norm, vec3 dir, out vec3 sky_irradiance);
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
+vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
+
+vec3 scaleSoftClipFrag(vec3 c);
+vec3 fullbrightScaleSoftClipFrag(vec3 c);
 vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
 vec3 decode_normal (vec2 enc);
 
-vec4 getPosition_d(vec2 pos_screen, float depth)
-{
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	return getPosition_d(pos_screen, depth);
-}
-
+vec3 ColorFromRadiance(vec3 radiance);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
 #ifdef WATER_FOG
 vec4 applyWaterFogView(vec3 pos, vec4 color);
@@ -105,24 +97,22 @@ void main()
 {
 	vec2 tc = vary_fragcoord.xy;
 	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec3 pos = getPosition_d(tc, depth).xyz;
+	vec3 pos = getPositionWithDepth(tc, depth).xyz;
 	vec4 norm = texture2DRect(normalMap, tc);
 	float envIntensity = norm.z;
-	norm.xyz = decode_normal(norm.xy); // unpack norm
-		
+    norm.xyz = decode_normal(norm.xy);
+
 	float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
 
 	float light_gamma = 1.0/1.3;
-	da = pow(da, light_gamma);
 
-	vec4 diffuse = texture2DRect(diffuseRect, tc);
+	vec4 diffuse = texture2DRect(diffuseRect, tc); // linear
 
-	//convert to gamma space
-	diffuse.rgb = linear_to_srgb(diffuse.rgb);
-	
 	vec3 col;
 	float bloom = 0.0;
 	{
+        vec3 camPos = (camPosLocal / 1000.0f) + vec3(0, 0, 6360.0f);
+
 		vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
 		
 		vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
@@ -132,17 +122,37 @@ void main()
 
 		float ambocc = scol_ambocc.g;
 
-		col *= diffuse.rgb;
-	
+        vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
+        vec4 l1r = texture2D(sh_input_r, vec2(0,0));
+        vec4 l1g = texture2D(sh_input_g, vec2(0,0));
+        vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+
+        vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
+                             dot(l1g, l1tap * vec4(1, norm.xyz)),
+                             dot(l1b, l1tap * vec4(1, norm.xyz)));
+
+        indirect = clamp(indirect, vec3(0), vec3(1.0));
+
+        vec3 transmittance;
+        vec3 sky_irradiance;
+        vec3 sun_irradiance = GetSunAndSkyIrradiance(camPos, norm.xyz, sun_dir, sky_irradiance);
+        vec3 inscatter = GetSkyLuminanceToPoint(camPos, (pos / 1000.f) + vec3(0, 0, 6360.0f), scol, sun_dir, transmittance);
+
+        vec3 radiance   = scol * (sun_irradiance + sky_irradiance) + inscatter;
+        vec3 atmo_color = ColorFromRadiance(radiance);
+
+        col = atmo_color + indirect;
+        col *= transmittance;
+        col *= diffuse.rgb;
+
 		vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
 
 		if (spec.a > 0.0) // specular reflection
 		{
 			// the old infinite-sky shiny reflection
 			//
-			
 			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+			vec3 dumbshiny = scol * texture2D(lightFunc, vec2(sa, spec.a)).r * atmo_color;
 			
 			// add the two types of shiny together
 			vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -155,17 +165,24 @@ void main()
 		if (envIntensity > 0.0)
 		{ //add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
-			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
-			col = mix(col.rgb, refcol, envintensity);
+            vec3 sun_direction  = (inv_modelview * vec4(sun_dir, 1.0)).xyz;
+            vec3 radiance_sun  = GetSkyLuminance(camPos, env_vec, 0.0f, sun_direction, transmittance);
+            vec3 refcol = ColorFromRadiance(radiance_sun);
+			col = mix(col.rgb, refcol, envIntensity);
 		}
 						
+		/*if (norm.w < 0.5)
+		{
+			col = scaleSoftClipFrag(col);
+		}*/
+
 		#ifdef WATER_FOG
 			vec4 fogged = applyWaterFogView(pos,vec4(col, bloom));
 			col = fogged.rgb;
 			bloom = fogged.a;
 		#endif
 
-		col = srgb_to_linear(col);
+        col = pow(col, vec3(light_gamma));
 	}
 	
 	frag_color.rgb = col;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
index c840d727843..9d872b8df81 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file softenLightF.glsl
+ * @file class3/deferred/softenLightV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,21 +22,17 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
-
-uniform mat4 modelview_projection_matrix;
-
 ATTRIBUTE vec3 position;
 
-uniform vec2 screen_res;
-
 VARYING vec2 vary_fragcoord;
 
+uniform mat4 modelview_projection_matrix;
+uniform vec2 screen_res;
+
 void main()
 {
 	//transform vertex
 	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
 	gl_Position = pos; 
-	
-	
 	vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
 }
diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
index a7da140b31c..80e2a9dd559 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -133,18 +133,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
index aa5e99a2f7b..894534b1051 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
@@ -68,19 +68,8 @@ uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
 vec3 decode_normal (vec2 enc);
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
 float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -124,13 +113,8 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
 void main() 
 {
 	vec2 pos_screen = vary_fragcoord.xy;
-	
-	//try doing an unproject here
-	
 	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
+	vec3 norm = getNorm(pos_screen);
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
index 58f3f2f91ee..0870a80a32d 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
@@ -68,81 +68,11 @@ uniform float shadow_offset;
 uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
-vec3 decode_normal (vec2 enc);
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec2 getKern(int i)
-{
-	vec2 kern[8];
-	// exponentially (^2) distant occlusion samples spread around origin
-	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-       
-	return kern[i];
-}
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
 //calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
-	float ret = 1.0;
-
-	vec2 pos_screen = vary_fragcoord.xy;
-	vec3 pos_world = pos.xyz;
-	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
-		
-	float angle_hidden = 0.0;
-	float points = 0;
-		
-	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
-	
-	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
-	for (int i = 0; i < 8; i++)
-	{
-		vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
-		vec3 samppos_world = getPosition(samppos_screen).xyz; 
-		
-		vec3 diff = pos_world - samppos_world;
-		float dist2 = dot(diff, diff);
-			
-		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
-		// --> solid angle shrinking by the square of distance
-		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
-		//(k should vary inversely with # of samples, but this is taken care of later)
-		
-		float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
-		angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
-			
-		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
-		float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
-		points = points + diffz_val;
-	}
-		
-	angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
-	
-	float points_val = (points > 0.0) ? 1.0 : 0.0;
-	ret = (1.0 - (points_val * angle_hidden));
-
-	ret = max(ret, 0.0);
-	return min(ret, 1.0);
-}
+float calcAmbientOcclusion(vec4 pos, vec3 norm, pos_screen);
 
 float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -184,14 +114,9 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;
-	
-	//try doing an unproject here
-	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
+	vec2 pos_screen = vary_fragcoord.xy;	
+	vec4 pos        = getPosition(pos_screen);
+	vec3 norm       = getNorm(pos_screen);
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
@@ -291,7 +216,7 @@ void main()
 	}
 	
 	frag_color[0] = shadow;
-	frag_color[1] = calcAmbientOcclusion(pos, norm);
+	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
 	
 	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
 	
-- 
GitLab