diff --git a/autobuild.xml b/autobuild.xml
index 36e22079804641e8cd0a0fcf873a2e60655a0235..11c2da52dc25642bda3b04818f32043b2749004a 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -762,9 +762,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>af42ebf504bf1cbe6032c34e87270b10</string>
+              <string>21babc394dbf8572830f2e85adec7b9f</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-google-breakpad-graham/rev/272414/arch/Darwin/installer/google_breakpad-0.0.0-rev1099-darwin-20130321.tar.bz2</string>
+              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20110202.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
@@ -774,9 +774,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-	      <string>f38026d0e0b19d20cf11572d06c5332f</string>
+              <string>204b02a9480c411232255798839431a2</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-google-breakpad-graham/rev/272414/arch/Linux/installer/google_breakpad-0.0.0-rev1099-linux-20130321.tar.bz2</string>
+              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-linux-20110311.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
@@ -786,9 +786,9 @@
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>a30bc071ec5cc086c58307211a44ac36</string>
+              <string>627c51136e14e64c5d39933f3abd3bdf</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-google-breakpad-graham/rev/272414/arch/CYGWIN/installer/google_breakpad-0.0.0-rev1099-windows-20130320.tar.bz2</string>
+              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-windows-20110218.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp
index f6fd8e557a8a911179a465adc4f4b96dd6550145..7d1ce4ab86d11aaec2905f05dfaa21471f452a6d 100644
--- a/indra/llprimitive/llmaterial.cpp
+++ b/indra/llprimitive/llmaterial.cpp
@@ -181,3 +181,36 @@ bool LLMaterial::operator != (const LLMaterial& rhs) const
 {
 	return !(*this == rhs);
 }
+
+
+U32 LLMaterial::getShaderMask()
+{ //NEVER incorporate this value into the message system -- this function will vary depending on viewer implementation
+	U32 ret = 0;
+
+	//two least significant bits are "diffuse alpha mode"
+	ret = getDiffuseAlphaMode();
+
+	llassert(ret < SHADER_COUNT);
+
+	//next bit is whether or not specular map is present
+	const U32 SPEC_BIT = 0x4;
+
+	if (getSpecularID().notNull())
+	{
+		ret |= SPEC_BIT;
+	}
+
+	llassert(ret < SHADER_COUNT);
+	
+	//next bit is whether or not normal map is present
+	const U32 NORM_BIT = 0x8;
+	if (getNormalID().notNull())
+	{
+		ret |= NORM_BIT;
+	}
+
+	llassert(ret < SHADER_COUNT);
+
+	return ret;
+}
+
diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h
index 5b56d11cd2cad1b7bdbe78c7f914b0a579e0cdd0..fd35045e457aaa5ce2658845e9232c9d04fffa98 100644
--- a/indra/llprimitive/llmaterial.h
+++ b/indra/llprimitive/llmaterial.h
@@ -36,6 +36,20 @@
 class LLMaterial
 {
 public:
+
+	typedef enum
+	{
+		DIFFUSE_ALPHA_MODE_NONE = 0,
+		DIFFUSE_ALPHA_MODE_BLEND = 1,
+		DIFFUSE_ALPHA_MODE_MASK = 2,
+		DIFFUSE_ALPHA_MODE_EMISSIVE = 3
+	} eDiffuseAlphaMode;
+
+	typedef enum
+	{
+		SHADER_COUNT = 16
+	} eShaderCount;
+	
 	LLMaterial();
 	LLMaterial(const LLSD& material_data);
 
@@ -77,6 +91,8 @@ class LLMaterial
 	bool		operator == (const LLMaterial& rhs) const;
 	bool		operator != (const LLMaterial& rhs) const;
 
+	U32			getShaderMask();
+
 protected:
 	LLUUID		mNormalID;
 	F32			mNormalOffsetX;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index ef04ef5ce66c3612adf9a902c354f664612a65c6..dd87ddb330edbfa39b2a079b1b57b603e2c43cbc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -59,7 +59,6 @@ void main()
 	vec4 pos = vec4(vary_position, 1.0);
 	
 	vec4 diff= diffuseLookup(vary_texcoord0.xy);
-	diff.rgb = pow(diff.rgb, vec3(2.2));
 
 	vec4 col = vec4(vary_ambient + vary_directional.rgb, vertex_color.a);
 	vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index aaf1e5e572229186969c414811f5775353d0110c..a8877284937978482b52334378ae026ccfbea9b8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -48,7 +48,7 @@ void main()
 			  dot(norm,vary_mat1),
 			  dot(norm,vary_mat2));
 						
