diff --git a/.clang-format b/.clang-format
index 0b19cae8387531906559f67da7a7de4acf277786..ee8a8a8c92f9c34e120e5a61c2f49aeeada06241 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,17 +1,18 @@
 ---
+# clang-format version 10.0.0+
 Language:        Cpp
 # BasedOnStyle:  Microsoft
 AccessModifierOffset: -2
 AlignAfterOpenBracket: Align
-AlignConsecutiveMacros: false
-AlignConsecutiveAssignments: false
-AlignConsecutiveDeclarations: false
-AlignEscapedNewlines: Right
+AlignConsecutiveMacros: true
+AlignConsecutiveAssignments: true
+AlignConsecutiveDeclarations: true
+AlignEscapedNewlines: Left
 AlignOperands:   true
 AlignTrailingComments: true
-AllowAllArgumentsOnNextLine: true
-AllowAllConstructorInitializersOnNextLine: true
-AllowAllParametersOfDeclarationOnNextLine: true
+AllowAllArgumentsOnNextLine: false
+AllowAllConstructorInitializersOnNextLine: false
+AllowAllParametersOfDeclarationOnNextLine: false
 AllowShortBlocksOnASingleLine: Always
 AllowShortCaseLabelsOnASingleLine: false
 AllowShortFunctionsOnASingleLine: All
@@ -29,21 +30,21 @@ BreakBeforeBraces: Allman
 BreakBeforeInheritanceComma: false
 BreakInheritanceList: BeforeColon
 BreakBeforeTernaryOperators: true
-BreakConstructorInitializersBeforeComma: false
-BreakConstructorInitializers: BeforeColon
+BreakConstructorInitializersBeforeComma: true
+BreakConstructorInitializers: AfterColon
 BreakAfterJavaFieldAnnotations: false
 BreakStringLiterals: true
-ColumnLimit:     120
+ColumnLimit:     140
 CommentPragmas:  '^ IWYU pragma:'
 CompactNamespaces: false
-ConstructorInitializerAllOnOneLineOrOnePerLine: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
 ConstructorInitializerIndentWidth: 4
 ContinuationIndentWidth: 4
 Cpp11BracedListStyle: true
 DeriveLineEnding: true
 DerivePointerAlignment: false
 DisableFormat:   false
-ExperimentalAutoDetectBinPacking: false
+ExperimentalAutoDetectBinPacking: true
 FixNamespaceComments: true
 ForEachMacros:
   - foreach
@@ -62,18 +63,18 @@ IncludeCategories:
     SortPriority:    0
 IncludeIsMainRegex: '(Test)?$'
 IncludeIsMainSourceRegex: ''
-IndentCaseLabels: false
+IndentCaseLabels: true
 IndentGotoLabels: true
 IndentPPDirectives: None
 IndentWidth:     4
 IndentWrappedFunctionNames: false
 JavaScriptQuotes: Leave
 JavaScriptWrapImports: true
-KeepEmptyLinesAtTheStartOfBlocks: true
+KeepEmptyLinesAtTheStartOfBlocks: false
 MacroBlockBegin: ''
 MacroBlockEnd:   ''
 MaxEmptyLinesToKeep: 1
-NamespaceIndentation: None
+NamespaceIndentation: Inner
 ObjCBinPackProtocolList: Auto
 ObjCBlockIndentWidth: 2
 ObjCSpaceAfterProperty: false
@@ -94,16 +95,16 @@ SpaceAfterCStyleCast: true
 SpaceAfterLogicalNot: false
 SpaceAfterTemplateKeyword: true
 SpaceBeforeAssignmentOperators: true
-SpaceBeforeCpp11BracedList: false
+SpaceBeforeCpp11BracedList: true
 SpaceBeforeCtorInitializerColon: true
 SpaceBeforeInheritanceColon: true
 SpaceBeforeParens: ControlStatements
 SpaceBeforeRangeBasedForLoopColon: true
 SpaceInEmptyBlock: false
 SpaceInEmptyParentheses: false
-SpacesBeforeTrailingComments: 1
+SpacesBeforeTrailingComments: 2
 SpacesInAngles:  false
-SpacesInContainerLiterals: true
+SpacesInContainerLiterals: false
 SpacesInCStyleCastParentheses: false
 SpacesInParentheses: false
 SpacesInSquareBrackets: false
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 865c057e33f064cebafaa62bd29c41bc3406ad5c..8aea50e02b1a2167b2c0fe61aebace3db1943ef3 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -63,7 +63,13 @@ if (WINDOWS)
   # Without PreferredToolArchitecture=x64, as of 2020-06-26 the 32-bit
   # compiler on our TeamCity build hosts has started running out of virtual
   # memory for the precompiled header file.
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /p:PreferredToolArchitecture=x64")
+  # CP changed to only append the flag for 32bit builds - on 64bit builds,
+  # locally at least, the build output is spammed with 1000s of 'D9002'
+  # warnings about this switch being ignored.
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")  
+  if( ADDRESS_SIZE EQUAL 32 )
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")  
+  endif()
 
   set(CMAKE_CXX_FLAGS_RELWITHDEBINFO 
       "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..48082f72f087ce7e6fa75b9c41d7387daecd447b 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -0,0 +1 @@
+12
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 306c73292057c05f4da4fe5b2e481d6a8413cdb2..81937dbda529ccbb6475e1d045e27d05274a6e81 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -1295,6 +1295,9 @@ void LLSettingsSky::clampColor(LLColor3& color, F32 gamma, F32 scale) const
     color = linear;
 }
 
+// Similar/Shared Algorithms:
+//     indra\llinventory\llsettingssky.cpp                                        -- LLSettingsSky::calculateLightSettings()
+//     indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars()
 void LLSettingsSky::calculateLightSettings() const
 {
     // Initialize temp variables
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index ff743802170263af651af6c0eda16c4e29bf1d82..3b6a49735ea378492acabd6c611f8e45527edca4 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -985,38 +985,56 @@ BOOL LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
 		return FALSE;
 	}
 
-	if( !mHasExplicitFormat )
-	{
-		switch (mComponents)
-		{
-			case 1:
-			// Use luminance alpha (for fonts)
-			mFormatInternal = GL_LUMINANCE8;
-			mFormatPrimary = GL_LUMINANCE;
-			mFormatType = GL_UNSIGNED_BYTE;
-			break;
-			case 2:
-			// Use luminance alpha (for fonts)
-			mFormatInternal = GL_LUMINANCE8_ALPHA8;
-			mFormatPrimary = GL_LUMINANCE_ALPHA;
-			mFormatType = GL_UNSIGNED_BYTE;
-			break;
-			case 3:
-			mFormatInternal = GL_RGB8;
-			mFormatPrimary = GL_RGB;
-			mFormatType = GL_UNSIGNED_BYTE;
-			break;
-			case 4:
-			mFormatInternal = GL_RGBA8;
-			mFormatPrimary = GL_RGBA;
-			mFormatType = GL_UNSIGNED_BYTE;
-			break;
-			default:
-			LL_ERRS() << "Bad number of components for texture: " << (U32)getComponents() << LL_ENDL;
-		}
-	}
+    if (!mHasExplicitFormat)
+    {
+        switch (mComponents)
+        {
+            case 1:
+                // Use luminance alpha (for fonts)
+                mFormatInternal = GL_LUMINANCE8;
+                mFormatPrimary  = GL_LUMINANCE;
+                mFormatType     = GL_UNSIGNED_BYTE;
+                break;
+            case 2:
+                // Use luminance alpha (for fonts)
+                mFormatInternal = GL_LUMINANCE8_ALPHA8;
+                mFormatPrimary  = GL_LUMINANCE_ALPHA;
+                mFormatType     = GL_UNSIGNED_BYTE;
+                break;
+            case 3:
+#if USE_SRGB_DECODE
+                if (gGLManager.mHasTexturesRGBDecode)
+                {
+                    mFormatInternal = GL_SRGB8;
+                }
+                else
+#endif
+                {
+                    mFormatInternal = GL_RGB8;
+                }
+                mFormatPrimary = GL_RGB;
+                mFormatType    = GL_UNSIGNED_BYTE;
+                break;
+            case 4:
+#if USE_SRGB_DECODE
+                if (gGLManager.mHasTexturesRGBDecode)
+                {
+                    mFormatInternal = GL_SRGB8_ALPHA8;
+                }
+                else
+#endif
+                {
+                    mFormatInternal = GL_RGBA8;
+                }
+                mFormatPrimary = GL_RGBA;
+                mFormatType    = GL_UNSIGNED_BYTE;
+                break;
+            default:
+                LL_ERRS() << "Bad number of components for texture: " << (U32) getComponents() << LL_ENDL;
+        }
+    }
 
-	mCurrentDiscardLevel = discard_level;	
+    mCurrentDiscardLevel = discard_level;	
 	mDiscardLevelInAtlas = discard_level;
 	mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
 	mLastBindTime = sLastFrameTime;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index ebc4659bcfbb0a76d6e5d3329238b6806e7fc2ab..11d9ef3f57fdd42633124929011b1b8b1bdd31fe 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -849,26 +849,32 @@ void LLTexUnit::debugTextureUnit(void)
 	}
 }
 
-void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) {
+void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
+{
     mTexColorSpace = space;
 
 #if USE_SRGB_DECODE
-    if (gGLManager.mHasTexturesRGBDecode) {
-
-        if (space == TCS_SRGB) {
+    if (gGLManager.mHasTexturesRGBDecode)
+    {
+        if (space == TCS_SRGB)
+        {
             glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
         }
-        else {
+        else
+        {
             glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
         }
 
-        if (gDebugGL) {
+        if (gDebugGL)
+        {
             assert_glerror();
         }
     }
+    else
 #endif
-    glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
-
+    {
+        glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+    }
 }
 
 LLLightState::LLLightState(S32 index)
@@ -1192,46 +1198,46 @@ void LLRender::refreshState(void)
 
 void LLRender::syncLightState()
 {
-	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+    LLGLSLShader *shader = LLGLSLShader::sCurBoundShaderPtr;
 
-	if (!shader)
-	{
-		return;
-	}
+    if (!shader)
+    {
+        return;
+    }
 
-	if (shader->mLightHash != mLightHash)
-	{
-		shader->mLightHash = mLightHash;
+    if (shader->mLightHash != mLightHash)
+    {
+        shader->mLightHash = mLightHash;
 
-		LLVector4 position[8];
-		LLVector3 direction[8];
-		LLVector4 attenuation[8];
-		LLVector3 diffuse[8];
-        LLVector3 diffuse_b[8];
-        bool      sun_primary[8];
+        LLVector4 position[LL_NUM_LIGHT_UNITS];
+        LLVector3 direction[LL_NUM_LIGHT_UNITS];
+        LLVector4 attenuation[LL_NUM_LIGHT_UNITS];
+        LLVector3 diffuse[LL_NUM_LIGHT_UNITS];
+        LLVector3 diffuse_b[LL_NUM_LIGHT_UNITS];
+        bool      sun_primary[LL_NUM_LIGHT_UNITS];
 
-		for (U32 i = 0; i < 8; i++)
-		{
-			LLLightState* light = mLightState[i];
+        for (U32 i = 0; i < LL_NUM_LIGHT_UNITS; i++)
+        {
+            LLLightState *light = mLightState[i];
 
-			position[i] = light->mPosition;
-			direction[i] = light->mSpotDirection;
+            position[i]  = light->mPosition;
+            direction[i] = light->mSpotDirection;
             attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[2], light->mSpecular.mV[3]);
-			diffuse[i].set(light->mDiffuse.mV);
+            diffuse[i].set(light->mDiffuse.mV);
             diffuse_b[i].set(light->mDiffuseB.mV);
             sun_primary[i] = light->mSunIsPrimary;
-		}
+        }
 
-		shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, 8, position[0].mV);
-		shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, 8, direction[0].mV);
-		shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[0].mV);
-		shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, 8, diffuse[0].mV);
-		shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
+        shader->uniform4fv(LLShaderMgr::LIGHT_POSITION, LL_NUM_LIGHT_UNITS, position[0].mV);
+        shader->uniform3fv(LLShaderMgr::LIGHT_DIRECTION, LL_NUM_LIGHT_UNITS, direction[0].mV);
+        shader->uniform4fv(LLShaderMgr::LIGHT_ATTENUATION, LL_NUM_LIGHT_UNITS, attenuation[0].mV);
+        shader->uniform3fv(LLShaderMgr::LIGHT_DIFFUSE, LL_NUM_LIGHT_UNITS, diffuse[0].mV);
+        shader->uniform4fv(LLShaderMgr::LIGHT_AMBIENT, 1, mAmbientLightColor.mV);
         shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_primary[0] ? 1 : 0);
         shader->uniform4fv(LLShaderMgr::AMBIENT, 1, mAmbientLightColor.mV);
         shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].mV);
         shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, diffuse_b[0].mV);
-	}
+    }
 }
 
 void LLRender::syncMatrices()
@@ -1539,11 +1545,17 @@ void LLRender::matrixMode(eMatrixMode mode)
 	{
         U32 tex_index = gGL.getCurrentTexUnitIndex();
         // the shaders don't actually reference anything beyond texture_matrix0/1 outside of terrain rendering
-        llassert_always(tex_index <= 3);
-		mode = eMatrixMode(MM_TEXTURE0 + gGL.getCurrentTexUnitIndex());
+        llassert(tex_index <= 3);
+        mode = eMatrixMode(MM_TEXTURE0 + tex_index);
+        if (mode > MM_TEXTURE3)
+        {
+            // getCurrentTexUnitIndex() can go as high as 32 (LL_NUM_TEXTURE_LAYERS)
+            // Large value will result in a crash at mMatrix
+            LL_WARNS_ONCE() << "Attempted to assign matrix mode out of bounds: " << mode << LL_ENDL;
+            mode = MM_TEXTURE0;
+        }
 	}
 
-	llassert(mode < NUM_MATRIX_MODES);
 	mMatrixMode = mode;
 }
 
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index 9fb4f7f2b07d18aed7bf79ea6bf7d69cad19a89d..e3c0255290fde73daac8dc5ff82493f47a4e186a 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -501,23 +501,23 @@ U32 LLRenderTarget::getNumTextures() const
 	return mTex.size();
 }
 
