diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 55e4ecda2a8212a77c7f522ae38e8329d918d563..d6fe35e2ca56a3392957eb55afdc6b7c60ca10ec 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -186,23 +186,15 @@ 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 (features->calculatesLighting || features->calculatesAtmospherics)
 	{
-		if (!shader->attachObject("deferred/indirect.glsl"))
+		if (!shader->attachObject("windlight/atmosphericsHelpersF.glsl"))
 		{
 			return FALSE;
 		}
 	}
 
+	// NOTE order of shader object attaching is VERY IMPORTANT!!!
 	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 c4caed4d7194fec2e56c467f4970973ca9c266a1..767fad016c956736719590aacb6a6877a8e9fb6d 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl
@@ -38,5 +38,12 @@ 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 94de2f7b5390b1973af3b0e3569ebd1ddd02f3b0..90bf2851c9e0f49534f19e18a07c6ecdefb66c91 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl
@@ -61,5 +61,12 @@ 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/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index a325faaad7d4ad397e0bf0e75cc06872e8c99e9b..3ec2ea12da465efecdfe1ded322729113256df00 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -89,7 +89,9 @@ vec2 encode_normal (vec3 n);
 vec3 decode_normal (vec2 enc);
 
 vec3 scaleSoftClipFrag(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 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
@@ -162,8 +164,6 @@ void main()
 	
 	float shadow = 1.0;
 
-    vec3 norm = vary_norm; 
-
 #if HAS_SHADOW
 	vec4 spos = pos;
 		
@@ -268,10 +268,13 @@ void main()
 	vec4 gamma_diff = diff;	
 	diff.rgb = srgb_to_linear(diff.rgb);
 
-    vec3 sunlit;
-    vec3 amblit;
-    vec3 additive;
-    vec3 atten;
+	vec3 norm = vary_norm; 
+
+        vec3 sunlit;
+        vec3 amblit;
+        vec3 additive;
+        vec3 atten;
+
 	calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
 
 	vec2 abnormal	= encode_normal(norm.xyz);
@@ -287,7 +290,7 @@ void main()
 
 	vec4 color = vec4(0,0,0,0);
 
-	color.rgb = (color.rgb * 0.5) + amblit;
+	color.rgb = atmosFragAmbient(color.rgb, amblit);
 	color.a   = final_alpha;
 
 	float ambient = abs(da);
@@ -296,7 +299,7 @@ void main()
 	ambient = (1.0-ambient);
 
 	color.rgb *= ambient;
-	color.rgb += (final_da * sunlit);
+	color.rgb += atmosFragAffectDirectionalLight(final_da, sunlit);
 	color.rgb *= gamma_diff.rgb;
 
 	//color.rgb = mix(diff.rgb, color.rgb, final_alpha);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 394ae80e53e222a5f29899c57f000bf5f01bc841..506118d381deb83ef7db62fc92acf6586016c751 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -73,7 +73,7 @@ void main()
 	vec3 norm;
 	
 	//transform vertex
-#if defined(HAS_SKIN)
+#ifdef HAS_SKIN
 	mat4 trans = getObjectSkinnedTransform();
 	trans = modelview_matrix * trans;
 	
@@ -83,7 +83,9 @@ void main()
 	norm = normalize((trans * vec4(norm, 1.0)).xyz - pos.xyz);
 	vec4 frag_pos = projection_matrix * pos;
 	gl_Position = frag_pos;
-#elif defined(IS_AVATAR_SKIN)
+#else
+
+#ifdef IS_AVATAR_SKIN
 	mat4 trans = getSkinnedTransform();
 	vec4 pos_in = vec4(position.xyz, 1.0);
 	pos.x = dot(trans[0], pos_in);
@@ -105,11 +107,14 @@ void main()
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 #endif
 	
+#endif
+
 #ifdef USE_INDEXED_TEX
 	passTextureIndex();
 #endif
 
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+	
 	vary_norm = norm;
 	vary_position = pos.xyz;
 
@@ -117,14 +122,18 @@ void main()
 	vertex_color = diffuse_color;
 #endif
 	
-#if defined(HAS_SKIN)
+#ifdef HAS_SKIN
 	vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
-#elif defined(IS_AVATAR_SKIN)
+#else
+
+#ifdef IS_AVATAR_SKIN
 	vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
 #else
 	pos = modelview_projection_matrix * vert;
 	vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
 #endif
 	
+#endif
+
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 7c9382d474aea86fbd2f903d44e5a876e4ff4c4c..b56abb66d1fd65ea01358fd1312187651e8b2813 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -33,6 +33,7 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
+uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 
@@ -44,7 +45,22 @@ uniform float kern_scale;
 
 VARYING vec2 vary_fragcoord;
 
-vec4 getPosition(vec2 pos_screen);
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+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;
+}
+
 vec3 decode_normal (vec2 enc);
 
 void main() 
@@ -103,5 +119,11 @@ void main()
 	col.y *= col.y;
 	
 	frag_color = col;
+
+#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.
+	vec3 dummy1 = kern[0];
+	vec3 dummy2 = kern[3];
+#endif
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index def149d86da0bab8df8ae79a6fa73f49b403aa55..6ba16b169ce8b82f1c44381aa8805535acf64b92 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -32,9 +32,11 @@ out vec4 frag_data[3];
 #endif
 
 uniform float minimum_alpha;
+
+
 uniform sampler2D diffuseMap;
-uniform sampler2D specularMap;
 uniform sampler2D normalMap;
+uniform sampler2D specularMap;
 
 VARYING vec2 vary_texcoord0;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 1e566b77bf798515303551fee9756b2881abff3e..c1c17532b8d98d93134051b5a5309d2871e52043 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -40,6 +40,7 @@ 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 scaleSoftClipFrag(vec3 l);
 
@@ -175,6 +176,19 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
 
 }
 
+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;
+}
+
+
 #else
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
@@ -219,8 +233,6 @@ vec3 decode_normal (vec2 enc);
 
 void main() 
 {
-    vec2 pos_screen = vary_texcoord0.xy;
-
 	vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
 	diffcol.rgb *= vertex_color.rgb;
 
@@ -378,7 +390,7 @@ void main()
 		  final_da = min(final_da, 1.0f);
 		  final_da = pow(final_da, 1.0/1.3);
 
-	col.rgb = (col * 0.5) + amblit;
+	col.rgb = atmosFragAmbient(col, amblit);
 	
 	float ambient = min(abs(da), 1.0);
 	ambient *= 0.5;
@@ -432,6 +444,9 @@ void main()
 		glare += cur_glare;
 	}
 
