From eb283701afc7ecbe3009a9fb75be1dcb222a383b Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Tue, 4 May 2010 00:45:28 -0500
Subject: Deferred pipeline integration of rigged attachments and cleanup.

---
 indra/llrender/llvertexbuffer.h                    |   2 +-
 .../shaders/class1/deferred/alphaF.glsl            |   5 +-
 .../shaders/class1/deferred/alphaV.glsl            |   2 +-
 .../shaders/class1/deferred/avatarAlphaV.glsl      |   4 +-
 .../shaders/class1/deferred/diffuseV.glsl          |   2 +-
 .../shaders/class2/deferred/alphaF.glsl            |   2 +-
 indra/newview/lldrawpoolavatar.cpp                 | 302 +++++++++++++++------
 indra/newview/lldrawpoolavatar.h                   |  51 +++-
 indra/newview/lldrawpoolbump.cpp                   |  27 +-
 indra/newview/lldrawpoolbump.h                     |   7 +-
 indra/newview/llviewershadermgr.cpp                |  36 ++-
 indra/newview/llviewershadermgr.h                  |   2 +
 indra/newview/llvovolume.cpp                       |  15 +
 13 files changed, 359 insertions(+), 98 deletions(-)

(limited to 'indra')

diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 225237215c..d1700aa54a 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -190,7 +190,7 @@ public:
 	U8* getIndicesPointer() const			{ return useVBOs() ? NULL : mMappedIndexData; }
 	U8* getVerticesPointer() const			{ return useVBOs() ? NULL : mMappedData; }
 	S32 getStride() const					{ return mStride; }
-	S32 getTypeMask() const					{ return mTypeMask; }
+	U32 getTypeMask() const					{ return mTypeMask; }
 	BOOL hasDataType(S32 type) const		{ return ((1 << type) & getTypeMask()) ? TRUE : FALSE; }
 	S32 getSize() const						{ return mNumVerts*mStride; }
 	S32 getIndicesSize() const				{ return mNumIndices * sizeof(U16); }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index fea2e16090..6f027de6a2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -22,7 +22,6 @@ varying vec3 vary_ambient;
 varying vec3 vary_directional;
 varying vec3 vary_fragcoord;
 varying vec3 vary_position;
-varying vec3 vary_light;
 
 uniform mat4 inv_proj;
 
@@ -55,8 +54,8 @@ void main()
 
 	color.rgb = scaleSoftClip(color.rgb);
 
-	//gl_FragColor = gl_Color;
-	gl_FragColor = color;
+	gl_FragColor = gl_Color;
+	//gl_FragColor = color;
 	//gl_FragColor = vec4(1,0,1,1);
 	//gl_FragColor = vec4(1,0,1,1)*shadow;
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 04e556c11a..43200f1b07 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -36,7 +36,7 @@ void main()
 	vec4 pos = (gl_ModelViewMatrix * gl_Vertex);
 	vec3 norm = normalize(gl_NormalMatrix * gl_Normal);
 	
-	vary_position = pos.xyz + norm.xyz * (-pos.z/64.0*shadow_offset+shadow_bias);
+	vary_position = pos.xyz;
 		
 	calcAtmospherics(pos.xyz);
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index 650fbcc3f5..da1dafda36 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -17,7 +17,7 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
 vec3 scaleUpLight(vec3 light);
 
-varying vec4 vary_position;
+varying vec3 vary_position;
 varying vec3 vary_ambient;
 varying vec3 vary_directional;
 varying vec3 vary_normal;
@@ -41,7 +41,7 @@ void main()
 	norm = normalize(norm);
 		
 	gl_Position = gl_ProjectionMatrix * pos;
-	vary_position = pos;
+	vary_position = pos.xyz;
 	vary_normal = norm;	
 	
 	calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index b458842657..44468cdfa2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -13,7 +13,7 @@ void main()
 	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
 	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
 	