-
 void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
 {
-	gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
+    gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
 
     bool isSRGB = false;
     llassert(mInternalFormat.size() > index);
     switch (mInternalFormat[index])
     {
-        case GL_SRGB_ALPHA:
         case GL_SRGB:
+        case GL_SRGB8:
+        case GL_SRGB_ALPHA:
         case GL_SRGB8_ALPHA8:
             isSRGB = true;
-        break;
+            break;
 
         default:
-        break;
+            break;
     }
 
     gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 13830208732d0a97c1821d16a7f290a8aedd01c0..236ebbd78fa013ccf0e8c0b0e799885bed5fb186 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1180,7 +1180,7 @@ void LLShaderMgr::initAttribsAndUniforms()
 
 	llassert(mReservedUniforms.size() == LLShaderMgr::MULTI_LIGHT_FAR_Z+1);
 
-
+    //NOTE: MUST match order in eGLSLReservedUniforms
 	mReservedUniforms.push_back("proj_mat");
 	mReservedUniforms.push_back("proj_near");
 	mReservedUniforms.push_back("proj_p");
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index a228920441cd2333fb157c8c0879a3fe94039cd6..b03e20c45679019318972bb0a1883a69c7a2b5d4 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.9
+6.4.10
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index c595a1c176c30f673fed3f3f6fab2274a8be2cf3..8d5a97d1cb3d6092180a0f7fee8b212e684a5173 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -812,17 +812,6 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
-    <key>FramePerSecondLimit</key>
-    <map>
-      <key>Comment</key>
-      <string>Controls upper limit of frames per second</string>
-      <key>Persist</key>
-      <integer>1</integer>
-      <key>Type</key>
-      <string>U32</string>
-      <key>Value</key>
-      <integer>120</integer>
-    </map>
     <key>BackgroundYieldTime</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index caa4fe1f65c5188c9ea15a231fb6165e0956fca9..b7036e02cfcc8f169dcdad32f858f334c79159c5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -1,24 +1,24 @@
-/** 
+/**
  * @file WLCloudsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -33,26 +33,26 @@ ATTRIBUTE vec2 texcoord0;
 ///////////////////////////////////////////////////////////////////////////////
 
 // Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec4  vary_CloudColorSun;
+VARYING vec4  vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
 
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
+VARYING vec2  vary_texcoord0;
+VARYING vec2  vary_texcoord1;
+VARYING vec2  vary_texcoord2;
+VARYING vec2  vary_texcoord3;
 VARYING float altitude_blend_factor;
 
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -60,7 +60,7 @@ uniform float cloud_shadow;
 uniform float density_multiplier;
 uniform float max_y;
 
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
@@ -70,133 +70,123 @@ uniform float cloud_scale;
 // NOTE: Keep these in sync!
 //       indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
 //       indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+//       indra\newview\app-settings\shaders\class2\windlight\cloudsV.glsl
 //       indra\newview\lllegacyatmospherics.cpp
+//       indra\newview\llsettingsvo.cpp
 void main()
 {
-
-	// World / view / projection
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-
-	// Texture coords
-	vary_texcoord0 = texcoord0;
-	vary_texcoord0.xy -= 0.5;
-	vary_texcoord0.xy /= cloud_scale;
-	vary_texcoord0.xy += 0.5;
-
-	vary_texcoord1 = vary_texcoord0;
-	vary_texcoord1.x += lightnorm.x * 0.0125;
-	vary_texcoord1.y += lightnorm.z * 0.0125;
-
-	vary_texcoord2 = vary_texcoord0 * 16.;
-	vary_texcoord3 = vary_texcoord1 * 16.;
-
-	// Get relative position
-	vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
-    altitude_blend_factor = clamp((P.y + 512.0) / max_y, 0.0, 1.0);
-
-	// Set altitude
-	if (P.y > 0.)
-	{
-		P *= (max_y / P.y);
-	}
-	else
-	{
-		altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
-		P *= (-32000. / P.y);
-	}
-
-	// Can normalize then
-	vec3 Pn = normalize(P);
-	float  Plen = length(P);
-
-	// Initialize temp variables
-	vec4 temp1 = vec4(0.);
-	vec4 temp2 = vec4(0.);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	//vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-	vec4 sunlight = sunlight_color;
-	vec4 light_atten;
-
-    float dens_mul = density_multiplier;
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
-	// Calculate relative weights
-	temp1 = abs(blue_density) + vec4(abs(haze_density));
-	blue_weight = blue_density / temp1;
-	haze_weight = haze_density / temp1;
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Distance
-	temp2.z = Plen * dens_mul;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z);
-
-
-	// Compute haze glow
-	temp2.x = dot(Pn, lightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .001);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.x *= glow.x;
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.x = pow(temp2.x, glow.z);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-    temp2.x *= sun_moon_glow_factor;
-
-	// Add "minimum anti-solar illumination"
-	temp2.x += .25;
-
-	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient_color;
-	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
-
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1. - cloud_shadow);
-
-	// Haze color below cloud
-	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-			 );	
-
-	// CLOUDS
-	temp2.y = max(0., lightnorm.y * 2.);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Cloud color out
-	vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
-	vary_CloudColorAmbient = tmpAmbient * cloud_color;
-	
-	// Attenuate cloud color by atmosphere
-	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
-	vary_CloudColorSun *= temp1;
-	vary_CloudColorAmbient *= temp1;
-	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
-
-	// Make a nice cloud density based on the cloud_shadow value that was passed in.
-	vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
-
-	// Combine these to minimize register use
-	vary_CloudColorAmbient += oHazeColorBelowCloud;
-
-	// needs this to compile on mac
-	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
-	// END CLOUDS
+    // World / view / projection
+    gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+    // Texture coords
+    // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+    vary_texcoord0 = vec2(-texcoord0.x, texcoord0.y);  // See: LLSettingsVOSky::applySpecial
+
+    vary_texcoord0.xy -= 0.5;
+    vary_texcoord0.xy /= cloud_scale;
+    vary_texcoord0.xy += 0.5;
+
+    vary_texcoord1 = vary_texcoord0;
+    vary_texcoord1.x += lightnorm.x * 0.0125;
+    vary_texcoord1.y += lightnorm.z * 0.0125;
+
+    vary_texcoord2 = vary_texcoord0 * 16.;
+    vary_texcoord3 = vary_texcoord1 * 16.;
+
+    // Get relative position
+    vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+    altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
+
+    // Set altitude
+    if (rel_pos.y > 0)
+    {
+        rel_pos *= (max_y / rel_pos.y);
+    }
+    if (rel_pos.y < 0)
+    {
+        altitude_blend_factor = 0;  // SL-11589 Fix clouds drooping below horizon
+        rel_pos *= (-32000. / rel_pos.y);
+    }
+
+    // Can normalize then
+    vec3  rel_pos_norm = normalize(rel_pos);
+    float rel_pos_len  = length(rel_pos);
+
+    // Initialize temp variables
+    vec4 sunlight = sunlight_color;
+    vec4 light_atten;
+
+    // Sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+    // Calculate relative weights
+    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = haze_density / combined_haze;
+
+    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+    float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Distance
+    float density_dist = rel_pos_len * density_multiplier;
+
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+    // compiler gets confused.
+    combined_haze = exp(-combined_haze * density_dist);
+
+    // Compute haze glow
+    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);
+    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+    haze_glow *= sun_moon_glow_factor;
+
+    // Add "minimum anti-solar illumination"
+    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+    // Increase ambient when there are more clouds
+    vec4 tmpAmbient = ambient_color;
+    tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+
+    // Dim sunlight by cloud shadow percentage
+    sunlight *= (1. - cloud_shadow);
+
+    // Haze color below cloud
+    vec4 additiveColorBelowCloud =
+        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+
+    // CLOUDS
+    off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Cloud color out
+    vary_CloudColorSun     = (sunlight * haze_glow) * cloud_color;
+    vary_CloudColorAmbient = tmpAmbient * cloud_color;
+
+    // Attenuate cloud color by atmosphere
+    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
+    vary_CloudColorSun *= combined_haze;
+    vary_CloudColorAmbient *= combined_haze;
+    vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+
+    // Make a nice cloud density based on the cloud_shadow value that was passed in.
+    vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+
+    // Combine these to minimize register use
+    vary_CloudColorAmbient += oHazeColorBelowCloud;
+
+    // needs this to compile on mac
+    // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+
+    // END CLOUDS
 }
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index bd0ad3bce80bf49604cb1eccd97b81dc841fccba..6b36d00f97e504b57a33e0b9f7c31b3bccfbab89 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -42,6 +42,9 @@ VARYING vec4 vary_position;
 
 uniform samplerCube environmentMap;
 
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
 vec3 fullbrightShinyAtmosTransport(vec3 light);
 vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
 vec3 fullbrightScaleSoftClip(vec3 light);
@@ -51,7 +54,9 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou
 vec3 linear_to_srgb(vec3 c);
 vec3 srgb_to_linear(vec3 c);
 
-
+// See:
+//   class1\deferred\fullbrightShinyF.glsl
+//   class1\lighting\lightFullbrightShinyF.glsl
 void main()
 {
 #ifdef HAS_DIFFUSE_LOOKUP
@@ -59,25 +64,39 @@ void main()
 #else
 	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
 #endif
-	
+
 	color.rgb *= vertex_color.rgb;
-	vec3 pos = vary_position.xyz/vary_position.w;
 
-	vec3 sunlit;
-	vec3 amblit;
-	vec3 additive;
-	vec3 atten;
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 0)
+	{
+		vec3 sunlit;
+		vec3 amblit;
+		vec3 additive;
+		vec3 atten;
+		vec3 pos = vary_position.xyz/vary_position.w;
+
+		calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
 
-	calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
-	
-	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
-	float env_intensity = vertex_color.a;
-	color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+		vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+		float env_intensity = vertex_color.a;
 
 	//color.rgb = srgb_to_linear(color.rgb);
-	
-	color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
-	color.rgb = fullbrightScaleSoftClip(color.rgb);
+		color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+
+		color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
+		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	}
+
+/*
+	// NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
+	else
+	{
+		vec3  envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+		float env_intensity = vertex_color.a;
+		color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
+	}
+*/
 
 	color.a = 1.0;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 0afd1a96720e026652903eeb17057c4173e187d2..80d19102b6ce957d0e8defa72d93bbcd77617322 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -1,439 +1,443 @@
-/**
-* @file materialF.glsl
-*
-* $LicenseInfo:firstyear=2007&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2007, Linden Research, Inc.
-*
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-*
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-* Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-*
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
-* $/LicenseInfo$
-*/
-
-/*[EXTRA_CODE_HERE]*/
-
-//class1/deferred/materialF.glsl
-
-// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
-
-#define DIFFUSE_ALPHA_MODE_NONE     0
-#define DIFFUSE_ALPHA_MODE_BLEND    1
-#define DIFFUSE_ALPHA_MODE_MASK     2
-#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-
-uniform float emissive_brightness;  // fullbright flag, 1.0 == fullbright, 0.0 otherwise
-uniform int sun_up_factor;
-
-#ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
-#endif
-
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
-
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
-
-vec3 srgb_to_linear(vec3 cs);
-vec3 linear_to_srgb(vec3 cs);
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-#ifdef HAS_SUN_SHADOW
-float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
-#endif
-
-uniform samplerCube environmentMap;
-uniform sampler2D     lightFunc;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-uniform mat3 env_mat;
-
-uniform vec3 sun_dir;
-uniform vec3 moon_dir;
-VARYING vec2 vary_fragcoord;
-
-VARYING vec3 vary_position;
-
-uniform mat4 proj_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec4 light_attenuation[8];
-uniform vec3 light_diffuse[8];
-
-float getAmbientClamp();
-
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
-{
-    vec3 col = vec3(0);
-
-    //get light vector
-    vec3 lv = lp.xyz - v;
-
-    //get distance
-    float dist = length(lv);
-    float da = 1.0;
-
-    dist /= la;
-
-    if (dist > 0.0 && la > 0.0)
-    {
-        //normalize light vector
-        lv = normalize(lv);
-
-        //distance attenuation
-        float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
-        dist_atten *= dist_atten;
-        dist_atten *= 2.0f;
-
-        if (dist_atten <= 0.0)
-        {
-            return col;
-        }
-
-        // spotlight coefficient.
-        float spot = max(dot(-ln, lv), is_pointlight);
-        da *= spot*spot; // GL_SPOT_EXPONENT=2
-
-        //angular attenuation
-        da *= dot(n, lv);
-
-        float lit = 0.0f;
-
-        float amb_da = ambiance;
-        if (da >= 0)
-        {
-            lit = max(da * dist_atten, 0.0);
-            col = lit * light_col * diffuse;
-            amb_da += (da*0.5 + 0.5) * ambiance;
-        }
-        amb_da += (da*da*0.5 + 0.5) * ambiance;
-        amb_da *= dist_atten;
-        amb_da = min(amb_da, 1.0f - lit);
-
-        // SL-10969 need to see why these are blown out
-        //col.rgb += amb_da * light_col * diffuse;
-
-        if (spec.a > 0.0)
-        {
-            //vec3 ref = dot(pos+lv, norm);
-            vec3 h = normalize(lv + npos);
-            float nh = dot(n, h);
-            float nv = dot(n, npos);
-            float vh = dot(npos, h);
-            float sa = nh;
-            float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
-            float gtdenom = 2 * nh;
-            float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
-            if (nh > 0.0)
-            {
-                float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
-                vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
-                speccol = clamp(speccol, vec3(0), vec3(1));
-                col += speccol;
-
-                float cur_glare = max(speccol.r, speccol.g);
-                cur_glare = max(cur_glare, speccol.b);
-                glare = max(glare, speccol.r);
-                glare += max(cur_glare, 0.0);
-            }
-        }
-    }
-
-    return max(col, vec3(0.0, 0.0, 0.0));
-}
-
-#else
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-#endif
-
-uniform sampler2D diffuseMap;  //always in sRGB space
-
-#ifdef HAS_NORMAL_MAP
-uniform sampler2D bumpMap;
-#endif
-
-#ifdef HAS_SPECULAR_MAP
-uniform sampler2D specularMap;
-
-VARYING vec2 vary_texcoord2;
-#endif
-
-uniform float env_intensity;
-uniform vec4 specular_color;  // specular color RGB and specular exponent (glossiness) in alpha
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-uniform float minimum_alpha;
-#endif
-
-#ifdef HAS_NORMAL_MAP
-VARYING vec3 vary_mat0;
-VARYING vec3 vary_mat1;
-VARYING vec3 vary_mat2;
-VARYING vec2 vary_texcoord1;
-#else
-VARYING vec3 vary_normal;
-#endif
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-vec2 encode_normal(vec3 n);
-
-void main()
-{
-    vec2 pos_screen = vary_texcoord0.xy;
-
-    vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
-	diffcol.rgb *= vertex_color.rgb;
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-
-    // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
-    float bias = 0.001953125; // 1/512, or half an 8-bit quantization
-    if (diffcol.a < minimum_alpha-bias)
-    {
-        discard;
-    }
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-	vec3 gamma_diff = diffcol.rgb;
-	diffcol.rgb = srgb_to_linear(diffcol.rgb);
-#endif
-
-#ifdef HAS_SPECULAR_MAP
-    vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
-    spec.rgb *= specular_color.rgb;
-#else
-    vec4 spec = vec4(specular_color.rgb, 1.0);
-#endif
-
-#ifdef HAS_NORMAL_MAP
-	vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
-
-	norm.xyz = norm.xyz * 2 - 1;
-
-	vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
-			  dot(norm.xyz,vary_mat1),
-			  dot(norm.xyz,vary_mat2));
-#else
-	vec4 norm = vec4(0,0,0,1.0);
-	vec3 tnorm = vary_normal;
-#endif
-
-    norm.xyz = normalize(tnorm.xyz);
-
-    vec2 abnormal = encode_normal(norm.xyz);
-
-    vec4 final_color = diffcol;
-
-#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
-	final_color.a = emissive_brightness;
-#else
-	final_color.a = max(final_color.a, emissive_brightness);
-#endif
-
-    vec4 final_specular = spec;
-    
-#ifdef HAS_SPECULAR_MAP
-    vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
-	final_specular.a = specular_color.a * norm.a;
-#else
-	vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
-	final_specular.a = specular_color.a;
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-    //forward rendering, output just lit sRGBA
-    vec3 pos = vary_position;
-
-    float shadow = 1.0f;
-
-#ifdef HAS_SUN_SHADOW
-    shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
-#endif
-
-    spec = final_specular;
-    vec4 diffuse = final_color;
-    float envIntensity = final_normal.z;
-
-    vec3 color = vec3(0,0,0);
-
-    vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
-
-    float bloom = 0.0;
-    vec3 sunlit;
-    vec3 amblit;
-    vec3 additive;
-    vec3 atten;
-
-    calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
-    
-        // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
-        // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
-        // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
-        //color = fullbrightScaleSoftClip(color);
-
-    vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
-    //we're in sRGB space, so gamma correct this dot product so 
-    // lighting from the sun stays sharp
-    float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
-    da = pow(da, 1.0 / 1.3);
-
-    color = amblit;
-
-    //darken ambient for normals perpendicular to light vector so surfaces in shadow 
-    // and facing away from light still have some definition to them.
-    // do NOT gamma correct this dot product so ambient lighting stays soft
-    float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
-    ambient *= 0.5;
-    ambient *= ambient;
-    ambient = (1.0 - ambient);
-
-    vec3 sun_contrib = min(da, shadow) * sunlit;
-    
-    color *= ambient;
-
-    color += sun_contrib;
-
-    color *= gamma_diff.rgb;
-
-    float glare = 0.0;
-
-    if (spec.a > 0.0) // specular reflection
-    {
-#if 1 //EEP
-
-        vec3 npos = -normalize(pos.xyz);
-
-        //vec3 ref = dot(pos+lv, norm);
-        vec3 h = normalize(light_dir.xyz + npos);
-        float nh = dot(norm.xyz, h);
-        float nv = dot(norm.xyz, npos);
-        float vh = dot(npos, h);
-        float sa = nh;
-        float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
-
-        float gtdenom = 2 * nh;
-        float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-
-        if (nh > 0.0)
-        {
-            float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
-            vec3 sp = sun_contrib*scol / 6.0f;
-            sp = clamp(sp, vec3(0), vec3(1));
-            bloom = dot(sp, sp) / 4.0;
-            color += sp * spec.rgb;
-        }
-#else // PRODUCTION
-        float sa = dot(refnormpersp, sun_dir.xyz);
-		vec3 dumbshiny = sunlit*shadow*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-							
-		// add the two types of shiny together
-		vec3 spec_contrib = dumbshiny * spec.rgb;
-		bloom = dot(spec_contrib, spec_contrib) / 6;
-
-		glare = max(spec_contrib.r, spec_contrib.g);
-		glare = max(glare, spec_contrib.b);
-
-		color += spec_contrib;
-#endif
-    }
-
-    color = mix(color.rgb, diffcol.rgb, diffuse.a);
-    
-    if (envIntensity > 0.0)
-    {
-        //add environmentmap
-        vec3 env_vec = env_mat * refnormpersp;
-
-        vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
-
-        color = mix(color, reflected_color, envIntensity);
-
-        float cur_glare = max(reflected_color.r, reflected_color.g);
-        cur_glare = max(cur_glare, reflected_color.b);
-        cur_glare *= envIntensity*4.0;
-        glare += cur_glare;
-    }
-
-    color = atmosFragLighting(color, additive, atten);
-    color = scaleSoftClipFrag(color);
-
-    //convert to linear before adding local lights
-    color = srgb_to_linear(color);
-
-    vec3 npos = normalize(-pos.xyz);
-
-    vec3 light = vec3(0, 0, 0);
-    
-#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
-
-    LIGHT_LOOP(1)
-        LIGHT_LOOP(2)
-        LIGHT_LOOP(3)
-        LIGHT_LOOP(4)
-        LIGHT_LOOP(5)
-        LIGHT_LOOP(6)
-        LIGHT_LOOP(7)
-
-    color += light;
-
-    glare = min(glare, 1.0);
-    float al = max(diffcol.a, glare)*vertex_color.a;
-
-    //convert to srgb as this color is being written post gamma correction
-    color = linear_to_srgb(color);
-
-#ifdef WATER_FOG
-    vec4 temp = applyWaterFogView(pos, vec4(color, al));
-    color = temp.rgb;
-    al = temp.a;
-#endif
-
-    frag_color = vec4(color, al);
-
-#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer 
-
-    // deferred path
-    frag_data[0] = final_color; //gbuffer is sRGB
-    frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
-    frag_data[2] = final_normal; // XY = Normal.  Z = Env. intensity.
-#endif
-}
-
+/**
+* @file materialF.glsl
+*
+* $LicenseInfo:firstyear=2007&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2007, Linden Research, Inc.
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+
+/*[EXTRA_CODE_HERE]*/
+
+//class1/deferred/materialF.glsl
+
+// This shader is used for both writing opaque/masked content to the gbuffer and writing blended content to the framebuffer during the alpha pass.
+
+#define DIFFUSE_ALPHA_MODE_NONE     0
+#define DIFFUSE_ALPHA_MODE_BLEND    1
+#define DIFFUSE_ALPHA_MODE_MASK     2
+#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
+
+uniform float emissive_brightness;  // fullbright flag, 1.0 == fullbright, 0.0 otherwise
+uniform int sun_up_factor;
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3 scaleSoftClipFrag(vec3 l);
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cs);
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+#ifdef HAS_SUN_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
+
+uniform samplerCube environmentMap;
+uniform sampler2D     lightFunc;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform mat3 env_mat;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+VARYING vec2 vary_fragcoord;
+
+VARYING vec3 vary_position;
+
+uniform mat4 proj_mat;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+uniform vec4 light_position[8];
+uniform vec3 light_direction[8];
+uniform vec4 light_attenuation[8];
+uniform vec3 light_diffuse[8];
+
+float getAmbientClamp();
+
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
+{
+    vec3 col = vec3(0);
+
+    //get light vector
+    vec3 lv = lp.xyz - v;
+
+    //get distance
+    float dist = length(lv);
+    float da = 1.0;
+
+    dist /= la;
+
+    if (dist > 0.0 && la > 0.0)
+    {
+        //normalize light vector
+        lv = normalize(lv);
+
+        //distance attenuation
+        float dist_atten = clamp(1.0 - (dist - 1.0*(1.0 - fa)) / fa, 0.0, 1.0);
+        dist_atten *= dist_atten;
+        dist_atten *= 2.0f;
+
+        if (dist_atten <= 0.0)
+        {
+            return col;
+        }
+
+        // spotlight coefficient.
+        float spot = max(dot(-ln, lv), is_pointlight);
+        da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+        //angular attenuation
+        da *= dot(n, lv);
+
+        float lit = 0.0f;
+
+        float amb_da = ambiance;
+        if (da >= 0)
+        {
+            lit = max(da * dist_atten, 0.0);
+            col = lit * light_col * diffuse;
+            amb_da += (da*0.5 + 0.5) * ambiance;
+        }
+        amb_da += (da*da*0.5 + 0.5) * ambiance;
+        amb_da *= dist_atten;
+        amb_da = min(amb_da, 1.0f - lit);
+
+        // SL-10969 need to see why these are blown out
+        //col.rgb += amb_da * light_col * diffuse;
+
+        if (spec.a > 0.0)
+        {
+            //vec3 ref = dot(pos+lv, norm);
+            vec3 h = normalize(lv + npos);
+            float nh = dot(n, h);
+            float nv = dot(n, npos);
+            float vh = dot(npos, h);
+            float sa = nh;
+            float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+            float gtdenom = 2 * nh;
+            float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+            if (nh > 0.0)
+            {
+                float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+                vec3 speccol = lit*scol*light_col.rgb*spec.rgb;
+                speccol = clamp(speccol, vec3(0), vec3(1));
+                col += speccol;
+
+                float cur_glare = max(speccol.r, speccol.g);
+                cur_glare = max(cur_glare, speccol.b);
+                glare = max(glare, speccol.r);
+                glare += max(cur_glare, 0.0);
+            }
+        }
+    }
+
+    return max(col, vec3(0.0, 0.0, 0.0));
+}
+
+#else
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+#endif
+
+uniform sampler2D diffuseMap;  //always in sRGB space
+
+#ifdef HAS_NORMAL_MAP
+uniform sampler2D bumpMap;
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+uniform sampler2D specularMap;
+
+VARYING vec2 vary_texcoord2;
+#endif
+
+uniform float env_intensity;
+uniform vec4 specular_color;  // specular color RGB and specular exponent (glossiness) in alpha
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+uniform float minimum_alpha;
+#endif
+
+#ifdef HAS_NORMAL_MAP
+VARYING vec3 vary_mat0;
+VARYING vec3 vary_mat1;
+VARYING vec3 vary_mat2;
+VARYING vec2 vary_texcoord1;
+#else
+VARYING vec3 vary_normal;
+#endif
+
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec2 encode_normal(vec3 n);
+
+void main()
+{
+    vec2 pos_screen = vary_texcoord0.xy;
+
+    vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
+	diffcol.rgb *= vertex_color.rgb;
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
+
+    // Comparing floats cast from 8-bit values, produces acne right at the 8-bit transition points
+    float bias = 0.001953125; // 1/512, or half an 8-bit quantization
+    if (diffcol.a < minimum_alpha-bias)
+    {
+        discard;
+    }
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+	vec3 gamma_diff = diffcol.rgb;
+	diffcol.rgb = srgb_to_linear(diffcol.rgb);
+#endif
+
+#ifdef HAS_SPECULAR_MAP
+    vec4 spec = texture2D(specularMap, vary_texcoord2.xy);
+    spec.rgb *= specular_color.rgb;
+#else
+    vec4 spec = vec4(specular_color.rgb, 1.0);
+#endif
+
+#ifdef HAS_NORMAL_MAP
+	vec4 norm = texture2D(bumpMap, vary_texcoord1.xy);
+
+	norm.xyz = norm.xyz * 2 - 1;
+
+	vec3 tnorm = vec3(dot(norm.xyz,vary_mat0),
+			  dot(norm.xyz,vary_mat1),
+			  dot(norm.xyz,vary_mat2));
+#else
+	vec4 norm = vec4(0,0,0,1.0);
+	vec3 tnorm = vary_normal;
+#endif
+
+    norm.xyz = normalize(tnorm.xyz);
+
+    vec2 abnormal = encode_normal(norm.xyz);
+
+    vec4 final_color = diffcol;
+
+#if (DIFFUSE_ALPHA_MODE != DIFFUSE_ALPHA_MODE_EMISSIVE)
+	final_color.a = emissive_brightness;
+#else
+	final_color.a = max(final_color.a, emissive_brightness);
+#endif
+
+    vec4 final_specular = spec;
+    
+#ifdef HAS_SPECULAR_MAP
+    vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity * spec.a, 0.0);
+	final_specular.a = specular_color.a * norm.a;
+#else
+	vec4 final_normal = vec4(encode_normal(normalize(tnorm)), env_intensity, 0.0);
+	final_specular.a = specular_color.a;
+#endif
+
+#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
+
+    //forward rendering, output just lit sRGBA
+    vec3 pos = vary_position;
+
+    float shadow = 1.0f;
+
+#ifdef HAS_SUN_SHADOW
+    shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, pos_screen);
+#endif
+
+    spec = final_specular;
+    vec4 diffuse = final_color;
+    float envIntensity = final_normal.z;
+
+    vec3 color = vec3(0,0,0);
+
+    vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
+
+    float bloom = 0.0;
+    vec3 sunlit;
+    vec3 amblit;
+    vec3 additive;
+    vec3 atten;
+
+    calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
+    
+        // This call breaks the Mac GLSL compiler/linker for unknown reasons (17Mar2020)
+        // The call is either a no-op or a pure (pow) gamma adjustment, depending on GPU level
+        // TODO: determine if we want to re-apply the gamma adjustment, and if so understand & fix Mac breakage
+        //color = fullbrightScaleSoftClip(color);
+
+    vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+    //we're in sRGB space, so gamma correct this dot product so 
+    // lighting from the sun stays sharp
+    float da = clamp(dot(normalize(norm.xyz), light_dir.xyz), 0.0, 1.0);
+    da = pow(da, 1.0 / 1.3);
+
+    color = amblit;
+
+    //darken ambient for normals perpendicular to light vector so surfaces in shadow 
+    // and facing away from light still have some definition to them.
+    // do NOT gamma correct this dot product so ambient lighting stays soft
+    float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+    ambient *= 0.5;
+    ambient *= ambient;
+    ambient = (1.0 - ambient);
+
+    vec3 sun_contrib = min(da, shadow) * sunlit;
+    
+    color *= ambient;
+
+    color += sun_contrib;
+
+    color *= gamma_diff.rgb;
+
+    float glare = 0.0;
+
+    if (spec.a > 0.0)  // specular reflection
+    {
+        /*  // Reverting this specular calculation to previous 'dumbshiny' version - DJH 6/17/2020
+            // Preserving the refactored version as a comment for potential reconsideration,
+            // overriding the general rule to avoid pollutiong the source with commented code.
+            //
+            //  If you're reading this in 2021+, feel free to obliterate.
+
+        vec3 npos = -normalize(pos.xyz);
+
+        //vec3 ref = dot(pos+lv, norm);
+        vec3 h = normalize(light_dir.xyz + npos);
+        float nh = dot(norm.xyz, h);
+        float nv = dot(norm.xyz, npos);
+        float vh = dot(npos, h);
+        float sa = nh;
+        float fres = pow(1 - dot(h, npos), 5)*0.4 + 0.5;
+
+        float gtdenom = 2 * nh;
+        float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+        if (nh > 0.0)
+        {
+            float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt / (nh*da);
+            vec3 sp = sun_contrib*scol / 6.0f;
+            sp = clamp(sp, vec3(0), vec3(1));
+            bloom = dot(sp, sp) / 4.0;
+            color += sp * spec.rgb;
+        }
+        */
+
+        float sa        = dot(refnormpersp, sun_dir.xyz);
+        vec3  dumbshiny = sunlit * shadow * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+        // add the two types of shiny together
+        vec3 spec_contrib = dumbshiny * spec.rgb;
+        bloom             = dot(spec_contrib, spec_contrib) / 6;
+
+        glare = max(spec_contrib.r, spec_contrib.g);
+        glare = max(glare, spec_contrib.b);
+
+        color += spec_contrib;
+    }
+
+    color = mix(color.rgb, diffcol.rgb, diffuse.a);
+
+    if (envIntensity > 0.0)
+    {
+        //add environmentmap
+        vec3 env_vec = env_mat * refnormpersp;
+
+        vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+
+        color = mix(color, reflected_color, envIntensity);
+
+        float cur_glare = max(reflected_color.r, reflected_color.g);
+        cur_glare = max(cur_glare, reflected_color.b);
+        cur_glare *= envIntensity*4.0;
+        glare += cur_glare;
+    }
+
+    color = atmosFragLighting(color, additive, atten);
+    color = scaleSoftClipFrag(color);
+
+    //convert to linear before adding local lights
+    color = srgb_to_linear(color);
+
+    vec3 npos = normalize(-pos.xyz);
+
+    vec3 light = vec3(0, 0, 0);
+    
+#define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
+
+    LIGHT_LOOP(1)
+        LIGHT_LOOP(2)
+        LIGHT_LOOP(3)
+        LIGHT_LOOP(4)
+        LIGHT_LOOP(5)
+        LIGHT_LOOP(6)
+        LIGHT_LOOP(7)
+
+    color += light;
+
+    glare = min(glare, 1.0);
+    float al = max(diffcol.a, glare)*vertex_color.a;
+
+    //convert to srgb as this color is being written post gamma correction
+    color = linear_to_srgb(color);
+
+#ifdef WATER_FOG
+    vec4 temp = applyWaterFogView(pos, vec4(color, al));
+    color = temp.rgb;
+    al = temp.a;
+#endif
+
+    frag_color = vec4(color, al);
+
+#else // mode is not DIFFUSE_ALPHA_MODE_BLEND, encode to gbuffer 
+
+    // deferred path
+    frag_data[0] = final_color; //gbuffer is sRGB
+    frag_data[1] = final_specular; // XYZ = Specular color. W = Specular exponent.
+    frag_data[2] = final_normal; // XY = Normal.  Z = Env. intensity.
+#endif
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
index 80f232948acd4a3d1bdc4e60e83c95d555c36941..35068899eee45503ed2f943e4589c93cf9546eda 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
@@ -1,9 +1,9 @@
 /** 
- * @file moonF.glsl
+ * @file class1\deferred\moonF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2005, 2020 Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -36,34 +36,33 @@ out vec4 frag_data[3];
 uniform vec4 color;
 uniform vec4 sunlight_color;
 uniform vec4 moonlight_color;
-uniform vec3 lumWeights;
+uniform vec3 moon_dir;
 uniform float moon_brightness;
-uniform float minLuminance;
 uniform sampler2D diffuseMap;
-uniform sampler2D altDiffuseMap;
-uniform float blend_factor; // interp factor between moon A/B
+
 VARYING vec2 vary_texcoord0;
 
 vec3 srgb_to_linear(vec3 c);
-void main() 
-{
-    vec4 moonA = texture2D(diffuseMap, vary_texcoord0.xy);
-    vec4 moonB = texture2D(altDiffuseMap, vary_texcoord0.xy);
-    vec4 c     = mix(moonA, moonB, blend_factor);
 
-    c.rgb = srgb_to_linear(c.rgb);
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light);
 
-    // mix factor which blends when sunlight is brighter
-    // and shows true moon color at night
-    vec3 luma_weights = vec3(0.3, 0.5, 0.3);
+void main() 
+{
+    // Restore Pre-EEP alpha fade moon near horizon
+    float fade = 1.0;
+    if( moon_dir.z > 0 )
+        fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
 
-    vec4 light_color = max(sunlight_color, moonlight_color);
-    float mix = 1.0 - dot(normalize(light_color.rgb), luma_weights);
+    vec4 c      = texture2D(diffuseMap, vary_texcoord0.xy);
+//       c.rgb  = srgb_to_linear(c.rgb);
+         c.rgb *= moonlight_color.rgb;
+         c.rgb *= moon_brightness;
 
-    vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0  - 1.0;
-    c.rgb = pow(c.rgb, exp);
+         c.rgb *= fade;
+         c.a   *= fade;
 
-    //c.rgb *= moonlight_color.rgb;
+         c.rgb  = scaleSoftClip(c.rgb);
 
     frag_data[0] = vec4(c.rgb, c.a);
     frag_data[1] = vec4(0.0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
index e1bac4f248081f80740689aaf4399f36d9c9cf2b..c4922afd7d5e54afaa8449599042859be6da7a8f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
@@ -1,9 +1,9 @@
 /** 
- * @file moonV.glsl
+ * @file class1\deferred\moonV.glsl
  *
   * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2007, 2020 Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -32,18 +32,13 @@ ATTRIBUTE vec2 texcoord0;
 
 VARYING vec2 vary_texcoord0;
 
-void calcAtmospherics(vec3 eye_pos);
-
 void main()
 {
     //transform vertex
-    vec3 offset = vec3(0, 0, 50);
-    vec4 vert = vec4(position.xyz - offset, 1.0);
+    vec4 vert = vec4(position.xyz, 1.0);
     vec4 pos = (modelview_matrix * vert);
 
     gl_Position = modelview_projection_matrix*vert;
 
-    calcAtmospherics(pos.xyz);
-    
     vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 0d1cc817866ad5d07da80ed3a1f251888808bb29..8c402fcb5466f54b229074e4498326d370085c67 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -1,24 +1,24 @@
-/** 
- * @file multiPointLightF.glsl
+/**
+ * @file class1/deferred/multiPointLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -36,119 +36,112 @@ out vec4 frag_color;
 uniform sampler2DRect depthMap;
 uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
-uniform samplerCube environmentMap;
-uniform sampler2D noiseMap;
-uniform sampler2D lightFunc;
+uniform samplerCube   environmentMap;
+uniform sampler2D     noiseMap;
+uniform sampler2D     lightFunc;
 
-
-uniform vec3 env_mat[3];
+uniform vec3  env_mat[3];
 uniform float sun_wash;
+uniform int   light_count;
+uniform vec4  light[LIGHT_COUNT];
+uniform vec4  light_col[LIGHT_COUNT];
 
-uniform int light_count;
-
-uniform vec4 light[LIGHT_COUNT];
-uniform vec4 light_col[LIGHT_COUNT];
-
-VARYING vec4 vary_fragcoord;
-uniform vec2 screen_res;
-
+uniform vec2  screen_res;
 uniform float far_z;
+uniform mat4  inv_proj;
 
-uniform mat4 inv_proj;
+VARYING vec4 vary_fragcoord;
 
 vec4 getPosition(vec2 pos_screen);
 vec3 getNorm(vec2 pos_screen);
 vec3 srgb_to_linear(vec3 c);
 
-void main() 
+void main()
 {
-	vec3 out_col = vec3(0,0,0);
-
 #if defined(LOCAL_LIGHT_KILL)
-    discard;
-#else
-	vec2 frag = (vary_fragcoord.xy*0.5+0.5)*screen_res;
-	vec3 pos = getPosition(frag.xy).xyz;
-	if (pos.z < far_z)
-	{
-		discard;
-	}
-	
-	vec3 norm = getNorm(frag.xy);
-
-	vec4 spec = texture2DRect(specularRect, frag.xy);
-	vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
-    diff.rgb = srgb_to_linear(diff.rgb);
-	
-	float noise = texture2D(noiseMap, frag.xy/128.0).b;
-	vec3 npos = normalize(-pos);
-
-	// As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
-	for (int i = 0; i < LIGHT_COUNT; ++i)
-	{
-		vec3 lv = light[i].xyz-pos;
-		float dist = length(lv);
-		dist /= light[i].w;
-		if (dist <= 1.0)
-		{
-		float da = dot(norm, lv);
-			if (da > 0.0)
-		{
-			lv = normalize(lv);
-			da = dot(norm, lv);
-			
-			float fa = light_col[i].a+1.0;
-			float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
-			dist_atten *= dist_atten;
-            
-            // Tweak falloff slightly to match pre-EEP attenuation
-			// NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit
-			dist_atten *= 2.0;
-			
-			dist_atten *= noise;
-
-			float lit = da * dist_atten;
-						
-			vec3 col = light_col[i].rgb*lit*diff;
-			
-			//vec3 col = vec3(dist2, light_col[i].a, lit);
-			
-			if (spec.a > 0.0)
-			{
-				lit = min(da*6.0, 1.0) * dist_atten;
-				//vec3 ref = dot(pos+lv, norm);
-				vec3 h = normalize(lv+npos);
-				float nh = dot(norm, h);
-				float nv = dot(norm, npos);
-				float vh = dot(npos, h);
-				float sa = nh;
-				float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
-				float gtdenom = 2 * nh;
-				float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-								
-				if (nh > 0.0)
-				{
-					float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
-					col += lit*scol*light_col[i].rgb*spec.rgb;
-					//col += spec.rgb;
-				}
-			}
-			
-			out_col += col;
-		}
-	}
-	}
+    discard;  // Bail immediately
 #endif
-	
-	frag_color.rgb = out_col;
-	frag_color.a = 0.0;
+
+    vec3 out_col = vec3(0, 0, 0);
+    vec2 frag    = (vary_fragcoord.xy * 0.5 + 0.5) * screen_res;
+    vec3 pos     = getPosition(frag.xy).xyz;
+    if (pos.z < far_z)
+    {
+        discard;
+    }
+
+    vec3 norm = getNorm(frag.xy);
+
+    vec4 spec = texture2DRect(specularRect, frag.xy);
+    spec.rgb  = srgb_to_linear(spec.rgb);
+    vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
+    diff.rgb  = srgb_to_linear(diff.rgb);
+
+    float noise = texture2D(noiseMap, frag.xy / 128.0).b;
+    vec3  npos  = normalize(-pos);
+
+    // As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
+    for (int i = 0; i < LIGHT_COUNT; ++i)
+    {
+        vec3  lv   = light[i].xyz - pos;
+        float dist = length(lv);
+        dist /= light[i].w;
+        if (dist <= 1.0)
+        {
+            float da = dot(norm, lv);
+            if (da > 0.0)
+            {
+                lv = normalize(lv);
+                da = dot(norm, lv);
+
+                float fa         = light_col[i].a + 1.0;
+                float dist_atten = clamp(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 0.0, 1.0);
+                dist_atten *= dist_atten;
+
+                // Tweak falloff slightly to match pre-EEP attenuation
+                // NOTE: this magic number also shows up in a great many other places, search for dist_atten *= to audit
+                dist_atten *= 2.0;
+
+                dist_atten *= noise;
+
+                float lit = da * dist_atten;
+
+                vec3 col = light_col[i].rgb * lit * diff;
+
+                if (spec.a > 0.0)
+                {
+                    lit        = min(da * 6.0, 1.0) * dist_atten;
+                    vec3  h    = normalize(lv + npos);
+                    float nh   = dot(norm, h);
+                    float nv   = dot(norm, npos);
+                    float vh   = dot(npos, h);
+                    float sa   = nh;
+                    float fres = pow(1 - dot(h, npos), 5) * 0.4 + 0.5;
+
+                    float gtdenom = 2 * nh;
+                    float gt      = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
+
+                    if (nh > 0.0)
+                    {
+                        float scol = fres * texture2D(lightFunc, vec2(nh, spec.a)).r * gt / (nh * da);
+                        col += lit * scol * light_col[i].rgb * spec.rgb;
+                    }
+                }
+
+                out_col += col;
+            }
+        }
+    }
+
+    frag_color.rgb = out_col;
+    frag_color.a   = 0.0;
 
 #ifdef IS_AMD_CARD
-	// If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage awawy which leads to unfun crashes and artifacts.
-	vec4 dummy1 = light[0];
-	vec4 dummy2 = light_col[0];
-	vec4 dummy3 = light[LIGHT_COUNT-1];
-	vec4 dummy4 = light_col[LIGHT_COUNT-1];
+    // If it's AMD make sure the GLSL compiler sees the arrays referenced once by static index. Otherwise it seems to optimise the storage
+    // awawy which leads to unfun crashes and artifacts.
+    vec4 dummy1 = light[0];
+    vec4 dummy2 = light_col[0];
+    vec4 dummy3 = light[LIGHT_COUNT - 1];
+    vec4 dummy4 = light_col[LIGHT_COUNT - 1];
 #endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index ead754ec76184e1ef81c3aed376c1329ebbac909..28a1faf24f75c47a3991d47b7a2b7e1d83731bc4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -1,24 +1,24 @@
-/** 
+/**
  * @file WLSkyV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -37,13 +37,13 @@ VARYING vec4 vary_HazeColor;
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -52,7 +52,7 @@ uniform float density_multiplier;
 uniform float distance_multiplier;
 uniform float max_y;
 
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
@@ -63,103 +63,91 @@ uniform vec4 cloud_color;
 //       indra\newview\lllegacyatmospherics.cpp
 void main()
 {
-
-	// World / view / projection
+    // World / view / projection
     vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
 
-	gl_Position = pos;
-	
-	// Get relative position
-	vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
-	// Set altitude
-	if (P.y > 0.)
-	{
-		P *= (max_y / P.y);
-	}
-	else
-	{
-		P *= (-32000. / P.y);
-	}
-
-	// Can normalize then
-	vec3 Pn = normalize(P);
-
-	float Plen = length(P);
-
-	// Initialize temp variables
-	vec4 temp1 = vec4(0.);
-	vec4 temp2 = vec4(0.);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-	vec4 light_atten;
-
-    float dens_mul = density_multiplier;
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
-	// Calculate relative weights
-	temp1 = abs(blue_density) + vec4(abs(haze_density));
-	blue_weight = blue_density / temp1;
-	haze_weight = haze_density / temp1;
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-    temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-    temp2.y = 1. / temp2.y;
-    sunlight *= exp( - light_atten * temp2.y);
-
-	// Distance
-	temp2.z = Plen * dens_mul;
-
-	// Transparency (-> temp1)
-    // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
-    // compiler gets confused.
-    temp1 = exp(-temp1 * temp2.z);
+    gl_Position = pos;
+
+    // Get relative position
+    vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+    // Adj position vector to clamp altitude
+    if (rel_pos.y > 0)
+    {
+        rel_pos *= (max_y / rel_pos.y);
+    }
+    if (rel_pos.y < 0)
+    {
+        rel_pos *= (-32000. / rel_pos.y);
+    }
+
+    // Can normalize then
+    vec3 rel_pos_norm = normalize(rel_pos);
 
-	// Compute haze glow
-	temp2.x = dot(Pn, lightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .001);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.x *= glow.x;
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.x = pow(temp2.x, glow.z);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
+    float rel_pos_len = length(rel_pos);
 
-	// Add "minimum anti-solar illumination"
-	temp2.x += .25;
+    // Initialize temp variables
+    vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+    vec4 light_atten;
 
-    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
-                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
-             );
+    // Sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
 
+    // Calculate relative weights
+    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = haze_density / combined_haze;
+
+    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+    float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Distance
+    float density_dist = rel_pos_len * density_multiplier;
+
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+    // compiler gets confused.
+    combined_haze = exp(-combined_haze * density_dist);
+
+    // Compute haze glow
+    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);
+    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+    // Add "minimum anti-solar illumination"
+    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+    vec4 color =
+        (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
 
     // Final atmosphere additive
-    color *= (1. - temp1);
+    color *= (1. - combined_haze);
 
-	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient_color;
-	tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; 
+    // Increase ambient when there are more clouds
+    vec4 tmpAmbient = ambient_color;
+    tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
 
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= max(0.0, (1. - cloud_shadow));
+    // Dim sunlight by cloud shadow percentage
+    sunlight *= max(0.0, (1. - cloud_shadow));
 
-	// Haze color below cloud
-	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-			 );	
+    // Haze color below cloud
+    vec4 additiveColorBelowCloud =
+        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
 
-	// Attenuate cloud color by atmosphere
-	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
+    // Attenuate cloud color by atmosphere
+    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
 
-	// At horizon, blend high altitude sky color towards the darker color below the clouds
-	color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+    // At horizon, blend high altitude sky color towards the darker color below the clouds
+    color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
 
     // Haze color above cloud
-	vary_HazeColor = color;	
+    vary_HazeColor = color;
 }
-
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index a5804220bc069a0ac8dca479953699e454e1ad16..f80f1a985a31a9ea796e2d47d3fef08939831e03 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -124,41 +124,15 @@ void main()
 
         if (spec.a > 0.0) // specular reflection
         {
+            float sa        = dot(refnormpersp, light_dir.xyz);
+            vec3  dumbshiny = sunlit * (texture2D(lightFunc, vec2(sa, spec.a)).r);
 
-#if 1 //EEP
-            vec3 npos = -normalize(pos.xyz);
-
-            //vec3 ref = dot(pos+lv, norm);
-            vec3 h = normalize(light_dir.xyz+npos);
-            float nh = dot(norm.xyz, h);
-            float nv = dot(norm.xyz, npos);
-            float vh = dot(npos, h);
-            float sa = nh;
-            float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
-            float gtdenom = 2 * nh;
-            float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-            
-            if (nh > 0.0)
-            {
-                float scontrib = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
-                vec3 sp = sun_contrib*scontrib / 6.0;
-                sp = clamp(sp, vec3(0), vec3(1));
-                bloom += dot(sp, sp) / 4.0;
-                color += sp * spec.rgb;
-            }
-#else //PRODUCTION
-            float sa = dot(refnormpersp, light_dir.xyz);
-            vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-            
             // add the two types of shiny together
             vec3 spec_contrib = dumbshiny * spec.rgb;
-            bloom = dot(spec_contrib, spec_contrib) / 6;
+            bloom             = dot(spec_contrib, spec_contrib) / 6;
             color.rgb += spec_contrib;
-#endif
-
         }
-       
+
        color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
 
         if (envIntensity > 0.0)
diff --git a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
index 50e781fa7867dc6e9755b04994c72b0135ce522c..6cd24455228f402580f9e9d068400b4d935728c6 100644
--- a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
@@ -23,6 +23,9 @@
  * $/LicenseInfo$
  */
 
