diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index d3a05c34c0fe51184c63160848547d312a114ab8..638a0f4e1525ef64d873246651c9a05250ab8ad0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -215,6 +215,11 @@ void main()
     float final_alpha = diffuse_linear.a;
 
 #ifdef USE_VERTEX_COLOR
+    if (vertex_color.a <= 0.0)
+    { // TODO: figure out how to get invisible faces out of 
+        // render batches without breaking glow
+        discard;
+    }
     final_alpha *= vertex_color.a;
     diffuse_srgb.rgb *= vertex_color.rgb;
     diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
@@ -308,7 +313,7 @@ vec3 post_atmo = color.rgb;
 #endif // WATER_FOG
 
 #endif
-    
+
     frag_color = color;
 }
 
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 2bf8e9b9112d0798aed014436f31d2fc6e4691ff..5656eb147157175ce7e642e0b8d3f70cd1e781ae 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -228,8 +228,8 @@ void LLDrawPoolAlpha::forwardRender(bool rigged)
     //enable writing to alpha for emissive effects
     gGL.setColorMask(true, true);
 
-    bool write_depth = rigged
-        || LLDrawPoolWater::sSkipScreenCopy
+    bool write_depth = rigged || 
+        LLDrawPoolWater::sSkipScreenCopy
         // we want depth written so that rendered alpha will
         // contribute to the alpha mask used for impostors
         || LLPipeline::sImpostorRenderAlphaDepthPass;
@@ -484,6 +484,7 @@ void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissi
 
 void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
 {
+    LLGLDepthTest depth(GL_TRUE, GL_FALSE); //disable depth writes since "emissive" is additive so sorting doesn't matter
     LLGLSLShader* shader = emissive_shader->mRiggedVariant;
     shader->bind();
     shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 79f50f22736907a440b5b04abbfd8336358fecc8..aa00c9d052630c73c84ba55fffd9516301647468 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -143,7 +143,7 @@ class alignas(16) LLFace
 	LLViewerObject*	getViewerObject()	const	{ return mVObjp; }
 	S32				getLOD()			const	{ return mVObjp.notNull() ? mVObjp->getLOD() : 0; }
 	void			setPoolType(U32 type)		{ mPoolType = type; }
-	S32				getTEOffset()				{ return mTEOffset; }
+	S32				getTEOffset()       const   { return mTEOffset; }
 	LLViewerTexture*	getTexture(U32 ch = LLRender::DIFFUSE_MAP) const;
 
 	void			setViewerObject(LLViewerObject* object);
@@ -233,6 +233,12 @@ class alignas(16) LLFace
 	void	notifyAboutCreatingTexture(LLViewerTexture *texture);
 	void	notifyAboutMissingAsset(LLViewerTexture *texture);
 
+    // used to preserve draw order of faces that are batched together. 
+    // Allows content creators to manipulate linked sets and face ordering 
+    // for consistent alpha sorting results, particularly for rigged attachments
+    void setDrawOrderIndex(U32 index) { mDrawOrderIndex = index; }
+    U32 getDrawOrderIndex() const { return mDrawOrderIndex; }
+
 public: //aligned members
 	LLVector4a		mExtents[2];
 
@@ -305,6 +311,7 @@ class alignas(16) LLFace
 	bool        mHasMedia ;
 	bool        mIsMediaAllowed;
 
+    U32 mDrawOrderIndex = 0; // see setDrawOrderIndex
 	
 protected:
 	static BOOL	sSafeRenderSelect;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index f8728a5ab79b1c01c46ceda935154a2aa3ea6060..f18f6b1116dda27753163f995124cd5ee62bcbcf 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -5467,6 +5467,7 @@ static inline void add_face(T*** list, U32* count, T* face)
     {
         if (count[1] < MAX_FACE_COUNT)
         {
+            face->setDrawOrderIndex(count[1]);
             list[1][count[1]++] = face;
         }
     }
@@ -5474,6 +5475,7 @@ static inline void add_face(T*** list, U32* count, T* face)
     {
         if (count[0] < MAX_FACE_COUNT)
         {
+            face->setDrawOrderIndex(count[0]);
             list[0][count[0]++] = face;
         }
     }
@@ -6088,7 +6090,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
 	} 
 }
 
-struct CompareBatchBreakerModified
+struct CompareBatchBreaker
 {
 	bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
 	{
@@ -6103,18 +6105,23 @@ struct CompareBatchBreakerModified
 		{
 			return lte->getFullbright() < rte->getFullbright();
 		}
-		else if (LLPipeline::sRenderDeferred && lte->getMaterialParams() != rte->getMaterialParams())
-		{
-			return lte->getMaterialParams() < rte->getMaterialParams();
-		}
-		else if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+        else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
+        {
+            return lte->getMaterialID() < rte->getMaterialID();
+        }
+		else if (lte->getShiny() != rte->getShiny())
 		{
 			return lte->getShiny() < rte->getShiny();
 		}
-		else
+        else if (lhs->getTexture() != rhs->getTexture())
 		{
 			return lhs->getTexture() < rhs->getTexture();
 		}
+        else 
+        {
+            // all else being equal, maintain consistent draw order
+            return lhs->getDrawOrderIndex() < rhs->getDrawOrderIndex();
+        }
 	}
 };
 
@@ -6122,9 +6129,6 @@ struct CompareBatchBreakerRigged
 {
     bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
     {
-        const LLTextureEntry* lte = lhs->getTextureEntry();
-        const LLTextureEntry* rte = rhs->getTextureEntry();
-
         if (lhs->mAvatar != rhs->mAvatar)
         {
             return lhs->mAvatar < rhs->mAvatar;
@@ -6133,23 +6137,12 @@ struct CompareBatchBreakerRigged
         {
             return lhs->mSkinInfo->mHash < rhs->mSkinInfo->mHash;
         }
-        else if (lhs->getTexture() != rhs->getTexture())
-        {
-            return lhs->getTexture() < rhs->getTexture();
-        }
-        else if (lte->getBumpmap() != rte->getBumpmap())
-        {
-            return lte->getBumpmap() < rte->getBumpmap();
-        }
-        else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
-        {
-            return lte->getMaterialID() < rte->getMaterialID();
-        }
-        else // if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+        else
         {
-            return lte->getShiny() < rte->getShiny();
+            // "inherit" non-rigged behavior
+            CompareBatchBreaker comp;
+            return comp(lhs, rhs);
         }
-        
     }
 };
 
@@ -6198,7 +6191,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
         else if (!distance_sort)
         {
             //sort faces by things that break batches, not including avatar and mesh id
-            std::sort(faces, faces + face_count, CompareBatchBreakerModified());
+            std::sort(faces, faces + face_count, CompareBatchBreaker());
         }
 		else
 		{