-	vary_nomral = normalize(gl_NormalMatrix * gl_Normal);
+	vary_normal = normalize(gl_NormalMatrix * gl_Normal);
 
 	gl_FrontColor = gl_Color;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
index 665fe16b43..fa6b4e2afb 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl
@@ -115,7 +115,7 @@ void main()
 
 	//gl_FragColor = gl_Color;
 	gl_FragColor = color;
-	//gl_FragColor = vec4(1,0,1,1)*shadow;
+	//gl_FragColor = vec4(1,shadow,1,1);
 	
 }
 
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 866aea42c4..ac599caa5b 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -63,6 +63,8 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;
 BOOL	LLDrawPoolAvatar::sSkipOpaque = FALSE;
 BOOL	LLDrawPoolAvatar::sSkipTransparent = FALSE;
 
+static bool is_deferred_render = false;
+
 extern BOOL gUseGLPick;
 
 F32 CLOTHING_GRAVITY_EFFECT = 0.7f;
@@ -100,6 +102,18 @@ S32 specular_channel = -1;
 S32 diffuse_channel = -1;
 S32 cube_channel = -1;
 
+static const U32 rigged_data_mask[] = {
+	LLDrawPoolAvatar::RIGGED_SIMPLE_MASK,
+	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK,
+	LLDrawPoolAvatar::RIGGED_SHINY_MASK,
+	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK,
+	LLDrawPoolAvatar::RIGGED_GLOW_MASK,
+	LLDrawPoolAvatar::RIGGED_ALPHA_MASK,
+	LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK,
+	LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK,						 
+	LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK,
+};
+
 
 static LLFastTimer::DeclareTimer FTM_SHADOW_AVATAR("Avatar Shadow");
 
@@ -155,21 +169,17 @@ LLMatrix4& LLDrawPoolAvatar::getModelView()
 //-----------------------------------------------------------------------------
 
 
-S32 LLDrawPoolAvatar::getNumDeferredPasses()
-{
-	return getNumPasses();
-}
 
 void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_CHARACTERS);
 	
 	sSkipTransparent = TRUE;
-
+	is_deferred_render = true;
+	
 	if (LLPipeline::sImpostorRender)
-	{
-		beginDeferredSkinned();
-		return;
+	{ //impostor pass does not have rigid or impostor rendering
+		pass += 2;
 	}
 
 	switch (pass)
@@ -184,7 +194,10 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
 		beginDeferredSkinned();
 		break;
 	case 3:
-		beginDeferredRigged();
+		beginDeferredRiggedSimple();
+		break;
+	case 4:
+		beginDeferredRiggedBump();
 		break;
 	}
 }
@@ -194,11 +207,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
 	LLFastTimer t(FTM_RENDER_CHARACTERS);
 
 	sSkipTransparent = FALSE;
+	is_deferred_render = false;
 
 	if (LLPipeline::sImpostorRender)
 	{
-		endDeferredSkinned();
-		return;
+		pass += 2;
 	}
 
 	switch (pass)
@@ -213,7 +226,11 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
 		endDeferredSkinned();
 		break;
 	case 3:
-		endDeferredRigged();
+		endDeferredRiggedSimple();
+		break;
+	case 4:
+		endDeferredRiggedBump();
+		break;
 	}
 }
 
@@ -224,10 +241,35 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass)
 
 S32 LLDrawPoolAvatar::getNumPostDeferredPasses()
 {
-	return 1;
+	return 6;
 }
 
 void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
+{
+	switch (pass)
+	{
+	case 0:
+		beginPostDeferredAlpha();
+		break;
+	case 1:
+		beginRiggedFullbright();
+		break;
+	case 2:
+		beginRiggedFullbrightShiny();
+		break;
+	case 3:
+		beginDeferredRiggedAlpha();
+		break;
+	case 4:
+		beginRiggedFullbrightAlpha();
+		break;
+	case 5:
+		beginRiggedGlow();
+		break;
+	}
+}
+
+void LLDrawPoolAvatar::beginPostDeferredAlpha()
 {
 	sSkipOpaque = TRUE;
 	sShaderLevel = mVertexShaderLevel;
@@ -240,7 +282,49 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
 	enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]);
 }
 
