From 3237923e10a34d14ac4aac17400811cb1c7c3bdf Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Thu, 16 Aug 2018 00:31:39 +0100
Subject: MAINT-3699 new shaders supporting alpha blend/mask rigged content.

Make shader loading debug logging of uniforms use ShaderUniform to make supression simpler.
---
 indra/llprimitive/lltextureentry.h                 |   2 +
 indra/llrender/llglslshader.cpp                    |  10 +-
 indra/llrender/llshadermgr.cpp                     |   4 +-
 .../deferred/attachmentAlphaMaskShadowF.glsl       |  64 ++++++
 .../class1/deferred/attachmentAlphaShadowF.glsl    |  68 ++++++
 .../class1/deferred/attachmentAlphaShadowV.glsl    |  74 +++++++
 .../class1/deferred/avatarAlphaMaskShadowF.glsl    |  65 ++++++
 .../class1/deferred/avatarAlphaShadowF.glsl        |  68 ++++++
 .../class1/deferred/avatarAlphaShadowV.glsl        |  82 +++++++
 indra/newview/lldrawpoolavatar.cpp                 | 236 ++++++++++++++++++---
 indra/newview/lldrawpoolavatar.h                   | 212 +++++++++---------
 indra/newview/llviewershadermgr.cpp                |  52 +++++
 indra/newview/llviewershadermgr.h                  |   4 +
 13 files changed, 807 insertions(+), 134 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl

(limited to 'indra')

diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h
index a40c3988f2..dc2e201044 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -136,6 +136,8 @@ public:
 	
 	virtual const LLUUID &getID() const { return mID; }
 	const LLColor4 &getColor() const { return mColor; }
+    const F32 getAlpha() const { return mColor.mV[VALPHA]; }
+
 	void getScale(F32 *s, F32 *t) const { *s = mScaleS; *t = mScaleT; }
 	F32  getScaleS() const { return mScaleS; }
 	F32  getScaleT() const { return mScaleT; }
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 4702042ab9..141ed51260 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -561,7 +561,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
                 mAttribute[i] = index;
 #endif
                 mAttributeMask |= 1 << i;
-                LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
+                LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
             }
         }
         if (attributes != NULL)
@@ -573,7 +573,7 @@ BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attri
                 if (index != -1)
                 {
                     mAttribute[LLShaderMgr::instance()->mReservedAttribs.size() + i] = index;
-                    LL_DEBUGS("ShaderLoading") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
+                    LL_DEBUGS("ShaderUniform") << "Attribute " << name << " assigned to channel " << index << LL_ENDL;
                 }
             }
         }
@@ -658,7 +658,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
         mUniformNameMap[location] = name;
         mUniformMap[hashedName] = location;
 
-        LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
+        LL_DEBUGS("ShaderUniform") << "Uniform " << name << " is at location " << location << LL_ENDL;
     
         //find the index of this uniform
         for (S32 i = 0; i < (S32) LLShaderMgr::instance()->mReservedUniforms.size(); i++)
@@ -706,7 +706,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)
         type == GL_SAMPLER_2D_MULTISAMPLE)
     {   //this here is a texture
         glUniform1iARB(location, mActiveTextureChannels);
-        LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
+        LL_DEBUGS("ShaderUniform") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL;
         return mActiveTextureChannels++;
     }
     return -1;
@@ -849,7 +849,7 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 
 	unbind();
 
-	LL_DEBUGS("ShaderLoading") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
+	LL_DEBUGS("ShaderUniform") << "Total Uniform Size: " << mTotalUniformSize << LL_ENDL;
 	return res;
 }
 
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index e721ad93fa..643c368870 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -537,8 +537,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		}
 	}
 	