+// Lambert Azimuthal Equal-Area projection
+// See: https://aras-p.info/texts/CompactNormalStorage.html
+// Also see: A_bit_more_deferred_-_CryEngine3.ppt
 vec2 encode_normal(vec3 n)
 {
 	float f = sqrt(8 * n.z + 8);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
index f665394b46b06c199e34a8793db3657b3367252c..0bb48061e0b391291939ca70eb907a20932ed136 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
@@ -31,6 +31,9 @@ out vec4 frag_color;
 
 uniform float minimum_alpha;
 
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO;
+uniform int no_atmo;
+
 vec3 atmosLighting(vec3 light);
 vec3 scaleSoftClip(vec3 light);
 
@@ -41,16 +44,19 @@ void default_lighting()
 {
 	vec4 color = diffuseLookup(vary_texcoord0.xy);
 	
-	color *= vertex_color;
-
 	if (color.a < minimum_alpha)
 	{
 		discard;
 	}
+	
+	color *= vertex_color;
 
-	color.rgb = atmosLighting(color.rgb);
-
-	color.rgb = scaleSoftClip(color.rgb);
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 0)
+	{
+		color.rgb = atmosLighting(color.rgb);
+		color.rgb = scaleSoftClip(color.rgb);
+	}
 
 	frag_color = color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
index 46390e4a0e4976446b1a3432a4155acc9d8e0425..1855cfceeb8c4b277e3fe3142d9a98791c4ecb3a 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
@@ -30,7 +30,10 @@ out vec4 frag_color;
 #endif
 
 uniform float minimum_alpha;
-uniform float texture_gamma;
+uniform float texture_gamma; // either 1.0 or 2.2; see: "::TEXTURE_GAMMA"
+
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
 
 vec3 fullbrightAtmosTransport(vec3 light);
 vec3 fullbrightScaleSoftClip(vec3 light);
@@ -50,9 +53,17 @@ void fullbright_lighting()
 	color.rgb *= vertex_color.rgb;
 
 	color.rgb = pow(color.rgb, vec3(texture_gamma));
-	color.rgb = fullbrightAtmosTransport(color.rgb);
-	
-	color.rgb = fullbrightScaleSoftClip(color.rgb);
+
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 0)
+	{
+		color.rgb = fullbrightAtmosTransport(color.rgb);
+		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	}
+
+	//*TODO: Are we missing an inverse pow() here?
+	// class1\lighting\lightFullbrightF.glsl has:
+    //     color.rgb = pow(color.rgb, vec3(1.0/texture_gamma));
 
 	frag_color = color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index b967709c57ce41e65aa0f3473fdded811619adca..5fcdf3107c63954568173fa3f64013e34af75428 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -34,6 +34,9 @@ VARYING vec2 vary_texcoord0;
 
 uniform float texture_gamma;
 
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO;
+uniform int no_atmo;
+
 vec3 fullbrightAtmosTransport(vec3 light);
 vec3 fullbrightScaleSoftClip(vec3 light);
 
@@ -43,9 +46,12 @@ void fullbright_lighting()
 	
 	color.rgb = pow(color.rgb, vec3(texture_gamma));
 
-	color.rgb = fullbrightAtmosTransport(color.rgb);
-	
-	color.rgb = fullbrightScaleSoftClip(color.rgb);
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 0)
+	{
+		color.rgb = fullbrightAtmosTransport(color.rgb);
+		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	}
 
 	color.rgb = pow(color.rgb, vec3(1.0/texture_gamma));
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index 567811cd75afec893025e9a282017bcdbd2aa4ad..6f7e777d23f6e16abc6324afe0cbbc0b1ec35054 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -35,20 +35,37 @@ VARYING vec3 vary_texcoord1;
 
 uniform samplerCube environmentMap;
 
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
 vec3 fullbrightShinyAtmosTransport(vec3 light);
 vec3 fullbrightScaleSoftClip(vec3 light);
 
+// See:
+//   class1\deferred\fullbrightShinyF.glsl
+//   class1\lighting\lightFullbrightShinyF.glsl
 void fullbright_shiny_lighting()
 {
 	vec4 color = diffuseLookup(vary_texcoord0.xy);
 	color.rgb *= vertex_color.rgb;
-	
-	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
-	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
 
-	color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 0)
+	{
+		vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+		color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
 
-	color.rgb = fullbrightScaleSoftClip(color.rgb);
+		color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	}
+/*
+	// NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
+	else
+	{
+		vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
+		color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
+	}
+*/
 
 	color.a = 1.0;
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index a59bd9c0a684e7e7cd9c757838ac850d37deb975..9ef7704b7038ad6ae074a8d3b5011c3fce7b48b7 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -1,4 +1,4 @@
-/** 
+/**
  * @file simpleV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
@@ -28,6 +28,9 @@ uniform mat4 texture_matrix0;
 uniform mat4 modelview_matrix;
 uniform mat4 modelview_projection_matrix;
 
+// render_hud_attachments() -> HUD objects set LLShaderMgr::NO_ATMO; used in LLDrawPoolAlpha::beginRenderPass()
+uniform int no_atmo;
+
 ATTRIBUTE vec3 position;
 void passTextureIndex();
 ATTRIBUTE vec2 texcoord0;
@@ -46,19 +49,23 @@ void main()
 {
 	//transform vertex
 	vec4 vert = vec4(position.xyz,1.0);
-	passTextureIndex();
-	vec4 pos = (modelview_matrix * vert);
 	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+
+	passTextureIndex();
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy;
-	
-	
-	
-	vec3 norm = normalize(normal_matrix * normal);
 
-	calcAtmospherics(pos.xyz);
+	// SL-9632 HUDs are affected by Atmosphere
+	if (no_atmo == 1)
+	{
+		vertex_color = diffuse_color;
+	}
+	else
+	{
+		vec4 pos = (modelview_matrix * vert);
+		vec3 norm = normalize(normal_matrix * normal);
 
-	vec4 color = calcLighting(pos.xyz, norm, diffuse_color);
-	vertex_color = color;
+		calcAtmospherics(pos.xyz);
 
-	
+		vertex_color = calcLighting(pos.xyz, norm, diffuse_color);
+	}
 }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
index dcb02bd1c17c6b5d7951dacd99e84e8058d0eadf..ea2690ba09de3d3a7c3d302dbabd0412f2799a4b 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
@@ -1,154 +1,134 @@
-/** 
+/**
  * @file class1\windlight\atmosphericsFuncs.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2019, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 uniform float cloud_shadow;
 uniform float density_multiplier;
 uniform float distance_multiplier;
 uniform float max_y;
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float scene_light_strength;
-uniform mat3 ssao_effect_mat;
-uniform int no_atmo;
+uniform mat3  ssao_effect_mat;
+uniform int   no_atmo;
 uniform float sun_moon_glow_factor;
 
-float getAmbientClamp()
+float getAmbientClamp() { return 1.0f; }
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive,
+                         out vec3 atten, bool use_ao)
 {
-    return 1.0f;
-}
+    vec3 rel_pos = inPositionEye;
 
+    //(TERRAIN) limit altitude
+    if (abs(rel_pos.y) > max_y) rel_pos *= (max_y / rel_pos.y);
 
-void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao) {
+    vec3  rel_pos_norm = normalize(rel_pos);
+    float rel_pos_len  = length(rel_pos);
+    vec4  sunlight     = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
 
-    vec3 P = inPositionEye;
-   
-    //(TERRAIN) limit altitude
-    if (P.y > max_y) P *= (max_y / P.y);
-    if (P.y < -max_y) P *= (-max_y / P.y); 
+    // sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+    // I had thought blue_density and haze_density should have equal weighting,
+    // but attenuation due to haze_density tends to seem too strong
 
-    vec3 tmpLightnorm = lightnorm.xyz;
+    vec4 combined_haze = blue_density + vec4(haze_density);
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = vec4(haze_density) / combined_haze;
 
-    vec3 Pn = normalize(P);
-    float Plen = length(P);
+    //(TERRAIN) compute sunlight from lightnorm y component. Factor is roughly cosecant(sun elevation) (for short rays like terrain)
+    float above_horizon_factor = 1.0 / max(1e-6, lightnorm.y);
+    sunlight *= exp(-light_atten * above_horizon_factor);  // for sun [horizon..overhead] this maps to an exp curve [0..1]
+
+    // main atmospheric scattering line integral
+    float density_dist = rel_pos_len * density_multiplier;
 
-    vec4 temp1 = vec4(0);
-    vec3 temp2 = vec3(0);
-    vec4 blue_weight;
-    vec4 haze_weight;
-    vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-    vec4 light_atten;
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist*distance_multiplier in a variable because the ati
+    // compiler gets confused.
+    combined_haze = exp(-combined_haze * density_dist * distance_multiplier);
 
-    float dens_mul = density_multiplier;
-    float dist_mul = distance_multiplier;
+    // final atmosphere attenuation factor
+    atten = combined_haze.rgb;
 
-    //sunlight attenuation effect (hue and brightness) due to atmosphere
-    //this is used later for sunlight modulation at various altitudes
-    light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-        //I had thought blue_density and haze_density should have equal weighting,
-        //but attenuation due to haze_density tends to seem too strong
+    // compute haze glow
+    float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
 
-    temp1 = blue_density + vec4(haze_density);
-    blue_weight = blue_density / temp1;
-    haze_weight = vec4(haze_density) / temp1;
+    // dampen sun additive contrib when not facing it...
+    // SL-13539: This "if" clause causes an "additive" white artifact at roughly 77 degreees.
+    //    if (length(light_dir) > 0.01)
+    haze_glow *= max(0.0f, dot(light_dir, rel_pos_norm));
 
-    //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-    temp2.y = max(0.0, tmpLightnorm.y);
-    if (abs(temp2.y) > 0.000001f)
-    {
-        temp2.y = 1. / abs(temp2.y);
-    }
-    temp2.y = max(0.0000001f, temp2.y);
-    sunlight *= exp(-light_atten * temp2.y);
+    haze_glow = 1. - haze_glow;
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);  // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
 
-    // main atmospheric scattering line integral
-    temp2.z = Plen * dens_mul;
+    // add "minimum anti-solar illumination"
+    haze_glow += .25;
 
-    // Transparency (-> temp1)
-    // ATI Bugfix -- can't store temp1*temp2.z*dist_mul in a variable because the ati
-    // compiler gets confused.
-    temp1 = exp(-temp1 * temp2.z * dist_mul);
+    haze_glow *= sun_moon_glow_factor;
 
-    //final atmosphere attenuation factor
-    atten = temp1.rgb;
-    
-    //compute haze glow
-    //(can use temp2.x as temp because we haven't used it yet)
-    temp2.x = dot(Pn, tmpLightnorm.xyz);
+    vec4 amb_color = ambient_color;
 
-    // dampen sun additive contrib when not facing it...
-    if (length(light_dir) > 0.01)
-    {
-        temp2.x *= max(0.0f, dot(light_dir, Pn));
-    }
-    temp2.x = 1. - temp2.x;
-        //temp2.x is 0 at the sun and increases away from sun
-    temp2.x = max(temp2.x, .001);    //was glow.y
-        //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-    temp2.x *= glow.x;
-        //higher glow.x gives dimmer glow (because next step is 1 / "angle")
-    temp2.x = pow(temp2.x, glow.z);
-        //glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-    //add "minimum anti-solar illumination"
-    temp2.x += .25;
-
-    temp2.x *= sun_moon_glow_factor;
- 
-    vec4 amb_color = ambient_color; 
-    
-    //increase ambient when there are more clouds
+    // increase ambient when there are more clouds
     vec4 tmpAmbient = amb_color + (vec4(1.) - amb_color) * cloud_shadow * 0.5;
-    
+
     /*  decrease value and saturation (that in HSV, not HSL) for occluded areas
      * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html
      * // The following line of code performs the equivalent of:
      * float ambAlpha = tmpAmbient.a;
      * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis
      * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue);
-     * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha);
+     * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat,
+     * ambAlpha);
      */
     if (use_ao)
     {
         tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
     }
 
-    //haze color
-        additive =
-        vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-      + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-          + tmpAmbient));
+    // Similar/Shared Algorithms:
+    //     indra\llinventory\llsettingssky.cpp                                        -- LLSettingsSky::calculateLightSettings()
+    //     indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars()
+    // haze color
+    vec3 cs = sunlight.rgb * (1. - cloud_shadow);
+    additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb);
 
-    //brightness of surface both sunlight and ambient
+    // brightness of surface both sunlight and ambient
     sunlit = sunlight.rgb * 0.5;
     amblit = tmpAmbient.rgb * .25;
-    additive *= vec3(1.0 - temp1);
+    additive *= vec3(1.0 - combined_haze);
 }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
index 24f3992e32fa6fbbdb3c419816f5b134af9598a1..2425a2ad049075f0dd0f294844d0ad732ab29f4c 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
@@ -3,7 +3,7 @@
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2005, Linden Research, Inc.
+ * Copyright (C) 2005, 2020 Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -36,28 +36,30 @@ out vec4 frag_color;
 uniform vec4 color;
 uniform vec4 sunlight_color;
 uniform vec4 moonlight_color;
-uniform vec3 lumWeights;
+uniform vec3 moon_dir;
 uniform float moon_brightness;
-uniform float minLuminance;
 uniform sampler2D diffuseMap;
-uniform sampler2D altDiffuseMap;
-uniform float blend_factor; // interp factor between moon A/B
+
 VARYING vec2 vary_texcoord0;
 
+vec3 scaleSoftClip(vec3 light);
+
 void main() 
 {
-    vec4 moonA = texture2D(diffuseMap, vary_texcoord0.xy);
-    vec4 moonB = texture2D(altDiffuseMap, vary_texcoord0.xy);
-    vec4 c     = mix(moonA, moonB, blend_factor);
+    // Restore Pre-EEP alpha fade moon near horizon
+    float fade = 1.0;
+    if( moon_dir.z > 0 )
+        fade = clamp( moon_dir.z*moon_dir.z*4.0, 0.0, 1.0 );
+
+    vec4 c     = texture2D(diffuseMap, vary_texcoord0.xy);
+//       c.rgb = pow(c.rgb, vec3(0.7f)); // can't use "srgb_to_linear(color.rgb)" as that is a deferred only function
+         c.rgb *= moonlight_color.rgb;
+         c.rgb *= moon_brightness;
 
-    // mix factor which blends when sunlight is brighter
-    // and shows true moon color at night
-    vec3 luma_weights = vec3(0.3, 0.5, 0.3);
-    float mix = 1.0f - dot(normalize(sunlight_color.rgb), luma_weights);
+         c.rgb *= fade;
+         c.a   *= fade;
 
-    vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0 - 1.0;
-    c.rgb = pow(c.rgb, exp);
-    //c.rgb *= moonlight_color.rgb;
+         c.rgb  = scaleSoftClip(c.rgb);
 
     frag_color = vec4(c.rgb, c.a);
 }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
index 8cd4b2ef4794611625a16d606cc5c27d8b629d4a..2fceb5f743f78d967e922f36965df88160972112 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
@@ -3,7 +3,7 @@
  *
   * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * Copyright (C) 2007, 2020 Linden Research, Inc.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -30,20 +30,15 @@ uniform mat4 modelview_projection_matrix;
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec2 texcoord0;
 
