diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 129c915139458f1a4badc88f04a4045e635b6f0a..60cbbd942fcd57d2af8a3111330f2e5d55d24497 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -98,7 +98,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
-	if (features->calculatesLighting || features->atmosphericHelpers)
+	if (features->calculatesLighting || features->calculatesAtmospherics)
 	{
 		if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
 		{
@@ -194,6 +194,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
+    if (features->calculatesLighting || features->calculatesAtmospherics)
+	{
+		if (!shader->attachObject("windlight/atmosphericsHelpersF.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
 	// NOTE order of shader object attaching is VERY IMPORTANT!!!
 	if (features->hasGamma)
 	{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 970f39ed02a4f19ce04689b895da2659dacf7e6d..2234ceeb5332ffd74077e81a1914d67cdec384f0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -39,19 +39,6 @@ out vec4 frag_color;
 
 uniform float display_gamma;
 uniform vec4 gamma;
-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 distance_multiplier;
-uniform float max_y;
-uniform vec4 glow;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
 uniform mat3 ssao_effect_mat;
 
@@ -84,12 +71,6 @@ VARYING vec3 vary_norm;
 VARYING vec4 vertex_color;
 #endif
 
-vec3 vary_PositionEye;
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
@@ -107,6 +88,12 @@ vec3 linear_to_srgb(vec3 cl);
 vec2 encode_normal (vec3 n);
 vec3 decode_normal (vec2 enc);
 
+vec3 scaleFragSoftClip(vec3 l);
+vec3 atmosFragAmbient(vec3 light, vec3 sunlit);
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten);
+vec3 atmosFragAffectDirectionalLight(float light, vec3 sunlit);
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+
 vec3 calcDirectionalLight(vec3 n, vec3 l)
 {
 	float a = max(dot(n,l),0.0);
@@ -174,191 +161,6 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
 }
 #endif
 
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//was glow.y
-		//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 + (vec4(1.) - ambient) * cloud_shadow * 0.5;
-	
-	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
-	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
-	 * // The following line of code performs the equivalent of:
-	 * float ambAlpha = tmpAmbient.a;
-	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
-	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
-	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
-	 */
-	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
-
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f));
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity);
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-    vec3 zeroes = vec3(0.0f, 0.0f, 0.0f);
-    vec3 ones   = vec3(1.0f, 1.0f, 1.0f);
-
-	light = ones - clamp(light, zeroes, ones);
-	light = ones - pow(light, gamma.xxx);
-
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
 
 void main() 
 {
@@ -475,7 +277,12 @@ void main()
 
 	vec3 norm = vary_norm; 
 
-	calcAtmospherics(pos.xyz, 1.0);
+        vec3 sunlit;
+        vec3 amblit;
+        vec3 additive;
+        vec3 atten;
+
+	calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
 
 	vec2 abnormal	= encode_normal(norm.xyz);
 	 norm.xyz   = decode_normal(abnormal.xy);
@@ -490,7 +297,7 @@ void main()
 
 	vec4 color = vec4(0,0,0,0);
 
-	color.rgb = atmosAmbient(color.rgb);
+	color.rgb = atmosFragAmbient(color.rgb, amblit);
 	color.a   = final_alpha;
 
 	float ambient = abs(da);
@@ -499,13 +306,13 @@ void main()
 	ambient = (1.0-ambient);
 
 	color.rgb *= ambient;
-	color.rgb += atmosAffectDirectionalLight(final_da);
+	color.rgb += atmosFragAffectDirectionalLight(final_da, sunlit);
 	color.rgb *= gamma_diff.rgb;
 
 	//color.rgb = mix(diff.rgb, color.rgb, final_alpha);
 	
-	color.rgb = atmosLighting(color.rgb);
-	color.rgb = scaleSoftClip(color.rgb);
+	color.rgb = atmosFragLighting(color.rgb, additive, atten);
+	color.rgb = scaleFragSoftClip(color.rgb);
 
 	vec4 light = vec4(0,0,0,0);
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index d14805eccf0fef882152c7967c812a8bd59f5a7b..a90e4336220f4f5633a82fbe426a25533809ea2d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -40,6 +40,12 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
 vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
 
+vec3 atmosFragAmbient(vec3 l, vec3 ambient);
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleFragSoftClip(vec3 l);
+vec3 atmosFragAffectDirectionalLight(float intensity, vec3 sunlit);
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
+
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
 
 #ifdef DEFINE_GL_FRAGCOLOR
@@ -88,19 +94,6 @@ uniform vec4 morphFactor;
 uniform vec3 camPosLocal;
 //uniform vec4 camPosWorld;
 uniform vec4 gamma;
-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 distance_multiplier;
-uniform float max_y;
-uniform vec4 glow;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
 uniform mat3 ssao_effect_mat;
 
@@ -109,13 +102,6 @@ VARYING vec2 vary_fragcoord;
 
 VARYING vec3 vary_position;
 
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
@@ -209,198 +195,6 @@ vec4 getPosition_d(vec2 pos_screen, float depth)
 	return pos;
 }
 
-#ifndef WATER_FOG
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-#endif
-
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//was glow.y
-		//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 + (vec4(1.) - ambient) * cloud_shadow * 0.5;
-	
-	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
-	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
-	 * // The following line of code performs the equivalent of:
-	 * float ambAlpha = tmpAmbient.a;
-	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
-	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
-	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
-	 */
-	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
-
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f));
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity);
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-    vec3 zeroes = vec3(0.0f, 0.0f, 0.0f);
-    vec3 ones   = vec3(1.0f, 1.0f, 1.0f);
-
-	light = ones - clamp(light, zeroes, ones);
-	light = ones - pow(light, gamma.xxx);
-
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
 
 #else
 #ifdef DEFINE_GL_FRAGCOLOR
