From fc4869fb7871632b95dd293157b9965fb2edcb73 Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 29 Mar 2013 16:13:36 -0500
Subject: [PATCH] NORSPEC-65 Hook up texture offset/scale/rotation for normal
 and specular maps.

---
 indra/llrender/llvertexbuffer.cpp             |   5 +-
 indra/llrender/llvertexbuffer.h               |   1 +
 .../shaders/class1/deferred/materialF.glsl    |   7 +-
 .../shaders/class1/deferred/materialV.glsl    |  15 ++
 indra/newview/lldrawpoolmaterials.h           |   2 +
 indra/newview/llface.cpp                      | 174 ++++++++++++------
 indra/newview/llvovolume.cpp                  |  62 +++++--
 7 files changed, 194 insertions(+), 72 deletions(-)

diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index dfbd8cd4eed..4e3cea9474a 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -2027,7 +2027,10 @@ bool LLVertexBuffer::getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 inde
 {
 	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD1>::get(*this, strider, index, count, map_range);
 }
-
+bool LLVertexBuffer::getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index, S32 count, bool map_range)
+{
+	return VertexBufferStrider<LLVector2,TYPE_TEXCOORD2>::get(*this, strider, index, count, map_range);
+}
 bool LLVertexBuffer::getNormalStrider(LLStrider<LLVector3>& strider, S32 index, S32 count, bool map_range)
 {
 	return VertexBufferStrider<LLVector3,TYPE_NORMAL>::get(*this, strider, index, count, map_range);
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 11fa4ab6a0d..1be9b79e847 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -250,6 +250,7 @@ class LLVertexBuffer : public LLRefCount
 	bool getIndexStrider(LLStrider<U16>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getTexCoord0Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getTexCoord1Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
+	bool getTexCoord2Strider(LLStrider<LLVector2>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getNormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getBinormalStrider(LLStrider<LLVector3>& strider, S32 index=0, S32 count = -1, bool map_range = false);
 	bool getColorStrider(LLStrider<LLColor4U>& strider, S32 index=0, S32 count = -1, bool map_range = false);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index fdaad550f7b..e406bf14a98 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -44,6 +44,8 @@ uniform sampler2D bumpMap;
 #if HAS_SPECULAR_MAP
 uniform sampler2D specularMap;
 uniform float env_intensity;
+
+VARYING vec2 vary_texcoord2;
 #endif
 
 uniform vec4 specular_color;
@@ -56,6 +58,7 @@ uniform float minimum_alpha;
 VARYING vec3 vary_mat0;
 VARYING vec3 vary_mat1;
 VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
 #else
 VARYING vec3 vary_normal;
 #endif
@@ -77,13 +80,13 @@ void main()
 #endif
 
 #if HAS_SPECULAR_MAP
-	vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
+	vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
 #else
 	vec4 spec = specular_color;
 #endif
 
 #if HAS_NORMAL_MAP
-	vec4 norm = texture2D(bumpMap, vary_texcoord0.xy);
+	vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
 
 	norm.xyz = norm.xyz * 2 - 1;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index f92ad63100c..744f79c0c9a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -34,14 +34,22 @@ ATTRIBUTE vec2 texcoord0;
 
 #if HAS_NORMAL_MAP
 ATTRIBUTE vec3 binormal;
+ATTRIBUTE vec2 texcoord1;
 
 VARYING vec3 vary_mat0;
 VARYING vec3 vary_mat1;
 VARYING vec3 vary_mat2;
+
+VARYING vec2 vary_texcoord1;
 #else
 VARYING vec3 vary_normal;
 #endif
 
+#if HAS_SPECULAR_MAP
+ATTRIBUTE vec2 texcoord2;
+VARYING vec2 vary_texcoord2;
+#endif
+ 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
@@ -51,6 +59,13 @@ void main()
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	
+#if HAS_NORMAL_MAP
+	vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy;
+#endif
+
+#if HAS_SPECULAR_MAP
+	vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy;
+#endif
 
 	vec3 n = normalize(normal_matrix * normal);
 #if HAS_NORMAL_MAP
diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h
index 1f5565afc85..cfbd13f335e 100644
--- a/indra/newview/lldrawpoolmaterials.h
+++ b/indra/newview/lldrawpoolmaterials.h
@@ -49,6 +49,8 @@ class LLDrawPoolMaterials : public LLRenderPass
 		VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX |
 		LLVertexBuffer::MAP_NORMAL |
 		LLVertexBuffer::MAP_TEXCOORD0 |
+		LLVertexBuffer::MAP_TEXCOORD1 |
+		LLVertexBuffer::MAP_TEXCOORD2 |
 		LLVertexBuffer::MAP_COLOR |
 		LLVertexBuffer::MAP_BINORMAL
 	};
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 6f0b1ee5676..9a8b37bf8b6 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1258,7 +1258,8 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 	}
 
 	LLStrider<LLVector3> vert;
-	LLStrider<LLVector2> tex_coords;
+	LLStrider<LLVector2> tex_coords0;
+	LLStrider<LLVector2> tex_coords1;
 	LLStrider<LLVector2> tex_coords2;
 	LLStrider<LLVector3> norm;
 	LLStrider<LLColor4U> colors;
@@ -1648,12 +1649,21 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			LLVector4a scalea;
 			scalea.load3(scale.mV);
 
+			LLMaterial* mat = tep->getMaterialParams().get();
+
 			bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1);