+	//col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
+	//col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col),  diffuse.a);
+
 	col = atmosFragLighting(col, additive, atten);
 	col = scaleSoftClipFrag(col);
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index eb65c28645ac93b12b2a51086b6bfdeb0453d85a..d1ac19270d20c935b9de24f43f763e0c8b427a6a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -59,7 +59,18 @@ uniform mat4 inv_proj;
 
 vec3 decode_normal (vec2 enc);
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 void main() 
 {
@@ -137,4 +148,12 @@ void main()
 	
 	frag_color.rgb = out_col;
 	frag_color.a = 0.0;
+
+#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 = light[0];
+	vec4 dummy2 = light_col[0];
+	vec4 dummy3 = light[LIGHT_COUNT-1];
+	vec4 dummy4 = light_col[LIGHT_COUNT-1];
+#endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index 3aa7a3a4494d11d366d37f2e8759566bdba9e0e5..1d75322b4cef711f183f056875def7ed959fad13 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -128,7 +128,19 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-vec4 getPosition(vec2 pos_screen);
+
+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;
+}
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index df48a66fabbe53f55a78ebbf280f0e3f06ec93e5..13b803e03e85dd7806c046eda670ad9d28e24596 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -57,7 +57,19 @@ uniform mat4 inv_proj;
 uniform vec4 viewport;
 
 vec3 decode_normal (vec2 enc);
-vec4 getPosition(vec2 pos_screen);
+
+vec4 getPosition(vec2 pos_screen)
+{
+	float depth = texture2DRect(depthMap, pos_screen.xy).r;
+	vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
+	sc /= viewport.zw;
+	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;
+}
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index 3da853144280848748666a7eced8a6c4418bf64e..a5625fbc16e1f567a41ff5f806ab187481a039ee 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 pointLightV.glsl
+ * @file pointLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index c2963046c5224999af15733856ff8faa80196e93..e33254304b33927aa0618eb7c548640d1b29d130 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -49,7 +49,18 @@ VARYING vec2 vary_fragcoord;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec4 getPosition(vec2 pos_screen);
+vec4 getPosition(vec2 pos_screen)
+{
+	float depth = texture2DRect(depthMap, pos_screen.xy).a;
+	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;
+}
 
 void main() 
 {
@@ -90,4 +101,10 @@ void main()
 	col = col*col*blur_quad.x + col*blur_quad.y + blur_quad.z;
 	
 	frag_color.rgb = col;
+
+#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.
+	vec2 dummy1 = kern[0];
+	vec2 dummy2 = kern[31];
+#endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index cac3e75f1f0204db26c43bdec9807e7663c0f10d..5627275df6c9d5186b923b959527c9501eddacf9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -69,17 +69,33 @@ vec3 srgb_to_linear(vec3 cs);
 vec3 linear_to_srgb(vec3 cl);
 vec3 decode_normal (vec2 enc);
 
-vec3 scaleSoftClipFrag(vec3 l);
 vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
 void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten);
 
-vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+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).a;
+	return getPosition_d(pos_screen, depth);
+}
+
 
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
 	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec4 pos = getPositionWithDepth(tc, depth);
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec4 norm = texture2DRect(normalMap, tc);
 	float envIntensity = norm.z;
 	norm.xyz = decode_normal(norm.xy); // unpack norm
@@ -140,25 +156,27 @@ 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);  
+
+			col = mix(col.rgb, refcol, 
+				envIntensity);  
 		}
 				
 		if (norm.w < 0.5)
 		{
 			col = atmosFragLighting(col, additive, atten);
-			col = scaleSoftClipFrag(col);
 		}
 
 		#ifdef WATER_FOG
-			vec4 fogged = applyWaterFogView(pos.xyz,vec4(col, bloom));
+			vec4 fogged = applyWaterFogView(pos,vec4(col, bloom));
 			col = fogged.rgb;
 			bloom = fogged.a;
 		#endif
 
 		col = srgb_to_linear(col);
 
-		//col = vec3(1,0,1);
 		//col.g = envIntensity;
 	}
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
index 5655c6f99f56087d20f8aacb554cf1a2e9c8bb17..b59fcbe0176e32582efff8bff94401a82b74b98e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
@@ -30,7 +30,6 @@ ATTRIBUTE vec3 position;
 uniform vec2 screen_res;
 
 VARYING vec2 vary_fragcoord;
-
 void main()
 {
 	//transform vertex
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 022bcbabca4d88ba414e26b06a569c257db01750..2b6428963dff7278d5f072cade24a628c3b2dbd1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -132,7 +132,18 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl b/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl
index bc3324f543845d86bcfa74e86edac1749cc4a079..00ba0e8fad8f072391fedacc9f4e4fdfa11f905c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl
@@ -48,6 +48,7 @@ vec3 srgb_to_linear(vec3 cs)
 
 	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
 	return mix(high_range, low_range, lte);
+
 }
 
 vec3 linear_to_srgb(vec3 cl)
@@ -58,4 +59,6 @@ vec3 linear_to_srgb(vec3 cl)
 
 	bvec3 lt = lessThan(cl,vec3(0.0031308));
 	return mix(high_range, low_range, lt);
+
 }
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 006a49d9a055593d5e08e99aaba6ba670aaa1cea..403df87853fce2d51ece14902758ea9711d23dbb 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -35,26 +35,102 @@ out vec4 frag_color;
 
 //class 1 -- no shadow, SSAO only
 
+uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
+uniform sampler2D noiseMap;
+
 
 // Inputs
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
 VARYING vec2 vary_fragcoord;
 
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
 vec3 decode_normal (vec2 enc);
-vec3 getNorm(vec2 pos_screen);
-vec4 getPosition(vec2 pos_screen);
+
+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;
+}
 
 //calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