@@ -585,7 +379,12 @@ void main()
     vec3 col = vec3(0.0f,0.0f,0.0f);
 
 	float bloom = 0.0;
-	calcAtmospherics(pos.xyz, 1.0);
+        vec3 sunlit;
+        vec3 amblit;
+        vec3 additive;
+        vec3 atten;
+
+	calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
 	
 	vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
 
@@ -598,7 +397,7 @@ void main()
 		  final_da = min(final_da, 1.0f);
 		  final_da = pow(final_da, 1.0/1.3);
 
-	col.rgb = atmosAmbient(col);
+	col.rgb = atmosFragAmbient(col, amblit);
 	
 	float ambient = min(abs(da), 1.0);
 	ambient *= 0.5;
@@ -607,7 +406,7 @@ void main()
 
 	col.rgb *= ambient;
 
-	col.rgb = col.rgb + atmosAffectDirectionalLight(final_da);
+	col.rgb = col.rgb + atmosFragAffectDirectionalLight(final_da, sunlit);
 
 	col.rgb *= gamma_diff.rgb;
 	
@@ -620,7 +419,7 @@ void main()
 		//
 				
 		float sa = dot(refnormpersp, sun_dir.xyz);
-		vec3 dumbshiny = vary_SunlitColor*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+		vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
 							
 		// add the two types of shiny together
 		vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -654,8 +453,8 @@ void main()
 	//col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
 	//col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col),  diffuse.a);
 
-	col = atmosLighting(col);
-	col = scaleSoftClip(col);
+	col = atmosFragLighting(col, additive, atten);
+	col = scaleFragSoftClip(col);
 
 	//convert to linear space before adding local lights
 	col = srgb_to_linear(col);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 5983d74cbc49e88cf585ac38c4c80a71519f51e5..fbfd43a4da7b4da47b06556dddc8be007ccab667 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -51,33 +51,13 @@ uniform vec4 morphFactor;
 uniform vec3 camPosLocal;
 //uniform vec4 camPosWorld;
 uniform vec4 gamma;