+void LLDrawPoolAvatar::beginDeferredRiggedAlpha()
+{
+	sVertexProgram = &gDeferredSkinnedAlphaProgram;
+	gPipeline.bindDeferredShader(*sVertexProgram);
+	diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+	LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+	gPipeline.enableLightsDynamic();
+}
+
+void LLDrawPoolAvatar::endDeferredRiggedAlpha()
+{
+	LLVertexBuffer::unbind();
+	gPipeline.unbindDeferredShader(*sVertexProgram);
+	LLVertexBuffer::sWeight4Loc = -1;
+	sVertexProgram = NULL;
+}
+
 void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)
+{
+	switch (pass)
+	{
+	case 0:
+		endPostDeferredAlpha();
+		break;
+	case 1:
+		endRiggedFullbright();
+		break;
+	case 2:
+		endRiggedFullbrightShiny();
+		break;
+	case 3:
+		endDeferredRiggedAlpha();
+		break;
+	case 4:
+		endRiggedFullbrightAlpha();
+		break;
+	case 5:
+		endRiggedGlow();
+		break;
+	}
+}
+
+void LLDrawPoolAvatar::endPostDeferredAlpha()
 {
 	// if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
 	sRenderingSkinned = FALSE;
@@ -254,7 +338,17 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)
 
 void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
 {
-	render(2); //pass 2 = skinned
+	const S32 actual_pass[] =
+	{ //map post deferred pass numbers to what render() expects
+		2, //skinned
+		4, // rigged fullbright
+		6, //rigged fullbright shiny
+		7, //rigged alpha
+		8, //rigged fullbright alpha
+		9, //rigged glow
+	};
+
+	render(actual_pass[pass]);
 }
 
 
@@ -288,6 +382,7 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 	else
 	{
 		sVertexProgram = &gDeferredAttachmentShadowProgram;
+		diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 		sVertexProgram->bind();
 		LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
 	}
@@ -352,7 +447,12 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
 	}
 	else
 	{
-		avatarp->renderSkinnedAttachments();
+		renderRigged(avatarp, RIGGED_SIMPLE);
+		renderRigged(avatarp, RIGGED_ALPHA);
+		renderRigged(avatarp, RIGGED_FULLBRIGHT);
+		renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY);
+		renderRigged(avatarp, RIGGED_SHINY);
+		renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);
 	}
 }
 
@@ -360,7 +460,7 @@ S32 LLDrawPoolAvatar::getNumPasses()
 {
 	if (LLPipeline::sImpostorRender)
 	{
-		return 1;
+		return 8;
 	}
 	else if (getVertexShaderLevel() > 0)
 	{
@@ -372,6 +472,19 @@ S32 LLDrawPoolAvatar::getNumPasses()
 	}
 }
 
+S32 LLDrawPoolAvatar::getNumDeferredPasses()
+{
+	if (LLPipeline::sImpostorRender)
+	{
+		return 3;
+	}
+	else
+	{
+		return 5;
+	}
+}
+
+
 void LLDrawPoolAvatar::render(S32 pass)
 {
 	LLFastTimer t(FTM_RENDER_CHARACTERS);
@@ -391,9 +504,8 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
 	LLVertexBuffer::unbind();
 
 	if (LLPipeline::sImpostorRender)
-	{
-		beginSkinned();
-		return;
+	{ //impostor render does not have impostors or rigid rendering
+		pass += 2;
 	}
 
 	switch (pass)
@@ -437,8 +549,7 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)
 
 	if (LLPipeline::sImpostorRender)
 	{
-		endSkinned();
-		return;
+		pass += 2;		
 	}
 
 	switch (pass)
@@ -536,8 +647,8 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
 
 	sVertexProgram = &gDeferredImpostorProgram;
 
-	normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
 	specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
+	normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
 	diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 
 	sVertexProgram->bind();
@@ -774,18 +885,40 @@ void LLDrawPoolAvatar::endRiggedFullbrightShiny()
 }
 
 