-			bool do_tex_mat = tex_mode && mTextureMatrix;
 
+			if (mat && !do_bump)
+			{
+				do_bump  = mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1) ||
+					mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2);
+			}
+			
+			bool do_tex_mat = tex_mode && mTextureMatrix;
+						
 			if (!do_bump)
 			{ //not bump mapped, might be able to do a cheap update
-				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount);
+				mVertexBuffer->getTexCoord0Strider(tex_coords0, mGeomIndex, mGeomCount);
 
 				if (texgen != LLTextureEntry::TEX_GEN_PLANAR)
 				{
@@ -1664,12 +1674,12 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 						{
 							LLFastTimer t(FTM_FACE_TEX_QUICK_NO_XFORM);
 							S32 tc_size = (num_vertices*2*sizeof(F32)+0xF) & ~0xF;
-							LLVector4a::memcpyNonAliased16((F32*) tex_coords.get(), (F32*) vf.mTexCoords, tc_size);
+							LLVector4a::memcpyNonAliased16((F32*) tex_coords0.get(), (F32*) vf.mTexCoords, tc_size);
 						}
 						else
 						{
 							LLFastTimer t(FTM_FACE_TEX_QUICK_XFORM);
-							F32* dst = (F32*) tex_coords.get();
+							F32* dst = (F32*) tex_coords0.get();
 							LLVector4a* src = (LLVector4a*) vf.mTexCoords;
 
 							LLVector4a trans;
@@ -1715,7 +1725,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							tmp = tmp * *mTextureMatrix;
 							tc.mV[0] = tmp.mV[0];
 							tc.mV[1] = tmp.mV[1];
-							*tex_coords++ = tc;	
+							*tex_coords0++ = tc;	
 						}
 					}
 				}
@@ -1738,7 +1748,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 							tc.mV[0] = tmp.mV[0];
 							tc.mV[1] = tmp.mV[1];
 				
-							*tex_coords++ = tc;	
+							*tex_coords0++ = tc;	
 						}
 					}
 					else
@@ -1754,7 +1764,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 						
 							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
 
-							*tex_coords++ = tc;	
+							*tex_coords0++ = tc;	
 						}
 					}
 				}
@@ -1765,58 +1775,114 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				}
 			}
 			else
