From 7e9033821a96a9d6e80b58fafb4c7da63807b9d4 Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Thu, 6 Dec 2018 10:59:11 -0800
Subject: [PATCH] De-duplicate deferred gbuffer access for getPosition/getNorm.

De-duplicate ambient occlusion shader code and move to new aoUtil.glsl

Split shared shadow tap funcs into shadowUtil.glsl
---
 indra/llrender/llglslshader.cpp               |   1 +
 indra/llrender/llglslshader.h                 |   1 +
 indra/llrender/llshadermgr.cpp                |  21 +-
 .../shaders/class1/deferred/alphaF.glsl       | 319 ++++----
 .../shaders/class1/deferred/aoUtil.glsl       |  93 +++
 .../shaders/class1/deferred/blurLightF.glsl   | 125 ++--
 .../shaders/class1/deferred/deferredUtil.glsl | 222 ------
 .../shaders/class1/deferred/materialF.glsl    | 487 ++++++------
 .../class1/deferred/multiPointLightF.glsl     |  13 +-
 .../class1/deferred/multiSpotLightF.glsl      |  14 +-
 .../shaders/class1/deferred/pointLightF.glsl  |  13 +-
 .../shaders/class1/deferred/shadowUtil.glsl   | 191 +++++
 .../shaders/class1/deferred/softenLightF.glsl |  36 +-
 .../shaders/class1/deferred/spotLightF.glsl   |  14 +-
 .../class1/deferred/sunLightSSAOF.glsl        |  87 +--
 .../class2/deferred/multiSpotLightF.glsl      |  14 +-
 .../shaders/class2/deferred/softenLightF.glsl |  40 +-
 .../shaders/class2/deferred/spotLightF.glsl   |  14 +-
 .../shaders/class2/deferred/sunLightF.glsl    |  39 +-
 .../class2/deferred/sunLightSSAOF.glsl        | 117 +--
 indra/newview/lldrawpool.cpp                  |   4 +-
 indra/newview/lldrawpool.h                    |   4 +-
 indra/newview/lldrawpoolalpha.cpp             |  12 +-
 indra/newview/lldrawpoolavatar.cpp            |  29 +-
 indra/newview/lldrawpoolavatar.h              |   2 +-
 indra/newview/lldrawpoolbump.cpp              |  30 +-
 indra/newview/lldrawpoolground.cpp            |   2 +-
 indra/newview/lldrawpoolmaterials.cpp         |   4 +-
 indra/newview/lldrawpoolsimple.cpp            |  40 +-
 indra/newview/lldrawpoolsky.cpp               |   8 +-
 indra/newview/lldrawpoolterrain.cpp           |  10 +-
 indra/newview/lldrawpooltree.cpp              |   4 +-
 indra/newview/lldrawpoolwater.cpp             |   6 +-
 indra/newview/lldrawpoolwlsky.h               |   2 +-
 indra/newview/llpanelvolume.cpp               |   2 +-
 indra/newview/llviewerdisplay.cpp             |   2 +-
 indra/newview/llviewerjointmesh.cpp           |  12 +-
 indra/newview/llviewermenu.cpp                |   8 +-
 indra/newview/llviewershadermgr.cpp           | 707 +++++++++++-------
 indra/newview/llviewershadermgr.h             |   4 +-
 indra/newview/llvoavatar.cpp                  |   4 +-
 indra/newview/llvosky.cpp                     |   4 +-
 indra/newview/llvovolume.cpp                  |   2 +-
 indra/newview/pipeline.cpp                    |  16 +-
 44 files changed, 1366 insertions(+), 1413 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl

diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 15a018a0bbb..4dae61e185e 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -84,6 +84,7 @@ LLShaderFeatures::LLShaderFeatures()
     , isDeferred(false)
     , hasIndirect(false)
     , hasShadows(false)
+    , hasAmbientOcclusion(false)
     , mIndexedTextureChannels(0)
     , disableTextureIndex(false)
     , hasAlphaMask(false)
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index ed13106bfd5..56d322fe6cc 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -49,6 +49,7 @@ class LLShaderFeatures
 	bool hasAtmospherics;
 	bool hasGamma;
     bool hasShadows;
+    bool hasAmbientOcclusion;
 	bool hasSrgb;
     bool encodesNormal;
     bool decodesNormal;
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 3a80ff0144d..29d120a1350 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -196,8 +196,8 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
-#if USE_DEFERRED_SHADER_API
-    if (features->isDeferred || features->hasShadows)
+    // we want this BEFORE shadows and AO because those facilities use pos/norm access
+    if (features->isDeferred || features->hasShadows || features->hasAmbientOcclusion)
 	{
 		if (!shader->attachObject("deferred/deferredUtil.glsl"))
 		{
@@ -205,6 +205,22 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		}
 	}
 