-void calcAtmospherics(vec3 inPositionEye);
-
 VARYING vec2 vary_texcoord0;
 
 void main()
 {
     //transform vertex
-    vec3 offset = vec3(0, 0, 50);
-    vec4 vert = vec4(position.xyz - offset, 1.0);
+    vec4 vert = vec4(position.xyz, 1.0);
     vec4 pos = (modelview_matrix * vert);
 
     gl_Position = modelview_projection_matrix*vert;
     
     vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-    
-    calcAtmospherics(pos.xyz);
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
index 1dce85a83b0ed14eea22f039ca8dd13d4e6454a6..1485c515a4d27863e5a4f64a26accd235de57933 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
@@ -1,24 +1,24 @@
-/** 
+/**
  * @file class2/deferred/skyF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -32,13 +32,13 @@ uniform mat4 modelview_projection_matrix;
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -47,7 +47,7 @@ uniform float density_multiplier;
 uniform float distance_multiplier;
 uniform float max_y;
 
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
@@ -73,16 +73,16 @@ uniform float ice_level;
 
 vec3 rainbow(float d)
 {
-   d = clamp(d, -1.0, 0.0);
-   float rad = (droplet_radius - 5.0f) / 1024.0f;
-   return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
+    d         = clamp(d, -1.0, 0.0);
+    float rad = (droplet_radius - 5.0f) / 1024.0f;
+    return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
 }
 
 vec3 halo22(float d)
 {
-   d = clamp(d, 0.1, 1.0);
-   float v = sqrt(clamp(1 - (d * d), 0, 1));
-   return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
+    d       = clamp(d, 0.1, 1.0);
+    float v = sqrt(clamp(1 - (d * d), 0, 1));
+    return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
 }
 
 /// Soft clips the light with a gamma correction
@@ -90,115 +90,96 @@ vec3 scaleSoftClip(vec3 light);
 
 void main()
 {
-
     // World / view / projection
-    // Get relative position
-    vec3 P = pos.xyz - camPosLocal.xyz + vec3(0,50,0);
+    // Get relative position (offset why?)
+    vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0);
 
-    // Set altitude
-    if (P.y > 0.)
+    // Adj position vector to clamp altitude
+    if (rel_pos.y > 0.)
     {
-        P *= (max_y / P.y);
+        rel_pos *= (max_y / rel_pos.y);
     }
-    else
+    if (rel_pos.y < 0.)
     {
-        P *= (-32000. / P.y);
+        rel_pos *= (-32000. / rel_pos.y);
     }
 
-    // Can normalize then
-    vec3 Pn = normalize(P);
-    float  Plen = length(P);
+    // Normalized
+    vec3  rel_pos_norm = normalize(rel_pos);
+    float rel_pos_len  = length(rel_pos);
 
     // Initialize temp variables
-    vec4 temp1 = vec4(0.);
-    vec4 temp2 = vec4(0.);
-    vec4 blue_weight;
-    vec4 haze_weight;
     vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-    vec4 light_atten;
-
-    float dens_mul = density_multiplier;
 
     // Sunlight attenuation effect (hue and brightness) due to atmosphere
     // this is used later for sunlight modulation at various altitudes
-    light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
+    vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
 
     // Calculate relative weights
-    temp1 = abs(blue_density) + vec4(abs(haze_density));
-    blue_weight = blue_density / temp1;
-    haze_weight = haze_density / temp1;
+    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = haze_density / combined_haze;
 
-    // Compute sunlight from P & lightnorm (for long rays like sky)
-    temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-    temp2.y = 1. / temp2.y;
-    sunlight *= exp( - light_atten * temp2.y);
+    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+    float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y);
+    sunlight *= exp(-light_atten * off_axis);
 
     // Distance
-    temp2.z = Plen * dens_mul;
+    float density_dist = rel_pos_len * density_multiplier;
 
-    // Transparency (-> temp1)
-    // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
     // compiler gets confused.
-    temp1 = exp(-temp1 * temp2.z);
+    combined_haze = exp(-combined_haze * density_dist);
 
     // Compute haze glow
-    temp2.x = dot(Pn, lightnorm.xyz);
-    temp2.x = 1. - temp2.x;
-        // temp2.x is 0 at the sun and increases away from sun
-    temp2.x = max(temp2.x, .001);   
-        // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-    temp2.x *= glow.x;
-        // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-    temp2.x = pow(temp2.x, glow.z);
-        // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+    float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
+    haze_glow       = 1. - haze_glow;
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);
+    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
 
     // Add "minimum anti-solar illumination"
-    temp2.x += .25;
-
-    temp2.x *= sun_moon_glow_factor;
+    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25));
 
     // Haze color above cloud
-    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
-                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
-             ); 
+    vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color) 
+               + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color);
 
     // Final atmosphere additive
-    color *= (1. - temp1);
+    color *= (1. - combined_haze);
 
     // Increase ambient when there are more clouds
-    vec4 tmpAmbient = ambient_color;
-    tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; 
+    // TODO 9/20: DJH what does this do?  max(0,(1-ambient)) will change the color
+    vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
 
     // Dim sunlight by cloud shadow percentage
     sunlight *= max(0.0, (1. - cloud_shadow));
 
     // Haze color below cloud
-    vec4 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
-                + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-             ); 
+    vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient) 
+                         + haze_horizon * haze_weight * (sunlight * haze_glow + ambient);
 
-    
-    
     // Attenuate cloud color by atmosphere
-    temp1 = sqrt(temp1);    //less atmos opacity (more transparency) below clouds
+    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
 
     // At horizon, blend high altitude sky color towards the darker color below the clouds
-    color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
-    
-    float optic_d = dot(Pn, lightnorm.xyz);
-
-    vec3 halo_22 = halo22(optic_d);
+    color += (add_below_cloud - color) * (1. - sqrt(combined_haze));
 
+    float optic_d = dot(rel_pos_norm, lightnorm.xyz);
+    vec3  halo_22 = halo22(optic_d);
     color.rgb += rainbow(optic_d);
-
     color.rgb += halo_22;
-
     color.rgb *= 2.;
     color.rgb = scaleSoftClip(color.rgb);
 
-    /// Gamma correct for WL (soft clip effect).
+    // Gamma correct for WL (soft clip effect).
     frag_data[0] = vec4(color.rgb, 1.0);
-    frag_data[1] = vec4(0.0,0.0,0.0,0.0);
-    frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog
+    frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0);
+    frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0);  // 1.0 in norm.w masks off fog
 }
-
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index b0dff0c62839c89935e2079b6f2118172eb083d2..f4db53e0b7816815fff8323758940e17283a2322 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -1,24 +1,24 @@
-/** 
+/**
  * @file class2/deferred/softenLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -39,7 +39,7 @@ uniform sampler2DRect specularRect;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 uniform sampler2DRect depthMap;
-uniform samplerCube environmentMap;
+uniform samplerCube   environmentMap;
 uniform sampler2D     lightFunc;
 
 uniform float blur_size;
@@ -50,7 +50,7 @@ uniform mat3 env_mat;
 
 uniform vec3 sun_dir;
 uniform vec3 moon_dir;
-uniform int sun_up_factor;
+uniform int  sun_up_factor;
 VARYING vec2 vary_fragcoord;
 
 uniform mat4 inv_proj;
@@ -61,10 +61,10 @@ vec4 getPositionWithDepth(vec2 pos_screen, float depth);
 
 void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
 float getAmbientClamp();
-vec3 atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
-vec3 scaleSoftClipFrag(vec3 l);
-vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
-vec3 fullbrightScaleSoftClip(vec3 light);
+vec3  atmosFragLighting(vec3 l, vec3 additive, vec3 atten);
+vec3  scaleSoftClipFrag(vec3 l);
+vec3  fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten);
+vec3  fullbrightScaleSoftClip(vec3 light);
 
 vec3 linear_to_srgb(vec3 c);
 vec3 srgb_to_linear(vec3 c);
@@ -73,128 +73,85 @@ vec3 srgb_to_linear(vec3 c);
 vec4 applyWaterFogView(vec3 pos, vec4 color);
 #endif
 
-void main() 
+void main()
 {
-    vec2 tc = vary_fragcoord.xy;
-    float depth = texture2DRect(depthMap, tc.xy).r;
-    vec4 pos = getPositionWithDepth(tc, depth);
-    vec4 norm = texture2DRect(normalMap, tc);
+    vec2  tc           = vary_fragcoord.xy;
+    float depth        = texture2DRect(depthMap, tc.xy).r;
+    vec4  pos          = getPositionWithDepth(tc, depth);
+    vec4  norm         = texture2DRect(normalMap, tc);
     float envIntensity = norm.z;
-    norm.xyz = getNorm(tc);
-    
-    vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;
-    float da = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
-    float light_gamma = 1.0/1.3;
-    da = pow(da, light_gamma);
-    
+    norm.xyz           = getNorm(tc);
+
+    vec3  light_dir   = (sun_up_factor == 1) ? sun_dir : moon_dir;
+    float da          = clamp(dot(norm.xyz, light_dir.xyz), 0.0, 1.0);
+    float light_gamma = 1.0 / 1.3;
+    da                = pow(da, light_gamma);
+
     vec4 diffuse = texture2DRect(diffuseRect, tc);
-    
-    vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+    vec4 spec    = texture2DRect(specularRect, vary_fragcoord.xy);
 
     vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
-    scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+    scol_ambocc      = pow(scol_ambocc, vec2(light_gamma));
+    float scol       = max(scol_ambocc.r, diffuse.a);
+    float ambocc     = scol_ambocc.g;
 
-    float scol = max(scol_ambocc.r, diffuse.a); 
+    vec3  color = vec3(0);
+    float bloom = 0.0;
 
-    float ambocc = scol_ambocc.g;
+    vec3 sunlit;
+    vec3 amblit;
+    vec3 additive;
+    vec3 atten;
+    calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
 
-    vec3 color = vec3(0);
-    float bloom = 0.0;
+    color.rgb = amblit;
+
+    float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+    ambient *= 0.5;
+    ambient *= ambient;
+    ambient = (1.0 - ambient);
+    color.rgb *= ambient;
+
+    vec3 sun_contrib = min(da, scol) * sunlit;
+    color.rgb += sun_contrib;
+    color.rgb *= diffuse.rgb;
+
+    vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+    if (spec.a > 0.0)  // specular reflection
     {
-        vec3 sunlit;
-        vec3 amblit;
-        vec3 additive;
-        vec3 atten;
-    
-        calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, true);
-
-        color.rgb = amblit;
-
-        float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
-        ambient *= 0.5;
-        ambient *= ambient;
-        ambient = (1.0 - ambient);
-
-        color.rgb *= ambient;
-
-        vec3 sun_contrib = min(da, scol) * sunlit;
-
-        color.rgb += sun_contrib;
-
-        color.rgb *= diffuse.rgb;
-
-        vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
-        if (spec.a > 0.0) // specular reflection
-        {
-
-#if 1 //EEP
-            vec3 npos = -normalize(pos.xyz);
-
-            //vec3 ref = dot(pos+lv, norm);
-            vec3 h = normalize(light_dir.xyz+npos);
-            float nh = dot(norm.xyz, h);
-            float nv = dot(norm.xyz, npos);
-            float vh = dot(npos, h);
-            float sa = nh;
-            float fres = pow(1 - dot(h, npos), 5)*0.4+0.5;
-
-            float gtdenom = 2 * nh;
-            float gt = max(0, min(gtdenom * nv / vh, gtdenom * da / vh));
-            
-            if (nh > 0.0)
-            {
-                float scontrib = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
-                vec3 sp = sun_contrib*scontrib / 6.0;
-                sp = clamp(sp, vec3(0), vec3(1));
-                bloom += dot(sp, sp) / 4.0;
-                color += sp * spec.rgb;
-            }
-#else //PRODUCTION
-            float sa = dot(refnormpersp, light_dir.xyz);
-            vec3 dumbshiny = sunlit*(texture2D(lightFunc, vec2(sa, spec.a)).r);
-            
-            // add the two types of shiny together
-            vec3 spec_contrib = dumbshiny * spec.rgb;
-            bloom = dot(spec_contrib, spec_contrib) / 6;
-            color.rgb += spec_contrib;
-#endif
+        float sa        = dot(refnormpersp, light_dir.xyz);
+        vec3  dumbshiny = sunlit * scol * (texture2D(lightFunc, vec2(sa, spec.a)).r);
+
+        // add the two types of shiny together
+        vec3 spec_contrib = dumbshiny * spec.rgb;
+        bloom             = dot(spec_contrib, spec_contrib) / 6;
+        color.rgb += spec_contrib;
+    }
+
+    color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
 
-        }
-       
-       color.rgb = mix(color.rgb, diffuse.rgb, diffuse.a);
-
-        if (envIntensity > 0.0)
-        { //add environmentmap
-            vec3 env_vec = env_mat * refnormpersp;
-            vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
-            color = mix(color.rgb, reflected_color, envIntensity);
-        }
-       
-        if (norm.w < 0.5)
-        {
-            color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
-            color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
-        }
-
-        #ifdef WATER_FOG
-            vec4 fogged = applyWaterFogView(pos.xyz,vec4(color, bloom));
-            color = fogged.rgb;
-            bloom = fogged.a;
-        #endif
+    if (envIntensity > 0.0)
+    {  // add environmentmap
+        vec3 env_vec         = env_mat * refnormpersp;
+        vec3 reflected_color = textureCube(environmentMap, env_vec).rgb;
+        color                = mix(color.rgb, reflected_color, envIntensity);
+    }
 
+    if (norm.w < 0.5)
+    {
+        color = mix(atmosFragLighting(color, additive, atten), fullbrightAtmosTransportFrag(color, additive, atten), diffuse.a);
+        color = mix(scaleSoftClipFrag(color), fullbrightScaleSoftClip(color), diffuse.a);
     }
 
-// linear debuggables
-//color.rgb = vec3(final_da);
-//color.rgb = vec3(ambient);
-//color.rgb = vec3(scol);
-//color.rgb = diffuse_srgb.rgb;
+#ifdef WATER_FOG
+    vec4 fogged = applyWaterFogView(pos.xyz, vec4(color, bloom));
+    color       = fogged.rgb;
+    bloom       = fogged.a;
+#endif
 
     // convert to linear as fullscreen lights need to sum in linear colorspace
     // and will be gamma (re)corrected downstream...
-    
     frag_color.rgb = srgb_to_linear(color.rgb);
-    frag_color.a = bloom;
+    frag_color.a   = bloom;
 }
-
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 2c1475d5478872d28080826443919bcfa81c52a2..1f881eb44b5fcb4f94b1e72ddd4136dac7d9bfc1 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -1,24 +1,24 @@
-/** 
+/**
  * @file class2\wl\cloudsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
@@ -33,25 +33,26 @@ ATTRIBUTE vec2 texcoord0;
 ///////////////////////////////////////////////////////////////////////////////
 
 // Output parameters
-VARYING vec4 vary_CloudColorSun;
-VARYING vec4 vary_CloudColorAmbient;
+VARYING vec4  vary_CloudColorSun;
+VARYING vec4  vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
-VARYING vec2 vary_texcoord0;
-VARYING vec2 vary_texcoord1;
-VARYING vec2 vary_texcoord2;
-VARYING vec2 vary_texcoord3;
+
+VARYING vec2  vary_texcoord0;
+VARYING vec2  vary_texcoord1;
+VARYING vec2  vary_texcoord2;
+VARYING vec2  vary_texcoord3;
 VARYING float altitude_blend_factor;
 
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -59,141 +60,133 @@ uniform float cloud_shadow;
 uniform float density_multiplier;
 uniform float max_y;
 
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
 
 uniform float cloud_scale;
 
+// NOTE: Keep these in sync!
+//       indra\newview\app_settings\shaders\class1\deferred\skyV.glsl
+//       indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+//       indra\newview\app-settings\shaders\class2\windlight\cloudsV.glsl
+//       indra\newview\lllegacyatmospherics.cpp
+//       indra\newview\llsettingsvo.cpp
 void main()
 {
+    // World / view / projection
+    gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+    // Texture coords
+    // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+    vary_texcoord0 = vec2(-texcoord0.x, texcoord0.y);  // See: LLSettingsVOSky::applySpecial
 
-	// World / view / projection
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+    vary_texcoord0.xy -= 0.5;
+    vary_texcoord0.xy /= cloud_scale;
+    vary_texcoord0.xy += 0.5;
 
-	vary_texcoord0 = texcoord0;
+    vary_texcoord1 = vary_texcoord0;
+    vary_texcoord1.x += lightnorm.x * 0.0125;
+    vary_texcoord1.y += lightnorm.z * 0.0125;
 
-	// Get relative position
-	vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
+    vary_texcoord2 = vary_texcoord0 * 16.;
+    vary_texcoord3 = vary_texcoord1 * 16.;
+
+    // Get relative position
+    vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
 
     // fade clouds beyond a certain point so the bottom of the sky dome doesn't look silly at high altitude
-    altitude_blend_factor = clamp((P.y + 512.0) / max_y, 0.0, 1.0);
-
-	// Set altitude
-	if (P.y > 0.)
-	{
-		P *= (max_y / P.y);
-	}
-	else
-	{
-		P *= (-32000. / P.y);
-	}
-
-	// Can normalize then
-	vec3 Pn = normalize(P);
-	float  Plen = length(P);
-
-	// Initialize temp variables
-	vec4 temp1 = vec4(0.);
-	vec4 temp2 = vec4(0.);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	//vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-	vec4 sunlight = sunlight_color;
-	vec4 light_atten;
-
-    float dens_mul = density_multiplier;
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
-	// Calculate relative weights
-	temp1 = abs(blue_density) + vec4(abs(haze_density));
-	blue_weight = blue_density / temp1;
-	haze_weight = haze_density / temp1;
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Distance
-	temp2.z = Plen * dens_mul;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z);
-
-
-	// Compute haze glow
-	temp2.x = dot(Pn, lightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .001);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.x *= glow.x;
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.x = pow(temp2.x, glow.z);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-    temp2.x *= sun_moon_glow_factor;
-
-	// Add "minimum anti-solar illumination"
-	temp2.x += .25;
-
-	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient_color;
-	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
-
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1. - cloud_shadow);
-
-	// Haze color below cloud
-	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-			 );	
-
-	// CLOUDS
-	temp2.y = max(0., lightnorm.y * 2.);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// Cloud color out
-	vary_CloudColorSun = (sunlight * temp2.x) * cloud_color;
-	vary_CloudColorAmbient = tmpAmbient * cloud_color;
-	
-	// Attenuate cloud color by atmosphere
-	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
-	vary_CloudColorSun *= temp1;
-	vary_CloudColorAmbient *= temp1;
-	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);
-
-	// Make a nice cloud density based on the cloud_shadow value that was passed in.
-	vary_CloudDensity = 2. * (cloud_shadow - 0.25);
-
-
-	// Texture coords
-	vary_texcoord0 = texcoord0;
-	vary_texcoord0.xy -= 0.5;
-	vary_texcoord0.xy /= cloud_scale;
-	vary_texcoord0.xy += 0.5;
-
-	vary_texcoord1 = vary_texcoord0;
-	vary_texcoord1.x += lightnorm.x * 0.0125;
-	vary_texcoord1.y += lightnorm.z * 0.0125;
-
-	vary_texcoord2 = vary_texcoord0 * 16.;
-	vary_texcoord3 = vary_texcoord1 * 16.;
-
-	// Combine these to minimize register use
-	vary_CloudColorAmbient += oHazeColorBelowCloud;
-
-	// needs this to compile on mac
-	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
-
-	// END CLOUDS
+    altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
+
+    // Adj position vector to clamp altitude
+    if (rel_pos.y > 0.)
+    {
+        rel_pos *= (max_y / rel_pos.y);
+    }
+    if (rel_pos.y < 0.)
+    {
+        rel_pos *= (-32000. / rel_pos.y);
+    }
+
+    // Can normalize then
+    vec3  rel_pos_norm = normalize(rel_pos);
+    float rel_pos_len  = length(rel_pos);
+
+    // Initialize temp variables
+    vec4 sunlight = sunlight_color;
+    vec4 light_atten;
+
+    // Sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+    // Calculate relative weights
+    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = haze_density / combined_haze;
+
+    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+    float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Distance
+    float density_dist = rel_pos_len * density_multiplier;
+
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+    // compiler gets confused.
+    combined_haze = exp(-combined_haze * density_dist);
+
+    // Compute haze glow
+    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);
+    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+    haze_glow *= sun_moon_glow_factor;
+
+    // Add "minimum anti-solar illumination"
+    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+    // Increase ambient when there are more clouds
+    vec4 tmpAmbient = ambient_color;
+    tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+
+    // Dim sunlight by cloud shadow percentage
+    sunlight *= (1. - cloud_shadow);
+
+    // Haze color below cloud
+    vec4 additiveColorBelowCloud =
+        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
+
+    // CLOUDS
+    off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Cloud color out
+    vary_CloudColorSun     = (sunlight * haze_glow) * cloud_color;
+    vary_CloudColorAmbient = tmpAmbient * cloud_color;
+
+    // Attenuate cloud color by atmosphere
+    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
+    vary_CloudColorSun *= combined_haze;
+    vary_CloudColorAmbient *= combined_haze;
+    vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
+
+    // Make a nice cloud density based on the cloud_shadow value that was passed in.
+    vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+
+    // Combine these to minimize register use
+    vary_CloudColorAmbient += oHazeColorBelowCloud;
+
+    // needs this to compile on mac
+    // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+
+    // END CLOUDS
 }
-
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 0d141342ce239d7c095446fbadaf1c41da7caf0b..a0a33b8642e516d020bb0cd569905d4c93e9477b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -1,28 +1,28 @@
-/** 
+/**
  * @file class2\wl\skyV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
 uniform mat4 modelview_projection_matrix;
 
 ATTRIBUTE vec3 position;
@@ -37,13 +37,13 @@ VARYING vec4 vary_HazeColor;
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 moonlight_color;
-uniform int sun_up_factor;
-uniform vec4 ambient_color;
-uniform vec4 blue_horizon;
-uniform vec4 blue_density;
+uniform vec4  lightnorm;
+uniform vec4  sunlight_color;
+uniform vec4  moonlight_color;
+uniform int   sun_up_factor;
+uniform vec4  ambient_color;
+uniform vec4  blue_horizon;
+uniform vec4  blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -52,110 +52,98 @@ uniform float density_multiplier;
 uniform float distance_multiplier;
 uniform float max_y;
 
-uniform vec4 glow;
+uniform vec4  glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
 
 void main()
 {
-
-	// World / view / projection
+    // World / view / projection
     vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
 
-	gl_Position = pos;
-	
-	// Get relative position
-	vec3 P = position.xyz - camPosLocal.xyz + vec3(0,50,0);
-
-	// Set altitude
-	if (P.y > 0.)
-	{
-		P *= (max_y / P.y);
-	}
-	else
-	{
-		P *= (-32000. / P.y);
-	}
-
-	// Can normalize then
-	vec3 Pn = normalize(P);
-
-	float Plen = length(P);
-
-	// Initialize temp variables
-	vec4 temp1 = vec4(0.);
-	vec4 temp2 = vec4(0.);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
-	vec4 light_atten;
-
-    float dens_mul = density_multiplier;
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
-
-	// Calculate relative weights
-	temp1 = abs(blue_density) + vec4(abs(haze_density));
-	blue_weight = blue_density / temp1;
-	haze_weight = haze_density / temp1;
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-    temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y );
-    temp2.y = 1. / temp2.y;
-    sunlight *= exp( - light_atten * temp2.y);
-
-	// Distance
-	temp2.z = Plen * dens_mul;
-
-	// Transparency (-> temp1)
-    // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
-    // compiler gets confused.
-    temp1 = exp(-temp1 * temp2.z);
+    gl_Position = pos;
+
+    // Get relative position
+    vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
+
+    // Adj position vector to clamp altitude
+    if (rel_pos.y > 0.)
+    {
+        rel_pos *= (max_y / rel_pos.y);
+    }
+    if (rel_pos.y < 0.)
+    {
+        rel_pos *= (-32000. / rel_pos.y);
+    }
 
-	// Compute haze glow
-	temp2.x = dot(Pn, lightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .001);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.x *= glow.x;
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.x = pow(temp2.x, glow.z);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
+    // Can normalize then
+    vec3 rel_pos_norm = normalize(rel_pos);
 
-	// Add "minimum anti-solar illumination"
-	temp2.x += .25;
+    float rel_pos_len = length(rel_pos);
 
-    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
-                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
-             );
+    // Initialize temp variables
+    vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color;
+    vec4 light_atten;
 
+    // Sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
+
+    // Calculate relative weights
+    vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
+    vec4 blue_weight   = blue_density / combined_haze;
+    vec4 haze_weight   = haze_density / combined_haze;
+
+    // Compute sunlight from rel_pos & lightnorm (for long rays like sky)
+    float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
+    sunlight *= exp(-light_atten * off_axis);
+
+    // Distance
+    float density_dist = rel_pos_len * density_multiplier;
+
+    // Transparency (-> combined_haze)
+    // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
+    // compiler gets confused.
+    combined_haze = exp(-combined_haze * density_dist);
+
+    // Compute haze glow
+    float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
+    // haze_glow is 0 at the sun and increases away from sun
+    haze_glow = max(haze_glow, .001);
+    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+    haze_glow *= glow.x;
+    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+    haze_glow = pow(haze_glow, glow.z);
+    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+    // Add "minimum anti-solar illumination"
+    // For sun, add to glow.  For moon, remove glow entirely. SL-13768
+    haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
+
+    vec4 color =
+        (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color));
 
     // Final atmosphere additive
-    color *= (1. - temp1);
+    color *= (1. - combined_haze);
 
-	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient_color;
-	tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; 
+    // Increase ambient when there are more clouds
+    vec4 tmpAmbient = ambient_color;
+    tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5;
 
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= max(0.0, (1. - cloud_shadow));
+    // Dim sunlight by cloud shadow percentage
+    sunlight *= max(0.0, (1. - cloud_shadow));
 
-	// Haze color below cloud
-	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
-			 );	
+    // Haze color below cloud
+    vec4 additiveColorBelowCloud =
+        (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
 
-	// Attenuate cloud color by atmosphere
-	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
+    // Attenuate cloud color by atmosphere
+    combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
 
-	// At horizon, blend high altitude sky color towards the darker color below the clouds
-	color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+    // At horizon, blend high altitude sky color towards the darker color below the clouds
+    color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze));
 
     // Haze color above cloud
-	vary_HazeColor = color;	
+    vary_HazeColor = color;
 }
-
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index f745bbde2530ab2f2feaf3ef9086e9af52a582c4..70b41a0a5faa2844101984a91d611d9d074f815c 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -73,6 +73,7 @@
 #include "llviewermedia.h"
 #include "llviewerparcelaskplay.h"
 #include "llviewerparcelmedia.h"
+#include "llviewershadermgr.h"
 #include "llviewermediafocus.h"
 #include "llviewermessage.h"
 #include "llviewerobjectlist.h"
@@ -688,8 +689,7 @@ LLAppViewer::LLAppViewer()
 	mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
 	mFastTimerLogThread(NULL),
 	mSettingsLocationList(NULL),
-	mIsFirstRun(false),
-	mMinMicroSecPerFrame(0.f)
+	mIsFirstRun(false)
 {
 	if(NULL != sInstance)
 	{
@@ -1258,10 +1258,6 @@ bool LLAppViewer::init()
 
 	joystick = LLViewerJoystick::getInstance();
 	joystick->setNeedsReset(true);
-	/*----------------------------------------------------------------------*/
-
-	gSavedSettings.getControl("FramePerSecondLimit")->getSignal()->connect(boost::bind(&LLAppViewer::onChangeFrameLimit, this, _2));
-	onChangeFrameLimit(gSavedSettings.getLLSD("FramePerSecondLimit"));
 
 	return true;
 }
@@ -1481,21 +1477,6 @@ bool LLAppViewer::doFrame()
 
 				display();
 
-				static U64 last_call = 0;
-				if (!gTeleportDisplay || gGLManager.mIsIntel) // SL-10625...throttle early, throttle often with Intel
-				{
-					// Frame/draw throttling
-					U64 elapsed_time = LLTimer::getTotalTime() - last_call;
-					if (elapsed_time < mMinMicroSecPerFrame)
-					{
-						LL_RECORD_BLOCK_TIME(FTM_SLEEP);
-						// llclamp for when time function gets funky
-						U64 sleep_time = llclamp(mMinMicroSecPerFrame - elapsed_time, (U64)1, (U64)1e6);
-						micro_sleep(sleep_time, 0);
-					}
-				}
-				last_call = LLTimer::getTotalTime();
-
 				pingMainloopTimeout("Main:Snapshot");
 				LLFloaterSnapshot::update(); // take snapshots
 					LLFloaterOutfitSnapshot::update();
@@ -5436,19 +5417,6 @@ void LLAppViewer::disconnectViewer()
 	LLUrlEntryParcel::setDisconnected(gDisconnected);
 }
 
