diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
index b474a5803fe7e294c791c8a0b571f3f6a4e21dba..f51b0f4d9e727c1644db86f0520665fbecd6c05e 100644
--- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
@@ -25,7 +25,6 @@
 
 uniform mat3 normal_matrix;
 uniform mat4 texture_matrix0;
-uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
 in vec3 position;
@@ -54,14 +53,27 @@ float calcDirectionalLight(vec3 n, vec3 l)
 //====================================================================================================
 
 
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+#endif
+
 void main()
 {
-	//transform vertex
-	vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0));
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+    vec3 norm;
+#ifdef HAS_SKIN
+    mat4 mat = getObjectSkinnedTransform();
+    mat = modelview_matrix * mat;
+    vec4 pos = mat * vec4(position.xyz, 1.0);
+    gl_Position = projection_matrix * pos;
+    norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#else
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
+    norm = normalize(normal_matrix * normal);
+#endif
+
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-	
-	vec3 norm = normalize(normal_matrix * normal);
 
 	vec4 col = vec4(0,0,0,1);
 
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 50eda783674feda0445045343c2f1e7ee34e8c15..d23f1058fe2533d87e2a5d81f0d395d20a6f8099 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 57
+version 58
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -159,7 +159,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   1
 
 //
-// Medium High Graphics Settings (deferred enabled)
+// Medium High Graphics Settings
 //
 list MidHigh
 RenderAnisotropicLevel			1	4
@@ -187,7 +187,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   2
 
 //
-// High Graphics Settings (deferred + SSAO)
+// High Graphics Settings (SSAO + sun shadows)
 //
 list High
 RenderAnisotropicLevel			1	8
@@ -206,7 +206,7 @@ RenderTerrainLODFactor		1	2.0
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.5
 RenderDeferredSSAO			1	1
-RenderShadowDetail			1	0
+RenderShadowDetail			1	1
 WLSkyDetail					1	96
 RenderFSAASamples			1	2
 RenderReflectionsEnabled    1   1
@@ -215,7 +215,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   3
 
 //
-// High Ultra Graphics Settings (deferred + SSAO + shadows)
+// High Ultra Graphics Settings (deferred + SSAO + all shadows)
 //
 list HighUltra
 RenderAnisotropicLevel			1	8
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 8ae85f274409fbd12807ade00afc068789215cea..4e7f14af164f7a969ed8b771e6c6cbc03ad51545 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 52
+version 53
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -157,7 +157,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   0
 
 //
-// Medium High Graphics Settings (deferred enabled)
+// Medium High Graphics Settings
 //
 list MidHigh
 RenderAnisotropicLevel			1	4
@@ -185,7 +185,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   0
 
 //
-// High Graphics Settings (deferred + SSAO)
+// High Graphics Settings (SSAO + sun shadows)
 //
 list High
 RenderAnisotropicLevel			1	8
@@ -204,7 +204,7 @@ RenderTerrainLODFactor		1	2.0
 RenderTreeLODFactor			1	0.5
 RenderVolumeLODFactor		1	1.5
 RenderDeferredSSAO			1	1
-RenderShadowDetail			1	0
+RenderShadowDetail			1	1
 WLSkyDetail					1	96
 RenderFSAASamples			1	2
 RenderReflectionsEnabled    1   1
@@ -213,7 +213,7 @@ RenderScreenSpaceReflections 1  0
 RenderReflectionProbeLevel  1   1
 
 //
-// High Ultra Graphics Settings (deferred + SSAO + shadows)
+// High Ultra Graphics Settings (SSAO + all shadows)
 //
 list HighUltra
 RenderAnisotropicLevel			1	8
diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp
index fc283f2e83a0147eb02daddd81da230ce6f3fec8..171c5a3408782babb90047f40c7d2d5f399cd94b 100644
--- a/indra/newview/llmodelpreview.cpp
+++ b/indra/newview/llmodelpreview.cpp
@@ -2753,6 +2753,16 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 
         base_iter++;
 