+    if (features->hasShadows)
+	{
+		if (!shader->attachObject("deferred/shadowUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->hasAmbientOcclusion)
+	{
+		if (!shader->attachObject("deferred/aoUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
     if (features->hasIndirect)
 	{
 		if (!shader->attachObject("deferred/indirect.glsl"))
@@ -212,7 +228,6 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			return FALSE;
 		}
 	}
-#endif
 
 	if (features->hasGamma)
 	{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index 5e3c767460f..33e61f20629 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -94,46 +94,46 @@ void calcFragAtmospherics(vec3 inPositionEye, float ambFactor, out vec3 sunlit,
 
 vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
-	//get light vector
-	vec3 lv = lp.xyz-v;
-	
-	//get distance
-	float d = length(lv);
-	
-	float da = 1.0;
-
-	vec3 col = vec3(0);
-
-	if (d > 0.0 && la > 0.0 && fa > 0.0)
-	{
-		//normalize light vector
-		lv = normalize(lv);
-	
-		//distance attenuation
-		float dist = d/la;
-		float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
-		dist_atten *= dist_atten;
-		dist_atten *= 2.0;
-
-		// spotlight coefficient.
-		float spot = max(dot(-ln, lv), is_pointlight);
-		da *= spot*spot; // GL_SPOT_EXPONENT=2
-
-		//angular attenuation
-		da *= max(dot(n, lv), 0.0);		
-
-		float lit = max(da * dist_atten,0.0);
-
-		col = light_col * lit * diffuse;
-
-		// no spec for alpha shader...
-	}
-
-	return max(col, vec3(0.0,0.0,0.0));
+    //get light vector
+    vec3 lv = lp.xyz-v;
+    
+    //get distance
+    float d = length(lv);
+    
+    float da = 1.0;
+
+    vec3 col = vec3(0);
+
+    if (d > 0.0 && la > 0.0 && fa > 0.0)
+    {
+        //normalize light vector
+        lv = normalize(lv);
+    
+        //distance attenuation
+        float dist = d/la;
+        float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+        dist_atten *= dist_atten;
+        dist_atten *= 2.0;
+
+        // spotlight coefficient.
+        float spot = max(dot(-ln, lv), is_pointlight);
+        da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+        //angular attenuation
+        da *= max(dot(n, lv), 0.0);     
+
+        float lit = max(da * dist_atten,0.0);
+
+        col = light_col * lit * diffuse;
+
+        // no spec for alpha shader...
+    }
+
+    return max(col, vec3(0.0,0.0,0.0));
 }
 
 #if HAS_SHADOW
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
+float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc)
 {
 	stc.xyz /= stc.w;
 	stc.z += shadow_bias;
@@ -152,174 +152,175 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
 }
 #endif
 
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen);
 
 void main() 
 {
-	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
-	frag *= screen_res;
-	
-	vec4 pos = vec4(vary_position, 1.0);
-	vec3 norm = vary_norm;
+    vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+    frag *= screen_res;
+    
+    vec4 pos = vec4(vary_position, 1.0);
+    vec3 norm = vary_norm;
 
-	float shadow = 1.0;
+    float shadow = 1.0;
 
 #if HAS_SHADOW
-	vec4 spos = pos;
-		
-	if (spos.z > -shadow_clip.w)
-	{	
-		shadow = 0.0;
-
-		vec4 lpos;
-		
-		vec4 near_split = shadow_clip*-0.75;
-		vec4 far_split = shadow_clip*-1.25;
-		vec4 transition_domain = near_split-far_split;
-		float weight = 0.0;
-
-		if (spos.z < near_split.z)
-		{
-			lpos = shadow_matrix[3]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap3, lpos)*w;
-			weight += w;
-			shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-		}
-
-		if (spos.z < near_split.y && spos.z > far_split.z)
-		{
-			lpos = shadow_matrix[2]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap2, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z < near_split.x && spos.z > far_split.y)
-		{
-			lpos = shadow_matrix[1]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-			shadow += pcfShadow(shadowMap1, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z > far_split.x)
-		{
-			lpos = shadow_matrix[0]*spos;
-							
-			float w = 1.0;
-			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-			shadow += pcfShadow(shadowMap0, lpos)*w;
-			weight += w;
-		}
-		
-
-		shadow /= weight;
-	}
-	else
-	{
-		shadow = 1.0;
-	}
+    vec4 spos = pos;
+        
+    if (spos.z > -shadow_clip.w)
+    {   
+        shadow = 0.0;
+
+        vec4 lpos;
+        
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        if (spos.z < near_split.z)
+        {
+            lpos = shadow_matrix[3]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+            shadow += pcfShadowLegacy(shadowMap3, lpos)*w;
+            weight += w;
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        if (spos.z < near_split.y && spos.z > far_split.z)
+        {
+            lpos = shadow_matrix[2]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
+            w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
+            shadow += pcfShadowLegacy(shadowMap2, lpos)*w;
+            weight += w;
+        }
+
+        if (spos.z < near_split.x && spos.z > far_split.y)
+        {
+            lpos = shadow_matrix[1]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
+            w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
+            shadow += pcfShadowLegacy(shadowMap1, lpos)*w;
+            weight += w;
+        }
+
+        if (spos.z > far_split.x)
+        {
+            lpos = shadow_matrix[0]*spos;
+                            
+            float w = 1.0;
+            w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
+                
+            shadow += pcfShadowLegacy(shadowMap0, lpos)*w;
+            weight += w;
+        }
+        
+
+        shadow /= weight;
+    }
+    else
+    {
+        shadow = 1.0;
+    }
 #endif
 
 #ifdef USE_INDEXED_TEX
-	vec4 diff = diffuseLookup(vary_texcoord0.xy);
+    vec4 diff = diffuseLookup(vary_texcoord0.xy);
 #else
-	vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
+    vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
 #endif
 
 #ifdef FOR_IMPOSTOR
-	vec4 color;
-	color.rgb = diff.rgb;
-	color.a = 1.0;
+    vec4 color;
+    color.rgb = diff.rgb;
+    color.a = 1.0;
 
 #ifdef USE_VERTEX_COLOR
-	float final_alpha = diff.a * vertex_color.a;
-	diff.rgb *= vertex_color.rgb;
+    float final_alpha = diff.a * vertex_color.a;
+    diff.rgb *= vertex_color.rgb;
 #else
-	float final_alpha = diff.a;
+    float final_alpha = diff.a;
 #endif
-	
-	// Insure we don't pollute depth with invis pixels in impostor rendering
-	//
-	if (final_alpha < 0.01)
-	{
-		discard;
-	}
+    
+    // Insure we don't pollute depth with invis pixels in impostor rendering
+    //
+    if (final_alpha < 0.01)
+    {
+        discard;
+    }
 #else
-	
+    
 #ifdef USE_VERTEX_COLOR
-	float final_alpha = diff.a * vertex_color.a;
-	diff.rgb *= vertex_color.rgb;
+    float final_alpha = diff.a * vertex_color.a;
+    diff.rgb *= vertex_color.rgb;
 #else
-	float final_alpha = diff.a;
+    float final_alpha = diff.a;
 #endif
 
     vec3 sunlit;
     vec3 amblit;
     vec3 additive;
     vec3 atten;
-	calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
+    calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
 
-	vec2 abnormal	= encode_normal(norm.xyz);
-		 norm.xyz   = decode_normal(abnormal.xy);
+    vec2 abnormal   = encode_normal(norm.xyz);
+         norm.xyz   = decode_normal(abnormal.xy);
 
-	float sun_da  = dot(norm.xyz, sun_dir.xyz);
-	float moon_da = dot(norm.xyz, moon_dir.xyz);
+    float sun_da  = dot(norm.xyz, sun_dir.xyz);
+    float moon_da = dot(norm.xyz, moon_dir.xyz);
 
     float final_da = max(sun_da, moon_da);
           final_da = min(final_da, shadow);
           final_da = clamp(final_da, 0.0f, 1.0f);
-	  final_da = pow(final_da, display_gamma);
+      final_da = pow(final_da, display_gamma);
 
-	vec4 color = vec4(0,0,0,0);
+    vec4 color = vec4(0,0,0,0);
 
-	color.rgb = atmosFragAmbient(color.rgb, amblit);
-	color.a   = final_alpha;
+    color.rgb = atmosFragAmbient(color.rgb, amblit);
+    color.a   = final_alpha;
 
-	float ambient = abs(final_da);
-	ambient *= 0.5;
-	ambient *= ambient;
-	ambient = (1.0-ambient);
+    float ambient = abs(final_da);
+    ambient *= 0.5;
+    ambient *= ambient;
+    ambient = (1.0-ambient);
 
-	color.rgb *= ambient;
-	color.rgb += (final_da * sunlit);
-	color.rgb *= diff.rgb;
+    color.rgb *= ambient;
+    color.rgb += (final_da * sunlit);
+    color.rgb *= diff.rgb;
 
-	//color.rgb = mix(diff.rgb, color.rgb, final_alpha);
-	
-	color.rgb = atmosFragLighting(color.rgb, additive, atten);
-	color.rgb = scaleSoftClip(color.rgb);
+    //color.rgb = mix(diff.rgb, color.rgb, final_alpha);
+    
+    color.rgb = atmosFragLighting(color.rgb, additive, atten);
+    color.rgb = scaleSoftClip(color.rgb);
 
-	vec4 light = vec4(0,0,0,0);
+    vec4 light = vec4(0,0,0,0);
 
    #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diff.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z);
 
-	LIGHT_LOOP(1)
-	LIGHT_LOOP(2)
-	LIGHT_LOOP(3)
-	LIGHT_LOOP(4)
-	LIGHT_LOOP(5)
-	LIGHT_LOOP(6)
-	LIGHT_LOOP(7)
+    LIGHT_LOOP(1)
+    LIGHT_LOOP(2)
+    LIGHT_LOOP(3)
+    LIGHT_LOOP(4)
+    LIGHT_LOOP(5)
+    LIGHT_LOOP(6)
+    LIGHT_LOOP(7)
 
-	// keep it linear
-	//
-	color.rgb += light.rgb;
+    // keep it linear
+    //
+    color.rgb += light.rgb;
 
 #ifdef WATER_FOG
-	color = applyWaterFogView(pos.xyz, color);
+    color = applyWaterFogView(pos.xyz, color);
 #endif
 #endif
 
-	frag_color = color;
+    frag_color = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
new file mode 100644
index 00000000000..3bb59dd7f9e
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
@@ -0,0 +1,93 @@
+/** 
+ * @file class1/deferred/aoUtil.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+uniform sampler2D       noiseMap;
+
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+vec4 getPosition(vec2 pos_screen);
+
+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, vec2 pos_screen)
+{
+    float ret = 1.0;
+    vec3 pos_world = pos.xyz;
+    vec2 noise_reflect = texture2D(noiseMap, pos_screen.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);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index b56abb66d1f..868eec39261 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -48,82 +48,69 @@ VARYING vec2 vary_fragcoord;
 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;
-}
-
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 vec3 decode_normal (vec2 enc);
 
 void main() 
 {
     vec2 tc = vary_fragcoord.xy;
-	vec3 norm = texture2DRect(normalMap, tc).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-
-	vec3 pos = getPosition(tc).xyz;
-	vec4 ccol = texture2DRect(lightMap, tc).rgba;
-	
-	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-	dlt /= max(-pos.z*dist_factor, 1.0);
-	
-	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
-	vec4 col = defined_weight.xyxx * ccol;
-
-	// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
-	float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
-
-	// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
-	float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
-	tc_mod -= floor(tc_mod);
-	tc_mod *= 2.0;
-	tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
-
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 samptc = tc + kern[i].z*dlt;
-	    vec3 samppos = getPosition(samptc).xyz; 
-
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		
-		if (d*d <= pointplanedist_tolerance_pow2)
-		{
-			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 samptc = tc - kern[i].z*dlt;
-	    vec3 samppos = getPosition(samptc).xyz; 
-
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		
-		if (d*d <= pointplanedist_tolerance_pow2)
-		{
-			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-
-	col /= defined_weight.xyxx;
-	col.y *= col.y;
-	
-	frag_color = col;
+    vec3 norm = getNorm(tc);
+    vec3 pos = getPosition(tc).xyz;
+    vec4 ccol = texture2DRect(lightMap, tc).rgba;
+    
+    vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+    dlt /= max(-pos.z*dist_factor, 1.0);
+    
+    vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+    vec4 col = defined_weight.xyxx * ccol;
+
+    // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+    float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+    // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+    float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
+    tc_mod -= floor(tc_mod);
+    tc_mod *= 2.0;
+    tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
+
+    for (int i = 1; i < 4; i++)
+    {
+        vec2 samptc = tc + kern[i].z*dlt;
+        vec3 samppos = getPosition(samptc).xyz; 
+
+        float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+        
+        if (d*d <= pointplanedist_tolerance_pow2)
+        {
+            col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+            defined_weight += kern[i].xy;
+        }
+    }
+
+    for (int i = 1; i < 4; i++)
+    {
+        vec2 samptc = tc - kern[i].z*dlt;
+        vec3 samppos = getPosition(samptc).xyz; 
+
+        float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+        
+        if (d*d <= pointplanedist_tolerance_pow2)
+        {
+            col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+            defined_weight += kern[i].xy;
+        }
+    }
+
+    col /= defined_weight.xyxx;
+    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];
+    // 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/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
index ec05dab57ff..9d7a7f65569 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -25,29 +25,6 @@
 
 uniform sampler2DRect   normalMap;
 uniform sampler2DRect   depthMap;
-uniform sampler2D       noiseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-uniform sampler2DShadow shadowMap4;
-uniform sampler2DShadow shadowMap5;
-
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-uniform vec2 shadow_res;
-uniform vec2 proj_shadow_res;
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float shadow_bias;
-
-uniform float spot_shadow_bias;
-uniform float spot_shadow_offset;
 
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
@@ -87,8 +64,6 @@ vec4 getPosition(vec2 pos_screen)
     return pos;
 }
 
-#if USE_DEFERRED_SHADER_API
-
 vec4 getPositionWithDepth(vec2 pos_screen, float depth)
 {
     vec2 sc = getScreenCoordinate(pos_screen);
@@ -98,200 +73,3 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth)
     pos.w = 1.0;
     return pos;
 }
-
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen)
-{
-    stc.xyz /= stc.w;
-    stc.z += shadow_bias * bias_scale;
-        
-    stc.x = floor(stc.x*pos_screen.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
-    
-    float cs = shadow2D(shadowMap, stc.xyz).x;
-    float shadow = cs;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-    return shadow*0.2;
-}
-
-float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen)
-{
-    stc.xyz /= stc.w;
-    stc.z += spot_shadow_bias * bias_scale;
-    stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
-
-    float cs = shadow2D(shadowMap, stc.xyz).x;
-    float shadow = cs;
-
-    vec2 off = 1.0/proj_shadow_res;
-    off.y *= 1.5;
-    
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
-    return shadow*0.2;
-}
-
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
-{
-    float dp_sun = max(0.0, dot(sun_dir.xyz, norm));
-    float dp_moon = max(0.0, dot(moon_dir.xyz, norm));
-    float dp_directional_light = max(dp_sun,dp_moon);
-          dp_directional_light = clamp(dp_directional_light, 0.0, 1.0);
-
-        vec3 light_dir = (dp_moon > dp_sun) ? moon_dir : sun_dir;
-    vec3 offset = light_dir * (1.0-dp_directional_light);
-    vec3 shadow_pos = pos.xyz + (offset * shadow_bias);
-
-    float shadow = 0.0f;
-    vec4 spos = vec4(shadow_pos,1.0);
-    if (spos.z > -shadow_clip.w)
-    {   
-        vec4 lpos;
-        vec4 near_split = shadow_clip*-0.75;
-        vec4 far_split = shadow_clip*-1.25;
-        vec4 transition_domain = near_split-far_split;
-        float weight = 0.0;
-
-        if (spos.z < near_split.z)
-        {
-            lpos = shadow_matrix[3]*spos;
-            
-            float w = 1.0;
-            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-            shadow += pcfShadow(shadowMap3, lpos, 0.5, pos_screen)*w;
-            weight += w;
-            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-        }
-
-        if (spos.z < near_split.y && spos.z > far_split.z)
-        {
-            lpos = shadow_matrix[2]*spos;
-            
-            float w = 1.0;
-            w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-            w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-            shadow += pcfShadow(shadowMap2, lpos, 0.75, pos_screen)*w;
-            weight += w;
-        }
-
-        if (spos.z < near_split.x && spos.z > far_split.y)
-        {
-            lpos = shadow_matrix[1]*spos;
-            
-            float w = 1.0;
-            w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-            w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-            shadow += pcfShadow(shadowMap1, lpos, 0.88, pos_screen)*w;
-            weight += w;
-        }
-
-        if (spos.z > far_split.x)
-        {
-            lpos = shadow_matrix[0]*spos;
-                            
-            float w = 1.0;
-            w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-                
-            shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
-            weight += w;
-        }
-
-        shadow /= weight;
-    }
-    return shadow;
-}
-
-float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
-{
-    float shadow = 0.0f;
-    pos += norm * spot_shadow_offset;
-
-    vec4 spos = vec4(pos,1.0);
-    if (spos.z > -shadow_clip.w)
-    {   
-        vec4 lpos;
-        
-        vec4 near_split = shadow_clip*-0.75;
-        vec4 far_split = shadow_clip*-1.25;
-        vec4 transition_domain = near_split-far_split;
-        float weight = 0.0;
-
-        {
-            lpos = shadow_matrix[4 + index]*spos;
-            float w = 1.0;
-            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-        
-            shadow += pcfSpotShadow((index == 0) ? shadowMap4 : shadowMap5, lpos, 0.8, spos.xy)*w;
-            weight += w;
-            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-        }
-
-        shadow /= weight;
-    }
-    return shadow;
-}
-
-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, vec2 pos_screen)
-{
-    float ret = 1.0;
-    vec3 pos_world = pos.xyz;
-    vec2 noise_reflect = texture2D(noiseMap, pos_screen.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);
-}
-
-#endif
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 211bedee593..a0da8563a26 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -25,9 +25,9 @@
  
 /*[EXTRA_CODE_HERE]*/
 
-#define DIFFUSE_ALPHA_MODE_IGNORE	0
-#define DIFFUSE_ALPHA_MODE_BLEND	1
-#define DIFFUSE_ALPHA_MODE_MASK		2
+#define DIFFUSE_ALPHA_MODE_IGNORE   0
+#define DIFFUSE_ALPHA_MODE_BLEND    1
+#define DIFFUSE_ALPHA_MODE_MASK     2
 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3
 
 uniform float emissive_brightness;
@@ -62,7 +62,7 @@ uniform vec4 shadow_clip;
 uniform vec2 shadow_res;
 uniform float shadow_bias;
 
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
+float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc)
 {
 	stc.xyz /= stc.w;
 	stc.z += shadow_bias;
@@ -80,10 +80,11 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
     return shadow*0.2;
 }
 
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen);
 #endif
 
 uniform samplerCube environmentMap;
-uniform sampler2D	  lightFunc;
+uniform sampler2D     lightFunc;
 
 // Inputs
 uniform vec4 morphFactor;
@@ -109,80 +110,80 @@ uniform vec3 light_diffuse[8];
 
 vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare)
 {
-	//get light vector
-	vec3 lv = lp.xyz-v;
-	
-	//get distance
-	float d = length(lv);
-	
-	float da = 1.0;
-
-	vec3 col = vec3(0,0,0);
-
-	if (d > 0.0 && la > 0.0 && fa > 0.0)
-	{
-		//normalize light vector
-		lv = normalize(lv);
-	
-		//distance attenuation
-		float dist = d/la;
-		float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
-		dist_atten *= dist_atten;
-		dist_atten *= 2.0;
-
-		// spotlight coefficient.
-		float spot = max(dot(-ln, lv), is_pointlight);
-		da *= spot*spot; // GL_SPOT_EXPONENT=2
-
-		//angular attenuation
-		da *= max(dot(n, lv), 0.0);		
-		
-		float lit = max(da * dist_atten, 0.0);
-
-		col = light_col*lit*diffuse;
-
-		if (spec.a > 0.0)
-		{
-			//vec3 ref = dot(pos+lv, norm);
-			vec3 h = normalize(lv+npos);
-			float nh = dot(n, h);
-			float nv = dot(n, npos);
-			float vh = dot(npos, h);
-			float sa = nh;
-			float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
-			float gtdenom = 2 * nh;
-			float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-								
-			if (nh > 0.0)
-			{
-				float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
-				vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
-				col += speccol;
-
-				float cur_glare = max(speccol.r, speccol.g);
-				cur_glare = max(cur_glare, speccol.b);
-				glare = max(glare, speccol.r);
-				glare += max(cur_glare, 0.0);
-				//col += spec.rgb;
-			}
-		}
-	}
-
-	return max(col, vec3(0.0,0.0,0.0));	
+    //get light vector
+    vec3 lv = lp.xyz-v;
+    
+    //get distance
+    float d = length(lv);
+    
+    float da = 1.0;
+
+    vec3 col = vec3(0,0,0);
+
+    if (d > 0.0 && la > 0.0 && fa > 0.0)
+    {
+        //normalize light vector
+        lv = normalize(lv);
+    
+        //distance attenuation
+        float dist = d/la;
+        float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+        dist_atten *= dist_atten;
+        dist_atten *= 2.0;
+
+        // spotlight coefficient.
+        float spot = max(dot(-ln, lv), is_pointlight);
+        da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+        //angular attenuation
+        da *= max(dot(n, lv), 0.0);     
+        
+        float lit = max(da * dist_atten, 0.0);
+
+        col = light_col*lit*diffuse;
+
+        if (spec.a > 0.0)
+        {
+            //vec3 ref = dot(pos+lv, norm);
+            vec3 h = normalize(lv+npos);
+            float nh = dot(n, h);
+            float nv = dot(n, npos);
+            float vh = dot(npos, h);
+            float sa = nh;
+            float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
+
+            float gtdenom = 2 * nh;
+            float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+                                
+            if (nh > 0.0)
+            {
+                float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
+                vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
+                col += speccol;
+
+                float cur_glare = max(speccol.r, speccol.g);
+                cur_glare = max(cur_glare, speccol.b);
+                glare = max(glare, speccol.r);
+                glare += max(cur_glare, 0.0);
+                //col += spec.rgb;
+            }
+        }
+    }
+
+    return max(col, vec3(0.0,0.0,0.0)); 
 
 }
 
 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;
+    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;
 }
 
 
@@ -232,253 +233,253 @@ void main()
 {
     vec2 pos_screen = vary_texcoord0.xy;
 
-	vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
-	diffcol.rgb *= vertex_color.rgb;
+    vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+    diffcol.rgb *= vertex_color.rgb;
 
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-	if (diffcol.a < minimum_alpha)
-	{
-		discard;
-	}
+    if (diffcol.a < minimum_alpha)
+    {
+        discard;
+    }
 #endif
 
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-	vec3 gamma_diff = diffcol.rgb;
+    vec3 gamma_diff = diffcol.rgb;
 #endif
 
 #if HAS_SPECULAR_MAP
-	vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
-	spec.rgb *= specular_color.rgb;
+    vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+    spec.rgb *= specular_color.rgb;
 #else
-	vec4 spec = vec4(specular_color.rgb, 1.0);
+    vec4 spec = vec4(specular_color.rgb, 1.0);
 #endif
 
 #if HAS_NORMAL_MAP
-	vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+    vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
 
-	norm.xyz = norm.xyz * 2 - 1;
+    norm.xyz = norm.xyz * 2 - 1;
 
-	vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
-			  dot(norm.xyz,vary_mat1),
-			  dot(norm.xyz,vary_mat2));
+    vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+              dot(norm.xyz,vary_mat1),
+              dot(norm.xyz,vary_mat2));
 #else
-	vec4 norm = vec4(0,0,0,1.0);
-	vec3 tnorm = vary_normal;
+    vec4 norm = vec4(0,0,0,1.0);
+    vec3 tnorm = vary_normal;
 #endif
 
     norm.xyz = tnorm;
     norm.xyz = normalize(norm.xyz);
 
-	vec2 abnormal	= encode_normal(norm.xyz);
-		 norm.xyz   = decode_normal(abnormal.xy);
+    vec2 abnormal   = encode_normal(norm.xyz);
+         norm.xyz   = decode_normal(abnormal.xy);
 
-	vec4 final_color = diffcol;
-	
+    vec4 final_color = diffcol;
+    
 #if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
-	final_color.a = emissive_brightness;
+    final_color.a = emissive_brightness;
 #else
-	final_color.a = max(final_color.a, emissive_brightness);
+    final_color.a = max(final_color.a, emissive_brightness);
 #endif
 
-	vec4 final_specular = spec;
+    vec4 final_specular = spec;
 #if HAS_SPECULAR_MAP
-	vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
-	final_specular.a = specular_color.a * norm.a;
+    vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
+    final_specular.a = specular_color.a * norm.a;
 #else
-	vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
-	final_specular.a = specular_color.a;
+    vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
+    final_specular.a = specular_color.a;
 #endif
-	
+    
 
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-		//forward rendering, output just lit RGBA
-	vec3 pos = vary_position;
+        //forward rendering, output just lit RGBA
+    vec3 pos = vary_position;
 
 #if HAS_SUN_SHADOW
-	float shadow = 0.0;
-	
-	vec4 spos = vec4(pos,1.0);
-		
-	if (spos.z > -shadow_clip.w)
-	{	
-		vec4 lpos;
-		
-		vec4 near_split = shadow_clip*-0.75;
-		vec4 far_split = shadow_clip*-1.25;
-		vec4 transition_domain = near_split-far_split;
-		float weight = 0.0;
-
-		if (spos.z < near_split.z)
-		{
-			lpos = shadow_matrix[3]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap3, lpos)*w;
-			weight += w;
-			shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-		}
-
-		if (spos.z < near_split.y && spos.z > far_split.z)
-		{
-			lpos = shadow_matrix[2]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap2, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z < near_split.x && spos.z > far_split.y)
-		{
-			lpos = shadow_matrix[1]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-			shadow += pcfShadow(shadowMap1, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z > far_split.x)
-		{
-			lpos = shadow_matrix[0]*spos;
-							
-			float w = 1.0;
-			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-			shadow += pcfShadow(shadowMap0, lpos)*w;
-			weight += w;
-		}
-		
-
-		shadow /= weight;
-	}
-	else
-	{
-		shadow = 1.0;
-	}
+    float shadow = 0.0;
+    
+    vec4 spos = vec4(pos,1.0);
+        
+    if (spos.z > -shadow_clip.w)
+    {   
+        vec4 lpos;
+        
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        if (spos.z < near_split.z)
+        {
+            lpos = shadow_matrix[3]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+            shadow += pcfShadowLegacy(shadowMap3, lpos)*w;
+            weight += w;
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        if (spos.z < near_split.y && spos.z > far_split.z)
+        {
+            lpos = shadow_matrix[2]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
+            w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
+            shadow += pcfShadowLegacy(shadowMap2, lpos)*w;
+            weight += w;
+        }
+
+        if (spos.z < near_split.x && spos.z > far_split.y)
+        {
+            lpos = shadow_matrix[1]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
+            w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
+            shadow += pcfShadowLegacy(shadowMap1, lpos)*w;
+            weight += w;
+        }
+
+        if (spos.z > far_split.x)
+        {
+            lpos = shadow_matrix[0]*spos;
+                            
+            float w = 1.0;
+            w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
+                
+            shadow += pcfShadowLegacy(shadowMap0, lpos)*w;
+            weight += w;
+        }
+        
+
+        shadow /= weight;
+    }
+    else
+    {
+        shadow = 1.0;
+    }
 #else
-	float shadow = 1.0;
+    float shadow = 1.0;
 #endif
 
-	spec = final_specular;
-	vec4 diffuse = final_color;
-	float envIntensity = final_normal.z;
+    spec = final_specular;
+    vec4 diffuse = final_color;
+    float envIntensity = final_normal.z;
 
     vec3 col = vec3(0.0f,0.0f,0.0f);
 
-	float bloom = 0.0;
+    float bloom = 0.0;
         vec3 sunlit;
         vec3 amblit;
         vec3 additive;
         vec3 atten;
 
-	calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
-	
-	vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+    calcFragAtmospherics(pos.xyz, 1.0, sunlit, amblit, additive, atten);
+    
+    vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
 
-	float sun_da  = dot(norm.xyz, sun_dir.xyz);
-	float moon_da = dot(norm.xyz, moon_dir.xyz);
+    float sun_da  = dot(norm.xyz, sun_dir.xyz);
+    float moon_da = dot(norm.xyz, moon_dir.xyz);
 
     float final_da = max(sun_da,moon_da);
           final_da = min(final_da, shadow);
           //final_da = max(final_da, diffuse.a);
           final_da = max(final_da, 0.0f);
-		  final_da = min(final_da, 1.0f);
-		  final_da = pow(final_da, display_gamma);
+          final_da = min(final_da, 1.0f);
+          final_da = pow(final_da, display_gamma);
 
-	col.rgb = (col * 0.5) + amblit;
-	
-	float ambient = min(abs(final_da), 1.0);
-	ambient *= 0.5;
-	ambient *= ambient;
-	ambient = (1.0-ambient);
+    col.rgb = (col * 0.5) + amblit;
+    
+    float ambient = min(abs(final_da), 1.0);
+    ambient *= 0.5;
+    ambient *= ambient;
+    ambient = (1.0-ambient);
 
-	col.rgb *= ambient;
+    col.rgb *= ambient;
 
-	col.rgb = col.rgb + (final_da * sunlit);
+    col.rgb = col.rgb + (final_da * sunlit);
 
-	col.rgb *= gamma_diff.rgb;
-	
+    col.rgb *= gamma_diff.rgb;
+    
 
-	float glare = 0.0;
+    float glare = 0.0;
 
-	if (spec.a > 0.0) // specular reflection
-	{
-		// the old infinite-sky shiny reflection
-		//
-				
+    if (spec.a > 0.0) // specular reflection
+    {
+        // the old infinite-sky shiny reflection
+        //
+                
         float sa = dot(refnormpersp, sun_dir.xyz);
 
-		vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-							
-		// add the two types of shiny together
-		vec3 spec_contrib = dumbshiny * spec.rgb;
-		bloom = dot(spec_contrib, spec_contrib) / 6;
+        vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+                            
+        // add the two types of shiny together
+        vec3 spec_contrib = dumbshiny * spec.rgb;
+        bloom = dot(spec_contrib, spec_contrib) / 6;
 
-		glare = max(spec_contrib.r, spec_contrib.g);
-		glare = max(glare, spec_contrib.b);
+        glare = max(spec_contrib.r, spec_contrib.g);
+        glare = max(glare, spec_contrib.b);
 
-		col += spec_contrib;
-	}
+        col += spec_contrib;
+    }
 
 
-	col = mix(col.rgb, diffcol.rgb, diffuse.a);
+    col = mix(col.rgb, diffcol.rgb, diffuse.a);
 
-	if (envIntensity > 0.0)
-	{
-		//add environmentmap
-		vec3 env_vec = env_mat * refnormpersp;
-		
-		vec3 refcol = textureCube(environmentMap, env_vec).rgb;
+    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);  
 
-		float cur_glare = max(refcol.r, refcol.g);
-		cur_glare = max(cur_glare, refcol.b);
-		cur_glare *= envIntensity*4.0;
-		glare += cur_glare;
-	}
+        float cur_glare = max(refcol.r, refcol.g);
+        cur_glare = max(cur_glare, refcol.b);
+        cur_glare *= envIntensity*4.0;
+        glare += cur_glare;
+    }
 