-void LLDrawPoolAvatar::beginDeferredRigged()
+void LLDrawPoolAvatar::beginDeferredRiggedSimple()
 {
 	sVertexProgram = &gDeferredSkinnedDiffuseProgram;
+	diffuse_channel = 0;
+	sVertexProgram->bind();
+	LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
+}
+
+void LLDrawPoolAvatar::endDeferredRiggedSimple()
+{
+	LLVertexBuffer::unbind();
+	sVertexProgram->unbind();
+	LLVertexBuffer::sWeight4Loc = -1;
+	sVertexProgram = NULL;
+}
+
+void LLDrawPoolAvatar::beginDeferredRiggedBump()
+{
+	sVertexProgram = &gDeferredSkinnedBumpProgram;
 	sVertexProgram->bind();
+	normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+	diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT);
 }
 
-void LLDrawPoolAvatar::endDeferredRigged()
+void LLDrawPoolAvatar::endDeferredRiggedBump()
 {
 	LLVertexBuffer::unbind();
+	sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
+	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	sVertexProgram->unbind();
 	LLVertexBuffer::sWeight4Loc = -1;
+	normal_channel = -1;
+	diffuse_channel = -1;
 	sVertexProgram = NULL;
 }
 
@@ -933,13 +1066,28 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 
 	if (pass == 3)
 	{
-		renderRiggedSimple(avatarp);
+		if (is_deferred_render)
+		{
+			renderDeferredRiggedSimple(avatarp);
+		}
+		else
+		{
+			renderRiggedSimple(avatarp);
+		}
 		return;
 	}
 
 	if (pass == 4)
 	{
-		renderRiggedFullbright(avatarp);
+		if (is_deferred_render)
+		{
+			renderDeferredRiggedBump(avatarp);
+		}
+		else
+		{
+			renderRiggedFullbright(avatarp);
+		}
+
 		return;
 	}
 
@@ -995,6 +1143,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 		renderRiggedGlow(avatarp);
 		gGL.setColorMask(true, false);
 		gGL.setSceneBlendType(LLRender::BT_ALPHA);
+		return;
 	}
 
 	
@@ -1034,12 +1183,21 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
 	}
 }
 
-void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face, U32 data_mask)
+void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)
 {
+	U32 data_mask = 0;
+	for (U32 i = 0; i < face->mRiggedIndex.size(); ++i)
+	{
+		if (face->mRiggedIndex[i] > -1)
+		{
+			data_mask |= rigged_data_mask[i];
+		}
+	}
+
 	LLVertexBuffer* buff = face->mVertexBuffer;
 
 	if (!buff || 
-		!buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) ||
+		buff->getTypeMask() != data_mask ||
 		buff->getRequestedVerts() != vol_face.mVertices.size())
 	{
 		face->setGeomIndex(0);
@@ -1067,7 +1225,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLFace* face, const LLMeshSk
 	}
 }
 
-void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow)
+void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 {
 	for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
 	{
@@ -1106,8 +1264,10 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data
 		}
 
 		const LLVolumeFace& vol_face = volume->getVolumeFace(te);
-		updateRiggedFaceVertexBuffer(face, skin, volume, vol_face, data_mask);
+		updateRiggedFaceVertexBuffer(face, skin, volume, vol_face);
 		
+		U32 data_mask = rigged_data_mask[type];
+
 		LLVertexBuffer* buff = face->mVertexBuffer;
 
 		if (buff)
@@ -1145,84 +1305,72 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, const U32 data
 				glColor4f(0,0,0,face->getTextureEntry()->getGlow());
 			}
 