+float calcAmbientOcclusion(vec4 pos, vec3 norm)
+{
+	float ret = 1.0;
+	
+	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;
+
+	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;
+	int 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(kern[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)
+			
+		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+			
+		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+		points = points + int(diff.z > -1.0);
+	}
+		
+	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+		
+	ret = (1.0 - (float(points != 0) * angle_hidden));
+	
+	return min(ret, 1.0);
+}
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;	
-	vec4 pos        = getPosition(pos_screen);
-	vec3 norm       = getNorm(pos_screen);
-
+	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);
+		
 	frag_color[0] = 1.0;
-	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
+	frag_color[1] = calcAmbientOcclusion(pos, norm);
 	frag_color[2] = 1.0; 
 	frag_color[3] = 1.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 69543b93eadf19163ae4b6e43ed56f58b003a7a7..73f6d9fec32fd91d81eb35d39176de7bd27d6e23 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -41,6 +41,15 @@ uniform sampler2D bumpMap2;
 uniform float blend_factor;
 uniform sampler2D screenTex;
 uniform sampler2D refTex;
+uniform sampler2DRectShadow shadowMap0;
+uniform sampler2DRectShadow shadowMap1;
+uniform sampler2DRectShadow shadowMap2;
+uniform sampler2DRectShadow shadowMap3;
+uniform sampler2D noiseMap;
+
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+
 uniform float sunAngle;
 uniform float sunAngle2;
 uniform vec3 lightDir;
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
index 2b8cf9d8df5fd54a83215bd6099ffcb850b6c004..c1cc3679a79f62c0b9bf6cecbc679610e6708439 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
@@ -23,10 +23,21 @@
  * $/LicenseInfo$
  */
  
+vec3 atmosFragAmbient(vec3 light, vec3 sunlit)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
+}
+
 vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-   return light;
+    /* stub function for fallback compatibility on class1 hardware */
+	return light;
+}
+
+vec3 atmosFragAffectDirectionalLight(float light, vec3 sunlit)
+{
+   return light * sunlit;
 }
 
 vec3 atmosLighting(vec3 light)
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 0848adba730fee3ba116a815d537a80ac92c0a15..864ba4859da93420f5a1ff4e6a4cf1ff56eaa094 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -133,7 +133,18 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 33f3eb46c082161d78649b014fd7fc587beb0c44..c92dbda18513c952ce293977279295a165f1846b 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -83,12 +83,51 @@ vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
 vec3 fullbrightScaleSoftClipFrag(vec3 l);
 vec3 scaleSoftClipFrag(vec3 l);
 
-vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightShinyAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+	return (light + additive) * atten.r * 2.0;
+}
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten) {
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+	float brightness = dot(light.rgb, vec3(0.33333));
+	return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive.rgb, brightness * brightness);
+}
+
+vec3 fullbrightShinyAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten) {
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+	float brightness = dot(light.rgb, vec3(0.33333));
+	return mix(atmosTransportFrag(light.rgb, additive, atten), (light.rgb + additive.rgb) * (2.0 - brightness), brightness * brightness);
+}
+
+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);
+}
 
-vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-vec4 getPosition(vec2 pos_screen);
 
 #ifdef WATER_FOG
 vec4 applyWaterFogView(vec3 pos, vec4 color);
@@ -98,7 +137,7 @@ void main()
 {
 	vec2 tc = vary_fragcoord.xy;
 	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec4 pos = getPositionWithDepth(tc, depth);
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec4 norm = texture2DRect(normalMap, tc);
 	float envIntensity = norm.z;
 	norm.xyz = decode_normal(norm.xy); // unpack norm
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
index 8b8b338f6851ffbf916ec28a3399b67b3c6e4b5f..c840d727843a95a9f2049dcf827eccb93d6519f3 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -36,5 +36,7 @@ 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/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 80e2a9dd5593ed616f1fd83138e3975ac734adf2..a7da140b31c25a6188c4f3ac18217d609c45c70f 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -133,7 +133,18 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index c4018ca61ad96faaee0f4b9156f18356eaddaa01..aa5e99a2f7b08199319223c35d1ee28f2166726e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -67,9 +67,20 @@ uniform float shadow_offset;
 uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
-vec3 getNorm(vec2 pos_screen);
 vec3 decode_normal (vec2 enc);
-vec4 getPosition(vec2 pos_screen);
+
+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;
+}
 
 float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -112,9 +123,14 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;	
-	vec4 pos        = getPosition(pos_screen);
-	vec3 norm       = getNorm(pos_screen);
+	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
 		
 	/*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/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index bd468306ee996833b1467fa1eae115ace73752ed..58f3f2f91ee6cce5ef22914ae73cb0e1ba2b788e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -70,10 +70,79 @@ uniform float spot_shadow_offset;
 
 vec3 decode_normal (vec2 enc);
 
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+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];
+}
+
+//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));
 
-float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
+	ret = max(ret, 0.0);
+	return min(ret, 1.0);
+}
 
 float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -116,8 +185,13 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
 void main() 
 {
 	vec2 pos_screen = vary_fragcoord.xy;
-	vec4 pos  = getPosition(pos_screen);
-	vec3 norm = getNorm(pos_screen);
+	
+	//try doing an unproject here
+	
+	vec4 pos = getPosition(pos_screen);
+	
+	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+	norm = decode_normal(norm.xy); // unpack norm
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
@@ -217,7 +291,7 @@ void main()
 	}
 	
 	frag_color[0] = shadow;
-	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
+	frag_color[1] = calcAmbientOcclusion(pos, norm);
 	
 	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
index f8373215f098f2a51e36e9f072e386a7b39e09fd..9f06319da31bfc8b83a3ac7b8b61240e0a2777d8 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 class3/deferred/cloudsF.glsl
+ * @file WLCloudsF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,9 +24,9 @@
  */
  
 #ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
+out vec4 frag_color;
 #else
-#define frag_data gl_FragData
+#define frag_color gl_FragColor
 #endif
 
 /////////////////////////////////////////////////////////////////////////
@@ -36,37 +36,20 @@ out vec4 frag_data[3];
 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 sunlight_color;
-uniform vec4 cloud_color;
-uniform float cloud_shadow;
+uniform vec4 gamma;
 uniform float cloud_scale;
 uniform float cloud_variance;
-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);
+
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
 
 /// Soft clips the light with a gamma correction
 vec3 scaleSoftClip(vec3 light);