-bool LLAppViewer::onChangeFrameLimit(LLSD const & evt)
-{
-	if (evt.asInteger() > 0)
-	{
-		mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger()));
-	}
-	else
-	{
-		mMinMicroSecPerFrame = 0;
-	}
-	return false;
-}
-
 void LLAppViewer::forceErrorLLError()
 {
    	LL_ERRS() << "This is a deliberate llerror" << LL_ENDL;
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index e8b3464c6e7815cc1b419a3e6fd64d096e938073..8f0f54de3becf1cbb6ff023652f64e90357dab75 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -255,8 +255,6 @@ class LLAppViewer : public LLApp
     void sendLogoutRequest();
     void disconnectViewer();
 
-	bool onChangeFrameLimit(LLSD const & evt);
-
 	// *FIX: the app viewer class should be some sort of singleton, no?
 	// Perhaps its child class is the singleton and this should be an abstract base.
 	static LLAppViewer* sInstance; 
@@ -313,10 +311,7 @@ class LLAppViewer : public LLApp
 	// llcorehttp library init/shutdown helper
 	LLAppCoreHttp mAppCoreHttp;
 
-        bool mIsFirstRun;
-	U64 mMinMicroSecPerFrame; // frame throttling
-
-
+    bool mIsFirstRun;
 };
 
 // consts from viewer.h
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 8c6cbc020b7ef7d918540e64bdd13ea4f1cd1e12..2219f202729317542ffb88067528ad23101377aa 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1178,11 +1178,33 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
 	}
 	else if (isRoot())
 	{
-		if (mSpatialBridge && (mSpatialBridge->asPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) != mVObjp->isHUDAttachment())
+		if (mSpatialBridge)
 		{
-			// remove obsolete bridge
-			mSpatialBridge->markDead();
-			setSpatialBridge(NULL);
+			U32 partition_type = mSpatialBridge->asPartition()->mPartitionType;
+			bool is_hud = mVObjp->isHUDAttachment();
+			bool is_animesh = mVObjp->isAnimatedObject() && mVObjp->getControlAvatar() != NULL;
+			bool is_attachment = mVObjp->isAttachment() && !is_hud && !is_animesh;
+			if ((partition_type == LLViewerRegion::PARTITION_HUD) != is_hud)
+			{
+				// Was/became HUD
+				// remove obsolete bridge
+				mSpatialBridge->markDead();
+				setSpatialBridge(NULL);
+			}
+			else if ((partition_type == LLViewerRegion::PARTITION_CONTROL_AV) != is_animesh)
+			{
+				// Was/became part of animesh
+				// remove obsolete bridge
+				mSpatialBridge->markDead();
+				setSpatialBridge(NULL);
+			}
+			else if ((partition_type == LLViewerRegion::PARTITION_AVATAR) != is_attachment)
+			{
+				// Was/became part of avatar
+				// remove obsolete bridge
+				mSpatialBridge->markDead();
+				setSpatialBridge(NULL);
+			}
 		}
 		//must be an active volume
 		if (!mSpatialBridge)
@@ -1191,6 +1213,15 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
 			{
 				setSpatialBridge(new LLHUDBridge(this, getRegion()));
 			}
+			else if (mVObjp->isAnimatedObject() && mVObjp->getControlAvatar())
+			{
+				setSpatialBridge(new LLControlAVBridge(this, getRegion()));
+			}
+			// check HUD first, because HUD is also attachment
+			else if (mVObjp->isAttachment())
+			{
+				setSpatialBridge(new LLAvatarBridge(this, getRegion()));
+			}
 			else
 			{
 				setSpatialBridge(new LLVolumeBridge(this, getRegion()));
@@ -1698,12 +1729,26 @@ void LLDrawable::updateFaceSize(S32 idx)
 LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp)
 : LLSpatialPartition(0, FALSE, 0, regionp) 
 { 
-	mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; 
+	mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; 
 	mPartitionType = LLViewerRegion::PARTITION_BRIDGE;
 	mLODPeriod = 16;
 	mSlopRatio = 0.25f;
 }
 
+LLAvatarPartition::LLAvatarPartition(LLViewerRegion* regionp)
+	: LLBridgePartition(regionp)
+{
+	mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+	mPartitionType = LLViewerRegion::PARTITION_AVATAR;
+}
+
+LLControlAVPartition::LLControlAVPartition(LLViewerRegion* regionp)
+	: LLBridgePartition(regionp)
+{
+	mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV;
+	mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV;
+}
+
 LLHUDBridge::LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
 : LLVolumeBridge(drawablep, regionp)
 {
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 2aee7b450acc116ecc355a6480cff6cedcde43ff..d583a692f9f26d4ca398ae88baeb75f9f9604d83 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -86,7 +86,8 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
 		poolp = new LLDrawPoolAlpha();
 		break;
 	case POOL_AVATAR:
-		poolp = new LLDrawPoolAvatar();
+	case POOL_CONTROL_AV:
+		poolp = new LLDrawPoolAvatar(type);
 		break;
 	case POOL_TREE:
 		poolp = new LLDrawPoolTree(tex0);
@@ -383,16 +384,6 @@ LLRenderPass::~LLRenderPass()
 
 }
 
-LLDrawPool* LLRenderPass::instancePool()
-{
-#if LL_RELEASE_FOR_DOWNLOAD
-	LL_WARNS() << "Attempting to instance a render pass.  Invalid operation." << LL_ENDL;
-#else
-	LL_ERRS() << "Attempting to instance a render pass.  Invalid operation." << LL_ENDL;
-#endif
-	return NULL;
-}
-
 void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
 {					
 	LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
@@ -449,7 +440,7 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
 	if (params.mModelMatrix != gGLLastMatrix)
 	{
 		gGLLastMatrix = params.mModelMatrix;
-        gGL.matrixMode(LLRender::MM_MODELVIEW);
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		gGL.loadMatrix(gGLModelView);
 		if (params.mModelMatrix)
 		{
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index b8562e90773f95cbcb42fa24f8eed37200ed5547..ecd9bd034ff85b84b0e825b185106b4af10c2651 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -60,6 +60,7 @@ class LLDrawPool
 		POOL_GRASS,
 		POOL_INVISIBLE, // see below *
 		POOL_AVATAR,
+		POOL_CONTROL_AV, // Animesh
 		POOL_VOIDWATER,
 		POOL_WATER,
 		POOL_GLOW,
@@ -110,7 +111,6 @@ class LLDrawPool
 	virtual S32 getShaderLevel() const { return mShaderLevel; }
 	
 	static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
-	virtual LLDrawPool *instancePool() = 0;	// Create an empty new instance of the pool.
 	virtual LLViewerTexture* getTexture() = 0;
 	virtual BOOL isFacePool() { return FALSE; }
 	virtual void resetDrawOrders() = 0;
@@ -162,7 +162,6 @@ class LLRenderPass : public LLDrawPool
 
 	LLRenderPass(const U32 type);
 	virtual ~LLRenderPass();
-	/*virtual*/ LLDrawPool* instancePool();
 	/*virtual*/ LLViewerTexture* getDebugTexture() { return NULL; }
 	LLViewerTexture* getTexture() { return NULL; }
 	BOOL isDead() { return FALSE; }
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index f3e922ce8e3241f9dfe7f787d5efc1a6ba3be20e..6fc39f213e1bd6a79d3c9fa76eddfadc352c5249 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -106,8 +106,8 @@ S32 cube_channel = -1;
 
 static LLTrace::BlockTimerStatHandle FTM_SHADOW_AVATAR("Avatar Shadow");
 
-LLDrawPoolAvatar::LLDrawPoolAvatar() : 
-	LLFacePool(POOL_AVATAR)	
+LLDrawPoolAvatar::LLDrawPoolAvatar(U32 type) : 
+	LLFacePool(type)	
 {
 }
 
@@ -136,15 +136,6 @@ BOOL LLDrawPoolAvatar::isDead()
     }
     return TRUE;
 }
- 
-//-----------------------------------------------------------------------------
-// instancePool()
-//-----------------------------------------------------------------------------
-LLDrawPool *LLDrawPoolAvatar::instancePool()
-{
-	return new LLDrawPoolAvatar();
-}
-
 
 S32 LLDrawPoolAvatar::getShaderLevel() const
 {
@@ -1815,7 +1806,7 @@ void LLDrawPoolAvatar::getRiggedGeometry(
 	}
 	else
 	{
-		face->setPoolType(LLDrawPool::POOL_AVATAR);
+		face->setPoolType(mType); // either POOL_AVATAR or POOL_CONTROL_AV
 	}
 
 	//LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL;
@@ -2499,7 +2490,7 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
 void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
 {
     llassert (facep->isState(LLFace::RIGGED));
-    llassert(getType() == LLDrawPool::POOL_AVATAR);
+    llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
     if (facep->getPool() && facep->getPool() != this)
     {
         LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL;
@@ -2521,7 +2512,7 @@ void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
 void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
 {
     llassert (facep->isState(LLFace::RIGGED));
-    llassert(getType() == LLDrawPool::POOL_AVATAR);
+    llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
     if (facep->getPool() != this)
     {
         LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL;
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index cb09eb18e2152bc3ef35b8aee6aa55d1dd21be68..92a85389588cb3a06c02e0bfc6f9ce14d68dba37 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -178,12 +178,10 @@ typedef enum
 
 	virtual S32 getShaderLevel() const;
 
-	LLDrawPoolAvatar();
+	LLDrawPoolAvatar(U32 type);
 
 	static LLMatrix4& getModelView();
 
-	/*virtual*/ LLDrawPool *instancePool();
-
 	/*virtual*/ S32  getNumPasses();
 	/*virtual*/ void beginRenderPass(S32 pass);
 	/*virtual*/ void endRenderPass(S32 pass);
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index 6bd2631d3b2badc315e0a494b3eebe432e20e5ab..5b74264dab4cb2ddca721316f733de27ebe174fb 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -46,11 +46,6 @@ LLDrawPoolGround::LLDrawPoolGround() :
 {
 }
 
-LLDrawPool *LLDrawPoolGround::instancePool()
-{
-	return new LLDrawPoolGround();
-}
-
 void LLDrawPoolGround::prerender()
 {
 	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
diff --git a/indra/newview/lldrawpoolground.h b/indra/newview/lldrawpoolground.h
index a4f8a3fcf50e343bba2dff7b85a0fc3c806cc243..15b1dc60a29f5f4b751a722264e75d4817f05047 100644
--- a/indra/newview/lldrawpoolground.h
+++ b/indra/newview/lldrawpoolground.h
@@ -43,8 +43,6 @@ class LLDrawPoolGround : public LLFacePool
 
 	LLDrawPoolGround();
 
-	/*virtual*/ LLDrawPool *instancePool();
-
 	/*virtual*/ void prerender();
 	/*virtual*/ void render(S32 pass = 0);
 };
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index dbe8724088716f844bd60a368dba81c721891239..b6f55e800afe8b21b57723351754763028bb2cd4 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -48,11 +48,6 @@ LLDrawPoolSky::LLDrawPoolSky()
 {
 }
 
-LLDrawPool *LLDrawPoolSky::instancePool()
-{
-	return new LLDrawPoolSky();
-}
-
 void LLDrawPoolSky::prerender()
 {
 	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); 
@@ -128,23 +123,12 @@ void LLDrawPoolSky::renderSkyFace(U8 index)
 		return;
 	}
 
-    F32 interp_val = gSky.mVOSkyp ? gSky.mVOSkyp->getInterpVal() : 0.0f;
-
     if (index < 6) // sky tex...interp
     {
         llassert(mSkyTex);
 	    mSkyTex[index].bindTexture(true); // bind the current tex
 
         face->renderIndexed();
-
-        if (interp_val > 0.01f) // iff, we've got enough info to lerp (a to and a from)
-	    {
-		    LLGLEnable blend(GL_BLEND);
-            llassert(mSkyTex);
-	        mSkyTex[index].bindTexture(false); // bind the "other" texture
-		    gGL.diffuseColor4f(1, 1, 1, interp_val); // lighting is disabled
-		    face->renderIndexed();
-	    }
     }
     else // heavenly body faces, no interp...
     {
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index 916d8c1cbe7243892900a4db5dcf6b59cf058537..d1dcd6b22ee5258d67aff3e503d795f34df96f89 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -49,8 +49,6 @@ class LLDrawPoolSky : public LLFacePool
 
 	LLDrawPoolSky();
 
-	/*virtual*/ LLDrawPool *instancePool();
-
 	/*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); }
 	/*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); }
 	/*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); }
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 33a11631fef9662b2487697c977ad8483f870ba0..37dc80e2b7d95e9e05c577eae0e94a78ee5d2b28 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -87,13 +87,6 @@ LLDrawPoolTerrain::~LLDrawPoolTerrain()
 	llassert( gPipeline.findPool( getType(), getTexture() ) == NULL );
 }
 
-
-LLDrawPool *LLDrawPoolTerrain::instancePool()
-{
-	return new LLDrawPoolTerrain(mTexturep);
-}
-
-
 U32 LLDrawPoolTerrain::getVertexDataMask() 
 { 
 	if (LLPipeline::sShadowRender)
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 04e27d9370ed4dd05309450a0e8a5eceebb441f0..5b4558020d6b9d63be94b9da99e9a8560dcb7c08 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -49,8 +49,6 @@ class LLDrawPoolTerrain : public LLFacePool
 	LLDrawPoolTerrain(LLViewerTexture *texturep);
 	virtual ~LLDrawPoolTerrain();
 
-	/*virtual*/ LLDrawPool *instancePool();
-
 	/*virtual*/ S32 getNumDeferredPasses() { return 1; }
 	/*virtual*/ void beginDeferredPass(S32 pass);
 	/*virtual*/ void endDeferredPass(S32 pass);
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index b885008caeade02b3eca3ab7f8e664971c8890e3..0d5195bdbfcd67211519270c39e3d029658905ed 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -51,11 +51,6 @@ LLDrawPoolTree::LLDrawPoolTree(LLViewerTexture *texturep) :
 	mTexturep->setAddressMode(LLTexUnit::TAM_WRAP);
 }
 
-LLDrawPool *LLDrawPoolTree::instancePool()
-{
-	return new LLDrawPoolTree(mTexturep);
-}
-
 void LLDrawPoolTree::prerender()
 {
 	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index 9c1e60f5ebb990a8fc8310cf0569e1230c6a997d..13f9ec8dcef699f5a6ee4e8e469fd2e440f4979f 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -45,8 +45,6 @@ class LLDrawPoolTree : public LLFacePool
 
 	LLDrawPoolTree(LLViewerTexture *texturep);
 
-	/*virtual*/ LLDrawPool *instancePool();
-
 	/*virtual*/ void prerender();
 
 	/*virtual*/ S32 getNumDeferredPasses() { return 1; }
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 073adfb627ae16cc3e7d73f60d8f33fce330a29c..7249f22555ee7c69807abc47de4219270663fa37 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -104,13 +104,6 @@ void LLDrawPoolWater::restoreGL()
     }*/
 }
 
-LLDrawPool *LLDrawPoolWater::instancePool()
-{
-	LL_ERRS() << "Should never be calling instancePool on a water pool!" << LL_ENDL;
-	return NULL;
-}
-
-
 void LLDrawPoolWater::prerender()
 {
 	mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index d436557e1cb070f43ceb23598c23b874864a7add..a5d163e0d716d289ffbab6c3d8bd130763559c17 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -61,7 +61,6 @@ class LLDrawPoolWater: public LLFacePool
 	LLDrawPoolWater();
 	/*virtual*/ ~LLDrawPoolWater();
 
-	/*virtual*/ LLDrawPool *instancePool();
 	static void restoreGL();
 	
 	/*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 961d72c62eb7bc18b3680ba43fb4a75b84726654..d4e7f1600e7637b025c41ab05fe94f0ddbfd2934 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -216,10 +216,11 @@ void LLDrawPoolWLSky::renderSkyHaze(const LLVector3& camPosLocal, F32 camHeightL
 
 	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
 	{
+        LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
         LLGLSPipelineDepthTestSkyBox sky(true, false);
         sky_shader->bind();
         sky_shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, 1);
-        sky_shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, 1.0f);
+        sky_shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor());
         renderDome(origin, camHeightLocal, sky_shader);	
 		sky_shader->unbind();
     }
@@ -531,8 +532,6 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
         }
 	}
 
-    blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor();
-
 	face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON];
 
 	if (gSky.mVOSkyp->getMoon().getDraw() && face && face->getTexture(LLRender::DIFFUSE_MAP) && face->getGeomCount() && moon_shader)
@@ -550,17 +549,17 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
             {
                 // Bind current and next sun textures
                 moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
-                blend_factor = 0;
+                //blend_factor = 0;
             }
             else if (tex_b && !tex_a)
             {
                 moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
-                blend_factor = 0;
+                //blend_factor = 0;
             }
             else if (tex_b != tex_a)
             {
                 moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
-                moon_shader->bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
+                //moon_shader->bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
             }
 
             LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
@@ -570,7 +569,8 @@ void LLDrawPoolWLSky::renderHeavenlyBodies()
             moon_shader->uniform1f(LLShaderMgr::MOON_BRIGHTNESS, moon_brightness);
             moon_shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, gSky.mVOSkyp->getMoon().getColor().mV);
             moon_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV);
-            moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+            //moon_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+            moon_shader->uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, psky->getMoonDirection().mV); // shader: moon_dir
 
             face->renderIndexed();
 
@@ -632,11 +632,6 @@ void LLDrawPoolWLSky::prerender()
 	//LL_INFOS() << "wlsky prerendering pass." << LL_ENDL;
 }
 
-LLDrawPoolWLSky *LLDrawPoolWLSky::instancePool()
-{
-	return new LLDrawPoolWLSky();
-}
-
 LLViewerTexture* LLDrawPoolWLSky::getTexture()
 {
 	return NULL;
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index 3acfda4eee55508f3779a5aa65e96a6300ffd3bf..a4f176d6db7f3247e3bbeef48c355096c5683111 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -62,8 +62,6 @@ class LLDrawPoolWLSky : public LLDrawPool {
 	
 	//static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
 
-	// Create an empty new instance of the pool.
-	/*virtual*/ LLDrawPoolWLSky *instancePool();  ///< covariant override
 	/*virtual*/ LLViewerTexture* getTexture();
 	/*virtual*/ BOOL isFacePool() { return FALSE; }
 	/*virtual*/ void resetDrawOrders();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 36832d85fdf3d41c9602fd954fe21526ae28a3e7..4a802ad9aa774462f5faa92d06c1f9dd7cc6567d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -196,7 +196,7 @@ void LLFace::destroy()
 
 	if (mDrawPoolp)
 	{
-		if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR)
+		if (this->isState(LLFace::RIGGED) && (mDrawPoolp->getType() == LLDrawPool::POOL_CONTROL_AV || mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR))
 		{
 			((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);
 		}
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index bd834b4260005c554f572cc97fcf592b7275e7e4..82ce97f311f2c027edfa29c1ae829a1f6b5a8f52 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -57,6 +57,9 @@
 #include "llviewerobjectlist.h"
 #include "boost/foreach.hpp"
 
+
+const S32 EVENTS_PER_IDLE_LOOP = 100;
+
 //
 // LLFloaterIMContainer
 //
@@ -66,7 +69,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
 	mConversationsRoot(NULL),
 	mConversationsEventStream("ConversationsEvents"),
 	mInitialized(false),
-	mIsFirstLaunch(true)
+	mIsFirstLaunch(true),
+	mConversationEventQueue()
 {
     mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
 	mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction,  this, _2));
@@ -424,7 +428,9 @@ void LLFloaterIMContainer::idle(void* user_data)
 {
 	LLFloaterIMContainer* self = static_cast<LLFloaterIMContainer*>(user_data);
 
-    if (!self->getVisible() || self->isMinimized())
+	self->idleProcessEvents();
+
+	if (!self->getVisible() || self->isMinimized())
     {
         return;
     }
@@ -485,13 +491,28 @@ void LLFloaterIMContainer::idleUpdate()
     }
 }
 
+void LLFloaterIMContainer::idleProcessEvents()
+{
+	if (!mConversationEventQueue.empty())
+	{
+		S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP);
+		for (S32 i = 0; i < events_to_handle; i++)
+		{
+			handleConversationModelEvent(mConversationEventQueue.back());
+			mConversationEventQueue.pop_back();
+		}
+	}
+}
+
 bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 {
-	// For debug only
-	//std::ostringstream llsd_value;
-	//llsd_value << LLSDOStreamer<LLSDNotationFormatter>(event) << std::endl;
-	//LL_INFOS() << "LLFloaterIMContainer::onConversationModelEvent, event = " << llsd_value.str() << LL_ENDL;
-	// end debug
+	mConversationEventQueue.push_front(event);
+	return true;
+}
+
+
+void LLFloaterIMContainer::handleConversationModelEvent(const LLSD& event)
+{
 	
 	// Note: In conversations, the model is not responsible for creating the view, which is a good thing. This means that
 	// the model could change substantially and the view could echo only a portion of this model (though currently the 
@@ -508,7 +529,7 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 	if (!session_view)
 	{
 		// We skip events that are not associated with a session
-		return false;
+		return;
 	}
 	LLConversationViewParticipant* participant_view = session_view->findParticipant(participant_id);
     LLFloaterIMSessionTab *conversation_floater = (session_id.isNull() ?
@@ -535,9 +556,9 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 	{
 		LLConversationItemSession* session_model = dynamic_cast<LLConversationItemSession*>(mConversationsItems[session_id]);
 		LLConversationItemParticipant* participant_model = (session_model ? session_model->findParticipant(participant_id) : NULL);
+		LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
 		if (!participant_view && session_model && participant_model)
-		{
-			LLIMModel::LLIMSession * im_sessionp = LLIMModel::getInstance()->findIMSession(session_id);
+		{	
 			if (session_id.isNull() || (im_sessionp && !im_sessionp->isP2PSessionType()))
 			{
 				participant_view = createConversationViewParticipant(participant_model);
@@ -548,7 +569,8 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 		// Add a participant view to the conversation floater 
 		if (conversation_floater && participant_model)
 		{
-			conversation_floater->addConversationViewParticipant(participant_model);
+			bool skip_updating = im_sessionp && im_sessionp->isGroupChat();
+			conversation_floater->addConversationViewParticipant(participant_model, !skip_updating);
 		}
 	}
 	else if (type == "update_participant")
@@ -571,12 +593,6 @@ bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 	
 	mConversationViewModel.requestSortAll();
 	mConversationsRoot->arrangeAll();
-	if (conversation_floater)
-	{
-		conversation_floater->refreshConversation();
-	}
-	
-	return false;
 }
 
 void LLFloaterIMContainer::draw()
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 0f7d0a557e474dcce030f9c2ca2b2b0412bbcf85..468b47f1f1b457037b013c1f3a9da46975ff5f8f 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -181,6 +181,7 @@ class LLFloaterIMContainer
 	bool isParticipantListExpanded();
 
 	void idleUpdate(); // for convenience (self) from static idle
+	void idleProcessEvents();
 
 	LLButton* mExpandCollapseBtn;
 	LLButton* mStubCollapseBtn;
@@ -220,6 +221,7 @@ class LLFloaterIMContainer
 	LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
 	LLConversationViewParticipant* createConversationViewParticipant(LLConversationItem* item);
 	bool onConversationModelEvent(const LLSD& event);
+	void handleConversationModelEvent(const LLSD& event);
 
 	// Conversation list data
 	LLPanel* mConversationsListPanel;	// This is the main widget we add conversation widget to
@@ -229,6 +231,8 @@ class LLFloaterIMContainer
 	LLFolderView* mConversationsRoot;
 	LLEventStream mConversationsEventStream; 
 
+	std::deque<LLSD> mConversationEventQueue;
+
 	LLTimer mParticipantRefreshTimer;
 };
 
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 3aee08482b95cf82383d2b9e3145cd5fdfa1ec7b..d604d0a789f66804b2cd48fb4c02e711b1efa554 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -465,9 +465,10 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD &args)
 	}
 }
 
-
+static LLTrace::BlockTimerStatHandle FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT("Build Conversation View");
 void LLFloaterIMSessionTab::buildConversationViewParticipant()
 {
+	LL_RECORD_BLOCK_TIME(FTM_BUILD_CONVERSATION_VIEW_PARTICIPANT);
 	// Clear the widget list since we are rebuilding afresh from the model
 	conversations_widgets_map::iterator widget_it = mConversationsWidgets.begin();
 	while (widget_it != mConversationsWidgets.end())
@@ -496,14 +497,20 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
 	}
 }
 
-void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model)
+void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* participant_model, bool update_view)
 {
+	if (!participant_model)
+	{
+		// Nothing to do if the model is inexistent
+		return;
+	}
+
 	// Check if the model already has an associated view
 	LLUUID uuid = participant_model->getUUID();
 	LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
 	
 	// If not already present, create the participant view and attach it to the root, otherwise, just refresh it
-	if (widget)
+	if (widget && update_view)
 	{
 		updateConversationViewParticipant(uuid); // overkill?
 	}
@@ -524,8 +531,8 @@ void LLFloaterIMSessionTab::removeConversationViewParticipant(const LLUUID& part
 	{
 		mConversationsRoot->extractItem(widget);
 		delete widget;
-		mConversationsWidgets.erase(participant_id);
 	}
+	mConversationsWidgets.erase(participant_id);
 }
 
 void LLFloaterIMSessionTab::updateConversationViewParticipant(const LLUUID& participant_id)
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 1b4922fd73105e715dfcb58d0b8b1665d0fe1929..5357a14ab9aee12b169eb40f26d7c96ce5b43d55 100644
--- a/indra/newview/llfloaterimsessiontab.h
+++ b/indra/newview/llfloaterimsessiontab.h
@@ -84,7 +84,7 @@ class LLFloaterIMSessionTab
 	/*virtual*/ void setFocus(BOOL focus);
 	
 	// Handle the left hand participant list widgets
-	void addConversationViewParticipant(LLConversationItem* item);
+	void addConversationViewParticipant(LLConversationItem* item, bool update_view = true);
 	void removeConversationViewParticipant(const LLUUID& participant_id);
 	void updateConversationViewParticipant(const LLUUID& participant_id);
 	void refreshConversation();
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index d96014bd729ad04acc1783dc80522939c37b26ae..32f88b49ac9595d2fbe335b3145f4f6c8cef7eac 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -944,9 +944,13 @@ static void formatDateString(std::string &date_string)
 	}
 }
 
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_MEMBERS_REPLY("Process Group Members");
+
 // static
 void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
 {
+    LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_MEMBERS_REPLY);
+
 	LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupMembersReply" << LL_ENDL;
 	LLUUID agent_id;
 	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
@@ -1050,9 +1054,13 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)
 	LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
 }
 
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_PROPERTIES_REPLY("Process Group Properties");
+
 //static 
 void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
 {
+    LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_PROPERTIES_REPLY);
+
 	LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupPropertiesReply" << LL_ENDL;
 	if (!msg)
 	{
@@ -1131,10 +1139,13 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)
 	LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES);
 }
 
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_DATA_REPLY("Process Group Role Data");
 // static
 void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
 {
-    LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleDataReply" << LL_ENDL;
+    LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_DATA_REPLY);
+
+	LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleDataReply" << LL_ENDL;
 	LLUUID agent_id;
 	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
 	if (gAgent.getID() != agent_id)
@@ -1216,9 +1227,12 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)
 	LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_DATA);
 }
 
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY("Process Group Role Members");
 // static
 void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
 {
+    LL_RECORD_BLOCK_TIME(FTM_PROCESS_GROUP_ROLE_MEMBERS_REPLY);
+
 	LL_DEBUGS("GrpMgr") << "LLGroupMgr::processGroupRoleMembersReply" << LL_ENDL;
 	LLUUID agent_id;
 	msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
@@ -1600,7 +1614,7 @@ void LLGroupMgr::sendGroupPropertiesRequest(const LLUUID& group_id)
 	LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupPropertiesRequest" << LL_ENDL;
 	// This will happen when we get the reply
 	//LLGroupMgrGroupData* group_datap = createGroupData(group_id);
-
+	
     if (LLGroupMgr::getInstance()->hasPendingPropertyRequest(group_id))
     {
         LL_DEBUGS("GrpMgr") << "LLGroupMgr::sendGroupPropertiesRequest suppressed repeat for " << group_id << LL_ENDL;
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index dff084e6cad7f8623573f6b4e4e40b4e5a906967..e03533c0293353d39b32d9fe06823258b9af30e8 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -1038,21 +1038,7 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
 					getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
 					getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
 
-					bool allAttachments = true;
-					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
-						iter != LLSelectMgr::getInstance()->getSelection()->end();iter++)
-					{
-						LLSelectNode* node = *iter;
-						LLViewerObject* object = node->getObject();
-						if (!object->isAttachment())
-						{
-							allAttachments = false;
-							break;
-						}
-					}
-
-					texture_ctrl->setBakeTextureEnabled(allAttachments);
-					
+					texture_ctrl->setBakeTextureEnabled(TRUE);
 				}
 				else if (id.isNull())
 					{
@@ -1077,21 +1063,8 @@ void LLPanelFace::updateUI(bool force_set_values /*false*/)
 					getChildView("label alphamode")->setEnabled(editable && mIsAlpha);
 					getChildView("maskcutoff")->setEnabled(editable && mIsAlpha);
 					getChildView("label maskcutoff")->setEnabled(editable && mIsAlpha);
-
-					bool allAttachments = true;
-					for (LLObjectSelection::iterator iter = LLSelectMgr::getInstance()->getSelection()->begin();
-						iter != LLSelectMgr::getInstance()->getSelection()->end();iter++)
-					{
-						LLSelectNode* node = *iter;
-						LLViewerObject* object = node->getObject();
-						if (!object->isAttachment())
-						{
-							allAttachments = false;
-							break;
-				}
-			}
-
-					texture_ctrl->setBakeTextureEnabled(allAttachments);
+					
+					texture_ctrl->setBakeTextureEnabled(TRUE);
 				}
 				
 			}
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 97b5b2a57dc57ef1e48b5990cc009900d6f751e7..1e5b893cbc8e5c218d54284aef9e5dcc7c78b50e 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -678,8 +678,17 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
 	{
     shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);        
 
+    // Legacy? SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate")
     LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]);
-    vect_c_p_d1 += LLVector4(LLEnvironment::instance().getCloudScrollDelta());
+    LLVector4 cloud_scroll( LLEnvironment::instance().getCloudScrollDelta() );
+
+    // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
+    // Keep in Sync!
+    // * indra\newview\llsettingsvo.cpp
+    // * indra\newview\app_settings\shaders\class2\windlight\cloudsV.glsl
+    // * indra\newview\app_settings\shaders\class1\deferred\cloudsV.glsl
+    cloud_scroll[0] = -cloud_scroll[0];
+    vect_c_p_d1 += cloud_scroll;
     shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV);
 
     LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2cdba4d9ba52232c15955730be213a2c8a3c0bd4..afb25778aa257db495b7f5c0e9b104b52cfab674 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -556,7 +556,9 @@ void LLSpatialGroup::shift(const LLVector4a &offset)
 	if (!getSpatialPartition()->mRenderByGroup && 
 		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE &&
 		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN &&
-		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE)
+		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE &&
+		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_AVATAR &&
+		getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_CONTROL_AV)
 	{
 		setState(GEOM_DIRTY);
 		gPipeline.markRebuild(this, TRUE);
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 7e65da42f7e471d9760d6920529d254b8834d676..919f386d29b5095dd3fa1f4a34ffc8301a138e07 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -685,6 +685,18 @@ class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager
 	virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); }
 };
 
+class LLAvatarBridge : public LLVolumeBridge
+{
+public:
+	LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
+};
+
+class LLControlAVBridge : public LLVolumeBridge
+{
+public:
+	LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp);
+};
+
 class LLHUDBridge : public LLVolumeBridge
 {
 public:
@@ -702,6 +714,18 @@ class LLBridgePartition : public LLSpatialPartition
 	virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) {  }
 };
 
+class LLAvatarPartition : public LLBridgePartition
+{
+public:
+	LLAvatarPartition(LLViewerRegion* regionp);
+};
+
+class LLControlAVPartition : public LLBridgePartition
+{
+public:
+	LLControlAVPartition(LLViewerRegion* regionp);
+};
+
 class LLHUDPartition : public LLBridgePartition
 {
 public:
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index cd37cf284734dc18fb3fbae29d636df1d6c09437..cd6f48b7e4843f5ce8d8b572fc2b62f415293f58 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -485,7 +485,7 @@ BOOL LLFloaterTexturePicker::postBuild()
 	getChild<LLComboBox>("l_bake_use_texture_combo_box")->setCommitCallback(onBakeTextureSelect, this);
 	getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setCommitCallback(onHideBaseMeshRegionCheck, this);
 
-	setBakeTextureEnabled(FALSE);
+	setBakeTextureEnabled(TRUE);
 	return TRUE;
 }
 
@@ -1210,8 +1210,7 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)
 	mImageAssetID(p.image_id),
 	mDefaultImageAssetID(p.default_image_id),
 	mDefaultImageName(p.default_image_name),
-	mFallbackImage(p.fallback_image),
-	mBakeTextureEnabled(FALSE)
+	mFallbackImage(p.fallback_image)
 {
 
 	// Default of defaults is white image for diff tex
@@ -1404,7 +1403,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus)
 		}
 		if (texture_floaterp)
 		{
-			texture_floaterp->setBakeTextureEnabled(mBakeTextureEnabled);
+			texture_floaterp->setBakeTextureEnabled(TRUE);
 		}
 
 		LLFloater* root_floater = gFloaterView->getParentFloater(this);
@@ -1583,7 +1582,6 @@ void LLTextureCtrl::setImageAssetID( const LLUUID& asset_id )
 
 void LLTextureCtrl::setBakeTextureEnabled(BOOL enabled)
 {
-	mBakeTextureEnabled = enabled;
 	LLFloaterTexturePicker* floaterp = (LLFloaterTexturePicker*)mFloaterHandle.get();
 	if (floaterp)
 	{
diff --git a/indra/newview/lltexturectrl.h b/indra/newview/lltexturectrl.h
index d86c06f686064c483f7e28cdb1f4ada0fb847009..4250cf86b80cbbc7ad6665dfedf03ca3e9547ee3 100644
--- a/indra/newview/lltexturectrl.h
+++ b/indra/newview/lltexturectrl.h
@@ -248,7 +248,6 @@ class LLTextureCtrl
 	BOOL					 	mShowLoadingPlaceholder;
 	std::string				 	mLoadingPlaceholderString;
 	S32						 	mLabelWidth;
-	BOOL						mBakeTextureEnabled;
 };
 
 //////////////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 0d2edc0268e2be3382e1869830523b2f7574b5c4..1c4187d30f0c8b6d1aec2b78dec95027535c3221 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -549,7 +549,7 @@ void LLGLTexMemBar::draw()
     U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
     U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
 
-	text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
+	text = llformat("GL Tot: %d/%d MB Bound: %4d/%4d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
 					total_mem.value(),
 					max_total_mem.value(),
 					bound_mem.value(),
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 12346f16d7be3a81cc0a89d55202c42ff5b225c6..864ce09430ab0f3eba5ad1b06f5ab1f2385ea3a3 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -671,7 +671,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
 	else
 	{
 		// perform a separate pick that detects transparent objects since they respond to 1-click actions
-		LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, TRUE, pick_rigged);
+		LLPickInfo click_action_pick = gViewerWindow->pickImmediate(x, y, FALSE, pick_rigged);
 
 		LLViewerObject* click_action_object = click_action_pick.getObject();
 
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index f025863072df5c4f058f529b9f51c7284beeb96a..caf79edfe4ac12c73b93617344806c2358d4c300 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -710,9 +710,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		LLGLState::checkTextureChannels();
 		LLGLState::checkClientArrays();
 
-		BOOL to_texture = gPipeline.canUseVertexShaders() &&
-						LLPipeline::sRenderGlow;
-
 		LLAppViewer::instance()->pingMainloopTimeout("Display:Swap");
 		
 		{ 
@@ -919,31 +916,28 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 
 		stop_glerror();
 
-		if (to_texture)
-		{
-			gGL.setColorMask(true, true);
-					
-			if (LLPipeline::sRenderDeferred)
-			{
-				gPipeline.mDeferredScreen.bindTarget();
-				glClearColor(1,0,1,1);
-				gPipeline.mDeferredScreen.clear();
-			}
-			else
-			{
-				gPipeline.mScreen.bindTarget();
-				if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
-				{
-					const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
-					glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-				}
-				gPipeline.mScreen.clear();
-			}
-			
-			gGL.setColorMask(true, false);
-		}
-		
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
+        gGL.setColorMask(true, true);
+
+        if (LLPipeline::sRenderDeferred)
+        {
+            gPipeline.mDeferredScreen.bindTarget();
+            glClearColor(1, 0, 1, 1);
+            gPipeline.mDeferredScreen.clear();
+        }
+        else
+        {
+            gPipeline.mScreen.bindTarget();
+            if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
+            {
+                const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
+                glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+            }
+            gPipeline.mScreen.clear();
+        }
+
+        gGL.setColorMask(true, false);
+
+        LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");
 		
 		if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
 				&& !gRestoreGL)
@@ -1005,38 +999,20 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 			}
 		}
 
-		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");		
-		
-		if (to_texture)
-		{
-			if (LLPipeline::sRenderDeferred)
-			{
-				gPipeline.mDeferredScreen.flush();
-				if(LLRenderTarget::sUseFBO)
-				{
-					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
-															  gPipeline.mDeferredScreen.getHeight(), 0, 0, 
-															  gPipeline.mDeferredScreen.getWidth(), 
-															  gPipeline.mDeferredScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-				}
-			}
-			else
-			{
-				gPipeline.mScreen.flush();
-				if(LLRenderTarget::sUseFBO)
-				{				
-					LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(), 
-															  gPipeline.mScreen.getHeight(), 0, 0, 
-															  gPipeline.mScreen.getWidth(), 
-															  gPipeline.mScreen.getHeight(), 
-															  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-				}
-			}
-		}
+		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush");
 
-		if (LLPipeline::sRenderDeferred)
-		{
+        LLRenderTarget &rt = (gPipeline.sRenderDeferred ? gPipeline.mDeferredScreen : gPipeline.mScreen);
+        rt.flush();
+
+        if (rt.sUseFBO)
+        {
+            LLRenderTarget::copyContentsToFramebuffer(rt, 0, 0, rt.getWidth(), rt.getHeight(), 0, 0, rt.getWidth(),
+                                                      rt.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
+                                                      GL_NEAREST);
+        }
+
+        if (LLPipeline::sRenderDeferred)
+        {
 			gPipeline.renderDeferredLighting(&gPipeline.mScreen);
 		}
 
@@ -1300,19 +1276,12 @@ void render_ui(F32 zoom_factor, int subfield)
 		gGL.popMatrix();
 	}
 
-	{
-		BOOL to_texture = gPipeline.canUseVertexShaders() &&
-							LLPipeline::sRenderGlow;
+    // Finalize scene
+    gPipeline.renderFinalize();
 
-		if (to_texture)
-		{
-			gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
-		}
-		
-		LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
-		render_hud_elements();
-		render_hud_attachments();
-	}
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
+    render_hud_elements();
+	render_hud_attachments();
 
 	LLGLSDefault gls_default;
 	LLGLSUIDefault gls_ui;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b6c7be2ed3550d403fc6af79fbd7111c3b824400..e6bd20b58fe73350babcb6916f0e70a76dab9ddb 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -740,6 +740,10 @@ U32 render_type_from_string(std::string render_type)
 	{
 		return LLPipeline::RENDER_TYPE_AVATAR;
 	}
+	else if ("controlAV" == render_type) // Animesh
+	{
+		return LLPipeline::RENDER_TYPE_CONTROL_AV;
+	}
 	else if ("surfacePatch" == render_type)
 	{
 		return LLPipeline::RENDER_TYPE_TERRAIN;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 06a8ebbe895ada2063220ee40ffe6faba973e4b2..ea9dba3c4eb23ed46139ddc6c6f4a1d62be6bdb5 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -2220,8 +2220,12 @@ class LLPostponedServerObjectNotification: public LLPostponedNotification
 	}
 };
 
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_IMPROVED_IM("Process IM");
+
 void process_improved_im(LLMessageSystem *msg, void **user_data)
 {
+    LL_RECORD_BLOCK_TIME(FTM_PROCESS_IMPROVED_IM);
+
     LLUUID from_id;
     BOOL from_group;
     LLUUID to_id;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 9c91cde09a22468964e811104d8d1b6188e096b7..aa775b2babb19abe34726ebe625239b3ea963006 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -284,6 +284,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mOnActiveList(FALSE),
 	mOnMap(FALSE),
 	mStatic(FALSE),
+	mSeatCount(0),
 	mNumFaces(0),
 	mRotTime(0.f),
 	mAngularVelocityRot(),
@@ -895,7 +896,12 @@ void LLViewerObject::addChild(LLViewerObject *childp)
 	if(childp->setParent(this))
 	{
 		mChildList.push_back(childp);
-        childp->afterReparent();
+		childp->afterReparent();
+
+		if (childp->isAvatar())
+		{
+			mSeatCount++;
+		}
 	}
 }
 
@@ -924,6 +930,11 @@ void LLViewerObject::removeChild(LLViewerObject *childp)
 			{
 				childp->setParent(NULL);			
 			}
+
+			if (childp->isAvatar())
+			{
+				mSeatCount--;
+			}
 			break;
 		}
 	}
@@ -981,21 +992,10 @@ BOOL LLViewerObject::isChild(LLViewerObject *childp) const
 	return FALSE;
 }
 
-
 // returns TRUE if at least one avatar is sitting on this object
 BOOL LLViewerObject::isSeat() const
 {
-	for (child_list_t::const_iterator iter = mChildList.begin();
-		 iter != mChildList.end(); iter++)
-	{
-		LLViewerObject* child = *iter;
-		if (child->isAvatar())
-		{
-			return TRUE;
-		}
-	}
-	return FALSE;
-
+	return mSeatCount > 0;
 }
 
 BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 03c5403a1e596ae3cb016006d4edf0143f755897..12a9b47307ee5bc307cb715c9c97ea69c69e9b78 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -832,6 +832,7 @@ class LLViewerObject
 	BOOL			mOnActiveList;
 	BOOL			mOnMap;						// On the map.
 	BOOL			mStatic;					// Object doesn't move.