-			gGL.getTexUnit(0)->bind(face->getTexture());
-			buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);		
+			gGL.getTexUnit(diffuse_channel)->bind(face->getTexture());
+			if (normal_channel > -1)
+			{
+				LLDrawPoolBump::bindBumpMap(face, normal_channel);
+			}
+
+			if (face->mTextureMatrix)
+			{
+				glMatrixMode(GL_TEXTURE);
+				glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix);
+				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
+				glLoadIdentity();
+				glMatrixMode(GL_MODELVIEW);
+			}
+			else
+			{
+				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);		
+			}
 		}
 	}
 }
 
-void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
+void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_NORMAL | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
+	renderRigged(avatar, RIGGED_DEFERRED_SIMPLE);
+}
 
-	renderRigged(avatar, RIGGED_SIMPLE, data_mask);
+void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar)
+{
+	renderRigged(avatar, RIGGED_DEFERRED_BUMP);
 }
 
-void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar)
+void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
+	renderRigged(avatar, RIGGED_SIMPLE);
+}
 
-	renderRigged(avatar, RIGGED_FULLBRIGHT, data_mask);
+void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar)
+{
+	renderRigged(avatar, RIGGED_FULLBRIGHT);
 }
 
 	
 void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_NORMAL | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
-
-	renderRigged(avatar, RIGGED_SHINY, data_mask);
+	renderRigged(avatar, RIGGED_SHINY);
 }
 
 void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_NORMAL | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
-
-	renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY, data_mask);
+	renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY);
 }
 
 void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_NORMAL | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
-
-	renderRigged(avatar, RIGGED_ALPHA, data_mask);
+	renderRigged(avatar, RIGGED_ALPHA);
 }
 
 void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_COLOR |
-							LLVertexBuffer::MAP_WEIGHT4;
-
-	renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA, data_mask);
+	renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA);
 }
 
 void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar)
 {
-	const U32 data_mask =	LLVertexBuffer::MAP_VERTEX | 
-							LLVertexBuffer::MAP_TEXCOORD0 |
-							LLVertexBuffer::MAP_WEIGHT4;
-
-	renderRigged(avatar, RIGGED_GLOW, data_mask, true);
+	renderRigged(avatar, RIGGED_GLOW, true);
 }
 
 
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 59f9cf7ddb..bab6f01480 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -103,6 +103,8 @@ public:
 	void beginRiggedAlpha();
 	void beginRiggedFullbrightAlpha();
 	void beginRiggedGlow();
+	void beginPostDeferredAlpha();
+	void beginDeferredRiggedAlpha();
 
 	void endRigid();
 	void endImpostor();
@@ -114,24 +116,27 @@ public:
 	void endRiggedAlpha();
 	void endRiggedFullbrightAlpha();
 	void endRiggedGlow();
+	void endPostDeferredAlpha();
+	void endDeferredRiggedAlpha();
 
 	void beginDeferredImpostor();
 	void beginDeferredRigid();
 	void beginDeferredSkinned();
-	void beginDeferredRigged();
+	void beginDeferredRiggedSimple();
+	void beginDeferredRiggedBump();
 	
 	void endDeferredImpostor();
 	void endDeferredRigid();
 	void endDeferredSkinned();
-	void endDeferredRigged();
+	void endDeferredRiggedSimple();
+	void endDeferredRiggedBump();
 		
 	void updateRiggedFaceVertexBuffer(LLFace* facep, 
 									  const LLMeshSkinInfo* skin, 
 									  LLVolume* volume,
-									  const LLVolumeFace& vol_face, 
-									  U32 data_mask);
+									  const LLVolumeFace& vol_face);
 
-	void renderRigged(LLVOAvatar* avatar, U32 type, const U32 data_mask, bool glow = false);
+	void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
 	void renderRiggedSimple(LLVOAvatar* avatar);
 	void renderRiggedAlpha(LLVOAvatar* avatar);
 	void renderRiggedFullbrightAlpha(LLVOAvatar* avatar);