-			{ //bump mapped, just do the whole expensive loop
+			{ //bump mapped or has material, just do the whole expensive loop
 				LLFastTimer t(FTM_FACE_TEX_DEFAULT);
-				mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex, mGeomCount, map_range);
-
+				
 				std::vector<LLVector2> bump_tc;
-		
-				for (S32 i = 0; i < num_vertices; i++)
-				{	
-					LLVector2 tc(vf.mTexCoords[i]);
+
+				if (mat)
+				{ //writing out normal and specular texture coordinates, not bump offsets
+					do_bump = false;
+				}
+
+				LLStrider<LLVector2> dst;
+
+				for (U32 ch = 0; ch < 3; ++ch)
+				{
+					switch (ch)
+					{
+						case 0: 
+							mVertexBuffer->getTexCoord0Strider(dst, mGeomIndex, mGeomCount, map_range); 
+							break;
+						case 1:
+							if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1))
+							{
+								mVertexBuffer->getTexCoord1Strider(dst, mGeomIndex, mGeomCount, map_range);
+								if (mat)
+								{
+									r  = mat->getNormalRotation();
+									mat->getNormalOffset(os, ot);
+									mat->getNormalRepeat(ms, mt);
+
+									cos_ang = cos(r);
+									sin_ang = sin(r);
+
+								}
+							}
+							else
+							{
+								continue;
+							}
+							break;
+						case 2:
+							if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD2))
+							{
+								mVertexBuffer->getTexCoord2Strider(dst, mGeomIndex, mGeomCount, map_range);
+								if (mat)
+								{
+									r  = mat->getSpecularRotation();
+									mat->getSpecularOffset(os, ot);
+									mat->getSpecularRepeat(ms, mt);
+
+									cos_ang = cos(r);
+									sin_ang = sin(r);
+								}
+							}
+							else
+							{
+								continue;
+							}
+							break;
+					}
+					
+
+					for (S32 i = 0; i < num_vertices; i++)
+					{	
+						LLVector2 tc(vf.mTexCoords[i]);
 			
-					LLVector4a& norm = vf.mNormals[i];
+						LLVector4a& norm = vf.mNormals[i];
 				
-					LLVector4a& center = *(vf.mCenter);
+						LLVector4a& center = *(vf.mCenter);
 		   
-					if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
-					{
-						LLVector4a vec = vf.mPositions[i];
+						if (texgen != LLTextureEntry::TEX_GEN_DEFAULT)
+						{
+							LLVector4a vec = vf.mPositions[i];
 				
-						vec.mul(scalea);
+							vec.mul(scalea);
 
-						switch (texgen)
-						{
-							case LLTextureEntry::TEX_GEN_PLANAR:
-								planarProjection(tc, norm, center, vec);
-								break;
-							case LLTextureEntry::TEX_GEN_SPHERICAL:
-								sphericalProjection(tc, norm, center, vec);
-								break;
-							case LLTextureEntry::TEX_GEN_CYLINDRICAL:
-								cylindricalProjection(tc, norm, center, vec);
-								break;
-							default:
-								break;
-						}		
-					}
+							switch (texgen)
+							{
+								case LLTextureEntry::TEX_GEN_PLANAR:
+									planarProjection(tc, norm, center, vec);
+									break;
+								case LLTextureEntry::TEX_GEN_SPHERICAL:
+									sphericalProjection(tc, norm, center, vec);
+									break;
+								case LLTextureEntry::TEX_GEN_CYLINDRICAL:
+									cylindricalProjection(tc, norm, center, vec);
+									break;
+								default:
+									break;
+							}		
+						}
 
-					if (tex_mode && mTextureMatrix)
-					{
-						LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
-						tmp = tmp * *mTextureMatrix;
-						tc.mV[0] = tmp.mV[0];
-						tc.mV[1] = tmp.mV[1];
-					}
-					else
-					{
-						xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
-					}
+						if (tex_mode && mTextureMatrix)
+						{
+							LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f);
+							tmp = tmp * *mTextureMatrix;
+							tc.mV[0] = tmp.mV[0];
+							tc.mV[1] = tmp.mV[1];
+						}
+						else
+						{
+							xform(tc, cos_ang, sin_ang, os, ot, ms, mt);
+						}
 
-					*tex_coords++ = tc;
-					if (do_bump)
-					{
-						bump_tc.push_back(tc);
+						*dst++ = tc;
+						if (do_bump)
+						{
+							bump_tc.push_back(tc);
+						}
 					}
 				}
 
@@ -1825,9 +1891,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 					mVertexBuffer->flush();
 				}
 
-				if (do_bump)
+				if (!mat && do_bump)
 				{
-					mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex, mGeomCount, map_range);
+					mVertexBuffer->getTexCoord1Strider(tex_coords1, mGeomIndex, mGeomCount, map_range);
 		
 					for (S32 i = 0; i < num_vertices; i++)
 					{
@@ -1854,7 +1920,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 						LLVector2 tc = bump_tc[i];
 						tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() );
 					