-	frag_data[0] = vec4(col * (1 - vertex_color.a), 0.0);
+	frag_data[0] = vec4(col, 0.0);
 	frag_data[1] = vertex_color.aaaa; // spec
 	//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
 	vec3 nvn = normalize(tnorm);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 85f28f68c061a90d9b646019ce96dfd46b371f59..2e456d00ddf30e6085f8c81b54685c732cac2536 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -38,7 +38,7 @@ VARYING vec2 vary_texcoord0;
 void main() 
 {
 	vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb;
-	frag_data[0] = vec4(col * (1 - vertex_color.a), 0.0);
+	frag_data[0] = vec4(col, 0.0);
 	frag_data[1] = vertex_color.aaaa; // spec
 	//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
 	vec3 nvn = normalize(vary_normal);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index 6b5a922c294e2b4d0a5d82b4ab09d87246848ad8..bb6dc9a57d05fea7ada290af91509cb6974bf486 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -37,7 +37,7 @@ void main()
 {
 	vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
 
-	frag_data[0] = vec4(col * (1 - vertex_color.a), 0.0);
+	frag_data[0] = vec4(col, 0.0);
 	frag_data[1] = vertex_color.aaaa; // spec
 	//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
 	vec3 nvn = normalize(vary_normal);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 4f7fc6a411be097660d72a4ec21fa8b4ee8624f8..5392466b25407a1d5bc5bad413c5f490857406ab 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -23,6 +23,12 @@
  * $/LicenseInfo$
  */
  
+#define DIFFUSE_ALPHA_MODE_IGNORE 0
+#define DIFFUSE_ALPHA_MODE_BLEND 1
+#define DIFFUSE_ALPHA_MODE_MASK 2
+#define DIFFUSE_ALPHA_MODE_GLOW 3
+
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -31,36 +37,52 @@ out vec4 frag_data[3];
 
 uniform sampler2D diffuseMap;
 
+#if HAS_NORMAL_MAP
 uniform sampler2D bumpMap;
+#endif
 
+#if HAS_SPECULAR_MAP
 uniform sampler2D specularMap;
 uniform float env_intensity;
+#endif
+
 uniform vec4 specular_color;
 
-#ifdef ALPHA_TEST
+#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK
 uniform float minimum_alpha;
 #endif
 
+#if HAS_NORMAL_MAP
 VARYING vec3 vary_mat0;
 VARYING vec3 vary_mat1;
 VARYING vec3 vary_mat2;
+#else
+VARYING vec3 vary_normal;
+#endif
 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
+
 void main() 
 {
-	vec4 col = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color;
+	vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
+	col.rgb *= vertex_color.rgb;
 
-	#ifdef ALPHA_TEST
+#if DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK
 	if (col.a < minimum_alpha)
 	{
 		discard;
 	}
-	#endif
-	
+#endif
+
+#if HAS_SPECULAR_MAP
 	vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
+#else
+	vec4 spec = specular_color;
+#endif
 
+#if HAS_NORMAL_MAP
 	vec4 norm = texture2D(bumpMap, vary_texcoord0.xy);
 
 	norm.xyz = norm.xyz * 2 - 1;
@@ -68,19 +90,29 @@ void main()
 	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;
+#endif
 
 	vec4 final_color = col;
-	final_color.rgb *= 1 - spec.a * env_intensity;
-
-	#ifndef EMISSIVE_MASK
+	
+#if DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_GLOW
 	final_color.a = 0;
-	#endif
+#endif
 
 	vec4 final_specular = spec;
+#if HAS_SPECULAR_MAP
+	//final_color.rgb *= 1 - spec.a * env_intensity;
 	final_specular.rgb *= specular_color.rgb;
-	final_specular.a = specular_color.a * norm.a;
-
+	
 	vec4 final_normal = vec4(normalize(tnorm), spec.a * env_intensity);
+	final_specular.a = specular_color.a * spec.a;
+#else
+	vec4 final_normal = vec4(normalize(tnorm), 0.0);
+	final_specular.a = spec.a;
+#endif
+
 	final_normal.xyz = final_normal.xyz * 0.5 + 0.5;
 	
 	frag_data[0] = final_color;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index c8d38bb8f74e72dd4ad681f1fb43b94cec2f6b00..f92ad63100cbe18bd145502dd793c1413c7b4735 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -31,11 +31,17 @@ ATTRIBUTE vec3 position;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
+
+#if HAS_NORMAL_MAP
 ATTRIBUTE vec3 binormal;
 
 VARYING vec3 vary_mat0;
 VARYING vec3 vary_mat1;
 VARYING vec3 vary_mat2;
+#else
+VARYING vec3 vary_normal;
+#endif
+
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
@@ -45,13 +51,18 @@ void main()
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	
+
 	vec3 n = normalize(normal_matrix * normal);
+#if HAS_NORMAL_MAP
 	vec3 b = normalize(normal_matrix * binormal);
 	vec3 t = cross(b, n);
 	
 	vary_mat0 = vec3(t.x, b.x, n.x);
 	vary_mat1 = vec3(t.y, b.y, n.y);
 	vary_mat2 = vec3(t.z, b.z, n.z);
+#else
+	vary_normal = n;
+#endif
 	
 	vertex_color = diffuse_color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 3f57b006cd4a22c2fde5c9a104ff9ce527e894a9..bf362e21a4d31ce7f7f45d2c7afd8b39417dbbf8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -37,7 +37,6 @@ uniform mat4 inv_proj;
 uniform vec2 screen_res;
 uniform float max_cof;
 uniform float res_scale;
-uniform float global_gamma;
 
 VARYING vec2 vary_fragcoord;
 
@@ -124,6 +123,6 @@ void main()
 
 		diff /= w;
 	}
-	diff.rgb = pow(diff.rgb, vec3(1.0/global_gamma));
+		
 	frag_color = diff;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
index c891c4e4452a53591beb8190f4aa18fe5c17a39c..eb5beeef39a6ce3a47753019ddbdaa385e161876 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl
@@ -35,13 +35,12 @@ uniform sampler2DRect diffuseRect;
 uniform sampler2D bloomMap;
 
 uniform vec2 screen_res;
-uniform float global_gamma;
 VARYING vec2 vary_fragcoord;
 
 void main() 
 {
 	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
-	diff.rgb = pow(diff.rgb, vec3(1.0/global_gamma));
+	
 	vec4 bloom = texture2D(bloomMap, vary_fragcoord.xy/screen_res);
 	frag_color = diff + bloom;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 2ec3fe4a52a444d566854ade83d3e3b81bb34faa..f50935c1a84195c0f46cc802fdad2d716104409c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -77,11 +77,6 @@ vec3 vary_AtmosAttenuation;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec3 samplesRGB(vec3 color)
-{
-	return pow(color, vec3(2.2));
-}
-
 vec4 getPosition_d(vec2 pos_screen, float depth)
 {
 	vec2 sc = pos_screen.xy*2.0;
@@ -106,15 +101,15 @@ vec3 getPositionEye()
 }
 vec3 getSunlitColor()
 {
-	return samplesRGB(vary_SunlitColor) * 4.4;
+	return vary_SunlitColor;
 }
 vec3 getAmblitColor()
 {
-	return samplesRGB((vary_AmblitColor)) * 2.2;
+	return vary_AmblitColor;
 }
 vec3 getAdditiveColor()
 {
-	return samplesRGB(vary_AdditiveColor) * 2.2;
+	return vary_AdditiveColor;
 }
 vec3 getAtmosAttenuation()
 {
@@ -305,7 +300,7 @@ void main()
 			//
 			vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
 			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = vary_SunlitColor*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+			vec3 dumbshiny = vary_SunlitColor*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
 			
 			// add the two types of shiny together
 			vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -314,7 +309,7 @@ void main()
 
 			//add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
-			col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2, 
+			col = mix(col.rgb, textureCube(environmentMap, env_vec).rgb, 
 				max(norm.a-diffuse.a*2.0, 0.0)); 
 		}
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index 9bdf87678f9a48a1559b45f3cc86d7ebc10d9ca0..cca63872de2142faa13bce99ad2b4e703e1a73bc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -72,8 +72,6 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
@@ -89,8 +87,6 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
 	float det = min(lod/(proj_lod*0.5), 1.0);
@@ -108,8 +104,6 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float d = dot(dist,dist);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
index 9543be562bd63afd54c6e8015b251692e109938e..6c34643aab0e577d00242b5942908b32e8efe70d 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
@@ -37,8 +37,6 @@ vec3 fullbrightScaleSoftClip(vec3 light);
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-uniform float texture_gamma;
-
 void fullbright_lighting()
 {
 	vec4 color = diffuseLookup(vary_texcoord0.xy) * vertex_color;
@@ -47,7 +45,7 @@ void fullbright_lighting()
 	{
 		discard;
 	}
-	color.rgb = pow(color.rgb, vec3(texture_gamma));
+
 	color.rgb = fullbrightAtmosTransport(color.rgb);
 	
 	color.rgb = fullbrightScaleSoftClip(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 359864556decf1e24143005783ffd02f5bbc927e..12706f130bd479e25c9facadf566577a99f5209e 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -149,7 +149,6 @@ void main()
 	}
 	
 	vec4 diff = diffuseLookup(vary_texcoord0.xy);
-	diff.rgb = pow(diff.rgb, vec3(2.2));
 
 	vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, vertex_color.a);
 	vec4 color = diff * col;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 695887c5ff64667a32d69fb642847726c28faf6d..5621e47ab70989761a7d7249fb43edb503c7b8a6 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -71,8 +71,6 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
@@ -88,8 +86,6 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
 	float det = min(lod/(proj_lod*0.5), 1.0);
@@ -107,8 +103,6 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float d = dot(dist,dist);
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index e95991a6356be9576878fe1c12994b2db052eac5..ff20b639722216e1dd912d65127a234d3704a618 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -79,11 +79,6 @@ vec3 vary_AmblitColor;
 vec3 vary_AdditiveColor;
 vec3 vary_AtmosAttenuation;
 
-vec3 samplesRGB(vec3 color)
-{
-	return pow(color, vec3(2.2));
-}
-
 vec4 getPosition_d(vec2 pos_screen, float depth)
 {
 	vec2 sc = pos_screen.xy*2.0;
@@ -108,15 +103,15 @@ vec3 getPositionEye()
 }
 vec3 getSunlitColor()
 {
-	return samplesRGB(vary_SunlitColor) * 4.4;
+	return vary_SunlitColor;
 }
 vec3 getAmblitColor()
 {
-	return samplesRGB(vary_AmblitColor) * 2.2;
+	return vary_AmblitColor;
 }
 vec3 getAdditiveColor()
 {
-	return samplesRGB(vary_AdditiveColor) * 2.2;
+	return vary_AdditiveColor;
 }
 vec3 getAtmosAttenuation()
 {
@@ -314,7 +309,7 @@ void main()
 			//
 			vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
 			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(texture2D(lightFunc, vec2(sa, spec.a)).r);
+			vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(6 * texture2D(lightFunc, vec2(sa, spec.a)).r);
 
 			// add the two types of shiny together
 			vec3 spec_contrib = dumbshiny * spec.rgb;
@@ -323,7 +318,7 @@ void main()
 
 			//add environmentmap
 			vec3 env_vec = env_mat * refnormpersp;
-			col = mix(col.rgb, samplesRGB(textureCube(environmentMap, env_vec).rgb) * 2.2, 
+			col = mix(col.rgb, textureCube(environmentMap, env_vec).rgb, 
 				max(norm.a-diffuse.a*2.0, 0.0)); 
 		}
 			
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 525dd32106afa184576e06b8672b8a2c344dada7..6d6ad6d5655560e5e07ce8008edf82c6500adb8d 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -71,8 +71,6 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float det = max(1.0-lod/(proj_lod*0.5), 0.0);
@@ -88,8 +86,6 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
 	float det = min(lod/(proj_lod*0.5), 1.0);
@@ -107,8 +103,6 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	
-	ret.rgb = pow(ret.rgb, vec3(2.2));
-
 	vec2 dist = tc-vec2(0.5);
 	
 	float d = dot(dist,dist);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
index dd7de9f12317694b3f918854fab5812ffac7267f..765b0927c3acc27cf0f87f8fc558b0ec5bddd5a8 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
@@ -27,7 +27,7 @@
 VARYING vec3 vary_SunlitColor;
 VARYING vec3 vary_AdditiveColor;
 VARYING vec3 vary_AtmosAttenuation;
-uniform float global_gamma;
+
 vec3 getSunlitColor()
 {
 	return vec3(0,0,0);
@@ -38,7 +38,7 @@ vec3 getAmblitColor()
 }
 vec3 getAdditiveColor()
 {
-	return pow(vary_AdditiveColor, vec3(global_gamma)) * global_gamma;
+	return vary_AdditiveColor;
 }
 vec3 getAtmosAttenuation()
 {
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
index 61f30886482f63453044ffad6f7a7859d8fc537d..99dbee15eed4006818f8f5a730990e86f68a3990 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
@@ -33,20 +33,18 @@ vec3 sunlit_color;
 vec3 amblit_color;
 vec3 position_eye;
 
-uniform float global_gamma;
-
 vec3 getSunlitColor()
 {
-	return pow(sunlit_color, vec3(global_gamma)) * global_gamma;
+	return sunlit_color;
 }
 vec3 getAmblitColor()
 {
-	return pow(amblit_color, vec3(global_gamma)) * global_gamma;
+	return amblit_color;
 }
 
 vec3 getAdditiveColor()
 {
-	return pow(additive_color, vec3(global_gamma)) * global_gamma;
+	return additive_color;
 }
 vec3 getAtmosAttenuation()
 {
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index caa57ad583e3cb78759c9d1dce5662494a552eb9..77067cc1ec5135881212b3cc1ae214426cc09b39 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -134,7 +134,22 @@ class LLRenderPass : public LLDrawPool
 		PASS_SHINY,
 		PASS_BUMP,
 		PASS_POST_BUMP,
-		PASS_MATERIALS,
+		PASS_MATERIAL,
+		PASS_MATERIAL_ALPHA,
+		PASS_MATERIAL_ALPHA_MASK,
+		PASS_MATERIAL_ALPHA_GLOW,
+		PASS_SPECMAP,
+		PASS_SPECMAP_BLEND,
+		PASS_SPECMAP_MASK,
+		PASS_SPECMAP_GLOW,
+		PASS_NORMMAP,
+		PASS_NORMMAP_BLEND,
+		PASS_NORMMAP_MASK,
+		PASS_NORMMAP_GLOW,
+		PASS_NORMSPEC,
+		PASS_NORMSPEC_BLEND,
+		PASS_NORMSPEC_MASK,
+		PASS_NORMSPEC_GLOW,
 		PASS_GLOW,
 		PASS_ALPHA,
 		PASS_ALPHA_MASK,
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index f0e1221f159b591a652e36ef87f2766c2a282d8e..b126dc3b4a262eeb1b318de10f294f9dbb318e1a 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -44,20 +44,75 @@ void LLDrawPoolMaterials::prerender()
 	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 
 }
 
+S32 LLDrawPoolMaterials::getNumDeferredPasses()
+{
+	return 12;
+}
+
 void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
 {
+	U32 shader_idx[] = 
+	{
+		0, //LLRenderPass::PASS_MATERIAL,
+		//1, //LLRenderPass::PASS_MATERIAL_ALPHA,
+		2, //LLRenderPass::PASS_MATERIAL_ALPHA_MASK,
+		3, //LLRenderPass::PASS_MATERIAL_ALPHA_GLOW,
+		4, //LLRenderPass::PASS_SPECMAP,
+		//5, //LLRenderPass::PASS_SPECMAP_BLEND,
+		6, //LLRenderPass::PASS_SPECMAP_MASK,
+		7, //LLRenderPass::PASS_SPECMAP_GLOW,
+		8, //LLRenderPass::PASS_NORMMAP,
+		//9, //LLRenderPass::PASS_NORMMAP_BLEND,
+		10, //LLRenderPass::PASS_NORMMAP_MASK,
+		11, //LLRenderPass::PASS_NORMMAP_GLOW,
+		12, //LLRenderPass::PASS_NORMSPEC,
+		//13, //LLRenderPass::PASS_NORMSPEC_BLEND,
+		14, //LLRenderPass::PASS_NORMSPEC_MASK,
+		15, //LLRenderPass::PASS_NORMSPEC_GLOW,
+	};
+	
+	mShader = &(gDeferredMaterialProgram[shader_idx[pass]]);
+	mShader->bind();
+
+	diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+		
 	LLFastTimer t(FTM_RENDER_MATERIALS);
 }
 
 void LLDrawPoolMaterials::endDeferredPass(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_MATERIALS);
+
+	mShader->unbind();
+
 	LLRenderPass::endRenderPass(pass);
 }
 
 void LLDrawPoolMaterials::renderDeferred(S32 pass)
 {
-	U32 type = LLRenderPass::PASS_MATERIALS;
+	U32 type_list[] = 
+	{
+		LLRenderPass::PASS_MATERIAL,
+		//LLRenderPass::PASS_MATERIAL_ALPHA,
+		LLRenderPass::PASS_MATERIAL_ALPHA_MASK,
+		LLRenderPass::PASS_MATERIAL_ALPHA_GLOW,
+		LLRenderPass::PASS_SPECMAP,
+		//LLRenderPass::PASS_SPECMAP_BLEND,
+		LLRenderPass::PASS_SPECMAP_MASK,
+		LLRenderPass::PASS_SPECMAP_GLOW,
+		LLRenderPass::PASS_NORMMAP,
+		//LLRenderPass::PASS_NORMMAP_BLEND,
+		LLRenderPass::PASS_NORMMAP_MASK,
+		LLRenderPass::PASS_NORMMAP_GLOW,
+		LLRenderPass::PASS_NORMSPEC,
+		//LLRenderPass::PASS_NORMSPEC_BLEND,
+		LLRenderPass::PASS_NORMSPEC_MASK,
+		LLRenderPass::PASS_NORMSPEC_GLOW,
+	};
+
+	llassert(pass < sizeof(type_list)/sizeof(U32));
+
+	U32 type = type_list[pass];
 	LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
 	LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
 	
@@ -65,27 +120,6 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
 	{
 		LLDrawInfo& params = **i;
 		
-		switch (params.mDiffuseAlphaMode)
-		{
-			case 0:
-				mShader = &gDeferredMaterialShinyNormal;
-				mShader->bind();
-				break;
-			case 1: // Alpha blending not supported in the opaque draw pool.
-				return;
-			case 2:
-				mShader = &gDeferredMaterialShinyNormalAlphaTest;
-				mShader->bind();
-				mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
-				break;
-			case 3:
-				mShader = &gDeferredMaterialShinyNormalEmissive;
-				mShader->bind();
-				break;
-		};
-		
-		
-		
 		mShader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);
 		mShader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);
 		
@@ -101,10 +135,9 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
 			bindSpecularMap(params.mSpecularMap);
 		}
 		
-		diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
+		mShader->setMinimumAlpha(params.mAlphaMaskCutoff);
+
 		pushBatch(params, VERTEX_DATA_MASK, TRUE);
-		mShader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
-		mShader->unbind();
 	}
 }
 
@@ -118,72 +151,6 @@ void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
 	mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
 }
 