-	col = atmosFragLighting(col, additive, atten);
+    col = atmosFragLighting(col, additive, atten);
 
-	vec3 npos = normalize(-pos.xyz);
-			
-	vec3 light = vec3(0,0,0);
+    vec3 npos = normalize(-pos.xyz);
+            
+    vec3 light = vec3(0,0,0);
 
  #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare);
 
-		LIGHT_LOOP(1)
-		LIGHT_LOOP(2)
-		LIGHT_LOOP(3)
-		LIGHT_LOOP(4)
-		LIGHT_LOOP(5)
-		LIGHT_LOOP(6)
-		LIGHT_LOOP(7)
+        LIGHT_LOOP(1)
+        LIGHT_LOOP(2)
+        LIGHT_LOOP(3)
+        LIGHT_LOOP(4)
+        LIGHT_LOOP(5)
+        LIGHT_LOOP(6)
+        LIGHT_LOOP(7)
 
-	col.rgb += light.rgb;
+    col.rgb += light.rgb;
 
-	glare = min(glare, 1.0);
-	float al = max(diffcol.a,glare)*vertex_color.a;
+    glare = min(glare, 1.0);
+    float al = max(diffcol.a,glare)*vertex_color.a;
 
-	col = scaleSoftClipFrag(col);
+    col = scaleSoftClipFrag(col);
 
 #ifdef WATER_FOG
-	vec4 temp = applyWaterFogView(pos, vec4(col.rgb, al));
-	col.rgb = temp.rgb;
-	al = temp.a;
+    vec4 temp = applyWaterFogView(pos, vec4(col.rgb, al));
+    col.rgb = temp.rgb;
+    al = temp.a;
 #endif
 
-	frag_color.rgb = col.rgb;
-	frag_color.a   = al;
+    frag_color.rgb = col.rgb;
+    frag_color.a   = al;
 
 #else
-	frag_data[0] = final_color;
-	frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
-	frag_data[2] = final_normal; // XY = Normal.  Z = Env. intensity.
+    frag_data[0] = final_color;
+    frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+    frag_data[2] = final_normal; // XY = Normal.  Z = Env. intensity.
 #endif
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index d1ac19270d2..e8eef9b94bc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -59,18 +59,7 @@ uniform mat4 inv_proj;
 
 vec3 decode_normal (vec2 enc);
 
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index b3dcd90d982..7438fac8fcc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -123,19 +123,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index 13b803e03e8..8e756c37bfd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -58,18 +58,7 @@ uniform vec4 viewport;
 
 vec3 decode_normal (vec2 enc);
 