-						*tex_coords2++ = tc;
+						*tex_coords1++ = tc;
 					}
 
 					if (map_range)
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 750d6bd2ac4..df462e50137 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4294,6 +4294,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 	std::vector<LLFace*> fullbright_faces;
 	std::vector<LLFace*> bump_faces;
+	std::vector<LLFace*> norm_faces;
+	std::vector<LLFace*> spec_faces;
+	std::vector<LLFace*> normspec_faces;
 	std::vector<LLFace*> simple_faces;
 
 	std::vector<LLFace*> alpha_faces;
@@ -4629,7 +4632,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						if (gPipeline.canUseWindLightShadersOnObjects()
 							&& LLPipeline::sRenderBump)
 						{
-							if (te->getBumpmap() || te->getMaterialParams()	!= NULL)
+							if (LLPipeline::sRenderDeferred && te->getMaterialParams() != NULL)
+							{
+								LLMaterial* mat = te->getMaterialParams().get();
+								if (mat->getNormalID().notNull())
+								{
+									if (mat->getSpecularID().notNull())
+									{ //has normal and specular maps (needs texcoord1, texcoord2, and binormal)
+										normspec_faces.push_back(facep);
+									}
+									else
+									{ //has normal map (needs texcoord1 and binormal)
+										norm_faces.push_back(facep);
+									}
+								}
+								else if (mat->getSpecularID().notNull())
+								{ //has specular map but no normal map, needs texcoord2
+									spec_faces.push_back(facep);
+								}
+								else
+								{ //has neither specular map nor normal map, only needs texcoord0
+									simple_faces.push_back(facep);
+								}									
+							}
+							else if (te->getBumpmap())
 							{ //needs normal + binormal
 								bump_faces.push_back(facep);
 							}
@@ -4687,32 +4713,38 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
 	U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR;
 
+	U32 norm_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_BINORMAL;
+	U32 normspec_mask = norm_mask | LLVertexBuffer::MAP_TEXCOORD2;
+	U32 spec_mask = simple_mask | LLVertexBuffer::MAP_TEXCOORD2;
+
 	if (emissive)
 	{ //emissive faces are present, include emissive byte to preserve batching
 		simple_mask = simple_mask | LLVertexBuffer::MAP_EMISSIVE;
 		alpha_mask = alpha_mask | LLVertexBuffer::MAP_EMISSIVE;
 		bump_mask = bump_mask | LLVertexBuffer::MAP_EMISSIVE;
 		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_EMISSIVE;
+		norm_mask = norm_mask | LLVertexBuffer::MAP_EMISSIVE;
+		normspec_mask = normspec_mask | LLVertexBuffer::MAP_EMISSIVE;
+		spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE;
 	}
 
-	bool batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+	BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
 
 	if (batch_textures)
 	{
-		bump_mask |= LLVertexBuffer::MAP_BINORMAL;
-		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE);
-		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE);
-		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, FALSE);
-		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE);
+		bump_mask = bump_mask | LLVertexBuffer::MAP_BINORMAL;
+		simple_mask = simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
+		alpha_mask = alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
+		fullbright_mask = fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX;
 	}
-	else
-	{
-		genDrawInfo(group, simple_mask, simple_faces);
-		genDrawInfo(group, fullbright_mask, fullbright_faces);
-		genDrawInfo(group, bump_mask, bump_faces, FALSE, FALSE);
-		genDrawInfo(group, alpha_mask, alpha_faces, TRUE);
-	}
-	
+
+	genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, batch_textures);
+	genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, batch_textures);
+	genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, batch_textures);
+	genDrawInfo(group, bump_mask, bump_faces, FALSE, FALSE);
+	genDrawInfo(group, norm_mask, norm_faces, FALSE, FALSE);
+	genDrawInfo(group, spec_mask, spec_faces, FALSE, FALSE);
+	genDrawInfo(group, normspec_mask, normspec_faces, FALSE, FALSE);
 
 	if (!LLPipeline::sDelayVBUpdate)
 	{
-- 
GitLab