+        bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
+
+        LLMatrix4a mat_normal;
+        if (skinned)
+        {
+            glh::matrix4f m((F32*)mdl->mSkinInfo.mBindShapeMatrix.getF32ptr());
+            m = m.inverse().transpose();
+            mat_normal.loadu(m.m);
+        }
+
         S32 num_faces = mdl->getNumVolumeFaces();
         for (S32 i = 0; i < num_faces; ++i)
         {
@@ -2767,7 +2777,7 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 
             LLVertexBuffer* vb = NULL;
 
-            bool skinned = include_skin_weights && !mdl->mSkinWeights.empty();
+            
 
             U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
 
@@ -2805,6 +2815,15 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
 
             LLVector4a::memcpyNonAliased16((F32*)vertex_strider.get(), (F32*)vf.mPositions, num_vertices * 4 * sizeof(F32));
 
+            if (skinned)
+            {
+                for (U32 i = 0; i < num_vertices; ++i)
+                {
+                    LLVector4a* v = (LLVector4a*)vertex_strider.get();
+                    mdl->mSkinInfo.mBindShapeMatrix.affineTransform(*v, *v);
+                    vertex_strider++;
+                }
+            }
             if (vf.mTexCoords)
             {
                 vb->getTexCoord0Strider(tc_strider);
@@ -2815,7 +2834,25 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights)
             if (vf.mNormals)
             {
                 vb->getNormalStrider(normal_strider);
-                LLVector4a::memcpyNonAliased16((F32*)normal_strider.get(), (F32*)vf.mNormals, num_vertices * 4 * sizeof(F32));
+
+                if (skinned)
+                {
+                    F32* normals = (F32*)normal_strider.get();
+                    LLVector4a* src = vf.mNormals;
+                    LLVector4a* end = src + num_vertices;
+
+                    while (src < end)
+                    {
+                        LLVector4a normal;
+                        mat_normal.rotate(*src++, normal);
+                        normal.store4a(normals);
+                        normals += 4;
+                    }
+                }
+                else
+                {
+                    LLVector4a::memcpyNonAliased16((F32*)normal_strider.get(), (F32*)vf.mNormals, num_vertices * 4 * sizeof(F32));
+                }
             }
 
             if (skinned)
@@ -3278,7 +3315,7 @@ BOOL LLModelPreview::render()
         refresh();
     }
 
-    gObjectPreviewProgram.bind();
+    gObjectPreviewProgram.bind(skin_weight);
 
     gGL.loadIdentity();
     gPipeline.enableLightsPreview();
@@ -3353,11 +3390,11 @@ BOOL LLModelPreview::render()
                 }
 
                 gGL.pushMatrix();
+
                 LLMatrix4 mat = instance.mTransform;
 
                 gGL.multMatrix((GLfloat*)mat.mMatrix);
-
-
+        
                 U32 num_models = mVertexBuffer[mPreviewLOD][model].size();
                 for (U32 i = 0; i < num_models; ++i)
                 {
@@ -3687,63 +3724,41 @@ BOOL LLModelPreview::render()
                         {
                             LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i];
 
-                            const LLVolumeFace& face = model->getVolumeFace(i);
-
-                            LLStrider<LLVector3> position;
-                            buffer->getVertexStrider(position);
-
-                            LLStrider<LLVector4a> weight;
-                            buffer->getWeight4Strider(weight);
+                            model->mSkinInfo.updateHash();
+                            LLRenderPass::uploadMatrixPalette(mPreviewAvatar, &model->mSkinInfo);
 
-                            //quick 'n dirty software vertex skinning
-
-                            //build matrix palette
-
-                            LLMatrix4a mat[LL_MAX_JOINTS_PER_MESH_OBJECT];
-                            LLSkinningUtil::initSkinningMatrixPalette(mat, joint_count,
-                                skin, getPreviewAvatar());
+                            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-                            const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix;
-                            for (U32 j = 0; j < buffer->getNumVerts(); ++j)
+                            if (textures)
                             {
-                                LLMatrix4a final_mat;
-                                 LLSkinningUtil::getPerVertexSkinMatrixChecked(weight[j], mat, final_mat);
-
-                                //VECTORIZE THIS
-                                LLVector4a& v = face.mPositions[j];
+                                int materialCnt = instance.mModel->mMaterialList.size();
+                                if (i < materialCnt)
+                                {
+                                    const std::string& binding = instance.mModel->mMaterialList[i];
+                                    const LLImportMaterial& material = instance.mMaterial[binding];
 
-                                LLVector4a t;
-                                LLVector4a dst;
-                                bind_shape_matrix.affineTransform(v, t);
-                                final_mat.affineTransform(t, dst);
+                                    gGL.diffuseColor4fv(material.mDiffuseColor.mV);
 
-                                position[j][0] = dst[0];
-                                position[j][1] = dst[1];
-                                position[j][2] = dst[2];
+                                    // Find the tex for this material, bind it, and add it to our set
+                                    //
+                                    LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
+                                    if (tex)
+                                    {
+                                        mTextureSet.insert(tex);
+                                    }
+                                }
                             }
-
-                            llassert(model->mMaterialList.size() > i);
-                            const std::string& binding = instance.mModel->mMaterialList[i];
-                            const LLImportMaterial& material = instance.mMaterial[binding];
-
-                            buffer->unmapBuffer();
-
-                            buffer->setBuffer();
-                            gGL.diffuseColor4fv(material.mDiffuseColor.mV);
-                            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
-                            // Find the tex for this material, bind it, and add it to our set
-                            //
-                            LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material);
-                            if (tex)
+                            else
                             {
-                                mTextureSet.insert(tex);
+                                gGL.diffuseColor4fv(PREVIEW_BASE_COL.mV);
                             }
 