-void LLDrawPoolMaterials::beginRenderPass(S32 pass)
-{
-	LLFastTimer t(FTM_RENDER_MATERIALS);
-	
-	// Materials isn't supported under forward rendering.
-	// Use the simple shaders to handle it instead.
-	// This is basically replicated from LLDrawPoolSimple.
-	
-	if (LLPipeline::sUnderWaterRender)
-	{
-		mShader = &gObjectSimpleWaterProgram;
-	}
-	else
-	{
-		mShader = &gObjectSimpleProgram;
-	}
-	
-	if (mVertexShaderLevel > 0)
-	{
-		mShader->bind();
-	}
-	else
-	{
-		// don't use shaders!
-		if (gGLManager.mHasShaderObjects)
-		{
-			LLGLSLShader::bindNoShader();
-		}
-	}
-}
-
-void LLDrawPoolMaterials::endRenderPass(S32 pass)
-{
-	LLFastTimer t(FTM_RENDER_MATERIALS);
-	stop_glerror();
-	LLRenderPass::endRenderPass(pass);
-	stop_glerror();
-	if (mVertexShaderLevel > 0)
-	{
-		mShader->unbind();
-	}
-}
-
-void LLDrawPoolMaterials::render(S32 pass)
-{
-	LLGLDisable blend(GL_BLEND);
-	
-	{ //render simple
-		LLFastTimer t(FTM_RENDER_MATERIALS);
-		gPipeline.enableLightsDynamic();
-		
-		if (mVertexShaderLevel > 0)
-		{
-			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
-			
-			pushBatches(LLRenderPass::PASS_MATERIALS, mask, TRUE, TRUE);
-		}
-		else
-		{
-			LLGLDisable alpha_test(GL_ALPHA_TEST);
-			renderTexture(LLRenderPass::PASS_MATERIALS, getVertexDataMask());
-		}
-	}
-}
-
-
 void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
 {
 	applyModelMatrix(params);
diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h
index e8838c64d672619e1fe443f951d00a53c099f193..1f5565afc85eda29babe23d79b6ac0c70f446a85 100644
--- a/indra/newview/lldrawpoolmaterials.h
+++ b/indra/newview/lldrawpoolmaterials.h
@@ -55,13 +55,11 @@ class LLDrawPoolMaterials : public LLRenderPass
 	
 	/*virtual*/ U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
 	
-	/*virtual*/ void render(S32 pass = 0);
-	/*virtual*/ void beginRenderPass( S32 pass );
-	/*virtual*/ void endRenderPass( S32 pass );
-	/*virtual*/ S32	 getNumPasses() {return 1;}
+	/*virtual*/ void render(S32 pass = 0) { }
+	/*virtual*/ S32	 getNumPasses() {return 0;}
 	/*virtual*/ void prerender();
 	
-	/*virtual*/ S32 getNumDeferredPasses() {return 1;}
+	/*virtual*/ S32 getNumDeferredPasses();
 	/*virtual*/ void beginDeferredPass(S32 pass);
 	/*virtual*/ void endDeferredPass(S32 pass);
 	/*virtual*/ void renderDeferred(S32 pass);
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index cef07984e06661a413d70c3d12c1493f99d05767..71cd87cc852405ba2b6f2ea61c26cdf92b876285 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1087,7 +1087,7 @@ void render_hud_attachments()
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_BUMP);
-		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MATERIALS);
+		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_MATERIAL);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK);
 		gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 17bfc24f43ccb594951863a27972cd0c9446778a..4e38d2f7e9738c3da405acc3e4ec3eee2d785f4c 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -208,15 +208,7 @@ LLGLSLShader			gDeferredStarProgram;
 LLGLSLShader			gNormalMapGenProgram;
 
 // Deferred materials shaders