-	LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL;
-
 	if (filename.empty()) 
 	{
 		return 0;
@@ -558,7 +556,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		fname << getShaderDirPrefix();
 		fname << gpu_class << "/" << filename;
 		
- 		LL_DEBUGS("ShaderLoading") << "Looking in " << fname.str() << LL_ENDL;
+ 		
 		file = LLFile::fopen(fname.str(), "r");		/* Flawfinder: ignore */
 		if (file)
 		{
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
new file mode 100644
index 0000000000..a08550d69c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaMaskShadowF.glsl
@@ -0,0 +1,64 @@
+/** 
+ * @file attachmentAlphaMaskShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 post_pos;
+VARYING vec2 vary_texcoord0;
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+
+void main() 
+{
+	float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+	if (alpha < 0.05) // treat as totally transparent
+	{
+		discard;
+	}
+
+	if (alpha < minimum_alpha) // treat as semi-transparent
+	{
+	  if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+	  {
+	    discard;
+	  }
+	}
+
+	frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP	
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
new file mode 100644
index 0000000000..b54c580ce9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowF.glsl
@@ -0,0 +1,68 @@
+/** 
+ * @file attachmentAlphaShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+uniform sampler2D diffuseMap;
+
+VARYING float pos_w;
+VARYING float target_pos_x;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main() 
+{
+	float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+	if (alpha < 0.05) // treat as totally transparent
+	{
+		discard;
+	}
+
+	if (alpha < minimum_alpha)
+	{
+	  if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+	  {
+	    discard;
+	  }
+	}
+
+	frag_color = vec4(1,1,1,1);
+
+#if !DEPTH_CLAMP	
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
new file mode 100644
index 0000000000..31b93dc36a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentAlphaShadowV.glsl
@@ -0,0 +1,74 @@
+/** 
+ * @file attachmentShadowV.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 mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+uniform mat4 texture_matrix0;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+mat4 getObjectSkinnedTransform();
+void passTextureIndex();
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+VARYING vec2 vary_texcoord0;
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+
+void main()
+{
+	//transform vertex
+	mat4 mat = getObjectSkinnedTransform();
+	
+	mat = modelview_matrix * mat;
+	vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+
+	vec4 p = projection_matrix * vec4(pos, 1.0);
+
+	pos_w = p.w;
+
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+	vertex_color = diffuse_color;
+
+#if !DEPTH_CLAMP
+	p.z = max(p.z, -p.w+0.01);
+    post_pos = p;
+	gl_Position = p;
+#else
+	gl_Position = p;
+#endif
+
+	passTextureIndex();
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
new file mode 100644
index 0000000000..b8ce54bcb1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaMaskShadowF.glsl
@@ -0,0 +1,65 @@
+/** 
+ * @file treeShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+uniform sampler2D diffuseMap;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING float target_pos_x;
+VARYING float pos_w;
+VARYING vec2 vary_texcoord0;
+
+void main() 
+{
+	float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
+
+	if (alpha < 0.05) // treat as totally transparent
+	{
+		discard;
+	}
+
+	if (alpha < minimum_alpha)
+	{
+	  if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+	  {
+	    discard;
+	  }
+	}
+
+	frag_color = vec4(1,1,1,1);
+	
+#if !DEPTH_CLAMP
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
new file mode 100644
index 0000000000..ef49b6f4e8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowF.glsl
@@ -0,0 +1,68 @@
+/** 
+ * @file avatarAlphaShadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2005&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2005, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+
+uniform sampler2D diffuseMap;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main() 
+{
+	float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a * vertex_color.a;
+
+	if (alpha < 0.05) // treat as totally transparent
+	{
+		discard;
+	}
+
+	if (alpha < minimum_alpha) // treat as semi-transparent
+	{
+	  if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+	  {
+	    discard;
+	  }
+	}
+
+	frag_color = vec4(1,1,1,1);
+	
+#if !DEPTH_CLAMP
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
new file mode 100644
index 0000000000..d1d7ece6fe
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaShadowV.glsl
@@ -0,0 +1,82 @@
+/** 
+ * @file avatarShadowV.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 mat4 texture_matrix0;
+uniform mat4 projection_matrix;
+uniform float shadow_target_width;
+
+mat4 getSkinnedTransform();
+void passTextureIndex();
+
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+#if !DEPTH_CLAMP
+VARYING vec4 post_pos;
+#endif
+VARYING float pos_w;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void main()
+{
+	vec4 pos;
+	vec3 norm;
+	
+	vec4 pos_in = vec4(position.xyz, 1.0);
+	mat4 trans = getSkinnedTransform();
+	pos.x = dot(trans[0], pos_in);
+	pos.y = dot(trans[1], pos_in);
+	pos.z = dot(trans[2], pos_in);
+	pos.w = 1.0;
+	
+	norm.x = dot(trans[0].xyz, normal);
+	norm.y = dot(trans[1].xyz, normal);
+	norm.z = dot(trans[2].xyz, normal);
+	norm = normalize(norm);
+	
+	pos = projection_matrix * pos;
+
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+	pos_w = pos.w;
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+	vertex_color = diffuse_color;
+#if !DEPTH_CLAMP
+	post_pos = pos;
+
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+
+	passTextureIndex();
+}
+
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index ef69990170..b318156cf8 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -60,6 +60,7 @@ static U32 sShaderLevel = 0;
 LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
 BOOL	LLDrawPoolAvatar::sSkipOpaque = FALSE;
 BOOL	LLDrawPoolAvatar::sSkipTransparent = FALSE;
+S32     LLDrawPoolAvatar::sShadowPass = -1;
 S32 LLDrawPoolAvatar::sDiffuseChannel = 0;
 F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f;
 
@@ -403,19 +404,33 @@ void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
 
 S32 LLDrawPoolAvatar::getNumShadowPasses()
 {
-	return 2;
+    // avatars opaque, avatar alpha, avatar alpha mask, alpha attachments, alpha mask attachments, opaque attachments...
+	return NUM_SHADOW_PASSES;
 }
 
 void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR);
 
-	if (pass == 0)
+	if (pass == SHADOW_PASS_AVATAR_OPAQUE)
 	{
 		sVertexProgram = &gDeferredAvatarShadowProgram;
 		
-		//gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f);		
+		if ((sShaderLevel > 0))  // for hardware blending
+		{
+			sRenderingSkinned = TRUE;
+			sVertexProgram->bind();
+		}
 
+		gGL.diffuseColor4f(1,1,1,1);
+	}
+    else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND)
+	{
+		sVertexProgram = &gDeferredAvatarAlphaShadowProgram;
+
+        // bind diffuse tex so we can reference the alpha channel...
+        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		
 		if ((sShaderLevel > 0))  // for hardware blending
 		{
 			sRenderingSkinned = TRUE;
@@ -424,7 +439,52 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 
 		gGL.diffuseColor4f(1,1,1,1);
 	}
-	else
+    else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK)
+	{
+		sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram;
+
+        // bind diffuse tex so we can reference the alpha channel...
+        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		
+		if ((sShaderLevel > 0))  // for hardware blending
+		{
+			sRenderingSkinned = TRUE;
+			sVertexProgram->bind();
+		}
+
+		gGL.diffuseColor4f(1,1,1,1);
+	}
+    else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)
+	{
+		sVertexProgram = &gDeferredAttachmentAlphaShadowProgram;
+
+        // bind diffuse tex so we can reference the alpha channel...
+        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		
+		if ((sShaderLevel > 0))  // for hardware blending
+		{
+			sRenderingSkinned = TRUE;
+			sVertexProgram->bind();
+		}
+
+		gGL.diffuseColor4f(1,1,1,1);
+	}
+    else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK)
+	{
+		sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram;
+
+        // bind diffuse tex so we can reference the alpha channel...
+		sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+
+		if ((sShaderLevel > 0))  // for hardware blending
+		{
+			sRenderingSkinned = TRUE;
+			sVertexProgram->bind();
+		}
+
+		gGL.diffuseColor4f(1,1,1,1);
+	}
+	else // SHADOW_PASS_ATTACHMENT_OPAQUE
 	{
 		sVertexProgram = &gDeferredAttachmentShadowProgram;
 		sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -435,20 +495,19 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 void LLDrawPoolAvatar::endShadowPass(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_SHADOW_AVATAR);
-	if (pass == 0)
-	{
-		if (sShaderLevel > 0)
-		{
-			sRenderingSkinned = FALSE;
-			sVertexProgram->unbind();
-		}
-	}
-	else
+
+	if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE)
 	{
 		LLVertexBuffer::unbind();
+	}
+
+    if (sShaderLevel > 0)
+	{			
 		sVertexProgram->unbind();
-		sVertexProgram = NULL;
 	}
+    sVertexProgram = NULL;
+    sRenderingSkinned = FALSE;
+    LLDrawPoolAvatar::sShadowPass = -1;
 }
 
 void LLDrawPoolAvatar::renderShadow(S32 pass)
@@ -480,16 +539,68 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
 		return;
 	}
 	
-	if (pass == 0)
+    LLDrawPoolAvatar::sShadowPass = pass;
+
+	if (pass == SHADOW_PASS_AVATAR_OPAQUE)
 	{
+        LLDrawPoolAvatar::sSkipTransparent = true;
 		avatarp->renderSkinned();
+        LLDrawPoolAvatar::sSkipTransparent = false;
 	}
-	else
+    else if (pass == SHADOW_PASS_AVATAR_ALPHA_BLEND)
 	{
-		for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
-		{
-			renderRigged(avatarp, i);
-		}
+        LLDrawPoolAvatar::sSkipOpaque = true;
+		avatarp->renderSkinned();
+        LLDrawPoolAvatar::sSkipOpaque = false;
+	}
+    else if (pass == SHADOW_PASS_AVATAR_ALPHA_MASK)
+	{
+        LLDrawPoolAvatar::sSkipOpaque = true;
+		avatarp->renderSkinned();
+        LLDrawPoolAvatar::sSkipOpaque = false;
+	}
+    else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha
+	{
+        LLDrawPoolAvatar::sSkipOpaque = true;
+        renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
+        renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
+        renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
+        renderRigged(avatarp, RIGGED_ALPHA);
+        renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);
+        renderRigged(avatarp, RIGGED_GLOW);
+        LLDrawPoolAvatar::sSkipOpaque = false;
+	}
+    else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask
+	{
+        LLDrawPoolAvatar::sSkipOpaque = true;
+        renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
+        renderRigged(avatarp, RIGGED_NORMMAP_MASK);
+        renderRigged(avatarp, RIGGED_SPECMAP_MASK);
+		renderRigged(avatarp, RIGGED_NORMSPEC_MASK);    
+        renderRigged(avatarp, RIGGED_GLOW);
+        LLDrawPoolAvatar::sSkipOpaque = false;
+	}
+	else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE
+	{
+        LLDrawPoolAvatar::sSkipTransparent = true;
+		renderRigged(avatarp, RIGGED_MATERIAL);
+        renderRigged(avatarp, RIGGED_SPECMAP);
+        renderRigged(avatarp, RIGGED_SPECMAP_BLEND);		
+		renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
+		renderRigged(avatarp, RIGGED_NORMMAP);
+		renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
+		renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
+		renderRigged(avatarp, RIGGED_NORMSPEC);
+		renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
+		renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
+		renderRigged(avatarp, RIGGED_SIMPLE);
+		renderRigged(avatarp, RIGGED_FULLBRIGHT);
+		renderRigged(avatarp, RIGGED_SHINY);
+		renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY);
+		renderRigged(avatarp, RIGGED_GLOW);
+		renderRigged(avatarp, RIGGED_DEFERRED_BUMP);
+		renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE);
+        LLDrawPoolAvatar::sSkipTransparent = false;
 	}
 }
 
@@ -1737,8 +1848,81 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 
 		LLVertexBuffer* buff = face->getVertexBuffer();
 
+        const LLTextureEntry* tex_entry = face->getTextureEntry();
+		LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr;
+
+        if (LLDrawPoolAvatar::sShadowPass >= 0)
+        {
+            bool is_alpha_blend = false;
+            bool is_alpha_mask  = false;
+
+            if (mat)
+            {                
+                switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
+                {
+                    case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
+                    {
+                        is_alpha_mask = true;
+                    }
+                    break;
+
+                    case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
+                    {
+                        is_alpha_blend = true;
+                    }
+                    break;
+
+                    case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
+                    case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT:
+                    case LLMaterial::DIFFUSE_ALPHA_MODE_NONE:
+                    default:
+                        break;
+                }
+            }
+
+            if (tex_entry)
+            {
+                if (tex_entry->getAlpha() <= 0.99f)
+                {
+                    is_alpha_blend = true;
+                }
+            }
+
+            LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
+            if (tex)
+            {
+                LLGLenum image_format = tex->getPrimaryFormat();
+                if (tex->getIsAlphaMask())
+                {
+                    is_alpha_mask = true;
+                }
+                else if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA))
+                {
+                    is_alpha_blend = true;
+                }
+            }
+
+            // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass...
+            if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK))
+            {
+                return;
+            }
+
+            // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass...
+            if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND))
+            {
+                return;
+            }
+
+            // if this is opaque content and we're skipping opaques...
+            if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque)
+            {
+                return;
+            }
+        }
+
 		if (buff)
-		{
+		{        
 			if (sShaderLevel > 0)
 			{
                 // upload matrix palette to shader
@@ -1794,9 +1978,6 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 				gGL.diffuseColor4f(0,0,0,face->getTextureEntry()->getGlow());
 			}*/
 
-			const LLTextureEntry* te = face->getTextureEntry();
-			LLMaterial* mat = te->getMaterialParams().get();
-
 			if (mat)
 			{
 				//order is important here LLRender::DIFFUSE_MAP should be last, becouse it change 
@@ -1827,12 +2008,12 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 
 				if (mat->getSpecularID().isNull())
 				{
-					env = te->getShiny()*0.25f;
+					env = tex_entry->getShiny()*0.25f;
 					col.set(env,env,env,0);
 					spec = env;
 				}
 		
-				BOOL fullbright = te->getFullbright();
+				BOOL fullbright = tex_entry->getFullbright();
 
 				sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f);
 				sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
@@ -1840,7 +2021,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 
 				if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 				{
-					sVertexProgram->setMinimumAlpha(mat->getAlphaMaskCutoff()/255.f);
+                    F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
+					sVertexProgram->setMinimumAlpha(cutoff);
 				}
 				else
 				{
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index b9d2204052..8afe6788ff 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -55,105 +55,7 @@ public:
 							LLVertexBuffer::MAP_CLOTHWEIGHT
 	};
 
-	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
-
-	virtual S32 getVertexShaderLevel() const;
-
-	LLDrawPoolAvatar();
-
-	static LLMatrix4& getModelView();
-
-	/*virtual*/ LLDrawPool *instancePool();
-
-	/*virtual*/ S32  getNumPasses();
-	/*virtual*/ void beginRenderPass(S32 pass);
-	/*virtual*/ void endRenderPass(S32 pass);
-	/*virtual*/ void prerender();
-	/*virtual*/ void render(S32 pass = 0);
-
-	/*virtual*/ S32 getNumDeferredPasses();
-	/*virtual*/ void beginDeferredPass(S32 pass);
-	/*virtual*/ void endDeferredPass(S32 pass);
-	/*virtual*/ void renderDeferred(S32 pass);
-	
-	/*virtual*/ S32 getNumPostDeferredPasses();
-	/*virtual*/ void beginPostDeferredPass(S32 pass);
-	/*virtual*/ void endPostDeferredPass(S32 pass);
-	/*virtual*/ void renderPostDeferred(S32 pass);
-
-	/*virtual*/ S32 getNumShadowPasses();
-	/*virtual*/ void beginShadowPass(S32 pass);
-	/*virtual*/ void endShadowPass(S32 pass);
-	/*virtual*/ void renderShadow(S32 pass);
-
-	void beginRigid();
-	void beginImpostor();
-	void beginSkinned();
-	
-	void endRigid();
-	void endImpostor();
-	void endSkinned();
-
-	void beginDeferredImpostor();
-	void beginDeferredRigid();
-	void beginDeferredSkinned();
-	
-	void endDeferredImpostor();
-	void endDeferredRigid();
-	void endDeferredSkinned();
-	
-	void beginPostDeferredAlpha();
-	void endPostDeferredAlpha();
-
-	void beginRiggedSimple();
-	void beginRiggedFullbright();
-	void beginRiggedFullbrightShiny();
-	void beginRiggedShinySimple();
-	void beginRiggedAlpha();
-	void beginRiggedFullbrightAlpha();
-	void beginRiggedGlow();
-	void beginDeferredRiggedAlpha();
-	void beginDeferredRiggedMaterial(S32 pass);
-	void beginDeferredRiggedMaterialAlpha(S32 pass);
-
-	void endRiggedSimple();
-	void endRiggedFullbright();
-	void endRiggedFullbrightShiny();
-	void endRiggedShinySimple();
-	void endRiggedAlpha();
-	void endRiggedFullbrightAlpha();
-	void endRiggedGlow();
-	void endDeferredRiggedAlpha();
-	void endDeferredRiggedMaterial(S32 pass);
-	void endDeferredRiggedMaterialAlpha(S32 pass);
-
-	void beginDeferredRiggedSimple();
-	void beginDeferredRiggedBump();
-	
-	void endDeferredRiggedSimple();
-	void endDeferredRiggedBump();
-		
-	void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
-	void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
-									  LLFace* facep, 
-									  const LLMeshSkinInfo* skin, 
-									  LLVolume* volume,
-									  const LLVolumeFace& vol_face);
-	void updateRiggedVertexBuffers(LLVOAvatar* avatar);
-
-	void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
-	void renderRiggedSimple(LLVOAvatar* avatar);
-	void renderRiggedAlpha(LLVOAvatar* avatar);
-	void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
-	void renderRiggedFullbright(LLVOAvatar* avatar);
-	void renderRiggedShinySimple(LLVOAvatar* avatar);
-	void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
-	void renderRiggedGlow(LLVOAvatar* avatar);
-	void renderDeferredRiggedSimple(LLVOAvatar* avatar);
-	void renderDeferredRiggedBump(LLVOAvatar* avatar);
-	void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass);
-	
-	typedef enum
+    typedef enum
 	{
 		RIGGED_MATERIAL=0,
 		RIGGED_MATERIAL_ALPHA,
@@ -258,6 +160,117 @@ public:
 							 LLVertexBuffer::MAP_WEIGHT4,
 	} eRiggedDataMask;
 