+	S32				mSeatCount;
 	S32				mNumFaces;
 
 	F32				mRotTime;					// Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b9cf4b07dcd69ad979ffc5706f859e506ffc4433..a30c5156fab60b0bedaf46652c5bda7ad265ba94 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -102,6 +102,7 @@ const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
 BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE;
 S32  LLViewerRegion::sLastCameraUpdated = 0;
 S32  LLViewerRegion::sNewObjectCreationThrottle = -1;
+LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
@@ -624,6 +625,8 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,
 	mImpl->mObjectPartition.push_back(new LLGrassPartition(this));		//PARTITION_GRASS
 	mImpl->mObjectPartition.push_back(new LLVolumePartition(this));	//PARTITION_VOLUME
 	mImpl->mObjectPartition.push_back(new LLBridgePartition(this));	//PARTITION_BRIDGE
+	mImpl->mObjectPartition.push_back(new LLAvatarPartition(this));	//PARTITION_AVATAR
+	mImpl->mObjectPartition.push_back(new LLControlAVPartition(this));	//PARTITION_CONTROL_AV
 	mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE
 	mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE
 	mImpl->mObjectPartition.push_back(NULL);					//PARTITION_NONE
@@ -648,6 +651,9 @@ void LLViewerRegion::initStats()
 	mAlive = false;					// can become false if circuit disconnects
 }
 
+static LLTrace::BlockTimerStatHandle FTM_CLEANUP_REGION_OBJECTS("Cleanup Region Objects");
+static LLTrace::BlockTimerStatHandle FTM_SAVE_REGION_CACHE("Save Region Cache");
+
 LLViewerRegion::~LLViewerRegion() 
 {
 	mDead = TRUE;
@@ -662,7 +668,10 @@ LLViewerRegion::~LLViewerRegion()
 	disconnectAllNeighbors();
 	LLViewerPartSim::getInstance()->cleanupRegion(this);
 
-	gObjectList.killObjects(this);
+    {
+        LL_RECORD_BLOCK_TIME(FTM_CLEANUP_REGION_OBJECTS);
+        gObjectList.killObjects(this);
+    }
 
 	delete mImpl->mCompositionp;
 	delete mParcelOverlay;
@@ -673,7 +682,10 @@ LLViewerRegion::~LLViewerRegion()
 #endif	
 	std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
 
-	saveObjectCache();
+    {
+        LL_RECORD_BLOCK_TIME(FTM_SAVE_REGION_CACHE);
+        saveObjectCache();
+    }
 
 	delete mImpl;
 	mImpl = NULL;
@@ -742,6 +754,8 @@ void LLViewerRegion::saveObjectCache()
 		mCacheDirty = FALSE;
 	}
 
+	// Map of LLVOCacheEntry takes time to release, store map for cleanup on idle
+	sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end());
 	mImpl->mCacheMap.clear();
 }
 
@@ -1503,6 +1517,16 @@ void LLViewerRegion::idleUpdate(F32 max_update_time)
 	return;
 }
 
+// static
+void LLViewerRegion::idleCleanup(F32 max_update_time)
+{
+    LLTimer update_timer;
+    while (!sRegionCacheCleanup.empty() && (max_update_time - update_timer.getElapsedTimeF32() > 0))
+    {
+        sRegionCacheCleanup.erase(sRegionCacheCleanup.begin());
+    }
+}
+
 //update the throttling number for new object creation
 void LLViewerRegion::calcNewObjectCreationThrottle()
 {
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 1b226ac2c69e2e0b0aab63a14675945f37202618..477aabb971f5d82d938c6784546300e6ffc51756 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -86,6 +86,8 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 		PARTITION_GRASS,
 		PARTITION_VOLUME,
 		PARTITION_BRIDGE,
+		PARTITION_AVATAR,
+		PARTITION_CONTROL_AV, // Animesh
 		PARTITION_HUD_PARTICLE,
 		PARTITION_VO_CACHE,
 		PARTITION_NONE,
@@ -230,6 +232,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	F32	getWidth() const						{ return mWidth; }
 
+	// regions are expensive to release, this function gradually releases cache from memory
+	static void idleCleanup(F32 max_update_time);
+
 	void idleUpdate(F32 max_update_time);
 	void lightIdleUpdate();
 	bool addVisibleGroup(LLViewerOctreeGroup* group);
@@ -548,6 +553,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	LLSD mSimulatorFeatures;
 
+    typedef std::map<U32, LLPointer<LLVOCacheEntry> >	   vocache_entry_map_t;
+    static vocache_entry_map_t sRegionCacheCleanup;
+
 	// the materials capability throttle
 	LLFrameTimer mMaterialsCapThrottleTimer;
 	LLFrameTimer mRenderInfoRequestTimer;
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 786d4aacb773ad3ff7a3c23b946411113b4ffc62..10f51f78965d80d538ffcb4436d84efd4abf6975 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2457,7 +2457,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
 		return;
 	}	
 
-	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))
+	if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))
 		&& !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf())
 	{
 		return;
@@ -2587,8 +2587,8 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time)
     if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0)
     {
         LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE_COMPLEXITY);
-        idleUpdateRenderComplexity();
-    }
+	idleUpdateRenderComplexity();
+}
     idleUpdateDebugInfo();
 }
 
@@ -4425,8 +4425,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)
 
     if (visible)
     {
-        // System avatar mesh vertices need to be reskinned.
-        mNeedsSkin = TRUE;
+	// System avatar mesh vertices need to be reskinned.
+	mNeedsSkin = TRUE;
     }
 
 	return visible;
@@ -6884,13 +6884,13 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline)
 	pipeline->allocDrawable(this);
 	mDrawable->setLit(FALSE);
 
-	LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR);
+	LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*)gPipeline.getPool(mIsControlAvatar ? LLDrawPool::POOL_CONTROL_AV : LLDrawPool::POOL_AVATAR);
 
 	// Only a single face (one per avatar)
 	//this face will be splitted into several if its vertex buffer is too long.
 	mDrawable->setState(LLDrawable::ACTIVE);
 	mDrawable->addFace(poolp, NULL);
-	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR);
+	mDrawable->setRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR);
 	
 	mNumInitFaces = mDrawable->getNumFaces() ;
 
@@ -6915,7 +6915,7 @@ static LLTrace::BlockTimerStatHandle FTM_UPDATE_AVATAR("Update Avatar");
 BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable)
 {
 	LL_RECORD_BLOCK_TIME(FTM_UPDATE_AVATAR);
- 	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)))
+	if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)))
 	{
 		return TRUE;
 	}
@@ -10071,7 +10071,7 @@ void LLVOAvatar::onActiveOverrideMeshesChanged()
 U32 LLVOAvatar::getPartitionType() const
 { 
 	// Avatars merely exist as drawables in the bridge partition
-	return LLViewerRegion::PARTITION_BRIDGE;
+	return mIsControlAvatar ? LLViewerRegion::PARTITION_CONTROL_AV : LLViewerRegion::PARTITION_AVATAR;
 }
 
 //static
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 07660ca6ac16efc94a662da152592ef40c066abf..689eeee0e3f3f3649325e9d362abd9b396f651f9 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -347,36 +347,24 @@ void LLVOCacheEntry::dump() const
 
 BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const
 {
-	BOOL success;
-	success = check_write(apr_file, (void*)&mLocalID, sizeof(U32));
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mCRC, sizeof(U32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mHitCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mDupeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		success = check_write(apr_file, (void*)&mCRCChangeCount, sizeof(S32));
-	}
-	if(success)
-	{
-		S32 size = mDP.getBufferSize();
-		success = check_write(apr_file, (void*)&size, sizeof(S32));
-	
-		if(success)
-		{
-			success = check_write(apr_file, (void*)mBuffer, size);
-		}
-	}
-
-	return success ;
+    static const S32 data_buffer_size = 6 * sizeof(S32);
+    static U8 data_buffer[data_buffer_size];
+    S32 size = mDP.getBufferSize();
+
+    memcpy(data_buffer, &mLocalID, sizeof(U32));
+    memcpy(data_buffer + sizeof(U32), &mCRC, sizeof(U32));
+    memcpy(data_buffer + (2 * sizeof(U32)), &mHitCount, sizeof(S32));
+    memcpy(data_buffer + (3 * sizeof(U32)), &mDupeCount, sizeof(S32));
+    memcpy(data_buffer + (4 * sizeof(U32)), &mCRCChangeCount, sizeof(S32));
+    memcpy(data_buffer + (5 * sizeof(U32)), &size, sizeof(S32));
+
+    BOOL success = check_write(apr_file, (void*)data_buffer, data_buffer_size);
+    if (success)
+    {
+        success = check_write(apr_file, (void*)mBuffer, size);
+    }
+
+    return success;
 }
 
 //static 
@@ -1537,7 +1525,8 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry:
 		{
 			S32 num_entries = cache_entry_map.size() ;
 			success = check_write(&apr_file, &num_entries, sizeof(S32));
-	
+
+			// This can have a lot of entries, so might be better to dump them into buffer first and write in one go.
 			for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter)
 			{
 				if(!removal_enabled || iter->second->isValid())
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 659b533b86a23791da8910f9522127de1f6a6224..ef39faa8142fabbc1f1e62a55c79c7a35ae01610 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -4893,6 +4893,14 @@ U32 LLVOVolume::getPartitionType() const
 	{
 		return LLViewerRegion::PARTITION_HUD;
 	}
+	if (isAnimatedObject() && getControlAvatar())
+	{
+		return LLViewerRegion::PARTITION_CONTROL_AV;
+	}
+	if (isAttachment())
+	{
+		return LLViewerRegion::PARTITION_AVATAR;
+	}
 
 	return LLViewerRegion::PARTITION_VOLUME;
 }
@@ -4923,6 +4931,20 @@ LLVolumeGeometryManager()
 	mSlopRatio = 0.25f;
 }
 
+LLAvatarBridge::LLAvatarBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
+	: LLVolumeBridge(drawablep, regionp)
+{
+	mDrawableType = LLPipeline::RENDER_TYPE_AVATAR;
+	mPartitionType = LLViewerRegion::PARTITION_AVATAR;
+}
+
+LLControlAVBridge::LLControlAVBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
+	: LLVolumeBridge(drawablep, regionp)
+{
+	mDrawableType = LLPipeline::RENDER_TYPE_CONTROL_AV;
+	mPartitionType = LLViewerRegion::PARTITION_CONTROL_AV;
+}
+
 bool can_batch_texture(LLFace* facep)
 {
 	if (facep->getTextureEntry()->getBumpmap())
@@ -5267,7 +5289,8 @@ static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj)
 				LLDrawPool* drawpool = face->getPool();
 				if (drawpool)
 				{
-					if (drawpool->getType() == LLDrawPool::POOL_AVATAR)
+					if (drawpool->getType() == LLDrawPool::POOL_AVATAR
+						|| drawpool->getType() == LLDrawPool::POOL_CONTROL_AV)
 					{
 						return (LLDrawPoolAvatar*) drawpool;
 					}
@@ -5546,7 +5569,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 						//remove face from old pool if it exists
 						LLDrawPool* old_pool = facep->getPool();
-						if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR)
+						if (old_pool
+							&& (old_pool->getType() == LLDrawPool::POOL_AVATAR || old_pool->getType() == LLDrawPool::POOL_CONTROL_AV))
 						{
 							((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep);
 						}
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 368a3f23351822c03944e403660f887091bd756f..d428cb15682779e6369abe6a167c1eccf483a4bb 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -99,6 +99,9 @@ LLDrawable * LLVOWLSky::createDrawable(LLPipeline * pipeline)
 
 inline F32 LLVOWLSky::calcPhi(U32 i)
 {
+    // Calc: PI/8 * 1-((1-t^4)*(1-t^4))  { 0<t<1 }
+    // Demos: \pi/8*\left(1-((1-x^{4})*(1-x^{4}))\right)\ \left\{0<x\le1\right\}
+
 	// i should range from [0..SKY_STACKS] so t will range from [0.f .. 1.f]
 	F32 t = float(i) / float(getNumStacks());
 
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8989bae96a7fd5ed8329ca5b9ef04c8e99219bc8..a1a1db35d64f600ff2fdc1594323dd3f5b6569ca 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -730,11 +730,20 @@ void LLWorld::updateRegions(F32 max_update_time)
 		{
 			//perform some necessary but very light updates.
 			(*iter)->lightIdleUpdate();
-		}		
+		}
+	}
+
+	if(max_time > 0.f)
+	{
+		max_time = llmin((F32)(max_update_time - update_timer.getElapsedTimeF32()), max_update_time * 0.25f);
+	}
+	if(max_time > 0.f)
+	{
+		LLViewerRegion::idleCleanup(max_time);
 	}
 
 	sample(sNumActiveCachedObjects, mNumOfActiveCachedObjects);
-		}
+}
 
 void LLWorld::clearAllVisibleObjects()
 {
@@ -1208,11 +1217,14 @@ class LLEstablishAgentCommunication : public LLHTTPNode
 	}
 };
 
+static LLTrace::BlockTimerStatHandle FTM_DISABLE_REGION("Disable Region");
 // disable the circuit to this simulator
 // Called in response to "DisableSimulator" message.
 void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
-{	
-	LLHost host = mesgsys->getSender();
+{
+    LL_RECORD_BLOCK_TIME(FTM_DISABLE_REGION);
+
+    LLHost host = mesgsys->getSender();
 
 	//LL_INFOS() << "Disabling simulator with message from " << host << LL_ENDL;
 	LLWorld::getInstance()->removeRegion(host);
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 01438bfb9f989e34f8292d97ae3005ee123e1e46..f565573935f9aea24d21e95503627ff506a57845 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1049,25 +1049,19 @@ void LLPipeline::updateRenderBump()
 	sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
 }
 
-//static
+// static
 void LLPipeline::updateRenderDeferred()
 {
-	bool deferred = (bool(RenderDeferred && 
-					 LLRenderTarget::sUseFBO &&
-					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&	 
-					 LLPipeline::sRenderBump &&
-					 RenderAvatarVP &&
-					 WindLightUseAtmosShaders)) &&
-					!gUseWireframe;
-
-	sRenderDeferred = deferred;	
-	if (deferred)
-	{ //must render glow when rendering deferred since post effect pass is needed to present any lighting at all
-		sRenderGlow = true;
-	}
+    sRenderDeferred = !gUseWireframe &&
+                      RenderDeferred &&
+                      LLRenderTarget::sUseFBO &&
+                      LLPipeline::sRenderBump &&
+                      RenderAvatarVP &&
+                      WindLightUseAtmosShaders &&
+                      (bool) LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
 }
 
-//static
+// static
 void LLPipeline::refreshCachedSettings()
 {
 	LLPipeline::sAutoMaskAlphaDeferred = gSavedSettings.getBOOL("RenderAutoMaskAlphaDeferred");
@@ -1259,24 +1253,20 @@ void LLPipeline::createGLBuffers()
 
 	GLuint resX = gViewerWindow->getWorldViewWidthRaw();
 	GLuint resY = gViewerWindow->getWorldViewHeightRaw();
-	
-	if (LLPipeline::sRenderGlow)
-	{ //screen space glow buffers
-		const U32 glow_res = llmax(1, 
-			llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
 
-		for (U32 i = 0; i < 3; i++)
-		{
-			mGlow[i].allocate(512,glow_res,GL_RGBA,FALSE,FALSE);
-		}
+    // allocate screen space glow buffers
+    const U32 glow_res = llmax(1, llmin(512, 1 << gSavedSettings.getS32("RenderGlowResolutionPow")));
+    for (U32 i = 0; i < 3; i++)
+    {
+        mGlow[i].allocate(512, glow_res, GL_RGBA, FALSE, FALSE);
+    }
 
-		allocateScreenBuffer(resX,resY);
-		mScreenWidth = 0;
-		mScreenHeight = 0;
-	}
-	
-	if (sRenderDeferred)
-	{
+    allocateScreenBuffer(resX, resY);
+    mScreenWidth = 0;
+    mScreenHeight = 0;
+
+    if (sRenderDeferred)
+    {
 		if (!mNoiseMap)
 		{
 			const U32 noiseRes = 128;
@@ -1609,6 +1599,7 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
 		break;
 
 	case LLDrawPool::POOL_AVATAR:
+	case LLDrawPool::POOL_CONTROL_AV:
 		break; // Do nothing
 
 	case LLDrawPool::POOL_SKY:
@@ -1995,7 +1986,7 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list)
 		drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED);
 		if (done)
 		{
-			if (drawablep->isRoot())
+			if (drawablep->isRoot() && !drawablep->isState(LLDrawable::ACTIVE))
 			{
 				drawablep->makeStatic();
 			}
@@ -3362,6 +3353,7 @@ static LLTrace::BlockTimerStatHandle FTM_RESET_DRAWORDER("Reset Draw Order");
 void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
 {
 	if (hasAnyRenderType(LLPipeline::RENDER_TYPE_AVATAR,
+					  LLPipeline::RENDER_TYPE_CONTROL_AV,
 					  LLPipeline::RENDER_TYPE_GROUND,
 					  LLPipeline::RENDER_TYPE_TERRAIN,
 					  LLPipeline::RENDER_TYPE_TREE,
@@ -5774,6 +5766,7 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
 		break;
 
 	case LLDrawPool::POOL_AVATAR:
+	case LLDrawPool::POOL_CONTROL_AV:
 		break; // Do nothing
 
 	case LLDrawPool::POOL_SKY:
@@ -5922,6 +5915,7 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
 		break;
 
 	case LLDrawPool::POOL_AVATAR:
+	case LLDrawPool::POOL_CONTROL_AV:
 		break; // Do nothing
 
 	case LLDrawPool::POOL_SKY:
@@ -6427,41 +6421,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 		light->setAmbient(LLColor4::black);
 		light->setSpecular(LLColor4::black);
 	}
-	if (gAgentAvatarp &&
-		gAgentAvatarp->mSpecialRenderMode == 3)
-	{
-		LLColor4  light_color = LLColor4::white;
-		light_color.mV[3] = 0.0f;
-
-		LLVector3 light_pos(LLViewerCamera::getInstance()->getOrigin());
-		LLVector4 light_pos_gl(light_pos, 1.0f);
-
-		F32 light_radius = 16.f;
-
-			F32 x = 3.f;
-		float linatten = x / (light_radius); // % of brightness at radius
-
-		if (LLPipeline::sRenderDeferred)
-		{
-			/*light_color.mV[0] = powf(light_color.mV[0], 2.2f);
-			light_color.mV[1] = powf(light_color.mV[1], 2.2f);
-			light_color.mV[2] = powf(light_color.mV[2], 2.2f);*/
-		}
-
-		mHWLightColors[2] = light_color;
-		LLLightState* light = gGL.getLight(2);
 
-		light->setPosition(light_pos_gl);
-		light->setDiffuse(light_color);
-        light->setDiffuseB(light_color * 0.25f);
-		light->setAmbient(LLColor4::black);
-		light->setSpecular(LLColor4::black);
-		light->setQuadraticAttenuation(0.f);
-		light->setConstantAttenuation(0.f);
-		light->setLinearAttenuation(linatten);
-		light->setSpotExponent(0.f);
-		light->setSpotCutoff(180.f);
-	}
+    // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode),
+    // prev site of forward (non-deferred) character light injection, removed by SL-13522 09/20
 
 	// Init GL state
 	if (!LLGLSLShader::sNoFixedFunction)
@@ -7151,7 +7113,8 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
 		for (U32 j = 0; j < LLViewerRegion::NUM_PARTITIONS; j++)
 		{
 			if ((j == LLViewerRegion::PARTITION_VOLUME) || 
-				(j == LLViewerRegion::PARTITION_BRIDGE) || 
+				(j == LLViewerRegion::PARTITION_BRIDGE) ||
+				(j == LLViewerRegion::PARTITION_CONTROL_AV) ||
 				(j == LLViewerRegion::PARTITION_TERRAIN) ||
 				(j == LLViewerRegion::PARTITION_TREE) ||
 				(j == LLViewerRegion::PARTITION_GRASS))  // only check these partitions for now
@@ -7213,7 +7176,7 @@ LLViewerObject* LLPipeline::lineSegmentIntersectInWorld(const LLVector4a& start,
 		{
 			LLViewerRegion* region = *iter;
 
-			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_BRIDGE);
+			LLSpatialPartition* part = region->getSpatialPartition(LLViewerRegion::PARTITION_AVATAR);
 			if (part && hasRenderType(part->mDrawableType))
 			{
 				LLDrawable* hit = part->lineSegmentIntersect(start, local_end, pick_transparent, pick_rigged, face_hit, &position, tex_coord, normal, tangent);
@@ -7539,641 +7502,633 @@ void LLPipeline::bindScreenToTexture()
 
 static LLTrace::BlockTimerStatHandle FTM_RENDER_BLOOM("Bloom");
 
-void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
+void LLPipeline::renderFinalize()
 {
-	if (!(gPipeline.canUseVertexShaders() &&
-		sRenderGlow))
-	{
-		return;
-	}
+    LLVertexBuffer::unbind();
+    LLGLState::checkStates();
+    LLGLState::checkTextureChannels();
 
-	LLVertexBuffer::unbind();
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
+    assertInitialized();
 
-	assertInitialized();
+    if (gUseWireframe)
+    {
+        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    }
 
-	if (gUseWireframe)
-	{
-		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
-	}
+    LLVector2 tc1(0, 0);
+    LLVector2 tc2((F32) mScreen.getWidth() * 2, (F32) mScreen.getHeight() * 2);
 
-	LLVector2 tc1(0,0);
-	LLVector2 tc2((F32) mScreen.getWidth()*2,
-				  (F32) mScreen.getHeight()*2);
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
+    gGL.color4f(1, 1, 1, 1);
+    LLGLDepthTest depth(GL_FALSE);
+    LLGLDisable blend(GL_BLEND);
+    LLGLDisable cull(GL_CULL_FACE);
 
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM);
-	gGL.color4f(1,1,1,1);
-	LLGLDepthTest depth(GL_FALSE);
-	LLGLDisable blend(GL_BLEND);
-	LLGLDisable cull(GL_CULL_FACE);
-	
-	enableLightsFullbright();
+    enableLightsFullbright();
 
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
+    gGL.matrixMode(LLRender::MM_PROJECTION);
+    gGL.pushMatrix();
+    gGL.loadIdentity();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.pushMatrix();
+    gGL.loadIdentity();
 
-	LLGLDisable test(GL_ALPHA_TEST);
+    LLGLDisable test(GL_ALPHA_TEST);
 
-	gGL.setColorMask(true, true);
-	glClearColor(0,0,0,0);
-		
-	{
-		{
-			LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
-			mGlow[2].bindTarget();
-			mGlow[2].clear();
-		}
-		
-		gGlowExtractProgram.bind();
-		F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
-		F32 maxAlpha = RenderGlowMaxExtractAlpha;		
-		F32 warmthAmount = RenderGlowWarmthAmount;	
-		LLVector3 lumWeights = RenderGlowLumWeights;
-		LLVector3 warmthWeights = RenderGlowWarmthWeights;
-
-
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
-		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1], lumWeights.mV[2]);
-		gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1], warmthWeights.mV[2]);
-		gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
-		LLGLEnable blend_on(GL_BLEND);
-		LLGLEnable test(GL_ALPHA_TEST);
-		
-		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
-		
-		mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
-		
-		gGL.color4f(1,1,1,1);
-		gPipeline.enableLightsFullbright();
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		gGL.getTexUnit(0)->unbind(mScreen.getUsage());
+    gGL.setColorMask(true, true);
+    glClearColor(0, 0, 0, 0);
 
-		mGlow[2].flush();
-	}
+    if (sRenderGlow)
+    {
+        {
+            LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
+            mGlow[2].bindTarget();
+            mGlow[2].clear();
+        }
 
-	tc1.setVec(0,0);
-	tc2.setVec(2,2);
+        gGlowExtractProgram.bind();
+        F32 minLum = llmax((F32) RenderGlowMinLuminance, 0.0f);
+        F32 maxAlpha = RenderGlowMaxExtractAlpha;
+        F32 warmthAmount = RenderGlowWarmthAmount;
+        LLVector3 lumWeights = RenderGlowLumWeights;
+        LLVector3 warmthWeights = RenderGlowWarmthWeights;
+
+        gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MIN_LUMINANCE, minLum);
+        gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_MAX_EXTRACT_ALPHA, maxAlpha);
+        gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_LUM_WEIGHTS, lumWeights.mV[0], lumWeights.mV[1],
+                                      lumWeights.mV[2]);
+        gGlowExtractProgram.uniform3f(LLShaderMgr::GLOW_WARMTH_WEIGHTS, warmthWeights.mV[0], warmthWeights.mV[1],
+                                      warmthWeights.mV[2]);
+        gGlowExtractProgram.uniform1f(LLShaderMgr::GLOW_WARMTH_AMOUNT, warmthAmount);
+        
+        {
+            LLGLEnable blend_on(GL_BLEND);
+            LLGLEnable test(GL_ALPHA_TEST);
 
-	// power of two between 1 and 1024
-	U32 glowResPow = RenderGlowResolutionPow;
-	const U32 glow_res = llmax(1, 
-		llmin(1024, 1 << glowResPow));
+            gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
 
-	S32 kernel = RenderGlowIterations*2;
-	F32 delta = RenderGlowWidth / glow_res;
-	// Use half the glow width if we have the res set to less than 9 so that it looks
-	// almost the same in either case.
-	if (glowResPow < 9)
-	{
-		delta *= 0.5f;
-	}
-	F32 strength = RenderGlowStrength;
+            mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
 
-	gGlowProgram.bind();
-	gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
+            gGL.color4f(1, 1, 1, 1);
+            gPipeline.enableLightsFullbright();
+            gGL.begin(LLRender::TRIANGLE_STRIP);
+            gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+            gGL.vertex2f(-1, -1);
 
-	for (S32 i = 0; i < kernel; i++)
-	{
-		{
-			LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
-			mGlow[i%2].bindTarget();
-			mGlow[i%2].clear();
-		}
-			
-		if (i == 0)
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[2]);
-		}
-		else
-		{
-			gGL.getTexUnit(0)->bind(&mGlow[(i-1)%2]);
-		}
+            gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+            gGL.vertex2f(-1, 3);
 
-		if (i%2 == 0)
-		{
-			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
-		}
-		else
-		{
-			gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
-		}
+            gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+            gGL.vertex2f(3, -1);
 
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
-		mGlow[i%2].flush();
-	}
+            gGL.end();
 
-	gGlowProgram.unbind();
+            gGL.getTexUnit(0)->unbind(mScreen.getUsage());
 
-	/*if (LLRenderTarget::sUseFBO)
-	{
-		LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
-		glBindFramebuffer(GL_FRAMEBUFFER, 0);
-	}*/
+            mGlow[2].flush();
 
-	gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-	gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-	gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-	gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-	glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+            tc1.setVec(0, 0);
+            tc2.setVec(2, 2); 
+        }
 
-	tc2.setVec((F32) mScreen.getWidth(),
-			(F32) mScreen.getHeight());
+        // power of two between 1 and 1024
+        U32 glowResPow = RenderGlowResolutionPow;
+        const U32 glow_res = llmax(1, llmin(1024, 1 << glowResPow));
 
-	gGL.flush();
-	
-	LLVertexBuffer::unbind();
+        S32 kernel = RenderGlowIterations * 2;
+        F32 delta = RenderGlowWidth / glow_res;
+        // Use half the glow width if we have the res set to less than 9 so that it looks
+        // almost the same in either case.
+        if (glowResPow < 9)
+        {
+            delta *= 0.5f;
+        }
+        F32 strength = RenderGlowStrength;
 
-	if (LLPipeline::sRenderDeferred)
-	{
+        gGlowProgram.bind();
+        gGlowProgram.uniform1f(LLShaderMgr::GLOW_STRENGTH, strength);
 
-		bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
-			(RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
-							RenderDepthOfField;
+        for (S32 i = 0; i < kernel; i++)
+        {
+            {
+                LL_RECORD_BLOCK_TIME(FTM_RENDER_BLOOM_FBO);
+                mGlow[i % 2].bindTarget();
+                mGlow[i % 2].clear();
+            }
 
+            if (i == 0)
+            {
+                gGL.getTexUnit(0)->bind(&mGlow[2]);
+            }
+            else
+            {
+                gGL.getTexUnit(0)->bind(&mGlow[(i - 1) % 2]);
+            }
 
-		bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
+            if (i % 2 == 0)
+            {
+                gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, delta, 0);
+            }
+            else
+            {
+                gGlowProgram.uniform2f(LLShaderMgr::GLOW_DELTA, 0, delta);
+            }
 
-		gViewerWindow->setup3DViewport();
-				
-		if (dof_enabled)
-		{
-			LLGLSLShader* shader = &gDeferredPostProgram;
-			LLGLDisable blend(GL_BLEND);
+            gGL.begin(LLRender::TRIANGLE_STRIP);
+            gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+            gGL.vertex2f(-1, -1);
 
-			//depth of field focal plane calculations
-			static F32 current_distance = 16.f;
-			static F32 start_distance = 16.f;
-			static F32 transition_time = 1.f;
+            gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+            gGL.vertex2f(-1, 3);
 
-			LLVector3 focus_point;
+            gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+            gGL.vertex2f(3, -1);
 
-			LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
-			if (obj && obj->mDrawable && obj->isSelected())
-			{ //focus on selected media object
-				S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
-				if (obj && obj->mDrawable)
-				{
-					LLFace* face = obj->mDrawable->getFace(face_idx);
-					if (face)
-					{
-						focus_point = face->getPositionAgent();
-					}
-				}
-			}
-		
-			if (focus_point.isExactlyZero())
-			{
-				if (LLViewerJoystick::getInstance()->getOverrideCamera())
-				{ //focus on point under cursor
-					focus_point.set(gDebugRaycastIntersection.getF32ptr());
-				}
-				else if (gAgentCamera.cameraMouselook())
-				{ //focus on point under mouselook crosshairs
-					LLVector4a result;
-					result.clear();
+            gGL.end();
 
-					gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE,
-													NULL,
-													&result);
+            mGlow[i % 2].flush();
+        }
 
-					focus_point.set(result.getF32ptr());
-				}
-				else
-				{
-					//focus on alt-zoom target
-					LLViewerRegion* region = gAgent.getRegion();
-					if (region)
-					{
-						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal());
-					}
-				}
-			}
+        gGlowProgram.unbind();
+    }
+    else // !sRenderGlow, skip the glow ping-pong and just clear the result target
+    {
+        mGlow[1].bindTarget();
+        mGlow[1].clear();
+        mGlow[1].flush();
+    }
 
-			LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
-			F32 target_distance = 16.f;
-			if (!focus_point.isExactlyZero())
-			{
-				target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
-			}
+    gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+    gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+    gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+    gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+    glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
 
-			if (transition_time >= 1.f &&
-				fabsf(current_distance-target_distance)/current_distance > 0.01f)
-			{ //large shift happened, interpolate smoothly to new target distance
-				transition_time = 0.f;
-				start_distance = current_distance;
-			}
-			else if (transition_time < 1.f)
-			{ //currently in a transition, continue interpolating
-				transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value();
-				transition_time = llmin(transition_time, 1.f);
+    tc2.setVec((F32) mScreen.getWidth(), (F32) mScreen.getHeight());
 
-				F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
-				current_distance = start_distance + (target_distance-start_distance)*t;
-			}
-			else
-			{ //small or no change, just snap to target distance
-				current_distance = target_distance;
-			}
+    gGL.flush();
 
-			//convert to mm
-			F32 subject_distance = current_distance*1000.f;
-			F32 fnumber = CameraFNumber;
-			F32 default_focal_length = CameraFocalLength;
+    LLVertexBuffer::unbind();
 
-			F32 fov = LLViewerCamera::getInstance()->getView();
-		
-			const F32 default_fov = CameraFieldOfView * F_PI/180.f;
-		
-			//F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
-		
-			F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
+    if (LLPipeline::sRenderDeferred)
+    {
 
-			F32 focal_length = dv/(2*tanf(fov/2.f));
-		 
-			//F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
-	
-			// from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
-			// where	 N = fnumber
-			//			 s2 = dot distance
-			//			 s1 = subject distance
-			//			 f = focal length
-			//	
+        bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater() &&
+                           (RenderDepthOfFieldInEditMode || !LLToolMgr::getInstance()->inBuildMode()) &&
+                           RenderDepthOfField;
 
-			F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
-			blur_constant /= 1000.f; //convert to meters for shader
-			F32 magnification = focal_length/(subject_distance-focal_length);
+        bool multisample = RenderFSAASamples > 1 && mFXAABuffer.isComplete();
 
-			{ //build diffuse+bloom+CoF
-				mDeferredLight.bindTarget();
-				shader = &gDeferredCoFProgram;
+        gViewerWindow->setup3DViewport();
 
-				bindDeferredShader(*shader);
+        if (dof_enabled)
+        {
+            LLGLSLShader *shader = &gDeferredPostProgram;
+            LLGLDisable blend(GL_BLEND);
 
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-				if (channel > -1)
-				{
-					mScreen.bindTexture(0, channel);
-				}
+            // depth of field focal plane calculations
+            static F32 current_distance = 16.f;
+            static F32 start_distance = 16.f;
+            static F32 transition_time = 1.f;
 
-				shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
-				shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
-				shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
-				shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+            LLVector3 focus_point;
 
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
+            LLViewerObject *obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+            if (obj && obj->mDrawable && obj->isSelected())
+            { // focus on selected media object
+                S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+                if (obj && obj->mDrawable)
+                {
+                    LLFace *face = obj->mDrawable->getFace(face_idx);
+                    if (face)
+                    {
+                        focus_point = face->getPositionAgent();
+                    }
+                }
+            }
 
-				unbindDeferredShader(*shader);
-				mDeferredLight.flush();
-			}
+            if (focus_point.isExactlyZero())
+            {
+                if (LLViewerJoystick::getInstance()->getOverrideCamera())
+                { // focus on point under cursor
+                    focus_point.set(gDebugRaycastIntersection.getF32ptr());
+                }
+                else if (gAgentCamera.cameraMouselook())
+                { // focus on point under mouselook crosshairs
+                    LLVector4a result;
+                    result.clear();
 
-			U32 dof_width = (U32) (mScreen.getWidth()*CameraDoFResScale);
-			U32 dof_height = (U32) (mScreen.getHeight()*CameraDoFResScale);
-			
-			{ //perform DoF sampling at half-res (preserve alpha channel)
-				mScreen.bindTarget();
-				glViewport(0,0, dof_width, dof_height);
-				gGL.setColorMask(true, false);
+                    gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, FALSE, NULL, &result);
 
-				shader = &gDeferredPostProgram;
-				bindDeferredShader(*shader);
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-				if (channel > -1)
-				{
-					mDeferredLight.bindTexture(0, channel);
-				}
+                    focus_point.set(result.getF32ptr());
+                }
+                else
+                {
+                    // focus on alt-zoom target
+                    LLViewerRegion *region = gAgent.getRegion();
+                    if (region)
+                    {
+                        focus_point = LLVector3(gAgentCamera.getFocusGlobal() - region->getOriginGlobal());
+                    }
+                }
+            }
 
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-				
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
+            LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+            F32 target_distance = 16.f;
+            if (!focus_point.isExactlyZero())
+            {
+                target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point - eye);
+            }
 
-				unbindDeferredShader(*shader);
-				mScreen.flush();
-				gGL.setColorMask(true, true);
-			}
-	
-			{ //combine result based on alpha
-				if (multisample)
-				{
-					mDeferredLight.bindTarget();
-					glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
-				}
-				else
-				{
-					gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-					gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-					gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-					gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-					glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-				}
+            if (transition_time >= 1.f && fabsf(current_distance - target_distance) / current_distance > 0.01f)
+            { // large shift happened, interpolate smoothly to new target distance
+                transition_time = 0.f;
+                start_distance = current_distance;
+            }
+            else if (transition_time < 1.f)
+            { // currently in a transition, continue interpolating
+                transition_time += 1.f / CameraFocusTransitionTime * gFrameIntervalSeconds.value();
+                transition_time = llmin(transition_time, 1.f);
 
-				shader = &gDeferredDoFCombineProgram;
-				bindDeferredShader(*shader);
-				
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-				if (channel > -1)
-				{
-					mScreen.bindTexture(0, channel);
-				}
+                F32 t = cosf(transition_time * F_PI + F_PI) * 0.5f + 0.5f;
+                current_distance = start_distance + (target_distance - start_distance) * t;
+            }
+            else
+            { // small or no change, just snap to target distance
+                current_distance = target_distance;
+            }
 
-				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
-				shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
-				shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width-1);
-				shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height-1);
+            // convert to mm
+            F32 subject_distance = current_distance * 1000.f;
+            F32 fnumber = CameraFNumber;
+            F32 default_focal_length = CameraFocalLength;
 
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
-		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
-		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
-		
-				gGL.end();
+            F32 fov = LLViewerCamera::getInstance()->getView();
 