-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 distance_multiplier;
-uniform float max_y;
-uniform vec4 glow;
 uniform float global_gamma;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
 uniform mat3 ssao_effect_mat;
 
 uniform vec3 sun_dir;
 VARYING vec2 vary_fragcoord;
 
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
@@ -89,6 +69,15 @@ vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
 vec3 decode_normal (vec2 enc);
 
+vec3 atmosFragAmbient(vec3 l, vec3 ambient);
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleFragSoftClip(vec3 l);
+vec3 atmosFragAffectDirectionalLight(float intensity, vec3 sunlit);
+vec3 fullbrightFragAtmosTransport(vec3 l, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClipFrag(vec3 l, vec3 atten);
+
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
+
 vec4 getPosition_d(vec2 pos_screen, float depth)
 {
 	vec2 sc = pos_screen.xy*2.0;
@@ -107,196 +96,6 @@ vec4 getPosition(vec2 pos_screen)
 	return getPosition_d(pos_screen, depth);
 }
 
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//was glow.y
-		//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 + (vec4(1.) - ambient) * cloud_shadow * 0.5;
-	
-	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
-	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
-	 * // The following line of code performs the equivalent of:
-	 * float ambAlpha = tmpAmbient.a;
-	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
-	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
-	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
-	 */
-	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
-
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-
-
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / scene_light_strength );
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * scene_light_strength);
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + light / 2.0;
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * lightIntensity;
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
-
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
 
 void main() 
 {
@@ -324,9 +123,13 @@ void main()
 	vec3 col;
 	float bloom = 0.0;
 	{
-		calcAtmospherics(pos.xyz, 1.0);
+                vec3 sunlit;
+                vec3 amblit;
+                vec3 additive;
+                vec3 atten;
+		calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
 	
-		col = atmosAmbient(vec3(0));
+		col = atmosFragAmbient(vec3(0), amblit);
 		float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
 		ambient *= 0.5;
 		ambient *= ambient;
@@ -334,7 +137,7 @@ void main()
 
 		col.rgb *= ambient;
 
-		col += atmosAffectDirectionalLight(final_da);	
+		col += atmosFragAffectDirectionalLight(final_da, sunlit);
 	
 		col *= diffuse.rgb;
 	
@@ -346,7 +149,7 @@ void main()
 			//
 			
 			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = vary_SunlitColor*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+			vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
 			
 			// add the two types of shiny together
 			vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -370,8 +173,8 @@ void main()
 				
 		if (norm.w < 0.5)
 		{
-			col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
-			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
+			col = mix(atmosFragLighting(col, additive, atten), fullbrightFragAtmosTransport(col, atten, additive), diffuse.a);
+			col = mix(scaleFragSoftClip(col), fullbrightScaleSoftClipFrag(col, atten), diffuse.a);
 		}
 
 		#ifdef WATER_FOG
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
index aacc503e1337e5109060f31880277d1cb484d496..584bd568c5f9f662b326b8a1cbd4e6d9dc11942e 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
@@ -31,3 +31,8 @@ vec3 atmosLighting(vec3 light)
 	return light;
 }
 
+
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor) {
+	/* stub function for fallback compatibility on class1 hardware */
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index fc69f6a69c2e5d098876ffa0ffca340b80e81007..c20092bfe0d8ccb1fd9a540766e69470e390336c 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -70,13 +70,6 @@ uniform mat3 ssao_effect_mat;
 uniform vec3 sun_dir;
 VARYING vec2 vary_fragcoord;
 
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
@@ -84,6 +77,12 @@ vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
 vec3 decode_normal (vec2 enc);
 
+vec3 atmosFragAmbient(vec3 l, vec3 ambient);
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleFragSoftClip(vec3 l);
+vec3 atmosFragAffectDirectionalLight(float intensity, vec3 sunlit);
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
+
 vec4 getPosition_d(vec2 pos_screen, float depth)
 {
 	vec2 sc = pos_screen.xy*2.0;
@@ -102,243 +101,11 @@ vec4 getPosition(vec2 pos_screen)
 	return getPosition_d(pos_screen, depth);
 }
 
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//was glow.y
-		//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 + (vec4(1.) - ambient) * cloud_shadow * 0.5;
-	
-	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
-	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
-	 * // The following line of code performs the equivalent of:
-	 * float ambAlpha = tmpAmbient.a;
-	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
-	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
-	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
-	 */
-	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
 
 #ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
+vec4 applyWaterFogDeferred(vec3 pos, vec4 color);
 #endif
 
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-
-
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / scene_light_strength );
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * scene_light_strength);
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + light / 2.0;
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * lightIntensity;
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
-
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
-
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
@@ -372,8 +139,13 @@ void main()
 		
 
 		float ambocc = scol_ambocc.g;