-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;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
new file mode 100644
index 00000000000..ae5cb7cbc13
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
@@ -0,0 +1,191 @@
+/** 
+ * @file class1/deferred/shadowUtil.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+uniform sampler2DRect   normalMap;
+uniform sampler2DRect   depthMap;
+uniform sampler2D       noiseMap;
+uniform sampler2DShadow shadowMap0;
+uniform sampler2DShadow shadowMap1;
+uniform sampler2DShadow shadowMap2;
+uniform sampler2DShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float shadow_bias;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec3 decode_normal(vec2 enc);
+
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen)
+{
+    stc.xyz /= stc.w;
+    stc.z += shadow_bias;
+        
+    stc.x = floor(stc.x*pos_screen.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
+    
+    float cs = shadow2D(shadowMap, stc.xyz).x;
+    float shadow = cs;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
+    return shadow*0.2;
+}
+
+float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen)
+{
+    stc.xyz /= stc.w;
+    stc.z += spot_shadow_bias * bias_scale;
+    stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
+
+    float cs = shadow2D(shadowMap, stc.xyz).x;
+    float shadow = cs;
+
+    vec2 off = 1.0/proj_shadow_res;
+    off.y *= 1.5;
+    
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
+    return shadow*0.2;
+}
+
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
+{
+    float dp_sun = max(0.0, dot(sun_dir.xyz, norm));
+    float dp_moon = max(0.0, dot(moon_dir.xyz, norm));
+    float dp_directional_light = max(dp_sun,dp_moon);
+          dp_directional_light = clamp(dp_directional_light, 0.0, 1.0);
+
+        vec3 light_dir = (dp_moon > dp_sun) ? moon_dir : sun_dir;
+    vec3 offset = light_dir * (1.0-dp_directional_light);
+    vec3 shadow_pos = pos.xyz + (offset * shadow_bias);
+
+    float shadow = 0.0f;
+    vec4 spos = vec4(shadow_pos,1.0);
+    if (spos.z > -shadow_clip.w)
+    {   
+        vec4 lpos;
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        if (spos.z < near_split.z)
+        {
+            lpos = shadow_matrix[3]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+            shadow += pcfShadow(shadowMap3, lpos, 0.5, pos_screen)*w;
+            weight += w;
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        if (spos.z < near_split.y && spos.z > far_split.z)
+        {
+            lpos = shadow_matrix[2]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
+            w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
+            shadow += pcfShadow(shadowMap2, lpos, 0.75, pos_screen)*w;
+            weight += w;
+        }
+
+        if (spos.z < near_split.x && spos.z > far_split.y)
+        {
+            lpos = shadow_matrix[1]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
+            w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
+            shadow += pcfShadow(shadowMap1, lpos, 0.88, pos_screen)*w;
+            weight += w;
+        }
+
+        if (spos.z > far_split.x)
+        {
+            lpos = shadow_matrix[0]*spos;
+                            
+            float w = 1.0;
+            w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
+                
+            shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
+            weight += w;
+        }
+
+        shadow /= weight;
+    }
+    return shadow;
+}
+
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
+{
+    float shadow = 0.0f;
+    pos += norm * spot_shadow_offset;
+
+    vec4 spos = vec4(pos,1.0);
+    if (spos.z > -shadow_clip.w)
+    {   
+        vec4 lpos;
+        
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        {
+            lpos = shadow_matrix[4 + index]*spos;
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+        
+            shadow += pcfSpotShadow((index == 0) ? shadowMap4 : shadowMap5, lpos, 0.8, spos.xy)*w;
+            weight += w;
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        shadow /= weight;
+    }
+    return shadow;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 2ba766a0c49..0de38a3d62f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -86,18 +86,14 @@ vec4 getPosition_d(vec2 pos_screen, float depth)
     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);
-}
-
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
     vec2 tc = vary_fragcoord.xy;
     float depth = texture2DRect(depthMap, tc.xy).r;
-    vec3 pos = getPosition_d(tc, depth).xyz;
+    vec3 pos = getPositionWithDepth(tc, depth).xyz;
     vec4 norm = texture2DRect(normalMap, tc);
     float envIntensity = norm.z;
     norm.xyz = decode_normal(norm.xy); // unpack norm
@@ -107,14 +103,14 @@ void main()
     float da = max(da_sun, da_moon);
 
     float final_da = clamp(da, 0.0, 1.0);
-          final_da = pow(final_da, global_gamma);
+          final_da = pow(final_da, global_gamma + 0.3);
 
     vec4 diffuse = texture2DRect(diffuseRect, tc);
 
-	vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-	vec3 col;
-	float bloom = 0.0;
-	{
+    vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+    vec3 col;
+    float bloom = 0.0;
+    {
         vec3 sunlit;
         vec3 amblit;
         vec3 additive;
@@ -162,14 +158,14 @@ void main()
             col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
         }
 
-		#ifdef WATER_FOG
-			vec4 fogged = applyWaterFogView(pos.xyz,vec4(col, bloom));
-			col = fogged.rgb;
-			bloom = fogged.a;
-		#endif
-	}
+        #ifdef WATER_FOG
+            vec4 fogged = applyWaterFogView(pos.xyz,vec4(col, bloom));
+            col = fogged.rgb;
+            bloom = fogged.a;
+        #endif
+    }
 
-	frag_color.rgb = col.rgb;
-	frag_color.a = bloom;
+    frag_color.rgb = col.rgb;
+    frag_color.a = bloom;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 1abdd4af332..22488944cda 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -121,19 +121,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 403df87853f..6d65ee2add1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -41,82 +41,15 @@ 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);
-
-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)
-{
-	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);
-}
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
 
 void main() 
 {
@@ -124,13 +57,11 @@ void main()
 	
 	//try doing an unproject here
 	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy);
+	vec4 pos = getPosition(pos_screen);	
+	vec3 norm = getNorm(pos_screen);
 		
-	frag_color[0] = 1.0;
-	frag_color[1] = calcAmbientOcclusion(pos, norm);
-	frag_color[2] = 1.0; 
-	frag_color[3] = 1.0;
+	frag_color.r = 1.0;
+	frag_color.g = calcAmbientOcclusion(pos, norm, pos_screen);
+	frag_color.b = 1.0; 
+	frag_color.a = 1.0;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 0a8981a102f..1c5d3901f5b 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -122,19 +122,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index 9de2741725e..1b0a1b5d849 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -85,24 +85,8 @@ vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
 vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
 vec3 fullbrightShinyAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
 
-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);
@@ -110,19 +94,19 @@ vec4 applyWaterFogView(vec3 pos, vec4 color);
 
 void main() 
 {
-    vec2 tc = vary_fragcoord.xy;
-    float depth = texture2DRect(depthMap, tc.xy).r;
-    vec3 pos = getPosition_d(tc, depth).xyz;
-    vec4 norm = texture2DRect(normalMap, tc);
-    float envIntensity = norm.z;
-    norm.xyz = decode_normal(norm.xy); // unpack norm
-        
-    float da_sun  = dot(norm.xyz, normalize(sun_dir.xyz));
+	vec2 tc = vary_fragcoord.xy;
+	float depth = texture2DRect(depthMap, tc.xy).r;
+	vec4 pos = getPositionWithDepth(tc, depth);
+	vec4 norm = texture2DRect(normalMap, tc);
+	float envIntensity = norm.z;
+	norm.xyz = decode_normal(norm.xy); // unpack norm
+		
+	float da_sun  = dot(norm.xyz, normalize(sun_dir.xyz));
     float da_moon = dot(norm.xyz, normalize(moon_dir.xyz));
     float da = max(da_sun, da_moon);
           da = clamp(da, 0.0, 1.0);
 
-	da = pow(da, global_gamma);
+	da = pow(da, global_gamma + 0.3);
 
 	vec4 diffuse = texture2DRect(diffuseRect, tc);
 	
@@ -132,7 +116,7 @@ void main()
         vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
         
         vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
-        scol_ambocc = pow(scol_ambocc, vec2(global_gamma));
+        scol_ambocc = pow(scol_ambocc, vec2(global_gamma + 0.3));
 
         float scol = max(scol_ambocc.r, diffuse.a); 
         float ambocc = scol_ambocc.g;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index d97bd936d97..36854b0e667 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -122,19 +122,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index f2d04c95fef..5f8f3114a1e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -68,22 +68,13 @@ uniform float shadow_offset;
 uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
-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;
-}
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen);
+float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen);
 
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
+float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
 	stc.xyz /= stc.w;
 	stc.z += shadow_bias;
@@ -102,7 +93,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
     return shadow*0.2;
 }
 
-float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
+float pcfSpotShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
 	stc.xyz /= stc.w;
 	stc.z += spot_shadow_bias*scl;
@@ -128,10 +119,8 @@ void main()
 	
 	//try doing an unproject here
 	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
+	vec4 pos  = getPosition(pos_screen);	
+	vec3 norm = getNorm(pos_screen);
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
@@ -174,7 +163,7 @@ void main()
 				
 				float w = 1.0;
 				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap3, lpos, 0.25, pos_screen)*w;
 				weight += w;
 				shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
 			}
@@ -186,7 +175,7 @@ void main()
 				float w = 1.0;
 				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
 				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap2, lpos, 0.5, pos_screen)*w;
 				weight += w;
 			}
 
@@ -197,7 +186,7 @@ void main()
 				float w = 1.0;
 				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
 				w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-				shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap1, lpos, 0.75, pos_screen)*w;
 				weight += w;
 			}
 
@@ -208,7 +197,7 @@ void main()
 				float w = 1.0;
 				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
 				
-				shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap0, lpos, 1.0, pos_screen)*w;
 				weight += w;
 			}
 		
@@ -242,11 +231,11 @@ void main()
 	
 	//spotlight shadow 1
 	vec4 lpos = shadow_matrix[4]*spos;
-	frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen); 
+	frag_color[2] = pcfSpotShadowLegacy(shadowMap4, lpos, 0.8, pos_screen); 
 	
 	//spotlight shadow 2
 	lpos = shadow_matrix[5]*spos;
-	frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen); 
+	frag_color[3] = pcfSpotShadowLegacy(shadowMap5, lpos, 0.8, pos_screen); 
 
 	//frag_color.rgb = pos.xyz;
 	//frag_color.b = shadow;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index fd3256e9c84..10ef1785da3 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file sunLightSSAOF.glsl
+ * @file class2/deferred/sunLightSSAOF.glsl
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
@@ -42,110 +42,33 @@ uniform sampler2DShadow shadowMap2;
 uniform sampler2DShadow shadowMap3;
 uniform sampler2DShadow shadowMap4;
 uniform sampler2DShadow shadowMap5;
-uniform sampler2D noiseMap;
-
-
-// Inputs
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-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;
 uniform vec2 proj_shadow_res;
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
 
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
 uniform vec2 shadow_res;
-
 uniform float shadow_bias;
 uniform float shadow_offset;
-
 uniform float spot_shadow_bias;
 uniform float spot_shadow_offset;
 
-vec3 decode_normal (vec2 enc);
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec2 getKern(int i)
-{
-	vec2 kern[8];
-	// exponentially (^2) distant occlusion samples spread around origin
-	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-       
-	return kern[i];
-}
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
 
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
-	float ret = 1.0;
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
-	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);
+float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen);
+float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen);
 
-	ret = max(ret, 0.0);
-	return min(ret, 1.0);
-}
 
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
+float pcfShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
 	stc.xyz /= stc.w;
 	stc.z += shadow_bias;
@@ -163,7 +86,7 @@ float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
         return shadow*0.2;
 }
 
-float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
+float pcfSpotShadowLegacy(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
 {
 	stc.xyz /= stc.w;
 	stc.z += spot_shadow_bias*scl;
@@ -189,10 +112,8 @@ void main()
 	
 	//try doing an unproject here
 	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
+	vec4 pos  = getPosition(pos_screen);
+	vec3 norm = getNorm(pos_screen);
 		
 	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
 	{
@@ -235,7 +156,7 @@ void main()
 				
 				float w = 1.0;
 				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap3, lpos, 0.25, pos_screen)*w;
 				weight += w;
 				shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
 			}
@@ -247,7 +168,7 @@ void main()
 				float w = 1.0;
 				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
 				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap2, lpos, 0.5, pos_screen)*w;
 				weight += w;
 			}
 
@@ -258,7 +179,7 @@ void main()
 				float w = 1.0;
 				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
 				w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-				shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap1, lpos, 0.75, pos_screen)*w;
 				weight += w;
 			}
 
@@ -269,7 +190,7 @@ void main()
 				float w = 1.0;
 				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
 				
-				shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
+				shadow += pcfShadowLegacy(shadowMap0, lpos, 1.0, pos_screen)*w;
 				weight += w;
 			}
 		
@@ -297,7 +218,7 @@ void main()
 	}
 	
 	frag_color[0] = shadow;
-	frag_color[1] = calcAmbientOcclusion(pos, norm);
+	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
 	
 	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
 	
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 82888b2df6d..00493c83dfd 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -127,7 +127,7 @@ LLDrawPool::LLDrawPool(const U32 type)
 	mType = type;
 	sNumDrawPools++;
 	mId = sNumDrawPools;
-	mVertexShaderLevel = 0;
+	mShaderLevel = 0;
 	mSkipRender = false;
 }
 
@@ -141,7 +141,7 @@ LLViewerTexture *LLDrawPool::getDebugTexture()
 	return NULL;
 }
 
-//virtuals
+//virtual
 void LLDrawPool::beginRenderPass( S32 pass )
 {
 }
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index bc299cc89fa..df86d78a897 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -107,7 +107,7 @@ class LLDrawPool
 	virtual void prerender() = 0;
 	virtual U32 getVertexDataMask() = 0;
 	virtual BOOL verify() const { return TRUE; }		// Verify that all data in the draw pool is correct!
-	virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
+	virtual S32 getShaderLevel() const { return mShaderLevel; }
 	
 	static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
 	virtual LLDrawPool *instancePool() = 0;	// Create an empty new instance of the pool.
@@ -116,7 +116,7 @@ class LLDrawPool
 	virtual void resetDrawOrders() = 0;
 
 protected:
-	S32 mVertexShaderLevel;
+	S32 mShaderLevel;
 	S32	mId;
 	U32 mType;				// Type of draw pool
 	BOOL mSkipRender;
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 7679d44826b..73582e2345a 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -69,7 +69,7 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
 
 void LLDrawPoolAlpha::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 S32 LLDrawPoolAlpha::getNumPostDeferredPasses() 
@@ -160,7 +160,7 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
     }
 
 	deferred_render = TRUE;
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		// Start out with no shaders.
 		current_shader = target_shader = NULL;
@@ -209,7 +209,7 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass)
 		emissive_shader = &gObjectEmissiveProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		// Start out with no shaders.
 		current_shader = target_shader = NULL;
@@ -264,7 +264,7 @@ void LLDrawPoolAlpha::render(S32 pass)
 		mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;       // }
 		gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
 
-		if (mVertexShaderLevel > 0)
+		if (mShaderLevel > 0)
 		{
 			if (LLPipeline::sImpostorRender)
 			{
@@ -326,7 +326,7 @@ void LLDrawPoolAlpha::render(S32 pass)
 		}
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass);
 	}
@@ -432,7 +432,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 			bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE
 													  || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
 
-			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow.
+			bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow.
 
 			
 			LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP);
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index d4dc6f3558a..996c7eed4b6 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -144,16 +144,16 @@ LLDrawPool *LLDrawPoolAvatar::instancePool()
 }
 
 
-S32 LLDrawPoolAvatar::getVertexShaderLevel() const
+S32 LLDrawPoolAvatar::getShaderLevel() const
 {
-	return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
+	return (S32) LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
 }
 
 void LLDrawPoolAvatar::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
 	
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	
 	if (sShaderLevel > 0)
 	{
@@ -304,7 +304,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
 void LLDrawPoolAvatar::beginPostDeferredAlpha()
 {
 	sSkipOpaque = TRUE;
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram = &gDeferredAvatarAlphaProgram;
 	sRenderingSkinned = TRUE;
 
@@ -395,7 +395,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha()
 		
 	gPipeline.unbindDeferredShader(*sVertexProgram);
 	sDiffuseChannel = 0;
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 }
 
 void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
@@ -493,7 +493,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
 	}
 	LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
 
-	if (avatarp->isDead() || avatarp->isUIAvatar() || avatarp->mDrawable.isNull())
+	if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull())
 	{
 		return;
 	}
@@ -714,7 +714,7 @@ void LLDrawPoolAvatar::beginRigid()
 
 void LLDrawPoolAvatar::endRigid()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	if (sVertexProgram != NULL)
 	{
 		sVertexProgram->unbind();
@@ -739,7 +739,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
 
 void LLDrawPoolAvatar::endDeferredImpostor()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
 	sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -766,7 +766,7 @@ void LLDrawPoolAvatar::beginDeferredRigid()
 
 void LLDrawPoolAvatar::endDeferredRigid()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	sVertexProgram->unbind();
 	gGL.getTexUnit(0)->activate();
@@ -848,7 +848,7 @@ void LLDrawPoolAvatar::endSkinned()
 		sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
 		gGL.getTexUnit(0)->activate();
 		sVertexProgram->unbind();
-		sShaderLevel = mVertexShaderLevel;
+		sShaderLevel = mShaderLevel;
 	}
 	else
 	{
@@ -1281,7 +1281,7 @@ void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass)
 
 void LLDrawPoolAvatar::beginDeferredSkinned()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram = &gDeferredAvatarProgram;
 	sRenderingSkinned = TRUE;
 
@@ -1308,7 +1308,7 @@ void LLDrawPoolAvatar::endDeferredSkinned()
 
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 
 	gGL.getTexUnit(0)->activate();
 }
@@ -1820,7 +1820,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
 
 void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 {
-	if (!avatar->shouldRenderRigged())
+	if (avatar->isSelf() && !gAgent.needsRenderAvatar())
 	{
 		return;
 	}
@@ -2196,6 +2196,7 @@ void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
 	{
 		LL_ERRS() << "Invalid rigged face type." << LL_ENDL;
 	}
+
 	if (facep->getRiggedIndex(type) != -1)
 	{
 		LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL;
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 45b6d71110c..82922790420 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -57,7 +57,7 @@ class LLDrawPoolAvatar : public LLFacePool
 
 	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
 
-	virtual S32 getVertexShaderLevel() const;
+	virtual S32 getShaderLevel() const;
 
 	LLDrawPoolAvatar();
     ~LLDrawPoolAvatar();
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index e27b6867b95..14069fa6c2b 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -193,7 +193,7 @@ LLDrawPoolBump::LLDrawPoolBump()
 
 void LLDrawPoolBump::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 // static
@@ -201,7 +201,7 @@ S32 LLDrawPoolBump::numBumpPasses()
 {
 	if (gSavedSettings.getBOOL("RenderObjectBump"))
 	{
-		if (mVertexShaderLevel > 1)
+		if (mShaderLevel > 1)
 		{
 			if (LLPipeline::sImpostorRender)
 			{
@@ -241,7 +241,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass)
 			beginShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				beginFullbrightShiny();
 			}
@@ -274,7 +274,7 @@ void LLDrawPoolBump::render(S32 pass)
 			renderShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				renderFullbrightShiny();
 			}
@@ -301,7 +301,7 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
 			endShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				endFullbrightShiny();
 			}
@@ -335,12 +335,12 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 	mShiny = TRUE;
 	sVertexMask = VERTEX_MASK_SHINY;
 	// Second pass: environment map
-	if (!invisible && mVertexShaderLevel > 1)
+	if (!invisible && mShaderLevel > 1)
 	{
 		sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
 	}
 	
-	if (getVertexShaderLevel() > 0)
+	if (getShaderLevel() > 0)
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
@@ -365,9 +365,9 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 		shader = NULL;
 	}
 
-	bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+	bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
 
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //indexed texture rendering, channel 0 is always diffuse
 		diffuse_channel = 0;
 	}
@@ -436,7 +436,7 @@ void LLDrawPoolBump::renderShiny(bool invisible)
 	if( gSky.mVOSkyp->getCubeMap() )
 	{
 		LLGLEnable blend_enable(GL_BLEND);
-		if (!invisible && mVertexShaderLevel > 1)
+		if (!invisible && mShaderLevel > 1)
 		{
 			LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		}
@@ -461,7 +461,7 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
 		{
 			shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
 					
-			if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
+			if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
 			{
 				if (diffuse_channel != 0)
 				{
@@ -494,7 +494,7 @@ void LLDrawPoolBump::endShiny(bool invisible)
 		return;
 	}
 
-	unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+	unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
 	if (shader)
 	{
 		shader->unbind();
@@ -568,7 +568,7 @@ void LLDrawPoolBump::beginFullbrightShiny()
 		gGL.getTexUnit(0)->activate();
 	}
 
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //indexed texture rendering, channel 0 is always diffuse
 		diffuse_channel = 0;
 	}
@@ -588,7 +588,7 @@ void LLDrawPoolBump::renderFullbrightShiny()
 	{
 		LLGLEnable blend_enable(GL_BLEND);
 
-		if (mVertexShaderLevel > 1)
+		if (mShaderLevel > 1)
 		{
 			LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		}
@@ -1541,7 +1541,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
 			tex_setup = true;
 		}
 
-		if (mShiny && mVertexShaderLevel > 1 && texture)
+		if (mShiny && mShaderLevel > 1 && texture)
 		{
 			if (params.mTexture.notNull())
 			{
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index bae07a171b9..6bd2631d3b2 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -53,7 +53,7 @@ LLDrawPool *LLDrawPoolGround::instancePool()
 
 void LLDrawPoolGround::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
 }
 
 void LLDrawPoolGround::render(S32 pass)
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 113c198a9ab..05b0c1f1a93 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -42,7 +42,7 @@ LLDrawPoolMaterials::LLDrawPoolMaterials()
 
 void LLDrawPoolMaterials::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 
 }
 
 S32 LLDrawPoolMaterials::getNumDeferredPasses()
@@ -203,7 +203,7 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture,
 			tex_setup = true;
 		}
 		
-		if (mVertexShaderLevel > 1 && texture)
+		if (mShaderLevel > 1 && texture)
 		{
 			if (params.mTexture.notNull())
 			{
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index bb50ad8e3e0..f6539206629 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -90,7 +90,7 @@ void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
 
 S32 LLDrawPoolGlow::getNumPasses()
 {
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
 	{
 		return 1;
 	}
@@ -111,7 +111,7 @@ void LLDrawPoolGlow::render(S32 pass)
 	glPolygonOffset(-1.0f, -1.0f);
 	gGL.setSceneBlendType(LLRender::BT_ADD);
 	
-	U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	U32 shader_level = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 
 	//should never get here without basic shaders enabled
 	llassert(shader_level > 0);
@@ -164,7 +164,7 @@ LLDrawPoolSimple::LLDrawPoolSimple() :
 
 void LLDrawPoolSimple::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolSimple::beginRenderPass(S32 pass)
@@ -184,7 +184,7 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
 		simple_shader = &gObjectSimpleProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 
@@ -213,7 +213,7 @@ void LLDrawPoolSimple::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -227,7 +227,7 @@ void LLDrawPoolSimple::render(S32 pass)
 		LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
 		gPipeline.enableLightsDynamic();
 
-		if (mVertexShaderLevel > 0)
+		if (mShaderLevel > 0)
 		{
 			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
 
@@ -270,7 +270,7 @@ LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() :
 
 void LLDrawPoolAlphaMask::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
@@ -286,7 +286,7 @@ void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
 		simple_shader = &gObjectSimpleAlphaMaskProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 
@@ -315,7 +315,7 @@ void LLDrawPoolAlphaMask::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -326,7 +326,7 @@ void LLDrawPoolAlphaMask::render(S32 pass)
 	LLGLDisable blend(GL_BLEND);
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
 	
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 		simple_shader->setMinimumAlpha(0.33f);
@@ -361,7 +361,7 @@ LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() :
 
 void LLDrawPoolFullbrightAlphaMask::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
@@ -377,7 +377,7 @@ void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
 		simple_shader = &gObjectFullbrightAlphaMaskProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 
@@ -406,7 +406,7 @@ void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -416,7 +416,7 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		if (simple_shader)
 		{
@@ -533,7 +533,7 @@ LLDrawPoolGrass::LLDrawPoolGrass() :
 
 void LLDrawPoolGrass::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 
@@ -551,7 +551,7 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
 		simple_shader = &gObjectAlphaMaskNonIndexedProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 		simple_shader->setMinimumAlpha(0.5f);
@@ -580,7 +580,7 @@ void LLDrawPoolGrass::endRenderPass(S32 pass)
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS);
 	LLRenderPass::endRenderPass(pass);
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -643,7 +643,7 @@ LLDrawPoolFullbright::LLDrawPoolFullbright() :
 
 void LLDrawPoolFullbright::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
@@ -711,7 +711,7 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
 
 	stop_glerror();
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		fullbright_shader->unbind();
 	}
@@ -726,7 +726,7 @@ void LLDrawPoolFullbright::render(S32 pass)
 
 	stop_glerror();
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		fullbright_shader->bind();
 		fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 4d4711d7c9b..516302676d8 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -55,7 +55,7 @@ LLDrawPool *LLDrawPoolSky::instancePool()
 
 void LLDrawPoolSky::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); 
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); 
 	gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
 }
 
@@ -75,7 +75,7 @@ void LLDrawPoolSky::render(S32 pass)
 	}
 	
 	// don't render sky under water (background just gets cleared to fog color)
-	if(mVertexShaderLevel > 0 && LLPipeline::sUnderWaterRender)
+	if(mShaderLevel > 0 && LLPipeline::sUnderWaterRender)
 	{
 		return;
 	}
@@ -100,8 +100,8 @@ void LLDrawPoolSky::render(S32 pass)
 
 	LLGLSPipelineDepthTestSkyBox gls_skybox(true, false);
 
-	LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
-
+	LLGLEnable fog_enable( (mShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
+	
 	gGL.pushMatrix();
 	LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
 	gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index b716a765436..593636b14a2 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -110,7 +110,7 @@ U32 LLDrawPoolTerrain::getVertexDataMask()
 
 void LLDrawPoolTerrain::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
 	sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
 }
 
@@ -123,7 +123,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass )
 					&gTerrainWaterProgram :
 					&gTerrainProgram;	
 
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0)
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
 	{
 		sShader->bind();
 	}
@@ -134,7 +134,7 @@ void LLDrawPoolTerrain::endRenderPass( S32 pass )
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN);
 	//LLFacePool::endRenderPass(pass);
 
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) {
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0) {
 		sShader->unbind();
 	}
 }
@@ -180,7 +180,7 @@ void LLDrawPoolTerrain::render(S32 pass)
 
 	LLGLSPipeline gls;
 	
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0)
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
 	{
 		gPipeline.enableLightsDynamic();
 
@@ -434,7 +434,7 @@ void LLDrawPoolTerrain::renderFullShader()
 
 void LLDrawPoolTerrain::hilightParcelOwners()
 {
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //use fullbright shader for highlighting
 		LLGLSLShader* old_shader = sShader;
 		sShader->unbind();
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index b1f40781f73..81b0c8b1bb6 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -57,7 +57,7 @@ LLDrawPool *LLDrawPoolTree::instancePool()
 
 void LLDrawPoolTree::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolTree::beginRenderPass(S32 pass)
@@ -138,7 +138,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass)
 		shader->unbind();
 	}
 	
-	if (mVertexShaderLevel <= 0)
+	if (mShaderLevel <= 0)
 	{
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index d217f95cf36..ee37f36cbd5 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -113,7 +113,7 @@ LLDrawPool *LLDrawPoolWater::instancePool()
 
 void LLDrawPoolWater::prerender()
 {
-	mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
+	mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
 }
 
 S32 LLDrawPoolWater::getNumPasses()
@@ -179,7 +179,7 @@ void LLDrawPoolWater::render(S32 pass)
 
 	LLGLEnable blend(GL_BLEND);
 
-	if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
+	if ((mShaderLevel > 0) && !sSkipScreenCopy)
 	{
 		shade();
 		return;
@@ -618,7 +618,7 @@ void LLDrawPoolWater::shade()
 	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
 	gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);	
 
-	if (mVertexShaderLevel == 1)
+	if (mShaderLevel == 1)
 	{
         LLColor4 fog_color(pwater->getWaterFogColor(), 0.f);
         fog_color[3] = pwater->getWaterFogDensity();
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index e7b47263213..1980ba68780 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -66,7 +66,7 @@ class LLDrawPoolWLSky : public LLDrawPool {
 	/*virtual*/ void prerender();
 	/*virtual*/ U32 getVertexDataMask() { return SKY_VERTEX_DATA_MASK; }
 	/*virtual*/ BOOL verify() const { return TRUE; }		// Verify that all data in the draw pool is correct!
