diff --git a/doc/contributions.txt b/doc/contributions.txt
index 5b9a98ef80e7423aba54e31b569795f3d53ad6e8..b942bc4c19b7d912bd78cbd93cce2052c629c954 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -1243,6 +1243,7 @@ Vadim Bigbear
 	VWR-2681
 Vaalith Jinn
     STORM-64
+    MATBUG-8
 Vector Hastings
 	VWR-8726
 Veritas Raymaker
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 1f2b9904eb6f351fa7b6e4d9e1f0ceb1f66ec8dc..2d9385390b45bbd893d4a815b2712f035d6f2fdf 100755
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -58,6 +58,8 @@
 #include "lltexlayerparams.h"
 #include "llvovolume.h"
 #include "llnotificationsutil.h"
+#include "pipeline.h"
+#include "llmaterialmgr.h"
 
 /*=======================================*/
 /*  Formal declarations, constants, etc. */
@@ -339,7 +341,12 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id)
 		return;
 	}
 
-	updateUserPrims(old_id, new_id);
+	// processing updates per channel; makes the process scalable.
+	// the only actual difference is in SetTE* call i.e. SetTETexture, SetTENormal, etc.
+	updateUserPrims(old_id, new_id, LLRender::DIFFUSE_MAP);
+	updateUserPrims(old_id, new_id, LLRender::NORMAL_MAP);
+	updateUserPrims(old_id, new_id, LLRender::SPECULAR_MAP);
+	
 	updateUserSculpts(old_id, new_id); // isn't there supposed to be an IMG_DEFAULT_SCULPT or something?
 	
 	// default safeguard image for layers
@@ -367,17 +374,15 @@ void LLLocalBitmap::replaceIDs(LLUUID old_id, LLUUID new_id)
 
 // this function sorts the faces from a getFaceList[getNumFaces] into a list of objects
 // in order to prevent multiple sendTEUpdate calls per object during updateUserPrims
-std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id)
+std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id, U32 channel)
 {
 	std::vector<LLViewerObject*> obj_list;
 	LLViewerFetchedTexture* old_texture = gTextureList.findImage(old_id);
-
-	U32 ch = LLRender::DIFFUSE_MAP;
-
-	for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(ch); face_iterator++)
+	
+	for(U32 face_iterator = 0; face_iterator < old_texture->getNumFaces(channel); face_iterator++)
 	{
 		// getting an object from a face
-		LLFace* face_to_object = (*old_texture->getFaceList(ch))[face_iterator];
+		LLFace* face_to_object = (*old_texture->getFaceList(channel))[face_iterator];
 
 		if(face_to_object)
 		{
@@ -418,9 +423,9 @@ std::vector<LLViewerObject*> LLLocalBitmap::prepUpdateObjects(LLUUID old_id)
 	return obj_list;
 }
 
-void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id)
+void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel)
 {
-	std::vector<LLViewerObject*> objectlist = prepUpdateObjects(old_id);
+	std::vector<LLViewerObject*> objectlist = prepUpdateObjects(old_id, channel);
 
 	for(std::vector<LLViewerObject*>::iterator object_iterator = objectlist.begin();
 		object_iterator != objectlist.end(); object_iterator++)
@@ -429,7 +434,8 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id)
 
 		if(object)
 		{
-			bool update_obj = false;
+			bool update_tex = false;
+			bool update_mat = false;
 			S32 num_faces = object->getNumFaces();
 
 			for (U8 face_iter = 0; face_iter < num_faces; face_iter++)
@@ -437,20 +443,51 @@ void LLLocalBitmap::updateUserPrims(LLUUID old_id, LLUUID new_id)
 				if (object->mDrawable)
 				{
 					LLFace* face = object->mDrawable->getFace(face_iter);
-					if (face && face->getTexture() && face->getTexture()->getID() == old_id)
+					if (face && face->getTexture(channel) && face->getTexture(channel)->getID() == old_id)
 					{
-						object->setTEImage(face_iter, LLViewerTextureManager::getFetchedTexture(
-							new_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
+						// these things differ per channel, unless there already is a universal
+						// texture setting function to setTE that takes channel as a param?
+						// p.s.: switch for now, might become if - if an extra test is needed to verify before touching normalmap/specmap
+						switch(channel)
+						{
+							case LLRender::DIFFUSE_MAP:
+							{
+                                object->setTETexture(face_iter, new_id);
+                                update_tex = true;
+								break;
+							}
+
+							case LLRender::NORMAL_MAP:
+							{
+								object->setTENormalMap(face_iter, new_id);
+								update_mat = true;
+								update_tex = true;
+                                break;
+							}
+
+							case LLRender::SPECULAR_MAP:
+							{
+								object->setTESpecularMap(face_iter, new_id);
+                                update_mat = true;
+								update_tex = true;
+                                break;
+							}
+						}
+						// end switch
 
-						update_obj = true;
 					}
 				}
 			}
 			
-			if (update_obj)
+			if (update_tex)
 			{
 				object->sendTEUpdate();
 			}
+
+			if (update_mat)
+			{
+                object->mDrawable->getVOVolume()->faceMappingChanged();
+			}
 		}
 	}
 	
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index 580b6dfa7e06ffff4ded45e3247b10a59c9bc8e2..2ee84bf46e72970d7283df83ba6b4096860f839f 100755
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -62,8 +62,8 @@ class LLLocalBitmap
 	private: /* self update private section */
 		bool decodeBitmap(LLPointer<LLImageRaw> raw);
 		void replaceIDs(LLUUID old_id, LLUUID new_id);
-		std::vector<LLViewerObject*> prepUpdateObjects(LLUUID old_id);
-		void updateUserPrims(LLUUID old_id, LLUUID new_id);
+		std::vector<LLViewerObject*> prepUpdateObjects(LLUUID old_id, U32 channel);
+		void updateUserPrims(LLUUID old_id, LLUUID new_id, U32 channel);
 		void updateUserSculpts(LLUUID old_id, LLUUID new_id);
 		void updateUserLayers(LLUUID old_id, LLUUID new_id, LLWearableType::EType type);
 		LLAvatarAppearanceDefines::ETextureIndex getTexIndex(LLWearableType::EType type, LLAvatarAppearanceDefines::EBakedTextureIndex baked_texind);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 56c552ab9f2abfcd8e6b4a96971493ab21d5c72b..928ff7f66bc32583de104c5a1623faf240c06565 100755
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -31,6 +31,7 @@
 #include "llviewertexture.h"
 #include "llviewermedia.h"
 #include "llframetimer.h"
+#include "lllocalbitmaps.h"
 #include "m3math.h"		// LLMatrix3
 #include "m4math.h"		// LLMatrix4
 #include <map>
@@ -158,6 +159,7 @@ class LLVOVolume : public LLViewerObject
 				const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const;
 
 				void	markForUpdate(BOOL priority)			{ LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; }
+				void    faceMappingChanged()                    { mFaceMappingChanged=TRUE; };
 
 	/*virtual*/ void	onShift(const LLVector4a &shift_vector); // Called when the drawable shifts