@@ -139,6 +144,8 @@ public:
 	void renderRiggedShinySimple(LLVOAvatar* avatar);
 	void renderRiggedFullbrightShiny(LLVOAvatar* avatar);
 	void renderRiggedGlow(LLVOAvatar* avatar);
+	void renderDeferredRiggedSimple(LLVOAvatar* avatar);
+	void renderDeferredRiggedBump(LLVOAvatar* avatar);
 
 	/*virtual*/ LLViewerTexture *getDebugTexture();
 	/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
@@ -154,11 +161,43 @@ public:
 		RIGGED_GLOW,
 		RIGGED_ALPHA,
 		RIGGED_FULLBRIGHT_ALPHA,
+		RIGGED_DEFERRED_BUMP,
+		RIGGED_DEFERRED_SIMPLE,
 		NUM_RIGGED_PASSES,
 		RIGGED_UNKNOWN,
 	} eRiggedPass;
 
-	
+	typedef enum
+	{
+		RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | 
+							 LLVertexBuffer::MAP_NORMAL | 
+							 LLVertexBuffer::MAP_TEXCOORD0 |
+							 LLVertexBuffer::MAP_COLOR |
+							 LLVertexBuffer::MAP_WEIGHT4,
+		RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX | 
+							 LLVertexBuffer::MAP_TEXCOORD0 |
+							 LLVertexBuffer::MAP_COLOR |
+							 LLVertexBuffer::MAP_WEIGHT4,
+		RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK,
+		RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK,							 
+		RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX | 
+							 LLVertexBuffer::MAP_TEXCOORD0 |
+							 LLVertexBuffer::MAP_WEIGHT4,
+		RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK,
+		RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK,
+		RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX | 
+							 LLVertexBuffer::MAP_NORMAL | 
+							 LLVertexBuffer::MAP_TEXCOORD0 |
+							 LLVertexBuffer::MAP_BINORMAL |
+							 LLVertexBuffer::MAP_COLOR |
+							 LLVertexBuffer::MAP_WEIGHT4,
+		RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | 
+							 LLVertexBuffer::MAP_NORMAL | 
+							 LLVertexBuffer::MAP_TEXCOORD0 |
+							 LLVertexBuffer::MAP_COLOR |
+							 LLVertexBuffer::MAP_WEIGHT4,
+	} eRiggedDataMask;
+
 	void addRiggedFace(LLFace* facep, U32 type);
 	void removeRiggedFace(LLFace* facep); 
 
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 2f449fa42f..906615ade8 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -591,18 +591,37 @@ void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL
 // static
 BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
 {
-	LLViewerTexture* bump = NULL;
-
 	U8 bump_code = params.mBump;
 
+	return bindBumpMap(bump_code, params.mTexture, params.mVSize, channel);
+}
+
+//static
+BOOL LLDrawPoolBump::bindBumpMap(LLFace* face, S32 channel)
+{
+	const LLTextureEntry* te = face->getTextureEntry();
+	if (te)
+	{
+		U8 bump_code = te->getBumpmap();
+		return bindBumpMap(bump_code, face->getTexture(), face->getVirtualSize(), channel);
+	}
+
+	return FALSE;
+}
+
+//static
+BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsize, S32 channel)
+{
 	//Note: texture atlas does not support bump texture now.
-	LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(params.mTexture) ;
+	LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(texture) ;
 	if(!tex)
 	{
 		//if the texture is not a fetched texture
 		return FALSE;
 	}
 
+	LLViewerTexture* bump = NULL;
+
 	switch( bump_code )
 	{
 	case BE_NO_BUMP:		
@@ -616,7 +635,7 @@ BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params, S32 channel)
 		if( bump_code < LLStandardBumpmap::sStandardBumpmapCount )
 		{
 			bump = gStandardBumpmapList[bump_code].mImage;
-			gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize);
+			gBumpImageList.addTextureStats(bump_code, tex->getID(), vsize);
 		}
 		break;
 	}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 89bbefe778..127c9efe85 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -93,7 +93,12 @@ public:
 	/*virtual*/ void endPostDeferredPass(S32 pass);
 	/*virtual*/ void renderPostDeferred(S32 pass);
 