-	/*virtual*/ S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
+	/*virtual*/ S32 getShaderLevel() const { return mShaderLevel; }
 	
 	//static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
 
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 96dd309fa49..49934415080 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -560,7 +560,7 @@ void LLPanelVolume::refresh()
 		mRootObject = NULL;
 	}
 
-	BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
+	BOOL visible = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
 
 	getChildView("Light FOV")->setVisible( visible);
 	getChildView("Light Focus")->setVisible( visible);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 82120db53ee..29b4ab0a244 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -653,7 +653,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		stop_glerror();
 
 		S32 water_clip = 0;
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
 			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || 
 			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
 		{
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 43a81ada495..6990f56a080 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -112,7 +112,7 @@ void LLViewerJointMesh::uploadJointMatrices()
 	S32 joint_num;
 	LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
 	LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
-	BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
+	BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE;
 
 	//calculate joint matrices
 	for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.size(); joint_num++)
@@ -246,7 +246,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 
 	stop_glerror();
 	
-	LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getVertexShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny);
+	LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny);
 
 	//----------------------------------------------------------------
 	// setup current texture
@@ -307,14 +307,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 
 	if (mMesh->hasWeights())
 	{
-		if ((mFace->getPool()->getVertexShaderLevel() > 0))
+		if ((mFace->getPool()->getShaderLevel() > 0))
 		{
 			if (first_pass)
 			{
 				uploadJointMatrices();
 			}
 			mask = mask | LLVertexBuffer::MAP_WEIGHT;
-			if (mFace->getPool()->getVertexShaderLevel() > 1)
+			if (mFace->getPool()->getShaderLevel() > 1)
 			{
 				mask = mask | LLVertexBuffer::MAP_CLOTHWEIGHT;
 			}
@@ -390,7 +390,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
 	}
 
 	LLDrawPool *poolp = mFace->getPool();
-	BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
+	BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE;
 
 	if (!hardware_skinning && terse_update)
 	{ //no need to do terse updates if we're doing software vertex skinning
@@ -538,7 +538,7 @@ void LLViewerJointMesh::updateJointGeometry()
 		  && mFace
 		  && mMesh->hasWeights()
 		  && mFace->getVertexBuffer()
-		  && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
+		  && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
 	{
 		return;
 	}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 00189f0b110..7033fd4d9f5 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -2274,8 +2274,8 @@ class LLAdvancedEnableRenderDeferred: public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
+		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
+			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
 		return new_value;
 	}
 };
@@ -2287,8 +2287,8 @@ class LLAdvancedEnableRenderDeferredOptions: public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");
+		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
+			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");
 		return new_value;
 	}
 };
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index f4f9a3a0c2b..bb3ad4bea60 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -247,7 +247,7 @@ LLGLSLShader			gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
 LLGLSLShader			gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
 
 LLViewerShaderMgr::LLViewerShaderMgr() :