-LLGLSLShader			gDeferredMaterialShiny;
-LLGLSLShader			gDeferredMaterialNormal;
-LLGLSLShader			gDeferredMaterialShinyNormal;
-LLGLSLShader			gDeferredMaterialShinyAlphaTest;
-LLGLSLShader			gDeferredMaterialNormalAlphaTest;
-LLGLSLShader			gDeferredMaterialShinyNormalAlphaTest;
-LLGLSLShader			gDeferredMaterialShinyEmissive;
-LLGLSLShader			gDeferredMaterialNormalEmissive;
-LLGLSLShader			gDeferredMaterialShinyNormalEmissive;
+LLGLSLShader			gDeferredMaterialProgram[LLMaterial::SHADER_COUNT];
 
 LLViewerShaderMgr::LLViewerShaderMgr() :
 	mVertexShaderLevel(SHADER_COUNT, 0),
@@ -1116,12 +1108,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWLCloudProgram.unload();
 		gDeferredStarProgram.unload();
 		gNormalMapGenProgram.unload();
-		gDeferredMaterialShiny.unload();
-		gDeferredMaterialNormal.unload();
-		gDeferredMaterialShinyAlphaTest.unload();
-		gDeferredMaterialNormalAlphaTest.unload();
-		gDeferredMaterialShinyEmissive.unload();
-		gDeferredMaterialNormalEmissive.unload();
+		for (U32 i = 0; i < LLMaterial::SHADER_COUNT; ++i)
+		{
+			gDeferredMaterialProgram[i].unload();
+		}
 		return TRUE;
 	}
 