@@ -84,9 +67,11 @@ void main()
 	// Set variables
 	vec2 uv1 = vary_texcoord0.xy;
 	vec2 uv2 = vary_texcoord1.xy;
-	vec2 uv3 = vary_texcoord2.xy;
-	float cloudDensity = 2.0 * (cloud_shadow - 0.25);
 
+	vec4 cloudColorSun = vary_CloudColorSun;
+	vec4 cloudColorAmbient = vary_CloudColorAmbient;
+	float cloudDensity = vary_CloudDensity;
+	vec2 uv3 = vary_texcoord2.xy;
 	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);
@@ -97,53 +82,33 @@ 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));
-
-    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 * cloud_pos_density1.z, 1.);
+	alpha1 = min(max(alpha1 + cloudDensity, 0.) * (10. + disturbance.y) * 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 * cloud_pos_density1.z, 1.);
+	alpha2 = min(max(alpha2 + cloudDensity, 0.) * (2.5 + disturbance.x) * 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.;
 
-    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);
+	/// Gamma correct for WL (soft clip effect).
+	frag_color.rgb = scaleSoftClip(color.rgb);
+	frag_color.a = alpha1;
 }
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
index 53b6d88ef5e9045d49c48e56c24f6fc36c4fb91a..c1dd45cd6729e9fbb3b9c7b6e849222cecf9a215 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
@@ -24,7 +24,6 @@
  */
 
 uniform mat4 modelview_projection_matrix;
-uniform mat4 modelview_matrix;
 
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec2 texcoord0;
@@ -34,37 +33,158 @@ 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 0848adba730fee3ba116a815d537a80ac92c0a15..864ba4859da93420f5a1ff4e6a4cf1ff56eaa094 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
@@ -133,7 +133,18 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 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 d0514f7d2349ff97d2d0d058ea9e6b287ad873a7..2073fc066f6ffbe217a273c31ceb9ecbe7dee90f 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/deferred/skyF.glsl
+ * @file class3/skyF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -44,7 +44,6 @@ 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;
@@ -54,7 +53,6 @@ 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;
@@ -95,15 +93,18 @@ void main()
     }
     s = smoothstep(0.9, 1.0, s) * 16.0f;
 
-    vec3 color = ColorFromRadiance(radiance_sun);
+    vec3 color = vec3(1.0) - exp(-radiance_sun * 0.0001);
 
     float optic_d = dot(view_direction, sun_direction);
+
     vec3 halo_22 = halo22(optic_d);
 
-    color.rgb += rainbow(optic_d) * optic_d;
+    if (optic_d <= 0)
+    color.rgb += rainbow(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 2eb222ada4aab9b8b68138b1dc876f2d02cf279a..a5cc49ca300a0e3eb2588ae7562b04dba3cc6e20 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 class3/deferred/skyV.glsl
+ * @file advancedAtmoV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,6 +23,12 @@
  * $/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 ecf6858136e8d16542d5d95033ae4bef3a76e546..2615400e52b8ebd8f94a08597c570d201574d303 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -38,21 +38,30 @@ uniform sampler2DRect specularRect;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 uniform sampler2DRect depthMap;
-uniform sampler2D     lightFunc;
-
-uniform float blur_size;
 uniform samplerCube environmentMap;
+uniform sampler2D	  lightFunc;
 
+uniform float blur_size;
 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;
@@ -65,29 +74,28 @@ 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);
 
-vec3 ColorFromRadiance(vec3 radiance);
-vec4 getPositionWithDepth(vec2 pos_screen, float depth);
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+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);
+}
+
 
 #ifdef WATER_FOG
 vec4 applyWaterFogView(vec3 pos, vec4 color);
@@ -97,22 +105,24 @@ void main()
 {
 	vec2 tc = vary_fragcoord.xy;
 	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec3 pos = getPositionWithDepth(tc, depth).xyz;
+	vec3 pos = getPosition_d(tc, depth).xyz;
 	vec4 norm = texture2DRect(normalMap, tc);
 	float envIntensity = norm.z;
-    norm.xyz = decode_normal(norm.xy);
-
+	norm.xyz = decode_normal(norm.xy); // unpack norm
+		
 	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); // linear
+	vec4 diffuse = texture2DRect(diffuseRect, tc);
 
+	//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;
@@ -122,37 +132,17 @@ void main()
 
 		float ambocc = scol_ambocc.g;
 
-        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;
-
+		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 = scol * texture2D(lightFunc, vec2(sa, spec.a)).r * atmo_color;
+			vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
 			
 			// add the two types of shiny together
 			vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -165,24 +155,17 @@ void main()
 		if (envIntensity > 0.0)
 		{ //add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
-            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);
+			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
+			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 = pow(col, vec3(light_gamma));
+		col = srgb_to_linear(col);
 	}
 	
 	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 9d872b8df81951912ebbd5091af838f18d9b6cf6..c840d727843a95a9f2049dcf827eccb93d6519f3 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 class3/deferred/softenLightV.glsl
+ * @file softenLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,17 +22,21 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
-ATTRIBUTE vec3 position;
-
-VARYING vec2 vary_fragcoord;
 
 uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
 uniform vec2 screen_res;
 
+VARYING vec2 vary_fragcoord;
+
 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 80e2a9dd5593ed616f1fd83138e3975ac734adf2..a7da140b31c25a6188c4f3ac18217d609c45c70f 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -133,7 +133,18 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 }
 
 
-vec4 getPosition(vec2 pos_screen);
+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;
+}
 
 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 894534b10518753ee676e9a719b7c8c577997306..aa5e99a2f7b08199319223c35d1ee28f2166726e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
@@ -68,8 +68,19 @@ uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
 vec3 decode_normal (vec2 enc);
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+
+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;
+}
 
 float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -113,8 +124,13 @@ 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 = getNorm(pos_screen);