+typedef enum
+	{
+		SHADOW_PASS_AVATAR_OPAQUE,
+        SHADOW_PASS_AVATAR_ALPHA_BLEND,
+        SHADOW_PASS_AVATAR_ALPHA_MASK,
+        SHADOW_PASS_ATTACHMENT_ALPHA_BLEND,
+        SHADOW_PASS_ATTACHMENT_ALPHA_MASK,
+        SHADOW_PASS_ATTACHMENT_OPAQUE,
+        NUM_SHADOW_PASSES
+	} eShadowPass;
+
+	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+
+	virtual S32 getVertexShaderLevel() const;
+
+	LLDrawPoolAvatar();
+
+	static LLMatrix4& getModelView();
+
+	/*virtual*/ LLDrawPool *instancePool();
+
+	/*virtual*/ S32  getNumPasses();
+	/*virtual*/ void beginRenderPass(S32 pass);
+	/*virtual*/ void endRenderPass(S32 pass);
+	/*virtual*/ void prerender();
+	/*virtual*/ void render(S32 pass = 0);
+
+	/*virtual*/ S32 getNumDeferredPasses();
+	/*virtual*/ void beginDeferredPass(S32 pass);
+	/*virtual*/ void endDeferredPass(S32 pass);
+	/*virtual*/ void renderDeferred(S32 pass);
+	
+	/*virtual*/ S32 getNumPostDeferredPasses();
+	/*virtual*/ void beginPostDeferredPass(S32 pass);
+	/*virtual*/ void endPostDeferredPass(S32 pass);
+	/*virtual*/ void renderPostDeferred(S32 pass);
+
+	/*virtual*/ S32 getNumShadowPasses();
+	/*virtual*/ void beginShadowPass(S32 pass);
+	/*virtual*/ void endShadowPass(S32 pass);
+	/*virtual*/ void renderShadow(S32 pass);
+
+	void beginRigid();
+	void beginImpostor();
+	void beginSkinned();
+	
+	void endRigid();
+	void endImpostor();
+	void endSkinned();
+
+	void beginDeferredImpostor();
+	void beginDeferredRigid();
+	void beginDeferredSkinned();
+	
+	void endDeferredImpostor();
+	void endDeferredRigid();
+	void endDeferredSkinned();
+	
+	void beginPostDeferredAlpha();
+	void endPostDeferredAlpha();
+
+	void beginRiggedSimple();
+	void beginRiggedFullbright();
+	void beginRiggedFullbrightShiny();
+	void beginRiggedShinySimple();
+	void beginRiggedAlpha();
+	void beginRiggedFullbrightAlpha();
+	void beginRiggedGlow();
+	void beginDeferredRiggedAlpha();
+	void beginDeferredRiggedMaterial(S32 pass);
+	void beginDeferredRiggedMaterialAlpha(S32 pass);
+
+	void endRiggedSimple();
+	void endRiggedFullbright();
+	void endRiggedFullbrightShiny();
+	void endRiggedShinySimple();
+	void endRiggedAlpha();
+	void endRiggedFullbrightAlpha();
+	void endRiggedGlow();
+	void endDeferredRiggedAlpha();
+	void endDeferredRiggedMaterial(S32 pass);
+	void endDeferredRiggedMaterialAlpha(S32 pass);
+
+	void beginDeferredRiggedSimple();
+	void beginDeferredRiggedBump();
+	
+	void endDeferredRiggedSimple();
+	void endDeferredRiggedBump();
+		
+	void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
+	void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
+									  LLFace* facep, 
+									  const LLMeshSkinInfo* skin, 
+									  LLVolume* volume,
+									  const LLVolumeFace& vol_face);
+	void updateRiggedVertexBuffers(LLVOAvatar* avatar);
+
+	void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
+	void renderRiggedSimple(LLVOAvatar* avatar);
+	void renderRiggedAlpha(LLVOAvatar* avatar);
+	void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
+	void renderRiggedFullbright(LLVOAvatar* avatar);
+	void renderRiggedShinySimple(LLVOAvatar* avatar);
+	void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
+	void renderRiggedGlow(LLVOAvatar* avatar);
+	void renderDeferredRiggedSimple(LLVOAvatar* avatar);
+	void renderDeferredRiggedBump(LLVOAvatar* avatar);
+	void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass);
+	
+	
+
 	void addRiggedFace(LLFace* facep, U32 type);
 	void removeRiggedFace(LLFace* facep); 
 