-	mVertexShaderLevel(SHADER_COUNT, 0),
+	mShaderLevel(SHADER_COUNT, 0),
 	mMaxAvatarShaderLevel(0)
 {	
 	/// Make sure WL Sky is the first program
@@ -354,7 +354,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 
 LLViewerShaderMgr::~LLViewerShaderMgr()
 {
-	mVertexShaderLevel.clear();
+	mShaderLevel.clear();
 	mShaderList.clear();
 }
 
@@ -391,9 +391,9 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
 //============================================================================
 // Set Levels
 
-S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type)
+S32 LLViewerShaderMgr::getShaderLevel(S32 type)
 {
-	return LLPipeline::sDisableShaders ? 0 : mVertexShaderLevel[type];
+	return LLPipeline::sDisableShaders ? 0 : mShaderLevel[type];
 }
 
 //============================================================================
@@ -468,7 +468,7 @@ void LLViewerShaderMgr::setShaders()
 
 	for (S32 i = 0; i < SHADER_COUNT; i++)
 	{
-		mVertexShaderLevel[i] = 0;
+		mShaderLevel[i] = 0;
 	}
 	mMaxAvatarShaderLevel = 0;
 
@@ -526,22 +526,22 @@ void LLViewerShaderMgr::setShaders()
 		}
 
 		// Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders
-		if (mVertexShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull())
+		if (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull())
 		{
 			gSky.mVOSkyp->forceSkyUpdate();
 		}
 
 		
 		// Load lighting shaders
-		mVertexShaderLevel[SHADER_LIGHTING] = light_class;
-		mVertexShaderLevel[SHADER_INTERFACE] = light_class;
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class;
-		mVertexShaderLevel[SHADER_WATER] = water_class;
-		mVertexShaderLevel[SHADER_OBJECT] = obj_class;
-		mVertexShaderLevel[SHADER_EFFECT] = effect_class;
-		mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class;
-		mVertexShaderLevel[SHADER_DEFERRED] = deferred_class;
-		mVertexShaderLevel[SHADER_TRANSFORM] = transform_class;
+		mShaderLevel[SHADER_LIGHTING] = light_class;
+		mShaderLevel[SHADER_INTERFACE] = light_class;
+		mShaderLevel[SHADER_ENVIRONMENT] = env_class;
+		mShaderLevel[SHADER_WATER] = water_class;
+		mShaderLevel[SHADER_OBJECT] = obj_class;
+		mShaderLevel[SHADER_EFFECT] = effect_class;
+		mShaderLevel[SHADER_WINDLIGHT] = wl_class;
+		mShaderLevel[SHADER_DEFERRED] = deferred_class;
+		mShaderLevel[SHADER_TRANSFORM] = transform_class;
 
 		BOOL loaded = loadBasicShaders();
         if (loaded)
@@ -646,7 +646,7 @@ void LLViewerShaderMgr::setShaders()
 			if (loaded)
 			{
 				// Load max avatar shaders to set the max level
-				mVertexShaderLevel[SHADER_AVATAR] = 3;
+				mShaderLevel[SHADER_AVATAR] = 3;
 				mMaxAvatarShaderLevel = 3;
 				
 				if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject())
@@ -657,17 +657,18 @@ void LLViewerShaderMgr::setShaders()
 					S32 avatar_class = avatar_cloth ? 3 : 1;
 				
 					// Set the actual level
-					mVertexShaderLevel[SHADER_AVATAR] = avatar_class;
+					mShaderLevel[SHADER_AVATAR] = avatar_class;
+
 					loaded = loadShadersAvatar();
                     llassert(loaded);
 
-					if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class)
+					if (mShaderLevel[SHADER_AVATAR] != avatar_class)
 					{
-						if (mVertexShaderLevel[SHADER_AVATAR] == 0)
+						if (mShaderLevel[SHADER_AVATAR] == 0)
 						{
 							gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
 						}
-						if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3)
+						if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3)
 						{
 							avatar_cloth = true;
 						}
@@ -680,8 +681,8 @@ void LLViewerShaderMgr::setShaders()
 				}
 				else
 				{ //hardware skinning not possible, neither is deferred rendering
-					mVertexShaderLevel[SHADER_AVATAR] = 0;
-					mVertexShaderLevel[SHADER_DEFERRED] = 0;
+					mShaderLevel[SHADER_AVATAR] = 0;
+					mShaderLevel[SHADER_DEFERRED] = 0;
 
 					if (gSavedSettings.getBOOL("RenderAvatarVP"))
 					{
@@ -734,14 +735,14 @@ void LLViewerShaderMgr::setShaders()
 			LLGLSLShader::sNoFixedFunction = false;
 			gPipeline.mVertexShadersEnabled = FALSE;
 			gPipeline.mVertexShadersLoaded = 0;
-			mVertexShaderLevel[SHADER_LIGHTING] = 0;
-			mVertexShaderLevel[SHADER_INTERFACE] = 0;
-			mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-			mVertexShaderLevel[SHADER_WATER] = 0;
-			mVertexShaderLevel[SHADER_OBJECT] = 0;
-			mVertexShaderLevel[SHADER_EFFECT] = 0;
-			mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-			mVertexShaderLevel[SHADER_AVATAR] = 0;
+			mShaderLevel[SHADER_LIGHTING] = 0;
+			mShaderLevel[SHADER_INTERFACE] = 0;
+			mShaderLevel[SHADER_ENVIRONMENT] = 0;
+			mShaderLevel[SHADER_WATER] = 0;
+			mShaderLevel[SHADER_OBJECT] = 0;
+			mShaderLevel[SHADER_EFFECT] = 0;
+			mShaderLevel[SHADER_WINDLIGHT] = 0;
+			mShaderLevel[SHADER_AVATAR] = 0;
 		}
 	}
 	else
@@ -749,14 +750,14 @@ void LLViewerShaderMgr::setShaders()
 		LLGLSLShader::sNoFixedFunction = false;
 		gPipeline.mVertexShadersEnabled = FALSE;
 		gPipeline.mVertexShadersLoaded = 0;
-		mVertexShaderLevel[SHADER_LIGHTING] = 0;
-		mVertexShaderLevel[SHADER_INTERFACE] = 0;
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-		mVertexShaderLevel[SHADER_WATER] = 0;
-		mVertexShaderLevel[SHADER_OBJECT] = 0;
-		mVertexShaderLevel[SHADER_EFFECT] = 0;
-		mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-		mVertexShaderLevel[SHADER_AVATAR] = 0;
+		mShaderLevel[SHADER_LIGHTING] = 0;
+		mShaderLevel[SHADER_INTERFACE] = 0;
+		mShaderLevel[SHADER_ENVIRONMENT] = 0;
+		mShaderLevel[SHADER_WATER] = 0;
+		mShaderLevel[SHADER_OBJECT] = 0;
+		mShaderLevel[SHADER_EFFECT] = 0;
+		mShaderLevel[SHADER_WINDLIGHT] = 0;
+		mShaderLevel[SHADER_AVATAR] = 0;
 	}
 	
 	if (gViewerWindow)
@@ -885,15 +886,15 @@ void LLViewerShaderMgr::unloadShaders()
 	gTransformColorProgram.unload();
 	gTransformTangentProgram.unload();
 
-	mVertexShaderLevel[SHADER_LIGHTING] = 0;
-	mVertexShaderLevel[SHADER_OBJECT] = 0;
-	mVertexShaderLevel[SHADER_AVATAR] = 0;
-	mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-	mVertexShaderLevel[SHADER_WATER] = 0;
-	mVertexShaderLevel[SHADER_INTERFACE] = 0;
-	mVertexShaderLevel[SHADER_EFFECT] = 0;
-	mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-	mVertexShaderLevel[SHADER_TRANSFORM] = 0;
+	mShaderLevel[SHADER_LIGHTING] = 0;
+	mShaderLevel[SHADER_OBJECT] = 0;
+	mShaderLevel[SHADER_AVATAR] = 0;
+	mShaderLevel[SHADER_ENVIRONMENT] = 0;
+	mShaderLevel[SHADER_WATER] = 0;
+	mShaderLevel[SHADER_INTERFACE] = 0;
+	mShaderLevel[SHADER_EFFECT] = 0;
+	mShaderLevel[SHADER_WINDLIGHT] = 0;
+	mShaderLevel[SHADER_TRANSFORM] = 0;
 
 	gPipeline.mVertexShadersLoaded = 0;
 }
@@ -936,16 +937,16 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 	// (in order of shader function call depth for reference purposes, deepest level first)
 
 	vector< pair<string, S32> > shaders;
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",		mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",	mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",	mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
 	shaders.push_back( make_pair( "lighting/sumLightsV.glsl",				sum_lights_class ) );
-	shaders.push_back( make_pair( "lighting/lightV.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl",		mVertexShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "lighting/lightV.glsl",					mShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl",		mShaderLevel[SHADER_LIGHTING] ) );
 	shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl",		sum_lights_class ) );
-	shaders.push_back( make_pair( "lighting/lightSpecularV.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsV.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "lighting/lightSpecularV.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsV.glsl",			mShaderLevel[SHADER_WINDLIGHT] ) );
 	shaders.push_back( make_pair( "avatar/avatarSkinV.glsl",				1 ) );
 	shaders.push_back( make_pair( "avatar/objectSkinV.glsl",				1 ) );
 	if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)
@@ -981,44 +982,44 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 	}
 
 	std::vector<S32> index_channels;    
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/transportF.glsl",				mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/gammaF.glsl",					mVertexShaderLevel[SHADER_WINDLIGHT]) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/waterFogF.glsl",				mVertexShaderLevel[SHADER_WATER] ) );
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/encodeNormF.glsl",				    mVertexShaderLevel[SHADER_ENVIRONMENT] ) );
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/decodeNormF.glsl",				    mVertexShaderLevel[SHADER_ENVIRONMENT] ) );
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/srgbF.glsl",				    mVertexShaderLevel[SHADER_ENVIRONMENT] ) );
-#if USE_DEFERRED_SHADER_API
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/deferredUtil.glsl",				    mVertexShaderLevel[SHADER_DEFERRED] ) );
-    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/indirect.glsl",				    mVertexShaderLevel[SHADER_DEFERRED] ) );
-#endif
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl",		mShaderLevel[SHADER_WINDLIGHT] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl",		mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/gammaF.glsl",					mShaderLevel[SHADER_WINDLIGHT]) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/transportF.glsl",				mShaderLevel[SHADER_WINDLIGHT] ) );	
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/waterFogF.glsl",				mShaderLevel[SHADER_WATER] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/encodeNormF.glsl",				    mShaderLevel[SHADER_ENVIRONMENT] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/decodeNormF.glsl",				    mShaderLevel[SHADER_ENVIRONMENT] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/srgbF.glsl",				    mShaderLevel[SHADER_ENVIRONMENT] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/deferredUtil.glsl",				    mShaderLevel[SHADER_DEFERRED] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/shadowUtil.glsl",				    mShaderLevel[SHADER_DEFERRED] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/aoUtil.glsl",				    mShaderLevel[SHADER_DEFERRED] ) );
+    index_channels.push_back(-1);	 shaders.push_back( make_pair( "deferred/indirect.glsl",				    mShaderLevel[SHADER_DEFERRED] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",					mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl",					mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightF.glsl",					mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl",					mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterF.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyF.glsl",				mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",	mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",			mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
 	
 	for (U32 i = 0; i < shaders.size(); i++)
 	{
@@ -1037,7 +1038,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0)
+	if (mShaderLevel[SHADER_ENVIRONMENT] == 0)
 	{
 		gTerrainProgram.unload();
 		return TRUE;
@@ -1048,21 +1049,24 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
 		gTerrainProgram.mName = "Terrain Shader";
 		gTerrainProgram.mFeatures.calculatesLighting = true;
 		gTerrainProgram.mFeatures.calculatesAtmospherics = true;
-		gTerrainProgram.mFeatures.hasAtmospherics = true;
+        gTerrainProgram.mFeatures.hasAtmospherics = true;
+        gTerrainProgram.mFeatures.hasTransport = true;
+        gTerrainProgram.mFeatures.hasGamma = true;
+        gTerrainProgram.mFeatures.hasSrgb = true;
 		gTerrainProgram.mFeatures.mIndexedTextureChannels = 0;
 		gTerrainProgram.mFeatures.disableTextureIndex = true;
 		gTerrainProgram.mFeatures.hasGamma = true;
 		gTerrainProgram.mShaderFiles.clear();
 		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
 		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
+		gTerrainProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
 		success = gTerrainProgram.createShader(NULL, NULL);
         llassert(success);
 	}
 
 	if (!success)
 	{
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+		mShaderLevel[SHADER_ENVIRONMENT] = 0;
 		return FALSE;
 	}
 	
@@ -1076,7 +1080,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 	BOOL success = TRUE;
 	BOOL terrainWaterSuccess = TRUE;
 
-	if (mVertexShaderLevel[SHADER_WATER] == 0)
+	if (mShaderLevel[SHADER_WATER] == 0)
 	{
 		gWaterProgram.unload();
 		gUnderWaterProgram.unload();
@@ -1095,7 +1099,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
         gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
-		gWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];
+		gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
 		success = gWaterProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1109,7 +1113,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		gUnderWaterProgram.mShaderFiles.clear();
 		gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];        
+		gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];        
 		gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;		
 		success = gUnderWaterProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1128,30 +1132,30 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		gTerrainWaterProgram.mShaderFiles.clear();
 		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
 		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTerrainWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
+		gTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
 		gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, NULL);
         llassert(terrainWaterSuccess);
 	}	
 
 	/// Keep track of water shader levels
-	if (gWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER]
-		|| gUnderWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER])
+	if (gWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER]
+		|| gUnderWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER])
 	{
-		mVertexShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel);
+		mShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel);
 	}
 
 	if (!success)
 	{
-		mVertexShaderLevel[SHADER_WATER] = 0;
+		mShaderLevel[SHADER_WATER] = 0;
 		return FALSE;
 	}
 
 	// if we failed to load the terrain water shaders and we need them (using class2 water),
 	// then drop down to class1 water.
-	if (mVertexShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess)
+	if (mShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess)
 	{
-		mVertexShaderLevel[SHADER_WATER]--;
+		mShaderLevel[SHADER_WATER]--;
 		return loadShadersWater();
 	}
 	