+
+                vec3 sunlit;
+                vec3 amblit;
+                vec3 additive;
+                vec3 atten;
 	
-		calcAtmospherics(pos.xyz, ambocc);
+		calcFragAtmospherics(pos.xyz, ambocc, sunlit, amblit, additive, atten);
 	
 		col = atmosAmbient(vec3(0));
 		float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
@@ -383,7 +155,7 @@ void main()
 
 		col.rgb *= ambient;
 
-		col += atmosAffectDirectionalLight(max(min(da, scol), 0.0));
+		col += atmosFragAffectDirectionalLight(max(min(da, scol), 0.0), sunlit);
 	
 		col *= diffuse.rgb;
 	
@@ -419,8 +191,8 @@ void main()
 						
 		if (norm.w < 0.5)
 		{
-			col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
-			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
+			col = mix(atmosFragLighting(col, additive, atten), fullbrightFragAtmosTransport(col, atten, additive), diffuse.a);
+			col = mix(scaleFragSoftClip(col), fullbrightFragScaleSoftClip(col), diffuse.a);
 		}
 
 		#ifdef WATER_FOG
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index fea3cbf69b5ec638486dbbf8b2a4a668d824af4d..fee1a7f311d2b9b1aeb058ec662717fdac6cd12c 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -22,23 +22,127 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-
-
-//////////////////////////////////////////////////////////
-// The fragment shader for the terrain atmospherics
-//////////////////////////////////////////////////////////
 
 vec3 getAdditiveColor();
 vec3 getAtmosAttenuation();
 
 uniform sampler2D cloudMap;
+uniform vec4 gamma;
 uniform vec4 cloud_pos_density1;
+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 distance_multiplier;
+uniform float max_y;
+uniform vec4 glow;
+uniform float scene_light_strength;
+uniform mat3 ssao_effect_mat;
 
-vec3 atmosLighting(vec3 light)
+vec3 scaleFragSoftClip(vec3 light)
+{
+	//soft clip effect:
+	light = 1. - clamp(light, vec3(0.), vec3(1.));
+	light = 1. - pow(light, gamma.xxx);
+	return light;
+}
+
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
 {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
+	light *= atten.r;
+	light += additive;
 	return (2.0 * light);
 }
 