-				unbindDeferredShader(*shader);
+            const F32 default_fov = CameraFieldOfView * F_PI / 180.f;
 
-				if (multisample)
-				{
-					mDeferredLight.flush();
-				}
-			}
-		}
-		else
-		{
-			if (multisample)
-			{
-				mDeferredLight.bindTarget();
-			}
-			LLGLSLShader* shader = &gDeferredPostNoDoFProgram;
-			
-			bindDeferredShader(*shader);
-							
-			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-			if (channel > -1)
-			{
-				mScreen.bindTexture(0, channel);
-			}
+            // F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
 
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-			gGL.vertex2f(-1,-1);
-		
-			gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-			gGL.vertex2f(-1,3);
-		
-			gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-			gGL.vertex2f(3,-1);
-		
-			gGL.end();
+            F32 dv = 2.f * default_focal_length * tanf(default_fov / 2.f);
 
-			unbindDeferredShader(*shader);
+            F32 focal_length = dv / (2 * tanf(fov / 2.f));
 
-			if (multisample)
-			{
-				mDeferredLight.flush();
-			}
-		}
+            // F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
 
-		if (multisample)
-		{
-			//bake out texture2D with RGBL for FXAA shader
-			mFXAABuffer.bindTarget();
-			
-			S32 width = mScreen.getWidth();
-			S32 height = mScreen.getHeight();
-			glViewport(0, 0, width, height);
+            // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+            // where	 N = fnumber
+            //			 s2 = dot distance
+            //			 s1 = subject distance
+            //			 f = focal length
+            //
 
-			LLGLSLShader* shader = &gGlowCombineFXAAProgram;
+            F32 blur_constant = focal_length * focal_length / (fnumber * (subject_distance - focal_length));
+            blur_constant /= 1000.f; // convert to meters for shader
+            F32 magnification = focal_length / (subject_distance - focal_length);
 
-			shader->bind();
-			shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+            { // build diffuse+bloom+CoF
+                mDeferredLight.bindTarget();
+                shader = &gDeferredCoFProgram;
 
-			S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-			if (channel > -1)
-			{
-				mDeferredLight.bindTexture(0, channel);
-			}
-						
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.vertex2f(-1,-1);
-			gGL.vertex2f(-1,3);
-			gGL.vertex2f(3,-1);
-			gGL.end();
+                bindDeferredShader(*shader);
 
-			gGL.flush();
+                S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+                if (channel > -1)
+                {
+                    mScreen.bindTexture(0, channel);
+                }
 
-			shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-			shader->unbind();
-			
-			mFXAABuffer.flush();
+                shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance / 1000.f);
+                shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+                shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f / LLDrawable::sCurPixelAngle));
+                shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+                shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+                shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
 
-			shader = &gFXAAProgram;
-			shader->bind();
+                gGL.begin(LLRender::TRIANGLE_STRIP);
+                gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+                gGL.vertex2f(-1, -1);
 
-			channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
-			if (channel > -1)
-			{
-				mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
-			}
-			
-			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
-			gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
-			gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
-			gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
-			glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
-
-			F32 scale_x = (F32) width/mFXAABuffer.getWidth();
-			F32 scale_y = (F32) height/mFXAABuffer.getHeight();
-			shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
-			shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f/width*scale_x, 1.f/height*scale_y);
-			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f/width*scale_x, -0.5f/height*scale_y, 0.5f/width*scale_x, 0.5f/height*scale_y);
-			shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f/width*scale_x, -2.f/height*scale_y, 2.f/width*scale_x, 2.f/height*scale_y);
-			
-			gGL.begin(LLRender::TRIANGLE_STRIP);
-			gGL.vertex2f(-1,-1);
-			gGL.vertex2f(-1,3);
-			gGL.vertex2f(3,-1);
-			gGL.end();
+                gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+                gGL.vertex2f(-1, 3);
 
-			gGL.flush();
-			shader->unbind();
-		}
-	}
-	else
-	{
-		U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
-		LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
-		buff->allocateBuffer(3,0,TRUE);
+                gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+                gGL.vertex2f(3, -1);
 
-		LLStrider<LLVector3> v;
-		LLStrider<LLVector2> uv1;
-		LLStrider<LLVector2> uv2;
+                gGL.end();
 
-		buff->getVertexStrider(v);
-		buff->getTexCoord0Strider(uv1);
-		buff->getTexCoord1Strider(uv2);
-		
-		uv1[0] = LLVector2(0, 0);
-		uv1[1] = LLVector2(0, 2);
-		uv1[2] = LLVector2(2, 0);
-		
-		uv2[0] = LLVector2(0, 0);
-		uv2[1] = LLVector2(0, tc2.mV[1]*2.f);
-		uv2[2] = LLVector2(tc2.mV[0]*2.f, 0);
-		
-		v[0] = LLVector3(-1,-1,0);
-		v[1] = LLVector3(-1,3,0);
-		v[2] = LLVector3(3,-1,0);
-				
-		buff->flush();
+                unbindDeferredShader(*shader);
+                mDeferredLight.flush();
+            }
 
-		LLGLDisable blend(GL_BLEND);
+            U32 dof_width = (U32)(mScreen.getWidth() * CameraDoFResScale);
+            U32 dof_height = (U32)(mScreen.getHeight() * CameraDoFResScale);
 
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gGlowCombineProgram.bind();
-		}
-		else
-		{
-			//tex unit 0
-			gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
-			//tex unit 1
-			gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR);
-		}
-		
-		gGL.getTexUnit(0)->bind(&mGlow[1]);
-		gGL.getTexUnit(1)->bind(&mScreen);
-		
-		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-		
-		buff->setBuffer(mask);
-		buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
-		
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gGlowCombineProgram.unbind();
-		}
-		else
-		{
-			gGL.getTexUnit(1)->disable();
-			gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+            { // perform DoF sampling at half-res (preserve alpha channel)
+                mScreen.bindTarget();
+                glViewport(0, 0, dof_width, dof_height);
+                gGL.setColorMask(true, false);
 
-			gGL.getTexUnit(0)->activate();
-			gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
-		}
-		
-	}
+                shader = &gDeferredPostProgram;
+                bindDeferredShader(*shader);
+                S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+                if (channel > -1)
+                {
+                    mDeferredLight.bindTexture(0, channel);
+                }
 
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+                shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+                shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
 
-	if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
-	{
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gSplatTextureRectProgram.bind();
-		}
+                gGL.begin(LLRender::TRIANGLE_STRIP);
+                gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+                gGL.vertex2f(-1, -1);
 
-		gGL.setColorMask(true, false);
+                gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+                gGL.vertex2f(-1, 3);
 
-		LLVector2 tc1(0,0);
-		LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2,
-				  (F32) gViewerWindow->getWorldViewHeightRaw()*2);
+                gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+                gGL.vertex2f(3, -1);
 
-		LLGLEnable blend(GL_BLEND);
-		gGL.color4f(1,1,1,0.75f);
+                gGL.end();
 
-		gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+                unbindDeferredShader(*shader);
+                mScreen.flush();
+                gGL.setColorMask(true, true);
+            }
 
-		gGL.begin(LLRender::TRIANGLES);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		gGL.flush();
+            { // combine result based on alpha
+                if (multisample)
+                {
+                    mDeferredLight.bindTarget();
+                    glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+                }
+                else
+                {
+                    gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+                    gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+                    gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+                    gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+                    glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+                }
 
-		if (LLGLSLShader::sNoFixedFunction)
-		{
-			gSplatTextureRectProgram.unbind();
-		}
-	}
+                shader = &gDeferredDoFCombineProgram;
+                bindDeferredShader(*shader);
 
-	
-	if (LLRenderTarget::sUseFBO)
-	{ //copy depth buffer from mScreen to framebuffer
-		LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 
-			0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
-	}
-	
+                S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+                if (channel > -1)
+                {
+                    mScreen.bindTexture(0, channel);
+                }
 
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();
+                shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
+                shader->uniform1f(LLShaderMgr::DOF_RES_SCALE, CameraDoFResScale);
+                shader->uniform1f(LLShaderMgr::DOF_WIDTH, dof_width - 1);
+                shader->uniform1f(LLShaderMgr::DOF_HEIGHT, dof_height - 1);
 
-	LLVertexBuffer::unbind();
+                gGL.begin(LLRender::TRIANGLE_STRIP);
+                gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+                gGL.vertex2f(-1, -1);
 
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
+                gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+                gGL.vertex2f(-1, 3);
+
+                gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+                gGL.vertex2f(3, -1);
+
+                gGL.end();
+
+                unbindDeferredShader(*shader);
+
+                if (multisample)
+                {
+                    mDeferredLight.flush();
+                }
+            }
+        }
+        else
+        {
+            if (multisample)
+            {
+                mDeferredLight.bindTarget();
+            }
+            LLGLSLShader *shader = &gDeferredPostNoDoFProgram;
+
+            bindDeferredShader(*shader);
+
+            S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+            if (channel > -1)
+            {
+                mScreen.bindTexture(0, channel);
+            }
+
+            gGL.begin(LLRender::TRIANGLE_STRIP);
+            gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+            gGL.vertex2f(-1, -1);
+
+            gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+            gGL.vertex2f(-1, 3);
+
+            gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+            gGL.vertex2f(3, -1);
+
+            gGL.end();
+
+            unbindDeferredShader(*shader);
+
+            if (multisample)
+            {
+                mDeferredLight.flush();
+            }
+        }
+
+        if (multisample)
+        {
+            // bake out texture2D with RGBL for FXAA shader
+            mFXAABuffer.bindTarget();
+
+            S32 width = mScreen.getWidth();
+            S32 height = mScreen.getHeight();
+            glViewport(0, 0, width, height);
+
+            LLGLSLShader *shader = &gGlowCombineFXAAProgram;
+
+            shader->bind();
+            shader->uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, width, height);
+
+            S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+            if (channel > -1)
+            {
+                mDeferredLight.bindTexture(0, channel);
+            }
+
+            gGL.begin(LLRender::TRIANGLE_STRIP);
+            gGL.vertex2f(-1, -1);
+            gGL.vertex2f(-1, 3);
+            gGL.vertex2f(3, -1);
+            gGL.end();
+
+            gGL.flush();
 
+            shader->disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+            shader->unbind();
+
+            mFXAABuffer.flush();
+
+            shader = &gFXAAProgram;
+            shader->bind();
+
+            channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
+            if (channel > -1)
+            {
+                mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
+            }
+
+            gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
+            gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom;
+            gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth();
+            gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight();
+            glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]);
+
+            F32 scale_x = (F32) width / mFXAABuffer.getWidth();
+            F32 scale_y = (F32) height / mFXAABuffer.getHeight();
+            shader->uniform2f(LLShaderMgr::FXAA_TC_SCALE, scale_x, scale_y);
+            shader->uniform2f(LLShaderMgr::FXAA_RCP_SCREEN_RES, 1.f / width * scale_x, 1.f / height * scale_y);
+            shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT, -0.5f / width * scale_x, -0.5f / height * scale_y,
+                              0.5f / width * scale_x, 0.5f / height * scale_y);
+            shader->uniform4f(LLShaderMgr::FXAA_RCP_FRAME_OPT2, -2.f / width * scale_x, -2.f / height * scale_y,
+                              2.f / width * scale_x, 2.f / height * scale_y);
+
+            gGL.begin(LLRender::TRIANGLE_STRIP);
+            gGL.vertex2f(-1, -1);
+            gGL.vertex2f(-1, 3);
+            gGL.vertex2f(3, -1);
+            gGL.end();
+
+            gGL.flush();
+            shader->unbind();
+        }
+    }
+    else // not deferred
+    {
+        U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
+        LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(mask, 0);
+        buff->allocateBuffer(3, 0, TRUE);
+
+        LLStrider<LLVector3> v;
+        LLStrider<LLVector2> uv1;
+        LLStrider<LLVector2> uv2;
+
+        buff->getVertexStrider(v);
+        buff->getTexCoord0Strider(uv1);
+        buff->getTexCoord1Strider(uv2);
+
+        uv1[0] = LLVector2(0, 0);
+        uv1[1] = LLVector2(0, 2);
+        uv1[2] = LLVector2(2, 0);
+
+        uv2[0] = LLVector2(0, 0);
+        uv2[1] = LLVector2(0, tc2.mV[1] * 2.f);
+        uv2[2] = LLVector2(tc2.mV[0] * 2.f, 0);
+
+        v[0] = LLVector3(-1, -1, 0);
+        v[1] = LLVector3(-1, 3, 0);
+        v[2] = LLVector3(3, -1, 0);
+
+        buff->flush();
+
+        LLGLDisable blend(GL_BLEND);
+
+        if (LLGLSLShader::sNoFixedFunction)
+        {
+            gGlowCombineProgram.bind();
+        }
+        else
+        {
+            // tex unit 0
+            gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
+            // tex unit 1
+            gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR,
+                                                    LLTexUnit::TBS_PREV_COLOR);
+        }
+
+        gGL.getTexUnit(0)->bind(&mGlow[1]);
+        gGL.getTexUnit(1)->bind(&mScreen);
+
+        LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+        buff->setBuffer(mask);
+        buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3);
+
+        if (LLGLSLShader::sNoFixedFunction)
+        {
+            gGlowCombineProgram.unbind();
+        }
+        else
+        {
+            gGL.getTexUnit(1)->disable();
+            gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+            gGL.getTexUnit(0)->activate();
+            gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+        }
+    }
+
+    gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+    if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PHYSICS_SHAPES))
+    {
+        if (LLGLSLShader::sNoFixedFunction)
+        {
+            gSplatTextureRectProgram.bind();
+        }
+
+        gGL.setColorMask(true, false);
+
+        LLVector2 tc1(0, 0);
+        LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw() * 2,
+                      (F32) gViewerWindow->getWorldViewHeightRaw() * 2);
+
+        LLGLEnable blend(GL_BLEND);
+        gGL.color4f(1, 1, 1, 0.75f);
+
+        gGL.getTexUnit(0)->bind(&mPhysicsDisplay);
+
+        gGL.begin(LLRender::TRIANGLES);
+        gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+        gGL.vertex2f(-1, -1);
+
+        gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+        gGL.vertex2f(-1, 3);
+
+        gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+        gGL.vertex2f(3, -1);
+
+        gGL.end();
+        gGL.flush();
+
+        if (LLGLSLShader::sNoFixedFunction)
+        {
+            gSplatTextureRectProgram.unbind();
+        }
+    }
+
+    if (LLRenderTarget::sUseFBO)
+    { // copy depth buffer from mScreen to framebuffer
+        LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(), 0, 0,
+                                                  mScreen.getWidth(), mScreen.getHeight(),
+                                                  GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
+    }
+
+    gGL.matrixMode(LLRender::MM_PROJECTION);
+    gGL.popMatrix();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.popMatrix();
+
+    LLVertexBuffer::unbind();
+
+    LLGLState::checkStates();
+    LLGLState::checkTextureChannels();
 }
 
 static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred");
@@ -8453,292 +8408,301 @@ static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
 static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors");
 static LLTrace::BlockTimerStatHandle FTM_POST("Post");
 
-
-void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
+void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
 {
-	if (!sCull)
-	{
-		return;
-	}
+    if (!sCull)
+    {
+        return;
+    }
 
-    LLRenderTarget* deferred_target       = &mDeferredScreen;
-    LLRenderTarget* deferred_depth_target = &mDeferredDepth;
-    LLRenderTarget* deferred_light_target = &mDeferredLight;
+    LLRenderTarget *deferred_target       = &mDeferredScreen;
+    LLRenderTarget *deferred_depth_target = &mDeferredDepth;
+    LLRenderTarget *deferred_light_target = &mDeferredLight;
 
-	{
-		LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
-		LLViewerCamera* camera = LLViewerCamera::getInstance();
-		{
-			LLGLDepthTest depth(GL_TRUE);
-            deferred_depth_target->copyContents(*deferred_target, 0, 0, deferred_target->getWidth(), deferred_target->getHeight(),
-                            0, 0, deferred_depth_target->getWidth(), deferred_depth_target->getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);  
-		}
+    {
+        LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
+        LLViewerCamera *camera = LLViewerCamera::getInstance();
+        {
+            LLGLDepthTest depth(GL_TRUE);
+            deferred_depth_target->copyContents(*deferred_target,
+                                                0,
+                                                0,
+                                                deferred_target->getWidth(),
+                                                deferred_target->getHeight(),
+                                                0,
+                                                0,
+                                                deferred_depth_target->getWidth(),
+                                                deferred_depth_target->getHeight(),
+                                                GL_DEPTH_BUFFER_BIT,
+                                                GL_NEAREST);
+        }
 
-		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+        LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
 
-		if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
-		{
-			gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
-		}
+        if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD))
+        {
+            gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD);
+        }
 
-		//ati doesn't seem to love actually using the stencil buffer on FBO's
-		LLGLDisable stencil(GL_STENCIL_TEST);
-		//glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
-		//glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+        // ati doesn't seem to love actually using the stencil buffer on FBO's
+        LLGLDisable stencil(GL_STENCIL_TEST);
+        // glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF);
+        // glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
 
-		gGL.setColorMask(true, true);
-		
-		//draw a cube around every light
-		LLVertexBuffer::unbind();
+        gGL.setColorMask(true, true);
 
-		LLGLEnable cull(GL_CULL_FACE);
-		LLGLEnable blend(GL_BLEND);
+        // draw a cube around every light
+        LLVertexBuffer::unbind();
+
+        LLGLEnable cull(GL_CULL_FACE);
+        LLGLEnable blend(GL_BLEND);
 
         glh::matrix4f mat = copy_matrix(gGLModelView);
 
-		LLStrider<LLVector3> vert; 
-		mDeferredVB->getVertexStrider(vert);
-		
-		vert[0].set(-1,1,0);
-		vert[1].set(-1,-3,0);
-		vert[2].set(3,1,0);
-		
-        setupHWLights(NULL); //to set mSun/MoonDir;
+        LLStrider<LLVector3> vert;
+        mDeferredVB->getVertexStrider(vert);
+
+        vert[0].set(-1, 1, 0);
+        vert[1].set(-1, -3, 0);
+        vert[2].set(3, 1, 0);
+
+        setupHWLights(NULL);  // to set mSun/MoonDir;
 
         glh::vec4f tc(mSunDir.mV);
-			mat.mult_matrix_vec(tc);
-			mTransformedSunDir.set(tc.v);
+        mat.mult_matrix_vec(tc);
+        mTransformedSunDir.set(tc.v);
 
         glh::vec4f tc_moon(mMoonDir.mV);
         mat.mult_matrix_vec(tc_moon);
         mTransformedMoonDir.set(tc_moon.v);
 
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.pushMatrix();
-		gGL.loadIdentity();
+        gGL.pushMatrix();
+        gGL.loadIdentity();
+        gGL.matrixMode(LLRender::MM_PROJECTION);
+        gGL.pushMatrix();
+        gGL.loadIdentity();
 
-		if (RenderDeferredSSAO || RenderShadowDetail > 0)
-		{
+        if (RenderDeferredSSAO || RenderShadowDetail > 0)
+        {
             deferred_light_target->bindTarget();
-			{ //paint shadow/SSAO light map (direct lighting lightmap)
-				LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
+            {  // paint shadow/SSAO light map (direct lighting lightmap)
+                LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
                 bindDeferredShader(gDeferredSunProgram, deferred_light_target);
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				glClearColor(1,1,1,1);
+                mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+                glClearColor(1, 1, 1, 1);
                 deferred_light_target->clear(GL_COLOR_BUFFER_BIT);
-				glClearColor(0,0,0,0);
+                glClearColor(0, 0, 0, 0);
 
                 glh::matrix4f inv_trans = get_current_modelview().inverse().transpose();
 
-				const U32 slice = 32;
-				F32 offset[slice*3];
-				for (U32 i = 0; i < 4; i++)
-				{
-					for (U32 j = 0; j < 8; j++)
-					{
-						glh::vec3f v;
-						v.set_value(sinf(6.284f/8*j), cosf(6.284f/8*j), -(F32) i);
-						v.normalize();
-						inv_trans.mult_matrix_vec(v);
-						v.normalize();
-						offset[(i*8+j)*3+0] = v.v[0];
-						offset[(i*8+j)*3+1] = v.v[2];
-						offset[(i*8+j)*3+2] = v.v[1];
-					}
-				}
+                const U32 slice = 32;
+                F32       offset[slice * 3];
+                for (U32 i = 0; i < 4; i++)
+                {
+                    for (U32 j = 0; j < 8; j++)
+                    {
+                        glh::vec3f v;
+                        v.set_value(sinf(6.284f / 8 * j), cosf(6.284f / 8 * j), -(F32) i);
+                        v.normalize();
+                        inv_trans.mult_matrix_vec(v);
+                        v.normalize();
+                        offset[(i * 8 + j) * 3 + 0] = v.v[0];
+                        offset[(i * 8 + j) * 3 + 1] = v.v[2];
+                        offset[(i * 8 + j) * 3 + 2] = v.v[1];
+                    }
+                }
 
-				gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
-                gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_light_target->getWidth(), deferred_light_target->getHeight());
-				
-				{
-					LLGLDisable blend(GL_BLEND);
-					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-					stop_glerror();
-					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-					stop_glerror();
-				}
-				
-				unbindDeferredShader(gDeferredSunProgram);
-			}
+                gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
+                gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES,
+                                              deferred_light_target->getWidth(),
+                                              deferred_light_target->getHeight());
+
+                {
+                    LLGLDisable   blend(GL_BLEND);
+                    LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+                    stop_glerror();
+                    mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                    stop_glerror();
+                }
+
+                unbindDeferredShader(gDeferredSunProgram);
+            }
             deferred_light_target->flush();