+                            buffer->setBuffer();
                             buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0);
 
                             if (edges)
                             {
+                                gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
                                 gGL.diffuseColor4fv(PREVIEW_EDGE_COL.mV);
                                 gGL.setLineWidth(PREVIEW_EDGE_WIDTH);
                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index d5114e637165650dd6e0ba9b9878da872816e473..6cd29d7be45cdaafcde78da9fb7bde4ee8909a90 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -253,6 +253,10 @@ void LLReflectionMapManager::update()
 
         if (probe != mDefaultProbe)
         {
+            if (probe->mViewerObject) //make sure probes track the viewer objects they are attached to
+            {
+                probe->mOrigin.load3(probe->mViewerObject->getPositionAgent().mV);
+            }
             d.setSub(camera_pos, probe->mOrigin);
             probe->mDistance = d.getLength3().getF32() - probe->mRadius;
         }
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 0c2db66282fb7ba81271614d1292a207d3e5752b..d6022e0f24218d962f491a6684e3b1505b638333 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -90,6 +90,7 @@ LLGLSLShader    gCopyDepthProgram;
 
 //object shaders
 LLGLSLShader		gObjectPreviewProgram;
+LLGLSLShader        gSkinnedObjectPreviewProgram;
 LLGLSLShader        gPhysicsPreviewProgram;
 LLGLSLShader		gObjectFullbrightAlphaMaskProgram;
 LLGLSLShader        gSkinnedObjectFullbrightAlphaMaskProgram;
@@ -265,7 +266,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gWaterProgram);
 	mShaderList.push_back(&gWaterEdgeProgram);
 	mShaderList.push_back(&gAvatarEyeballProgram); 
-	mShaderList.push_back(&gObjectPreviewProgram);
 	mShaderList.push_back(&gImpostorProgram);
 	mShaderList.push_back(&gObjectBumpProgram);
     mShaderList.push_back(&gSkinnedObjectBumpProgram);
@@ -3201,20 +3201,16 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 
 	if (success)
 	{
-		gObjectPreviewProgram.mName = "Simple Shader";
-		gObjectPreviewProgram.mFeatures.calculatesLighting = false;
-		gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false;
-		gObjectPreviewProgram.mFeatures.hasGamma = false;
-		gObjectPreviewProgram.mFeatures.hasAtmospherics = false;
-		gObjectPreviewProgram.mFeatures.hasLighting = false;
-		gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
+		gObjectPreviewProgram.mName = "Object Preview Shader";
 		gObjectPreviewProgram.mFeatures.disableTextureIndex = true;
 		gObjectPreviewProgram.mShaderFiles.clear();
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER));
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER));
 		gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
+        success = make_rigged_variant(gObjectPreviewProgram, gSkinnedObjectPreviewProgram);
 		success = gObjectPreviewProgram.createShader(NULL, NULL);
 		gObjectPreviewProgram.mFeatures.hasLighting = true;
+        gSkinnedObjectPreviewProgram.mFeatures.hasLighting = true;
 	}
 
 	if (success)
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index ba752b1d223800327f532681d7bc239b781b4118..16d6f08d5ac00b1b971045b1ca6af72bb270e7f7 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -10681,8 +10681,11 @@ class LLOctreeDirty : public OctreeTraveler
     {
         LLSpatialGroup* group = (LLSpatialGroup*)state->getListener(0);
 
-        group->setState(LLSpatialGroup::GEOM_DIRTY);
-        gPipeline.markRebuild(group);
+        if (group->getSpatialPartition()->mRenderByGroup)
+        {
+            group->setState(LLSpatialGroup::GEOM_DIRTY);
+            gPipeline.markRebuild(group);
+        }
 
         for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i)
         {
@@ -10704,6 +10707,9 @@ void LLPipeline::rebuildDrawInfo()
 
         LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_VOLUME);
         dirty.traverse(part->mOctree);
+
+        part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+        dirty.traverse(part->mOctree);
     }
 }