@@ -1236,114 +1226,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredBumpProgram.createShader(NULL, NULL);
 	}
 	
-	if (success)
-	{
-		gDeferredMaterialShiny.mName = "Deferred Shiny Material Shader";
-		gDeferredMaterialShiny.mShaderFiles.clear();
-		gDeferredMaterialShiny.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShiny.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShiny.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShiny.addPermutation("SHINY_MATERIAL", "1");
-		success = gDeferredMaterialShiny.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialNormal.mName = "Deferred Normal Mapped Material Shader";
-		gDeferredMaterialNormal.mShaderFiles.clear();
-		gDeferredMaterialNormal.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialNormal.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialNormal.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialNormal.addPermutation("NORMAL_MATERIAL", "1");
-		success = gDeferredMaterialNormal.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialShinyNormal.mName = "Deferred Normal Mapped Shiny Material Shader";
-		gDeferredMaterialShinyNormal.mShaderFiles.clear();
-		gDeferredMaterialShinyNormal.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShinyNormal.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShinyNormal.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShinyNormal.addPermutation("NORMAL_MATERIAL", "1");
-		gDeferredMaterialShinyNormal.addPermutation("SHINY_MATERIAL", "1");
-		success = gDeferredMaterialShinyNormal.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialShinyAlphaTest.mName = "Deferred Alpha Tested Shiny Material Shader";
-		gDeferredMaterialShinyAlphaTest.mShaderFiles.clear();
-		gDeferredMaterialShinyAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShinyAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShinyAlphaTest.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShinyAlphaTest.addPermutation("SHINY_MATERIAL", "1");
-		gDeferredMaterialShinyAlphaTest.addPermutation("ALPHA_TEST", "1");
-		success = gDeferredMaterialShinyAlphaTest.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialNormalAlphaTest.mName = "Deferred Alpha Tested Normal Mapped Material Shader";
-		gDeferredMaterialNormalAlphaTest.mShaderFiles.clear();
-		gDeferredMaterialNormalAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialNormalAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialNormalAlphaTest.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialNormalAlphaTest.addPermutation("NORMAL_MATERIAL", "1");
-		gDeferredMaterialNormalAlphaTest.addPermutation("ALPHA_TEST", "1");
-		success = gDeferredMaterialNormalAlphaTest.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialNormalAlphaTest.mName = "Deferred Alpha Tested Shiny Normal Mapped Material Shader";
-		gDeferredMaterialShinyNormalAlphaTest.mShaderFiles.clear();
-		gDeferredMaterialShinyNormalAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShinyNormalAlphaTest.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShinyNormalAlphaTest.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShinyNormalAlphaTest.addPermutation("NORMAL_MATERIAL", "1");
-		gDeferredMaterialShinyNormalAlphaTest.addPermutation("SHINY_MATERIAL", "1");
-		gDeferredMaterialShinyNormalAlphaTest.addPermutation("ALPHA_TEST", "1");
-		success = gDeferredMaterialShinyNormalAlphaTest.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialShinyEmissive.mName = "Deferred Emissive Mask Shiny Material Shader";
-		gDeferredMaterialShinyEmissive.mShaderFiles.clear();
-		gDeferredMaterialShinyEmissive.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShinyEmissive.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShinyEmissive.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShinyEmissive.addPermutation("SHINY_MATERIAL", "1");
-		gDeferredMaterialShinyEmissive.addPermutation("EMISSIVE_MASK", "1");
-		success = gDeferredMaterialShinyEmissive.createShader(NULL, NULL);
-	}
-	
-	if (success)
-	{
-		gDeferredMaterialNormalEmissive.mName = "Deferred Emissive Mask Normal Mapped Material Shader";
-		gDeferredMaterialNormalEmissive.mShaderFiles.clear();
-		gDeferredMaterialNormalEmissive.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialNormalEmissive.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialNormalEmissive.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialNormalEmissive.addPermutation("NORMAL_MATERIAL", "1");
-		gDeferredMaterialNormalEmissive.addPermutation("EMISSIVE_MASK", "1");
-		success = gDeferredMaterialNormalEmissive.createShader(NULL, NULL);
-	}
-	
-	if (success)
+
+	for (U32 i = 0; i < LLMaterial::SHADER_COUNT; ++i)
 	{
-		gDeferredMaterialShinyNormalEmissive.mName = "Deferred Emissive Mask Normal Mapped Material Shader";
-		gDeferredMaterialShinyNormalEmissive.mShaderFiles.clear();
-		gDeferredMaterialShinyNormalEmissive.mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredMaterialShinyNormalEmissive.mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMaterialShinyNormalEmissive.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredMaterialShinyNormalEmissive.addPermutation("NORMAL_MATERIAL", "1");
-		gDeferredMaterialShinyNormalEmissive.addPermutation("SHINY_MATERIAL", "1");
-		gDeferredMaterialShinyNormalEmissive.addPermutation("EMISSIVE_MASK", "1");
-		success = gDeferredMaterialShinyNormalEmissive.createShader(NULL, NULL);
+		if (success)
+		{
+			gDeferredMaterialProgram[i].mName = llformat("Deferred Material Shader %d", i);
+			
+			U32 alpha_mode = i & 0x3;
+
+			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].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));
+
+			success = gDeferredMaterialProgram[i].createShader(NULL, NULL);
+		}
 	}
 