@@ -1164,7 +1168,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_EFFECT] == 0)
+	if (mShaderLevel[SHADER_EFFECT] == 0)
 	{
 		gGlowProgram.unload();
 		gGlowExtractProgram.unload();
@@ -1179,7 +1183,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 		gGlowProgram.mShaderFiles.clear();
 		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+		gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
 		success = gGlowProgram.createShader(NULL, NULL);
 		if (!success)
 		{
@@ -1193,7 +1197,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 		gGlowExtractProgram.mShaderFiles.clear();
 		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+		gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
 		success = gGlowExtractProgram.createShader(NULL, NULL);
 		if (!success)
 		{
@@ -1207,7 +1211,9 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 
 BOOL LLViewerShaderMgr::loadShadersDeferred()
 {
-	if (mVertexShaderLevel[SHADER_DEFERRED] == 0)
+    bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1;
+
+	if (mShaderLevel[SHADER_DEFERRED] == 0)
 	{
 		gDeferredTreeProgram.unload();
 		gDeferredTreeShadowProgram.unload();
@@ -1279,11 +1285,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader";
         gDeferredDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredDiffuseProgram.mFeatures.isDeferred = true;
 		gDeferredDiffuseProgram.mShaderFiles.clear();
 		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDiffuseProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1292,11 +1299,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader";
         gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
+        gDeferredDiffuseAlphaMaskProgram.mFeatures.isDeferred = true;
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1305,10 +1313,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
         gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
+        gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.isDeferred = true;
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1317,10 +1326,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
         gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true;
+        gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.isDeferred = true;
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear();
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1329,10 +1339,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader";
         gDeferredNonIndexedDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredNonIndexedDiffuseProgram.mFeatures.isDeferred = true;
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear();
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1342,10 +1353,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
 		gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true;
         gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredSkinnedDiffuseProgram.mFeatures.isDeferred = true;
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.clear();
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1355,10 +1367,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader";
 		gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true;
         gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = true;
+        gDeferredSkinnedBumpProgram.mFeatures.isDeferred = true;
 		gDeferredSkinnedBumpProgram.mShaderFiles.clear();
 		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1378,15 +1391,18 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
         gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true;
         gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
+        gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true;
+        gDeferredSkinnedAlphaProgram.mFeatures.hasIndirect = true;
+        gDeferredSkinnedAlphaProgram.mFeatures.isDeferred = true;
 
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
 		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1");
 		gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
 		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
 		llassert(success);
 
@@ -1399,10 +1415,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredBumpProgram.mName = "Deferred Bump Shader";
         gDeferredBumpProgram.mFeatures.encodesNormal = true;
+        gDeferredBumpProgram.mFeatures.isDeferred = true;
 		gDeferredBumpProgram.mShaderFiles.clear();
 		gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredBumpProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1436,21 +1453,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialProgram[i].mShaderFiles.clear();
 			gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
 			gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gDeferredMaterialProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+			gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 			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", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+			gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", use_sun_shadow ? "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;
+            gDeferredMaterialProgram[i].mFeatures.isDeferred = true;
 
 			if (has_skin)
 			{
@@ -1470,25 +1490,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialWaterProgram[i].mShaderFiles.clear();
 			gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
 			gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gDeferredMaterialWaterProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+			gDeferredMaterialWaterProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 			gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER;
 
 			gDeferredMaterialWaterProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0");
 			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0");
 			gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
-			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", use_sun_shadow ? "1" : "0");
 			bool has_skin = i & 0x10;
 			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0");
 			gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1");
 
 			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.hasTransport = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasShadows = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasIndirect = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.isDeferred = true;
 
 			if (has_skin)
 			{
@@ -1524,9 +1548,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredTreeProgram.mName = "Deferred Tree Shader";
 		gDeferredTreeProgram.mShaderFiles.clear();
         gDeferredTreeProgram.mFeatures.encodesNormal = true;
+        gDeferredTreeProgram.mFeatures.isDeferred = true;
 		gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredTreeProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1535,9 +1560,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader";
 		gDeferredTreeShadowProgram.mShaderFiles.clear();
+        gDeferredTreeShadowProgram.mFeatures.isDeferred = true;
 		gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredTreeShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredTreeShadowProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1548,10 +1574,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredImpostorProgram.mFeatures.hasSrgb = true;
         gDeferredImpostorProgram.mFeatures.decodesNormal = true;
         gDeferredImpostorProgram.mFeatures.encodesNormal = true;
+        //gDeferredImpostorProgram.mFeatures.isDeferred = true;
 		gDeferredImpostorProgram.mShaderFiles.clear();
 		gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredImpostorProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1560,10 +1587,13 @@ 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));
-		gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredLightProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1575,10 +1605,13 @@ 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));
-			gDeferredMultiLightProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+			gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 			gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1));
 			success = gDeferredMultiLightProgram[i].createShader(NULL, NULL);
             llassert(success);
@@ -1591,9 +1624,12 @@ 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];
+		gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredSpotLightProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1604,10 +1640,13 @@ 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));
-		gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1618,14 +1657,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		std::string fragment;
 		std::string vertex = "deferred/sunLightV.glsl";
 
-		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
+        bool use_ao = gSavedSettings.getBOOL("RenderDeferredSSAO");
+
+		if (use_ao)
 		{
 			fragment = "deferred/sunLightSSAOF.glsl";
 		}
 		else
 		{
 			fragment = "deferred/sunLightF.glsl";
-			if (mVertexShaderLevel[SHADER_DEFERRED] == 1)
+			if (mShaderLevel[SHADER_DEFERRED] == 1)
 			{ //no shadows, no SSAO, no frag coord
 				vertex = "deferred/sunLightNoFragCoordV.glsl";
 			}
@@ -1633,10 +1674,15 @@ 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.mFeatures.hasAmbientOcclusion = use_ao;
+
 		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));
-		gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredSunProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1646,10 +1692,12 @@ 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));
-		gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredBlurLightProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1664,13 +1712,17 @@ 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)
+		if (mShaderLevel[SHADER_DEFERRED] < 1)
 		{
 			gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		}
@@ -1683,9 +1735,9 @@ 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", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+		gDeferredAlphaProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
 		gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAlphaProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1705,8 +1757,12 @@ 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)
+		if (mShaderLevel[SHADER_DEFERRED] < 1)
 		{
 			gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		}
@@ -1719,11 +1775,11 @@ 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", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+		gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
 		gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1");
 		gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1");
 
-		gDeferredAlphaImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAlphaImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1742,13 +1798,17 @@ 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.hasTransport = true;
+        gDeferredAlphaWaterProgram.mFeatures.isDeferred = true;
+        gDeferredAlphaWaterProgram.mFeatures.hasShadows = true;
+        gDeferredAlphaWaterProgram.mFeatures.hasIndirect = true;
 
-		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
+		if (mShaderLevel[SHADER_DEFERRED] < 1)
 		{
 			gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		}
@@ -1763,8 +1823,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1");
 		gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1");
 		gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAlphaWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", use_sun_shadow ? "1" : "0");
+		gDeferredAlphaWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAlphaWaterProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1783,11 +1843,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true;
         gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true;
         gDeferredAvatarEyesProgram.mFeatures.encodesNormal = true;
-        gDeferredAvatarEyesProgram.mFeatures.hasGamma = true;
+        gDeferredAvatarEyesProgram.mFeatures.isDeferred = true;
+        gDeferredAvatarEyesProgram.mFeatures.hasShadows = 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));
-		gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarEyesProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1799,12 +1861,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightProgram.mFeatures.hasGamma = true;
+        gDeferredFullbrightProgram.mFeatures.isDeferred = true;
+
 		gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightProgram.mShaderFiles.clear();
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1816,13 +1879,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true;
+        gDeferredFullbrightAlphaMaskProgram.mFeatures.isDeferred = true;
+
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1");
-		gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1835,12 +1899,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightWaterProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightWaterProgram.mFeatures.hasGamma = true;
+        gDeferredFullbrightWaterProgram.mFeatures.isDeferred = true;
 		gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1");
 		success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL);
@@ -1855,12 +1919,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasTransport = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasSrgb = true;
-        gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasGamma = true;
+        gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.isDeferred = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1");
 		gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1");
@@ -1874,11 +1938,12 @@ 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));
 		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1892,10 +1957,11 @@ 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));
-		gDeferredSkinnedFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gDeferredSkinnedFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1908,10 +1974,11 @@ 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));
-		gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1922,11 +1989,12 @@ 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));
 		gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredEmissiveProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1939,10 +2007,14 @@ 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));
-		gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
         gDeferredWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gDeferredWaterProgram.createShader(NULL, NULL);
         llassert(success);
@@ -1958,10 +2030,14 @@ 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));
-		gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredUnderWaterProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -1974,18 +2050,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSoftenProgram.mFeatures.decodesNormal = true;
         gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredSoftenProgram.mFeatures.hasAtmospherics = true;
-        gDeferredSoftenProgram.mFeatures.hasGamma = 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];
+        gDeferredSoftenProgram.mShaderLevel = mShaderLevel[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);
@@ -1998,7 +2085,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
 
-		gDeferredSoftenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredSoftenWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        
 		gDeferredSoftenWaterProgram.addPermutation("WATER_FOG", "1");
 		gDeferredSoftenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		gDeferredSoftenWaterProgram.mFeatures.hasWaterFog = true;
@@ -2006,8 +2094,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
         gDeferredSoftenWaterProgram.mFeatures.decodesNormal = true;
         gDeferredSoftenWaterProgram.mFeatures.calculatesAtmospherics = true;
         gDeferredSoftenWaterProgram.mFeatures.hasAtmospherics = true;
-        gDeferredSoftenWaterProgram.mFeatures.hasGamma = 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 (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
@@ -2021,10 +2117,11 @@ 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));
-		gDeferredShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
 		success = gDeferredShadowProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2033,11 +2130,12 @@ 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));
 		gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredShadowCubeProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2046,11 +2144,12 @@ 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));
 		gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredShadowAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2059,11 +2158,12 @@ 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));
 		gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2072,11 +2172,12 @@ 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));
 		gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2085,10 +2186,11 @@ 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));
-		gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredTerrainProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2098,10 +2200,11 @@ 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));
-		gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2121,14 +2224,20 @@ 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));
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
 		gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1");
-		gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        if (use_sun_shadow)
+        {
+		    gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", "1");
+        }
+		gDeferredAvatarAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2141,10 +2250,11 @@ 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));
-		gDeferredPostGammaCorrectProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2152,10 +2262,11 @@ 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));
-		gFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gFXAAProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2163,10 +2274,11 @@ 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));
-		gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2177,7 +2289,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredCoFProgram.mShaderFiles.clear();
 		gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredCoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredCoFProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2185,10 +2297,11 @@ 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));
-		gDeferredDoFCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDoFCombineProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2196,10 +2309,11 @@ 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));
-		gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2212,10 +2326,17 @@ 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];
+        gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        if (gAtmosphere && gDeferredWLSkyProgram.mShaderLevel > 2)
+        {
+            gDeferredWLSkyProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink();
+        }
 		success = gDeferredWLSkyProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2227,10 +2348,17 @@ 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];
+		gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        if (gAtmosphere && gDeferredWLCloudProgram.mShaderLevel > 2)
+        {
+            gDeferredWLCloudProgram.mExtraLinkObject = gAtmosphere->getAtmosphericShaderForLink();
+        }
 		success = gDeferredWLCloudProgram.createShader(NULL, NULL);
         llassert(success);
 	}
@@ -2244,10 +2372,11 @@ 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));
-		gDeferredWLSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gDeferredWLSunProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2262,10 +2391,12 @@ 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));
-		gDeferredWLMoonProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gDeferredWLMoonProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2274,10 +2405,11 @@ 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));
-		gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gDeferredStarProgram.createShader(NULL, NULL);
         llassert(success);
@@ -2286,10 +2418,11 @@ 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));
-		gNormalMapGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gNormalMapGenProgram.createShader(NULL, NULL);
 	}
@@ -2301,7 +2434,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 {
 	BOOL success = TRUE;
 	
-	if (mVertexShaderLevel[SHADER_OBJECT] == 0)
+	if (mShaderLevel[SHADER_OBJECT] == 0)
 	{
 		gObjectShinyProgram.unload();
 		gObjectFullbrightShinyProgram.unload();
@@ -2366,7 +2499,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL);
 	}
 	
@@ -2382,7 +2515,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL);
 	}
 	
@@ -2399,7 +2532,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2416,7 +2549,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL);
 	}
@@ -2434,7 +2567,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL);
 	}
 	
@@ -2451,7 +2584,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2469,7 +2602,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL);
 	}
 	
@@ -2486,7 +2619,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL);
 	}
@@ -2504,7 +2637,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gTreeProgram.mShaderFiles.clear();
 		gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gTreeProgram.createShader(NULL, NULL);
 	}
 	
@@ -2521,7 +2654,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gTreeWaterProgram.mShaderFiles.clear();
 		gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTreeWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gTreeWaterProgram.createShader(NULL, NULL);
 	}
@@ -2538,7 +2671,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.clear();
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2554,7 +2687,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2571,7 +2704,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.clear();
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2586,7 +2719,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2603,7 +2736,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNoColorProgram.mShaderFiles.clear();
 		gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL);
 	}
 
@@ -2618,7 +2751,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL);
 	}
@@ -2635,7 +2768,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyNonIndexedProgram.mShaderFiles.clear();
 		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
-		gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2651,7 +2784,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
-		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2668,7 +2801,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2685,7 +2818,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2698,7 +2831,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gImpostorProgram.mShaderFiles.clear();
 		gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB));
 		gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gImpostorProgram.createShader(NULL, NULL);
 	}
 
@@ -2715,7 +2848,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectPreviewProgram.mShaderFiles.clear();
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectPreviewProgram.createShader(NULL, NULL);
 		gObjectPreviewProgram.mFeatures.hasLighting = true;
 	}
@@ -2732,7 +2865,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleProgram.mShaderFiles.clear();
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleProgram.createShader(NULL, NULL);
 	}
 
@@ -2752,7 +2885,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleImpostorProgram.mShaderFiles.clear();
 		gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		
 		success = gObjectSimpleImpostorProgram.createShader(NULL, NULL);
 	}
@@ -2769,7 +2902,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterProgram.mShaderFiles.clear();
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleWaterProgram.createShader(NULL, NULL);
 	}