-		}
-		
-		if (RenderDeferredSSAO)
-		{ //soften direct lighting lightmap
-			LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
-			//blur lightmap
+        }
+
+        if (RenderDeferredSSAO)
+        {  // soften direct lighting lightmap
+            LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
+            // blur lightmap
             screen_target->bindTarget();
-			glClearColor(1,1,1,1);
+            glClearColor(1, 1, 1, 1);
             screen_target->clear(GL_COLOR_BUFFER_BIT);
-			glClearColor(0,0,0,0);
-			
-			bindDeferredShader(gDeferredBlurLightProgram);
-			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			LLVector3 go = RenderShadowGaussian;
-			const U32 kern_length = 4;
-			F32 blur_size = RenderShadowBlurSize;
-			F32 dist_factor = RenderShadowBlurDistFactor;
+            glClearColor(0, 0, 0, 0);
 
-			// sample symmetrically with the middle sample falling exactly on 0.0
-			F32 x = 0.f;
+            bindDeferredShader(gDeferredBlurLightProgram);
+            mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+            LLVector3 go          = RenderShadowGaussian;
+            const U32 kern_length = 4;
+            F32       blur_size   = RenderShadowBlurSize;
+            F32       dist_factor = RenderShadowBlurDistFactor;
 
-			LLVector3 gauss[32]; // xweight, yweight, offset
+            // sample symmetrically with the middle sample falling exactly on 0.0
+            F32 x = 0.f;
 
-			for (U32 i = 0; i < kern_length; i++)
-			{
-				gauss[i].mV[0] = llgaussian(x, go.mV[0]);
-				gauss[i].mV[1] = llgaussian(x, go.mV[1]);
-				gauss[i].mV[2] = x;
-				x += 1.f;
-			}
+            LLVector3 gauss[32];  // xweight, yweight, offset
+
+            for (U32 i = 0; i < kern_length; i++)
+            {
+                gauss[i].mV[0] = llgaussian(x, go.mV[0]);
+                gauss[i].mV[1] = llgaussian(x, go.mV[1]);
+                gauss[i].mV[2] = x;
+                x += 1.f;
+            }
+
+            gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
+            gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
+            gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
+            gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length / 2.f - 0.5f));
+
+            {
+                LLGLDisable   blend(GL_BLEND);
+                LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+                stop_glerror();
+                mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                stop_glerror();
+            }
 
-			gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f);
-			gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor);
-			gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV);
-			gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length/2.f - 0.5f));
-		
-			{
-				LLGLDisable blend(GL_BLEND);
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-				stop_glerror();
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				stop_glerror();
-			}
-			
             screen_target->flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
+            unbindDeferredShader(gDeferredBlurLightProgram);
 
             bindDeferredShader(gDeferredBlurLightProgram, screen_target);
 
-			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+            mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
             deferred_light_target->bindTarget();
 
-			gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
+            gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);
 
-			{
-				LLGLDisable blend(GL_BLEND);
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
-				stop_glerror();
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				stop_glerror();
-			}
+            {
+                LLGLDisable   blend(GL_BLEND);
+                LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+                stop_glerror();
+                mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                stop_glerror();
+            }
             deferred_light_target->flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
-		}
+            unbindDeferredShader(gDeferredBlurLightProgram);
+        }
 
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
+        stop_glerror();
+        gGL.popMatrix();
+        stop_glerror();
+        gGL.matrixMode(LLRender::MM_MODELVIEW);
+        stop_glerror();
+        gGL.popMatrix();
+        stop_glerror();
 
         screen_target->bindTarget();
-		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
-		glClearColor(0,0,0,0);
+        // clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+        glClearColor(0, 0, 0, 0);
         screen_target->clear(GL_COLOR_BUFFER_BIT);
-		
-		if (RenderDeferredAtmospheric)
-		{ //apply sunlight contribution 
-            LLGLSLShader& soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
 
-			LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS);
-            bindDeferredShader(soften_shader);  
+        if (RenderDeferredAtmospheric)
+        {  // apply sunlight contribution
+            LLGLSLShader &soften_shader = LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram;
 
-            LLEnvironment& environment = LLEnvironment::instance();
+            LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS);
+            bindDeferredShader(soften_shader);
+
+            LLEnvironment &environment = LLEnvironment::instance();
             soften_shader.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
             soften_shader.uniform4fv(LLShaderMgr::LIGHTNORM, 1, environment.getClampedLightNorm().mV);
 
-			{
-				LLGLDepthTest depth(GL_FALSE);
-				LLGLDisable blend(GL_BLEND);
-				LLGLDisable test(GL_ALPHA_TEST);
+            {
+                LLGLDepthTest depth(GL_FALSE);
+                LLGLDisable   blend(GL_BLEND);
+                LLGLDisable   test(GL_ALPHA_TEST);
 
-				//full screen blit
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.pushMatrix();
-				gGL.loadIdentity();
+                // full screen blit
+                gGL.pushMatrix();
+                gGL.loadIdentity();
+                gGL.matrixMode(LLRender::MM_PROJECTION);
+                gGL.pushMatrix();
+                gGL.loadIdentity();
 
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
+                mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 
-			unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
-		}
+                gGL.popMatrix();
+                gGL.matrixMode(LLRender::MM_MODELVIEW);
+                gGL.popMatrix();
+            }
 
-		{ //render non-deferred geometry (fullbright, alpha, etc)
-			LLGLDisable blend(GL_BLEND);
-			LLGLDisable stencil(GL_STENCIL_TEST);
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
+            unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
+        }
 
-			gPipeline.pushRenderTypeMask();
-			
-			gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-										LLPipeline::RENDER_TYPE_CLOUDS,
-										LLPipeline::RENDER_TYPE_WL_SKY,
-										LLPipeline::END_RENDER_TYPES);
-								
-			
-			renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
-			gPipeline.popRenderTypeMask();
-		}
+        {  // render non-deferred geometry (fullbright, alpha, etc)
+            LLGLDisable blend(GL_BLEND);
+            LLGLDisable stencil(GL_STENCIL_TEST);
+            gGL.setSceneBlendType(LLRender::BT_ALPHA);
 
-		bool render_local = RenderLocalLights;
-				
-		if (render_local)
-		{
-			gGL.setSceneBlendType(LLRender::BT_ADD);
-			std::list<LLVector4> fullscreen_lights;
-			LLDrawable::drawable_list_t spot_lights;
-			LLDrawable::drawable_list_t fullscreen_spot_lights;
+            gPipeline.pushRenderTypeMask();
 
-			for (U32 i = 0; i < 2; i++)
-			{
-				mTargetShadowSpotLight[i] = NULL;
-			}
+            gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
+                                        LLPipeline::RENDER_TYPE_CLOUDS,
+                                        LLPipeline::RENDER_TYPE_WL_SKY,
+                                        LLPipeline::END_RENDER_TYPES);
 
-			std::list<LLVector4> light_colors;
+            renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
+            gPipeline.popRenderTypeMask();
+        }
 
-			LLVertexBuffer::unbind();
+        bool render_local = RenderLocalLights;
 
-			{
-				bindDeferredShader(gDeferredLightProgram);
-				
-				if (mCubeVB.isNull())
-				{
-					mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
-				}
+        if (render_local)
+        {
+            gGL.setSceneBlendType(LLRender::BT_ADD);
+            std::list<LLVector4>        fullscreen_lights;
+            LLDrawable::drawable_list_t spot_lights;
+            LLDrawable::drawable_list_t fullscreen_spot_lights;
 
-				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
-				{
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
-					if (!volume)
-					{
-						continue;
-					}
+            for (U32 i = 0; i < 2; i++)
+            {
+                mTargetShadowSpotLight[i] = NULL;
+            }
 
-					if (volume->isAttachment())
-					{
-						if (!sRenderAttachedLights)
-						{
-							continue;
-						}
-					}
+            std::list<LLVector4> light_colors;
+
+            LLVertexBuffer::unbind();
+
+            {
+                bindDeferredShader(gDeferredLightProgram);
+
+                if (mCubeVB.isNull())
+                {
+                    mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX, GL_STATIC_DRAW_ARB);
+                }
+
+                mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+
+                LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+                for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); iter != mLights.end(); ++iter)
+                {
+                    LLDrawable *drawablep = *iter;
+
+                    LLVOVolume *volume = drawablep->getVOVolume();
+                    if (!volume)
+                    {
+                        continue;
+                    }
+
+                    if (volume->isAttachment())
+                    {
+                        if (!sRenderAttachedLights)
+                        {
+                            continue;
+                        }
+                    }
 
                     const LLViewerObject *vobj = drawablep->getVObj();
                     if (vobj)
@@ -8756,325 +8720,324 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget* screen_target)
                         continue;
                     }
 
-					LLVector4a center;
-					center.load3(position.mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
+                    LLVector4a center;
+                    center.load3(position.mV);
+                    const F32 *c = center.getF32ptr();
+                    F32        s = volume->getLightRadius() * 1.5f;
 
-                    //send light color to shader in linear space
+                    // send light color to shader in linear space
                     LLColor3 col = volume->getLightLinearColor();
-					
-					if (col.magVecSquared() < 0.001f)
-					{
-						continue;
-					}
 
-					if (s <= 0.001f)
-					{
-						continue;
-					}
+                    if (col.magVecSquared() < 0.001f)
+                    {
+                        continue;
+                    }
 
-					LLVector4a sa;
-					sa.splat(s);
-					if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
-					{
-						continue;
-					}
+                    if (s <= 0.001f)
+                    {
+                        continue;
+                    }
 
-					sVisibleLightCount++;
-										
-					if (camera->getOrigin().mV[0] > c[0] + s + 0.2f ||
-						camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
-						camera->getOrigin().mV[1] > c[1] + s + 0.2f ||
-						camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
-						camera->getOrigin().mV[2] > c[2] + s + 0.2f ||
-						camera->getOrigin().mV[2] < c[2] - s - 0.2f)
-					{ //draw box if camera is outside box
-						if (render_local)
-						{
-							if (volume->isLightSpotlight())
-							{
-								drawablep->getVOVolume()->updateSpotLightPriority();
-								spot_lights.push_back(drawablep);
-								continue;
-							}
-							
-							LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS);
-							gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
-							gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
-							gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+                    LLVector4a sa;
+                    sa.splat(s);
+                    if (camera->AABBInFrustumNoFarClip(center, sa) == 0)
+                    {
+                        continue;
+                    }
+
+                    sVisibleLightCount++;
+
+                    if (camera->getOrigin().mV[0] > c[0] + s + 0.2f || camera->getOrigin().mV[0] < c[0] - s - 0.2f ||
+                        camera->getOrigin().mV[1] > c[1] + s + 0.2f || camera->getOrigin().mV[1] < c[1] - s - 0.2f ||
+                        camera->getOrigin().mV[2] > c[2] + s + 0.2f || camera->getOrigin().mV[2] < c[2] - s - 0.2f)
+                    {  // draw box if camera is outside box
+                        if (render_local)
+                        {
+                            if (volume->isLightSpotlight())
+                            {
+                                drawablep->getVOVolume()->updateSpotLightPriority();
+                                spot_lights.push_back(drawablep);
+                                continue;
+                            }
+
+                            LL_RECORD_BLOCK_TIME(FTM_LOCAL_LIGHTS);
+                            gDeferredLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
+                            gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
+                            gDeferredLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
                             gDeferredLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF));
-							gGL.syncMatrices();
-							
-							mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
-							stop_glerror();
-						}
-					}
-					else
-					{	
-						if (volume->isLightSpotlight())
-						{
-							drawablep->getVOVolume()->updateSpotLightPriority();
-							fullscreen_spot_lights.push_back(drawablep);
-							continue;
-						}
+                            gGL.syncMatrices();
 
-						glh::vec3f tc(c);
-						mat.mult_matrix_vec(tc);
-					
-						fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s));
+                            mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
+                            stop_glerror();
+                        }
+                    }
+                    else
+                    {
+                        if (volume->isLightSpotlight())
+                        {
+                            drawablep->getVOVolume()->updateSpotLightPriority();
+                            fullscreen_spot_lights.push_back(drawablep);
+                            continue;
+                        }
+
+                        glh::vec3f tc(c);
+                        mat.mult_matrix_vec(tc);
+
+                        fullscreen_lights.push_back(LLVector4(tc.v[0], tc.v[1], tc.v[2], s));
                         light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF)));
-					}
-				}
-				unbindDeferredShader(gDeferredLightProgram);
-			}
+                    }
+                }
 
-			if (!spot_lights.empty())
-			{
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				bindDeferredShader(gDeferredSpotLightProgram);
+                // Bookmark comment to allow searching for mSpecialRenderMode == 3 (avatar edit mode),
+                // prev site of appended deferred character light, removed by SL-13522 09/20
 
-				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+                unbindDeferredShader(gDeferredLightProgram);
+            }
 
-				gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+            if (!spot_lights.empty())
+            {
+                LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+                bindDeferredShader(gDeferredSpotLightProgram);
 
-				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
-				{
-					LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
+                mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 
-					LLVOVolume* volume = drawablep->getVOVolume();
+                gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
 
-					LLVector4a center;
-					center.load3(drawablep->getPositionAgent().mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
+                for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
+                {
+                    LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
+                    LLDrawable *drawablep = *iter;
 
-					sVisibleLightCount++;
+                    LLVOVolume *volume = drawablep->getVOVolume();
 
-					setupSpotLight(gDeferredSpotLightProgram, drawablep);
-					
-                    //send light color to shader in linear space
+                    LLVector4a center;
+                    center.load3(drawablep->getPositionAgent().mV);
+                    const F32 *c = center.getF32ptr();
+                    F32        s = volume->getLightRadius() * 1.5f;
+
+                    sVisibleLightCount++;
+
+                    setupSpotLight(gDeferredSpotLightProgram, drawablep);
+
+                    // send light color to shader in linear space
                     LLColor3 col = volume->getLightLinearColor();
-					
-					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
-					gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
-					gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+
+                    gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, c);
+                    gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
+                    gDeferredSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
                     gDeferredSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF));
-					gGL.syncMatrices();
-										
-					mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
-				}
-				gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredSpotLightProgram);
-			}
+                    gGL.syncMatrices();
 
-			//reset mDeferredVB to fullscreen triangle
-			mDeferredVB->getVertexStrider(vert);
-			vert[0].set(-1,1,0);
-			vert[1].set(-1,-3,0);
-			vert[2].set(3,1,0);
+                    mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
+                }
+                gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+                unbindDeferredShader(gDeferredSpotLightProgram);
+            }
 
-			{
-				LLGLDepthTest depth(GL_FALSE);
+            // reset mDeferredVB to fullscreen triangle
+            mDeferredVB->getVertexStrider(vert);
+            vert[0].set(-1, 1, 0);
+            vert[1].set(-1, -3, 0);
+            vert[2].set(3, 1, 0);
 
-				//full screen blit
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.pushMatrix();
-				gGL.loadIdentity();
+            {
+                LLGLDepthTest depth(GL_FALSE);
 
-				U32 count = 0;
+                // full screen blit
+                gGL.pushMatrix();
+                gGL.loadIdentity();
+                gGL.matrixMode(LLRender::MM_PROJECTION);
+                gGL.pushMatrix();
+                gGL.loadIdentity();
 
-				const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT;
-				LLVector4 light[max_count];
-				LLVector4 col[max_count];
+                U32 count = 0;
 
-				F32 far_z = 0.f;
+                const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT;
+                LLVector4 light[max_count];
+                LLVector4 col[max_count];
 
-				while (!fullscreen_lights.empty())
-				{
-					LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS);
-					light[count] = fullscreen_lights.front();
-					fullscreen_lights.pop_front();
-					col[count] = light_colors.front();
-					light_colors.pop_front();
-
-					far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z);
-					count++;
-					if (count == max_count || fullscreen_lights.empty())
-					{
-						U32 idx = count-1;
-						bindDeferredShader(gDeferredMultiLightProgram[idx]);
-						gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
-						gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
-						gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
-						gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
-						far_z = 0.f;
-						count = 0; 
-      mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-						mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-						unbindDeferredShader(gDeferredMultiLightProgram[idx]);
-					}
-				}
-				
-				bindDeferredShader(gDeferredMultiSpotLightProgram);
+                F32 far_z = 0.f;
 
-				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+                while (!fullscreen_lights.empty())
+                {
+                    LL_RECORD_BLOCK_TIME(FTM_FULLSCREEN_LIGHTS);
+                    light[count] = fullscreen_lights.front();
+                    fullscreen_lights.pop_front();
+                    col[count] = light_colors.front();
+                    light_colors.pop_front();
+
+                    far_z = llmin(light[count].mV[2] - light[count].mV[3], far_z);
+                    count++;
+                    if (count == max_count || fullscreen_lights.empty())
+                    {
+                        U32 idx = count - 1;
+                        bindDeferredShader(gDeferredMultiLightProgram[idx]);
+                        gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
+                        gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat *) light);
+                        gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat *) col);
+                        gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
+                        far_z = 0.f;
+                        count = 0;
+                        mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+                        mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                        unbindDeferredShader(gDeferredMultiLightProgram[idx]);
+                    }
+                }
 
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+                bindDeferredShader(gDeferredMultiSpotLightProgram);
 
-				for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
-				{
-					LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-					
-					LLVOVolume* volume = drawablep->getVOVolume();
+                gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+
+                mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 
-					LLVector3 center = drawablep->getPositionAgent();
-					F32* c = center.mV;
-                    F32 light_size_final = volume->getLightRadius()*1.5f;
-                    F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF);
+                for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
+                {
+                    LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
+                    LLDrawable *drawablep           = *iter;
+                    LLVOVolume *volume              = drawablep->getVOVolume();
+                    LLVector3   center              = drawablep->getPositionAgent();
+                    F32 *       c                   = center.mV;
+                    F32         light_size_final    = volume->getLightRadius() * 1.5f;
+                    F32         light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF);
 
-					sVisibleLightCount++;
+                    sVisibleLightCount++;
 
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+                    glh::vec3f tc(c);
+                    mat.mult_matrix_vec(tc);
 
-                    //send light color to shader in linear space
+                    setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
+
+                    // send light color to shader in linear space
                     LLColor3 col = volume->getLightLinearColor();
-					
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
+
+                    gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
                     gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final);
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
+                    gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
                     gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, light_falloff_final);
-					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				}
+                    mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+                }
 
-				gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredMultiSpotLightProgram);
+                gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
+                unbindDeferredShader(gDeferredMultiSpotLightProgram);
 
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
-		}
+                gGL.popMatrix();
+                gGL.matrixMode(LLRender::MM_MODELVIEW);
+                gGL.popMatrix();
+            }
+        }
 
-		gGL.setColorMask(true, true);
-	}
+        gGL.setColorMask(true, true);
+    }
 
     screen_target->flush();
 
-	//gamma correct lighting
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.pushMatrix();
-	gGL.loadIdentity();
+    // gamma correct lighting
+    gGL.matrixMode(LLRender::MM_PROJECTION);
+    gGL.pushMatrix();
+    gGL.loadIdentity();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.pushMatrix();
+    gGL.loadIdentity();
 
-	{
-		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
+    {
+        LLGLDepthTest depth(GL_FALSE, GL_FALSE);
 
-		LLVector2 tc1(0,0);
-        LLVector2 tc2((F32) screen_target->getWidth()*2,
-                  (F32) screen_target->getHeight()*2);
+        LLVector2 tc1(0, 0);
+        LLVector2 tc2((F32) screen_target->getWidth() * 2, (F32) screen_target->getHeight() * 2);
 
         screen_target->bindTarget();
-		// Apply gamma correction to the frame here.
-		gDeferredPostGammaCorrectProgram.bind();
-		//mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-		S32 channel = 0;
-        channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
-		if (channel > -1)
-		{
+        // Apply gamma correction to the frame here.
+        gDeferredPostGammaCorrectProgram.bind();
+        // mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+        S32 channel = 0;
+        channel     = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
+        if (channel > -1)
+        {
             screen_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
-		}
-		
+        }
+
         gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screen_target->getWidth(), screen_target->getHeight());
-		
-		F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
 
-		gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
-		
-		gGL.begin(LLRender::TRIANGLE_STRIP);
-		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-		gGL.vertex2f(-1,-1);
-		
-		gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-		gGL.vertex2f(-1,3);
-		
-		gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-		gGL.vertex2f(3,-1);
-		
-		gGL.end();
-		
+        F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+
+        gDeferredPostGammaCorrectProgram.uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+
+        gGL.begin(LLRender::TRIANGLE_STRIP);
+        gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+        gGL.vertex2f(-1, -1);
+
+        gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+        gGL.vertex2f(-1, 3);
+
+        gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+        gGL.vertex2f(3, -1);
+
+        gGL.end();
+
         gGL.getTexUnit(channel)->unbind(screen_target->getUsage());
-		gDeferredPostGammaCorrectProgram.unbind();
+        gDeferredPostGammaCorrectProgram.unbind();
         screen_target->flush();
-	}
+    }
 
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();	
+    gGL.matrixMode(LLRender::MM_PROJECTION);
+    gGL.popMatrix();
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
+    gGL.popMatrix();
 
     screen_target->bindTarget();
 
-	{ //render non-deferred geometry (alpha, fullbright, glow)
-		LLGLDisable blend(GL_BLEND);
-		LLGLDisable stencil(GL_STENCIL_TEST);
+    {  // render non-deferred geometry (alpha, fullbright, glow)
+        LLGLDisable blend(GL_BLEND);
+        LLGLDisable stencil(GL_STENCIL_TEST);
+
+        pushRenderTypeMask();
+        andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
+                          LLPipeline::RENDER_TYPE_FULLBRIGHT,
+                          LLPipeline::RENDER_TYPE_VOLUME,
+                          LLPipeline::RENDER_TYPE_GLOW,
+                          LLPipeline::RENDER_TYPE_BUMP,
+                          LLPipeline::RENDER_TYPE_PASS_SIMPLE,
+                          LLPipeline::RENDER_TYPE_PASS_ALPHA,
+                          LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
+                          LLPipeline::RENDER_TYPE_PASS_BUMP,
+                          LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
+                          LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
+                          LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
+                          LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
+                          LLPipeline::RENDER_TYPE_PASS_GLOW,
+                          LLPipeline::RENDER_TYPE_PASS_GRASS,
+                          LLPipeline::RENDER_TYPE_PASS_SHINY,
+                          LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
+                          LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
+                          LLPipeline::RENDER_TYPE_AVATAR,
+                          LLPipeline::RENDER_TYPE_CONTROL_AV,
+                          LLPipeline::RENDER_TYPE_ALPHA_MASK,
+                          LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
+                          END_RENDER_TYPES);
+
+        renderGeomPostDeferred(*LLViewerCamera::getInstance());
+        popRenderTypeMask();
+    }
 
-		pushRenderTypeMask();
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
-						 LLPipeline::RENDER_TYPE_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_VOLUME,
-						 LLPipeline::RENDER_TYPE_GLOW,
-						 LLPipeline::RENDER_TYPE_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_SIMPLE,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA,
-						 LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_GLOW,
-						 LLPipeline::RENDER_TYPE_PASS_GRASS,
-						 LLPipeline::RENDER_TYPE_PASS_SHINY,
-						 LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
-						 LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
-						 LLPipeline::RENDER_TYPE_AVATAR,
-						 LLPipeline::RENDER_TYPE_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
-						 END_RENDER_TYPES);
-		
-		renderGeomPostDeferred(*LLViewerCamera::getInstance());
-		popRenderTypeMask();
-	}
+    {
+        // render highlights, etc.
+        renderHighlights();
+        mHighlightFaces.clear();
 
-	{
-		//render highlights, etc.
-		renderHighlights();
-		mHighlightFaces.clear();
+        renderDebug();
 
-		renderDebug();
+        LLVertexBuffer::unbind();
 
-		LLVertexBuffer::unbind();
-
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-			// Render debugging beacons.
-			gObjectList.renderObjectBeacons();
-			gObjectList.resetObjectBeacons();
+        if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+        {
+            // Render debugging beacons.
+            gObjectList.renderObjectBeacons();
+            gObjectList.resetObjectBeacons();
             gSky.addSunMoonBeacons();
-		}
-	}
+        }
+    }
 
-	screen_target->flush();                        
+    screen_target->flush();
 }
 
 void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
@@ -9291,7 +9254,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 		
 		gPipeline.pushRenderTypeMask();
 
-        glh::matrix4f projection = get_current_projection();
+        glh::matrix4f saved_modelview  = get_current_modelview();
+        glh::matrix4f saved_projection = get_current_projection();
 		glh::matrix4f mat;
 
         S32 detail = RenderReflectionDetail;
@@ -9330,8 +9294,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			//disable occlusion culling for reflection map for now
 			LLPipeline::sUseOcclusion = 0;
 
-        glh::matrix4f current = get_current_modelview();
-
         if (!camera_is_underwater)
         {   //generate planar reflection map
 
@@ -9340,15 +9302,10 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
             gGL.matrixMode(LLRender::MM_MODELVIEW);
             gGL.pushMatrix();
 
-            glh::matrix4f mat;
-            camera.getOpenGLTransform(mat.m);
+            mat.set_scale(glh::vec3f(1, 1, -1));
+            mat.set_translate(glh::vec3f(0,0,water_height*2.f));
+            mat = saved_modelview * mat;
 
-            glh::matrix4f scal;
-            scal.set_scale(glh::vec3f(1, 1, -1));
-            mat = scal * mat;
-
-            // convert from CFR to OGL coord sys...
-            mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
 
             mReflectionModelView = mat;
 
@@ -9357,6 +9314,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
 			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
 
+            glh::vec3f    origin(0, 0, 0);
+            glh::matrix4f inv_mat = mat.inverse();
+            inv_mat.mult_matrix_vec(origin);
+
+            camera.setOrigin(origin.v);
+
 			glCullFace(GL_FRONT);
 
 			if (LLDrawPoolWater::sNeedsReflectionUpdate)
@@ -9401,7 +9364,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
 						if (detail < 3)
 						{
-							clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+                            clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, END_RENDER_TYPES);
 							if (detail < 2)
 							{
 								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
@@ -9409,7 +9372,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 						}
 					}
 
-                    LLGLUserClipPlane clip_plane(plane, mReflectionModelView, projection);
+                    LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection);
 					LLGLDisable cull(GL_CULL_FACE);
                     updateCull(camera, mReflectedObjects, -water_clip, &plane);
                     stateSort(camera, mReflectedObjects);
@@ -9423,7 +9386,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
             gGL.matrixMode(LLRender::MM_MODELVIEW);
 			gGL.popMatrix();
             
-            set_current_modelview(current);         
+            set_current_modelview(saved_modelview);
 		}
 
         //LLPipeline::sUseOcclusion = occlusion;
@@ -9479,7 +9442,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
                 //clip out geometry on the same side of water as the camera w/ enough margin to not include the water geo itself,
                 // but not so much as to clip out parts of avatars that should be seen under the water in the distortion map
                 LLPlane plane(-pnorm, water_dist);
-                LLGLUserClipPlane clip_plane(plane, current, projection);
+                LLGLUserClipPlane clip_plane(plane, saved_modelview, saved_projection);
 
 				gGL.setColorMask(true, true);
 				mWaterDis.clear();
@@ -10116,6 +10079,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 					LLPipeline::RENDER_TYPE_BUMP,
 					LLPipeline::RENDER_TYPE_VOLUME,
 					LLPipeline::RENDER_TYPE_AVATAR,
+					LLPipeline::RENDER_TYPE_CONTROL_AV,
 					LLPipeline::RENDER_TYPE_TREE, 
 					LLPipeline::RENDER_TYPE_TERRAIN,
 					LLPipeline::RENDER_TYPE_WATER,
@@ -10909,7 +10873,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 	
 	if (visually_muted || too_complex)
 	{
-		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);
+		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR,
+							LLPipeline::RENDER_TYPE_CONTROL_AV,
+							END_RENDER_TYPES);
 	}
 	else
 	{
@@ -10932,6 +10898,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 						LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
 						LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
 			LLPipeline::RENDER_TYPE_AVATAR,
+			LLPipeline::RENDER_TYPE_CONTROL_AV,
 			LLPipeline::RENDER_TYPE_ALPHA_MASK,
 			LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
 			LLPipeline::RENDER_TYPE_INVISIBLE,
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 68ce3fe88dea8dd719ecc65df0e930cf4898a75a..600bdd9d06dc1aba6baba86a462f9fca789267ea 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -139,7 +139,7 @@ class LLPipeline
 	void resetVertexBuffers(LLDrawable* drawable);
 	void generateImpostor(LLVOAvatar* avatar);
 	void bindScreenToTexture();
-	void renderBloom(bool for_snapshot, F32 zoom_factor = 1.f, int subfield = 0);
+	void renderFinalize();
 
 	void init();
 	void cleanup();
@@ -453,6 +453,7 @@ class LLPipeline
 		RENDER_TYPE_BUMP						= LLDrawPool::POOL_BUMP,
 		RENDER_TYPE_MATERIALS					= LLDrawPool::POOL_MATERIALS,
 		RENDER_TYPE_AVATAR						= LLDrawPool::POOL_AVATAR,
+		RENDER_TYPE_CONTROL_AV					= LLDrawPool::POOL_CONTROL_AV, // Animesh
 		RENDER_TYPE_TREE						= LLDrawPool::POOL_TREE,
 		RENDER_TYPE_INVISIBLE					= LLDrawPool::POOL_INVISIBLE,
 		RENDER_TYPE_VOIDWATER					= LLDrawPool::POOL_VOIDWATER,
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 873b95926b7845fa650e7caec9ac5f1961b9c571..5fa1847d1b840941e54557745c34542d3056f5fb 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1732,6 +1732,16 @@ function="World.EnvPreset"
                  function="Advanced.ToggleRenderType"
                  parameter="character" />
             </menu_item_check>
+            <menu_item_check
+             label="Animeshes"
+             name="Rendering Type Control Avatar">
+                <menu_item_check.on_check
+                 function="Advanced.CheckRenderType"
+                 parameter="controlAV" />
+                <menu_item_check.on_click
+                 function="Advanced.ToggleRenderType"
+                 parameter="controlAV" />
+            </menu_item_check>
             <menu_item_check
              label="Surface Patch"
              name="Rendering Type Surface Patch"
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
index bec793bbeeeff4bd0deef6da4806408b16da47d4..6f82a0efa1a42fa21ca3162c91b9864c15d03fe6 100644
--- a/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -203,10 +203,10 @@
                         Ice Level:
                     </text>
                     <slider
-                            decimal_digits="1"
+                            decimal_digits="3"
                             follows="left|top"
                             height="14"
-                            increment="0.1"
+                            increment="0.001"
                             initial_value="0"
                             left_delta="5"
                             top_delta="20"