@@ -271,6 +284,7 @@ public:
 
 	static BOOL sSkipOpaque;
 	static BOOL sSkipTransparent;
+    static S32  sShadowPass;
 	static S32 sDiffuseChannel;
 	static F32 sMinimumAlpha;
 
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index d2acfa291c..2468aeffa2 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -212,7 +212,11 @@ LLGLSLShader			gDeferredShadowProgram;
 LLGLSLShader			gDeferredShadowCubeProgram;
 LLGLSLShader			gDeferredShadowAlphaMaskProgram;
 LLGLSLShader			gDeferredAvatarShadowProgram;
+LLGLSLShader			gDeferredAvatarAlphaShadowProgram;
+LLGLSLShader			gDeferredAvatarAlphaMaskShadowProgram;
 LLGLSLShader			gDeferredAttachmentShadowProgram;
+LLGLSLShader			gDeferredAttachmentAlphaShadowProgram;
+LLGLSLShader			gDeferredAttachmentAlphaMaskShadowProgram;
 LLGLSLShader			gDeferredAlphaProgram;
 LLGLSLShader			gDeferredAlphaImpostorProgram;
 LLGLSLShader			gDeferredAlphaWaterProgram;
@@ -1836,6 +1840,30 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
 	}
 
+    if (success)
+	{
+		gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader";
+		gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true;
+		gDeferredAvatarAlphaShadowProgram.mShaderFiles.clear();
+		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAvatarAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+		gDeferredAvatarAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL);
+	}
+
+    if (success)
+	{
+		gDeferredAvatarAlphaMaskShadowProgram.mName = "Deferred Avatar Alpha Mask Shadow Shader";
+		gDeferredAvatarAlphaMaskShadowProgram.mFeatures.hasSkinning  = true;
+		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.clear();
+		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAvatarAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+		gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL);
+	}
+
 	if (success)
 	{
 		gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader";
@@ -1847,6 +1875,30 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
 	}