+vec3 atmosLighting(vec3 light)
+{
+    return atmosFragLighting(light, getAdditiveColor(), getAtmosAttenuation());
+}
+
+void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten) {
+
+	vec3 P = inPositionEye;
+	
+	vec3 tmpLightnorm = lightnorm.xyz;
+
+	vec3 Pn = normalize(P);
+	float Plen = length(P);
+
+	vec4 temp1 = vec4(0);
+	vec3 temp2 = vec3(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);
+		//I had thought blue_density and haze_density should have equal weighting,
+		//but attenuation due to haze_density tends to seem too strong
+
+	temp1 = blue_density + vec4(haze_density);
+	blue_weight = blue_density / temp1;
+	haze_weight = vec4(haze_density) / temp1;
+
+	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
+	temp2.y = max(0.0, tmpLightnorm.y);
+	temp2.y = 1. / temp2.y;
+	sunlight *= exp( - light_atten * temp2.y);
+
+	// main atmospheric scattering line integral
+	temp2.z = Plen * density_multiplier;
+
+	// Transparency (-> temp1)
+	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
+	// compiler gets confused.
+	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
+
+	//final atmosphere attenuation factor
+	atten = temp1.rgb;
+	
+	//compute haze glow
+	//(can use temp2.x as temp because we haven't used it yet)
+	temp2.x = dot(Pn, tmpLightnorm.xyz);
+	temp2.x = 1. - temp2.x;
+		//temp2.x is 0 at the sun and increases away from sun
+	temp2.x = max(temp2.x, .03);	//was glow.y
+		//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 + (vec4(1.) - ambient) * cloud_shadow * 0.5;
+	
+	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas
+	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
+	 * // The following line of code performs the equivalent of:
+	 * float ambAlpha = tmpAmbient.a;
+	 * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
+	 * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
+	 * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+	 */
+	tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
+
+	//haze color
+        additive =
+		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
+     	          + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
+		  + tmpAmbient));
+
+	//brightness of surface both sunlight and ambient
+	sunlit = vec3(sunlight * .5);
+	amblit = vec3(tmpAmbient * .25);
+	additive *= vec3(1.0 - temp1);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3582759e62bf21f42bee9d486cf2f7e25e340b7b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl
@@ -0,0 +1,49 @@
+/**
+ * @file atmosphericsHelpersV.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+// Output variables
+
+uniform float scene_light_strength;
+
+vec3 atmosFragAmbient(vec3 light, vec3 amblit)
+{
+	return amblit + light / 2.0;
+}
+
+vec3 atmosFragAffectDirectionalLight(float lightIntensity, vec3 sunlit)
+{
+	return sunlit * lightIntensity;
+}
+
+vec3 scaleDownLightFrag(vec3 light)
+{
+	return (light / scene_light_strength );
+}
+
+vec3 scaleUpLightFrag(vec3 light)
+{
+	return (light * scene_light_strength);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index 478373d729c631fbfa2198d75c35d48148087ab4..2db633cd01e847a606177cdb861b224e4b6049e9 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -38,7 +38,12 @@ vec3 scaleSoftClip(vec3 light) {
 	return light;
 }
 
+vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 atten)
+{
+	return mix(scaleSoftClip(light.rgb), light.rgb, atten);
+}
+
 vec3 fullbrightScaleSoftClip(vec3 light) {
-	return mix(scaleSoftClip(light.rgb), light.rgb, getAtmosAttenuation());
+	return fullbrightScaleSoftClipFrag(light.rgb, getAtmosAttenuation());
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index 8a8e4cb0f68a582e9586b2cae51d3a295351078d..82e1d7fe3510d230178f282bbc4901d446d107f6 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -33,21 +33,30 @@ vec3 getAtmosAttenuation();
 uniform sampler2D cloudMap;
 uniform vec4 cloud_pos_density1;
 
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
+vec3 atmosFragTransport(vec3 light, vec3 atten, vec3 additive) {
+	light *= atten.r;
+	light += additive * 2.0;
 	return light;
 }
 
-vec3 fullbrightAtmosTransport(vec3 light) {
+vec3 fullbrightFragAtmosTransport(vec3 light, vec3 atten, vec3 additive) {
 	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
+	return mix(atmosFragTransport(light.rgb, atten, additive), light.rgb + additive.rgb, brightness * brightness);
 }
 
-vec3 fullbrightShinyAtmosTransport(vec3 light) {
+vec3 fullbrightFragShinyAtmosTransport(vec3 light, vec3 atten, vec3 additive) {
 	float brightness = dot(light.rgb, vec3(0.33333));
+	return mix(atmosFragTransport(light.rgb, atten, additive), (light.rgb + additive.rgb) * (2.0 - brightness), brightness * brightness);
+}
 
-	return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
+vec3 atmosTransport(vec3 light) {
+     return atmosFragTransport(light, getAtmosAttenuation(), getAdditiveColor());
 }
 
+vec3 fullbrightAtmosTransport(vec3 light) {
+     return fullbrightFragAtmosTransport(light, getAtmosAttenuation(), getAdditiveColor());
+}
+
+vec3 fullbrightShinyAtmosTransport(vec3 light) {
+    return fullbrightFragShinyAtmosTransport(light, getAtmosAttenuation(), getAdditiveColor());
+}
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index abb0f78c986caf78e530881e3319ecaa57876b39..54f48baa974bfaf2da2bed28b9f5cfa517111a3f 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -941,9 +941,10 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 		ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
 	}
 
-	std::vector<S32> index_channels;
+	std::vector<S32> index_channels;    
 	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
 	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
 	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/gammaF.glsl",					mVertexShaderLevel[SHADER_WINDLIGHT]) );
 	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
 	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/transportF.glsl",				mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
@@ -1316,6 +1317,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedAlphaProgram.mFeatures.hasSrgb = true;
         gDeferredSkinnedAlphaProgram.mFeatures.decodesNormal = true;
         gDeferredSkinnedAlphaProgram.mFeatures.encodesNormal = true;
+        gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
+
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1382,6 +1386,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialProgram[i].mFeatures.hasSrgb = true;
             gDeferredMaterialProgram[i].mFeatures.decodesNormal = true;
             gDeferredMaterialProgram[i].mFeatures.encodesNormal = true;
+            gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true;
+            gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true;
 
 			if (has_skin)
 			{
@@ -1415,6 +1421,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialWaterProgram[i].mFeatures.hasSrgb = true;
             gDeferredMaterialWaterProgram[i].mFeatures.decodesNormal = true;
             gDeferredMaterialWaterProgram[i].mFeatures.encodesNormal = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.calculatesAtmospherics = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasAtmospherics = true;
 
 			if (has_skin)
 			{
@@ -1582,6 +1590,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredAlphaProgram.mFeatures.hasSrgb = true;
         gDeferredAlphaProgram.mFeatures.decodesNormal = true;
         gDeferredAlphaProgram.mFeatures.encodesNormal = true;
+        gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
 
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1655,6 +1665,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true;
         gDeferredAlphaWaterProgram.mFeatures.decodesNormal = true;
         gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true;
+        gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true;
 
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1861,6 +1873,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSoftenProgram.mShaderFiles.clear();
 		gDeferredSoftenProgram.mFeatures.hasSrgb = true;
         gDeferredSoftenProgram.mFeatures.decodesNormal = true;
+        gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredSoftenProgram.mFeatures.hasAtmospherics = true;
+        gDeferredSoftenProgram.mFeatures.hasTransport = true;
+        gDeferredSoftenProgram.mFeatures.hasGamma = true;
+
 		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
 
@@ -1887,6 +1904,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSoftenWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredSoftenWaterProgram.mFeatures.hasSrgb = true;
         gDeferredSoftenWaterProgram.mFeatures.decodesNormal = true;
+        gDeferredSoftenWaterProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredSoftenWaterProgram.mFeatures.hasAtmospherics = true;
+        gDeferredSoftenWaterProgram.mFeatures.hasTransport = true;
+        gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
@@ -1988,6 +2009,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasSrgb = true;
         gDeferredAvatarAlphaProgram.mFeatures.encodesNormal = true;
         gDeferredAvatarAlphaProgram.mFeatures.decodesNormal = true;
+        gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
+        gDeferredAvatarAlphaProgram.mFeatures.hasTransport = true;
+        gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
+
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));