+	
+	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
+	norm = decode_normal(norm.xy); // unpack norm
 		
 	/*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 0870a80a32d4d9dd9ae170901c8fbd46a915ec45..58f3f2f91ee6cce5ef22914ae73cb0e1ba2b788e 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
@@ -68,11 +68,81 @@ uniform float shadow_offset;
 uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
-vec4 getPosition(vec2 pos_screen);
-vec3 getNorm(vec2 pos_screen);
+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];
+}
 
 //calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm, pos_screen);
+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 pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
@@ -114,9 +184,14 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_scr
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;	
-	vec4 pos        = getPosition(pos_screen);
-	vec3 norm       = getNorm(pos_screen);
+	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
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
@@ -216,7 +291,7 @@ void main()
 	}
 	
 	frag_color[0] = shadow;
-	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
+	frag_color[1] = calcAmbientOcclusion(pos, norm);
 	
 	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
 	
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 6498ed652a440c151f634054b9b641625c5af166..a3886b916a440739cf5d62ba3426188a232ea8b2 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -483,8 +483,6 @@ void LLViewerShaderMgr::setShaders()
         S32 shadow_detail            = gSavedSettings.getS32("RenderShadowDetail");
         bool useRenderDeferred       = canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");
         bool doingWindLight          = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders");
-        bool useAdvancedAtmospherics = doingWindLight && gSavedSettings.getBOOL("RenderUseAdvancedAtmospherics");
-        (void)useAdvancedAtmospherics;
 
 		//using shaders, disable fixed function
 		LLGLSLShader::sNoFixedFunction = true;
@@ -1046,10 +1044,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
 		gTerrainProgram.mName = "Terrain Shader";
 		gTerrainProgram.mFeatures.calculatesLighting = true;
 		gTerrainProgram.mFeatures.calculatesAtmospherics = true;
-        gTerrainProgram.mFeatures.hasAtmospherics = true;
-        gTerrainProgram.mFeatures.hasTransport = true;
-        gTerrainProgram.mFeatures.hasGamma = true;
-        gTerrainProgram.mFeatures.hasSrgb = true;
+		gTerrainProgram.mFeatures.hasAtmospherics = true;
 		gTerrainProgram.mFeatures.mIndexedTextureChannels = 0;
 		gTerrainProgram.mFeatures.disableTextureIndex = true;
 		gTerrainProgram.mFeatures.hasGamma = true;
@@ -1208,8 +1203,6 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 
 BOOL LLViewerShaderMgr::loadShadersDeferred()
 {
-    bool use_sun_shadow = mVertexShaderLevel[SHADER_DEFERRED] > 1;
-
 	if (mVertexShaderLevel[SHADER_DEFERRED] == 0)
 	{
 		gDeferredTreeProgram.unload();
@@ -1381,8 +1374,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
         gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true;
         gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
-        gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true;
-        gDeferredSkinnedAlphaProgram.mFeatures.hasIndirect = true;
 
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1391,7 +1382,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
 		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1");
 		gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
+		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
 		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
 		llassert(success);
 
@@ -1445,19 +1436,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0");
 			gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0");
 			gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
-			gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", use_sun_shadow ? "1" : "0");
+			gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
 			bool has_skin = i & 0x10;
 			gDeferredMaterialProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0");
 
 			gDeferredMaterialProgram[i].mFeatures.hasSrgb = true;
+            gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
             gDeferredMaterialProgram[i].mFeatures.hasTransport = true;
             gDeferredMaterialProgram[i].mFeatures.decodesNormal = true;
             gDeferredMaterialProgram[i].mFeatures.encodesNormal = true;
             gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true;
             gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true;
-            gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
-            gDeferredMaterialProgram[i].mFeatures.hasShadows = true;
-            gDeferredMaterialProgram[i].mFeatures.hasIndirect = true;
 
 			if (has_skin)
 			{
@@ -1490,14 +1479,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 			gDeferredMaterialWaterProgram[i].mFeatures.hasWaterFog = true;
 			gDeferredMaterialWaterProgram[i].mFeatures.hasSrgb = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasGamma = true;
             gDeferredMaterialWaterProgram[i].mFeatures.hasTransport = true;
             gDeferredMaterialWaterProgram[i].mFeatures.decodesNormal = true;
             gDeferredMaterialWaterProgram[i].mFeatures.encodesNormal = true;
             gDeferredMaterialWaterProgram[i].mFeatures.calculatesAtmospherics = true;
             gDeferredMaterialWaterProgram[i].mFeatures.hasAtmospherics = true;
-            gDeferredMaterialWaterProgram[i].mFeatures.hasGamma = true;
-            gDeferredMaterialWaterProgram[i].mFeatures.hasShadows = true;
-            gDeferredMaterialWaterProgram[i].mFeatures.hasIndirect = true;
 
 			if (has_skin)
 			{
@@ -1569,9 +1556,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{		
 		gDeferredLightProgram.mName = "Deferred Light Shader";
         gDeferredLightProgram.mFeatures.decodesNormal = true;
-        gDeferredLightProgram.mFeatures.isDeferred = true;
-        gDeferredLightProgram.mFeatures.hasShadows = true;
-
 		gDeferredLightProgram.mShaderFiles.clear();
 		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1587,9 +1571,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 			gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i);
             gDeferredMultiLightProgram[i].mFeatures.decodesNormal = true;
-            gDeferredMultiLightProgram[i].mFeatures.isDeferred = true;
-            gDeferredMultiLightProgram[i].mFeatures.hasShadows = true;
-
 			gDeferredMultiLightProgram[i].mShaderFiles.clear();
 			gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
 			gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1606,9 +1587,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSpotLightProgram.mShaderFiles.clear();
 		gDeferredSpotLightProgram.mFeatures.hasSrgb = true;
         gDeferredSpotLightProgram.mFeatures.decodesNormal = true;
-        gDeferredSpotLightProgram.mFeatures.isDeferred = true;
-        gDeferredSpotLightProgram.mFeatures.hasShadows = true;
-
 		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
@@ -1622,9 +1600,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
 		gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true;
         gDeferredMultiSpotLightProgram.mFeatures.decodesNormal = true;
-        gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true;
-        gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true;
-
 		gDeferredMultiSpotLightProgram.mShaderFiles.clear();
 		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1654,10 +1629,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 
 		gDeferredSunProgram.mName = "Deferred Sun Shader";
         gDeferredSunProgram.mFeatures.decodesNormal = true;
-        gDeferredSunProgram.mFeatures.isDeferred    = true;
-        gDeferredSunProgram.mFeatures.hasShadows    = true;
-        gDeferredSunProgram.mFeatures.hasIndirect   = true;
-
 		gDeferredSunProgram.mShaderFiles.clear();
 		gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB));
 		gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
@@ -1671,8 +1642,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
         gDeferredBlurLightProgram.mFeatures.decodesNormal = true;
-        gDeferredBlurLightProgram.mFeatures.isDeferred = true;
-
 		gDeferredBlurLightProgram.mShaderFiles.clear();
 		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1691,15 +1660,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
         gDeferredAlphaProgram.mFeatures.hasSrgb = true;
+        gDeferredAlphaProgram.mFeatures.hasGamma = true;
         gDeferredAlphaProgram.mFeatures.decodesNormal = true;
         gDeferredAlphaProgram.mFeatures.encodesNormal = true;
         gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
-        gDeferredAlphaProgram.mFeatures.hasGamma = true;
-        gDeferredAlphaProgram.mFeatures.hasTransport = true;
-        gDeferredAlphaProgram.mFeatures.isDeferred = true;
-        gDeferredAlphaProgram.mFeatures.hasShadows = true;
-        gDeferredAlphaProgram.mFeatures.hasIndirect = true;
 
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1714,7 +1679,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1");
-		gDeferredAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
+		gDeferredAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
 		gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
 		gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 
@@ -1736,10 +1701,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true;
         gDeferredAlphaImpostorProgram.mFeatures.decodesNormal = true;
         gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true;
-        gDeferredAlphaImpostorProgram.mFeatures.isDeferred = true;
-        gDeferredAlphaImpostorProgram.mFeatures.hasShadows = true;
-        gDeferredAlphaImpostorProgram.mFeatures.hasIndirect = true;
-
 		gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1754,7 +1715,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1");
-		gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
+		gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
 		gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1");
 		gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1");
 
@@ -1777,14 +1738,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
 		gDeferredAlphaWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true;
+        gDeferredAlphaWaterProgram.mFeatures.hasGamma = true;
         gDeferredAlphaWaterProgram.mFeatures.decodesNormal = true;
         gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true;
         gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true;
-        gDeferredAlphaWaterProgram.mFeatures.hasGamma = true;
-        gDeferredAlphaWaterProgram.mFeatures.isDeferred = true;
-        gDeferredAlphaWaterProgram.mFeatures.hasShadows = true;
-        gDeferredAlphaWaterProgram.mFeatures.hasIndirect = true;
 
 		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
 		{
@@ -1801,7 +1759,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1");
 		gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1");
 		gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
+		gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
 		gDeferredAlphaWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAlphaWaterProgram.createShader(NULL, NULL);
@@ -1821,9 +1779,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true;
         gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true;
         gDeferredAvatarEyesProgram.mFeatures.encodesNormal = true;
-        gDeferredAvatarEyesProgram.mFeatures.isDeferred = true;
-        gDeferredAvatarEyesProgram.mFeatures.hasShadows = true;
-
+        gDeferredAvatarEyesProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarEyesProgram.mShaderFiles.clear();
 		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1839,8 +1795,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightProgram.mFeatures.isDeferred = true;
-
+        gDeferredFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightProgram.mShaderFiles.clear();
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1857,8 +1812,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightAlphaMaskProgram.mFeatures.isDeferred = true;
-
+        gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1877,7 +1831,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightWaterProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightWaterProgram.mFeatures.isDeferred = true;
+        gDeferredFullbrightWaterProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1897,7 +1851,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.isDeferred = true;
+        gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1916,7 +1870,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightShinyProgram.mFeatures.hasTransport = true;
-        gDeferredFullbrightShinyProgram.mFeatures.isDeferred = true;
 		gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels-1;
 		gDeferredFullbrightShinyProgram.mShaderFiles.clear();
 		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1935,7 +1888,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.hasSrgb = true;
-        gDeferredSkinnedFullbrightProgram.mFeatures.isDeferred = true;
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.clear();
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1952,7 +1904,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true;
-        gDeferredSkinnedFullbrightShinyProgram.mFeatures.isDeferred = true;
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear();
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -1967,7 +1918,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredEmissiveProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredEmissiveProgram.mFeatures.hasGamma = true;
 		gDeferredEmissiveProgram.mFeatures.hasTransport = true;
-        gDeferredEmissiveProgram.mFeatures.isDeferred = true;
 		gDeferredEmissiveProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredEmissiveProgram.mShaderFiles.clear();
 		gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
@@ -1985,10 +1935,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWaterProgram.mFeatures.hasGamma = true;
 		gDeferredWaterProgram.mFeatures.hasTransport = true;
         gDeferredWaterProgram.mFeatures.encodesNormal = true;
-        gDeferredWaterProgram.mFeatures.isDeferred = true;
-        gDeferredWaterProgram.mFeatures.hasShadows = true;
-        gDeferredWaterProgram.mFeatures.hasIndirect = true;
-
 		gDeferredWaterProgram.mShaderFiles.clear();
 		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2008,10 +1954,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredUnderWaterProgram.mFeatures.hasTransport = true;
 		gDeferredUnderWaterProgram.mFeatures.hasSrgb = true;
         gDeferredUnderWaterProgram.mFeatures.encodesNormal = true;
-        gDeferredUnderWaterProgram.mFeatures.isDeferred = true;
-        gDeferredUnderWaterProgram.mFeatures.hasShadows = true;
-        gDeferredUnderWaterProgram.mFeatures.hasIndirect = true;
-
 		gDeferredUnderWaterProgram.mShaderFiles.clear();
 		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2028,29 +1970,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSoftenProgram.mFeatures.decodesNormal = true;
         gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredSoftenProgram.mFeatures.hasAtmospherics = true;
-        gDeferredSoftenProgram.mFeatures.hasTransport = true;
         gDeferredSoftenProgram.mFeatures.hasGamma = true;
-        gDeferredSoftenProgram.mFeatures.isDeferred = true;
-        gDeferredSoftenProgram.mFeatures.hasShadows = true;
-        gDeferredSoftenProgram.mFeatures.hasIndirect = 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));
 
 		gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 
-        if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
+		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
 			gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2);
 		}
-
-        // insure we use class3/deferred version of softenLight for advanced atmo..
-        gDeferredSoftenProgram.mShaderLevel = gSavedSettings.getBOOL("RenderUseAdvancedAtmospherics") ? 3 : gDeferredSoftenProgram.mShaderLevel;
-        
-        if (gAtmosphere && gDeferredSoftenProgram.mShaderLevel > 2)
-        {
-            gDeferredSoftenProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink();
-        }
 				
 		success = gDeferredSoftenProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2071,21 +2001,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSoftenWaterProgram.mFeatures.decodesNormal = true;
         gDeferredSoftenWaterProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredSoftenWaterProgram.mFeatures.hasAtmospherics = true;
-        gDeferredSoftenWaterProgram.mFeatures.hasTransport = true;
         gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
-        gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;
-        gDeferredSoftenWaterProgram.mFeatures.hasShadows = true;
-        gDeferredSoftenWaterProgram.mFeatures.hasIndirect = true;
-
-        if (gAtmosphere && gDeferredSoftenWaterProgram.mShaderLevel > 2)
-        {
-            gDeferredSoftenWaterProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink();
-        }
-
-        if (gAtmosphere && gDeferredSoftenWaterProgram.mShaderLevel > 2)
-        {
-            gDeferredSoftenWaterProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink();
-        }
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
@@ -2099,7 +2015,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredShadowProgram.mName = "Deferred Shadow Shader";
-        gDeferredShadowProgram.mFeatures.isDeferred = true;
 		gDeferredShadowProgram.mShaderFiles.clear();
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2112,7 +2027,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader";
-        gDeferredShadowCubeProgram.mFeatures.isDeferred = true;
 		gDeferredShadowCubeProgram.mShaderFiles.clear();
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2126,7 +2040,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";
 		gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-        gDeferredShadowAlphaMaskProgram.mFeatures.isDeferred = true;
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2140,7 +2053,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader";
 		gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true;
-        gDeferredAvatarShadowProgram.mFeatures.isDeferred = true;
 		gDeferredAvatarShadowProgram.mShaderFiles.clear();
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2154,7 +2066,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader";
 		gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true;
-        gDeferredAttachmentShadowProgram.mFeatures.isDeferred = true;
 		gDeferredAttachmentShadowProgram.mShaderFiles.clear();
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2168,7 +2079,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gTerrainProgram.mName = "Deferred Terrain Shader";
         gDeferredTerrainProgram.mFeatures.encodesNormal = true;
-        gDeferredTerrainProgram.mFeatures.isDeferred = true;
 		gDeferredTerrainProgram.mShaderFiles.clear();
 		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2182,7 +2092,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarProgram.mName = "Avatar Shader";
 		gDeferredAvatarProgram.mFeatures.hasSkinning = true;
         gDeferredAvatarProgram.mFeatures.encodesNormal = true;
-        gDeferredAvatarProgram.mFeatures.isDeferred = true;
 		gDeferredAvatarProgram.mShaderFiles.clear();
 		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2206,9 +2115,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
         gDeferredAvatarAlphaProgram.mFeatures.hasTransport = true;
         gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
-        gDeferredAvatarAlphaProgram.mFeatures.isDeferred = true;
-        gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true;
-        gDeferredAvatarAlphaProgram.mFeatures.hasIndirect = true;
 
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
@@ -2229,7 +2135,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process";
 		gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true;
-        gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true;
 		gDeferredPostGammaCorrectProgram.mShaderFiles.clear();
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2241,7 +2146,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gFXAAProgram.mName = "FXAA Shader";
-        gFXAAProgram.mFeatures.isDeferred = true;
 		gFXAAProgram.mShaderFiles.clear();
 		gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
 		gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2253,7 +2157,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredPostProgram.mName = "Deferred Post Shader";
-        gFXAAProgram.mFeatures.isDeferred = true;
 		gDeferredPostProgram.mShaderFiles.clear();
 		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2276,7 +2179,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader";
-        gDeferredDoFCombineProgram.mFeatures.isDeferred = true;
 		gDeferredDoFCombineProgram.mShaderFiles.clear();
 		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2288,7 +2190,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
-        gDeferredPostNoDoFProgram.mFeatures.isDeferred = true;
 		gDeferredPostNoDoFProgram.mShaderFiles.clear();
 		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2305,9 +2206,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredWLSkyProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredWLSkyProgram.mFeatures.hasTransport = true;
         gDeferredWLSkyProgram.mFeatures.hasGamma = true;
-        gDeferredWLSkyProgram.mFeatures.hasSrgb = true;
-        gDeferredWLSkyProgram.mFeatures.isDeferred = true;
-
 		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
         gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
@@ -2323,9 +2221,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredWLCloudProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredWLCloudProgram.mFeatures.hasTransport = true;
         gDeferredWLCloudProgram.mFeatures.hasGamma = true;
-        gDeferredWLCloudProgram.mFeatures.hasSrgb = true;
-        gDeferredWLCloudProgram.mFeatures.isDeferred = true;
-
 		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
@@ -2343,7 +2238,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWLSunProgram.mFeatures.hasAtmospherics = true;
         gDeferredWLSunProgram.mFeatures.isFullbright = true;
 		gDeferredWLSunProgram.mFeatures.disableTextureIndex = true;
-        gDeferredWLSunProgram.mFeatures.isDeferred = true;
 		gDeferredWLSunProgram.mShaderFiles.clear();
 		gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2362,8 +2256,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWLMoonProgram.mFeatures.hasAtmospherics = true;
         gDeferredWLMoonProgram.mFeatures.isFullbright = true;
 		gDeferredWLMoonProgram.mFeatures.disableTextureIndex = true;
-        gDeferredWLMoonProgram.mFeatures.isDeferred = true;
-
 		gDeferredWLMoonProgram.mShaderFiles.clear();
 		gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2376,7 +2268,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredStarProgram.mName = "Deferred Star Program";
-        gDeferredStarProgram.mFeatures.isDeferred = true;
 		gDeferredStarProgram.mShaderFiles.clear();
 		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -2389,7 +2280,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gNormalMapGenProgram.mName = "Normal Map Generation Program";
-        gNormalMapGenProgram.mFeatures.isDeferred = true;
 		gNormalMapGenProgram.mShaderFiles.clear();
 		gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB));
 		gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB));
@@ -3714,11 +3604,14 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 		return TRUE;
 	}
 
-    if (gSavedSettings.getBOOL("RenderUseAdvancedAtmospherics") && mVertexShaderLevel[SHADER_WINDLIGHT] > 2)
+#if USE_ADVANCED_ATMOSPHERICS
+// disabled until we can determine why low-end machines crash during this init...
+    if (mVertexShaderLevel[SHADER_WINDLIGHT] > 1)
     {
         // Prepare precomputed atmospherics textures using libatmosphere
         LLAtmosphere::initClass();
     }
+#endif
 
 	if (success)
 	{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bac6267bbde24ab0159bf93086f1a607773c7ec4..e605f5b420df03bdc59d1059392c6c5830e4388f 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -951,7 +951,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		{
 			for (U32 i = 0; i < 4; i++)
 			{
-                releaseShadowTarget(i);
+				mShadow[i].release();
+				mShadowOcclusion[i].release();
 			}
 		}
 
@@ -989,7 +990,8 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		{
 			for (U32 i = 4; i < 6; i++)
 			{
-                releaseShadowTarget(i);
+				mShadow[i].release();
+				mShadowOcclusion[i].release();
 			}
 		}
 
@@ -1003,7 +1005,11 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 	{
 		mDeferredLight.release();
 				
-		releaseShadowTargets();
+		for (U32 i = 0; i < 6; i++)
+		{
+			mShadow[i].release();
+			mShadowOcclusion[i].release();
+		}
 		mFXAABuffer.release();
 		mScreen.release();
 		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
@@ -1200,7 +1206,11 @@ void LLPipeline::releaseScreenBuffers()
 	mDeferredLight.release();
 	mOcclusionDepth.release();
 		
-	releaseShadowTargets();
+	for (U32 i = 0; i < 6; i++)
+	{
+		mShadow[i].release();
+		mShadowOcclusion[i].release();
+	}
 
 	mInscatter.release();
 }
@@ -8316,24 +8326,20 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 
 	for (U32 i = 0; i < 4; i++)
 	{
-        LLRenderTarget* shadow_target = getShadowTarget(i);
-        if (shadow_target)
-        {
-		    channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
-		    stop_glerror();
-		    if (channel > -1)
-		    {
-			    stop_glerror();
-			    gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
-			    gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			    gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			    stop_glerror();
+		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
+		stop_glerror();
+		if (channel > -1)
+		{
+			stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
 			
-			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			    stop_glerror();
-		    }
-        }
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
+		}
 	}
 
 	for (U32 i = 4; i < 6; i++)
@@ -8343,36 +8349,17 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 		if (channel > -1)
 		{
 			stop_glerror();
-            LLRenderTarget* shadow_target = getShadowTarget(i);
-            if (shadow_target)
-            {
-			    gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
-			    gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-			    gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-			    stop_glerror();
+			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
+			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+			stop_glerror();
 			
-			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
-			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
-			    stop_glerror();
-            }
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);
+			stop_glerror();
 		}
 	}
 
-    /*channel = shader.enableTexture(LLShaderMgr::INSCATTER_RT, LLTexUnit::TT_TEXTURE);
-    stop_glerror();
-    if (channel > -1)
-    {
-        stop_glerror();
-        gGL.getTexUnit(channel)->bind(&mInscatter, TRUE);
-        gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-        gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
-        stop_glerror();
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_ALWAYS);
-        stop_glerror();
-    }*/
-
 	stop_glerror();
 
 	F32 mat[16*6];