+    
+    if (success)
+	{
+		gDeferredAttachmentAlphaShadowProgram.mName = "Deferred Attachment Alpha Shadow Shader";
+		gDeferredAttachmentAlphaShadowProgram.mFeatures.hasObjectSkinning = true;
+		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.clear();
+		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAttachmentAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+		gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL);
+	}
+
+    if (success)
+	{
+		gDeferredAttachmentAlphaMaskShadowProgram.mName = "Deferred Attachment Alpha Mask Shadow Shader";
+		gDeferredAttachmentAlphaMaskShadowProgram.mFeatures.hasObjectSkinning = true;
+		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.clear();
+		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAttachmentAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+		gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL);
+	}
 
 	if (success)
 	{
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 923aa522ad..9ba7d7f742 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -319,6 +319,10 @@ extern LLGLSLShader			gDeferredPostNoDoFProgram;
 extern LLGLSLShader			gDeferredPostGammaCorrectProgram;
 extern LLGLSLShader			gDeferredAvatarShadowProgram;
 extern LLGLSLShader			gDeferredAttachmentShadowProgram;
+extern LLGLSLShader			gDeferredAttachmentAlphaShadowProgram;
+extern LLGLSLShader			gDeferredAttachmentAlphaMaskShadowProgram;
+extern LLGLSLShader			gDeferredAvatarAlphaShadowProgram;
+extern LLGLSLShader			gDeferredAvatarAlphaMaskShadowProgram;
 extern LLGLSLShader			gDeferredAlphaProgram;
 extern LLGLSLShader			gDeferredAlphaImpostorProgram;
 extern LLGLSLShader			gDeferredFullbrightProgram;
-- 
cgit v1.2.3