-	BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2);
+	static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2);
+	static BOOL bindBumpMap(LLFace* face, S32 channel = -2);
+
+private:
+	static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel);
+
 };
 
 enum EBumpEffect
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index eafc52748e..e64fdfc0b4 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -114,6 +114,8 @@ LLGLSLShader			gDeferredEdgeProgram;
 LLGLSLShader			gDeferredWaterProgram;
 LLGLSLShader			gDeferredDiffuseProgram;
 LLGLSLShader			gDeferredSkinnedDiffuseProgram;
+LLGLSLShader			gDeferredSkinnedBumpProgram;
+LLGLSLShader			gDeferredSkinnedAlphaProgram;
 LLGLSLShader			gDeferredBumpProgram;
 LLGLSLShader			gDeferredTerrainProgram;
 LLGLSLShader			gDeferredTreeProgram;
@@ -173,6 +175,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredLightProgram);
 	mShaderList.push_back(&gDeferredMultiLightProgram);
 	mShaderList.push_back(&gDeferredAlphaProgram);
+	mShaderList.push_back(&gDeferredSkinnedAlphaProgram);
 	mShaderList.push_back(&gDeferredFullbrightProgram);
 	mShaderList.push_back(&gDeferredPostGIProgram);
 	mShaderList.push_back(&gDeferredEdgeProgram);
@@ -591,6 +594,8 @@ void LLViewerShaderMgr::unloadShaders()
 
 	gDeferredDiffuseProgram.unload();
 	gDeferredSkinnedDiffuseProgram.unload();
+	gDeferredSkinnedBumpProgram.unload();
+	gDeferredSkinnedAlphaProgram.unload();
 
 	mVertexShaderLevel[SHADER_LIGHTING] = 0;
 	mVertexShaderLevel[SHADER_OBJECT] = 0;
@@ -906,6 +911,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredTreeProgram.unload();
 		gDeferredDiffuseProgram.unload();
 		gDeferredSkinnedDiffuseProgram.unload();
+		gDeferredSkinnedBumpProgram.unload();
+		gDeferredSkinnedAlphaProgram.unload();
 		gDeferredBumpProgram.unload();
 		gDeferredImpostorProgram.unload();
 		gDeferredTerrainProgram.unload();
@@ -958,6 +965,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader";
+		gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true;
+		gDeferredSkinnedBumpProgram.mShaderFiles.clear();
+		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL);
+	}
+
+	if (success)
+	{
+		gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
+		gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
+		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
+		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
+	}
+
 	if (success)
 	{
 		gDeferredBumpProgram.mName = "Deferred Bump Shader";
@@ -1176,7 +1210,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
 		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
 	}
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index bb28cd7ec2..da16a38427 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -350,6 +350,8 @@ extern LLGLSLShader			gDeferredEdgeProgram;
 extern LLGLSLShader			gDeferredWaterProgram;
 extern LLGLSLShader			gDeferredDiffuseProgram;
 extern LLGLSLShader			gDeferredSkinnedDiffuseProgram;
+extern LLGLSLShader			gDeferredSkinnedBumpProgram;
+extern LLGLSLShader			gDeferredSkinnedAlphaProgram;
 extern LLGLSLShader			gDeferredBumpProgram;
 extern LLGLSLShader			gDeferredTerrainProgram;
 extern LLGLSLShader			gDeferredTreeProgram;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index e263f8d937..220634897e 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3586,6 +3586,21 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						{
 							pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);
 						}
+
+						if (LLPipeline::sRenderDeferred)
+						{
+							if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright())
+							{
+								if (te->getBumpmap())
+								{
+									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP);
+								}
+								else
+								{
+									pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE);
+								}
+							}
+						}
 					}
 
 				}
-- 
cgit v1.2.3