@@ -10862,13 +10849,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 		for (S32 j = 0; j < 4; j++)
 		{
-            LLRenderTarget* shadow_target = getShadowTarget(j);
-            if (shadow_target)
-            {
-			    shadow_target->bindTarget();
-			    shadow_target->clear();
-			    shadow_target->flush();
-            }
+			mShadow[j].bindTarget();
+			mShadow[j].clear();
+			mShadow[j].flush();
 		}
 	}
 	else
@@ -10934,16 +10917,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 					mShadowCamera[j+4] = shadow_cam;
 				}
 
-                LLRenderTarget* shadow_target = getShadowTarget(j);
-                if (shadow_target)
-                {
-				    shadow_target->bindTarget();
-				    {
-					    LLGLDepthTest depth(GL_TRUE);
-					    shadow_target->clear();
-				    }
-				    shadow_target->flush();
-                }
+				mShadow[j].bindTarget();
+				{
+					LLGLDepthTest depth(GL_TRUE);
+					mShadow[j].clear();
+				}
+				mShadow[j].flush();
 
 				mShadowError.mV[j] = 0.f;
 				mShadowFOV.mV[j] = 0.f;
@@ -11232,24 +11211,20 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 		
 			stop_glerror();
 
-            LLRenderTarget* shadow_target = getShadowTarget(j);
-
-            if (shadow_target)
-            {
-			    shadow_target->bindTarget();
-			    shadow_target->getViewport(gGLViewport);
-			    shadow_target->clear();			
-
-			    U32 target_width = shadow_target->getWidth();
+			mShadow[j].bindTarget();
+			mShadow[j].getViewport(gGLViewport);
+			mShadow[j].clear();
+		
+			U32 target_width = mShadow[j].getWidth();
 
-			    {
-				    static LLCullResult result[4];
-				    renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width);
-			    }
+			{
+				static LLCullResult result[4];
 
-			    shadow_target->flush();
-            }
+				renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width);
+			}
 
+			mShadow[j].flush();
+ 
 			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
 			{
 				LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
@@ -11382,23 +11357,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 			stop_glerror();
 
-            LLRenderTarget* shadow_target = getShadowTarget(i + 4);
+			mShadow[i+4].bindTarget();
+			mShadow[i+4].getViewport(gGLViewport);
+			mShadow[i+4].clear();
 
-            if (shadow_target)
-            {
-			    shadow_target->bindTarget();
-			    shadow_target->getViewport(gGLViewport);
-			    shadow_target->clear();
-            
-                U32 target_width = shadow_target->getWidth();
+			U32 target_width = mShadow[i+4].getWidth();
 
-			    static LLCullResult result[2];
-			    LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
+			static LLCullResult result[2];
 
-			    renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
+			LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
 
-			    shadow_target->flush();
-            }
+			renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
+
+			mShadow[i+4].flush();
  		}
 	}
 	else