+	
 	if (success)
 	{
 		gDeferredTreeProgram.mName = "Deferred Tree Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 15bff6882ee8239818efe1b733da9623eff69145..f0bf352e755a67d2a5730650a56d5fd8c6aa257f 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -28,6 +28,7 @@
 #define LL_VIEWER_SHADER_MGR_H
 
 #include "llshadermgr.h"
+#include "llmaterial.h"
 
 class LLViewerShaderMgr: public LLShaderMgr
 {
@@ -363,14 +364,6 @@ extern LLGLSLShader			gDeferredStarProgram;
 extern LLGLSLShader			gNormalMapGenProgram;
 
 // Deferred materials shaders
-extern LLGLSLShader			gDeferredMaterialShiny;
-extern LLGLSLShader			gDeferredMaterialNormal;
-extern LLGLSLShader			gDeferredMaterialShinyNormal;
-extern LLGLSLShader			gDeferredMaterialShinyAlphaTest;
-extern LLGLSLShader			gDeferredMaterialNormalAlphaTest;
-extern LLGLSLShader			gDeferredMaterialShinyNormalAlphaTest;
-extern LLGLSLShader			gDeferredMaterialShinyEmissive;
-extern LLGLSLShader			gDeferredMaterialNormalEmissive;
-extern LLGLSLShader			gDeferredMaterialShinyNormalEmissive;
+extern LLGLSLShader			gDeferredMaterialProgram[LLMaterial::SHADER_COUNT];
 
 #endif
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 44eefd3c4abdf634df51d439f7398b8ec6b88938..f149c5088431659ddda1d8439cca1ff7895116bc 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4143,16 +4143,16 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 				// We have a material.  Update our draw info accordingly.
 				draw_info->mMaterialID = &facep->getTextureEntry()->getMaterialID();
 				LLVector4 specColor;
-				specColor.mV[0] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[0] * (1.0 / 255);
-				specColor.mV[1] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[1] * (1.0 / 255);
-				specColor.mV[2] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[2] * (1.0 / 255);
-				specColor.mV[3] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightExponent() * (1.0 / 255);
+				specColor.mV[0] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[0] * (1.f / 255.f);
+				specColor.mV[1] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[1] * (1.f / 255.f);
+				specColor.mV[2] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightColor().mV[2] * (1.f / 255.f);
+				specColor.mV[3] = facep->getTextureEntry()->getMaterialParams()->getSpecularLightExponent() * (1.f / 255.f);
 				draw_info->mSpecColor = specColor;
-				draw_info->mEnvIntensity = facep->getTextureEntry()->getMaterialParams()->getEnvironmentIntensity() * (1.0 / 255);
-				draw_info->mAlphaMaskCutoff = facep->getTextureEntry()->getMaterialParams()->getAlphaMaskCutoff() * (1.0 / 255);
+				draw_info->mEnvIntensity = facep->getTextureEntry()->getMaterialParams()->getEnvironmentIntensity() * (1.f / 255.f);
+				draw_info->mAlphaMaskCutoff = facep->getTextureEntry()->getMaterialParams()->getAlphaMaskCutoff() * (1.f / 255.f);
 				draw_info->mDiffuseAlphaMode = facep->getTextureEntry()->getMaterialParams()->getDiffuseAlphaMode();
-				draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTextureIndex());
-				draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTextureIndex());
+				draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());
+				draw_info->mSpecularMap = facep->getViewerObject()->getTESpecularMap(facep->getTEOffset());
 			}
 		} else {
 			U8 shiny = facep->getTextureEntry()->getShiny();
@@ -5151,7 +5151,39 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 
 			BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE;
 		
-			if (is_alpha)
+			LLMaterial* mat = te->getMaterialParams().get();
+
+			if (mat && LLPipeline::sRenderDeferred && !hud_group)
+			{
+				U32 pass[] = 
+				{
+					LLRenderPass::PASS_MATERIAL,
+					LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_MATERIAL_ALPHA,
+					LLRenderPass::PASS_MATERIAL_ALPHA_MASK,
+					LLRenderPass::PASS_MATERIAL_ALPHA_GLOW,
+					LLRenderPass::PASS_SPECMAP,
+					LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_SPECMAP_BLEND,
+					LLRenderPass::PASS_SPECMAP_MASK,
+					LLRenderPass::PASS_SPECMAP_GLOW,
+					LLRenderPass::PASS_NORMMAP,
+					LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMMAP_BLEND,
+					LLRenderPass::PASS_NORMMAP_MASK,
+					LLRenderPass::PASS_NORMMAP_GLOW,
+					LLRenderPass::PASS_NORMSPEC,
+					LLRenderPass::PASS_ALPHA, //LLRenderPass::PASS_NORMSPEC_BLEND,
+					LLRenderPass::PASS_NORMSPEC_MASK,
+					LLRenderPass::PASS_NORMSPEC_GLOW,
+				};
+
+				U32 mask = mat->getShaderMask();
+
+				llassert(mask < sizeof(pass)/sizeof(U32));
+
+				mask = llmin(mask, sizeof(pass)/sizeof(U32)-1);
+
+				registerFace(group, facep, pass[mask]);
+			}
+			else if (is_alpha)
 			{
 				// can we safely treat this as an alpha mask?
 				if (facep->getFaceColor().mV[3] <= 0.f)
@@ -5197,10 +5229,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 					{ //register in deferred bump pass
 						registerFace(group, facep, LLRenderPass::PASS_BUMP);
 					}
-					else if (te->getMaterialParams())
-					{
-						registerFace(group, facep, LLRenderPass::PASS_MATERIALS);
-					}
 					else
 					{ //register in deferred simple pass (deferred simple includes shiny)
 						llassert(mask & LLVertexBuffer::MAP_NORMAL);
@@ -5236,10 +5264,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
 					{ //non-shiny or fullbright deferred bump
 						registerFace(group, facep, LLRenderPass::PASS_BUMP);
 					}
-					else if (te->getMaterialParams())
-					{
-						registerFace(group, facep, LLRenderPass::PASS_MATERIALS);
-					}
 					else
 					{ //all around simple
 						llassert(mask & LLVertexBuffer::MAP_NORMAL);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 8b9e02946b85bf9eac12108449f8ed84c0ef04f1..c5fedab8c03671bb9b2673f4770e37537c74a4d0 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -398,8 +398,8 @@ void validate_framebuffer_object();
 
 bool addDeferredAttachments(LLRenderTarget& target)
 {
-	return target.addColorAttachment(GL_SRGB_ALPHA) && //specular
-			target.addColorAttachment(GL_RGB10_A2); //normal+z
+	return target.addColorAttachment(GL_RGBA) && //specular
+			target.addColorAttachment(GL_RGBA); //normal+z
 }
 
 LLPipeline::LLPipeline() :
@@ -908,7 +908,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		BOOL ssao = RenderDeferredSSAO;
 		
 		//allocate deferred rendering color buffers
-		if (!mDeferredScreen.allocate(resX, resY, GL_SRGB8_ALPHA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
+		if (!mDeferredScreen.allocate(resX, resY, GL_RGBA8, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE, samples)) return false;
 		if (!addDeferredAttachments(mDeferredScreen)) return false;
 		
@@ -1204,7 +1204,7 @@ void LLPipeline::createGLBuffers()
 
 		for (U32 i = 0; i < 3; i++)
 		{
-			mGlow[i].allocate(512,glow_res,sRenderDeferred ? GL_RGB10_A2 : GL_RGB10_A2,FALSE,FALSE);
+			mGlow[i].allocate(512,glow_res, GL_RGBA,FALSE,FALSE);
 		}
 
 		allocateScreenBuffer(resX,resY);
@@ -1268,6 +1268,45 @@ void LLPipeline::createLUTBuffers()
 		{
 			U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
 			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
+			U8* ls = new U8[lightResX*lightResY];
+			F32 specExp = gSavedSettings.getF32("RenderSpecularExponent");
+            // Calculate the (normalized) Blinn-Phong specular lookup texture.
+			for (U32 y = 0; y < lightResY; ++y)
+			{
+				for (U32 x = 0; x < lightResX; ++x)
+				{
+					ls[y*lightResX+x] = 0;
+					F32 sa = (F32) x/(lightResX-1);
+					F32 spec = (F32) y/(lightResY-1);
+					F32 n = spec * spec * specExp;
+					
+					// Nothing special here.  Just your typical blinn-phong term.
+					spec = powf(sa, n);
+					
+					// Apply our normalization function.
+					// Note: This is the full equation that applies the full normalization curve, not an approximation.
+					// This is fine, given we only need to create our LUT once per buffer initialization.
+					// The only trade off is we have a really low dynamic range.
+					// This means we have to account for things not being able to exceed 0 to 1 in our shaders.
+					spec *= (((n + 2) * (n + 4)) / (8 * F_PI * (powf(2, -n/2) + n)));
+					
+					// Always sample at a 1.0/2.2 curve.
+					// This "Gamma corrects" our specular term, boosting our lower exponent reflections.
+					spec = powf(spec, 1.f/2.2f);
+					
+					// Easy fix for our dynamic range problem: divide by 6 here, multiply by 6 in our shaders.
+					// This allows for our specular term to exceed a value of 1 in our shaders.
+					// This is something that can be important for energy conserving specular models where higher exponents can result in highlights that exceed a range of 0 to 1.
+					// Technically, we could just use an R16F texture, but driver support for R16F textures can be somewhat spotty at times.
+					// This works remarkably well for higher specular exponents, though banding can sometimes be seen on lower exponents.
+					// Combined with a bit of noise and trilinear filtering, the banding is hardly noticable.
+					ls[y*lightResX+x] = (U8)(llclamp(spec * (1.f / 6), 0.f, 1.f) * 255);
+				}
+			}
+		
+
+			/*U32 lightResX = gSavedSettings.getU32("RenderSpecularResX");
+			U32 lightResY = gSavedSettings.getU32("RenderSpecularResY");
 			F32* ls = new F32[lightResX*lightResY];
 			//F32 specExp = gSavedSettings.getF32("RenderSpecularExponent"); // Note: only use this when creating new specular lighting functions.
             // Calculate the (normalized) blinn-phong specular lookup texture. (with a few tweaks)
@@ -1292,11 +1331,11 @@ void LLPipeline::createLUTBuffers()
 					// Though some older drivers may not like this, newer drivers shouldn't have this problem.
 					ls[y*lightResX+x] = spec;
 				}
-			}
+			}*/
 			
-			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R16F, 1, &mLightFunc);
+			LLImageGL::generateTextures(LLTexUnit::TT_TEXTURE, GL_R8, 1, &mLightFunc);
 			gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLightFunc);
-			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R16F, lightResX, lightResY, GL_RED, GL_FLOAT, ls, false);
+			LLImageGL::setManualImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_R16F, lightResX, lightResY, GL_RED, GL_UNSIGNED_BYTE, ls, false);
 			gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
 			gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR);
 			
@@ -8297,7 +8336,7 @@ void LLPipeline::renderDeferredLighting()
 					light_colors.pop_front();
 
 					far_z = llmin(light[count].mV[2]-sqrtf(light[count].mV[3]), far_z);
-					col[count] = pow4fsrgb(col[count], 2.2f);
+					//col[count] = pow4fsrgb(col[count], 2.2f);
 					count++;
 					if (count == max_count || fullscreen_lights.empty())
 					{
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 22a0ca6a2fb7f4590738085bc9100905edf43f60..fd4813e41537f6e7c0b7c02cd75de86545f31a33 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -437,7 +437,7 @@ class LLPipeline
 		RENDER_TYPE_PASS_SHINY					= LLRenderPass::PASS_SHINY,
 		RENDER_TYPE_PASS_BUMP					= LLRenderPass::PASS_BUMP,
 		RENDER_TYPE_PASS_POST_BUMP				= LLRenderPass::PASS_POST_BUMP,
-		RENDER_TYPE_PASS_MATERIALS				= LLRenderPass::PASS_MATERIALS,
+		RENDER_TYPE_PASS_MATERIAL				= LLRenderPass::PASS_MATERIAL,
 		RENDER_TYPE_PASS_GLOW					= LLRenderPass::PASS_GLOW,
 		RENDER_TYPE_PASS_ALPHA					= LLRenderPass::PASS_ALPHA,
 		RENDER_TYPE_PASS_ALPHA_MASK				= LLRenderPass::PASS_ALPHA_MASK,