@@ -2787,7 +2920,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectBumpProgram.mShaderFiles.clear();
 		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectBumpProgram.createShader(NULL, NULL);
 		if (success)
 		{ //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1
@@ -2812,7 +2945,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.clear();
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
@@ -2829,7 +2962,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear();
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL);
 	}
@@ -2846,7 +2979,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightProgram.mShaderFiles.clear();
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightProgram.createShader(NULL, NULL);
 	}
 
@@ -2861,7 +2994,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightWaterProgram.createShader(NULL, NULL);
 	}
@@ -2878,7 +3011,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveProgram.mShaderFiles.clear();
 		gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectEmissiveProgram.createShader(NULL, NULL);
 	}
 
@@ -2893,7 +3026,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveWaterProgram.mShaderFiles.clear();
 		gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectEmissiveWaterProgram.createShader(NULL, NULL);
 	}
@@ -2911,7 +3044,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear();
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
@@ -2927,7 +3060,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear();
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL);
 	}
@@ -2944,7 +3077,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyProgram.mShaderFiles.clear();
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
-		gObjectShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectShinyProgram.createShader(NULL, NULL);
 	}
 
@@ -2960,7 +3093,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyWaterProgram.mShaderFiles.clear();
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
-		gObjectShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectShinyWaterProgram.createShader(NULL, NULL);
 	}
@@ -2977,7 +3110,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightShinyProgram.createShader(NULL, NULL);
 	}
 
@@ -2994,12 +3127,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
 	}
 
-	if (mVertexShaderLevel[SHADER_AVATAR] > 0)
+	if (mShaderLevel[SHADER_AVATAR] > 0)
 	{ //load hardware skinned attachment shaders
 		if (success)
 		{
@@ -3015,7 +3148,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL);
 		}
 
@@ -3033,7 +3166,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL);
 		}
 
@@ -3050,7 +3183,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectEmissiveProgram.mShaderFiles.clear();
 			gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL);
 		}
 
@@ -3067,7 +3200,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -3085,7 +3218,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL);
 		}
 
@@ -3103,7 +3236,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL);
 		}
 
@@ -3124,7 +3257,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -3143,7 +3276,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -3163,7 +3296,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -3183,14 +3316,14 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL);
 		}
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_OBJECT] = 0;
+		mShaderLevel[SHADER_OBJECT] = 0;
 		return FALSE;
 	}
 	
@@ -3201,7 +3334,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_AVATAR] == 0)
+	if (mShaderLevel[SHADER_AVATAR] == 0)
 	{
 		gAvatarProgram.unload();
 		gAvatarWaterProgram.unload();
@@ -3224,7 +3357,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarProgram.mShaderFiles.clear();
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarProgram.createShader(NULL, NULL);
 			
 		if (success)
@@ -3242,15 +3375,15 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 			// Note: no cloth under water:
-			gAvatarWaterProgram.mShaderLevel = llmin(mVertexShaderLevel[SHADER_AVATAR], 1);	
+			gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1);	
 			gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;				
 			success = gAvatarWaterProgram.createShader(NULL, NULL);
 		}
 
 		/// Keep track of avatar levels
-		if (gAvatarProgram.mShaderLevel != mVertexShaderLevel[SHADER_AVATAR])
+		if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR])
 		{
-			mMaxAvatarShaderLevel = mVertexShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel;
+			mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel;
 		}
 	}
 
@@ -3262,7 +3395,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarPickProgram.mShaderFiles.clear();
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarPickProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarPickProgram.createShader(NULL, NULL);
 	}
 
@@ -3280,13 +3413,13 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarEyeballProgram.mShaderFiles.clear();
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarEyeballProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarEyeballProgram.createShader(NULL, NULL);
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_AVATAR] = 0;
+		mShaderLevel[SHADER_AVATAR] = 0;
 		mMaxAvatarShaderLevel = 0;
 		return FALSE;
 	}
@@ -3298,7 +3431,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_INTERFACE] == 0)
+	if (mShaderLevel[SHADER_INTERFACE] == 0)
 	{
 		gHighlightProgram.unload();
 		return TRUE;
@@ -3310,7 +3443,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightProgram.mShaderFiles.clear();
 		gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gHighlightProgram.createShader(NULL, NULL);
 	}
 
@@ -3320,7 +3453,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightNormalProgram.mShaderFiles.clear();
 		gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gHighlightNormalProgram.createShader(NULL, NULL);
 	}
 
@@ -3330,7 +3463,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightSpecularProgram.mShaderFiles.clear();
 		gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gHighlightSpecularProgram.createShader(NULL, NULL);
 	}
 
@@ -3340,7 +3473,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gUIProgram.mShaderFiles.clear();
 		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB));
 		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gUIProgram.createShader(NULL, NULL);
 	}
 
@@ -3350,7 +3483,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gPathfindingProgram.mShaderFiles.clear();
 		gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB));
 		gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gPathfindingProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gPathfindingProgram.createShader(NULL, NULL);
 	}
 
@@ -3360,7 +3493,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gPathfindingNoNormalsProgram.mShaderFiles.clear();
 		gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB));
 		gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gPathfindingNoNormalsProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gPathfindingNoNormalsProgram.createShader(NULL, NULL);
 	}
 
@@ -3370,7 +3503,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gCustomAlphaProgram.mShaderFiles.clear();
 		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gCustomAlphaProgram.createShader(NULL, NULL);
 	}
 
@@ -3380,7 +3513,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gSplatTextureRectProgram.mShaderFiles.clear();
 		gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB));
 		gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gSplatTextureRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gSplatTextureRectProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3396,7 +3529,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gGlowCombineProgram.mShaderFiles.clear();
 		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gGlowCombineProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3413,7 +3546,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gGlowCombineFXAAProgram.mShaderFiles.clear();
 		gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowCombineFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gGlowCombineFXAAProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3431,7 +3564,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gTwoTextureAddProgram.mShaderFiles.clear();
 		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB));
 		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gTwoTextureAddProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3448,7 +3581,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gTwoTextureCompareProgram.mShaderFiles.clear();
 		gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB));
 		gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTwoTextureCompareProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gTwoTextureCompareProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3465,7 +3598,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOneTextureFilterProgram.mShaderFiles.clear();
 		gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB));
 		gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOneTextureFilterProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3481,7 +3614,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOneTextureNoColorProgram.mShaderFiles.clear();
 		gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB));
 		gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOneTextureNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOneTextureNoColorProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3496,7 +3629,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gSolidColorProgram.mShaderFiles.clear();
 		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB));
 		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gSolidColorProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3512,7 +3645,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOcclusionProgram.mShaderFiles.clear();
 		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB));
 		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOcclusionProgram.createShader(NULL, NULL);
 	}
 
@@ -3522,7 +3655,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOcclusionCubeProgram.mShaderFiles.clear();
 		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB));
 		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOcclusionCubeProgram.createShader(NULL, NULL);
 	}
 
@@ -3532,7 +3665,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDebugProgram.mShaderFiles.clear();
 		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB));
 		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDebugProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDebugProgram.createShader(NULL, NULL);
 	}
 
@@ -3542,7 +3675,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gClipProgram.mShaderFiles.clear();
 		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB));
 		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gClipProgram.createShader(NULL, NULL);
 	}
 
@@ -3552,7 +3685,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDownsampleDepthProgram.mShaderFiles.clear();
 		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
 		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDownsampleDepthProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDownsampleDepthProgram.createShader(NULL, NULL);
 	}
 
@@ -3562,7 +3695,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gBenchmarkProgram.mShaderFiles.clear();
 		gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB));
 		gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gBenchmarkProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gBenchmarkProgram.createShader(NULL, NULL);
 	}
 
@@ -3572,7 +3705,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDownsampleDepthRectProgram.mShaderFiles.clear();
 		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
 		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
 	}
 
@@ -3582,13 +3715,13 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gAlphaMaskProgram.mShaderFiles.clear();
 		gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB));
 		gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_INTERFACE] = 0;
+		mShaderLevel[SHADER_INTERFACE] = 0;
 		return FALSE;
 	}
 	
@@ -3599,7 +3732,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_WINDLIGHT] < 2)
+	if (mShaderLevel[SHADER_WINDLIGHT] < 2)
 	{
 		gWLSkyProgram.unload();
 		gWLCloudProgram.unload();
@@ -3629,7 +3762,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
         gWLSkyProgram.mFeatures.hasGamma = true;
 		gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB));
 		gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+		gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gWLSkyProgram.createShader(NULL, NULL);
 	}
@@ -3644,7 +3777,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
         gWLCloudProgram.mFeatures.hasGamma = true;
 		gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
 		gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+		gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gWLCloudProgram.createShader(NULL, NULL);
 	}
@@ -3662,7 +3795,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 		gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
 		gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+		gWLSunProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gWLSunProgram.createShader(NULL, NULL);
 	}
@@ -3680,7 +3813,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 		gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonV.glsl", GL_VERTEX_SHADER_ARB));
 		gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLMoonProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
+		gWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
 		gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gWLMoonProgram.createShader(NULL, NULL);
 	}
@@ -3692,7 +3825,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 {
 	BOOL success = TRUE;
 	
-	if (mVertexShaderLevel[SHADER_TRANSFORM] < 1)
+	if (mShaderLevel[SHADER_TRANSFORM] < 1)
 	{
 		gTransformPositionProgram.unload();
 		gTransformTexCoordProgram.unload();
@@ -3707,7 +3840,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformPositionProgram.mName = "Position Transform Shader";
 		gTransformPositionProgram.mShaderFiles.clear();
 		gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"position_out",
@@ -3722,7 +3855,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformTexCoordProgram.mName = "TexCoord Transform Shader";
 		gTransformTexCoordProgram.mShaderFiles.clear();
 		gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"texcoord_out",
@@ -3736,7 +3869,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformNormalProgram.mName = "Normal Transform Shader";
 		gTransformNormalProgram.mShaderFiles.clear();
 		gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"normal_out",
@@ -3750,7 +3883,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformColorProgram.mName = "Color Transform Shader";
 		gTransformColorProgram.mShaderFiles.clear();
 		gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"color_out",
@@ -3764,7 +3897,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformTangentProgram.mName = "Binormal Transform Shader";
 		gTransformTangentProgram.mShaderFiles.clear();
 		gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformTangentProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"tangent_out",
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 250f8f1ee39..ac2cfc11600 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -48,7 +48,7 @@ class LLViewerShaderMgr: public LLShaderMgr
 	void initAttribsAndUniforms(void);
 	void setShaders();
 	void unloadShaders();
-	S32 getVertexShaderLevel(S32 type);
+    S32  getShaderLevel(S32 type);
 	BOOL loadBasicShaders();
 	BOOL loadShadersEffects();
 	BOOL loadShadersDeferred();
@@ -60,7 +60,7 @@ class LLViewerShaderMgr: public LLShaderMgr
 	BOOL loadShadersWindLight();
 	BOOL loadTransformShaders();
 
-	std::vector<S32> mVertexShaderLevel;
+	std::vector<S32> mShaderLevel;
 	S32	mMaxAvatarShaderLevel;
 
 	enum EShaderClass
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 321f774210e..cc030dfb604 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2950,7 +2950,7 @@ void LLVOAvatar::idleUpdateLoadingEffect()
 void LLVOAvatar::idleUpdateWindEffect()
 {
 	// update wind effect
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
+	if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
 	{
 		F32 hover_strength = 0.f;
 		F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast;
@@ -4651,7 +4651,7 @@ U32 LLVOAvatar::renderSkinned()
 		}
 	}
 
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
 	{
 		if (mNeedsSkin)
 		{
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index d30bb260e1a..af078251b30 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -1074,7 +1074,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	if (mFace[FACE_REFLECTION] == NULL)
 	{
 		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
-		if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0)
+		if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0)
 		{
 			mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
 		}
@@ -1177,7 +1177,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	}
 	
     bool above_water = (height_above_water > 0);
-    bool render_ref  = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
+    bool render_ref  = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() == 0;
     setDrawRefl(above_water ? (sun_flag ? 0 : 1) : -1);
     if (render_ref)
 	{        
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0b1f1df4c8e..2c9f6f02dc8 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5859,7 +5859,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE;
 	}
 
-	BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+	BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
 
 	if (batch_textures)
 	{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index cd2146ab4e0..d56350f7052 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1422,7 +1422,7 @@ bool LLPipeline::canUseVertexShaders()
 
 bool LLPipeline::canUseWindLightShaders() const
 {
-    bool usingWindlight = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1;
+    bool usingWindlight = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1;
     bool haveShaders    = ((gWLSkyProgram.mProgramObject != 0) || (gDeferredWLSkyProgram.mProgramObject != 0));
 	return (!LLPipeline::sDisableShaders && haveShaders && usingWindlight);
 }
@@ -1430,7 +1430,7 @@ bool LLPipeline::canUseWindLightShaders() const
 bool LLPipeline::canUseWindLightShadersOnObjects() const
 {
 	return (canUseWindLightShaders() 
-		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
+		&& LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
 }
 
 bool LLPipeline::canUseAntiAliasing() const
@@ -4244,7 +4244,7 @@ void LLPipeline::renderHighlights()
 		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
 	}
 
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+	if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 	{
 		gHighlightProgram.bind();
 		gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4291,7 +4291,7 @@ void LLPipeline::renderHighlights()
 	// have touch-handlers.
 	mHighlightFaces.clear();
 
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
 	{
 		gHighlightProgram.unbind();
 	}
@@ -4300,7 +4300,7 @@ void LLPipeline::renderHighlights()
 	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP))
 	{
 		color.setVec(1.0f, 0.5f, 0.5f, 0.5f);
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightNormalProgram.bind();
 			gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4321,7 +4321,7 @@ void LLPipeline::renderHighlights()
 			facep->renderSelected(mFaceSelectImagep, color);
 		}
 
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightNormalProgram.unbind();
 		}
@@ -4330,7 +4330,7 @@ void LLPipeline::renderHighlights()
 	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP))
 	{
 		color.setVec(0.0f, 0.3f, 1.0f, 0.8f);
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightSpecularProgram.bind();
 			gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4351,7 +4351,7 @@ void LLPipeline::renderHighlights()
 			facep->renderSelected(mFaceSelectImagep, color);
 		}
 
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightSpecularProgram.unbind();
 		}
-- 
GitLab