diff --git a/doc/contributions.txt b/doc/contributions.txt
index d401620b2c33ab0997fcadcc813db9be312fd5e6..36b65ae84de7252efca710caf5784eedc56b52f3 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -485,6 +485,16 @@ Geenz Spad
 	STORM-1900
 	STORM-1905
 	NORSPEC-229
+	BUG-226611
+	BUG-226617
+	BUG-226618
+	BUG-226646
+	BUG-226647
+	BUG-226648
+	OPEN-339
+	BUG-226620
+	OPEN-340
+	OPEN-343
 Gene Frostbite
 GeneJ Composer
 Geneko Nemeth
@@ -1074,6 +1084,7 @@ Nicky Dasmijn
 	SL-10291
 	SL-10293
 	SL-11061
+    SL-11072
 Nicky Perian
 	OPEN-1
 	STORM-1087
@@ -1325,6 +1336,7 @@ Sovereign Engineer
     STORM-2148
     MAINT-7343
     SL-11079
+    OPEN-343
 SpacedOut Frye
 	VWR-34
 	VWR-45
diff --git a/indra/cmake/Atmosphere.cmake b/indra/cmake/Atmosphere.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..9c14df2a11cc8e6167c76f4d846327d4f842d063
--- /dev/null
+++ b/indra/cmake/Atmosphere.cmake
@@ -0,0 +1,5 @@
+# -*- cmake -*-
+include(Prebuilt)
+use_prebuilt_binary(libatmosphere)
+set(LIBATMOSPHERE_LIBRARIES atmosphere)
+set(LIBATMOSPHERE_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/atmosphere)
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index e60037b7399dbfe16881929a9325cabae3618fda..f7fbb6fda15660cd8aefaf3dd3e8dbaf09508ac8 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -81,8 +81,8 @@ class LLAvatarBoneInfo
 	LLAvatarBoneInfo() : mIsJoint(FALSE) {}
 	~LLAvatarBoneInfo()
 	{
-		std::for_each(mChildList.begin(), mChildList.end(), DeletePointer());
-		mChildList.clear();
+		std::for_each(mChildren.begin(), mChildren.end(), DeletePointer());
+		mChildren.clear();
 	}
 	BOOL parseXml(LLXmlTreeNode* node);
 	
@@ -96,8 +96,8 @@ class LLAvatarBoneInfo
 	LLVector3 mRot;
 	LLVector3 mScale;
 	LLVector3 mPivot;
-	typedef std::vector<LLAvatarBoneInfo*> child_list_t;
-	child_list_t mChildList;
+	typedef std::vector<LLAvatarBoneInfo*> bones_t;
+	bones_t mChildren;
 };
 
 //------------------------------------------------------------------------
@@ -679,8 +679,8 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
 
 
 	// setup children
-	LLAvatarBoneInfo::child_list_t::const_iterator iter;
-	for (iter = info->mChildList.begin(); iter != info->mChildList.end(); ++iter)
+	LLAvatarBoneInfo::bones_t::const_iterator iter;
+	for (iter = info->mChildren.begin(); iter != info->mChildren.end(); ++iter)
 	{
 		LLAvatarBoneInfo *child_info = *iter;
 		if (!setupBone(child_info, joint, volume_num, joint_num))
@@ -1684,7 +1684,7 @@ BOOL LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
 			delete child_info;
 			return FALSE;
 		}
-		mChildList.push_back(child_info);
+		mChildren.push_back(child_info);
 	}
 	return TRUE;
 }
@@ -1743,10 +1743,9 @@ void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info)
         mJointAliasMap[*i] = bone_name;
     }
 
-    LLAvatarBoneInfo::child_list_t::const_iterator iter;
-    for (iter = bone_info->mChildList.begin(); iter != bone_info->mChildList.end(); ++iter)
+    for (LLAvatarBoneInfo* bone : bone_info->mChildren)
     {
-        makeJointAliases( *iter );
+        makeJointAliases(bone);
     }
 }
 
diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp
index 29642be099a3d9c26c3fed801f332cf892ee948d..80b3e42b52904b7a32d2b63097d24b441a3cc7d8 100644
--- a/indra/llappearance/llavatarjoint.cpp
+++ b/indra/llappearance/llavatarjoint.cpp
@@ -100,7 +100,7 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
 	//----------------------------------------------------------------
 	if (recursive)
 	{
-		for (child_list_t::iterator iter = mChildren.begin();
+		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
 			LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
@@ -118,10 +118,10 @@ void LLAvatarJoint::setSkeletonComponents( U32 comp, BOOL recursive )
 	mComponents = comp;
 	if (recursive)
 	{
-		for (child_list_t::iterator iter = mChildren.begin();
+		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
-			LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+			LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 			joint->setSkeletonComponents(comp, recursive);
 		}
 	}
@@ -133,7 +133,7 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
 
 	if (recursive)
 	{
-		for (child_list_t::iterator iter = mChildren.begin();
+		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
 			LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
@@ -144,27 +144,27 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
 
 void LLAvatarJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area)
 {
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 		joint->updateFaceSizes(num_vertices, num_indices, pixel_area);
 	}
 }
 
 void LLAvatarJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind, bool terse_update)
 {
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 		joint->updateFaceData(face, pixel_area, damp_wind, terse_update);
 	}
 }
 
 void LLAvatarJoint::updateJointGeometry()
 {
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
 		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
@@ -178,10 +178,10 @@ BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
 	BOOL lod_changed = FALSE;
 	BOOL found_lod = FALSE;
 
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 		F32 jointLOD = joint->getLOD();
 		
 		if (found_lod || jointLOD == DEFAULT_AVATAR_JOINT_LOD)
@@ -207,10 +207,10 @@ BOOL LLAvatarJoint::updateLOD(F32 pixel_area, BOOL activate)
 
 void LLAvatarJoint::dump()
 {
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 		joint->dump();
 	}
 }
diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp
index 7ca0928171f55ab33a00832b9ac8948baf84f715..0a23b1fda304e4223679081526839aece8f8b6d7 100644
--- a/indra/llappearance/llavatarjointmesh.cpp
+++ b/indra/llappearance/llavatarjointmesh.cpp
@@ -379,7 +379,7 @@ void LLAvatarJointMesh::setupJoint(LLAvatarJoint* current_joint)
 	}
 
 	// depth-first traversal
-	for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin();
+	for (LLJoint::joints_t::iterator iter = current_joint->mChildren.begin();
 		 iter != current_joint->mChildren.end(); ++iter)
 	{
 		LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
diff --git a/indra/llappearance/lldriverparam.cpp b/indra/llappearance/lldriverparam.cpp
index e5e502b158fd72b3d7e3bc4bfce10bc9635d1da6..05d26fbe7aa66230891d7b51511b5280c0cc2032 100644
--- a/indra/llappearance/lldriverparam.cpp
+++ b/indra/llappearance/lldriverparam.cpp
@@ -614,7 +614,7 @@ void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight)
 		mAvatarAppearance->isValid() &&
 		driven->mParam->getCrossWearable())
 	{
-		LLWearable* wearable = dynamic_cast<LLWearable*> (mWearablep);
+		LLWearable* wearable = mWearablep;
 		if (mAvatarAppearance->getWearableData()->isOnTop(wearable))
 		{
 			use_self = true;
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index 2cb4c65d7c49a197f1e871397c010a6038c6265f..ce7010984a0c74995873c02ce120116889c2141d 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -816,8 +816,8 @@ void LLPolyVertexMask::generateMask(U8 *maskTextureData, S32 width, S32 height,
 		U32 s = llclamp((U32)(uvCoords.mV[VX] * (F32)(width - 1)), (U32)0, (U32)width - 1);
 		U32 t = llclamp((U32)(uvCoords.mV[VY] * (F32)(height - 1)), (U32)0, (U32)height - 1);
 		
-		mWeights[index] = ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f;
-		
+		mWeights[index] = maskTextureData ? ((F32) maskTextureData[((t * width + s) * num_components) + (num_components - 1)]) / 255.f : 0.0f;
+
 		if (invert) 
 		{
 			mWeights[index] = 1.f - mWeights[index];
diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp
index 5b77a7433ac3d50e1f8bb96620f7fa7d824a7c6c..ae38c25dbf1f316d7fa7f44e1e0047d39e217360 100644
--- a/indra/llappearance/llpolyskeletaldistortion.cpp
+++ b/indra/llappearance/llpolyskeletaldistortion.cpp
@@ -160,7 +160,7 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info)
         mJointScales[joint] = bone_info->mScaleDeformation;
 
         // apply to children that need to inherit it
-        for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+        for (LLJoint::joints_t::iterator iter = joint->mChildren.begin();
              iter != joint->mChildren.end(); ++iter)
         {
             LLAvatarJoint* child_joint = (LLAvatarJoint*)(*iter);
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index 186986bf9cb0c026df701c98d54e5c99efa21db8..c90b11ae7129a36090246c311036a093e9e8d48d 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -137,7 +137,7 @@ void LLTexLayerSetBuffer::postRenderTexLayerSet(BOOL success)
 	popProjection();
 }
 
-BOOL LLTexLayerSetBuffer::renderTexLayerSet()
+BOOL LLTexLayerSetBuffer::renderTexLayerSet(LLRenderTarget* bound_target)
 {
 	// Default color mask for tex layer render
 	gGL.setColorMask(true, true);
@@ -161,7 +161,7 @@ BOOL LLTexLayerSetBuffer::renderTexLayerSet()
 	// Composite the color data
 	LLGLSUIDefault gls_ui;
 	success &= mTexLayerSet->render( getCompositeOriginX(), getCompositeOriginY(), 
-									 getCompositeWidth(), getCompositeHeight() );
+									 getCompositeWidth(), getCompositeHeight(), bound_target );
 	gGL.flush();
 
 	midRenderTexLayerSet(success);
@@ -375,7 +375,7 @@ void LLTexLayerSet::deleteCaches()
 }
 
 
-BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
+BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target )
 {
 	BOOL success = TRUE;
 	mIsVisible = TRUE;
@@ -427,12 +427,12 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
 			if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
 			{
 				gGL.flush();
-				success &= layer->render(x, y, width, height);
+				success &= layer->render(x, y, width, height, bound_target);
 				gGL.flush();
 			}
 		}
 		
-		renderAlphaMaskTextures(x, y, width, height, false);
+		renderAlphaMaskTextures(x, y, width, height, bound_target, false);
 	
 		stop_glerror();
 	}
@@ -523,7 +523,7 @@ const LLTexLayerSetBuffer* LLTexLayerSet::getComposite() const
 }
 
 static LLTrace::BlockTimerStatHandle FTM_GATHER_MORPH_MASK_ALPHA("gatherMorphMaskAlpha");
-void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height)
+void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target)
 {
 	LL_RECORD_BLOCK_TIME(FTM_GATHER_MORPH_MASK_ALPHA);
 	memset(data, 255, width * height);
@@ -531,15 +531,15 @@ void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S
 	for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
 	{
 		LLTexLayerInterface* layer = *iter;
-		layer->gatherAlphaMasks(data, origin_x, origin_y, width, height);
+		layer->gatherAlphaMasks(data, origin_x, origin_y, width, height, bound_target);
 	}
 	
 	// Set alpha back to that of our alpha masks.
-	renderAlphaMaskTextures(origin_x, origin_y, width, height, true);
+	renderAlphaMaskTextures(origin_x, origin_y, width, height, bound_target, true);
 }
 
 static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_TEXTURES("renderAlphaMaskTextures");
-void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear)
+void LLTexLayerSet::renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target, bool forceClear)
 {
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_TEXTURES);
 	const LLTexLayerSetInfo *info = getInfo();
@@ -1065,7 +1065,7 @@ LLTexLayer::~LLTexLayer()
 		 iter != mAlphaCache.end(); iter++ )
 	{
 		U8* alpha_data = iter->second;
-		delete [] alpha_data;
+		ll_aligned_free_32(alpha_data);
 	}
 
 }
@@ -1124,7 +1124,7 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
 	}
 }
 
-BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
+BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
 {
 	LLGLEnable color_mat(GL_COLOR_MATERIAL);
 	// *TODO: Is this correct?
@@ -1185,7 +1185,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
 		}//*/
 
 		const bool force_render = true;
-		renderMorphMasks(x, y, width, height, net_color, force_render);
+		renderMorphMasks(x, y, width, height, net_color, bound_target, force_render);
 		alpha_mask_specified = TRUE;
 		gGL.flush();
 		gGL.blendFunc(LLRender::BF_DEST_ALPHA, LLRender::BF_ONE_MINUS_DEST_ALPHA);
@@ -1428,13 +1428,13 @@ BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
 	return success;
 }
 
-/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
+/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
 {
-	addAlphaMask(data, originX, originY, width, height);
+	addAlphaMask(data, originX, originY, width, height, bound_target);
 }
 
 static LLTrace::BlockTimerStatHandle FTM_RENDER_MORPH_MASKS("renderMorphMasks");
-void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render)
+void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render)
 {
 	if (!force_render && !hasMorph())
 	{
@@ -1572,17 +1572,64 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
 			{
 				alpha_cache_t::iterator iter2 = mAlphaCache.begin(); // arbitrarily grab the first entry
 				alpha_data = iter2->second;
-				delete [] alpha_data;
+                ll_aligned_free_32(alpha_data);
 				mAlphaCache.erase(iter2);
 			}
-			alpha_data = new U8[width * height];
-			mAlphaCache[cache_index] = alpha_data;
-    
-			// nSight doesn't support use of glReadPixels
-			if (!LLRender::sNsightDebugSupport)
+			
+            // GPUs tend to be very uptight about memory alignment as the DMA used to convey
+            // said data to the card works better when well-aligned so plain old default-aligned heap mem is a no-no
+            //new U8[width * height];
+            size_t bytes_per_pixel = 1; // unsigned byte alpha channel only...
+            size_t row_size        = (width + 3) & ~0x3; // OpenGL 4-byte row align (even for things < 4 bpp...)
+            size_t pixels          = (row_size * height);
+            size_t mem_size        = pixels * bytes_per_pixel;
+
+            alpha_data = (U8*)ll_aligned_malloc_32(mem_size);
+
+            bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels
+
+			if (!skip_readback)
 			{
-			glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
-		}
+                if (gGLManager.mIsIntel)
+                { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO
+                  // returning only the alpha portion without locking up downstream 
+                    U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA
+
+                    if (bound_target)
+                    {
+                        gGL.getTexUnit(0)->bind(bound_target);
+                    }
+                    else
+                    {
+                        gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, 0);
+                    }
+
+                    glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
+
+                    U8* alpha_cursor = alpha_data;
+                    U8* pixel        = temp;
+                    for (int i = 0; i < pixels; i++)
+                    {
+                        *alpha_cursor++ = pixel[3];
+                        pixel += 4;
+                    }
+
+                    gGL.getTexUnit(0)->disable();
+
+                    ll_aligned_free_32(temp);
+                }
+                else
+                { // platforms with working drivers...
+				    glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);                
+                }
+			}
+            else
+            {
+                ll_aligned_free_32(alpha_data);
+                alpha_data = nullptr;
+            }
+
+            mAlphaCache[cache_index] = alpha_data;
 		}
 		
 		getTexLayerSet()->getAvatarAppearance()->dirtyMesh();
@@ -1593,7 +1640,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
 }
 
 static LLTrace::BlockTimerStatHandle FTM_ADD_ALPHA_MASK("addAlphaMask");
-void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
+void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
 {
 	LL_RECORD_BLOCK_TIME(FTM_ADD_ALPHA_MASK);
 	S32 size = width * height;
@@ -1605,7 +1652,7 @@ void LLTexLayer::addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32
 		// TODO: eliminate need for layer morph mask valid flag
 		invalidateMorphMasks();
 		const bool force_render = false;
-		renderMorphMasks(originX, originY, width, height, net_color, force_render);
+		renderMorphMasks(originX, originY, width, height, net_color, bound_target, force_render);
 		alphaData = getAlphaData();
 	}
 	if (alphaData)
@@ -1739,7 +1786,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
 	return layer;
 }
 
-/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height)
+/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target)
 {
 	if(!mInfo)
 	{
@@ -1766,7 +1813,7 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
 		{
 			wearable->writeToAvatar(mAvatarAppearance);
 			layer->setLTO(lto);
-			success &= layer->render(x,y,width,height);
+			success &= layer->render(x, y, width, height, bound_target);
 		}
 	}
 
@@ -1788,14 +1835,14 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
 	return success;
 }
 
-/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
+/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target)
 {
 	U32 num_wearables = updateWearableCache();
 	U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
 	LLTexLayer *layer = getLayer(i);
 	if (layer)
 	{
-		layer->addAlphaMask(data, originX, originY, width, height);
+		layer->addAlphaMask(data, originX, originY, width, height, bound_target);
 	}
 }
 
diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h
index 9318b23fd199b32841d84a7192748634dcf282e2..6a5040cf0ba69009a22afcbcd4541c65f65513a2 100644
--- a/indra/llappearance/lltexlayer.h
+++ b/indra/llappearance/lltexlayer.h
@@ -65,7 +65,7 @@ class LLTexLayerInterface
 	LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
 	virtual ~LLTexLayerInterface() {}
 
-	virtual BOOL			render(S32 x, S32 y, S32 width, S32 height) = 0;
+	virtual BOOL			render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
 	virtual void			deleteCaches() = 0;
 	virtual BOOL			blendAlphaTexture(S32 x, S32 y, S32 width, S32 height) = 0;
 	virtual BOOL			isInvisibleAlphaMask() const = 0;
@@ -85,7 +85,7 @@ class LLTexLayerInterface
 	BOOL					isMorphValid() const		{ return mMorphMasksValid; }
 
 	void					requestUpdate();
-	virtual void			gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height) = 0;
+	virtual void			gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target) = 0;
 	BOOL					hasAlphaParams() const 		{ return !mParamAlphaList.empty(); }
 
 	ERenderPass				getRenderPass() const;
@@ -121,10 +121,10 @@ class LLTexLayerTemplate : public LLTexLayerInterface
 	LLTexLayerTemplate(LLTexLayerSet* const layer_set, LLAvatarAppearance* const appearance);
 	LLTexLayerTemplate(const LLTexLayerTemplate &layer);
 	/*virtual*/ ~LLTexLayerTemplate();
-	/*virtual*/ BOOL		render(S32 x, S32 y, S32 width, S32 height);
+	/*virtual*/ BOOL		render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
 	/*virtual*/ BOOL		setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
 	/*virtual*/ BOOL		blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
-	/*virtual*/ void		gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
+	/*virtual*/ void		gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
 	/*virtual*/ void		setHasMorph(BOOL newval);
 	/*virtual*/ void		deleteCaches();
 	/*virtual*/ BOOL		isInvisibleAlphaMask() const;
@@ -152,16 +152,16 @@ class LLTexLayer : public LLTexLayerInterface
 	/*virtual*/ ~LLTexLayer();
 
 	/*virtual*/ BOOL		setInfo(const LLTexLayerInfo *info, LLWearable* wearable); // This sets mInfo and calls initialization functions
-	/*virtual*/ BOOL		render(S32 x, S32 y, S32 width, S32 height);
+	/*virtual*/ BOOL		render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target);
 
 	/*virtual*/ void		deleteCaches();
 	const U8*				getAlphaData() const;
 
 	BOOL					findNetColor(LLColor4* color) const;
 	/*virtual*/ BOOL		blendAlphaTexture(S32 x, S32 y, S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
-	/*virtual*/ void		gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
-	void					renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, bool force_render);
-	void					addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height);
+	/*virtual*/ void		gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
+	void					renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, LLRenderTarget* bound_target, bool force_render);
+	void					addAlphaMask(U8 *data, S32 originX, S32 originY, S32 width, S32 height, LLRenderTarget* bound_target);
 	/*virtual*/ BOOL		isInvisibleAlphaMask() const;
 
 	void					setLTO(LLLocalTextureObject *lto) 	{ mLocalTextureObject = lto; }
@@ -194,13 +194,13 @@ class LLTexLayerSet
 	const LLTexLayerSetBuffer* 	getComposite() const; // Do not create one if it doesn't exist.
 	virtual void				createComposite() = 0;
 	void						destroyComposite();
-	void						gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height);
+	void						gatherMorphMaskAlpha(U8 *data, S32 origin_x, S32 origin_y, S32 width, S32 height, LLRenderTarget* bound_target);
 
 	const LLTexLayerSetInfo* 	getInfo() const 			{ return mInfo; }
 	BOOL						setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
 
-	BOOL						render(S32 x, S32 y, S32 width, S32 height);
-	void						renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, bool forceClear = false);
+	BOOL						render(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr);
+	void						renderAlphaMaskTextures(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* bound_target = nullptr, bool forceClear = false);
 
 	BOOL						isBodyRegion(const std::string& region) const;
 	void						applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
@@ -282,7 +282,7 @@ class LLTexLayerSetBuffer : public virtual LLRefCount
 	virtual S32				getCompositeOriginY() const = 0;
 	virtual S32				getCompositeWidth() const = 0;
 	virtual S32				getCompositeHeight() const = 0;
-	BOOL					renderTexLayerSet();
+	BOOL					renderTexLayerSet(LLRenderTarget* bound_target);
 
 	LLTexLayerSet* const	mTexLayerSet;
 };
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
index dc02b5e2257b4e6e7bb27333c506fc8eda8a04ec..d6ff28e2d26c09fb3e54b50b5baf072125bbdcfa 100644
--- a/indra/llappearance/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -181,6 +181,6 @@ BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
 // static
 LLWearableType::EType LLWearableType::inventoryFlagsToWearableType(U32 flags)
 {
-    return  (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK);
+    return  (LLWearableType::EType)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK);
 }
 
diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h
index 5fe969822a9e64027da017d7a965b9dc3daec777..148ccafdd8907f34e64d62be9ab0eacfab96fc3b 100644
--- a/indra/llappearance/llwearabletype.h
+++ b/indra/llappearance/llwearabletype.h
@@ -31,16 +31,7 @@
 #include "lldictionary.h"
 #include "llinventorytype.h"
 #include "llsingleton.h"
-
-class LLTranslationBridge
-{
-public:
-	// clang needs this to be happy
-	virtual ~LLTranslationBridge() {}
-
-	virtual std::string getString(const std::string &xml_desc) = 0;
-};
-
+#include "llinvtranslationbrdg.h"
 
 class LLWearableType : public LLParamSingleton<LLWearableType>
 {
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 4df975ecc5d425ec4e0af8387b9efd2b9290a121..b764ef0c7e1f206abe615efe2f17e4c7418de877 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -252,7 +252,7 @@ void LLCharacter::dumpCharacter( LLJoint* joint )
 	LL_INFOS() << "DEBUG: " << joint->getName() << " (" << (joint->getParent()?joint->getParent()->getName():std::string("ROOT")) << ")" << LL_ENDL;
 
 	// recurse
-	for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+	for (LLJoint::joints_t::iterator iter = joint->mChildren.begin();
 		 iter != joint->mChildren.end(); ++iter)
 	{
 		LLJoint* child_joint = *iter;
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index e2f512f86e0e57722cc6cc799eefccf07bbd1861..a685df592563bcd05f4b144d463508cb7dcb2baa 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -209,7 +209,7 @@ void LLJoint::touch(U32 flags)
 			child_flags |= POSITION_DIRTY;
 		}
 
-		for (child_list_t::iterator iter = mChildren.begin();
+		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
 			LLJoint* joint = *iter;
@@ -251,7 +251,7 @@ LLJoint *LLJoint::findJoint( const std::string &name )
 	if (name == getName())
 		return this;
 
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
 		LLJoint* joint = *iter;
@@ -286,7 +286,7 @@ void LLJoint::addChild(LLJoint* joint)
 //--------------------------------------------------------------------
 void LLJoint::removeChild(LLJoint* joint)
 {
-	child_list_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
+	joints_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
 	if (iter != mChildren.end())
 	{
 		mChildren.erase(iter);
@@ -303,16 +303,17 @@ void LLJoint::removeChild(LLJoint* joint)
 //--------------------------------------------------------------------
 void LLJoint::removeAllChildren()
 {
-	for (child_list_t::iterator iter = mChildren.begin();
-		 iter != mChildren.end();)
+	for (LLJoint* joint : mChildren)
 	{
-		child_list_t::iterator curiter = iter++;
-		LLJoint* joint = *curiter;
-		mChildren.erase(curiter);
-		joint->mXform.setParent(NULL);
-		joint->mParent = NULL;
-		joint->touch();
+		if (joint)
+        {
+		    joint->mXform.setParent(NULL);
+		    joint->mParent = NULL;
+		    joint->touch();
+            //delete joint;
+        }
 	}
+    mChildren.clear();
 }
 
 
@@ -985,7 +986,7 @@ void LLJoint::updateWorldMatrixChildren()
 	{
 		updateWorldMatrix();
 	}
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
 		LLJoint* joint = *iter;
@@ -1031,7 +1032,7 @@ void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
 {
 	LLVector3 main_axis(1.f, 0.f, 0.f);
 
-	for (child_list_t::iterator iter = mChildren.begin();
+	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
 		LLJoint* joint = *iter;
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 8112d246f28b89d3b2b7a0f11daf44fb35a1cf89..aa997a4cf7a48eb78a3ad69ded536cde95dc0a9e 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -139,8 +139,8 @@ class LLJoint
 	S32				mJointNum;
 
 	// child joints
-	typedef std::list<LLJoint*> child_list_t;
-	child_list_t mChildren;
+	typedef std::vector<LLJoint*> joints_t;
+	joints_t mChildren;
 
 	// debug statics
 	static S32		sNumTouches;
diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp
index 5d323ed5d69617897e91e351cfc3b631606dfdad..cde38c8091d9a82c6813704bfc057bf5591f1280 100644
--- a/indra/llcharacter/llkeyframemotion.cpp
+++ b/indra/llcharacter/llkeyframemotion.cpp
@@ -2321,7 +2321,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
 	LLCharacter* character = *char_iter;
 
 	// look for an existing instance of this motion
-	LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
+	LLKeyframeMotion* motionp = static_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
 	if (motionp)
 	{
 		if (0 == status)
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index e13176e8facdb3bdb716016a98d636992d3a71de..1b48e4daf3a911c94867d11a31587d79a7209083 100644
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -64,7 +64,6 @@ const LLUUID IMG_ALPHA_GRAD				("e97cf410-8e61-7005-ec06-629eba4cd1fb"); // VIEW
 const LLUUID IMG_ALPHA_GRAD_2D			("38b86f85-2575-52a9-a531-23108d8da837"); // VIEWER
 const LLUUID IMG_TRANSPARENT			("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); // VIEWER
 
-const LLUUID IMG_BLOOM1	  			    ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
 const LLUUID TERRAIN_DIRT_DETAIL		("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
 const LLUUID TERRAIN_GRASS_DETAIL		("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
 const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 0fbf4b966b2becc9e4a68ec57e48c92b64d5abb0..e7b0e0ef8e9f3c962f71c94bfe77a9af04c7d893 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -200,7 +200,6 @@ LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD;
 LL_COMMON_API extern const LLUUID IMG_ALPHA_GRAD_2D;
 LL_COMMON_API extern const LLUUID IMG_TRANSPARENT;
 
-LL_COMMON_API extern const LLUUID IMG_BLOOM1;
 LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
 LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
 LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 7e5a157cdfedd1281067df86504ac5f191daa586..e6cc06e8d01a1220581153c1216d8d740eb88b35 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -95,11 +95,14 @@ LLAssetDictionary::LLAssetDictionary()
 	addEntry(LLAssetType::AT_MESH,              new AssetEntry("MESH",              "mesh",     "mesh",             false,      false,      false));
 	addEntry(LLAssetType::AT_WIDGET,            new AssetEntry("WIDGET",            "widget",   "widget",           false,      false,      false));
 	addEntry(LLAssetType::AT_PERSON,            new AssetEntry("PERSON",            "person",   "person",           false,      false,      false));
+	addEntry(LLAssetType::AT_SETTINGS,          new AssetEntry("SETTINGS",          "settings", "settings blob",    true,       true,       true));
 	addEntry(LLAssetType::AT_UNKNOWN,           new AssetEntry("UNKNOWN",           "invalid",  NULL,               false,      false,      false));
-	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE));
+    addEntry(LLAssetType::AT_NONE,              new AssetEntry("NONE",              "-1",		NULL,		  		FALSE,		FALSE,		FALSE));
 
 };
 
+const std::string LLAssetType::BADLOOKUP("llassettype_bad_lookup");
+
 // static
 LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
 {
@@ -118,7 +121,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
 	}
 	else
 	{
-		return badLookup();
+		return BADLOOKUP;
 	}
 }
 
@@ -133,7 +136,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
 	}
 	else
 	{
-		return badLookup().c_str();
+		return BADLOOKUP.c_str();
 	}
 }
 
@@ -171,7 +174,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
 	}
 	else
 	{
-		return badLookup().c_str();
+		return BADLOOKUP.c_str();
 	}
 }
 
@@ -221,14 +224,6 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
 	return false;
 }
 
-// static
-const std::string &LLAssetType::badLookup()
-{
-	static const std::string sBadLookup = "llassettype_bad_lookup";
-	return sBadLookup;
-
-}
-
 // static
 bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type)
 {
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 79ab3d7efec66391b3d643407c1b049de8cadda6..652c548d59a54c91998540a10679534e35a22621 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -116,10 +116,19 @@ class LL_COMMON_API LLAssetType
 		AT_PERSON = 45,
 			// A user uuid  which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop.
 
-		AT_MESH = 49,
-			// Mesh data in our proprietary SLM format
-		
-		AT_COUNT = 50,
+        AT_MESH = 49,
+        // Mesh data in our proprietary SLM format
+
+        AT_RESERVED_1 = 50,
+        AT_RESERVED_2 = 51,
+        AT_RESERVED_3 = 52,
+        AT_RESERVED_4 = 53,
+        AT_RESERVED_5 = 54,
+        AT_RESERVED_6 = 55,
+
+        AT_SETTINGS = 56,   // Collection of settings
+            
+		AT_COUNT = 57,
 
 			// +*********************************************************+
 			// |  TO ADD AN ELEMENT TO THIS ENUM:                        |
@@ -153,7 +162,7 @@ class LL_COMMON_API LLAssetType
 	static bool 				lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
 	static bool 				lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
 
-	static const std::string&	badLookup(); // error string when a lookup fails
+    static const std::string    BADLOOKUP;
 
 protected:
 	LLAssetType() {}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 335a0995feb1a87b830f8fb412df22b6169bec5b..b46f49ba341b9c73ffe72cc510518f99521096e4 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -181,32 +181,35 @@ namespace {
             return LLError::getEnabledLogTypesMask() & 0x04;
         }
         
+        LL_FORCE_INLINE std::string createANSI(const std::string& color)
+        {
+            std::string ansi_code;
+            ansi_code  += '\033';
+            ansi_code  += "[";
+            ansi_code  += color;
+            ansi_code += "m";
+            return ansi_code;
+        }
+
 		virtual void recordMessage(LLError::ELevel level,
 					   const std::string& message) override
-		{
-			if (ANSI_PROBE == mUseANSI)
-				mUseANSI = (checkANSI() ? ANSI_YES : ANSI_NO);
+		{            
+            static std::string s_ansi_error = createANSI("31"); // red
+            static std::string s_ansi_warn  = createANSI("34"); // blue
+            static std::string s_ansi_debug = createANSI("35"); // magenta
+
+            mUseANSI = (ANSI_PROBE == mUseANSI) ? (checkANSI() ? ANSI_YES : ANSI_NO) : mUseANSI;
 
 			if (ANSI_YES == mUseANSI)
 			{
-				// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
-				colorANSI("1"); // bold
-				switch (level) {
-				case LLError::LEVEL_ERROR:
-					colorANSI("31"); // red
-					break;
-				case LLError::LEVEL_WARN:
-					colorANSI("34"); // blue
-					break;
-				case LLError::LEVEL_DEBUG:
-					colorANSI("35"); // magenta
-					break;
-				default:
-					break;
-				}
+                writeANSI((level == LLError::LEVEL_ERROR) ? s_ansi_error :
+                          (level == LLError::LEVEL_WARN)  ? s_ansi_warn :
+                                                            s_ansi_debug, message);
 			}
-			fprintf(stderr, "%s\n", message.c_str());
-			if (ANSI_YES == mUseANSI) colorANSI("0"); // reset
+            else
+            {
+                 fprintf(stderr, "%s\n", message.c_str());
+            }
 		}
 	
 	private:
@@ -217,11 +220,14 @@ namespace {
 			ANSI_NO
 		}					mUseANSI;
 
-		void colorANSI(const std::string color)
+        LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message)
 		{
-			// ANSI color code escape sequence
-			fprintf(stderr, "\033[%sm", color.c_str() );
-		};
+            static std::string s_ansi_bold  = createANSI("1");  // bold
+            static std::string s_ansi_reset = createANSI("0");  // reset
+			// ANSI color code escape sequence, message, and reset in one fprintf call
+            // Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
+			fprintf(stderr, "%s%s%s\n%s", s_ansi_bold.c_str(), ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() );
+		}
 
 		bool checkANSI(void)
 		{
@@ -232,8 +238,8 @@ namespace {
 			return (0 != isatty(2)) &&
 				(NULL == getenv("LL_NO_ANSI_COLOR"));
 #endif // LL_LINUX
-			return false;
-		};
+            return FALSE; // works in a cygwin shell... ;)
+		}
 	};
 
 	class RecordToFixedBuffer : public LLError::Recorder
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index b3debf35506c06cb8504afd94a0b49681bc0a523..1884d6f04fbdab37acae68de43c5eccc9f873860 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -77,7 +77,7 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
 //static 
 void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
 {
-	sMaxHeapSizeInKB = max_heap_size;
+	sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
 	sEnableMemoryFailurePrevention = prevent_heap_failure ;
 }
 
@@ -93,9 +93,9 @@ void LLMemory::updateMemoryInfo()
 		return ;
 	}
 
-	sAllocatedMemInKB = U64Bytes(counters.WorkingSetSize) ;
+	sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
 	sample(sAllocatedMem, sAllocatedMemInKB);
-	sAllocatedPageSizeInKB = U64Bytes(counters.PagefileUsage) ;
+	sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
 	sample(sVirtualMem, sAllocatedPageSizeInKB);
 
 	U32Kilobytes avail_phys, avail_virtual;
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 57aa7d9c07ce35cdbd34af2184d732746950fa23..57b746889d8f19ed1c2386b2f86d427c53aa9ffb 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -132,6 +132,7 @@ class LLSD::Impl
 	
 	virtual bool has(const String&) const		{ return false; }
 	virtual LLSD get(const String&) const		{ return LLSD(); }
+	virtual LLSD getKeys() const				{ return LLSD::emptyArray(); }
 	virtual void erase(const String&)			{ }
 	virtual const LLSD& ref(const String&) const{ return undef(); }
 	
@@ -380,7 +381,8 @@ namespace
 		using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
 		using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
 		virtual LLSD get(const LLSD::String&) const; 
-		void insert(const LLSD::String& k, const LLSD& v);
+		virtual LLSD getKeys() const; 
+		        void insert(const LLSD::String& k, const LLSD& v);
 		virtual void erase(const LLSD::String&);
 		              LLSD& ref(const LLSD::String&);
 		virtual const LLSD& ref(const LLSD::String&) const;
@@ -421,7 +423,19 @@ namespace
 		DataMap::const_iterator i = mData.find(k);
 		return (i != mData.end()) ? i->second : LLSD();
 	}
-	
+
+	LLSD ImplMap::getKeys() const
+	{ 
+		LLSD keys = LLSD::emptyArray();
+		DataMap::const_iterator iter = mData.begin();
+		while (iter != mData.end())
+		{
+			keys.append((*iter).first);
+			iter++;
+		}
+		return keys;
+	}
+
 	void ImplMap::insert(const LLSD::String& k, const LLSD& v)
 	{
 		mData.insert(DataMap::value_type(k, v));
@@ -502,7 +516,7 @@ namespace
 		virtual LLSD get(LLSD::Integer) const;
 		        void set(LLSD::Integer, const LLSD&);
 		        void insert(LLSD::Integer, const LLSD&);
-		        void append(const LLSD&);
+		        LLSD& append(const LLSD&);
 		virtual void erase(LLSD::Integer);
 		              LLSD& ref(LLSD::Integer);
 		virtual const LLSD& ref(LLSD::Integer) const; 
@@ -570,9 +584,10 @@ namespace
 		mData.insert(mData.begin() + index, v);
 	}
 	
-	void ImplArray::append(const LLSD& v)
+	LLSD& ImplArray::append(const LLSD& v)
 	{
 		mData.push_back(v);
+		return mData.back();
 	}
 	
 	void ImplArray::erase(LLSD::Integer i)
@@ -862,6 +877,7 @@ LLSD LLSD::emptyMap()
 
 bool LLSD::has(const String& k) const	{ return safe(impl).has(k); }
 LLSD LLSD::get(const String& k) const	{ return safe(impl).get(k); } 
+LLSD LLSD::getKeys() const				{ return safe(impl).getKeys(); } 
 void LLSD::insert(const String& k, const LLSD& v) {	makeMap(impl).insert(k, v); }
 
 LLSD& LLSD::with(const String& k, const LLSD& v)
@@ -895,7 +911,7 @@ LLSD& LLSD::with(Integer i, const LLSD& v)
 											makeArray(impl).insert(i, v); 
 											return *this;
 										}
-void LLSD::append(const LLSD& v)		{ makeArray(impl).append(v); }
+LLSD& LLSD::append(const LLSD& v)		{ return makeArray(impl).append(v); }
 void LLSD::erase(Integer i)				{ makeArray(impl).erase(i); }
 
 LLSD&		LLSD::operator[](Integer i)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 7b9b1285f59c1a3bda4c85de7c25585c84c67547..5b6d5545af11d61bfa2f9ca731e9f34c4091886d 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -79,7 +79,7 @@
 	an LLSD array).
 	
 	An array is a sequence of zero or more LLSD values.
-	
+
 	Thread Safety
 
 	In general, these LLSD classes offer *less* safety than STL container
@@ -284,6 +284,7 @@ class LL_COMMON_API LLSD
 		
 		bool has(const String&) const;
 		LLSD get(const String&) const;
+		LLSD getKeys() const;				// Return an LLSD array with keys as strings
 		void insert(const String&, const LLSD&);
 		void erase(const String&);
 		LLSD& with(const String&, const LLSD&);
@@ -301,7 +302,7 @@ class LL_COMMON_API LLSD
 		LLSD get(Integer) const;
 		void set(Integer, const LLSD&);
 		void insert(Integer, const LLSD&);
-		void append(const LLSD&);
+		LLSD& append(const LLSD&);
 		void erase(Integer);
 		LLSD& with(Integer, const LLSD&);
 		
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index 1aaff5628f2658ab89e9d733b2b6dc5bbb1b6b7c..c3fb4ebc2ca415569f4a12d5123841cf6bee7b9d 100644
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -55,6 +55,7 @@ static const S32 UNZIP_LLSD_MAX_DEPTH = 96;
 static const char LEGACY_NON_HEADER[] = "<llsd>";
 const std::string LLSD_BINARY_HEADER("LLSD/Binary");
 const std::string LLSD_XML_HEADER("LLSD/XML");
+const std::string LLSD_NOTATION_HEADER("llsd/notation");
 
 //used to deflate a gzipped asset (currently used for navmeshes)
 #define windowBits 15
@@ -81,6 +82,11 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
 		f = new LLSDXMLFormatter;
 		break;
 
+    case LLSD_NOTATION:
+        str << "<? " << LLSD_NOTATION_HEADER << " ?>\n";
+        f = new LLSDNotationFormatter;
+        break;
+
 	default:
 		LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
 	}
@@ -168,6 +174,10 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 	{
 		p = new LLSDXMLParser;
 	}
+    else if (header == LLSD_NOTATION_HEADER)
+    {
+        p = new LLSDNotationParser;
+    }
 	else
 	{
 		LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h
index 8165410e80d0c8d069a4c1c6d16dfcbb40b4d1f8..fe0f4443ef2e6ba44ce5eed4b5aec90b77d68342 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -706,7 +706,7 @@ class LL_COMMON_API LLSDSerialize
 public:
 	enum ELLSD_Serialize
 	{
-		LLSD_BINARY, LLSD_XML
+        LLSD_BINARY, LLSD_XML, LLSD_NOTATION
 	};
 
 	/**
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 9d00395c0ab826dba49d0569c0cb6f5d1d0ecddd..6a23c443a04d2d612d459e3d8c0234e5eac3e390 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -322,6 +322,180 @@ BOOL compare_llsd_with_template(
 	return TRUE;
 }
 
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of 
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+//     test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+//     for *all* the elements of the test array.  If the template array is of
+//     different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+	const LLSD & llsd_to_test,
+	const LLSD & template_llsd,
+	LLSD & resultant_llsd)
+{
+	if (llsd_to_test.isUndefined() && template_llsd.isDefined())
+	{
+		resultant_llsd = template_llsd;
+		return true;
+	}
+	else if (llsd_to_test.type() != template_llsd.type())
+	{
+		resultant_llsd = LLSD();
+		return false;
+	}
+
+	if (llsd_to_test.isArray())
+	{
+		//they are both arrays
+		//we loop over all the items in the template
+		//verifying that the to_test has a subset (in the same order)
+		//any shortcoming in the testing_llsd are just taken
+		//to be the rest of the template
+		LLSD data;
+		LLSD::array_const_iterator test_iter;
+		LLSD::array_const_iterator template_iter;
+
+		resultant_llsd = LLSD::emptyArray();
+		test_iter = llsd_to_test.beginArray();
+
+		if (1 == template_llsd.size())
+		{
+			// If the template has a single item, treat it as
+			// the template for *all* items in the test LLSD.
+			template_iter = template_llsd.beginArray();
+
+			for (; test_iter != llsd_to_test.endArray(); ++test_iter)
+			{
+				if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd.append(data);
+				}
+			}
+		}
+		else
+		{
+			// Traditional compare_llsd_with_template matching
+			
+			for (template_iter = template_llsd.beginArray();
+				 template_iter != template_llsd.endArray() &&
+					 test_iter != llsd_to_test.endArray();
+				 ++template_iter, ++test_iter)
+			{
+				if (! filter_llsd_with_template(*test_iter, *template_iter, data))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd.append(data);
+				}
+			}
+
+			//so either the test or the template ended
+			//we do another loop now to the end of the template
+			//grabbing the default values
+			for (;
+				 template_iter != template_llsd.endArray();
+				 ++template_iter)
+			{
+				resultant_llsd.append(*template_iter);
+			}
+		}
+	}
+	else if (llsd_to_test.isMap())
+	{
+		resultant_llsd = LLSD::emptyMap();
+		
+		//now we loop over the keys of the two maps
+		//any excess is taken from the template
+		//excess is ignored in the test
+
+		// Special tag for wildcarded LLSD map key templates
+		const LLSD::String wildcard_tag("*");
+
+		const bool template_has_wildcard = template_llsd.has(wildcard_tag);
+		LLSD wildcard_value;
+		LLSD value;
+
+		const LLSD::map_const_iterator template_iter_end(template_llsd.endMap());
+		for (LLSD::map_const_iterator template_iter(template_llsd.beginMap());
+			 template_iter_end != template_iter;
+			 ++template_iter)
+		{
+			if (wildcard_tag == template_iter->first)
+			{
+				wildcard_value = template_iter->second;
+			}
+			else if (llsd_to_test.has(template_iter->first))
+			{
+				//the test LLSD has the same key
+				if (! filter_llsd_with_template(llsd_to_test[template_iter->first],
+												template_iter->second,
+												value))
+				{
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					resultant_llsd[template_iter->first] = value;
+				}
+			}
+			else if (! template_has_wildcard)
+			{
+				// test llsd doesn't have it...take the
+				// template as default value
+				resultant_llsd[template_iter->first] = template_iter->second;
+			}
+		}
+		if (template_has_wildcard)
+		{
+			LLSD sub_value;
+			LLSD::map_const_iterator test_iter;
+			
+			for (test_iter = llsd_to_test.beginMap();
+				 test_iter != llsd_to_test.endMap();
+				 ++test_iter)
+			{
+				if (resultant_llsd.has(test_iter->first))
+				{
+					// Final value has test key, assume more specific
+					// template matched and we shouldn't modify it again.
+					continue;
+				}
+				else if (! filter_llsd_with_template(test_iter->second,
+													 wildcard_value,
+													 sub_value))
+				{
+					// Test value doesn't match wildcarded template
+					resultant_llsd = LLSD();
+					return false;
+				}
+				else
+				{
+					// Test value matches template, add the actuals.
+					resultant_llsd[test_iter->first] = sub_value;
+				}
+			}
+		}
+	}
+	else
+	{
+		//of same type...take the test llsd's value
+		resultant_llsd = llsd_to_test;
+	}
+
+	return true;
+}
+
 /*****************************************************************************
 *   Helpers for llsd_matches()
 *****************************************************************************/
@@ -681,3 +855,104 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
         return false;               // pacify the compiler
     }
 }
+
+// Construct a deep partial clone of of an LLSD object. primitive types share 
+// references, however maps, arrays and binary objects are duplicated. An optional
+// filter may be include to exclude/include keys in a map. 
+LLSD llsd_clone(LLSD value, LLSD filter)
+{
+    LLSD clone;
+    bool has_filter(filter.isMap());
+
+    switch (value.type())
+    {
+    case LLSD::TypeMap:
+        clone = LLSD::emptyMap();
+        for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+        {
+            if (has_filter)
+            {
+                if (filter.has((*itm).first))
+                {
+                    if (!filter[(*itm).first].asBoolean())
+                        continue;
+                }
+                else if (filter.has("*"))
+                {
+                    if (!filter["*"].asBoolean())
+                        continue;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            clone[(*itm).first] = llsd_clone((*itm).second, filter);
+        }
+        break;
+    case LLSD::TypeArray:
+        clone = LLSD::emptyArray();
+        for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+        {
+            clone.append(llsd_clone(*ita, filter));
+        }
+        break;
+
+    case LLSD::TypeBinary:
+    {
+        LLSD::Binary bin(value.asBinary().begin(), value.asBinary().end());
+        clone = LLSD::Binary(bin);
+        break;
+    }
+    default:
+        clone = value;
+    }
+
+    return clone;
+}
+
+LLSD llsd_shallow(LLSD value, LLSD filter)
+{
+    LLSD shallow;
+    bool has_filter(filter.isMap());
+
+    if (value.isMap())
+    {
+        shallow = LLSD::emptyMap();
+        for (LLSD::map_const_iterator itm = value.beginMap(); itm != value.endMap(); ++itm)
+        {
+            if (has_filter)
+            {
+                if (filter.has((*itm).first))
+                {
+                    if (!filter[(*itm).first].asBoolean())
+                        continue;
+                }
+                else if (filter.has("*"))
+                {
+                    if (!filter["*"].asBoolean())
+                        continue;
+                }
+                else
+                {
+                    continue;
+                }
+            }
+            shallow[(*itm).first] = (*itm).second;
+        }
+    }
+    else if (value.isArray())
+    {
+        shallow = LLSD::emptyArray();
+        for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+        {
+            shallow.append(*ita);
+        }
+    }
+    else
+    {
+        return value;
+    }
+
+    return shallow;
+}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 01ab6bcb8d00989d8b802fb97f42ab282bca18bb..863be04c8a81500b86634a65fb60d1f1e30ffe70 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -30,6 +30,7 @@
 #define LL_LLSDUTIL_H
 
 #include "llsd.h"
+#include <boost/functional/hash.hpp>
 
 // U32
 LL_COMMON_API LLSD ll_sd_from_U32(const U32);
@@ -70,6 +71,19 @@ LL_COMMON_API BOOL compare_llsd_with_template(
 	const LLSD& template_llsd,
 	LLSD& resultant_llsd);
 
+// filter_llsd_with_template() is a direct clone (copy-n-paste) of 
+// compare_llsd_with_template with the following differences:
+// (1) bool vs BOOL return types
+// (2) A map with the key value "*" is a special value and maps any key in the
+//     test llsd that doesn't have an explicitly matching key in the template.
+// (3) The element of an array with exactly one element is taken as a template
+//     for *all* the elements of the test array.  If the template array is of
+//     different size, compare_llsd_with_template() semantics apply.
+bool filter_llsd_with_template(
+	const LLSD & llsd_to_test,
+	const LLSD & template_llsd,
+	LLSD & resultant_llsd);
+
 /**
  * Recursively determine whether a given LLSD data block "matches" another
  * LLSD prototype. The returned string is empty() on success, non-empty() on
@@ -421,4 +435,86 @@ class inMap
 
 } // namespace llsd
 
+
+// Creates a deep clone of an LLSD object.  Maps, Arrays and binary objects 
+// are duplicated, atomic primitives (Boolean, Integer, Real, etc) simply
+// use a shared reference. 
+// Optionally a filter may be specified to control what is duplicated. The 
+// map takes the form "keyname/boolean".
+// If the value is true the value will be duplicated otherwise it will be skipped 
+// when encountered in a map. A key name of "*" can be specified as a wild card
+// and will specify the default behavior.  If no wild card is given and the clone
+// encounters a name not in the filter, that value will be skipped.
+LLSD llsd_clone(LLSD value, LLSD filter = LLSD());
+
+// Creates a shallow copy of a map or array.  If passed any other type of LLSD 
+// object it simply returns that value.  See llsd_clone for a description of 
+// the filter parameter.
+LLSD llsd_shallow(LLSD value, LLSD filter = LLSD());
+
+
+// Specialization for generating a hash value from an LLSD block. 
+template <>
+struct boost::hash<LLSD>
+{
+    typedef LLSD argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const& s) const 
+    {
+        result_type seed(0);
+
+        LLSD::Type stype = s.type();
+        boost::hash_combine(seed, (S32)stype);
+
+        switch (stype)
+        {
+        case LLSD::TypeBoolean:
+            boost::hash_combine(seed, s.asBoolean());
+            break;
+        case LLSD::TypeInteger:
+            boost::hash_combine(seed, s.asInteger());
+            break;
+        case LLSD::TypeReal:
+            boost::hash_combine(seed, s.asReal());
+            break;
+        case LLSD::TypeURI:
+        case LLSD::TypeString:
+            boost::hash_combine(seed, s.asString());
+            break;
+        case LLSD::TypeUUID:
+            boost::hash_combine(seed, s.asUUID());
+            break;
+        case LLSD::TypeDate:
+            boost::hash_combine(seed, s.asDate().secondsSinceEpoch());
+            break;
+        case LLSD::TypeBinary:
+        {
+            const LLSD::Binary &b(s.asBinary());
+            boost::hash_range(seed, b.begin(), b.end());
+            break;
+        }
+        case LLSD::TypeMap:
+        {
+            for (LLSD::map_const_iterator itm = s.beginMap(); itm != s.endMap(); ++itm)
+            {
+                boost::hash_combine(seed, (*itm).first);
+                boost::hash_combine(seed, (*itm).second);
+            }
+            break;
+        }
+        case LLSD::TypeArray:
+            for (LLSD::array_const_iterator ita = s.beginArray(); ita != s.endArray(); ++ita)
+            {
+                boost::hash_combine(seed, (*ita));
+            }
+            break;
+        case LLSD::TypeUndefined:
+        default:
+            break;
+        }
+
+        return seed;
+    }
+};
+
 #endif // LL_LLSDUTIL_H
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 0da6d548ab007aaf1719acba4a4093919d7f9b3b..7def9b019ca1b57b12a0c41d950093ad5c6b7f93 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -763,6 +763,17 @@ private:                                                                \
     friend class LLSingleton<DERIVED_CLASS>;                            \
     DERIVED_CLASS(__VA_ARGS__)
 
+/**
+ * A slight variance from the above, but includes the "override" keyword
+ */
+#define LLSINGLETON_C11(DERIVED_CLASS)                                  \
+private:                                                                \
+    /* implement LLSingleton pure virtual method whose sole purpose */  \
+    /* is to remind people to use this macro */                         \
+    virtual void you_must_use_LLSINGLETON_macro() override {}           \
+    friend class LLSingleton<DERIVED_CLASS>;                            \
+    DERIVED_CLASS()
+
 /**
  * Use LLSINGLETON_EMPTY_CTOR(Foo); at the start of an LLSingleton<Foo>
  * subclass body when the constructor is trivial:
@@ -781,4 +792,8 @@ private:                                                                \
     /* LLSINGLETON() is carefully implemented to permit exactly this */ \
     LLSINGLETON(DERIVED_CLASS) {}
 
+#define LLSINGLETON_EMPTY_CTOR_C11(DERIVED_CLASS)                       \
+    /* LLSINGLETON() is carefully implemented to permit exactly this */ \
+    LLSINGLETON_C11(DERIVED_CLASS) {}
+
 #endif
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index ac8504ca61586a0513ede9994bd8e6b434bf9bdf..81f244e42282022bd9707c0805e8cc3b7405cf12 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -132,23 +132,34 @@ struct LLUnit
 		return mValue;
 	}
 
-	LL_FORCE_INLINE void value(storage_t value)
+	LL_FORCE_INLINE void value(const storage_t& value)
 	{
 		mValue = value;
 	}
 
 	template<typename NEW_UNITS> 
-	storage_t valueInUnits()
+	storage_t valueInUnits() const
 	{
 		return LLUnit<storage_t, NEW_UNITS>(*this).value();
 	}
 
 	template<typename NEW_UNITS> 
-	void valueInUnits(storage_t value)
+	void valueInUnits(const storage_t& value) const
 	{
 		*this = LLUnit<storage_t, NEW_UNITS>(value);
 	}
 
+    LL_FORCE_INLINE operator storage_t() const
+    {
+        return value();
+    }
+
+    /*LL_FORCE_INLINE self_t& operator= (storage_t v)
+	{
+		value(v);
+        return *this;
+	}*/
+
 	LL_FORCE_INLINE void operator += (self_t other)
 	{
 		mValue += convert(other).mValue;
@@ -159,60 +170,60 @@ struct LLUnit
 		mValue -= convert(other).mValue;
 	}
 
-	LL_FORCE_INLINE void operator *= (storage_t multiplicand)
+	LL_FORCE_INLINE void operator *= (const storage_t& multiplicand)
 	{
 		mValue *= multiplicand;
 	}
 
-	LL_FORCE_INLINE void operator *= (self_t multiplicand)
+	LL_FORCE_INLINE void operator *= (const self_t& multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
 	}
 
-	LL_FORCE_INLINE void operator /= (storage_t divisor)
+	LL_FORCE_INLINE void operator /= (const storage_t& divisor)
 	{
 		mValue /= divisor;
 	}
 
-	void operator /= (self_t divisor)
+	void operator /= (const self_t& divisor)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator == (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue == convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator != (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue != convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator < (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue < convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator <= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue <= convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator > (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue > convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	LL_FORCE_INLINE bool operator >= (const LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS>& other) const
 	{
 		return mValue >= convert(other).value();
 	}
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index dd8660a3c8dbc1275a5ae04724124b3becf7e593..fe7482ba29f82c70598a1497da8e04f4fa1f5faa 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -31,6 +31,7 @@
 #include <vector>
 #include "stdtypes.h"
 #include "llpreprocessor.h"
+#include <boost/functional/hash.hpp>
 
 class LLMutex;
 
@@ -164,6 +165,25 @@ class LL_COMMON_API LLTransactionID : public LLUUID
 	LLAssetID makeAssetID(const LLUUID& session) const;
 };
 
+// Generate a hash of an LLUUID object using the boost hash templates. 
+template <>
+struct boost::hash<LLUUID>
+{
+    typedef LLUUID argument_type;
+    typedef std::size_t result_type;
+    result_type operator()(argument_type const& s) const
+    {
+        result_type seed(0);
+
+        for (S32 i = 0; i < UUID_BYTES; ++i)
+        {
+            boost::hash_combine(seed, s.mData[i]);
+        }
+
+        return seed;
+    }
+};
+
 #endif
 
 
diff --git a/indra/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index 32a83a88d98fac4606d2401ae0c6c36a6c85d1fe..e829788c91f4bfe1e8ffda9d88fd0e542d087e26 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -22,12 +22,17 @@ set(llinventory_SOURCE_FILES
     llfoldertype.cpp
     llinventory.cpp
     llinventorydefines.cpp
+    llinventorysettings.cpp
     llinventorytype.cpp
     lllandmark.cpp
     llnotecard.cpp
     llparcel.cpp
     llpermissions.cpp
     llsaleinfo.cpp
+    llsettingsbase.cpp
+    llsettingsdaycycle.cpp
+    llsettingssky.cpp
+    llsettingswater.cpp
     lltransactionflags.cpp
     lluserrelations.cpp
     )
@@ -39,7 +44,9 @@ set(llinventory_HEADER_FILES
     llfoldertype.h
     llinventory.h
     llinventorydefines.h
+    llinventorysettings.h
     llinventorytype.h
+    llinvtranslationbrdg.h
     lllandmark.h
     llnotecard.h
     llparcel.h
@@ -47,6 +54,10 @@ set(llinventory_HEADER_FILES
     llpermissions.h
     llpermissionsflags.h
     llsaleinfo.h
+    llsettingsbase.h
+    llsettingsdaycycle.h
+    llsettingssky.h
+    llsettingswater.h
     lltransactionflags.h
     lltransactiontypes.h
     lluserrelations.h
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index b0daf639fad2c054e77f45b21584fa795f1fc585..7241b3c0c28631f2d838981fd8be2e8f9dd9a73f 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -100,6 +100,8 @@ LLFolderDictionary::LLFolderDictionary()
 	addEntry(LLFolderType::FT_MARKETPLACE_STOCK,    new FolderEntry("stock",    FALSE));
 	addEntry(LLFolderType::FT_MARKETPLACE_VERSION,  new FolderEntry("version",    FALSE));
 		 
+    addEntry(LLFolderType::FT_SETTINGS,             new FolderEntry("settings", TRUE));
+
 	addEntry(LLFolderType::FT_NONE, 				new FolderEntry("-1",		FALSE));
 };
 
@@ -147,7 +149,7 @@ bool LLFolderType::lookupIsEnsembleType(EType folder_type)
 // static
 LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
 {
-	if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup())
+	if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::BADLOOKUP)
 	{
 		LL_WARNS() << "Converting to unknown asset type " << folder_type << LL_ENDL;
 	}
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index 515bb05a3f10e343251a1336b92a7dadc2084a0d..85b86f9ce5452fe2be1a642233cd58703c9bbf84 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -91,6 +91,8 @@ class LL_COMMON_API LLFolderType
 		FT_MARKETPLACE_STOCK = 54,
 		FT_MARKETPLACE_VERSION = 55,    // Note: We actually *never* create folders with that type. This is used for icon override only.
 
+        FT_SETTINGS = 56,
+
 		FT_COUNT,
 
 		FT_NONE = -1
diff --git a/indra/llinventory/llinventorydefines.h b/indra/llinventory/llinventorydefines.h
index 3881fb1fd72d22d9c1e8ff9b18b36b8f5d4c556f..54562673f3be33238b50d114ef2c37449c7a5ff2 100644
--- a/indra/llinventory/llinventorydefines.h
+++ b/indra/llinventory/llinventorydefines.h
@@ -81,9 +81,10 @@ class LLInventoryItemFlags
 		II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS			= 0x200000,
 			// Whether a returned object is composed of multiple items.
 
-		II_FLAGS_WEARABLES_MASK = 0xff,
-			// Wearables use the low order byte of flags to store the
-			// LLWearableType::EType enumeration found in newview/llwearable.h
+		II_FLAGS_SUBTYPE_MASK                       = 0x0000ff,
+			// Some items like Wearables and settings use the low order byte 
+			// of flags to store the sub type of the inventory item.
+			// see LLWearableType::EType enumeration found in newview/llwearable.h
 
 		II_FLAGS_PERM_OVERWRITE_MASK = 				(II_FLAGS_OBJECT_SLAM_PERM |
 													 II_FLAGS_OBJECT_SLAM_SALE |
diff --git a/indra/llinventory/llinventorysettings.cpp b/indra/llinventory/llinventorysettings.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdad50e8d46b70fe5772d5d15df8088a7517014f
--- /dev/null
+++ b/indra/llinventory/llinventorysettings.cpp
@@ -0,0 +1,116 @@
+/**
+* @file llinventorysettings.cpp
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "linden_common.h"
+#include "llinventorysettings.h"
+#include "llinventorytype.h"
+#include "llinventorydefines.h"
+#include "lldictionary.h"
+#include "llsingleton.h"
+#include "llinvtranslationbrdg.h"
+
+//=========================================================================
+namespace {
+    LLTranslationBridge::ptr_t sTranslator;
+}
+
+//=========================================================================
+struct SettingsEntry : public LLDictionaryEntry
+{
+    SettingsEntry(const std::string &name,
+        const std::string& default_new_name,
+        LLInventoryType::EIconName iconName) :
+        LLDictionaryEntry(name),
+        mDefaultNewName(default_new_name),
+        mLabel(name),
+        mIconName(iconName)
+    {
+        std::string transdname = sTranslator->getString(mLabel);
+        if (!transdname.empty())
+        {
+            mLabel = transdname;
+        }
+    }
+
+    std::string mLabel;
+    std::string mDefaultNewName; //keep mLabel for backward compatibility
+    LLInventoryType::EIconName mIconName;
+};
+
+class LLSettingsDictionary : public LLSingleton<LLSettingsDictionary>,
+    public LLDictionary<LLSettingsType::type_e, SettingsEntry>
+{
+    LLSINGLETON(LLSettingsDictionary);
+
+    void initSingleton();
+};
+
+LLSettingsDictionary::LLSettingsDictionary() 
+{
+}
+
+void LLSettingsDictionary::initSingleton()
+{
+    addEntry(LLSettingsType::ST_SKY,        new SettingsEntry("sky",        "New Sky",      LLInventoryType::ICONNAME_SETTINGS_SKY));
+    addEntry(LLSettingsType::ST_WATER,      new SettingsEntry("water",      "New Water",    LLInventoryType::ICONNAME_SETTINGS_WATER));
+    addEntry(LLSettingsType::ST_DAYCYCLE,   new SettingsEntry("day",        "New Day",      LLInventoryType::ICONNAME_SETTINGS_DAY));
+    addEntry(LLSettingsType::ST_NONE,       new SettingsEntry("none",       "New Settings", LLInventoryType::ICONNAME_SETTINGS));
+    addEntry(LLSettingsType::ST_INVALID,    new SettingsEntry("invalid",    "New Settings", LLInventoryType::ICONNAME_SETTINGS));
+}
+
+//=========================================================================
+
+LLSettingsType::type_e LLSettingsType::fromInventoryFlags(U32 flags)
+{
+    return  (LLSettingsType::type_e)(flags & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK);
+}
+
+LLInventoryType::EIconName LLSettingsType::getIconName(LLSettingsType::type_e type)
+{
+    const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type);
+    if (!entry) 
+        return getIconName(ST_INVALID);
+    return entry->mIconName;
+}
+
+std::string LLSettingsType::getDefaultName(LLSettingsType::type_e type)
+{
+    const SettingsEntry *entry = LLSettingsDictionary::instance().lookup(type);
+    if (!entry)
+        return getDefaultName(ST_INVALID);
+    return entry->mDefaultNewName;
+}
+
+void LLSettingsType::initClass(LLTranslationBridge::ptr_t &trans)
+{
+    sTranslator = trans;
+}
+
+void LLSettingsType::cleanupClass()
+{
+    sTranslator.reset();
+}
diff --git a/indra/llinventory/llinventorysettings.h b/indra/llinventory/llinventorysettings.h
new file mode 100644
index 0000000000000000000000000000000000000000..906540689c0dda7e51cd7b949c97830f4dfdccfa
--- /dev/null
+++ b/indra/llinventory/llinventorysettings.h
@@ -0,0 +1,56 @@
+/**
+* @file llinventorysettings.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_INVENTORY_SETTINGS_H
+#define LL_INVENTORY_SETTINGS_H
+
+#include "llinventorytype.h"
+#include "llinvtranslationbrdg.h"
+
+class LLSettingsType
+{
+public:
+    enum type_e
+    {
+        ST_SKY = 0,
+        ST_WATER = 1,
+        ST_DAYCYCLE = 2,
+
+        ST_INVALID = 255,
+        ST_NONE = -1
+    };
+
+    static type_e fromInventoryFlags(U32 flags);
+    static LLInventoryType::EIconName getIconName(type_e type);
+    static std::string getDefaultName(type_e type);
+
+    static void initClass(LLTranslationBridge::ptr_t &trans);
+    static void cleanupClass();
+};
+
+
+#endif
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 7399e1bca4d0be8e71823914619e2faba8e23ca3..853ed655f5264d0beb10edefdd5bff656d71b81c 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -85,6 +85,7 @@ LLInventoryDictionary::LLInventoryDictionary()
 	addEntry(LLInventoryType::IT_MESH,                new InventoryEntry("mesh",      "mesh",          1, LLAssetType::AT_MESH));
 	addEntry(LLInventoryType::IT_WIDGET,              new InventoryEntry("widget",    "widget",        1, LLAssetType::AT_WIDGET));
 	addEntry(LLInventoryType::IT_PERSON,              new InventoryEntry("person",    "person",        1, LLAssetType::AT_PERSON));
+    addEntry(LLInventoryType::IT_SETTINGS,            new InventoryEntry("settings",  "settings",      1, LLAssetType::AT_SETTINGS));
 }
 
 
@@ -145,6 +146,14 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
 	LLInventoryType::IT_NONE,			// 47	AT_NONE
 	LLInventoryType::IT_NONE,			// 48	AT_NONE
 	LLInventoryType::IT_MESH,			// 49	AT_MESH
+
+    LLInventoryType::IT_NONE,   		// 50   AT_RESERVED_1
+    LLInventoryType::IT_NONE,	    	// 51   AT_RESERVED_2
+    LLInventoryType::IT_NONE,		    // 52   AT_RESERVED_3
+    LLInventoryType::IT_NONE,			// 53   AT_RESERVED_4
+    LLInventoryType::IT_NONE,			// 54   AT_RESERVED_5
+
+    LLInventoryType::IT_SETTINGS,       // 55   AT_SETTINGS
 };
 
 // static
@@ -200,6 +209,12 @@ bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)
 	}
 }
 
+// Should show permissions that apply only to objects rezed in world.
+bool LLInventoryType::showInWorldPermissions(LLInventoryType::EType type)
+{
+    return (type != IT_SETTINGS);
+}
+
 bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
 									 LLAssetType::EType asset_type)
 {
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index 034cee5f45d81d615698ae7c2f0de79c7030cd27..b6e7fb047f8f5ea12529aea0826f2f8163261b0e 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -64,7 +64,8 @@ class LLInventoryType
 		IT_MESH = 22,
 		IT_WIDGET = 23,
 		IT_PERSON = 24,
-		IT_COUNT = 25,
+        IT_SETTINGS = 25,
+		IT_COUNT = 26,
 
 		IT_UNKNOWN = 255,
 		IT_NONE = -1
@@ -112,6 +113,11 @@ class LLInventoryType
 		ICONNAME_LINKFOLDER,
 		ICONNAME_MESH,
 
+        ICONNAME_SETTINGS,
+        ICONNAME_SETTINGS_SKY,
+        ICONNAME_SETTINGS_WATER,
+        ICONNAME_SETTINGS_DAY,
+
 		ICONNAME_INVALID,
 		ICONNAME_UNKNOWN,
 		ICONNAME_COUNT,
@@ -131,6 +137,8 @@ class LLInventoryType
 	// true if this type cannot have restricted permissions.
 	static bool cannotRestrictPermissions(EType type);
 
+    static bool showInWorldPermissions(EType type);
+
 private:
 	// don't instantiate or derive one of these objects
 	LLInventoryType( void );
diff --git a/indra/llinventory/llinvtranslationbrdg.h b/indra/llinventory/llinvtranslationbrdg.h
new file mode 100644
index 0000000000000000000000000000000000000000..fbd887030a4f66223568f731730f16ab6d2087a5
--- /dev/null
+++ b/indra/llinventory/llinvtranslationbrdg.h
@@ -0,0 +1,41 @@
+/**
+* @file llinvtranslationbrdg.h
+* @brief Translation adapter for inventory.
+*
+* $LicenseInfo:firstyear=2002&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, 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$
+*/
+
+#ifndef LL_TRANSLATIONBRDG_H
+#define LL_TRANSLATIONBRDG_H
+
+class LLTranslationBridge
+{
+public:
+    typedef std::shared_ptr<LLTranslationBridge>    ptr_t;
+
+    // clang needs this to be happy
+    virtual ~LLTranslationBridge() {}
+
+    virtual std::string getString(const std::string &xml_desc) = 0;
+};
+
+#endif
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index 0908613c105b2114276c47f2559103bd5ff54e7d..e2469f3c7e651275c33b67c54138e04a0dba8526 100644
--- a/indra/llinventory/llparcel.cpp
+++ b/indra/llinventory/llparcel.cpp
@@ -231,6 +231,9 @@ void LLParcel::init(const LLUUID &owner_id,
 	setAllowGroupAVSounds(TRUE);
 	setAllowAnyAVSounds(TRUE);
 	setHaveNewParcelLimitData(FALSE);
+
+    setRegionAllowEnvironmentOverride(FALSE);
+    setParcelEnvironmentVersion(INVALID_PARCEL_ENVIRONMENT_VERSION);
 }
 
 void LLParcel::overrideOwner(const LLUUID& owner_id, BOOL is_group_owned)
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 135d0ca7b937bd7a17f62537dc39fb02528797f3..3b39aeb56b3a6503fc932e4ed1020afc30539713 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -34,6 +34,7 @@
 #include "llpermissions.h"
 #include "lltimer.h"
 #include "v3math.h"
+#include "llsettingsdaycycle.h"
 
 // Grid out of which parcels taken is stepped every 4 meters.
 const F32 PARCEL_GRID_STEP_METERS	= 4.f;
@@ -102,6 +103,10 @@ const U32 RT_SELL	= 0x1 << 5;
 
 const S32 INVALID_PARCEL_ID = -1;
 
+const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
+// if Region settings are used, parcel env. version is -1
+const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
+
 // Timeouts for parcels
 // default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
 const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
@@ -510,6 +515,10 @@ class LLParcel
 					{ return mRegionDenyAgeUnverifiedOverride; }
     BOOL    getRegionAllowAccessOverride() const
                     { return mRegionAllowAccessoverride; }
+    BOOL    getRegionAllowEnvironmentOverride() const
+                    { return mRegionAllowEnvironmentOverride; }
+    S32     getParcelEnvironmentVersion() const 
+                    { return mCurrentEnvironmentVersion; }
 
 
 	BOOL	getAllowGroupAVSounds()	const	{ return mAllowGroupAVSounds;	} 
@@ -580,6 +589,9 @@ class LLParcel
 	void	setRegionDenyAnonymousOverride(BOOL override)	{ mRegionDenyAnonymousOverride = override; }
 	void	setRegionDenyAgeUnverifiedOverride(BOOL override)	{ mRegionDenyAgeUnverifiedOverride = override; }
     void    setRegionAllowAccessOverride(BOOL override) { mRegionAllowAccessoverride = override; }
+    void    setRegionAllowEnvironmentOverride(BOOL override) { mRegionAllowEnvironmentOverride = override; }
+
+    void    setParcelEnvironmentVersion(S32 version) { mCurrentEnvironmentVersion = version; }
 
 	// Accessors for parcel sellWithObjects
 	void	setPreviousOwnerID(LLUUID prev_owner)	{ mPreviousOwnerID = prev_owner; }
@@ -589,8 +601,7 @@ class LLParcel
 	LLUUID	getPreviousOwnerID() const		{ return mPreviousOwnerID; }
 	BOOL	getPreviouslyGroupOwned() const	{ return mPreviouslyGroupOwned; }
 	BOOL	getSellWithObjects() const		{ return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; }
-	
-	
+
 protected:
 	LLUUID mID;
 	LLUUID				mOwnerID;
@@ -662,10 +673,13 @@ class LLParcel
 	BOOL				mRegionDenyAnonymousOverride;
 	BOOL				mRegionDenyAgeUnverifiedOverride;
     BOOL                mRegionAllowAccessoverride;
+    BOOL                mRegionAllowEnvironmentOverride;
 	BOOL				mAllowGroupAVSounds;
 	BOOL				mAllowAnyAVSounds;
+    S32                 mCurrentEnvironmentVersion;
 	
-	
+    bool                mIsDefaultDayCycle;
+
 public:
 	// HACK, make private
 	S32					mLocalID;
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..61b59e35aacd523ea90f693108896098f5b4f557
--- /dev/null
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -0,0 +1,751 @@
+/**
+* @file llsettingsbase.cpp
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "llsettingsbase.h"
+
+#include "llmath.h"
+#include <algorithm>
+
+#include "llsdserialize.h"
+
+//=========================================================================
+namespace
+{
+    const LLSettingsBase::TrackPosition BREAK_POINT = 0.5;
+}
+
+const LLSettingsBase::TrackPosition LLSettingsBase::INVALID_TRACKPOS(-1.0);
+const std::string LLSettingsBase::DEFAULT_SETTINGS_NAME("_default_");
+
+//=========================================================================
+std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings)
+{
+    LLSDSerialize::serialize(settings.getSettings(), os, LLSDSerialize::LLSD_NOTATION);
+
+    return os;
+}
+
+//=========================================================================
+const std::string LLSettingsBase::SETTING_ID("id");
+const std::string LLSettingsBase::SETTING_NAME("name");
+const std::string LLSettingsBase::SETTING_HASH("hash");
+const std::string LLSettingsBase::SETTING_TYPE("type");
+const std::string LLSettingsBase::SETTING_ASSETID("asset_id");
+const std::string LLSettingsBase::SETTING_FLAGS("flags");
+
+const U32 LLSettingsBase::FLAG_NOCOPY(0x01 << 0);
+const U32 LLSettingsBase::FLAG_NOMOD(0x01 << 1);
+const U32 LLSettingsBase::FLAG_NOTRANS(0x01 << 2);
+const U32 LLSettingsBase::FLAG_NOSAVE(0x01 << 3);
+
+const U32 LLSettingsBase::Validator::VALIDATION_PARTIAL(0x01 << 0);
+
+//=========================================================================
+LLSettingsBase::LLSettingsBase():
+    mSettings(LLSD::emptyMap()),
+    mDirty(true),
+    mBlendedFactor(0.0)
+{
+}
+
+LLSettingsBase::LLSettingsBase(const LLSD setting) :
+    mSettings(setting),
+    mDirty(true),
+    mBlendedFactor(0.0)
+{
+}
+
+//=========================================================================
+void LLSettingsBase::lerpSettings(const LLSettingsBase &other, F64 mix) 
+{
+    mSettings = interpolateSDMap(mSettings, other.mSettings, other.getParameterMap(), mix);
+    setDirtyFlag(true);
+}
+
+LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) const
+{
+    LLSD newSettings;
+
+    for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it)
+    {
+        std::string key_name = (*it).first;
+        LLSD value = (*it).second;
+
+        LLSD::Type setting_type = value.type();
+        switch (setting_type)
+        {
+        case LLSD::TypeMap:
+            newSettings[key_name] = combineSDMaps(value, LLSD());
+            break;
+        case LLSD::TypeArray:
+            newSettings[key_name] = LLSD::emptyArray();
+            for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+            {
+                newSettings[key_name].append(*ita);
+            }
+            break;
+        //case LLSD::TypeInteger:
+        //case LLSD::TypeReal:
+        //case LLSD::TypeBoolean:
+        //case LLSD::TypeString:
+        //case LLSD::TypeUUID:
+        //case LLSD::TypeURI:
+        //case LLSD::TypeDate:
+        //case LLSD::TypeBinary:
+        default:
+            newSettings[key_name] = value;
+            break;
+        }
+    }
+
+    if (!other.isUndefined())
+    {
+        for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
+        {
+            std::string key_name = (*it).first;
+            LLSD value = (*it).second;
+
+            LLSD::Type setting_type = value.type();
+            switch (setting_type)
+            {
+            case LLSD::TypeMap:
+                newSettings[key_name] = combineSDMaps(value, LLSD());
+                break;
+            case LLSD::TypeArray:
+                newSettings[key_name] = LLSD::emptyArray();
+                for (LLSD::array_const_iterator ita = value.beginArray(); ita != value.endArray(); ++ita)
+                {
+                    newSettings[key_name].append(*ita);
+                }
+                break;
+            //case LLSD::TypeInteger:
+            //case LLSD::TypeReal:
+            //case LLSD::TypeBoolean:
+            //case LLSD::TypeString:
+            //case LLSD::TypeUUID:
+            //case LLSD::TypeURI:
+            //case LLSD::TypeDate:
+            //case LLSD::TypeBinary:
+            default:
+                newSettings[key_name] = value;
+                break;
+            }
+        }
+    }
+
+    return newSettings;
+}
+
+LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix) const
+{
+    LLSD newSettings;
+
+    stringset_t skip = getSkipInterpolateKeys();
+    stringset_t slerps = getSlerpKeys();
+
+    llassert(mix >= 0.0f && mix <= 1.0f);
+
+    for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it)
+    {
+        std::string key_name = (*it).first;
+        LLSD value = (*it).second;
+
+        if (skip.find(key_name) != skip.end())
+            continue;
+
+        LLSD other_value;
+        if (other.has(key_name))
+        {
+            other_value = other[key_name];
+        }
+        else
+        {
+            parammapping_t::const_iterator def_iter = defaults.find(key_name);
+            if (def_iter != defaults.end())
+            {
+                other_value = def_iter->second.getDefaultValue();
+            }
+            else if (value.type() == LLSD::TypeMap)
+            {
+                // interpolate in case there are defaults inside (part of legacy)
+                other_value = LLSDMap();
+            }
+            else
+            {
+                // The other or defaults does not contain this setting, keep the original value 
+                // TODO: Should I blend this out instead?
+                newSettings[key_name] = value;
+                continue;
+            }
+        }
+
+        newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, slerps);
+    }
+
+    // Special handling cases
+    // Flags
+    if (settings.has(SETTING_FLAGS))
+    {
+        U32 flags = (U32)settings[SETTING_FLAGS].asInteger();
+        if (other.has(SETTING_FLAGS))
+            flags |= (U32)other[SETTING_FLAGS].asInteger();
+
+        newSettings[SETTING_FLAGS] = LLSD::Integer(flags);
+    }
+
+    // Now add anything that is in other but not in the settings
+    for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
+    {
+        std::string key_name = (*it).first;
+
+        if (skip.find(key_name) != skip.end())
+            continue;
+
+        if (settings.has(key_name))
+            continue;
+
+        parammapping_t::const_iterator def_iter = defaults.find(key_name);
+        if (def_iter != defaults.end())
+        {
+            // Blend against default value
+            newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, slerps);
+        }
+        else if ((*it).second.type() == LLSD::TypeMap)
+        {
+            // interpolate in case there are defaults inside (part of legacy)
+            newSettings[key_name] = interpolateSDValue(key_name, LLSDMap(), (*it).second, defaults, mix, slerps);
+        }
+        // else do nothing when no known defaults
+        // TODO: Should I blend this out instead?
+    }
+
+    // Note: writes variables from skip list, bug?
+    for (LLSD::map_const_iterator it = other.beginMap(); it != other.endMap(); ++it)
+    {
+        // TODO: Should I blend this in instead?
+        if (skip.find((*it).first) == skip.end())
+            continue;
+
+        if (!settings.has((*it).first))
+            continue;
+    
+        newSettings[(*it).first] = (*it).second;
+    }
+
+    return newSettings;
+}
+
+LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const
+{
+    LLSD new_value;
+
+    LLSD::Type setting_type = value.type();
+
+    if (other_value.type() != setting_type)
+    {
+        // The data type mismatched between this and other. Hard switch when we pass the break point
+        // but issue a warning.
+        LL_WARNS("SETTINGS") << "Setting lerp between mismatched types for '" << key_name << "'." << LL_ENDL;
+        new_value = (mix > BREAK_POINT) ? other_value : value;
+    }
+
+    switch (setting_type)
+    {
+        case LLSD::TypeInteger:
+            // lerp between the two values rounding the result to the nearest integer. 
+            new_value = LLSD::Integer(llroundf(lerp(value.asReal(), other_value.asReal(), mix)));
+            break;
+        case LLSD::TypeReal:
+            // lerp between the two values.
+            new_value = LLSD::Real(lerp(value.asReal(), other_value.asReal(), mix));
+            break;
+        case LLSD::TypeMap:
+            // deep copy.
+            new_value = interpolateSDMap(value, other_value, defaults, mix);
+            break;
+
+        case LLSD::TypeArray:
+        {
+            LLSD new_array(LLSD::emptyArray());
+
+            if (slerps.find(key_name) != slerps.end())
+            {
+                LLQuaternion a(value);
+                LLQuaternion b(other_value);
+                LLQuaternion q = slerp(mix, a, b);
+                new_array = q.getValue();
+            }
+            else
+            {   // TODO: We could expand this to inspect the type and do a deep lerp based on type. 
+                // for now assume a heterogeneous array of reals. 
+                size_t len = std::max(value.size(), other_value.size());
+
+                for (size_t i = 0; i < len; ++i)
+                {
+
+                    new_array[i] = lerp(value[i].asReal(), other_value[i].asReal(), mix);
+                }
+            }
+
+            new_value = new_array;
+        }
+
+        break;
+
+        case LLSD::TypeUUID:
+            new_value = value.asUUID();
+            break;
+
+            //      case LLSD::TypeBoolean:
+            //      case LLSD::TypeString:
+            //      case LLSD::TypeURI:
+            //      case LLSD::TypeBinary:
+            //      case LLSD::TypeDate:
+        default:
+            // atomic or unknown data types. Lerping between them does not make sense so switch at the break.
+            new_value = (mix > BREAK_POINT) ? other_value : value;
+            break;
+    }
+
+    return new_value;
+}
+
+LLSettingsBase::stringset_t LLSettingsBase::getSkipInterpolateKeys() const
+{
+    static stringset_t skipSet;
+
+    if (skipSet.empty())
+    {
+        skipSet.insert(SETTING_FLAGS);
+        skipSet.insert(SETTING_HASH);
+    }
+
+    return skipSet;
+}
+
+LLSD LLSettingsBase::getSettings() const
+{
+    return mSettings;
+}
+
+LLSD LLSettingsBase::cloneSettings() const
+{
+    U32 flags = getFlags();
+    LLSD settings (combineSDMaps(getSettings(), LLSD()));
+    if (flags)
+        settings[SETTING_FLAGS] = LLSD::Integer(flags);
+    return settings;
+}
+
+size_t LLSettingsBase::getHash() const
+{   // get a shallow copy of the LLSD filtering out values to not include in the hash
+    LLSD hash_settings = llsd_shallow(getSettings(), 
+        LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true));
+
+    boost::hash<LLSD> hasher;
+    return hasher(hash_settings);
+}
+
+bool LLSettingsBase::validate()
+{
+    validation_list_t validations = getValidationList();
+
+    if (!mSettings.has(SETTING_TYPE))
+    {
+        mSettings[SETTING_TYPE] = getSettingsType();
+    }
+
+    LLSD result = LLSettingsBase::settingValidation(mSettings, validations);
+
+    if (result["errors"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Validation errors: " << result["errors"] << LL_ENDL;
+    }
+    if (result["warnings"].size() > 0)
+    {
+        LL_DEBUGS("SETTINGS") << "Validation warnings: " << result["warnings"] << LL_ENDL;
+    }
+
+    return result["success"].asBoolean();
+}
+
+LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial)
+{
+    static Validator  validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, 63));
+    static Validator  validateId(SETTING_ID, false, LLSD::TypeUUID);
+    static Validator  validateHash(SETTING_HASH, false, LLSD::TypeInteger);
+    static Validator  validateType(SETTING_TYPE, false, LLSD::TypeString);
+    static Validator  validateAssetId(SETTING_ASSETID, false, LLSD::TypeUUID);
+    static Validator  validateFlags(SETTING_FLAGS, false, LLSD::TypeInteger);
+    stringset_t       validated;
+    stringset_t       strip;
+    bool              isValid(true);
+    LLSD              errors(LLSD::emptyArray());
+    LLSD              warnings(LLSD::emptyArray());
+    U32               flags(0);
+    
+    if (partial)
+        flags |= Validator::VALIDATION_PARTIAL;
+
+    // Fields common to all settings.
+    if (!validateName.verify(settings, flags))
+    {
+        errors.append( LLSD::String("Unable to validate 'name'.") );
+        isValid = false;
+    }
+    validated.insert(validateName.getName());
+
+    if (!validateId.verify(settings, flags))
+    {
+        errors.append( LLSD::String("Unable to validate 'id'.") );
+        isValid = false;
+    }
+    validated.insert(validateId.getName());
+
+    if (!validateHash.verify(settings, flags))
+    {
+        errors.append( LLSD::String("Unable to validate 'hash'.") );
+        isValid = false;
+    }
+    validated.insert(validateHash.getName());
+
+    if (!validateAssetId.verify(settings, flags))
+    {
+        errors.append(LLSD::String("Invalid asset Id"));
+        isValid = false;
+    }
+    validated.insert(validateAssetId.getName());
+
+    if (!validateType.verify(settings, flags))
+    {
+        errors.append( LLSD::String("Unable to validate 'type'.") );
+        isValid = false;
+    }
+    validated.insert(validateType.getName());
+
+    if (!validateFlags.verify(settings, flags))
+    {
+        errors.append(LLSD::String("Unable to validate 'flags'."));
+        isValid = false;
+    }
+    validated.insert(validateFlags.getName());
+
+    // Fields for specific settings.
+    for (validation_list_t::iterator itv = validations.begin(); itv != validations.end(); ++itv)
+    {
+#ifdef VALIDATION_DEBUG
+        LLSD oldvalue;
+        if (settings.has((*itv).getName()))
+        {
+            oldvalue = llsd_clone(mSettings[(*itv).getName()]);
+        }
+#endif
+
+        if (!(*itv).verify(settings, flags))
+        {
+            std::stringstream errtext;
+
+            errtext << "Settings LLSD fails validation and could not be corrected for '" << (*itv).getName() << "'!\n";
+            errors.append( errtext.str() );
+            isValid = false;
+        }
+        validated.insert((*itv).getName());
+
+#ifdef VALIDATION_DEBUG
+        if (!oldvalue.isUndefined())
+        {
+            if (!compare_llsd(settings[(*itv).getName()], oldvalue))
+            {
+                LL_WARNS("SETTINGS") << "Setting '" << (*itv).getName() << "' was changed: " << oldvalue << " -> " << settings[(*itv).getName()] << LL_ENDL;
+            }
+        }
+#endif
+    }
+
+    // strip extra entries
+    for (LLSD::map_const_iterator itm = settings.beginMap(); itm != settings.endMap(); ++itm)
+    {
+        if (validated.find((*itm).first) == validated.end())
+        {
+            std::stringstream warntext;
+
+            warntext << "Stripping setting '" << (*itm).first << "'";
+            warnings.append( warntext.str() );
+            strip.insert((*itm).first);
+        }
+    }
+
+    for (stringset_t::iterator its = strip.begin(); its != strip.end(); ++its)
+    {
+        settings.erase(*its);
+    }
+
+    return LLSDMap("success", LLSD::Boolean(isValid))
+        ("errors", errors)
+        ("warnings", warnings);
+}
+
+//=========================================================================
+
+bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
+{
+    if (!data.has(mName) || (data.has(mName) && data[mName].isUndefined()))
+    {
+        if ((flags & VALIDATION_PARTIAL) != 0) // we are doing a partial validation.  Do no attempt to set a default if missing (or fail even if required)
+            return true;    
+        
+        if (!mDefault.isUndefined())
+        {
+            data[mName] = mDefault;
+            return true;
+        }
+        if (mRequired)
+            LL_WARNS("SETTINGS") << "Missing required setting '" << mName << "' with no default." << LL_ENDL;
+        return !mRequired;
+    }
+
+    if (data[mName].type() != mType)
+    {
+        LL_WARNS("SETTINGS") << "Setting '" << mName << "' is incorrect type." << LL_ENDL;
+        return false;
+    }
+
+    if (!mVerify.empty() && !mVerify(data[mName]))
+    {
+        LL_WARNS("SETTINGS") << "Setting '" << mName << "' fails validation." << LL_ENDL;
+        return false;
+    }
+
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyColor(LLSD &value)
+{
+    return (value.size() == 3 || value.size() == 4);
+}
+
+bool LLSettingsBase::Validator::verifyVector(LLSD &value, S32 length)
+{
+    return (value.size() == length);
+}
+
+bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
+{
+    if (value.size() != length)
+        return false;
+
+    LLSD newvector;
+
+    switch (length)
+    {
+    case 2:
+    {
+        LLVector2 vect(value);
+
+        if (is_approx_equal(vect.normalize(), 1.0f))
+            return true;
+        newvector = vect.getValue();
+        break;
+    }
+    case 3:
+    {
+        LLVector3 vect(value);
+
+        if (is_approx_equal(vect.normalize(), 1.0f))
+            return true;
+        newvector = vect.getValue();
+        break;
+    }
+    case 4:
+    {
+        LLVector4 vect(value);
+
+        if (is_approx_equal(vect.normalize(), 1.0f))
+            return true;
+        newvector = vect.getValue();
+        break;
+    }
+    default:
+        return false;
+    }
+
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals)
+{
+    for (S32 index = 0; index < value.size(); ++index)
+    {
+        if (minvals[index].asString() != "*")
+        {
+            if (minvals[index].asReal() > value[index].asReal())
+            {
+                value[index] = minvals[index].asReal();
+            }
+        }
+        if (maxvals[index].asString() != "*") 
+        {
+            if (maxvals[index].asReal() < value[index].asReal())
+            {
+                value[index] = maxvals[index].asReal();
+            }
+        }
+    }
+
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value)
+{
+    return (value.size() == 4);
+}
+
+bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
+{
+    if (value.size() != 4)
+        return false;
+
+    LLQuaternion quat(value);
+
+    if (is_approx_equal(quat.normalize(), 1.0f))
+        return true;
+
+    LLSD newquat = quat.getValue();
+    for (S32 index = 0; index < 4; ++index)
+    {
+        value[index] = newquat[index];
+    }
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
+{
+    F64 real = value.asReal();
+
+    F64 clampedval = llclamp(LLSD::Real(real), range[0].asReal(), range[1].asReal());
+
+    if (is_approx_equal(clampedval, real))
+        return true;
+
+    value = LLSD::Real(clampedval);
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
+{
+    S32 ival = value.asInteger();
+
+    S32 clampedval = llclamp(LLSD::Integer(ival), range[0].asInteger(), range[1].asInteger());
+
+    if (clampedval == ival)
+        return true;
+
+    value = LLSD::Integer(clampedval);
+    return true;
+}
+
+bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length)
+{
+    std::string sval = value.asString();
+
+    if (!sval.empty())
+    {
+        sval = sval.substr(0, length);
+        value = LLSD::String(sval);
+    }
+    return true;
+}
+
+//=========================================================================
+void LLSettingsBlender::update(const LLSettingsBase::BlendFactor& blendf)
+{
+    F64 res = setBlendFactor(blendf);
+    llassert(res >= 0.0 && res <= 1.0);
+    (void)res;
+    mTarget->update();
+}
+
+F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_in)
+{
+    LLSettingsBase::TrackPosition blendf = blendf_in;
+    if (blendf >= 1.0)
+    {
+        triggerComplete();
+    }
+    blendf = llclamp(blendf, 0.0f, 1.0f);
+
+    if (mTarget)
+    {
+        mTarget->replaceSettings(mInitial->getSettings());
+        mTarget->blend(mFinal, blendf);
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "No target for settings blender." << LL_ENDL;
+    }
+
+    return blendf;
+}
+
+void LLSettingsBlender::triggerComplete()
+{
+    if (mTarget)
+        mTarget->replaceSettings(mFinal->getSettings());
+    LLSettingsBlender::ptr_t hold = shared_from_this();   // prevents this from deleting too soon
+    mTarget->update();
+    mOnFinished(shared_from_this());
+}
+
+//-------------------------------------------------------------------------
+const LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::MIN_BLEND_DELTA(FLT_EPSILON);
+
+LLSettingsBase::BlendFactor LLSettingsBlenderTimeDelta::calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const
+{
+    return LLSettingsBase::BlendFactor(fmod((F64)spanpos, (F64)spanlen) / (F64)spanlen);
+}
+
+bool LLSettingsBlenderTimeDelta::applyTimeDelta(const LLSettingsBase::Seconds& timedelta)
+{
+    mTimeSpent += timedelta;
+
+    if (mTimeSpent > mBlendSpan)
+    {
+        triggerComplete();
+        return false;
+    }
+
+    LLSettingsBase::BlendFactor blendf = calculateBlend(mTimeSpent, mBlendSpan);
+
+    if (fabs(mLastBlendF - blendf) < mBlendFMinDelta)
+    {
+        return false;
+    }
+
+    mLastBlendF = blendf;
+    update(blendf);
+    return true;
+}
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d118f07899d332d12b936a1f06e756018ed2656
--- /dev/null
+++ b/indra/llinventory/llsettingsbase.h
@@ -0,0 +1,518 @@
+/**
+* @file llsettingsbase.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_SETTINGS_BASE_H
+#define LL_SETTINGS_BASE_H
+
+#include <string>
+#include <map>
+#include <vector>
+#include <boost/signals2.hpp>
+
+#include "llsd.h"
+#include "llsdutil.h"
+#include "v2math.h"
+#include "v3math.h"
+#include "v4math.h"
+#include "llquaternion.h"
+#include "v4color.h"
+#include "v3color.h"
+#include "llunits.h"
+
+#include "llinventorysettings.h"
+
+#define PTR_NAMESPACE     std
+#define SETTINGS_OVERRIDE override
+
+class LLSettingsBase : 
+    public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBase>,
+    private boost::noncopyable
+{
+    friend class LLEnvironment;
+    friend class LLSettingsDay;
+
+    friend std::ostream &operator <<(std::ostream& os, LLSettingsBase &settings);
+
+protected:
+    LOG_CLASS(LLSettingsBase);
+public:
+    typedef F64Seconds Seconds;
+    typedef F64        BlendFactor;
+    typedef F32        TrackPosition; // 32-bit as these are stored in LLSD as such
+    static const TrackPosition INVALID_TRACKPOS;
+    static const std::string DEFAULT_SETTINGS_NAME;
+
+    static const std::string SETTING_ID;
+    static const std::string SETTING_NAME;
+    static const std::string SETTING_HASH;
+    static const std::string SETTING_TYPE;
+    static const std::string SETTING_ASSETID;
+    static const std::string SETTING_FLAGS;
+
+    static const U32 FLAG_NOCOPY;
+    static const U32 FLAG_NOMOD;
+    static const U32 FLAG_NOTRANS;
+    static const U32 FLAG_NOSAVE;
+
+    class DefaultParam
+    {
+    public:
+        DefaultParam(S32 key, const LLSD& value) : mShaderKey(key), mDefaultValue(value) {}
+        DefaultParam() : mShaderKey(-1) {}
+        S32 getShaderKey() const { return mShaderKey; }
+        const LLSD getDefaultValue() const { return mDefaultValue; }
+
+    private:
+        S32 mShaderKey;
+        LLSD mDefaultValue;
+    };
+    // Contains settings' names (map key), related shader id-key and default
+    // value for revert in case we need to reset shader (no need to search each time)
+    typedef std::map<std::string, DefaultParam>  parammapping_t;
+
+    typedef PTR_NAMESPACE::shared_ptr<LLSettingsBase> ptr_t;
+
+    virtual ~LLSettingsBase() { };
+
+    //---------------------------------------------------------------------
+    virtual std::string getSettingsType() const = 0;
+
+    virtual LLSettingsType::type_e getSettingsTypeValue() const = 0;
+
+    //---------------------------------------------------------------------
+    // Settings status 
+    inline bool hasSetting(const std::string &param) const { return mSettings.has(param); }
+    virtual bool isDirty() const { return mDirty; }
+    virtual bool isVeryDirty() const { return mReplaced; }
+    inline void setDirtyFlag(bool dirty) { mDirty = dirty; clearAssetId(); }
+
+    size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash
+
+    inline LLUUID getId() const
+    {
+        return getValue(SETTING_ID).asUUID();
+    }
+
+    inline std::string getName() const
+    {
+        return getValue(SETTING_NAME).asString();
+    }
+
+    inline void setName(std::string val)
+    {
+        setValue(SETTING_NAME, val);
+    }
+
+    inline LLUUID getAssetId() const
+    {
+        if (mSettings.has(SETTING_ASSETID))
+            return mSettings[SETTING_ASSETID].asUUID();
+        return LLUUID();
+    }
+
+    inline U32 getFlags() const
+    {
+        if (mSettings.has(SETTING_FLAGS))
+            return static_cast<U32>(mSettings[SETTING_FLAGS].asInteger());
+        return 0;
+    }
+
+    inline void setFlags(U32 value)
+    {
+        setLLSD(SETTING_FLAGS, LLSD::Integer(value));
+    }
+
+    inline bool getFlag(U32 flag) const
+    {
+        if (mSettings.has(SETTING_FLAGS))
+            return ((U32)mSettings[SETTING_FLAGS].asInteger() & flag) == flag;
+        return false;
+    }
+
+    inline void setFlag(U32 flag)
+    {
+        U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
+
+        flags |= flag;
+
+        if (flags)
+            mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
+        else
+            mSettings.erase(SETTING_FLAGS);
+    }
+
+    inline void clearFlag(U32 flag)
+    {
+        U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
+
+        flags &= ~flag;
+
+        if (flags)
+            mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
+        else
+            mSettings.erase(SETTING_FLAGS);
+    }
+
+    virtual void replaceSettings(LLSD settings)
+    {
+        mBlendedFactor = 0.0;
+        setDirtyFlag(true);
+        mReplaced = true;
+        mSettings = settings;
+    }
+
+    virtual LLSD getSettings() const;
+
+    //---------------------------------------------------------------------
+    // 
+    inline void setLLSD(const std::string &name, const LLSD &value)
+    {
+        mSettings[name] = value;
+        mDirty = true;
+        if (name != SETTING_ASSETID)
+            clearAssetId();
+    }
+
+    inline void setValue(const std::string &name, const LLSD &value)
+    {
+        setLLSD(name, value);
+    }
+
+    inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD()) const
+    {
+        if (!mSettings.has(name))
+            return deflt;
+        return mSettings[name];
+    }
+
+    inline void setValue(const std::string &name, F32 v)
+    {
+        setLLSD(name, LLSD::Real(v));
+    }
+
+    inline void setValue(const std::string &name, const LLVector2 &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline void setValue(const std::string &name, const LLVector3 &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline void setValue(const std::string &name, const LLVector4 &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline void setValue(const std::string &name, const LLQuaternion &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline void setValue(const std::string &name, const LLColor3 &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline void setValue(const std::string &name, const LLColor4 &value)
+    {
+        setValue(name, value.getValue());
+    }
+
+    inline BlendFactor getBlendFactor() const
+    {
+        return mBlendedFactor;
+    }
+
+    // Note this method is marked const but may modify the settings object.
+    // (note the internal const cast).  This is so that it may be called without
+    // special consideration from getters.
+    inline void     update() const
+    {
+        if ((!mDirty) && (!mReplaced))
+            return;
+        (const_cast<LLSettingsBase *>(this))->updateSettings();
+    }
+
+    virtual void    blend(const ptr_t &end, BlendFactor blendf) = 0;
+
+    virtual bool    validate();
+
+    virtual ptr_t   buildDerivedClone() const = 0;
+
+    class Validator
+    {
+    public:
+        static const U32 VALIDATION_PARTIAL;
+        
+        typedef boost::function<bool(LLSD &)> verify_pr;
+
+        Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD())  :
+            mName(name),
+            mRequired(required),
+            mType(type),
+            mVerify(verify),
+            mDefault(defval)
+        {   }
+
+        std::string getName() const { return mName; }
+        bool        isRequired() const { return mRequired; }
+        LLSD::Type  getType() const { return mType; }
+
+        bool        verify(LLSD &data, U32 flags);
+
+        // Some basic verifications
+        static bool verifyColor(LLSD &value);
+        static bool verifyVector(LLSD &value, S32 length);
+        static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals);
+        static bool verifyVectorNormalized(LLSD &value, S32 length);
+        static bool verifyQuaternion(LLSD &value);
+        static bool verifyQuaternionNormal(LLSD &value);
+        static bool verifyFloatRange(LLSD &value, LLSD range);
+        static bool verifyIntegerRange(LLSD &value, LLSD range);
+        static bool verifyStringLength(LLSD &value, S32 length);
+
+    private:
+        std::string mName;
+        bool        mRequired;
+        LLSD::Type  mType;
+        verify_pr   mVerify;
+        LLSD        mDefault;
+    };
+    typedef std::vector<Validator> validation_list_t;
+
+    static LLSD settingValidation(LLSD &settings, validation_list_t &validations, bool partial = false);
+
+    inline void setAssetId(LLUUID value)
+    {   // note that this skips setLLSD
+        mSettings[SETTING_ASSETID] = value;
+    }
+
+    inline void clearAssetId()
+    {
+        if (mSettings.has(SETTING_ASSETID))
+            mSettings.erase(SETTING_ASSETID);
+    }
+
+    // Calculate any custom settings that may need to be cached.
+    virtual void updateSettings() { mDirty = false; mReplaced = false; }
+protected:
+
+    LLSettingsBase();
+    LLSettingsBase(const LLSD setting);
+
+    static LLSD settingValidation(LLSD settings);
+
+    typedef std::set<std::string>   stringset_t;
+    
+    // combining settings objects. Customize for specific setting types
+    virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix);
+
+    // combining settings maps where it can based on mix rate
+    // @settings initial value (mix==0)
+    // @other target value (mix==1)
+    // @defaults list of default values for legacy fields and (re)setting shaders
+    // @mix from 0 to 1, ratio or rate of transition from initial 'settings' to 'other'
+    // return interpolated and combined LLSD map
+    LLSD    interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix) const;
+    LLSD    interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const;
+
+    /// when lerping between settings, some may require special handling.  
+    /// Get a list of these key to be skipped by the default settings lerp.
+    /// (handling should be performed in the override of lerpSettings.
+    virtual stringset_t getSkipInterpolateKeys() const; 
+
+    // A list of settings that represent quaternions and should be slerped 
+    // rather than lerped.
+    virtual stringset_t getSlerpKeys() const { return stringset_t(); }
+
+    virtual validation_list_t getValidationList() const = 0;
+
+    // Apply any settings that need special handling. 
+    virtual void applySpecial(void *, bool force = false) { };
+
+    virtual parammapping_t getParameterMap() const { return parammapping_t(); }
+
+    LLSD        mSettings;
+    bool        mIsValid;
+
+    LLSD        cloneSettings() const;
+
+    inline void setBlendFactor(BlendFactor blendfactor) 
+    {
+        mBlendedFactor = blendfactor;
+    }
+
+    void replaceWith(LLSettingsBase::ptr_t other)
+    {
+        replaceSettings(other->cloneSettings());
+        setBlendFactor(other->getBlendFactor());
+    }
+
+private:
+    bool        mDirty;
+    bool        mReplaced; // super dirty!
+
+    LLSD        combineSDMaps(const LLSD &first, const LLSD &other) const;
+
+    BlendFactor mBlendedFactor;
+};
+
+
+class LLSettingsBlender : public PTR_NAMESPACE::enable_shared_from_this<LLSettingsBlender>
+{
+    LOG_CLASS(LLSettingsBlender);
+public:
+    typedef PTR_NAMESPACE::shared_ptr<LLSettingsBlender>      ptr_t;
+    typedef boost::signals2::signal<void(const ptr_t )> finish_signal_t;
+    typedef boost::signals2::connection     connection_t;
+
+    LLSettingsBlender(const LLSettingsBase::ptr_t &target,
+            const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting) :
+        mOnFinished(),
+        mTarget(target),
+        mInitial(initsetting),
+        mFinal(endsetting)
+    {
+        if (mInitial && mTarget)
+            mTarget->replaceSettings(mInitial->getSettings());
+
+        if (!mFinal)
+            mFinal = mInitial;
+    }
+
+    virtual ~LLSettingsBlender() {}
+
+    virtual void reset( LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition&)
+    {
+        // note: the 'span' reset parameter is unused by the base class.
+        if (!mInitial)
+            LL_WARNS("BLENDER") << "Reseting blender with empty initial setting. Expect badness in the future." << LL_ENDL;
+
+        mInitial = initsetting;
+        mFinal = endsetting;
+
+        if (!mFinal)
+            mFinal = mInitial;
+
+        if (mTarget)
+            mTarget->replaceSettings(mInitial->getSettings());
+    }
+
+    LLSettingsBase::ptr_t getTarget() const
+    {
+        return mTarget;
+    }
+
+    LLSettingsBase::ptr_t getInitial() const
+    {
+        return mInitial;
+    }
+
+    LLSettingsBase::ptr_t getFinal() const
+    {
+        return mFinal;
+    }
+
+    connection_t            setOnFinished(const finish_signal_t::slot_type &onfinished)
+    {
+        return mOnFinished.connect(onfinished);
+    }
+
+    virtual void            update(const LLSettingsBase::BlendFactor& blendf);
+    virtual bool            applyTimeDelta(const LLSettingsBase::Seconds& timedelta)
+    {
+        llassert(false);
+        // your derived class needs to implement an override of this func
+        return false;
+    }
+
+    virtual F64             setBlendFactor(const LLSettingsBase::BlendFactor& position);
+
+    virtual void            switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) { /*NoOp*/ }
+
+protected:
+    void                    triggerComplete();
+
+    finish_signal_t         mOnFinished;
+
+    LLSettingsBase::ptr_t   mTarget;
+    LLSettingsBase::ptr_t   mInitial;
+    LLSettingsBase::ptr_t   mFinal;
+};
+
+class LLSettingsBlenderTimeDelta : public LLSettingsBlender
+{
+    LOG_CLASS(LLSettingsBlenderTimeDelta);
+public:
+    static const LLSettingsBase::BlendFactor MIN_BLEND_DELTA;
+
+    LLSettingsBlenderTimeDelta(const LLSettingsBase::ptr_t &target,
+        const LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::Seconds& blend_span) :
+        LLSettingsBlender(target, initsetting, endsetting),
+        mBlendSpan(blend_span),
+        mLastUpdate(0.0f),
+        mTimeSpent(0.0f),
+        mBlendFMinDelta(MIN_BLEND_DELTA),
+        mLastBlendF(-1.0f)
+    {
+        mTimeStart = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch());
+        mLastUpdate = mTimeStart;
+    }
+
+    virtual ~LLSettingsBlenderTimeDelta() 
+    {
+    }
+
+    virtual void reset(LLSettingsBase::ptr_t &initsetting, const LLSettingsBase::ptr_t &endsetting, const LLSettingsBase::TrackPosition& blend_span) SETTINGS_OVERRIDE
+    {
+        LLSettingsBlender::reset(initsetting, endsetting, blend_span);
+
+        mBlendSpan  = blend_span;
+        mTimeStart  = LLSettingsBase::Seconds(LLDate::now().secondsSinceEpoch());
+        mLastUpdate = mTimeStart;
+        mTimeSpent  = LLSettingsBase::Seconds(0.0f);
+        mLastBlendF = LLSettingsBase::BlendFactor(-1.0f);
+    }
+
+    virtual bool applyTimeDelta(const LLSettingsBase::Seconds& timedelta) SETTINGS_OVERRIDE;
+
+    inline void setTimeSpent(LLSettingsBase::Seconds time) { mTimeSpent = time; }
+protected:
+    LLSettingsBase::BlendFactor calculateBlend(const LLSettingsBase::TrackPosition& spanpos, const LLSettingsBase::TrackPosition& spanlen) const;
+
+    LLSettingsBase::TrackPosition mBlendSpan;
+    LLSettingsBase::Seconds mLastUpdate;
+    LLSettingsBase::Seconds mTimeSpent;
+    LLSettingsBase::Seconds mTimeStart;
+    LLSettingsBase::BlendFactor mBlendFMinDelta;
+    LLSettingsBase::BlendFactor mLastBlendF;
+};
+
+
+#endif
diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..457e5b747898a2a37644ac3e2be4e995beac5e94
--- /dev/null
+++ b/indra/llinventory/llsettingsdaycycle.cpp
@@ -0,0 +1,896 @@
+/**
+* @file llsettingsdaycycle.cpp
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "llsettingsdaycycle.h"
+#include "llerror.h"
+#include <algorithm>
+#include <boost/make_shared.hpp>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+
+#include "llframetimer.h"
+
+//=========================================================================
+namespace
+{
+    LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment");
+    LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment");
+
+    template<typename T>
+    inline T get_wrapping_distance(T begin, T end)
+    {
+        if (begin < end)
+        {
+            return end - begin;
+        }
+        else if (begin > end)
+        {
+            return T(1.0) - (begin - end);
+        }
+
+        return 0;
+    }
+
+    LLSettingsDay::CycleTrack_t::iterator get_wrapping_atafter(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
+    {
+        if (collection.empty())
+            return collection.end();
+
+        LLSettingsDay::CycleTrack_t::iterator it = collection.upper_bound(key);
+
+        if (it == collection.end())
+        {   // wrap around
+            it = collection.begin();
+        }
+
+        return it;
+    }
+
+    LLSettingsDay::CycleTrack_t::iterator get_wrapping_atbefore(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
+    {
+        if (collection.empty())
+            return collection.end();
+
+        LLSettingsDay::CycleTrack_t::iterator it = collection.lower_bound(key);
+
+        if (it == collection.end())
+        {   // all keyframes are lower, take the last one.
+            --it; // we know the range is not empty
+        }
+        else if ((*it).first > key)
+        {   // the keyframe we are interested in is smaller than the found.
+            if (it == collection.begin())
+                it = collection.end();
+            --it;
+        }
+
+        return it;
+    }
+
+
+}
+
+//=========================================================================
+const std::string LLSettingsDay::SETTING_KEYID("key_id");
+const std::string LLSettingsDay::SETTING_KEYNAME("key_name");
+const std::string LLSettingsDay::SETTING_KEYKFRAME("key_keyframe");
+const std::string LLSettingsDay::SETTING_KEYHASH("key_hash");
+const std::string LLSettingsDay::SETTING_TRACKS("tracks");
+const std::string LLSettingsDay::SETTING_FRAMES("frames");
+
+const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYLENGTH(14400);  // 4 hours
+const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYLENGTH(14400);  // 4 hours
+const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYLENGTH(604800); // 7 days
+
+const LLSettingsDay::Seconds LLSettingsDay::MINIMUM_DAYOFFSET(0);
+const LLSettingsDay::Seconds LLSettingsDay::DEFAULT_DAYOFFSET(57600);  // +16 hours == -8 hours (SLT time offset)
+const LLSettingsDay::Seconds LLSettingsDay::MAXIMUM_DAYOFFSET(86400);  // 24 hours
+
+const S32 LLSettingsDay::TRACK_WATER(0);   // water track is 0
+const S32 LLSettingsDay::TRACK_GROUND_LEVEL(1);
+const S32 LLSettingsDay::TRACK_MAX(5);     // 5 tracks, 4 skys, 1 water
+const S32 LLSettingsDay::FRAME_MAX(56);
+
+const F32 LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR(0.02501f);
+
+const LLUUID LLSettingsDay::DEFAULT_ASSET_ID("5646d39e-d3d7-6aff-ed71-30fc87d64a91");
+
+// Minimum value to prevent multislider in edit floaters from eating up frames that 'encroach' on one another's space
+static const F32 DEFAULT_MULTISLIDER_INCREMENT(0.005f);
+//=========================================================================
+LLSettingsDay::LLSettingsDay(const LLSD &data) :
+    LLSettingsBase(data),
+    mInitialized(false)
+{
+    mDayTracks.resize(TRACK_MAX);
+}
+
+LLSettingsDay::LLSettingsDay() :
+    LLSettingsBase(),
+    mInitialized(false)
+{
+    mDayTracks.resize(TRACK_MAX);
+}
+
+//=========================================================================
+LLSD LLSettingsDay::getSettings() const
+{
+    LLSD settings(LLSD::emptyMap());
+
+    if (mSettings.has(SETTING_NAME))
+        settings[SETTING_NAME] = mSettings[SETTING_NAME];
+
+    if (mSettings.has(SETTING_ID))
+        settings[SETTING_ID] = mSettings[SETTING_ID];
+
+    if (mSettings.has(SETTING_ASSETID))
+        settings[SETTING_ASSETID] = mSettings[SETTING_ASSETID];
+
+    settings[SETTING_TYPE] = getSettingsType();
+
+    std::map<std::string, LLSettingsBase::ptr_t> in_use;
+
+    LLSD tracks(LLSD::emptyArray());
+    
+    for (CycleList_t::const_iterator itTrack = mDayTracks.begin(); itTrack != mDayTracks.end(); ++itTrack)
+    {
+        LLSD trackout(LLSD::emptyArray());
+
+        for (CycleTrack_t::const_iterator itFrame = (*itTrack).begin(); itFrame != (*itTrack).end(); ++itFrame)
+        {
+            F32 frame = (*itFrame).first;
+            LLSettingsBase::ptr_t data = (*itFrame).second;
+            size_t datahash = data->getHash();
+
+            std::stringstream keyname;
+            keyname << datahash;
+
+            trackout.append(LLSD(LLSDMap(SETTING_KEYKFRAME, LLSD::Real(frame))(SETTING_KEYNAME, keyname.str())));
+            in_use[keyname.str()] = data;
+        }
+        tracks.append(trackout);
+    }
+    settings[SETTING_TRACKS] = tracks;
+
+    LLSD frames(LLSD::emptyMap());
+    for (std::map<std::string, LLSettingsBase::ptr_t>::iterator itFrame = in_use.begin(); itFrame != in_use.end(); ++itFrame)
+    {
+        LLSD framesettings = llsd_clone((*itFrame).second->getSettings(),
+            LLSDMap("*", true)(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false));
+
+        frames[(*itFrame).first] = framesettings;
+    }
+    settings[SETTING_FRAMES] = frames;
+
+    return settings;
+}
+
+bool LLSettingsDay::initialize(bool validate_frames)
+{
+    LLSD tracks = mSettings[SETTING_TRACKS];
+    LLSD frames = mSettings[SETTING_FRAMES];
+
+    // save for later... 
+    LLUUID assetid;
+    if (mSettings.has(SETTING_ASSETID))
+    {
+        assetid = mSettings[SETTING_ASSETID].asUUID();
+    }
+
+    std::map<std::string, LLSettingsBase::ptr_t> used;
+
+    for (LLSD::map_const_iterator itFrame = frames.beginMap(); itFrame != frames.endMap(); ++itFrame)
+    {
+        std::string name = (*itFrame).first;
+        LLSD data = (*itFrame).second;
+        LLSettingsBase::ptr_t keyframe;
+
+        if (data[SETTING_TYPE].asString() == "sky")
+        {
+            keyframe = buildSky(data);
+        }
+        else if (data[SETTING_TYPE].asString() == "water")
+        {
+            keyframe = buildWater(data);
+        }
+        else
+        {
+            LL_WARNS("DAYCYCLE") << "Unknown child setting type '" << data[SETTING_TYPE].asString() << "' named '" << name << "'" << LL_ENDL;
+        }
+        if (!keyframe)
+        {
+            LL_WARNS("DAYCYCLE") << "Invalid frame data" << LL_ENDL;
+            continue;
+        }
+
+        used[name] = keyframe;
+    }
+
+    bool haswater(false);
+    bool hassky(false);
+
+    for (S32 i = 0; (i < tracks.size()) && (i < TRACK_MAX); ++i)
+    {
+        mDayTracks[i].clear();
+        LLSD curtrack = tracks[i];
+        for (LLSD::array_const_iterator it = curtrack.beginArray(); it != curtrack.endArray(); ++it)
+        {
+            LLSettingsBase::TrackPosition keyframe = LLSettingsBase::TrackPosition((*it)[SETTING_KEYKFRAME].asReal());
+            keyframe = llclamp(keyframe, 0.0f, 1.0f);
+            LLSettingsBase::ptr_t setting;
+
+            
+            if ((*it).has(SETTING_KEYNAME))
+            {
+                std::string key_name = (*it)[SETTING_KEYNAME];
+                if (i == TRACK_WATER)
+                {
+                    setting = used[key_name];
+                    if (setting && setting->getSettingsType() != "water")
+                    {
+                        LL_WARNS("DAYCYCLE") << "Water track referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL;
+                        setting.reset();
+                    }
+                }
+                else
+                {
+                    setting = used[key_name];
+                    if (setting && setting->getSettingsType() != "sky")
+                    {
+                        LL_WARNS("DAYCYCLE") << "Sky track #" << i << " referencing " << setting->getSettingsType() << " frame at " << keyframe << "." << LL_ENDL;
+                        setting.reset();
+                    }
+                }
+            }
+
+            if (setting)
+            {
+                if (i == TRACK_WATER)
+                    haswater |= true;
+                else
+                    hassky |= true;
+
+                if (validate_frames && mDayTracks[i].size() > 0)
+                {
+                    // check if we hit close to anything in the list
+                    LLSettingsDay::CycleTrack_t::value_type frame = getSettingsNearKeyframe(keyframe, i, DEFAULT_FRAME_SLOP_FACTOR);
+                    if (frame.second)
+                    {
+                        // figure out direction of search
+                        LLSettingsBase::TrackPosition found = frame.first;
+                        LLSettingsBase::TrackPosition new_frame = keyframe;
+                        F32 total_frame_shift = 0;
+                        // We consider frame DEFAULT_FRAME_SLOP_FACTOR away as still encroaching, so add minimum increment
+                        F32 move_factor = DEFAULT_FRAME_SLOP_FACTOR + DEFAULT_MULTISLIDER_INCREMENT;
+                        bool move_forward = true;
+                        if ((new_frame < found && (found - new_frame) <= DEFAULT_FRAME_SLOP_FACTOR)
+                            || (new_frame > found && (new_frame - found) > DEFAULT_FRAME_SLOP_FACTOR))
+                        {
+                            move_forward = false;
+                        }
+
+                        if (move_forward)
+                        {
+                            CycleTrack_t::iterator iter = mDayTracks[i].find(found);
+                            new_frame = found; // for total_frame_shift
+                            while (total_frame_shift < 1)
+                            {
+                                // calculate shifted position from previous found point
+                                total_frame_shift += move_factor + (found >= new_frame ? found : found + 1) - new_frame;
+                                new_frame = found + move_factor;
+                                if (new_frame > 1) new_frame--;
+
+                                // we know that current point is too close, go for next one
+                                iter++;
+                                if (iter == mDayTracks[i].end())
+                                {
+                                    iter = mDayTracks[i].begin();
+                                }
+
+                                if (((iter->first >= (new_frame - DEFAULT_MULTISLIDER_INCREMENT)) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= iter->first))
+                                    || ((iter->first < new_frame) && ((new_frame + DEFAULT_FRAME_SLOP_FACTOR) >= (iter->first + 1))))
+                                {
+                                    // we are encroaching at new point as well
+                                    found = iter->first;
+                                }
+                                else // (new_frame + DEFAULT_FRAME_SLOP_FACTOR < iter->first)
+                                {
+                                    //we found clear spot
+                                    break;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            CycleTrack_t::reverse_iterator iter = mDayTracks[i].rbegin();
+                            while (iter->first != found)
+                            {
+                                iter++;
+                            }
+                            new_frame = found; // for total_frame_shift
+                            while (total_frame_shift < 1)
+                            {
+                                // calculate shifted position from current found point
+                                total_frame_shift += move_factor + new_frame - (found <= new_frame ? found : found - 1);
+                                new_frame = found - move_factor;
+                                if (new_frame < 0) new_frame++;
+
+                                // we know that current point is too close, go for next one
+                                iter++;
+                                if (iter == mDayTracks[i].rend())
+                                {
+                                    iter = mDayTracks[i].rbegin();
+                                }
+
+                                if ((iter->first <= (new_frame + DEFAULT_MULTISLIDER_INCREMENT) && (new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= iter->first)
+                                    || ((iter->first > new_frame) && ((new_frame - DEFAULT_FRAME_SLOP_FACTOR) <= (iter->first - 1))))
+                                {
+                                    // we are encroaching at new point as well
+                                    found = iter->first;
+                                }
+                                else // (new_frame - DEFAULT_FRAME_SLOP_FACTOR > iter->first)
+                                {
+                                    //we found clear spot
+                                    break;
+                                }
+                            }
+
+
+                        }
+
+                        if (total_frame_shift >= 1)
+                        {
+                            LL_WARNS("SETTINGS") << "Could not fix frame position, adding as is to position: " << keyframe << LL_ENDL;
+                        }
+                        else
+                        {
+                            // Mark as new position
+                            keyframe = new_frame;
+                        }
+                    }
+                }
+                mDayTracks[i][keyframe] = setting;
+            }
+        }
+    }
+
+    if (!haswater || !hassky)
+    {
+        LL_WARNS("DAYCYCLE") << "Must have at least one water and one sky frame!" << LL_ENDL;
+        return false;
+    }
+    // these are no longer needed and just take up space now.
+    mSettings.erase(SETTING_TRACKS);
+    mSettings.erase(SETTING_FRAMES);
+
+    if (!assetid.isNull())
+    {
+        mSettings[SETTING_ASSETID] = assetid;
+    }
+
+    mInitialized = true;
+    return true;
+}
+
+
+//=========================================================================
+LLSD LLSettingsDay::defaults()
+{
+    static LLSD dfltsetting;
+
+    if (dfltsetting.size() == 0)
+    {
+        dfltsetting[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
+        dfltsetting[SETTING_TYPE] = "daycycle";
+
+        LLSD frames(LLSD::emptyMap());
+        LLSD waterTrack;
+        LLSD skyTrack;
+
+    
+        const U32 FRAME_COUNT = 8;
+        const F32 FRAME_STEP  = 1.0f / F32(FRAME_COUNT);
+        F32 time = 0.0f;
+        for (U32 i = 0; i < FRAME_COUNT; i++)
+        {
+            std::string name(DEFAULT_SETTINGS_NAME);
+            name += ('a' + i);
+
+            std::string water_frame_name("water:");
+            std::string sky_frame_name("sky:");
+
+            water_frame_name += name;
+            sky_frame_name   += name;
+
+            waterTrack[SETTING_KEYKFRAME] = time;
+            waterTrack[SETTING_KEYNAME]   = water_frame_name;
+
+            skyTrack[SETTING_KEYKFRAME] = time;
+            skyTrack[SETTING_KEYNAME]   = sky_frame_name;
+
+            frames[water_frame_name] = LLSettingsWater::defaults(time);
+            frames[sky_frame_name]   = LLSettingsSky::defaults(time);
+
+            time += FRAME_STEP;
+        }
+
+        LLSD tracks;
+        tracks.append(LLSDArray(waterTrack));
+        tracks.append(LLSDArray(skyTrack));
+
+        dfltsetting[SETTING_TRACKS] = tracks;
+        dfltsetting[SETTING_FRAMES] = frames;
+    }
+
+    return dfltsetting;
+}
+
+void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix)
+{
+    LL_ERRS("DAYCYCLE") << "Day cycles are not blendable!" << LL_ENDL;
+}
+
+namespace
+{
+    bool validateDayCycleTrack(LLSD &value)
+    {
+        // Trim extra tracks.
+        while (value.size() > LLSettingsDay::TRACK_MAX)
+        {
+            value.erase(value.size() - 1);
+        }
+
+        S32 framecount(0);
+
+        for (LLSD::array_iterator track = value.beginArray(); track != value.endArray(); ++track)
+        {
+            S32 index = 0;
+            while (index < (*track).size())
+            {
+                LLSD& elem = (*track)[index];
+
+                ++framecount;
+                if (index >= LLSettingsDay::FRAME_MAX)
+                {
+                    (*track).erase(index);
+                    continue;
+                }
+
+                if (!elem.has(LLSettingsDay::SETTING_KEYKFRAME))
+                {
+                    (*track).erase(index);
+                    continue;
+                }
+
+                if (!elem[LLSettingsDay::SETTING_KEYKFRAME].isReal())
+                {
+                    (*track).erase(index);
+                    continue;
+                }
+
+                if (!elem.has(LLSettingsDay::SETTING_KEYNAME) &&
+                    !elem.has(LLSettingsDay::SETTING_KEYID))
+                {
+                    (*track).erase(index);
+                    continue;
+                }
+
+                LLSettingsBase::TrackPosition frame = elem[LLSettingsDay::SETTING_KEYKFRAME].asReal();
+                if ((frame < 0.0) || (frame > 1.0))
+                {
+                    frame = llclamp(frame, 0.0f, 1.0f);
+                    elem[LLSettingsDay::SETTING_KEYKFRAME] = frame;
+                }
+                ++index;
+            }
+
+        }
+
+        int waterTracks = value[0].size();
+        int skyTracks   = framecount - waterTracks;
+
+        if (waterTracks < 1)
+        {
+            LL_WARNS("SETTINGS") << "Missing water track" << LL_ENDL;
+            return false;
+        }
+
+        if (skyTracks < 1)
+        {
+            LL_WARNS("SETTINGS") << "Missing sky tracks" << LL_ENDL;
+            return false;
+        }
+        return true;
+    }
+
+    bool validateDayCycleFrames(LLSD &value)
+    {
+        bool hasSky(false);
+        bool hasWater(false);
+
+        for (LLSD::map_iterator itf = value.beginMap(); itf != value.endMap(); ++itf)
+        {
+            LLSD frame = (*itf).second;
+
+            std::string ftype = frame[LLSettingsBase::SETTING_TYPE];
+            if (ftype == "sky")
+            {
+                LLSettingsSky::validation_list_t valid_sky = LLSettingsSky::validationList();
+                LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky);
+                
+                if (res_sky["success"].asInteger() == 0)
+                {
+                    LL_WARNS("SETTINGS") << "Sky setting named '" << (*itf).first << "' validation failed!: " << res_sky << LL_ENDL;
+                    LL_WARNS("SETTINGS") << "Sky: " << frame << LL_ENDL;
+                    continue;
+                }
+                hasSky |= true;
+            }
+            else if (ftype == "water")
+            {
+                LLSettingsWater::validation_list_t valid_h2o = LLSettingsWater::validationList();
+                LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o);
+                if (res_h2o["success"].asInteger() == 0)
+                {
+                    LL_WARNS("SETTINGS") << "Water setting named '" << (*itf).first << "' validation failed!: " << res_h2o << LL_ENDL;
+                    LL_WARNS("SETTINGS") << "Water: " << frame << LL_ENDL;
+                    continue;
+                }
+                hasWater |= true;
+            }
+            else
+            {
+                LL_WARNS("SETTINGS") << "Unknown settings block of type '" << ftype << "' named '" << (*itf).first << "'" << LL_ENDL;
+                return false;
+            }
+        }
+
+        if (!hasSky)
+        {
+            LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
+            return false;
+        }
+
+        if (!hasWater)
+        {
+            LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
+            return false;
+        }
+
+        return true;
+    }
+}
+
+LLSettingsDay::validation_list_t LLSettingsDay::getValidationList() const
+{
+    return LLSettingsDay::validationList();
+}
+
+LLSettingsDay::validation_list_t LLSettingsDay::validationList()
+{
+    static validation_list_t validation;
+
+    if (validation.empty())
+    {
+        validation.push_back(Validator(SETTING_TRACKS, true, LLSD::TypeArray, 
+            &validateDayCycleTrack));
+        validation.push_back(Validator(SETTING_FRAMES, true, LLSD::TypeMap, 
+            &validateDayCycleFrames));
+    }
+
+    return validation;
+}
+
+LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrack(S32 track)
+{
+    static CycleTrack_t emptyTrack;
+    if (mDayTracks.size() <= track)
+        return emptyTrack;
+
+    return mDayTracks[track];
+}
+
+const LLSettingsDay::CycleTrack_t& LLSettingsDay::getCycleTrackConst(S32 track) const
+{
+    static CycleTrack_t emptyTrack;
+    if (mDayTracks.size() <= track)
+        return emptyTrack;
+
+    return mDayTracks[track];
+}
+
+bool LLSettingsDay::clearCycleTrack(S32 track)
+{
+    if ((track < 0) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to clear track (#" << track << ") out of range!" << LL_ENDL;
+        return false;
+    }
+    mDayTracks[track].clear();
+    clearAssetId();
+    setDirtyFlag(true);
+    return true;
+}
+
+bool LLSettingsDay::replaceCycleTrack(S32 track, const CycleTrack_t &source)
+{
+    if (source.empty())
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to copy an empty track." << LL_ENDL;
+        return false;
+    }
+
+    {
+        LLSettingsBase::ptr_t   first((*source.begin()).second);
+        std::string setting_type = first->getSettingsType();
+
+        if (((setting_type == "water") && (track != 0)) ||
+            ((setting_type == "sky") && (track == 0)))
+        {
+            LL_WARNS("DAYCYCLE") << "Attempt to copy track missmatch" << LL_ENDL;
+            return false;
+        }
+    }
+
+    if (!clearCycleTrack(track))
+        return false;
+
+    mDayTracks[track] = source;
+    return true;
+}
+
+
+bool LLSettingsDay::isTrackEmpty(S32 track) const
+{
+    if ((track < 0) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to test track (#" << track << ") out of range!" << LL_ENDL;
+        return true;
+    }
+
+    return mDayTracks[track].empty();
+}
+
+//=========================================================================
+void LLSettingsDay::startDayCycle()
+{
+    if (!mInitialized)
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to start day cycle on uninitialized object." << LL_ENDL;
+        return;
+    }
+}
+
+
+void LLSettingsDay::updateSettings()
+{
+}
+
+//=========================================================================
+LLSettingsDay::KeyframeList_t LLSettingsDay::getTrackKeyframes(S32 trackno)
+{
+    if ((trackno < 0) || (trackno >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
+        return KeyframeList_t();
+    }
+
+    KeyframeList_t keyframes;
+    CycleTrack_t &track = mDayTracks[trackno];
+
+    keyframes.reserve(track.size());
+
+    for (CycleTrack_t::iterator it = track.begin(); it != track.end(); ++it)
+    {
+        keyframes.push_back((*it).first);
+    }
+
+    return keyframes;
+}
+
+bool LLSettingsDay::moveTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame)
+{
+    if ((trackno < 0) || (trackno >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
+        return false;
+    }
+
+    if (llabs(old_frame - new_frame) < F_APPROXIMATELY_ZERO)
+    {
+        return false;
+    }
+
+    CycleTrack_t &track = mDayTracks[trackno];
+    CycleTrack_t::iterator iter = track.find(old_frame);
+    if (iter != track.end())
+    {
+        LLSettingsBase::ptr_t base = iter->second;
+        track.erase(iter);
+        track[llclamp(new_frame, 0.0f, 1.0f)] = base;
+        track[new_frame] = base;
+        return true;
+    }
+
+    return false;
+
+}
+
+bool LLSettingsDay::removeTrackKeyframe(S32 trackno, const LLSettingsBase::TrackPosition& frame)
+{
+    if ((trackno < 0) || (trackno >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt get track (#" << trackno << ") out of range!" << LL_ENDL;
+        return false;
+    }
+
+    CycleTrack_t &track = mDayTracks[trackno];
+    CycleTrack_t::iterator iter = track.find(frame);
+    if (iter != track.end())
+    {
+        LLSettingsBase::ptr_t base = iter->second;
+        track.erase(iter);
+        return true;
+    }
+
+    return false;
+}
+
+void LLSettingsDay::setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe)
+{
+    setSettingsAtKeyframe(water, keyframe, TRACK_WATER);
+}
+
+LLSettingsWater::ptr_t LLSettingsDay::getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const
+{
+    LLSettingsBase* p = getSettingsAtKeyframe(keyframe, TRACK_WATER).get();
+    return LLSettingsWater::ptr_t((LLSettingsWater*)p);
+}
+
+void LLSettingsDay::setSkyAtKeyframe(const LLSettingsSky::ptr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track)
+{
+    if ((track < 1) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
+        return;
+    }
+
+    setSettingsAtKeyframe(sky, keyframe, track);
+}
+
+LLSettingsSky::ptr_t LLSettingsDay::getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const
+{
+    if ((track < 1) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
+        return LLSettingsSky::ptr_t();
+    }
+
+    return PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(getSettingsAtKeyframe(keyframe, track));
+}
+
+void LLSettingsDay::setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track)
+{
+    if ((track < 0) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to set track (#" << track << ") out of range!" << LL_ENDL;
+        return;
+    }
+
+    std::string type = settings->getSettingsType();
+    if ((track == TRACK_WATER) && (type != "water"))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to water track!" << LL_ENDL;
+        llassert(type == "water");
+        return;
+    }
+    else if ((track != TRACK_WATER) && (type != "sky"))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to add frame of type '" << type << "' to sky track!" << LL_ENDL;
+        llassert(type == "sky");
+        return;
+    }
+
+    mDayTracks[track][llclamp(keyframe, 0.0f, 1.0f)] = settings;
+    setDirtyFlag(true);
+}
+
+LLSettingsBase::ptr_t LLSettingsDay::getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const
+{
+    if ((track < 0) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to set sky track (#" << track << ") out of range!" << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    // todo: better way to identify keyframes?
+    CycleTrack_t::const_iterator iter = mDayTracks[track].find(keyframe);
+    if (iter != mDayTracks[track].end())
+    {
+        return iter->second;
+    }
+
+    return LLSettingsBase::ptr_t();
+}
+
+LLSettingsDay::CycleTrack_t::value_type LLSettingsDay::getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const
+{
+    if ((track < 0) || (track >= TRACK_MAX))
+    {
+        LL_WARNS("DAYCYCLE") << "Attempt to get track (#" << track << ") out of range!" << LL_ENDL;
+        return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
+    }
+
+    if (mDayTracks[track].empty())
+    {
+        LL_INFOS("DAYCYCLE") << "Empty track" << LL_ENDL;
+        return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
+    }
+
+    TrackPosition startframe(keyframe - fudge);
+    if (startframe < 0.0f)
+        startframe = 1.0f + startframe;
+
+    LLSettingsDay::CycleTrack_t collection = const_cast<CycleTrack_t &>(mDayTracks[track]);
+    CycleTrack_t::iterator it = get_wrapping_atafter(collection, startframe);
+
+    F32 dist = get_wrapping_distance(startframe, (*it).first);
+
+    CycleTrack_t::iterator next_it = std::next(it);
+    if ((dist <= DEFAULT_MULTISLIDER_INCREMENT) && next_it != collection.end())
+        return (*next_it);
+    else if (dist <= (fudge * 2.0f))
+        return (*it);
+
+    return CycleTrack_t::value_type(TrackPosition(INVALID_TRACKPOS), LLSettingsBase::ptr_t());
+}
+
+LLSettingsBase::TrackPosition LLSettingsDay::getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe)
+{
+    return get_wrapping_atafter(mDayTracks[track], keyframe)->first;
+}
+
+LLSettingsBase::TrackPosition LLSettingsDay::getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe)
+{
+    return get_wrapping_atbefore(mDayTracks[track], keyframe)->first;
+}
+
+LLSettingsDay::TrackBound_t LLSettingsDay::getBoundingEntries(LLSettingsDay::CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe)
+{
+    return TrackBound_t(get_wrapping_atbefore(track, keyframe), get_wrapping_atafter(track, keyframe));
+}
+
+LLUUID LLSettingsDay::GetDefaultAssetId()
+{
+    return DEFAULT_ASSET_ID;
+}
+
+//=========================================================================
diff --git a/indra/llinventory/llsettingsdaycycle.h b/indra/llinventory/llsettingsdaycycle.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7f5bb63b667e982b94155bc7a60edf72b1b5849
--- /dev/null
+++ b/indra/llinventory/llsettingsdaycycle.h
@@ -0,0 +1,154 @@
+/**
+* @file llsettingsdaycycle.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_SETTINGS_DAYCYCLE_H
+#define LL_SETTINGS_DAYCYCLE_H
+
+#include "llsettingsbase.h"
+
+class LLSettingsWater;
+class LLSettingsSky;
+
+// These are alias for LLSettingsWater::ptr_t and LLSettingsSky::ptr_t respectively.
+// Here for definitions only.
+typedef PTR_NAMESPACE::shared_ptr<LLSettingsWater> LLSettingsWaterPtr_t;
+typedef PTR_NAMESPACE::shared_ptr<LLSettingsSky> LLSettingsSkyPtr_t;
+
+class LLSettingsDay : public LLSettingsBase
+{
+public:
+    // 32-bit as LLSD only supports that width at present
+    typedef S32Seconds Seconds;
+
+    static const std::string    SETTING_KEYID;
+    static const std::string    SETTING_KEYNAME;
+    static const std::string    SETTING_KEYKFRAME;
+    static const std::string    SETTING_KEYHASH;
+    static const std::string    SETTING_TRACKS;
+    static const std::string    SETTING_FRAMES;
+
+    static const Seconds MINIMUM_DAYLENGTH;
+    static const Seconds DEFAULT_DAYLENGTH;
+    static const Seconds MAXIMUM_DAYLENGTH;
+
+    static const Seconds MINIMUM_DAYOFFSET;
+    static const Seconds DEFAULT_DAYOFFSET;
+    static const Seconds MAXIMUM_DAYOFFSET;
+
+    static const S32     TRACK_WATER;
+    static const S32     TRACK_GROUND_LEVEL;
+    static const S32     TRACK_MAX;
+    static const S32     FRAME_MAX;
+
+    static const F32     DEFAULT_FRAME_SLOP_FACTOR;
+
+    static const LLUUID DEFAULT_ASSET_ID;
+
+    typedef std::map<LLSettingsBase::TrackPosition, LLSettingsBase::ptr_t>  CycleTrack_t;
+    typedef std::vector<CycleTrack_t>                                       CycleList_t;
+    typedef PTR_NAMESPACE::shared_ptr<LLSettingsDay>                        ptr_t;
+    typedef PTR_NAMESPACE::weak_ptr<LLSettingsDay>                          wptr_t;
+    typedef std::vector<LLSettingsBase::TrackPosition>                      KeyframeList_t;
+    typedef std::pair<CycleTrack_t::iterator, CycleTrack_t::iterator>       TrackBound_t;
+
+    //---------------------------------------------------------------------
+    LLSettingsDay(const LLSD &data);
+    virtual ~LLSettingsDay() { };
+
+    bool                        initialize(bool validate_frames = false);
+
+    virtual ptr_t               buildClone() const = 0;
+    virtual ptr_t               buildDeepCloneAndUncompress() const = 0;
+    virtual LLSD                getSettings() const SETTINGS_OVERRIDE;
+    virtual LLSettingsType::type_e  getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; }
+
+
+    //---------------------------------------------------------------------
+    virtual std::string         getSettingsType() const SETTINGS_OVERRIDE { return std::string("daycycle"); }
+
+    // Settings status 
+    virtual void                blend(const LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE;
+
+    static LLSD                 defaults();
+
+    //---------------------------------------------------------------------
+    KeyframeList_t              getTrackKeyframes(S32 track);
+    bool                        moveTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& old_frame, const LLSettingsBase::TrackPosition& new_frame);
+    bool                        removeTrackKeyframe(S32 track, const LLSettingsBase::TrackPosition& frame);
+
+    void                        setWaterAtKeyframe(const LLSettingsWaterPtr_t &water, const LLSettingsBase::TrackPosition& keyframe);
+    LLSettingsWaterPtr_t        getWaterAtKeyframe(const LLSettingsBase::TrackPosition& keyframe) const;
+    void                        setSkyAtKeyframe(const LLSettingsSkyPtr_t &sky, const LLSettingsBase::TrackPosition& keyframe, S32 track);
+    LLSettingsSkyPtr_t          getSkyAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const;
+    void                        setSettingsAtKeyframe(const LLSettingsBase::ptr_t &settings, const LLSettingsBase::TrackPosition& keyframe, S32 track);
+    LLSettingsBase::ptr_t       getSettingsAtKeyframe(const LLSettingsBase::TrackPosition& keyframe, S32 track) const;
+    CycleTrack_t::value_type    getSettingsNearKeyframe(const LLSettingsBase::TrackPosition &keyframe, S32 track, F32 fudge) const;
+
+        //---------------------------------------------------------------------
+    void                        startDayCycle();
+
+    virtual LLSettingsSkyPtr_t  getDefaultSky() const = 0;
+    virtual LLSettingsWaterPtr_t getDefaultWater() const = 0;
+
+    virtual LLSettingsSkyPtr_t  buildSky(LLSD) const = 0;
+    virtual LLSettingsWaterPtr_t buildWater(LLSD) const = 0;
+
+    void                        setInitialized(bool value = true) { mInitialized = value; }
+    CycleTrack_t &              getCycleTrack(S32 track);
+    const CycleTrack_t &        getCycleTrackConst(S32 track) const;
+    bool                        clearCycleTrack(S32 track);
+    bool                        replaceCycleTrack(S32 track, const CycleTrack_t &source);
+    bool                        isTrackEmpty(S32 track) const;
+
+    virtual validation_list_t   getValidationList() const SETTINGS_OVERRIDE;
+    static validation_list_t    validationList();
+
+    virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
+	
+    LLSettingsBase::TrackPosition getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
+    LLSettingsBase::TrackPosition getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
+
+    static LLUUID GetDefaultAssetId();
+
+protected:
+    LLSettingsDay();
+
+    virtual void                updateSettings() SETTINGS_OVERRIDE;
+
+    bool                        mInitialized;
+
+private:
+    CycleList_t                 mDayTracks;
+
+    LLSettingsBase::Seconds     mLastUpdateTime;
+
+    static CycleTrack_t::iterator   getEntryAtOrBefore(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
+    static CycleTrack_t::iterator   getEntryAtOrAfter(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
+    TrackBound_t                    getBoundingEntries(CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe);
+};
+
+#endif
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..306c73292057c05f4da4fe5b2e481d6a8413cdb2
--- /dev/null
+++ b/indra/llinventory/llsettingssky.cpp
@@ -0,0 +1,1757 @@
+/**
+* @file llsettingssky.cpp
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "llsettingssky.h"
+#include "indra_constants.h"
+#include <algorithm>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+
+//=========================================================================
+namespace
+{
+    const LLUUID IMG_BLOOM1("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef");
+    const LLUUID IMG_RAINBOW("11b4c57c-56b3-04ed-1f82-2004363882e4");
+    const LLUUID IMG_HALO("12149143-f599-91a7-77ac-b52a3c0f59cd");
+}
+
+namespace {
+    LLQuaternion convert_azimuth_and_altitude_to_quat(F32 azimuth, F32 altitude)
+    {
+        F32 sinTheta = sin(azimuth);
+        F32 cosTheta = cos(azimuth);
+        F32 sinPhi   = sin(altitude);
+        F32 cosPhi   = cos(altitude);
+
+        LLVector3 dir;
+        // +x right, +z up, +y at...	
+        dir.mV[0] = cosTheta * cosPhi;
+        dir.mV[1] = sinTheta * cosPhi;	
+        dir.mV[2] = sinPhi;
+
+        LLVector3 axis = LLVector3::x_axis % dir;
+        axis.normalize();
+
+        F32 angle = acos(LLVector3::x_axis * dir);
+
+        LLQuaternion quat;
+        quat.setAngleAxis(angle, axis);
+
+        return quat;
+    }
+}
+
+static LLTrace::BlockTimerStatHandle FTM_BLEND_SKYVALUES("Blending Sky Environment");
+static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_SKYVALUES("Recalculate Sky");
+static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_BODIES("Recalculate Heavenly Bodies");
+static LLTrace::BlockTimerStatHandle FTM_RECALCULATE_LIGHTING("Recalculate Lighting");
+
+//=========================================================================
+const std::string LLSettingsSky::SETTING_AMBIENT("ambient");
+const std::string LLSettingsSky::SETTING_BLUE_DENSITY("blue_density");
+const std::string LLSettingsSky::SETTING_BLUE_HORIZON("blue_horizon");
+const std::string LLSettingsSky::SETTING_DENSITY_MULTIPLIER("density_multiplier");
+const std::string LLSettingsSky::SETTING_DISTANCE_MULTIPLIER("distance_multiplier");
+const std::string LLSettingsSky::SETTING_HAZE_DENSITY("haze_density");
+const std::string LLSettingsSky::SETTING_HAZE_HORIZON("haze_horizon");
+
+const std::string LLSettingsSky::SETTING_BLOOM_TEXTUREID("bloom_id");
+const std::string LLSettingsSky::SETTING_RAINBOW_TEXTUREID("rainbow_id");
+const std::string LLSettingsSky::SETTING_HALO_TEXTUREID("halo_id");
+const std::string LLSettingsSky::SETTING_CLOUD_COLOR("cloud_color");
+const std::string LLSettingsSky::SETTING_CLOUD_POS_DENSITY1("cloud_pos_density1");
+const std::string LLSettingsSky::SETTING_CLOUD_POS_DENSITY2("cloud_pos_density2");
+const std::string LLSettingsSky::SETTING_CLOUD_SCALE("cloud_scale");
+const std::string LLSettingsSky::SETTING_CLOUD_SCROLL_RATE("cloud_scroll_rate");
+const std::string LLSettingsSky::SETTING_CLOUD_SHADOW("cloud_shadow");
+const std::string LLSettingsSky::SETTING_CLOUD_TEXTUREID("cloud_id");
+const std::string LLSettingsSky::SETTING_CLOUD_VARIANCE("cloud_variance");
+
+const std::string LLSettingsSky::SETTING_DOME_OFFSET("dome_offset");
+const std::string LLSettingsSky::SETTING_DOME_RADIUS("dome_radius");
+const std::string LLSettingsSky::SETTING_GAMMA("gamma");
+const std::string LLSettingsSky::SETTING_GLOW("glow");
+
+const std::string LLSettingsSky::SETTING_LIGHT_NORMAL("lightnorm");
+const std::string LLSettingsSky::SETTING_MAX_Y("max_y");
+const std::string LLSettingsSky::SETTING_MOON_ROTATION("moon_rotation");
+const std::string LLSettingsSky::SETTING_MOON_SCALE("moon_scale");
+const std::string LLSettingsSky::SETTING_MOON_TEXTUREID("moon_id");
+const std::string LLSettingsSky::SETTING_MOON_BRIGHTNESS("moon_brightness");
+
+const std::string LLSettingsSky::SETTING_STAR_BRIGHTNESS("star_brightness");
+const std::string LLSettingsSky::SETTING_SUNLIGHT_COLOR("sunlight_color");
+const std::string LLSettingsSky::SETTING_SUN_ROTATION("sun_rotation");
+const std::string LLSettingsSky::SETTING_SUN_SCALE("sun_scale");
+const std::string LLSettingsSky::SETTING_SUN_TEXTUREID("sun_id");
+
+const std::string LLSettingsSky::SETTING_LEGACY_EAST_ANGLE("east_angle");
+const std::string LLSettingsSky::SETTING_LEGACY_ENABLE_CLOUD_SCROLL("enable_cloud_scroll");
+const std::string LLSettingsSky::SETTING_LEGACY_SUN_ANGLE("sun_angle");
+
+// these are new settings for the advanced atmospherics model
+const std::string LLSettingsSky::SETTING_PLANET_RADIUS("planet_radius");
+const std::string LLSettingsSky::SETTING_SKY_BOTTOM_RADIUS("sky_bottom_radius");
+const std::string LLSettingsSky::SETTING_SKY_TOP_RADIUS("sky_top_radius");
+const std::string LLSettingsSky::SETTING_SUN_ARC_RADIANS("sun_arc_radians");
+
+const std::string LLSettingsSky::SETTING_RAYLEIGH_CONFIG("rayleigh_config");
+const std::string LLSettingsSky::SETTING_MIE_CONFIG("mie_config");
+const std::string LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR("anisotropy");
+const std::string LLSettingsSky::SETTING_ABSORPTION_CONFIG("absorption_config");
+
+const std::string LLSettingsSky::KEY_DENSITY_PROFILE("density");
+const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH("width");
+const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM("exp_term");
+const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR("exp_scale");
+const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM("linear_term");
+const std::string LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM("constant_term");
+
+const std::string LLSettingsSky::SETTING_SKY_MOISTURE_LEVEL("moisture_level");
+const std::string LLSettingsSky::SETTING_SKY_DROPLET_RADIUS("droplet_radius");
+const std::string LLSettingsSky::SETTING_SKY_ICE_LEVEL("ice_level");
+
+const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("3ae23978-ac82-bcf3-a9cb-ba6e52dcb9ad");
+
+static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver
+static const LLUUID DEFAULT_MOON_ID("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
+static const LLUUID DEFAULT_CLOUD_ID("1dc1368f-e8fe-f02d-a08d-9d9f11c1af6b");
+
+const std::string LLSettingsSky::SETTING_LEGACY_HAZE("legacy_haze");
+
+const F32 LLSettingsSky::DOME_OFFSET(0.96f);
+const F32 LLSettingsSky::DOME_RADIUS(15000.f);
+
+namespace
+{
+
+LLSettingsSky::validation_list_t legacyHazeValidationList()
+{
+    static LLSettingsBase::validation_list_t legacyHazeValidation;
+    if (legacyHazeValidation.empty())
+    {
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT,             false,  LLSD::TypeArray, 
+            boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY,        false,  LLSD::TypeArray, 
+            boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON,        false,  LLSD::TypeArray, 
+            boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY,        false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON,        false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER,  false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(2.0f)))));
+        legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false,  LLSD::TypeReal,
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(1000.0f)))));
+    }
+    return legacyHazeValidation;
+}
+
+LLSettingsSky::validation_list_t rayleighValidationList()
+{
+    static LLSettingsBase::validation_list_t rayleighValidation;
+    if (rayleighValidation.empty())
+    {
+        rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH,      false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+
+        rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM,   false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+        
+        rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+
+        rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+
+        rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+    }
+    return rayleighValidation;
+}
+
+LLSettingsSky::validation_list_t absorptionValidationList()
+{
+    static LLSettingsBase::validation_list_t absorptionValidation;
+    if (absorptionValidation.empty())
+    {
+        absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH,      false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+
+        absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM,   false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+        
+        absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+
+        absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+
+        absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+    }
+    return absorptionValidation;
+}
+
+LLSettingsSky::validation_list_t mieValidationList()
+{
+    static LLSettingsBase::validation_list_t mieValidation;
+    if (mieValidation.empty())
+    {
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH,      false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM,   false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+        
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+
+        mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false,  LLSD::TypeReal,  
+            boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+    }
+    return mieValidation;
+}
+
+bool validateLegacyHaze(LLSD &value)
+{
+    LLSettingsSky::validation_list_t legacyHazeValidations = legacyHazeValidationList();
+    llassert(value.type() == LLSD::TypeMap);
+    LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations);
+    if (result["errors"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Legacy Haze Config Validation errors: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    if (result["warnings"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Legacy Haze Config Validation warnings: " << result["warnings"] << LL_ENDL;
+        return false;
+    }
+    return true;
+}
+
+bool validateRayleighLayers(LLSD &value)
+{
+    LLSettingsSky::validation_list_t rayleighValidations = rayleighValidationList();
+    if (value.isArray())
+    {
+        bool allGood = true;
+        for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf)
+        {
+            LLSD& layerConfig = (*itf);
+            if (layerConfig.type() == LLSD::TypeMap)
+            {
+                if (!validateRayleighLayers(layerConfig))
+                {
+                    allGood = false;
+                }
+            }
+            else if (layerConfig.type() == LLSD::TypeArray)
+            {
+                return validateRayleighLayers(layerConfig);
+            }
+            else
+            {
+                return LLSettingsBase::settingValidation(value, rayleighValidations);
+            }
+        }
+        return allGood;
+    }    
+    llassert(value.type() == LLSD::TypeMap);
+    LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations);
+    if (result["errors"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Rayleigh Config Validation errors: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    if (result["warnings"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Rayleigh Config Validation warnings: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    return true;
+}
+
+bool validateAbsorptionLayers(LLSD &value)
+{
+    LLSettingsBase::validation_list_t absorptionValidations = absorptionValidationList();
+    if (value.isArray())
+    {
+        bool allGood = true;   
+        for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf)
+        {
+            LLSD& layerConfig = (*itf);
+            if (layerConfig.type() == LLSD::TypeMap)
+            {
+                if (!validateAbsorptionLayers(layerConfig))
+                {
+                    allGood = false;
+                }
+            }
+            else if (layerConfig.type() == LLSD::TypeArray)
+            {
+                return validateAbsorptionLayers(layerConfig);
+            }
+            else
+            {
+                return LLSettingsBase::settingValidation(value, absorptionValidations);
+            }
+        }
+        return allGood;
+    }
+    llassert(value.type() == LLSD::TypeMap);
+    LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations);
+    if (result["errors"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Absorption Config Validation errors: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    if (result["warnings"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Absorption Config Validation warnings: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    return true;
+}
+
+bool validateMieLayers(LLSD &value)
+{
+    LLSettingsBase::validation_list_t mieValidations = mieValidationList();
+    if (value.isArray())
+    {
+        bool allGood = true;
+        for (LLSD::array_iterator itf = value.beginArray(); itf != value.endArray(); ++itf)
+        {
+            LLSD& layerConfig = (*itf);
+            if (layerConfig.type() == LLSD::TypeMap)
+            {
+                if (!validateMieLayers(layerConfig))
+                {
+                    allGood = false;
+                }
+            }
+            else if (layerConfig.type() == LLSD::TypeArray)
+            {
+                return validateMieLayers(layerConfig);
+            }
+            else
+            {
+                return LLSettingsBase::settingValidation(value, mieValidations);
+            }
+        }
+        return allGood;
+    }
+    LLSD result = LLSettingsBase::settingValidation(value, mieValidations);
+    if (result["errors"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Mie Config Validation errors: " << result["errors"] << LL_ENDL;
+        return false;
+    }
+    if (result["warnings"].size() > 0)
+    {
+        LL_WARNS("SETTINGS") << "Mie Config Validation warnings: " << result["warnings"] << LL_ENDL;
+        return false;
+    }
+    return true;
+}
+
+}
+
+//=========================================================================
+LLSettingsSky::LLSettingsSky(const LLSD &data) :
+    LLSettingsBase(data),
+    mNextSunTextureId(),
+    mNextMoonTextureId(),
+    mNextCloudTextureId(),
+    mNextBloomTextureId(),
+    mNextRainbowTextureId(),
+    mNextHaloTextureId()
+{
+}
+
+LLSettingsSky::LLSettingsSky():
+    LLSettingsBase(),
+    mNextSunTextureId(),
+    mNextMoonTextureId(),
+    mNextCloudTextureId(),
+    mNextBloomTextureId(),
+    mNextRainbowTextureId(),
+    mNextHaloTextureId()
+{
+}
+
+void LLSettingsSky::replaceSettings(LLSD settings)
+{
+    LLSettingsBase::replaceSettings(settings);
+    mNextSunTextureId.setNull();
+    mNextMoonTextureId.setNull();
+    mNextCloudTextureId.setNull();
+    mNextBloomTextureId.setNull();
+    mNextRainbowTextureId.setNull();
+    mNextHaloTextureId.setNull();
+}
+
+void LLSettingsSky::replaceWithSky(LLSettingsSky::ptr_t pother)
+{
+    replaceWith(pother);
+
+    mNextSunTextureId = pother->mNextSunTextureId;
+    mNextMoonTextureId = pother->mNextMoonTextureId;
+    mNextCloudTextureId = pother->mNextCloudTextureId;
+    mNextBloomTextureId = pother->mNextBloomTextureId;
+    mNextRainbowTextureId = pother->mNextRainbowTextureId;
+    mNextHaloTextureId = pother->mNextHaloTextureId;
+}
+
+void LLSettingsSky::blend(const LLSettingsBase::ptr_t &end, F64 blendf) 
+{
+    llassert(getSettingsType() == end->getSettingsType());
+
+    LLSettingsSky::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsSky>(end);
+    if (other)
+    {
+        if (other->mSettings.has(SETTING_LEGACY_HAZE))
+        {
+            if (!mSettings.has(SETTING_LEGACY_HAZE) || !mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT))
+            {
+                // Special case since SETTING_AMBIENT is both in outer and legacy maps, we prioritize legacy one
+                // see getAmbientColor(), we are about to replaceSettings(), so we are free to set it
+                setAmbientColor(getAmbientColor());
+            }
+        }
+        else
+        {
+            if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(SETTING_AMBIENT))
+            {
+                // Special case due to ambient's duality
+                // We need to match 'other's' structure for interpolation.
+                // We are free to change mSettings, since we are about to reset it
+                mSettings[SETTING_AMBIENT] = getAmbientColor().getValue();
+                mSettings[SETTING_LEGACY_HAZE].erase(SETTING_AMBIENT);
+            }
+        }
+
+        LLUUID cloud_noise_id = getCloudNoiseTextureId();
+        LLUUID cloud_noise_id_next = other->getCloudNoiseTextureId();
+        F64 cloud_shadow = 0;
+        if (!cloud_noise_id.isNull() && cloud_noise_id_next.isNull())
+        {
+            // If there is no cloud texture in destination, reduce coverage to imitate disappearance
+            // See LLDrawPoolWLSky::renderSkyClouds... we don't blend present texture with null
+            // Note: Probably can be done by shader
+            cloud_shadow = lerp(mSettings[SETTING_CLOUD_SHADOW].asReal(), (F64)0.f, blendf);
+            cloud_noise_id_next = cloud_noise_id;
+        }
+        else if (cloud_noise_id.isNull() && !cloud_noise_id_next.isNull())
+        {
+            // Source has no cloud texture, reduce initial coverage to imitate appearance
+            // use same texture as destination
+            cloud_shadow = lerp((F64)0.f, other->mSettings[SETTING_CLOUD_SHADOW].asReal(), blendf);
+            setCloudNoiseTextureId(cloud_noise_id_next);
+        }
+        else
+        {
+            cloud_shadow = lerp(mSettings[SETTING_CLOUD_SHADOW].asReal(), other->mSettings[SETTING_CLOUD_SHADOW].asReal(), blendf);
+        }
+
+        LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf);
+        blenddata[SETTING_CLOUD_SHADOW] = LLSD::Real(cloud_shadow);
+        replaceSettings(blenddata);
+        mNextSunTextureId = other->getSunTextureId();
+        mNextMoonTextureId = other->getMoonTextureId();
+        mNextCloudTextureId = cloud_noise_id_next;
+        mNextBloomTextureId = other->getBloomTextureId();
+        mNextRainbowTextureId = other->getRainbowTextureId();
+        mNextHaloTextureId = other->getHaloTextureId();
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Could not cast end settings to sky. No blend performed." << LL_ENDL;
+    }
+
+    setBlendFactor(blendf);
+}
+
+LLSettingsSky::stringset_t LLSettingsSky::getSkipInterpolateKeys() const
+{
+    static stringset_t skipSet;
+
+    if (skipSet.empty())
+    {
+        skipSet = LLSettingsBase::getSkipInterpolateKeys();
+        skipSet.insert(SETTING_RAYLEIGH_CONFIG);
+        skipSet.insert(SETTING_MIE_CONFIG);
+        skipSet.insert(SETTING_ABSORPTION_CONFIG);
+        skipSet.insert(SETTING_CLOUD_SHADOW);
+    }
+
+    return skipSet;
+}
+
+LLSettingsSky::stringset_t LLSettingsSky::getSlerpKeys() const 
+{ 
+    static stringset_t slepSet;
+
+    if (slepSet.empty())
+    {
+        slepSet.insert(SETTING_SUN_ROTATION);
+        slepSet.insert(SETTING_MOON_ROTATION);
+    }
+
+    return slepSet;
+}
+
+LLSettingsSky::validation_list_t LLSettingsSky::getValidationList() const
+{
+    return LLSettingsSky::validationList();
+}
+
+LLSettingsSky::validation_list_t LLSettingsSky::validationList()
+{
+    static validation_list_t validation;
+
+    if (validation.empty())
+    {   // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the 
+        // copy constructor for LLSDArray.  Directly binding the LLSDArray as 
+        // a parameter without first wrapping it in a pure LLSD object will result 
+        // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
+        validation.push_back(Validator(SETTING_BLOOM_TEXTUREID,     true,  LLSD::TypeUUID));
+        validation.push_back(Validator(SETTING_RAINBOW_TEXTUREID,   false,  LLSD::TypeUUID));
+        validation.push_back(Validator(SETTING_HALO_TEXTUREID,      false,  LLSD::TypeUUID));
+
+        validation.push_back(Validator(SETTING_CLOUD_COLOR,         true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
+        validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1,  true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(1.0f)(1.0f)(3.0f)("*")))));
+        validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2,  true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
+        validation.push_back(Validator(SETTING_CLOUD_SCALE,         true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.001f)(3.0f)))));
+        validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE,   true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(-50.0f)(-50.0f)),
+                LLSD(LLSDArray(50.0f)(50.0f)))));
+        validation.push_back(Validator(SETTING_CLOUD_SHADOW,        true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+        validation.push_back(Validator(SETTING_CLOUD_TEXTUREID,     false, LLSD::TypeUUID));
+        validation.push_back(Validator(SETTING_CLOUD_VARIANCE,      false,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+
+        validation.push_back(Validator(SETTING_DOME_OFFSET,         false, LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+        validation.push_back(Validator(SETTING_DOME_RADIUS,         false, LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(2000.0f)))));
+        validation.push_back(Validator(SETTING_GAMMA,               true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
+        validation.push_back(Validator(SETTING_GLOW,                true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.2f)("*")(-10.0f)("*")),
+                LLSD(LLSDArray(40.0f)("*")(10.0f)("*")))));
+        
+        validation.push_back(Validator(SETTING_MAX_Y,               true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(10000.0f)))));
+        validation.push_back(Validator(SETTING_MOON_ROTATION,       true,  LLSD::TypeArray, &Validator::verifyQuaternionNormal));
+        validation.push_back(Validator(SETTING_MOON_SCALE,          false, LLSD::TypeReal,
+                boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+        validation.push_back(Validator(SETTING_MOON_TEXTUREID,      false, LLSD::TypeUUID));
+        validation.push_back(Validator(SETTING_MOON_BRIGHTNESS,     false,  LLSD::TypeReal, 
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+
+        validation.push_back(Validator(SETTING_STAR_BRIGHTNESS,     true,  LLSD::TypeReal, 
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(500.0f)))));
+        validation.push_back(Validator(SETTING_SUNLIGHT_COLOR,      true,  LLSD::TypeArray, 
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
+                LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
+        validation.push_back(Validator(SETTING_SUN_ROTATION,        true,  LLSD::TypeArray, &Validator::verifyQuaternionNormal));
+        validation.push_back(Validator(SETTING_SUN_SCALE,           false, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+        validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID));
+
+        validation.push_back(Validator(SETTING_PLANET_RADIUS,       true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+
+        validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS,   true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+
+        validation.push_back(Validator(SETTING_SKY_TOP_RADIUS,       true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+
+        validation.push_back(Validator(SETTING_SUN_ARC_RADIANS,      true,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(0.1f)))));
+
+        validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL,      false,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+
+        validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS,      false,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(5.0f)(1000.0f)))));
+
+        validation.push_back(Validator(SETTING_SKY_ICE_LEVEL,      false,  LLSD::TypeReal,  
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+
+        validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
+        validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
+        validation.push_back(Validator(SETTING_MIE_CONFIG, true, LLSD::TypeArray, &validateMieLayers));
+        validation.push_back(Validator(SETTING_LEGACY_HAZE, false, LLSD::TypeMap, &validateLegacyHaze));
+    }
+    return validation;
+}
+
+LLSD LLSettingsSky::createDensityProfileLayer(
+    F32 width,
+    F32 exponential_term,
+    F32 exponential_scale_factor,
+    F32 linear_term,
+    F32 constant_term,
+    F32 aniso_factor)
+{
+    LLSD dflt_layer;
+    dflt_layer[SETTING_DENSITY_PROFILE_WIDTH]            = width; // 0 -> the entire atmosphere
+    dflt_layer[SETTING_DENSITY_PROFILE_EXP_TERM]         = exponential_term;
+    dflt_layer[SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR] = exponential_scale_factor;
+    dflt_layer[SETTING_DENSITY_PROFILE_LINEAR_TERM]      = linear_term;
+    dflt_layer[SETTING_DENSITY_PROFILE_CONSTANT_TERM]    = constant_term;
+
+    if (aniso_factor != 0.0f)
+    {
+        dflt_layer[SETTING_MIE_ANISOTROPY_FACTOR] = aniso_factor;
+    }
+
+    return dflt_layer;
+}
+
+LLSD LLSettingsSky::createSingleLayerDensityProfile(
+    F32 width,
+    F32 exponential_term,
+    F32 exponential_scale_factor,
+    F32 linear_term,
+    F32 constant_term,
+    F32 aniso_factor)
+{
+    LLSD dflt;
+    LLSD dflt_layer = createDensityProfileLayer(width, exponential_term, exponential_scale_factor, linear_term, constant_term, aniso_factor);
+    dflt.append(dflt_layer);
+    return dflt;
+}
+
+LLSD LLSettingsSky::rayleighConfigDefault()
+{
+    return createSingleLayerDensityProfile(0.0f,  1.0f, -1.0f / 8000.0f, 0.0f, 0.0f);
+}
+
+LLSD LLSettingsSky::absorptionConfigDefault()
+{
+// absorption (ozone) has two linear ramping zones
+    LLSD dflt_absorption_layer_a = createDensityProfileLayer(25000.0f, 0.0f, 0.0f, -1.0f / 25000.0f, -2.0f / 3.0f);
+    LLSD dflt_absorption_layer_b = createDensityProfileLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f);
+    LLSD dflt_absorption;
+    dflt_absorption.append(dflt_absorption_layer_a);
+    dflt_absorption.append(dflt_absorption_layer_b);
+    return dflt_absorption;
+}
+
+LLSD LLSettingsSky::mieConfigDefault()
+{
+    LLSD dflt_mie = createSingleLayerDensityProfile(0.0f,  1.0f, -1.0f / 1200.0f, 0.0f, 0.0f, 0.8f);
+    return dflt_mie;
+}
+
+LLSD LLSettingsSky::defaults(const LLSettingsBase::TrackPosition& position)
+{
+    static LLSD dfltsetting;
+
+    if (dfltsetting.size() == 0)
+    {
+        LLQuaternion sunquat;
+        LLQuaternion moonquat;
+
+        F32 azimuth  = (F_PI * position) + (80.0f * DEG_TO_RAD);
+        F32 altitude = (F_PI * position);
+
+        // give the sun and moon slightly different tracks through the sky
+        // instead of positioning them at opposite poles from each other...
+        sunquat  = convert_azimuth_and_altitude_to_quat(altitude,                   azimuth);
+        moonquat = convert_azimuth_and_altitude_to_quat(altitude + (F_PI * 0.125f), azimuth + (F_PI * 0.125f));
+
+        // Magic constants copied form dfltsetting.xml 
+        dfltsetting[SETTING_CLOUD_COLOR]        = LLColor4(0.4099, 0.4099, 0.4099, 0.0).getValue();
+        dfltsetting[SETTING_CLOUD_POS_DENSITY1] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
+        dfltsetting[SETTING_CLOUD_POS_DENSITY2] = LLColor4(1.0000, 0.5260, 1.0000, 0.0).getValue();
+        dfltsetting[SETTING_CLOUD_SCALE]        = LLSD::Real(0.4199);
+        dfltsetting[SETTING_CLOUD_SCROLL_RATE]  = LLSDArray(0.0f)(0.0f);
+        dfltsetting[SETTING_CLOUD_SHADOW]       = LLSD::Real(0.2699);
+        dfltsetting[SETTING_CLOUD_VARIANCE]     = LLSD::Real(0.0);
+
+        dfltsetting[SETTING_DOME_OFFSET]        = LLSD::Real(0.96f);
+        dfltsetting[SETTING_DOME_RADIUS]        = LLSD::Real(15000.f);
+        dfltsetting[SETTING_GAMMA]              = LLSD::Real(1.0);
+        dfltsetting[SETTING_GLOW]               = LLColor4(5.000, 0.0010, -0.4799, 1.0).getValue();
+    
+        dfltsetting[SETTING_MAX_Y]              = LLSD::Real(1605);
+        dfltsetting[SETTING_MOON_ROTATION]      = moonquat.getValue();
+        dfltsetting[SETTING_MOON_BRIGHTNESS]    = LLSD::Real(0.5f);
+
+        dfltsetting[SETTING_STAR_BRIGHTNESS]    = LLSD::Real(250.0000);
+        dfltsetting[SETTING_SUNLIGHT_COLOR]     = LLColor4(0.7342, 0.7815, 0.8999, 0.0).getValue();
+        dfltsetting[SETTING_SUN_ROTATION]       = sunquat.getValue();
+
+        dfltsetting[SETTING_BLOOM_TEXTUREID]    = GetDefaultBloomTextureId();
+        dfltsetting[SETTING_CLOUD_TEXTUREID]    = GetDefaultCloudNoiseTextureId();
+        dfltsetting[SETTING_MOON_TEXTUREID]     = GetDefaultMoonTextureId();
+        dfltsetting[SETTING_SUN_TEXTUREID]      = GetDefaultSunTextureId();
+        dfltsetting[SETTING_RAINBOW_TEXTUREID]  = GetDefaultRainbowTextureId();
+        dfltsetting[SETTING_HALO_TEXTUREID]     = GetDefaultHaloTextureId();
+
+        dfltsetting[SETTING_TYPE] = "sky";
+
+        // defaults are for earth...
+        dfltsetting[SETTING_PLANET_RADIUS]      = 6360.0f;
+        dfltsetting[SETTING_SKY_BOTTOM_RADIUS]  = 6360.0f;
+        dfltsetting[SETTING_SKY_TOP_RADIUS]     = 6420.0f;
+        dfltsetting[SETTING_SUN_ARC_RADIANS]    = 0.00045f;
+
+        dfltsetting[SETTING_SKY_MOISTURE_LEVEL] = 0.0f;
+        dfltsetting[SETTING_SKY_DROPLET_RADIUS] = 800.0f;
+        dfltsetting[SETTING_SKY_ICE_LEVEL]      = 0.0f;
+
+        dfltsetting[SETTING_RAYLEIGH_CONFIG]    = rayleighConfigDefault();
+        dfltsetting[SETTING_MIE_CONFIG]         = mieConfigDefault();
+        dfltsetting[SETTING_ABSORPTION_CONFIG]  = absorptionConfigDefault();
+    }
+
+    return dfltsetting;
+}
+
+LLSD LLSettingsSky::translateLegacyHazeSettings(const LLSD& legacy)
+{
+    LLSD legacyhazesettings;
+
+// AdvancedAtmospherics TODO
+// These need to be translated into density profile info in the new settings format...
+// LEGACY_ATMOSPHERICS    
+    if (legacy.has(SETTING_AMBIENT))
+    {
+        legacyhazesettings[SETTING_AMBIENT] = LLColor3(legacy[SETTING_AMBIENT]).getValue();
+    }
+    if (legacy.has(SETTING_BLUE_DENSITY))
+    {
+        legacyhazesettings[SETTING_BLUE_DENSITY] = LLColor3(legacy[SETTING_BLUE_DENSITY]).getValue();
+    }
+    if (legacy.has(SETTING_BLUE_HORIZON))
+    {
+        legacyhazesettings[SETTING_BLUE_HORIZON] = LLColor3(legacy[SETTING_BLUE_HORIZON]).getValue();
+    }
+    if (legacy.has(SETTING_DENSITY_MULTIPLIER))
+    {
+        legacyhazesettings[SETTING_DENSITY_MULTIPLIER] = LLSD::Real(legacy[SETTING_DENSITY_MULTIPLIER][0].asReal());
+    }
+    if (legacy.has(SETTING_DISTANCE_MULTIPLIER))
+    {
+        legacyhazesettings[SETTING_DISTANCE_MULTIPLIER] = LLSD::Real(legacy[SETTING_DISTANCE_MULTIPLIER][0].asReal());
+    }
+    if (legacy.has(SETTING_HAZE_DENSITY))
+    {
+        legacyhazesettings[SETTING_HAZE_DENSITY] = LLSD::Real(legacy[SETTING_HAZE_DENSITY][0].asReal());
+    }
+    if (legacy.has(SETTING_HAZE_HORIZON))
+    {
+        legacyhazesettings[SETTING_HAZE_HORIZON] = LLSD::Real(legacy[SETTING_HAZE_HORIZON][0].asReal());
+    }
+
+    return legacyhazesettings;
+}
+
+LLSD LLSettingsSky::translateLegacySettings(const LLSD& legacy)
+{
+    bool converted_something(false);
+    LLSD newsettings(defaults());
+
+    // Move legacy haze parameters to an inner map
+    // allowing backward compat and simple conversion to legacy format
+    LLSD legacyhazesettings;
+    legacyhazesettings = translateLegacyHazeSettings(legacy);
+    if (legacyhazesettings.size() > 0)
+    {
+        newsettings[SETTING_LEGACY_HAZE] = legacyhazesettings;
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_CLOUD_COLOR))
+    {
+        newsettings[SETTING_CLOUD_COLOR] = LLColor3(legacy[SETTING_CLOUD_COLOR]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_CLOUD_POS_DENSITY1))
+    {
+        newsettings[SETTING_CLOUD_POS_DENSITY1] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY1]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_CLOUD_POS_DENSITY2))
+    {
+        newsettings[SETTING_CLOUD_POS_DENSITY2] = LLColor3(legacy[SETTING_CLOUD_POS_DENSITY2]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_CLOUD_SCALE))
+    {
+        newsettings[SETTING_CLOUD_SCALE] = LLSD::Real(legacy[SETTING_CLOUD_SCALE][0].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_CLOUD_SCROLL_RATE))
+    {
+        LLVector2 cloud_scroll(legacy[SETTING_CLOUD_SCROLL_RATE]);
+
+        cloud_scroll -= LLVector2(10, 10);
+        if (legacy.has(SETTING_LEGACY_ENABLE_CLOUD_SCROLL))
+        {
+            LLSD enabled = legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL];
+            if (!enabled[0].asBoolean())
+                cloud_scroll.mV[0] = 0.0f;
+            if (!enabled[1].asBoolean())
+                cloud_scroll.mV[1] = 0.0f;
+        }
+
+        newsettings[SETTING_CLOUD_SCROLL_RATE] = cloud_scroll.getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_CLOUD_SHADOW))
+    {
+        newsettings[SETTING_CLOUD_SHADOW] = LLSD::Real(legacy[SETTING_CLOUD_SHADOW][0].asReal());
+        converted_something |= true;
+    }
+    
+
+    if (legacy.has(SETTING_GAMMA))
+    {
+        newsettings[SETTING_GAMMA] = legacy[SETTING_GAMMA][0].asReal();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_GLOW))
+    {
+        newsettings[SETTING_GLOW] = LLColor3(legacy[SETTING_GLOW]).getValue();
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_MAX_Y))
+    {
+        newsettings[SETTING_MAX_Y] = LLSD::Real(legacy[SETTING_MAX_Y][0].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_STAR_BRIGHTNESS))
+    {
+        newsettings[SETTING_STAR_BRIGHTNESS] = LLSD::Real(legacy[SETTING_STAR_BRIGHTNESS].asReal() * 250.0f);
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_SUNLIGHT_COLOR))
+    {
+        newsettings[SETTING_SUNLIGHT_COLOR] = LLColor4(legacy[SETTING_SUNLIGHT_COLOR]).getValue();
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_PLANET_RADIUS))
+    {
+        newsettings[SETTING_PLANET_RADIUS] = LLSD::Real(legacy[SETTING_PLANET_RADIUS].asReal());
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_SKY_BOTTOM_RADIUS))
+    {
+        newsettings[SETTING_SKY_BOTTOM_RADIUS] = LLSD::Real(legacy[SETTING_SKY_BOTTOM_RADIUS].asReal());
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_SKY_TOP_RADIUS))
+    {
+        newsettings[SETTING_SKY_TOP_RADIUS] = LLSD::Real(legacy[SETTING_SKY_TOP_RADIUS].asReal());
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_SUN_ARC_RADIANS))
+    {
+        newsettings[SETTING_SUN_ARC_RADIANS] = LLSD::Real(legacy[SETTING_SUN_ARC_RADIANS].asReal());
+        converted_something |= true;
+    }
+
+    if (legacy.has(SETTING_LEGACY_EAST_ANGLE) && legacy.has(SETTING_LEGACY_SUN_ANGLE))
+    {
+        // get counter-clockwise radian angle from clockwise legacy WL east angle...
+        F32 azimuth  = -legacy[SETTING_LEGACY_EAST_ANGLE].asReal();
+        F32 altitude =  legacy[SETTING_LEGACY_SUN_ANGLE].asReal();
+        
+        LLQuaternion sunquat  = convert_azimuth_and_altitude_to_quat(azimuth, altitude);
+        // original WL moon dir was diametrically opposed to the sun dir
+        LLQuaternion moonquat = convert_azimuth_and_altitude_to_quat(azimuth + F_PI, -altitude);
+
+        newsettings[SETTING_SUN_ROTATION]  = sunquat.getValue();
+        newsettings[SETTING_MOON_ROTATION] = moonquat.getValue();
+        converted_something |= true;
+    }
+
+    if (!converted_something)
+        return LLSD();
+
+    return newsettings;
+}
+
+void LLSettingsSky::updateSettings()
+{
+    LL_RECORD_BLOCK_TIME(FTM_RECALCULATE_SKYVALUES);
+
+    // base class clears dirty flag so as to not trigger recursive update
+    LLSettingsBase::updateSettings();
+
+    // NOTE: these functions are designed to do nothing unless a dirty bit has been set
+    // so if you add new settings that are referenced by these update functions,
+    // you'll need to insure that your setter updates the dirty bits as well
+    calculateHeavenlyBodyPositions();
+    calculateLightSettings();
+}
+
+F32 LLSettingsSky::getSunMoonGlowFactor() const
+{
+    return getIsSunUp()  ? 1.0f  :
+           getIsMoonUp() ? getMoonBrightness() * 0.25 : 0.0f;
+}
+
+bool LLSettingsSky::getIsSunUp() const
+{
+    LLVector3 sunDir = getSunDirection();
+    return sunDir.mV[2] >= 0.0f;
+}
+
+bool LLSettingsSky::getIsMoonUp() const
+{
+    LLVector3 moonDir = getMoonDirection();
+    return moonDir.mV[2] >= 0.0f;
+}
+
+void LLSettingsSky::calculateHeavenlyBodyPositions()  const
+{
+    LLQuaternion sunq  = getSunRotation();
+    LLQuaternion moonq = getMoonRotation();
+
+    mSunDirection  = LLVector3::x_axis * sunq;
+    mMoonDirection = LLVector3::x_axis * moonq;
+
+    mSunDirection.normalize();
+    mMoonDirection.normalize();
+
+    if (mSunDirection.lengthSquared() < 0.01f)
+        LL_WARNS("SETTINGS") << "Zero length sun direction. Wailing and gnashing of teeth may follow... or not." << LL_ENDL;
+    if (mMoonDirection.lengthSquared() < 0.01f)
+        LL_WARNS("SETTINGS") << "Zero length moon direction. Wailing and gnashing of teeth may follow... or not." << LL_ENDL;
+}
+
+LLVector3 LLSettingsSky::getLightDirection() const
+{
+    update();
+
+    // is the normal from the sun or the moon
+    if (getIsSunUp())
+    {
+        return mSunDirection;
+    }
+    else if (getIsMoonUp())
+    {
+        return mMoonDirection;
+    }
+
+    return LLVector3::z_axis_neg;
+}
+
+LLColor3 LLSettingsSky::getLightDiffuse() const
+{
+    update();
+
+    // is the normal from the sun or the moon
+    if (getIsSunUp())
+    {
+        return getSunDiffuse();
+    }
+    else if (getIsMoonUp())
+    {
+        return getMoonDiffuse();
+    }
+
+    return LLColor3::white;
+}
+
+LLColor3 LLSettingsSky::getColor(const std::string& key, const LLColor3& default_value) const
+{
+    if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key))
+    {
+        return LLColor3(mSettings[SETTING_LEGACY_HAZE][key]);
+    }
+    if (mSettings.has(key))
+    {
+        return LLColor3(mSettings[key]);
+    }
+    return default_value;
+}
+
+F32 LLSettingsSky::getFloat(const std::string& key, F32 default_value) const
+{
+    if (mSettings.has(SETTING_LEGACY_HAZE) && mSettings[SETTING_LEGACY_HAZE].has(key))
+    {
+        return mSettings[SETTING_LEGACY_HAZE][key].asReal();
+    }
+    if (mSettings.has(key))
+    {
+        return mSettings[key].asReal();
+    }
+    return default_value;
+}
+
+LLColor3 LLSettingsSky::getAmbientColor() const
+{
+    return getColor(SETTING_AMBIENT, LLColor3(0.25f, 0.25f, 0.25f));
+}
+
+LLColor3 LLSettingsSky::getAmbientColorClamped() const
+{
+    LLColor3 ambient = getAmbientColor();
+
+    F32 max_color = llmax(ambient.mV[0], ambient.mV[1], ambient.mV[2]);
+    if (max_color > 1.0f)
+    {
+        ambient *= 1.0f/max_color;
+    }
+
+    return ambient;
+}
+
+LLColor3 LLSettingsSky::getBlueDensity() const
+{
+    return getColor(SETTING_BLUE_DENSITY, LLColor3(0.2447f, 0.4487f, 0.7599f));
+}
+
+LLColor3 LLSettingsSky::getBlueHorizon() const
+{
+    return getColor(SETTING_BLUE_HORIZON, LLColor3(0.4954f, 0.4954f, 0.6399f));
+}
+
+F32 LLSettingsSky::getHazeDensity() const
+{
+    return getFloat(SETTING_HAZE_DENSITY, 0.7f);
+}
+
+F32 LLSettingsSky::getHazeHorizon() const
+{
+    return getFloat(SETTING_HAZE_HORIZON, 0.19f);
+}
+
+F32 LLSettingsSky::getDensityMultiplier() const
+{
+    return getFloat(SETTING_DENSITY_MULTIPLIER, 0.0001f);
+}
+
+F32 LLSettingsSky::getDistanceMultiplier() const
+{
+    return getFloat(SETTING_DISTANCE_MULTIPLIER, 0.8f);
+}
+
+void LLSettingsSky::setPlanetRadius(F32 radius)
+{
+    mSettings[SETTING_PLANET_RADIUS] = radius;
+}
+
+void LLSettingsSky::setSkyBottomRadius(F32 radius)
+{
+    mSettings[SETTING_SKY_BOTTOM_RADIUS] = radius;
+}
+
+void LLSettingsSky::setSkyTopRadius(F32 radius)
+{
+    mSettings[SETTING_SKY_TOP_RADIUS] = radius;
+}
+
+void LLSettingsSky::setSunArcRadians(F32 radians)
+{
+    mSettings[SETTING_SUN_ARC_RADIANS] = radians;
+}
+
+void LLSettingsSky::setMieAnisotropy(F32 aniso_factor)
+{
+    getMieConfig()[SETTING_MIE_ANISOTROPY_FACTOR] = aniso_factor;
+}
+
+void LLSettingsSky::setSkyMoistureLevel(F32 moisture_level)
+{
+    setValue(SETTING_SKY_MOISTURE_LEVEL, moisture_level);
+}
+
+void LLSettingsSky::setSkyDropletRadius(F32 radius)
+{
+    setValue(SETTING_SKY_DROPLET_RADIUS,radius);
+}
+
+void LLSettingsSky::setSkyIceLevel(F32 ice_level)
+{
+    setValue(SETTING_SKY_ICE_LEVEL, ice_level);
+}
+
+void LLSettingsSky::setAmbientColor(const LLColor3 &val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_AMBIENT] = val.getValue();
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setBlueDensity(const LLColor3 &val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_DENSITY] = val.getValue();
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setBlueHorizon(const LLColor3 &val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_BLUE_HORIZON] = val.getValue();
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setDensityMultiplier(F32 val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_DENSITY_MULTIPLIER] = val;
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setDistanceMultiplier(F32 val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_DISTANCE_MULTIPLIER] = val;
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setHazeDensity(F32 val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_DENSITY] = val;
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setHazeHorizon(F32 val)
+{
+    mSettings[SETTING_LEGACY_HAZE][SETTING_HAZE_HORIZON] = val;
+    setDirtyFlag(true);
+}
+
+// Get total from rayleigh and mie density values for normalization
+LLColor3 LLSettingsSky::getTotalDensity() const
+{
+    LLColor3    blue_density = getBlueDensity();
+    F32         haze_density = getHazeDensity();
+    LLColor3 total_density = blue_density + smear(haze_density);
+    return total_density;
+}
+
+// Sunlight attenuation effect (hue and brightness) due to atmosphere
+// this is used later for sunlight modulation at various altitudes
+LLColor3 LLSettingsSky::getLightAttenuation(F32 distance) const
+{
+    F32         density_multiplier = getDensityMultiplier();
+    LLColor3    blue_density       = getBlueDensity();
+    F32         haze_density       = getHazeDensity();
+    // Approximate line integral over requested distance
+    LLColor3    light_atten = (blue_density * 1.0 + smear(haze_density * 0.25f)) * density_multiplier * distance;
+    return light_atten;
+}
+
+LLColor3 LLSettingsSky::getLightTransmittance(F32 distance) const
+{
+    LLColor3 total_density      = getTotalDensity();
+    F32      density_multiplier = getDensityMultiplier();
+    // Transparency (-> density) from Beer's law
+    LLColor3 transmittance = componentExp(total_density * -(density_multiplier * distance));
+    return transmittance;
+}
+
+// performs soft scale clip and gamma correction ala the shader implementation
+// scales colors down to 0 - 1 range preserving relative ratios
+LLColor3 LLSettingsSky::gammaCorrect(const LLColor3& in) const
+{
+    F32 gamma = getGamma();
+
+    LLColor3 v(in);
+    // scale down to 0 to 1 range preserving relative ratio (aka homegenize)
+    F32 max_color = llmax(llmax(in.mV[0], in.mV[1]), in.mV[2]);
+    if (max_color > 1.0f)
+    {
+        v *= 1.0f / max_color;
+    }
+
+    LLColor3 color = in * 2.0f;
+	color = smear(1.f) - componentSaturate(color); // clamping after mul seems wrong, but prevents negative colors...
+	componentPow(color, gamma);
+	color = smear(1.f) - color;
+    return color;
+}
+
+LLVector3 LLSettingsSky::getSunDirection() const
+{
+    update();
+    return mSunDirection;
+}
+
+LLVector3 LLSettingsSky::getMoonDirection() const
+{
+    update();
+    return mMoonDirection;
+}
+
+LLColor4 LLSettingsSky::getMoonAmbient() const
+{
+    update();
+    return mMoonAmbient;
+}
+
+LLColor3 LLSettingsSky::getMoonDiffuse() const
+{
+    update();
+    return mMoonDiffuse;
+}
+
+LLColor4 LLSettingsSky::getSunAmbient() const
+{
+    update();
+    return mSunAmbient;
+}
+
+LLColor3 LLSettingsSky::getSunDiffuse() const
+{
+    update();
+    return mSunDiffuse;
+}
+
+LLColor4 LLSettingsSky::getHazeColor() const
+{
+    update();
+    return mHazeColor;
+}
+
+LLColor4 LLSettingsSky::getTotalAmbient() const
+{
+    update();
+    return mTotalAmbient;
+}
+
+LLColor3 LLSettingsSky::getMoonlightColor() const
+{
+    return getSunlightColor(); //moon and sun share light color
+}
+
+void LLSettingsSky::clampColor(LLColor3& color, F32 gamma, F32 scale) const
+{
+    F32 max_color = llmax(color.mV[0], color.mV[1], color.mV[2]);
+    if (max_color > scale)
+    {
+        color *= scale/max_color;
+    }
+    LLColor3 linear(color);
+    linear *= 1.0 / scale;
+    linear = smear(1.0f) - linear;
+    linear = componentPow(linear, gamma);
+    linear *= scale;
+    color = linear;
+}
+
+void LLSettingsSky::calculateLightSettings() const
+{
+    // Initialize temp variables
+    LLColor3    sunlight = getSunlightColor();
+    LLColor3    ambient  = getAmbientColor();
+
+    F32         cloud_shadow = getCloudShadow();
+    LLVector3   lightnorm = getLightDirection();
+
+    // Sunlight attenuation effect (hue and brightness) due to atmosphere
+    // this is used later for sunlight modulation at various altitudes
+    F32         max_y               = getMaxY();
+    LLColor3    light_atten         = getLightAttenuation(max_y);
+    LLColor3    light_transmittance = getLightTransmittance(max_y);
+
+    // and vary_sunlight will work properly with moon light
+    const F32 LIMIT = FLT_EPSILON * 8.0f;
+
+    F32 lighty = fabs(lightnorm[2]);
+    if(lighty >= LIMIT)
+    {
+        lighty = 1.f / lighty;
+    }
+    lighty = llmax(LIMIT, lighty);
+    componentMultBy(sunlight, componentExp((light_atten * -1.f) * lighty));
+    componentMultBy(sunlight, light_transmittance);
+
+    //increase ambient when there are more clouds
+    LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5;
+
+    //brightness of surface both sunlight and ambient
+    mSunDiffuse = sunlight;
+    mSunAmbient = tmpAmbient;
+
+    F32 haze_horizon = getHazeHorizon();
+    
+    sunlight *= 1.0 - cloud_shadow;
+    sunlight += tmpAmbient;
+
+    mHazeColor = getBlueHorizon() * getBlueDensity() * sunlight;
+    mHazeColor += LLColor4(haze_horizon, haze_horizon, haze_horizon, haze_horizon) * getHazeDensity() * sunlight;
+
+    F32 moon_brightness = getIsMoonUp() ? getMoonBrightness() : 0.001f;
+
+    LLColor3 moonlight = getMoonlightColor();
+    LLColor3 moonlight_b(0.66, 0.66, 1.2); // scotopic ambient value
+
+    componentMultBy(moonlight, componentExp((light_atten * -1.f) * lighty));
+
+    mMoonDiffuse  = componentMult(moonlight, light_transmittance) * moon_brightness;
+    mMoonAmbient  = moonlight_b * 0.0125f;
+
+    mTotalAmbient = ambient;
+}
+
+LLUUID LLSettingsSky::GetDefaultAssetId()
+{
+    return DEFAULT_ASSET_ID;
+}
+
+LLUUID LLSettingsSky::GetDefaultSunTextureId()
+{
+    return LLUUID::null;
+}
+
+
+LLUUID LLSettingsSky::GetBlankSunTextureId()
+{
+    return DEFAULT_SUN_ID;
+}
+
+LLUUID LLSettingsSky::GetDefaultMoonTextureId()
+{
+    return DEFAULT_MOON_ID;
+}
+
+LLUUID LLSettingsSky::GetDefaultCloudNoiseTextureId()
+{
+    return DEFAULT_CLOUD_ID;
+}
+
+LLUUID LLSettingsSky::GetDefaultBloomTextureId()
+{
+    return IMG_BLOOM1;
+}
+
+LLUUID LLSettingsSky::GetDefaultRainbowTextureId()
+{
+    return IMG_RAINBOW;
+}
+
+LLUUID LLSettingsSky::GetDefaultHaloTextureId()
+{
+    return IMG_HALO;
+}
+
+F32 LLSettingsSky::getPlanetRadius() const
+{
+    return mSettings[SETTING_PLANET_RADIUS].asReal();
+}
+
+F32 LLSettingsSky::getSkyMoistureLevel() const
+{
+    return mSettings[SETTING_SKY_MOISTURE_LEVEL].asReal();
+}
+
+F32 LLSettingsSky::getSkyDropletRadius() const
+{
+    return mSettings[SETTING_SKY_DROPLET_RADIUS].asReal();
+}
+
+F32 LLSettingsSky::getSkyIceLevel() const
+{
+    return mSettings[SETTING_SKY_ICE_LEVEL].asReal();
+}
+
+F32 LLSettingsSky::getSkyBottomRadius() const
+{
+    return mSettings[SETTING_SKY_BOTTOM_RADIUS].asReal();
+}
+
+F32 LLSettingsSky::getSkyTopRadius() const
+{
+    return mSettings[SETTING_SKY_TOP_RADIUS].asReal();
+}
+
+F32 LLSettingsSky::getSunArcRadians() const
+{
+    return mSettings[SETTING_SUN_ARC_RADIANS].asReal();
+}
+
+F32 LLSettingsSky::getMieAnisotropy() const
+{
+    return getMieConfig()[SETTING_MIE_ANISOTROPY_FACTOR].asReal();
+}
+ 
+LLSD LLSettingsSky::getRayleighConfig() const
+{
+    LLSD copy = *(mSettings[SETTING_RAYLEIGH_CONFIG].beginArray());
+    return copy;
+}
+
+LLSD LLSettingsSky::getMieConfig() const
+{
+    LLSD copy = *(mSettings[SETTING_MIE_CONFIG].beginArray());
+    return copy;
+}
+
+LLSD LLSettingsSky::getAbsorptionConfig() const
+{
+    LLSD copy = *(mSettings[SETTING_ABSORPTION_CONFIG].beginArray());
+    return copy;
+}
+   
+LLSD LLSettingsSky::getRayleighConfigs() const
+{
+    return mSettings[SETTING_RAYLEIGH_CONFIG];
+}
+
+LLSD LLSettingsSky::getMieConfigs() const
+{
+    return mSettings[SETTING_MIE_CONFIG];
+}
+
+LLSD LLSettingsSky::getAbsorptionConfigs() const
+{
+    return mSettings[SETTING_ABSORPTION_CONFIG];
+}
+
+void LLSettingsSky::setRayleighConfigs(const LLSD& rayleighConfig)
+{
+    mSettings[SETTING_RAYLEIGH_CONFIG] = rayleighConfig;
+}
+
+void LLSettingsSky::setMieConfigs(const LLSD& mieConfig)
+{
+    mSettings[SETTING_MIE_CONFIG] = mieConfig;
+}
+
+void LLSettingsSky::setAbsorptionConfigs(const LLSD& absorptionConfig)
+{
+    mSettings[SETTING_ABSORPTION_CONFIG] = absorptionConfig;
+}
+
+LLUUID LLSettingsSky::getBloomTextureId() const
+{
+    return mSettings[SETTING_BLOOM_TEXTUREID].asUUID();
+}
+
+LLUUID LLSettingsSky::getRainbowTextureId() const
+{
+    return mSettings[SETTING_RAINBOW_TEXTUREID].asUUID();
+}
+
+LLUUID LLSettingsSky::getHaloTextureId() const
+{
+    return mSettings[SETTING_HALO_TEXTUREID].asUUID();
+}
+
+//---------------------------------------------------------------------
+LLColor3 LLSettingsSky::getCloudColor() const
+{
+    return LLColor3(mSettings[SETTING_CLOUD_COLOR]);
+}
+
+void LLSettingsSky::setCloudColor(const LLColor3 &val)
+{
+    setValue(SETTING_CLOUD_COLOR, val);
+}
+
+LLUUID LLSettingsSky::getCloudNoiseTextureId() const
+{
+    return mSettings[SETTING_CLOUD_TEXTUREID].asUUID();
+}
+
+void LLSettingsSky::setCloudNoiseTextureId(const LLUUID &id)
+{
+    setValue(SETTING_CLOUD_TEXTUREID, id);
+}
+
+LLColor3 LLSettingsSky::getCloudPosDensity1() const
+{
+    return LLColor3(mSettings[SETTING_CLOUD_POS_DENSITY1]);
+}
+
+void LLSettingsSky::setCloudPosDensity1(const LLColor3 &val)
+{
+    setValue(SETTING_CLOUD_POS_DENSITY1, val);
+}
+
+LLColor3 LLSettingsSky::getCloudPosDensity2() const
+{
+    return LLColor3(mSettings[SETTING_CLOUD_POS_DENSITY2]);
+}
+
+void LLSettingsSky::setCloudPosDensity2(const LLColor3 &val)
+{
+    setValue(SETTING_CLOUD_POS_DENSITY2, val);
+}
+
+F32 LLSettingsSky::getCloudScale() const
+{
+    return mSettings[SETTING_CLOUD_SCALE].asReal();
+}
+
+void LLSettingsSky::setCloudScale(F32 val)
+{
+    setValue(SETTING_CLOUD_SCALE, val);
+}
+
+LLVector2 LLSettingsSky::getCloudScrollRate() const
+{
+    return LLVector2(mSettings[SETTING_CLOUD_SCROLL_RATE]);
+}
+
+void LLSettingsSky::setCloudScrollRate(const LLVector2 &val)
+{
+    setValue(SETTING_CLOUD_SCROLL_RATE, val);
+}
+
+void LLSettingsSky::setCloudScrollRateX(F32 val)
+{
+    mSettings[SETTING_CLOUD_SCROLL_RATE][0] = val;
+    setDirtyFlag(true);
+}
+
+void LLSettingsSky::setCloudScrollRateY(F32 val)
+{
+    mSettings[SETTING_CLOUD_SCROLL_RATE][1] = val;
+    setDirtyFlag(true);
+}
+
+F32 LLSettingsSky::getCloudShadow() const
+{
+    return mSettings[SETTING_CLOUD_SHADOW].asReal();
+}
+
+void LLSettingsSky::setCloudShadow(F32 val)
+{
+    setValue(SETTING_CLOUD_SHADOW, val);
+}
+
+F32 LLSettingsSky::getCloudVariance() const
+{
+    return mSettings[SETTING_CLOUD_VARIANCE].asReal();
+}
+
+void LLSettingsSky::setCloudVariance(F32 val)
+{
+    setValue(SETTING_CLOUD_VARIANCE, val);
+}
+
+F32 LLSettingsSky::getDomeOffset() const
+{
+    //return mSettings[SETTING_DOME_OFFSET].asReal();
+    return DOME_OFFSET;    
+}
+
+F32 LLSettingsSky::getDomeRadius() const
+{
+    //return mSettings[SETTING_DOME_RADIUS].asReal();
+    return DOME_RADIUS;    
+}
+
+F32 LLSettingsSky::getGamma() const
+{
+    return mSettings[SETTING_GAMMA].asReal();
+}
+
+void LLSettingsSky::setGamma(F32 val)
+{
+    mSettings[SETTING_GAMMA] = LLSD::Real(val);
+    setDirtyFlag(true);
+}
+
+LLColor3 LLSettingsSky::getGlow() const
+{
+    return LLColor3(mSettings[SETTING_GLOW]);
+}
+
+void LLSettingsSky::setGlow(const LLColor3 &val)
+{
+    setValue(SETTING_GLOW, val);
+}
+
+F32 LLSettingsSky::getMaxY() const
+{
+    return mSettings[SETTING_MAX_Y].asReal();
+}
+
+void LLSettingsSky::setMaxY(F32 val) 
+{
+    setValue(SETTING_MAX_Y, val);
+}
+
+LLQuaternion LLSettingsSky::getMoonRotation() const
+{
+    return LLQuaternion(mSettings[SETTING_MOON_ROTATION]);
+}
+
+void LLSettingsSky::setMoonRotation(const LLQuaternion &val)
+{
+    setValue(SETTING_MOON_ROTATION, val);
+}
+
+F32 LLSettingsSky::getMoonScale() const
+{
+    return mSettings[SETTING_MOON_SCALE].asReal();
+}
+
+void LLSettingsSky::setMoonScale(F32 val)
+{
+    setValue(SETTING_MOON_SCALE, val);
+}
+
+LLUUID LLSettingsSky::getMoonTextureId() const
+{
+    return mSettings[SETTING_MOON_TEXTUREID].asUUID();
+}
+
+void LLSettingsSky::setMoonTextureId(LLUUID id)
+{
+    setValue(SETTING_MOON_TEXTUREID, id);
+}
+
+F32  LLSettingsSky::getMoonBrightness() const
+{
+    return mSettings[SETTING_MOON_BRIGHTNESS].asReal();
+}
+
+void LLSettingsSky::setMoonBrightness(F32 brightness_factor)
+{
+    setValue(SETTING_MOON_BRIGHTNESS, brightness_factor);
+}
+
+F32 LLSettingsSky::getStarBrightness() const
+{
+    return mSettings[SETTING_STAR_BRIGHTNESS].asReal();
+}
+
+void LLSettingsSky::setStarBrightness(F32 val)
+{
+    setValue(SETTING_STAR_BRIGHTNESS, val);
+}
+
+LLColor3 LLSettingsSky::getSunlightColor() const
+{
+    return LLColor3(mSettings[SETTING_SUNLIGHT_COLOR]);
+}
+
+LLColor3 LLSettingsSky::getSunlightColorClamped() const
+{
+    LLColor3 sunlight = getSunlightColor();
+    //clampColor(sunlight, getGamma(), 3.0f);
+
+    F32 max_color = llmax(sunlight.mV[0], sunlight.mV[1], sunlight.mV[2]);
+    if (max_color > 1.0f)
+    {
+        sunlight *= 1.0f/max_color;
+    }
+
+    return sunlight;
+}
+
+void LLSettingsSky::setSunlightColor(const LLColor3 &val)
+{
+    setValue(SETTING_SUNLIGHT_COLOR, val);
+}
+
+LLQuaternion LLSettingsSky::getSunRotation() const
+{
+    return LLQuaternion(mSettings[SETTING_SUN_ROTATION]);
+}
+
+void LLSettingsSky::setSunRotation(const LLQuaternion &val) 
+{
+    setValue(SETTING_SUN_ROTATION, val);
+}
+
+
+F32 LLSettingsSky::getSunScale() const
+{
+    return mSettings[SETTING_SUN_SCALE].asReal();
+}
+
+void LLSettingsSky::setSunScale(F32 val)
+{
+    setValue(SETTING_SUN_SCALE, val);
+}
+
+LLUUID LLSettingsSky::getSunTextureId() const
+{
+    return mSettings[SETTING_SUN_TEXTUREID].asUUID();
+}
+
+void LLSettingsSky::setSunTextureId(LLUUID id) 
+{
+    setValue(SETTING_SUN_TEXTUREID, id);
+}
+
+LLUUID LLSettingsSky::getNextSunTextureId() const
+{
+    return mNextSunTextureId;
+}
+
+LLUUID LLSettingsSky::getNextMoonTextureId() const
+{
+    return mNextMoonTextureId;
+}
+
+LLUUID LLSettingsSky::getNextCloudNoiseTextureId() const
+{
+    return mNextCloudTextureId;
+}
+
+LLUUID LLSettingsSky::getNextBloomTextureId() const
+{
+    return mNextBloomTextureId;
+}
+
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
new file mode 100644
index 0000000000000000000000000000000000000000..412791164327d9e7c3dcebfa5fca437f9a069b6a
--- /dev/null
+++ b/indra/llinventory/llsettingssky.h
@@ -0,0 +1,374 @@
+/**
+* @file llsettingssky.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_SETTINGS_SKY_H
+#define LL_SETTINGS_SKY_H
+
+#include "llsettingsbase.h"
+#include "v4coloru.h"
+
+const F32 EARTH_RADIUS  =      6.370e6f;
+const F32 SUN_RADIUS    =    695.508e6f;
+const F32 SUN_DIST      = 149598.260e6f;
+const F32 MOON_RADIUS   =      1.737e6f;
+const F32 MOON_DIST     =    384.400e6f;
+
+class LLSettingsSky: public LLSettingsBase
+{
+public:
+    static const std::string SETTING_AMBIENT;
+    static const std::string SETTING_BLOOM_TEXTUREID;
+    static const std::string SETTING_RAINBOW_TEXTUREID;
+    static const std::string SETTING_HALO_TEXTUREID;
+    static const std::string SETTING_BLUE_DENSITY;
+    static const std::string SETTING_BLUE_HORIZON;
+    static const std::string SETTING_DENSITY_MULTIPLIER;
+    static const std::string SETTING_DISTANCE_MULTIPLIER;
+    static const std::string SETTING_HAZE_DENSITY;
+    static const std::string SETTING_HAZE_HORIZON;
+    static const std::string SETTING_CLOUD_COLOR;
+    static const std::string SETTING_CLOUD_POS_DENSITY1;
+    static const std::string SETTING_CLOUD_POS_DENSITY2;
+    static const std::string SETTING_CLOUD_SCALE;
+    static const std::string SETTING_CLOUD_SCROLL_RATE;
+    static const std::string SETTING_CLOUD_SHADOW;
+    static const std::string SETTING_CLOUD_TEXTUREID;
+    static const std::string SETTING_CLOUD_VARIANCE;
+
+    static const std::string SETTING_DOME_OFFSET;
+    static const std::string SETTING_DOME_RADIUS;
+    static const std::string SETTING_GAMMA;
+    static const std::string SETTING_GLOW;    
+    static const std::string SETTING_LIGHT_NORMAL;
+    static const std::string SETTING_MAX_Y;
+    static const std::string SETTING_MOON_ROTATION;
+    static const std::string SETTING_MOON_SCALE;
+    static const std::string SETTING_MOON_TEXTUREID;
+    static const std::string SETTING_MOON_BRIGHTNESS;
+
+    static const std::string SETTING_STAR_BRIGHTNESS;
+    static const std::string SETTING_SUNLIGHT_COLOR;
+    static const std::string SETTING_SUN_ROTATION;
+    static const std::string SETTING_SUN_SCALE;
+    static const std::string SETTING_SUN_TEXTUREID;
+
+    static const std::string SETTING_PLANET_RADIUS;
+    static const std::string SETTING_SKY_BOTTOM_RADIUS;
+    static const std::string SETTING_SKY_TOP_RADIUS;
+    static const std::string SETTING_SUN_ARC_RADIANS;
+    static const std::string SETTING_MIE_ANISOTROPY_FACTOR;
+
+    static const std::string SETTING_RAYLEIGH_CONFIG;
+    static const std::string SETTING_MIE_CONFIG;
+    static const std::string SETTING_ABSORPTION_CONFIG;
+
+    static const std::string KEY_DENSITY_PROFILE;
+        static const std::string SETTING_DENSITY_PROFILE_WIDTH;
+        static const std::string SETTING_DENSITY_PROFILE_EXP_TERM;
+        static const std::string SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR;
+        static const std::string SETTING_DENSITY_PROFILE_LINEAR_TERM;
+        static const std::string SETTING_DENSITY_PROFILE_CONSTANT_TERM;
+        
+    static const std::string SETTING_SKY_MOISTURE_LEVEL;
+    static const std::string SETTING_SKY_DROPLET_RADIUS;
+    static const std::string SETTING_SKY_ICE_LEVEL;
+
+    static const std::string SETTING_LEGACY_HAZE;
+
+    static const LLUUID DEFAULT_ASSET_ID;
+
+    typedef PTR_NAMESPACE::shared_ptr<LLSettingsSky> ptr_t;
+
+    //---------------------------------------------------------------------
+    LLSettingsSky(const LLSD &data);
+    virtual ~LLSettingsSky() { };
+
+    virtual ptr_t   buildClone() const = 0;
+
+    //---------------------------------------------------------------------
+    virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("sky"); }
+    virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; }
+
+    // Settings status 
+    virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
+
+    virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
+
+    void replaceWithSky(LLSettingsSky::ptr_t pother);
+    static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
+
+    F32 getPlanetRadius() const;
+    F32 getSkyBottomRadius() const;
+    F32 getSkyTopRadius() const;
+    F32 getSunArcRadians() const;
+    F32 getMieAnisotropy() const;   
+
+    F32 getSkyMoistureLevel() const;
+    F32 getSkyDropletRadius() const;
+    F32 getSkyIceLevel() const;
+
+    // Return first (only) profile layer represented in LLSD
+    LLSD getRayleighConfig() const;
+    LLSD getMieConfig() const;
+    LLSD getAbsorptionConfig() const;
+
+    // Return entire LLSDArray of profile layers represented in LLSD
+    LLSD getRayleighConfigs() const;
+    LLSD getMieConfigs() const;
+    LLSD getAbsorptionConfigs() const;
+
+    LLUUID getBloomTextureId() const;
+    LLUUID getRainbowTextureId() const;
+    LLUUID getHaloTextureId() const;
+
+    void setRayleighConfigs(const LLSD& rayleighConfig);
+    void setMieConfigs(const LLSD& mieConfig);
+    void setAbsorptionConfigs(const LLSD& absorptionConfig);
+
+    void setPlanetRadius(F32 radius);
+    void setSkyBottomRadius(F32 radius);
+    void setSkyTopRadius(F32 radius);
+    void setSunArcRadians(F32 radians);
+    void setMieAnisotropy(F32 aniso_factor);
+
+    void setSkyMoistureLevel(F32 moisture_level);
+    void setSkyDropletRadius(F32 radius);
+    void setSkyIceLevel(F32 ice_level);
+
+    //---------------------------------------------------------------------
+    LLColor3 getAmbientColor() const;
+    void setAmbientColor(const LLColor3 &val);
+
+    LLColor3 getCloudColor() const;
+    void setCloudColor(const LLColor3 &val);
+
+    LLUUID getCloudNoiseTextureId() const;
+    void setCloudNoiseTextureId(const LLUUID &id);
+
+    LLColor3 getCloudPosDensity1() const;
+    void setCloudPosDensity1(const LLColor3 &val);
+
+    LLColor3 getCloudPosDensity2() const;
+    void setCloudPosDensity2(const LLColor3 &val);
+
+    F32 getCloudScale() const;
+    void setCloudScale(F32 val);
+
+    LLVector2 getCloudScrollRate() const;
+    void setCloudScrollRate(const LLVector2 &val);
+
+    void setCloudScrollRateX(F32 val);
+    void setCloudScrollRateY(F32 val);
+
+    F32 getCloudShadow() const;
+    void setCloudShadow(F32 val);
+    
+    F32 getCloudVariance() const;
+    void setCloudVariance(F32 val);
+
+    F32 getDomeOffset() const;
+    F32 getDomeRadius() const;
+
+    F32 getGamma() const;
+
+    void setGamma(F32 val);
+
+    LLColor3 getGlow() const;
+    void setGlow(const LLColor3 &val);
+
+    F32 getMaxY() const;
+
+    void setMaxY(F32 val);
+
+    LLQuaternion getMoonRotation() const;
+    void setMoonRotation(const LLQuaternion &val);
+
+    F32 getMoonScale() const;
+    void setMoonScale(F32 val);
+
+    LLUUID getMoonTextureId() const;
+    void setMoonTextureId(LLUUID id);
+
+    F32  getMoonBrightness() const;
+    void setMoonBrightness(F32 brightness_factor);
+
+    F32 getStarBrightness() const;
+    void setStarBrightness(F32 val);
+
+    LLColor3 getSunlightColor() const;
+    void setSunlightColor(const LLColor3 &val);
+
+    LLQuaternion getSunRotation() const;
+    void setSunRotation(const LLQuaternion &val) ;
+
+    F32 getSunScale() const;
+    void setSunScale(F32 val);
+
+    LLUUID getSunTextureId() const;
+    void setSunTextureId(LLUUID id);
+
+    //=====================================================================
+    // transient properties used in animations.
+    LLUUID getNextSunTextureId() const;
+    LLUUID getNextMoonTextureId() const;
+    LLUUID getNextCloudNoiseTextureId() const;
+    LLUUID getNextBloomTextureId() const;
+
+    //=====================================================================
+    virtual void loadTextures() { };
+
+    //=====================================================================
+    virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
+    static validation_list_t validationList();
+
+    static LLSD translateLegacySettings(const LLSD& legacy);
+
+// LEGACY_ATMOSPHERICS
+    static LLSD translateLegacyHazeSettings(const LLSD& legacy);
+
+    LLColor3 getLightAttenuation(F32 distance) const;
+    LLColor3 getLightTransmittance(F32 distance) const;
+    LLColor3 getTotalDensity() const;
+    LLColor3 gammaCorrect(const LLColor3& in) const;
+
+    LLColor3 getBlueDensity() const;
+    LLColor3 getBlueHorizon() const;
+    F32 getHazeDensity() const;
+    F32 getHazeHorizon() const;
+    F32 getDensityMultiplier() const;
+    F32 getDistanceMultiplier() const;
+
+    void setBlueDensity(const LLColor3 &val);
+    void setBlueHorizon(const LLColor3 &val);
+    void setDensityMultiplier(F32 val);
+    void setDistanceMultiplier(F32 val);
+    void setHazeDensity(F32 val);
+    void setHazeHorizon(F32 val);
+
+// Internal/calculated settings
+    bool getIsSunUp() const;
+    bool getIsMoonUp() const;
+
+    // determines how much the haze glow effect occurs in rendering
+    F32 getSunMoonGlowFactor() const;
+
+    LLVector3 getLightDirection() const;
+    LLColor3  getLightDiffuse() const;
+
+    LLVector3 getSunDirection() const;
+    LLVector3 getMoonDirection() const;
+
+    // color based on brightness
+    LLColor3  getMoonlightColor() const;
+    
+    LLColor4  getMoonAmbient() const;
+    LLColor3  getMoonDiffuse() const;
+    LLColor4  getSunAmbient() const;
+    LLColor3  getSunDiffuse() const;
+    LLColor4  getTotalAmbient() const;
+    LLColor4  getHazeColor() const;
+
+    LLColor3 getSunlightColorClamped() const;
+    LLColor3 getAmbientColorClamped() const;
+
+    virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
+
+    static LLUUID GetDefaultAssetId();
+    static LLUUID GetDefaultSunTextureId();
+    static LLUUID GetBlankSunTextureId();
+    static LLUUID GetDefaultMoonTextureId();
+    static LLUUID GetDefaultCloudNoiseTextureId();
+    static LLUUID GetDefaultBloomTextureId();
+    static LLUUID GetDefaultRainbowTextureId();
+    static LLUUID GetDefaultHaloTextureId();
+
+    static LLSD createDensityProfileLayer(
+                    F32 width,
+                    F32 exponential_term,
+                    F32 exponential_scale_factor,
+                    F32 linear_term,
+                    F32 constant_term,
+                    F32 aniso_factor = 0.0f);
+
+    static LLSD createSingleLayerDensityProfile(
+                    F32 width,
+                    F32 exponential_term,
+                    F32 exponential_scale_factor,
+                    F32 linear_term,
+                    F32 constant_term,
+                    F32 aniso_factor = 0.0f);
+
+    virtual void        updateSettings() SETTINGS_OVERRIDE;
+protected:
+    static const std::string SETTING_LEGACY_EAST_ANGLE;
+    static const std::string SETTING_LEGACY_ENABLE_CLOUD_SCROLL;
+    static const std::string SETTING_LEGACY_SUN_ANGLE;
+
+    LLSettingsSky();
+
+    virtual stringset_t getSlerpKeys() const SETTINGS_OVERRIDE;
+    virtual stringset_t getSkipInterpolateKeys() const SETTINGS_OVERRIDE;
+
+    LLUUID      mNextSunTextureId;
+    LLUUID      mNextMoonTextureId;
+    LLUUID      mNextCloudTextureId;
+    LLUUID      mNextBloomTextureId;
+    LLUUID      mNextRainbowTextureId;
+    LLUUID      mNextHaloTextureId;
+
+private:
+    static LLSD rayleighConfigDefault();
+    static LLSD absorptionConfigDefault();
+    static LLSD mieConfigDefault();
+
+    LLColor3 getColor(const std::string& key, const LLColor3& default_value) const;
+    F32      getFloat(const std::string& key, F32 default_value) const;
+
+    void        calculateHeavenlyBodyPositions() const;
+    void        calculateLightSettings() const;
+    void        clampColor(LLColor3& color, F32 gamma, const F32 scale = 1.0f) const;
+
+    mutable LLVector3   mSunDirection;
+    mutable LLVector3   mMoonDirection;
+    mutable LLVector3   mLightDirection;
+
+    static const F32 DOME_RADIUS;
+    static const F32 DOME_OFFSET;
+
+    mutable LLColor4    mMoonAmbient;
+    mutable LLColor3    mMoonDiffuse;
+    mutable LLColor4    mSunAmbient;
+    mutable LLColor3    mSunDiffuse;
+    mutable LLColor4    mTotalAmbient;
+    mutable LLColor4    mHazeColor;
+
+    typedef std::map<std::string, S32> mapNameToUniformId_t;
+
+    static mapNameToUniformId_t sNameToUniformMapping;
+};
+
+#endif
diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0eb95dcd8958f269caf108375a2e8259d9ed4a38
--- /dev/null
+++ b/indra/llinventory/llsettingswater.cpp
@@ -0,0 +1,304 @@
+/**
+* @file llsettingswater.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "llsettingswater.h"
+#include <algorithm>
+#include <boost/make_shared.hpp>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+#include "indra_constants.h"
+
+//=========================================================================
+namespace
+{
+     LLTrace::BlockTimerStatHandle FTM_BLEND_WATERVALUES("Blending Water Environment");
+     LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERVALUES("Update Water Environment");
+}
+
+//=========================================================================
+const std::string LLSettingsWater::SETTING_BLUR_MULTIPLIER("blur_multiplier");
+const std::string LLSettingsWater::SETTING_FOG_COLOR("water_fog_color");
+const std::string LLSettingsWater::SETTING_FOG_DENSITY("water_fog_density");
+const std::string LLSettingsWater::SETTING_FOG_MOD("underwater_fog_mod");
+const std::string LLSettingsWater::SETTING_FRESNEL_OFFSET("fresnel_offset");
+const std::string LLSettingsWater::SETTING_FRESNEL_SCALE("fresnel_scale");
+const std::string LLSettingsWater::SETTING_TRANSPARENT_TEXTURE("transparent_texture");
+const std::string LLSettingsWater::SETTING_NORMAL_MAP("normal_map");
+const std::string LLSettingsWater::SETTING_NORMAL_SCALE("normal_scale");
+const std::string LLSettingsWater::SETTING_SCALE_ABOVE("scale_above");
+const std::string LLSettingsWater::SETTING_SCALE_BELOW("scale_below");
+const std::string LLSettingsWater::SETTING_WAVE1_DIR("wave1_direction");
+const std::string LLSettingsWater::SETTING_WAVE2_DIR("wave2_direction");
+
+const std::string LLSettingsWater::SETTING_LEGACY_BLUR_MULTIPLIER("blurMultiplier");
+const std::string LLSettingsWater::SETTING_LEGACY_FOG_COLOR("waterFogColor");
+const std::string LLSettingsWater::SETTING_LEGACY_FOG_DENSITY("waterFogDensity");
+const std::string LLSettingsWater::SETTING_LEGACY_FOG_MOD("underWaterFogMod");
+const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_OFFSET("fresnelOffset");
+const std::string LLSettingsWater::SETTING_LEGACY_FRESNEL_SCALE("fresnelScale");
+const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_MAP("normalMap");
+const std::string LLSettingsWater::SETTING_LEGACY_NORMAL_SCALE("normScale");
+const std::string LLSettingsWater::SETTING_LEGACY_SCALE_ABOVE("scaleAbove");
+const std::string LLSettingsWater::SETTING_LEGACY_SCALE_BELOW("scaleBelow");
+const std::string LLSettingsWater::SETTING_LEGACY_WAVE1_DIR("wave1Dir");
+const std::string LLSettingsWater::SETTING_LEGACY_WAVE2_DIR("wave2Dir");
+
+const LLUUID LLSettingsWater::DEFAULT_ASSET_ID("59d1a851-47e7-0e5f-1ed7-6b715154f41a");
+
+static const LLUUID DEFAULT_TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
+static const LLUUID DEFAULT_OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
+
+//=========================================================================
+LLSettingsWater::LLSettingsWater(const LLSD &data) :
+    LLSettingsBase(data),
+    mNextNormalMapID()
+{
+}
+
+LLSettingsWater::LLSettingsWater() :
+    LLSettingsBase(),
+    mNextNormalMapID()
+{
+}
+
+//=========================================================================
+LLSD LLSettingsWater::defaults(const LLSettingsBase::TrackPosition& position)
+{
+    static LLSD dfltsetting;
+
+    if (dfltsetting.size() == 0)
+    {
+        // give the normal scale offset some variability over track time...
+        F32 normal_scale_offset = (position * 0.5f) - 0.25f;
+
+        // Magic constants copied form defaults.xml 
+        dfltsetting[SETTING_BLUR_MULTIPLIER] = LLSD::Real(0.04000f);
+        dfltsetting[SETTING_FOG_COLOR] = LLColor3(0.0156f, 0.1490f, 0.2509f).getValue();
+        dfltsetting[SETTING_FOG_DENSITY] = LLSD::Real(2.0f);
+        dfltsetting[SETTING_FOG_MOD] = LLSD::Real(0.25f);
+        dfltsetting[SETTING_FRESNEL_OFFSET] = LLSD::Real(0.5f);
+        dfltsetting[SETTING_FRESNEL_SCALE] = LLSD::Real(0.3999);
+        dfltsetting[SETTING_TRANSPARENT_TEXTURE] = GetDefaultTransparentTextureAssetId();
+        dfltsetting[SETTING_NORMAL_MAP] = GetDefaultWaterNormalAssetId();
+        dfltsetting[SETTING_NORMAL_SCALE] = LLVector3(2.0f + normal_scale_offset, 2.0f + normal_scale_offset, 2.0f + normal_scale_offset).getValue();
+        dfltsetting[SETTING_SCALE_ABOVE] = LLSD::Real(0.0299f);
+        dfltsetting[SETTING_SCALE_BELOW] = LLSD::Real(0.2000f);
+        dfltsetting[SETTING_WAVE1_DIR] = LLVector2(1.04999f, -0.42000f).getValue();
+        dfltsetting[SETTING_WAVE2_DIR] = LLVector2(1.10999f, -1.16000f).getValue();
+
+        dfltsetting[SETTING_TYPE] = "water";
+    }
+
+    return dfltsetting;
+}
+
+LLSD LLSettingsWater::translateLegacySettings(LLSD legacy)
+{
+    bool converted_something(false);
+    LLSD newsettings(defaults());
+
+    if (legacy.has(SETTING_LEGACY_BLUR_MULTIPLIER))
+    {
+        newsettings[SETTING_BLUR_MULTIPLIER] = LLSD::Real(legacy[SETTING_LEGACY_BLUR_MULTIPLIER].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_FOG_COLOR))
+    {
+        newsettings[SETTING_FOG_COLOR] = LLColor3(legacy[SETTING_LEGACY_FOG_COLOR]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_FOG_DENSITY))
+    {
+        newsettings[SETTING_FOG_DENSITY] = LLSD::Real(legacy[SETTING_LEGACY_FOG_DENSITY]);
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_FOG_MOD))
+    {
+        newsettings[SETTING_FOG_MOD] = LLSD::Real(legacy[SETTING_LEGACY_FOG_MOD].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_FRESNEL_OFFSET))
+    {
+        newsettings[SETTING_FRESNEL_OFFSET] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_OFFSET].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_FRESNEL_SCALE))
+    {
+        newsettings[SETTING_FRESNEL_SCALE] = LLSD::Real(legacy[SETTING_LEGACY_FRESNEL_SCALE].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_NORMAL_MAP))
+    {
+        newsettings[SETTING_NORMAL_MAP] = LLSD::UUID(legacy[SETTING_LEGACY_NORMAL_MAP].asUUID());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_NORMAL_SCALE))
+    {
+        newsettings[SETTING_NORMAL_SCALE] = LLVector3(legacy[SETTING_LEGACY_NORMAL_SCALE]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_SCALE_ABOVE))
+    {
+        newsettings[SETTING_SCALE_ABOVE] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_ABOVE].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_SCALE_BELOW))
+    {
+        newsettings[SETTING_SCALE_BELOW] = LLSD::Real(legacy[SETTING_LEGACY_SCALE_BELOW].asReal());
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_WAVE1_DIR))
+    {
+        newsettings[SETTING_WAVE1_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE1_DIR]).getValue();
+        converted_something |= true;
+    }
+    if (legacy.has(SETTING_LEGACY_WAVE2_DIR))
+    {
+        newsettings[SETTING_WAVE2_DIR] = LLVector2(legacy[SETTING_LEGACY_WAVE2_DIR]).getValue();
+        converted_something |= true;
+    }
+
+    if (!converted_something)
+        return LLSD();
+    return newsettings;
+}
+
+void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F64 blendf) 
+{
+    LLSettingsWater::ptr_t other = PTR_NAMESPACE::static_pointer_cast<LLSettingsWater>(end);
+    if (other)
+    {
+        LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf);
+        replaceSettings(blenddata);
+        mNextNormalMapID = other->getNormalMapID();
+        mNextTransparentTextureID = other->getTransparentTextureID();
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Could not cast end settings to water. No blend performed." << LL_ENDL;
+    }
+    setBlendFactor(blendf);
+}
+
+void LLSettingsWater::replaceSettings(LLSD settings)
+{
+    LLSettingsBase::replaceSettings(settings);
+    mNextNormalMapID.setNull();
+    mNextTransparentTextureID.setNull();
+}
+
+void LLSettingsWater::replaceWithWater(LLSettingsWater::ptr_t other)
+{
+    replaceWith(other);
+
+    mNextNormalMapID = other->mNextNormalMapID;
+    mNextTransparentTextureID = other->mNextTransparentTextureID;
+}
+
+LLSettingsWater::validation_list_t LLSettingsWater::getValidationList() const
+{
+    return LLSettingsWater::validationList();
+}
+
+LLSettingsWater::validation_list_t LLSettingsWater::validationList()
+{
+    static validation_list_t validation;
+
+    if (validation.empty())
+    {   // Note the use of LLSD(LLSDArray()()()...) This is due to an issue with the 
+        // copy constructor for LLSDArray.  Directly binding the LLSDArray as 
+        // a parameter without first wrapping it in a pure LLSD object will result 
+        // in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
+
+        validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-0.5f)(0.5f)))));
+        validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray,
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)),
+                LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f)))));
+        validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-10.0f)(10.0f)))));
+        validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
+        validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+        validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+        validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID));
+        validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray,
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(0.0f)(0.0f)(0.0f)),
+                LLSD(LLSDArray(10.0f)(10.0f)(10.0f)))));
+        validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
+        validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal,
+            boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
+        validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray,
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(-20.0f)(-20.0f)),
+                LLSD(LLSDArray(20.0f)(20.0f)))));
+        validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray,
+            boost::bind(&Validator::verifyVectorMinMax, _1,
+                LLSD(LLSDArray(-20.0f)(-20.0f)),
+                LLSD(LLSDArray(20.0f)(20.0f)))));
+    }
+
+    return validation;
+}
+
+LLUUID LLSettingsWater::GetDefaultAssetId()
+{
+    return DEFAULT_ASSET_ID;
+}
+
+LLUUID LLSettingsWater::GetDefaultWaterNormalAssetId()
+{
+    return DEFAULT_WATER_NORMAL;
+}
+
+LLUUID LLSettingsWater::GetDefaultTransparentTextureAssetId()
+{
+    return DEFAULT_TRANSPARENT_WATER_TEXTURE;
+}
+
+LLUUID LLSettingsWater::GetDefaultOpaqueTextureAssetId()
+{
+    return DEFAULT_OPAQUE_WATER_TEXTURE;
+}
+
+F32 LLSettingsWater::getModifiedWaterFogDensity(bool underwater) const
+{
+    F32 fog_density = getWaterFogDensity();
+    F32 underwater_fog_mod = getFogMod();
+    if (underwater && underwater_fog_mod > 0.0f)
+    {        
+        underwater_fog_mod = llclamp(underwater_fog_mod, 0.0f, 10.0f);
+        fog_density = pow(fog_density, underwater_fog_mod);
+    }
+    return fog_density;
+}
diff --git a/indra/llinventory/llsettingswater.h b/indra/llinventory/llsettingswater.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0bfd29f2d91f8d910a2a909d27e3eba2ab3af44
--- /dev/null
+++ b/indra/llinventory/llsettingswater.h
@@ -0,0 +1,249 @@
+/**
+* @file llsettingssky.h
+* @author optional
+* @brief A base class for asset based settings groups.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_SETTINGS_WATER_H
+#define LL_SETTINGS_WATER_H
+
+#include "llsettingsbase.h"
+
+class LLSettingsWater : public LLSettingsBase
+{
+public:
+    static const std::string SETTING_BLUR_MULTIPLIER;
+    static const std::string SETTING_FOG_COLOR;
+    static const std::string SETTING_FOG_DENSITY;
+    static const std::string SETTING_FOG_MOD;
+    static const std::string SETTING_FRESNEL_OFFSET;
+    static const std::string SETTING_FRESNEL_SCALE;
+    static const std::string SETTING_TRANSPARENT_TEXTURE;
+    static const std::string SETTING_NORMAL_MAP;
+    static const std::string SETTING_NORMAL_SCALE;
+    static const std::string SETTING_SCALE_ABOVE;
+    static const std::string SETTING_SCALE_BELOW;
+    static const std::string SETTING_WAVE1_DIR;
+    static const std::string SETTING_WAVE2_DIR;
+
+    static const LLUUID DEFAULT_ASSET_ID;
+
+    typedef PTR_NAMESPACE::shared_ptr<LLSettingsWater> ptr_t;
+
+    //---------------------------------------------------------------------
+    LLSettingsWater(const LLSD &data);
+    virtual ~LLSettingsWater() { };
+
+    virtual ptr_t   buildClone() const = 0;
+
+    //---------------------------------------------------------------------
+    virtual std::string     getSettingsType() const SETTINGS_OVERRIDE { return std::string("water"); }
+    virtual LLSettingsType::type_e  getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; }
+
+    // Settings status 
+    virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
+
+    virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
+    void replaceWithWater(LLSettingsWater::ptr_t other);
+
+    static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
+
+    //---------------------------------------------------------------------
+    F32 getBlurMultiplier() const
+    {   
+        return mSettings[SETTING_BLUR_MULTIPLIER].asReal();
+    }
+
+    void setBlurMultiplier(F32 val)
+    {
+        setValue(SETTING_BLUR_MULTIPLIER, val);
+    }
+
+    LLColor3 getWaterFogColor() const
+    {
+        return LLColor3(mSettings[SETTING_FOG_COLOR]);
+    }
+
+    void setWaterFogColor(LLColor3 val)
+    {
+        setValue(SETTING_FOG_COLOR, val);
+    }
+
+    F32 getWaterFogDensity() const
+    {
+        return mSettings[SETTING_FOG_DENSITY].asReal();
+    }
+
+    F32 getModifiedWaterFogDensity(bool underwater) const;
+
+    void setWaterFogDensity(F32 val)
+    {
+        setValue(SETTING_FOG_DENSITY, val);
+    }
+
+    F32 getFogMod() const
+    {
+        return mSettings[SETTING_FOG_MOD].asReal();
+    }
+
+    void setFogMod(F32 val)
+    {
+        setValue(SETTING_FOG_MOD, val);
+    }
+
+    F32 getFresnelOffset() const
+    {
+        return mSettings[SETTING_FRESNEL_OFFSET].asReal();
+    }
+
+    void setFresnelOffset(F32 val)
+    {
+        setValue(SETTING_FRESNEL_OFFSET, val);
+    }
+
+    F32 getFresnelScale() const
+    {
+        return mSettings[SETTING_FRESNEL_SCALE].asReal();
+    }
+
+    void setFresnelScale(F32 val)
+    {
+        setValue(SETTING_FRESNEL_SCALE, val);
+    }
+
+    LLUUID getTransparentTextureID() const
+    {
+        return mSettings[SETTING_TRANSPARENT_TEXTURE].asUUID();
+    }
+
+    void setTransparentTextureID(LLUUID val)
+    {
+        setValue(SETTING_TRANSPARENT_TEXTURE, val);
+    }
+
+    LLUUID getNormalMapID() const
+    {
+        return mSettings[SETTING_NORMAL_MAP].asUUID();
+    }
+
+    void setNormalMapID(LLUUID val)
+    {
+        setValue(SETTING_NORMAL_MAP, val);
+    }
+
+    LLVector3 getNormalScale() const
+    {
+        return LLVector3(mSettings[SETTING_NORMAL_SCALE]);
+    }
+
+    void setNormalScale(LLVector3 val)
+    {
+        setValue(SETTING_NORMAL_SCALE, val);
+    }
+
+    F32 getScaleAbove() const
+    {
+        return mSettings[SETTING_SCALE_ABOVE].asReal();
+    }
+
+    void setScaleAbove(F32 val)
+    {
+        setValue(SETTING_SCALE_ABOVE, val);
+    }
+
+    F32 getScaleBelow() const
+    {
+        return mSettings[SETTING_SCALE_BELOW].asReal();
+    }
+
+    void setScaleBelow(F32 val)
+    {
+        setValue(SETTING_SCALE_BELOW, val);
+    }
+
+    LLVector2 getWave1Dir() const
+    {
+        return LLVector2(mSettings[SETTING_WAVE1_DIR]);
+    }
+
+    void setWave1Dir(LLVector2 val)
+    {
+        setValue(SETTING_WAVE1_DIR, val);
+    }
+
+    LLVector2 getWave2Dir() const
+    {
+        return LLVector2(mSettings[SETTING_WAVE2_DIR]);
+    }
+
+    void setWave2Dir(LLVector2 val)
+    {
+        setValue(SETTING_WAVE2_DIR, val);
+    }
+
+    //-------------------------------------------
+    LLUUID getNextNormalMapID() const
+    {
+        return mNextNormalMapID;
+    }
+
+    LLUUID getNextTransparentTextureID() const
+    {
+        return mNextTransparentTextureID;
+    }
+
+    virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
+    static validation_list_t validationList();
+
+    static LLSD         translateLegacySettings(LLSD legacy);
+
+    virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
+
+    static LLUUID GetDefaultAssetId();
+    static LLUUID GetDefaultWaterNormalAssetId();
+    static LLUUID GetDefaultTransparentTextureAssetId();
+    static LLUUID GetDefaultOpaqueTextureAssetId();
+
+protected:
+    static const std::string SETTING_LEGACY_BLUR_MULTIPLIER;
+    static const std::string SETTING_LEGACY_FOG_COLOR;
+    static const std::string SETTING_LEGACY_FOG_DENSITY;
+    static const std::string SETTING_LEGACY_FOG_MOD;
+    static const std::string SETTING_LEGACY_FRESNEL_OFFSET;
+    static const std::string SETTING_LEGACY_FRESNEL_SCALE;
+    static const std::string SETTING_LEGACY_NORMAL_MAP;
+    static const std::string SETTING_LEGACY_NORMAL_SCALE;
+    static const std::string SETTING_LEGACY_SCALE_ABOVE;
+    static const std::string SETTING_LEGACY_SCALE_BELOW;
+    static const std::string SETTING_LEGACY_WAVE1_DIR;
+    static const std::string SETTING_LEGACY_WAVE2_DIR;
+
+    LLSettingsWater();
+
+    LLUUID    mNextTransparentTextureID;
+    LLUUID    mNextNormalMapID;
+
+};
+
+#endif
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 379c3ee9eaf8f0c73140e9c54a7d3c24e3f17ede..999bee0a3fe04a64d2b46562f24008acce55510a 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -90,6 +90,7 @@ set(llmath_HEADER_FILES
     raytrace.h
     v2math.h
     v3color.h
+    v3colorutil.h
     v3dmath.h
     v3math.h
     v4color.h
diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp
index ff90532f75959303d0adc7134d28cc465f99a98a..90341820721bc656451790c72861789b21ba7a5b 100644
--- a/indra/llmath/llcamera.cpp
+++ b/indra/llmath/llcamera.cpp
@@ -93,6 +93,11 @@ F32 LLCamera::getMaxView() const
 		: MAX_FIELD_OF_VIEW; // narrow views
 }
 
+LLPlane LLCamera::getUserClipPlane()
+{
+    return mAgentPlanes[AGENT_PLANE_USER_CLIP];
+}
+
 // ---------------- LLCamera::setFoo() member functions ----------------
 
 void LLCamera::setUserClipPlane(LLPlane& plane)
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index 321b8ddcc43799d136716010cacd5a857ee27349..d0afa0e88f3a58517a4126dda321c2bdc3ddb366 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -154,6 +154,7 @@ class LLCamera
 	
 	bool isChanged(); //check if mAgentPlanes changed since last frame.
 
+    LLPlane getUserClipPlane();
 	void setUserClipPlane(LLPlane& plane);
 	void disableUserClipPlane();
 	virtual void setView(F32 vertical_fov_rads);
diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp
index 1bf51ca0eb2e0a8ebbce0780a8493629bdf871e5..b25fd948f5db2b01682c1836335b9be458096081 100644
--- a/indra/llmath/llcoordframe.cpp
+++ b/indra/llmath/llcoordframe.cpp
@@ -34,6 +34,20 @@
 #include "llquaternion.h"
 #include "llcoordframe.h"
 
+#define CHECK_FINITE(var)                                            \
+    if (!var.isFinite())                                             \
+    {                                                                \
+        LL_WARNS() << "Non Finite " << std::string(#var) << LL_ENDL; \
+        reset();                                                     \
+    }
+
+#define CHECK_FINITE_OBJ()                                       \
+    if (!isFinite())                                             \
+    {                                                            \
+        LL_WARNS() << "Non Finite in LLCoordFrame " << LL_ENDL;  \
+        reset();                                                 \
+    }
+
 #ifndef X_AXIS
 	#define X_AXIS 1.0f,0.0f,0.0f
 	#define Y_AXIS 0.0f,1.0f,0.0f
@@ -56,11 +70,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin) :
 	mYAxis(Y_AXIS),
 	mZAxis(Z_AXIS)
 {
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
 LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction) :
@@ -68,11 +78,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLVector3 &direction)
 {
 	lookDir(direction);
 	
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+    CHECK_FINITE_OBJ();
 }
 
 LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis,
@@ -83,11 +89,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &x_axis,
 	mYAxis(y_axis), 
 	mZAxis(z_axis)
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
@@ -99,11 +101,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
 	mYAxis(y_axis), 
 	mZAxis(z_axis)
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -114,11 +112,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin,
 	mYAxis(rotation.mMatrix[VY]),
 	mZAxis(rotation.mMatrix[VZ])
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 LLCoordFrame::LLCoordFrame(const LLQuaternion &q) :
@@ -129,11 +123,7 @@ LLCoordFrame::LLCoordFrame(const LLQuaternion &q) :
 	mYAxis.setVec(rotation_matrix.mMatrix[VY]);
 	mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
 
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) :
@@ -144,11 +134,7 @@ LLCoordFrame::LLCoordFrame(const LLVector3 &origin, const LLQuaternion &q) :
 	mYAxis.setVec(rotation_matrix.mMatrix[VY]);
 	mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
 
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) :
@@ -157,11 +143,7 @@ LLCoordFrame::LLCoordFrame(const LLMatrix4 &mat) :
 	mYAxis(mat.mMatrix[VY]),
 	mZAxis(mat.mMatrix[VZ])
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -173,11 +155,7 @@ LLCoordFrame::LLCoordFrame(const F32 *origin, const F32 *rotation) :
 	mYAxis(rotation+3*VY),
 	mZAxis(rotation+3*VZ)
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 */
 
@@ -188,11 +166,7 @@ LLCoordFrame::LLCoordFrame(const F32 *origin_and_rotation) :
 	mYAxis(origin_and_rotation + 3*(VY+1)),
 	mZAxis(origin_and_rotation + 3*(VZ+1))
 {
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::LLCoordFrame()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 */
 
@@ -217,21 +191,13 @@ void LLCoordFrame::setOrigin(F32 x, F32 y, F32 z)
 {
 	mOrigin.setVec(x, y, z); 
 
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
 void LLCoordFrame::setOrigin(const LLVector3 &new_origin)
 {
 	mOrigin = new_origin; 
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
-	}
+	CHECK_FINITE(mOrigin);
 }
 
 void LLCoordFrame::setOrigin(const F32 *origin)
@@ -239,23 +205,13 @@ void LLCoordFrame::setOrigin(const F32 *origin)
 	mOrigin.mV[VX] = *(origin + VX);
 	mOrigin.mV[VY] = *(origin + VY);
 	mOrigin.mV[VZ] = *(origin + VZ);
-
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
 void LLCoordFrame::setOrigin(const LLCoordFrame &frame)
 {
 	mOrigin = frame.getOrigin();
-
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setOrigin()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
 // setAxes()  member functions set the axes, and assume that
@@ -268,11 +224,7 @@ void LLCoordFrame::setAxes(const LLVector3 &x_axis,
 	mXAxis = x_axis;
 	mYAxis = y_axis;
 	mZAxis = z_axis;
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -281,11 +233,7 @@ void LLCoordFrame::setAxes(const LLMatrix3 &rotation_matrix)
 	mXAxis.setVec(rotation_matrix.mMatrix[VX]);
 	mYAxis.setVec(rotation_matrix.mMatrix[VY]);
 	mZAxis.setVec(rotation_matrix.mMatrix[VZ]);
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -293,11 +241,7 @@ void LLCoordFrame::setAxes(const LLQuaternion &q )
 {
 	LLMatrix3 rotation_matrix(q);
 	setAxes(rotation_matrix);
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -313,11 +257,7 @@ void LLCoordFrame::setAxes(  const F32 *rotation_matrix )
 	mZAxis.mV[VY] = *(rotation_matrix + 3*VZ + VY);
 	mZAxis.mV[VZ] = *(rotation_matrix + 3*VZ + VZ);
 
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 
@@ -326,40 +266,22 @@ void LLCoordFrame::setAxes(const LLCoordFrame &frame)
 	mXAxis = frame.getXAxis();
 	mYAxis = frame.getYAxis();
 	mZAxis = frame.getZAxis();
-
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::setAxes()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
-
 // translate() member functions move mOrigin to a relative position
-
 void LLCoordFrame::translate(F32 x, F32 y, F32 z)
 {
 	mOrigin.mV[VX] += x;
 	mOrigin.mV[VY] += y;
 	mOrigin.mV[VZ] += z;
-
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
-
 void LLCoordFrame::translate(const LLVector3 &v)
 {
 	mOrigin += v;
-
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
-	}
+    CHECK_FINITE(mOrigin);
 }
 
 
@@ -368,12 +290,7 @@ void LLCoordFrame::translate(const F32 *origin)
 	mOrigin.mV[VX] += *(origin + VX);
 	mOrigin.mV[VY] += *(origin + VY);
 	mOrigin.mV[VZ] += *(origin + VZ);
-
-	if( !mOrigin.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::translate()" << LL_ENDL;
-	}
+	CHECK_FINITE(mOrigin);
 }
 
 
@@ -383,6 +300,7 @@ void LLCoordFrame::rotate(F32 angle, F32 x, F32 y, F32 z)
 {
 	LLQuaternion q(angle, LLVector3(x,y,z));
 	rotate(q);
+    CHECK_FINITE_OBJ();
 }
 
 
@@ -390,6 +308,7 @@ void LLCoordFrame::rotate(F32 angle, const LLVector3 &rotation_axis)
 {
 	LLQuaternion q(angle, rotation_axis);
 	rotate(q);
+    CHECK_FINITE_OBJ();
 }
 
 
@@ -397,6 +316,7 @@ void LLCoordFrame::rotate(const LLQuaternion &q)
 {
 	LLMatrix3 rotation_matrix(q);
 	rotate(rotation_matrix);
+    CHECK_FINITE_OBJ();
 }
 
 
@@ -405,12 +325,7 @@ void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix)
 	mXAxis.rotVec(rotation_matrix);
 	mYAxis.rotVec(rotation_matrix);
 	orthonormalize();
-
-	if( !isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::rotate()" << LL_ENDL;
-	}
+    CHECK_FINITE_OBJ();
 }
 
 
@@ -419,12 +334,7 @@ void LLCoordFrame::roll(F32 angle)
 	LLQuaternion q(angle, mXAxis);
 	LLMatrix3 rotation_matrix(q);
 	rotate(rotation_matrix);
-
-	if( !mYAxis.isFinite() || !mZAxis.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::roll()" << LL_ENDL;
-	}
+    CHECK_FINITE_OBJ();
 }
 
 void LLCoordFrame::pitch(F32 angle)
@@ -432,12 +342,7 @@ void LLCoordFrame::pitch(F32 angle)
 	LLQuaternion q(angle, mYAxis);
 	LLMatrix3 rotation_matrix(q);
 	rotate(rotation_matrix);
-
-	if( !mXAxis.isFinite() || !mZAxis.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::pitch()" << LL_ENDL;
-	}
+	CHECK_FINITE_OBJ();
 }
 
 void LLCoordFrame::yaw(F32 angle)
@@ -445,12 +350,7 @@ void LLCoordFrame::yaw(F32 angle)
 	LLQuaternion q(angle, mZAxis);
 	LLMatrix3 rotation_matrix(q);
 	rotate(rotation_matrix);
-
-	if( !mXAxis.isFinite() || !mYAxis.isFinite() )
-	{
-		reset();
-		LL_WARNS() << "Non Finite in LLCoordFrame::yaw()" << LL_ENDL;
-	}
+    CHECK_FINITE_OBJ();
 }
 
 // get*() routines
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index e508c9a19976cabea54d7055a8753dffaa6ef20a..8f01ad6c1cad3f02a79c14b928327ba62bd43a61 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -537,6 +537,35 @@ inline void ll_remove_outliers(std::vector<VEC_TYPE>& data, F32 k)
 	}
 }
 
+// Converts given value from a linear RGB floating point value (0..1) to a gamma corrected (sRGB) value.
+// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
+// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied
+// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch)
+// Note: DO NOT cache the conversion.  This leads to error prone synchronization and is actually slower in the typical case due to cache misses
+inline float linearTosRGB(const float val) {
+    if (val < 0.0031308f) {
+        return val * 12.92f;
+    }
+    else {
+        return 1.055f * pow(val, 1.0f / 2.4f) - 0.055f;
+    }
+}
+
+// Converts given value from a gamma corrected (sRGB) floating point value (0..1) to a linear color value.
+// Some shaders require color values in linear space, while others require color values in gamma corrected (sRGB) space.
+// Note: In our code, values labeled as sRGB are gamma corrected linear values, NOT linear values with monitor gamma applied
+// Note: Stored color values should generally be gamma corrected sRGB.  
+//       If you're serializing the return value of this function, you're probably doing it wrong.
+// Note: DO NOT cache the conversion.  This leads to error prone synchronization and is actually slower in the typical case due to cache misses.
+inline float sRGBtoLinear(const float val) {
+    if (val < 0.04045f) {
+        return val / 12.92f;
+    }
+    else {
+        return pow((val + 0.055f) / 1.055f, 2.4f);
+    }
+}
+
 // Include simd math header
 #include "llsimdmath.h"
 
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index 47374c287f2d4c1b008534b726fe5647dd9b3bc0..57a976b57ae365ebad38006ad7ccb0a37dff4d78 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -104,6 +104,11 @@ LLQuaternion::LLQuaternion(const LLVector3 &x_axis,
 	normalize();
 }
 
+LLQuaternion::LLQuaternion(const LLSD &sd)
+{
+    setValue(sd);
+}
+
 // Quatizations
 void	LLQuaternion::quantize16(F32 lower, F32 upper)
 {
@@ -860,6 +865,26 @@ void LLQuaternion::getAngleAxis(F32* angle, LLVector3 &vec) const
 	}
 }
 
+const LLQuaternion& LLQuaternion::setFromAzimuthAndAltitude(F32 azimuthRadians, F32 altitudeRadians)
+{
+    // euler angle inputs are complements of azimuth/altitude which are measured from zenith
+    F32 pitch = llclamp(F_PI_BY_TWO - altitudeRadians, 0.0f, F_PI_BY_TWO);
+    F32 yaw   = llclamp(F_PI_BY_TWO - azimuthRadians,  0.0f, F_PI_BY_TWO);
+    setEulerAngles(0.0f, pitch, yaw);
+    return *this;
+}
+
+void LLQuaternion::getAzimuthAndAltitude(F32 &azimuthRadians, F32 &altitudeRadians)
+{
+    F32 rick_roll;
+    F32 pitch;
+    F32 yaw;
+    getEulerAngles(&rick_roll, &pitch, &yaw);
+    // make these measured from zenith
+    altitudeRadians = llclamp(F_PI_BY_TWO - pitch, 0.0f, F_PI_BY_TWO);
+    azimuthRadians  = llclamp(F_PI_BY_TWO - yaw,   0.0f, F_PI_BY_TWO);
+}
+
 // quaternion does not need to be normalized
 void LLQuaternion::getEulerAngles(F32 *roll, F32 *pitch, F32 *yaw) const
 {
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 95e4c096953893d7de13e4cd28ad04811768d0ce..51ce163b4e51ca704d13a2998b329a727e3fa5e0 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -28,7 +28,7 @@
 #define LLQUATERNION_H
 
 #include <iostream>
-#include <llsd.h>
+#include "llsd.h"
 
 #ifndef LLMATH_H //enforce specific include order to avoid tangling inline dependencies
 #error "Please include llmath.h first."
@@ -64,29 +64,10 @@ class LLQuaternion
 	LLQuaternion(const LLVector3 &x_axis,
 				 const LLVector3 &y_axis,
 				 const LLVector3 &z_axis);			// Initializes Quaternion from Matrix3 = [x_axis ; y_axis ; z_axis]
+    explicit LLQuaternion(const LLSD &sd);          // Initializes Quaternion from LLSD array.
 
-	explicit LLQuaternion(const LLSD& sd)
-	{
-		setValue(sd);
-	}
-
-	void setValue(const LLSD& sd)
-	{
-		mQ[VX] = (F32) sd[0].asReal();
-		mQ[VY] = (F32) sd[1].asReal();
-		mQ[VZ] = (F32) sd[2].asReal();
-		mQ[VS] = (F32) sd[3].asReal();
-	}
-
-	LLSD getValue() const
-	{
-		LLSD ret;
-		ret[0] = mQ[VX];
-		ret[1] = mQ[VY];
-		ret[2] = mQ[VZ];
-		ret[3] = mQ[VS];
-		return ret;
-	}
+    LLSD getValue() const;
+    void setValue(const LLSD& sd);
 
 	BOOL isIdentity() const;
 	BOOL isNotIdentity() const;
@@ -103,7 +84,8 @@ class LLQuaternion
 	const LLQuaternion&	set(const F32 *q);						// Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW])
 	const LLQuaternion&	set(const LLMatrix3 &mat);				// Sets Quaternion to mat2quat(mat)
 	const LLQuaternion&	set(const LLMatrix4 &mat);				// Sets Quaternion to mat2quat(mat)
-
+    const LLQuaternion& setFromAzimuthAndAltitude(F32 azimuth, F32 altitude);
+    
 	const LLQuaternion&	setAngleAxis(F32 angle, F32 x, F32 y, F32 z);	// Sets Quaternion to axis_angle2quat(angle, x, y, z)
 	const LLQuaternion&	setAngleAxis(F32 angle, const LLVector3 &vec);	// Sets Quaternion to axis_angle2quat(angle, vec)
 	const LLQuaternion&	setAngleAxis(F32 angle, const LLVector4 &vec);	// Sets Quaternion to axis_angle2quat(angle, vec)
@@ -124,6 +106,7 @@ class LLQuaternion
 	void		getAngleAxis(F32* angle, F32* x, F32* y, F32* z) const;	// returns rotation in radians about axis x,y,z
 	void		getAngleAxis(F32* angle, LLVector3 &vec) const;
 	void		getEulerAngles(F32 *roll, F32* pitch, F32 *yaw) const;
+    void        getAzimuthAndAltitude(F32 &azimuth, F32 &altitude);
 
 	F32	normalize();	// Normalizes Quaternion and returns magnitude
 	F32	normQuat();		// deprecated
@@ -190,6 +173,24 @@ class LLQuaternion
 	//static U32 mMultCount;
 };
 
+inline LLSD LLQuaternion::getValue() const
+{
+    LLSD ret;
+    ret[0] = mQ[0];
+    ret[1] = mQ[1];
+    ret[2] = mQ[2];
+    ret[3] = mQ[3];
+    return ret;
+}
+
+inline void LLQuaternion::setValue(const LLSD& sd)
+{
+    mQ[0] = sd[0].asReal();
+    mQ[1] = sd[1].asReal();
+    mQ[2] = sd[2].asReal();
+    mQ[3] = sd[3].asReal();
+}
+
 // checker
 inline BOOL	LLQuaternion::isFinite() const
 {
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 49a186bc875c90e4512e8348a4d55241800db055..2ac1eb99ce7d250ebba085d4ca251bae0750931e 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -2205,7 +2205,6 @@ BOOL LLVolume::generate()
 			{
 				rot_mat.rotate(*profile++, tmp);
 				dst->setAdd(tmp,offset);
-				llassert(dst->isFinite3()); // MAINT-5660; don't know why this happens, does not affect Release builds
 				++dst;
 			}
 		}
@@ -4657,6 +4656,10 @@ LLVolumeFace::LLVolumeFace() :
 	mTexCoords(NULL),
 	mIndices(NULL),
 	mWeights(NULL),
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    mJustWeights(NULL),
+    mJointIndices(NULL),
+#endif
     mWeightsScrubbed(FALSE),
 	mOctree(NULL),
 	mOptimized(FALSE)
@@ -4683,6 +4686,10 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)
 	mTexCoords(NULL),
 	mIndices(NULL),
 	mWeights(NULL),
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    mJustWeights(NULL),
+    mJointIndices(NULL),
+#endif
     mWeightsScrubbed(FALSE),
 	mOctree(NULL)
 { 
@@ -4747,24 +4754,46 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
 
 		if (src.mWeights)
 		{
+            llassert(!mWeights); // don't orphan an old alloc here accidentally
 			allocateWeights(src.mNumVertices);
-			LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
+			LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);            
+            mWeightsScrubbed = src.mWeightsScrubbed;
 		}
 		else
 		{
-			ll_aligned_free_16(mWeights);
-			mWeights = NULL;
-		}
-        mWeightsScrubbed = src.mWeightsScrubbed;
-	}
+			ll_aligned_free_16(mWeights);            
+			mWeights = NULL;            
+            mWeightsScrubbed = FALSE;
+		}   
+
+    #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+        if (src.mJointIndices)
+        {
+            llassert(!mJointIndices); // don't orphan an old alloc here accidentally
+            allocateJointIndices(src.mNumVertices);
+            LLVector4a::memcpyNonAliased16((F32*) mJointIndices, (F32*) src.mJointIndices, src.mNumVertices * sizeof(U8) * 4);
+        }
+        else*/
+        {
+            ll_aligned_free_16(mJointIndices);
+            mJointIndices = NULL;
+        }     
+    #endif
 
+	}
+    
 	if (mNumIndices)
 	{
 		S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF;
 		
 		LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);
 	}
-	
+	else
+    {
+        ll_aligned_free_16(mIndices);
+        mIndices = NULL;
+    }
+
 	mOptimized = src.mOptimized;
 
 	//delete 
@@ -4796,6 +4825,13 @@ void LLVolumeFace::freeData()
 	ll_aligned_free_16(mWeights);
 	mWeights = NULL;
 
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    ll_aligned_free_16(mJointIndices);
+	mJointIndices = NULL;
+    ll_aligned_free_16(mJustWeights);
+	mJustWeights = NULL;
+#endif
+
 	delete mOctree;
 	mOctree = NULL;
 }
@@ -5449,11 +5485,17 @@ bool LLVolumeFace::cacheOptimize()
 	// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
 	ll_aligned_free_16(mWeights);
 	ll_aligned_free_16(mTangents);
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    ll_aligned_free_16(mJointIndices);
+    ll_aligned_free_16(mJustWeights);
+    mJustWeights = NULL;
+    mJointIndices = NULL; // filled in later as necessary by skinning code for acceleration
+#endif
 
 	mPositions = pos;
 	mNormals = norm;
 	mTexCoords = tc;
-	mWeights = wght;
+	mWeights = wght;    
 	mTangents = binorm;
 
 	//std::string result = llformat("ACMR pre/post: %.3f/%.3f  --  %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
@@ -6363,7 +6405,19 @@ void LLVolumeFace::allocateTangents(S32 num_verts)
 void LLVolumeFace::allocateWeights(S32 num_verts)
 {
 	ll_aligned_free_16(mWeights);
-	mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
+	mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
+    
+}
+
+void LLVolumeFace::allocateJointIndices(S32 num_verts)
+{
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    ll_aligned_free_16(mJointIndices);
+    ll_aligned_free_16(mJustWeights);
+
+    mJointIndices = (U8*)ll_aligned_malloc_16(sizeof(U8) * 4 * num_verts);    
+    mJustWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a) * num_verts);    
+#endif
 }
 
 void LLVolumeFace::resizeIndices(S32 num_indices)
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 1d6d35c4324895c873c802a99b29230031870aa5..a77e8c08c6585b1606243f514627bf7256e432ac 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -875,6 +875,7 @@ class LLVolumeFace
 	void resizeVertices(S32 num_verts);
 	void allocateTangents(S32 num_verts);
 	void allocateWeights(S32 num_verts);
+    void allocateJointIndices(S32 num_verts);
 	void resizeIndices(S32 num_indices);
 	void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
 
@@ -956,6 +957,11 @@ class LLVolumeFace
 	// mWeights.size() should be empty or match mVertices.size()  
 	LLVector4a* mWeights;
 
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    LLVector4a* mJustWeights;
+    U8* mJointIndices;
+#endif
+
     mutable BOOL mWeightsScrubbed;
 
     // Which joints are rigged to, and the bounding box of any rigged
diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp
index 802ddb9e5739176a3b890a4808847d5eb18efbd4..65eb3348de4620f1d8ebc80b3500facee31c491b 100644
--- a/indra/llmath/m3math.cpp
+++ b/indra/llmath/m3math.cpp
@@ -75,13 +75,6 @@ LLMatrix3::LLMatrix3(const F32 angle, const LLVector4 &vec)
 	setRot(quat);
 }
 
-LLMatrix3::LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z)
-{
-	LLVector3 vec(x, y, z);
-	LLQuaternion	quat(angle, vec);
-	setRot(quat);
-}
-
 LLMatrix3::LLMatrix3(const F32 roll, const F32 pitch, const F32 yaw)
 {
 	setRot(roll,pitch,yaw);
@@ -294,14 +287,6 @@ LLQuaternion	LLMatrix3::quaternion() const
 	return quat;
 }
 
-
-// These functions take Rotation arguments
-const LLMatrix3&	LLMatrix3::setRot(const F32 angle, const F32 x, const F32 y, const F32 z)
-{
-	setRot(LLQuaternion(angle,x,y,z));
-	return *this;
-}
-
 const LLMatrix3&	LLMatrix3::setRot(const F32 angle, const LLVector3 &vec)
 {
 	setRot(LLQuaternion(angle, vec));
@@ -394,15 +379,6 @@ const LLMatrix3& LLMatrix3::setCol( U32 colIndex, const LLVector3& col )
 
 	return *this;
 }
-		
-// Rotate exisitng mMatrix
-const LLMatrix3&	LLMatrix3::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
-{
-	LLMatrix3	mat(angle, x, y, z);
-	*this *= mat;
-	return *this;
-}
-
 
 const LLMatrix3&	LLMatrix3::rotate(const F32 angle, const LLVector3 &vec)
 {
diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h
index 2be5452f8dc05b66fc0a0d41472d3f81c8e9d4f7..bf3889585582fc37e8998e1747d4e7ce0430b63b 100644
--- a/indra/llmath/m3math.h
+++ b/indra/llmath/m3math.h
@@ -60,7 +60,6 @@ class LLMatrix3
 		explicit LLMatrix3(const F32 *mat);					// Initializes Matrix to values in mat
 		explicit LLMatrix3(const LLQuaternion &q);			// Initializes Matrix with rotation q
 
-		LLMatrix3(const F32 angle, const F32 x, const F32 y, const F32 z);	// Initializes Matrix with axis angle
 		LLMatrix3(const F32 angle, const LLVector3 &vec);	// Initializes Matrix with axis angle
 		LLMatrix3(const F32 angle, const LLVector3d &vec);	// Initializes Matrix with axis angle
 		LLMatrix3(const F32 angle, const LLVector4 &vec);	// Initializes Matrix with axis angle
@@ -81,8 +80,7 @@ class LLMatrix3
 		// Matrix setters - set some properties without modifying others
 		//
 
-		// These functions take Rotation arguments
-		const LLMatrix3& setRot(const F32 angle, const F32 x, const F32 y, const F32 z);	// Calculate rotation matrix for rotating angle radians about (x, y, z)
+		// These functions take Rotation arguments		
 		const LLMatrix3& setRot(const F32 angle, const LLVector3 &vec);	// Calculate rotation matrix for rotating angle radians about vec
 		const LLMatrix3& setRot(const F32 roll, const F32 pitch, const F32 yaw);	// Calculate rotation matrix from Euler angles
 		const LLMatrix3& setRot(const LLQuaternion &q);			// Transform matrix by Euler angles and translating by pos
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index d89c482804d760ec49504fb713b959d590bddca4..3baf1bad18bc5ac0f6450793f6353831135b6b7a 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -384,13 +384,6 @@ void LLMatrix4::initRows(const LLVector4 &row0,
 }
 
 
-const LLMatrix4& 	LLMatrix4::initRotation(const F32 angle, const F32 x, const F32 y, const F32 z)
-{
-	LLMatrix3	mat(angle, x, y, z);
-	return initMatrix(mat);
-}
-
-
 const LLMatrix4& 	LLMatrix4::initRotation(F32 angle, const LLVector4 &vec)
 {
 	LLMatrix3	mat(angle, vec);
@@ -412,17 +405,6 @@ const LLMatrix4&  	LLMatrix4::initRotation(const LLQuaternion &q)
 }
 
 
-// Position and Rotation
-const LLMatrix4&  	LLMatrix4::initRotTrans(const F32 angle, const F32 rx, const F32 ry, const F32 rz,
-											const F32 tx, const F32 ty, const F32 tz)
-{
-	LLMatrix3	mat(angle, rx, ry, rz);
-	LLVector3	translation(tx, ty, tz);
-	initMatrix(mat);
-	setTranslation(translation);
-	return (*this);
-}
-
 const LLMatrix4&  	LLMatrix4::initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3&translation)
 {
 	LLMatrix3	mat(angle, axis);
@@ -513,15 +495,6 @@ const LLMatrix4& LLMatrix4::initAll(const LLVector3 &scale, const LLQuaternion &
 	return (*this);
 }
 
-// Rotate exisitng mMatrix
-const LLMatrix4&  	LLMatrix4::rotate(const F32 angle, const F32 x, const F32 y, const F32 z)
-{
-	LLVector4	vec4(x, y, z);
-	LLMatrix4	mat(angle, vec4);
-	*this *= mat;
-	return *this;
-}
-
 const LLMatrix4&  	LLMatrix4::rotate(const F32 angle, const LLVector4 &vec)
 {
 	LLMatrix4	mat(angle, vec);
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index a77c5bc76d11111149559b0f3552823ac9164f9f..bf60adb9b6e9083a4bd684c3b8be98306144be71 100644
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -137,7 +137,6 @@ class LLMatrix4
 	bool isIdentity() const;
 	const LLMatrix4& setZero();						// Clears matrix to all zeros.
 
-	const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z);	// Calculate rotation matrix by rotating angle radians about (x, y, z)
 	const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis);	// Calculate rotation matrix for rotating angle radians about vec
 	const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw);		// Calculate rotation matrix from Euler angles
 	const LLMatrix4& initRotation(const LLQuaternion &q);			// Set with Quaternion and position
@@ -148,10 +147,6 @@ class LLMatrix4
 
 	// These operation create a matrix that will rotate and translate by the
 	// specified amounts.
-	const LLMatrix4& initRotTrans(const F32 angle,
-								  const F32 rx, const F32 ry, const F32 rz,
-								  const F32 px, const F32 py, const F32 pz);
-
 	const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation);	 // Rotation from axis angle + translation
 	const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation
 	const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos);	// Set with Quaternion and position
@@ -211,7 +206,6 @@ class LLMatrix4
 
 	// Rotate existing matrix
 	// These are really, really, inefficient as implemented! - djs
-	const LLMatrix4& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); 		// Rotate matrix by rotating angle radians about (x, y, z)
 	const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec);		// Rotate matrix by rotating angle radians about vec
 	const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw);		// Rotate matrix by Euler angles
 	const LLMatrix4& rotate(const LLQuaternion &q);				// Rotate matrix by Quaternion
diff --git a/indra/llmath/tests/m3math_test.cpp b/indra/llmath/tests/m3math_test.cpp
index 1ca2b005d996b039dc0fd63e79b0dafbc8de54c7..2a0fe76aa7b85257daba5d7e0a317736813be2ff 100644
--- a/indra/llmath/tests/m3math_test.cpp
+++ b/indra/llmath/tests/m3math_test.cpp
@@ -77,7 +77,7 @@ namespace tut
 	template<> template<>
 	void m3math_test_object_t::test<2>()
 	{
-		LLMatrix3 llmat3_obj(30, 1, 2, 3);
+		LLMatrix3 llmat3_obj;
 		llmat3_obj.setZero();
 
 		ensure("LLMatrix3::setZero failed", 0.f == llmat3_obj.setZero().mMatrix[0][0] &&
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index a0cd6428538b61c197dcf7aa29b4fd57163298b0..a24571f2c82ea53af1c0b9438c69cc0fadbb637f 100644
--- a/indra/llmath/v2math.cpp
+++ b/indra/llmath/v2math.cpp
@@ -118,7 +118,7 @@ LLSD LLVector2::getValue() const
 	return ret;
 }
 
-void LLVector2::setValue(LLSD& sd)
+void LLVector2::setValue(const LLSD& sd)
 {
 	mV[0] = (F32) sd[0].asReal();
 	mV[1] = (F32) sd[1].asReal();
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index 8d5db96f5e295633531865c8254960526b970037..2335a2e3273b8991b8405ed6ddd13874b911e2ef 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -49,6 +49,7 @@ class LLVector2
 		LLVector2(F32 x, F32 y);			      // Initializes LLVector2 to (x. y)
 		LLVector2(const F32 *vec);				  // Initializes LLVector2 to (vec[0]. vec[1])
         explicit LLVector2(const LLVector3 &vec); // Initializes LLVector2 to (vec[0]. vec[1])
+        explicit LLVector2(const LLSD &sd);
 		
 		// Clears LLVector2 to (0, 0).  DEPRECATED - prefer zeroVec.
 		void	clear();
@@ -61,7 +62,7 @@ class LLVector2
 		void	set(const F32 *vec);			// Sets LLVector2 to vec
 
 		LLSD	getValue() const;
-		void	setValue(LLSD& sd);
+		void	setValue(const LLSD& sd);
 
 		void	setVec(F32 x, F32 y);	        // deprecated
 		void	setVec(const LLVector2 &vec);	// deprecated
@@ -145,6 +146,10 @@ inline LLVector2::LLVector2(const LLVector3 &vec)
 	mV[VY] = vec.mV[VY];
 }
 
+inline LLVector2::LLVector2(const LLSD &sd)
+{
+    setValue(sd);
+}
 
 // Clear and Assignment Functions
 
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index daf3a6857b489c5f01701ebfb9bbb66169b0c4de..43a632408c7fc05ddec03bf0ad266c800855a7cb 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -100,6 +100,23 @@ class LLColor3
 
 	const LLColor3&	operator=(const LLColor4 &a);
 	
+    LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2)
+    {
+        return LLColor3(
+                mV[0] / col2.mV[0],
+                mV[1] / col2.mV[1],
+                mV[2] / col2.mV[2] );
+    }
+
+    LL_FORCE_INLINE LLColor3 color_norm()
+    {
+        F32 l = length();
+        return LLColor3(
+                mV[0] / l,
+                mV[1] / l,
+                mV[2] / l );
+    }
+
 	friend std::ostream&	 operator<<(std::ostream& s, const LLColor3 &a);		// Print a
 	friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b);	// Return vector a + b
 	friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b);	// Return vector a minus b
@@ -458,5 +475,22 @@ inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u)
 		a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
 }
 
+inline const LLColor3 srgbColor3(const LLColor3 &a) {
+	LLColor3 srgbColor;
+	srgbColor.mV[0] = linearTosRGB(a.mV[0]);
+	srgbColor.mV[1] = linearTosRGB(a.mV[1]);
+	srgbColor.mV[2] = linearTosRGB(a.mV[2]);
+
+	return srgbColor;
+}
+
+inline const LLColor3 linearColor3(const LLColor3 &a) {
+    LLColor3 linearColor;
+    linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
+    linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
+    linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
+
+    return linearColor;
+}
 
 #endif
diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d8cd9329bae87716d9d31c2759d69cc9d7bc691
--- /dev/null
+++ b/indra/llmath/v3colorutil.h
@@ -0,0 +1,115 @@
+/** 
+ * @file v3color.h
+ * @brief LLColor3 class header file.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#ifndef LL_V3COLORUTIL_H
+#define LL_V3COLORUTIL_H
+
+#include "v3color.h"
+
+inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
+{
+    return LLColor3(left.mV[0] / right.mV[0],
+        left.mV[1] / right.mV[1],
+        left.mV[2] / right.mV[2]);
+}
+
+
+inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
+{
+    return LLColor3(left.mV[0] * right.mV[0],
+        left.mV[1] * right.mV[1],
+        left.mV[2] * right.mV[2]);
+}
+
+
+inline LLColor3 componentExp(LLColor3 const &v)
+{
+    return LLColor3(exp(v.mV[0]),
+        exp(v.mV[1]),
+        exp(v.mV[2]));
+}
+
+inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
+{
+    return LLColor3(pow(v.mV[0], exponent),
+        pow(v.mV[1], exponent),
+        pow(v.mV[2], exponent));
+}
+
+inline LLColor3 componentSaturate(LLColor3 const &v)
+{
+    return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
+        std::max(std::min(v.mV[1], 1.f), 0.f),
+        std::max(std::min(v.mV[2], 1.f), 0.f));
+}
+
+
+inline LLColor3 componentSqrt(LLColor3 const &v)
+{
+    return LLColor3(sqrt(v.mV[0]),
+        sqrt(v.mV[1]),
+        sqrt(v.mV[2]));
+}
+
+inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
+{
+    left.mV[0] *= right.mV[0];
+    left.mV[1] *= right.mV[1];
+    left.mV[2] *= right.mV[2];
+}
+
+inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
+{
+    return (left + ((right - left) * amount));
+}
+
+inline LLColor3 smear(F32 val)
+{
+    return LLColor3(val, val, val);
+}
+
+inline F32 color_intens(const LLColor3 &col)
+{
+    return col.mV[0] + col.mV[1] + col.mV[2];
+}
+
+inline F32 color_max(const LLColor3 &col)
+{
+    return llmax(col.mV[0], col.mV[1], col.mV[2]);
+}
+
+inline F32 color_max(const LLColor4 &col)
+{
+    return llmax(col.mV[0], col.mV[1], col.mV[2]);
+}
+
+
+inline F32 color_min(const LLColor3 &col)
+{
+    return llmin(col.mV[0], col.mV[1], col.mV[2]);
+}
+
+#endif
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index 8f353ead5a251c95aca64570f66329753868f7d3..175edf147142fcef08068d1b8efb80a905ed4871 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -114,9 +114,11 @@ class LLColor4
 		friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b);	// Return vector a minus b
 		friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b);	// Return component wise a * b
 		friend LLColor4 operator*(const LLColor4 &a, F32 k);				// Return rgb times scaler k (no alpha change)
+        friend LLColor4 operator/(const LLColor4 &a, F32 k);                // Return rgb divided by scalar k (no alpha change)
 		friend LLColor4 operator*(F32 k, const LLColor4 &a);				// Return rgb times scaler k (no alpha change)
 		friend LLColor4 operator%(const LLColor4 &a, F32 k);				// Return alpha times scaler k (no rgb change)
 		friend LLColor4 operator%(F32 k, const LLColor4 &a);				// Return alpha times scaler k (no rgb change)
+
 		friend bool operator==(const LLColor4 &a, const LLColor4 &b);		// Return a == b
 		friend bool operator!=(const LLColor4 &a, const LLColor4 &b);		// Return a != b
 		
@@ -477,6 +479,15 @@ inline LLColor4 operator*(const LLColor4 &a, F32 k)
 		a.mV[VW]);
 }
 
+inline LLColor4 operator/(const LLColor4 &a, F32 k)
+{
+    return LLColor4(
+        a.mV[VX] / k,
+        a.mV[VY] / k,
+        a.mV[VZ] / k,
+        a.mV[VW]);
+}
+
 inline LLColor4 operator*(F32 k, const LLColor4 &a)
 {
 	// only affects rgb (not a!)
@@ -645,5 +656,29 @@ void LLColor4::clamp()
 	}
 }
 
+// Return the given linear space color value in gamma corrected (sRGB) space
+inline const LLColor4 srgbColor4(const LLColor4 &a) {
+    LLColor4 srgbColor;
+
+    srgbColor.mV[0] = linearTosRGB(a.mV[0]);
+    srgbColor.mV[1] = linearTosRGB(a.mV[1]);
+    srgbColor.mV[2] = linearTosRGB(a.mV[2]);
+    srgbColor.mV[3] = a.mV[3];
+
+    return srgbColor;
+}
+
+// Return the given gamma corrected (sRGB) color in linear space
+inline const LLColor4 linearColor4(const LLColor4 &a)
+{
+    LLColor4 linearColor;
+    linearColor.mV[0] = sRGBtoLinear(a.mV[0]);
+    linearColor.mV[1] = sRGBtoLinear(a.mV[1]);
+    linearColor.mV[2] = sRGBtoLinear(a.mV[2]);
+    linearColor.mV[3] = a.mV[3];
+
+    return linearColor;
+}
+
 #endif
 
diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h
index 623c8b200353bb60bd5f052213a2b3a8f86cc7e8..b8835ba2e40331b292a970a61d218bd3870a672d 100644
--- a/indra/llmath/v4math.h
+++ b/indra/llmath/v4math.h
@@ -30,6 +30,7 @@
 #include "llerror.h"
 #include "llmath.h"
 #include "v3math.h"
+#include "v2math.h"
 
 class LLMatrix3;
 class LLMatrix4;
@@ -46,8 +47,11 @@ class LLVector4
 		LLVector4();						// Initializes LLVector4 to (0, 0, 0, 1)
 		explicit LLVector4(const F32 *vec);			// Initializes LLVector4 to (vec[0]. vec[1], vec[2], vec[3])
 		explicit LLVector4(const F64 *vec);			// Initialized LLVector4 to ((F32) vec[0], (F32) vec[1], (F32) vec[3], (F32) vec[4]);
+        explicit LLVector4(const LLVector2 &vec);
+        explicit LLVector4(const LLVector2 &vec, F32 z, F32 w);
 		explicit LLVector4(const LLVector3 &vec);			// Initializes LLVector4 to (vec, 1)
 		explicit LLVector4(const LLVector3 &vec, F32 w);	// Initializes LLVector4 to (vec, w)
+        explicit LLVector4(const LLSD &sd);
 		LLVector4(F32 x, F32 y, F32 z);		// Initializes LLVector4 to (x. y, z, 1)
 		LLVector4(F32 x, F32 y, F32 z, F32 w);
 
@@ -61,6 +65,15 @@ class LLVector4
 			return ret;
 		}
 
+        void setValue(const LLSD& sd)
+        {
+            mV[0] = sd[0].asReal();
+            mV[1] = sd[1].asReal();
+            mV[2] = sd[2].asReal();
+            mV[3] = sd[3].asReal();
+        }
+
+
 		inline BOOL isFinite() const;									// checks to see if all values of LLVector3 are finite
 
 		inline void	clear();		// Clears LLVector4 to (0, 0, 0, 1)
@@ -175,6 +188,22 @@ inline LLVector4::LLVector4(const F64 *vec)
 	mV[VW] = (F32) vec[VW];
 }
 
+inline LLVector4::LLVector4(const LLVector2 &vec)
+{
+    mV[VX] = vec[VX];
+    mV[VY] = vec[VY];
+    mV[VZ] = 0.f;
+    mV[VW] = 0.f;
+}
+
+inline LLVector4::LLVector4(const LLVector2 &vec, F32 z, F32 w)
+{
+    mV[VX] = vec[VX];
+    mV[VY] = vec[VY];
+    mV[VZ] = z;
+    mV[VW] = w;
+}
+
 inline LLVector4::LLVector4(const LLVector3 &vec)
 {
 	mV[VX] = vec.mV[VX];
@@ -191,6 +220,11 @@ inline LLVector4::LLVector4(const LLVector3 &vec, F32 w)
 	mV[VW] = w;
 }
 
+inline LLVector4::LLVector4(const LLSD &sd)
+{
+    setValue(sd);
+}
+
 
 inline BOOL LLVector4::isFinite() const
 {
@@ -500,6 +534,18 @@ inline F32		LLVector4::normVec(void)
 	return (mag);
 }
 
+// Because apparently some parts of the viewer use this for color info.
+inline const LLVector4 srgbVector4(const LLVector4 &a) {
+    LLVector4 srgbColor;
+
+    srgbColor.mV[0] = linearTosRGB(a.mV[0]);
+    srgbColor.mV[1] = linearTosRGB(a.mV[1]);
+    srgbColor.mV[2] = linearTosRGB(a.mV[2]);
+    srgbColor.mV[3] = a.mV[3];
+
+    return srgbColor;
+}
+
 
 #endif
 
diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp
index 596d57c7b7b838bdf3450fbd4d91ae9e9a47961a..18b2b124e1aad446ec86c68eecf30a1fca266257 100644
--- a/indra/llmessage/llassetstorage.cpp
+++ b/indra/llmessage/llassetstorage.cpp
@@ -62,6 +62,42 @@ const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-0
 
 const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000);       // microseconds
 
+namespace
+{
+    bool operator == (const LLAssetStorage::LLGetAssetCallback &lhs, const LLAssetStorage::LLGetAssetCallback &rhs)
+    {
+        auto fnPtrLhs = lhs.target<LLAssetStorage::LLGetAssetCallback>();
+        auto fnPtrRhs = rhs.target<LLAssetStorage::LLGetAssetCallback>();
+        if (fnPtrLhs && fnPtrRhs)
+            return (*fnPtrLhs == *fnPtrRhs);
+        else if (!fnPtrLhs && !fnPtrRhs)
+            return true;
+        return false;
+    }
+
+// Rider: This is the general case of the operator declared above. The code compares the callback 
+// passed into the LLAssetStorage functions to determine if there are duplicated requests for an 
+// asset.  Unfortunately std::function does not provide a direct way to compare two variables so 
+// we define the operator here. 
+// XCode is not very happy with the variadic temples in use below so we will just define the specific 
+// case of comparing two LLGetAssetCallback objects since that is all we really use.
+// 
+//     template<typename T, typename... U>
+//     bool operator == (const std::function<T(U...)> &a, const std::function <T(U...)> &b)
+//     {
+//         typedef T(fnType)(U...);
+// 
+//         auto fnPtrA = a.target<T(*)(U...)>();
+//         auto fnPtrB = b.target<T(*)(U...)>();
+//         if (fnPtrA && fnPtrB)
+//             return (*fnPtrA == *fnPtrB);
+//         else if (!fnPtrA && !fnPtrB)
+//             return true;
+//         return false;
+//     }
+
+}
+
 ///----------------------------------------------------------------------------
 /// LLAssetInfo
 ///----------------------------------------------------------------------------
@@ -160,7 +196,7 @@ void LLAssetInfo::setFromNameValue( const LLNameValue& nv )
 LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetType::EType type)
     : mUUID(uuid),
       mType(type),
-      mDownCallback(NULL),
+      mDownCallback(),
       mUserData(NULL),
       mHost(),
       mIsTemp(FALSE),
@@ -191,7 +227,7 @@ LLBaseDownloadRequest* LLBaseDownloadRequest::getCopy()
 
 LLAssetRequest::LLAssetRequest(const LLUUID &uuid, const LLAssetType::EType type)
     :   LLBaseDownloadRequest(uuid, type),
-        mUpCallback( NULL ),
+        mUpCallback(),
         mInfoCallback( NULL ),
         mIsLocal(FALSE),
         mIsUserWaiting(FALSE),
@@ -449,7 +485,7 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse
 // IW - uuid is passed by value to avoid side effects, please don't re-add &    
 void LLAssetStorage::getAssetData(const LLUUID uuid,
                                   LLAssetType::EType type, 
-                                  LLGetAssetCallback callback, 
+                                  LLAssetStorage::LLGetAssetCallback callback,
                                   void *user_data, 
                                   BOOL is_priority)
 {
@@ -496,7 +532,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
     BOOL exists = mVFS->getExists(uuid, type);
     LLVFile file(mVFS, uuid, type);
     U32 size = exists ? file.getSize() : 0;
-    
+
     if (size > 0)
     {
         // we've already got the file
@@ -1326,9 +1362,13 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
          iter != mPendingDownloads.end();  )
     {
         LLAssetRequest* tmp = *iter++;
+
+        //void(*const* cbptr)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat) 
+        auto cbptr = tmp->mDownCallback.target<void(*)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)>();
+
         if (type == tmp->getType() && 
             uuid == tmp->getUUID() &&
-            legacyGetDataCallback == tmp->mDownCallback &&
+            (cbptr && (*cbptr == legacyGetDataCallback)) &&
             callback == ((LLLegacyAssetRequest *)tmp->mUserData)->mDownCallback &&
             user_data == ((LLLegacyAssetRequest *)tmp->mUserData)->mUserData)
         {
diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h
index 33b88473b9d2e343515745bc842ef9c8a34d86bb..c799d8eefc5b147f6acfd55d8e7296ea0564f301 100644
--- a/indra/llmessage/llassetstorage.h
+++ b/indra/llmessage/llassetstorage.h
@@ -28,6 +28,7 @@
 #ifndef LL_LLASSETSTORAGE_H
 #define LL_LLASSETSTORAGE_H
 #include <string>
+#include <functional>
 
 #include "lluuid.h"
 #include "lltimer.h"
@@ -59,6 +60,14 @@ const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
 const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
 const int LL_ERR_PRICE_MISMATCH = -23018;
 
+// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
+// future project would be to convert these to C++ callables (std::function<>) so that 
+// we can use bind and remove the userData parameter.
+// 
+typedef std::function<void(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
+typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
+
+
 class LLAssetInfo
 {
 protected:
@@ -110,7 +119,8 @@ class LLBaseDownloadRequest
     LLAssetType::EType mType;
 
 public:
-    void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
+    LLGetAssetCallback mDownCallback;
+//    void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
 
     void	*mUserData;
     LLHost  mHost;
@@ -131,7 +141,8 @@ class LLAssetRequest : public LLBaseDownloadRequest
 
     virtual LLBaseDownloadRequest* getCopy();
 
-	void	(*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
+    LLStoreAssetCallback mUpCallback;
+//	void	(*mUpCallback)(const LLUUID&, void *, S32, LLExtStat);
 	void	(*mInfoCallback)(LLAssetInfo *, void *, S32);
 
 	BOOL	mIsLocal;
@@ -182,12 +193,7 @@ class LLEstateAssetRequest : public LLBaseDownloadRequest
 // Map of known bad assets
 typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
 
-// *TODO: these typedefs are passed into the VFS via a legacy C function pointer
-// future project would be to convert these to C++ callables (std::function<>) so that 
-// we can use bind and remove the userData parameter.
-// 
-typedef void (*LLGetAssetCallback)(LLVFS *vfs, const LLUUID &asset_id,
-                                   LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status);
+
 
 class LLAssetStorage
 {
@@ -195,7 +201,8 @@ class LLAssetStorage
 	// VFS member is public because static child methods need it :(
 	LLVFS *mVFS;
 	LLVFS *mStaticVFS;
-	typedef void (*LLStoreAssetCallback)(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status);
+    typedef ::LLStoreAssetCallback LLStoreAssetCallback;
+    typedef ::LLGetAssetCallback LLGetAssetCallback;
 
 	enum ERequestType
 	{
@@ -377,8 +384,8 @@ class LLAssetStorage
 	void _cleanupRequests(BOOL all, S32 error);
 	void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status);
 
-	virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type,
-								   void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+	virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
+//								   void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
 								   void *user_data, BOOL duplicate,
 								   BOOL is_priority) = 0;
 
@@ -424,7 +431,7 @@ class LLLegacyAssetRequest
 {
 public:
 	void	(*mDownCallback)(const char *, const LLUUID&, void *, S32, LLExtStat);
-	LLAssetStorage::LLStoreAssetCallback mUpCallback;
+	LLStoreAssetCallback mUpCallback;
 
 	void	*mUserData;
 };
diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp
index 8dbe2f84117c0f1eb2f3bf10b6d41e7e8b4aff30..8baa2e328b99d3157be5e25c185a72ceaf2086d7 100644
--- a/indra/llmessage/llcircuit.cpp
+++ b/indra/llmessage/llcircuit.cpp
@@ -543,7 +543,7 @@ void LLCircuitData::checkPeriodTime()
 		mBytesOutLastPeriod	= mBytesOutThisPeriod;
 		mBytesInThisPeriod	= S32Bytes(0);
 		mBytesOutThisPeriod	= S32Bytes(0);
-		mLastPeriodLength	= period_length;
+		mLastPeriodLength	= F32Seconds::convert(period_length);
 
 		mPeriodTime = mt_sec;
 	}
@@ -1378,8 +1378,8 @@ F32Milliseconds LLCircuitData::getPingInTransitTime()
 
 	if (mPingsInTransit)
 	{
-		time_since_ping_was_sent =  ((mPingsInTransit*mHeartbeatInterval - F32Seconds(1)) 
-			+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime));
+		time_since_ping_was_sent =  F32Milliseconds::convert(((mPingsInTransit*mHeartbeatInterval - F32Seconds(1)) 
+			+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime)));
 	}
 
 	return time_since_ping_was_sent;
diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp
index c40fe0d3891404d0cd1052d56658b50c4012fa0a..717ef10f70283c1b319cf57a2fa381277fa3fbeb 100644
--- a/indra/llmessage/lldispatcher.cpp
+++ b/indra/llmessage/lldispatcher.cpp
@@ -101,48 +101,70 @@ LLDispatchHandler* LLDispatcher::addHandler(
 
 // static
 bool LLDispatcher::unpackMessage(
-		LLMessageSystem* msg,
-		LLDispatcher::key_t& method,
-		LLUUID& invoice,
-		LLDispatcher::sparam_t& parameters)
+    LLMessageSystem* msg,
+    LLDispatcher::key_t& method,
+    LLUUID& invoice,
+    LLDispatcher::sparam_t& parameters)
 {
-	char buf[MAX_STRING];	/*Flawfinder: ignore*/
-	msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
-	msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
-	S32 size;
-	S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
-	for (S32 i = 0; i < count; ++i)
-	{
-		// we treat the SParam as binary data (since it might be an 
-		// LLUUID in compressed form which may have embedded \0's,)
-		size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
-		if (size >= 0)
-		{
-			msg->getBinaryDataFast(
-				_PREHASH_ParamList, _PREHASH_Parameter,
-				buf, size, i, MAX_STRING-1);
+    char buf[MAX_STRING];	/*Flawfinder: ignore*/
+    msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
+    msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
+    S32 size;
+    S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
+    for (S32 i = 0; i < count; ++i)
+    {
+        // we treat the SParam as binary data (since it might be an 
+        // LLUUID in compressed form which may have embedded \0's,)
+        size = msg->getSizeFast(_PREHASH_ParamList, i, _PREHASH_Parameter);
+        if (size >= 0)
+        {
+            msg->getBinaryDataFast(
+                _PREHASH_ParamList, _PREHASH_Parameter,
+                buf, size, i, MAX_STRING - 1);
 
-			// If the last byte of the data is 0x0, this is either a normally
-			// packed string, or a binary packed UUID (which for these messages
-			// are packed with a 17th byte 0x0).  Unpack into a std::string
-			// without the trailing \0, so "abc\0" becomes std::string("abc", 3)
-			// which matches const char* "abc".
-			if (size > 0
-				&& buf[size-1] == 0x0)
-			{
-				// special char*/size constructor because UUIDs may have embedded
-				// 0x0 bytes.
-				std::string binary_data(buf, size-1);
-				parameters.push_back(binary_data);
-			}
-			else
-			{
-				// This is either a NULL string, or a string that was packed 
-				// incorrectly as binary data, without the usual trailing '\0'.
-				std::string string_data(buf, size);
-				parameters.push_back(string_data);
-			}
-		}
-	}
-	return true;
+            // If the last byte of the data is 0x0, this is either a normally
+            // packed string, or a binary packed UUID (which for these messages
+            // are packed with a 17th byte 0x0).  Unpack into a std::string
+            // without the trailing \0, so "abc\0" becomes std::string("abc", 3)
+            // which matches const char* "abc".
+            if (size > 0
+                && buf[size - 1] == 0x0)
+            {
+                // special char*/size constructor because UUIDs may have embedded
+                // 0x0 bytes.
+                std::string binary_data(buf, size - 1);
+                parameters.push_back(binary_data);
+            }
+            else
+            {
+                // This is either a NULL string, or a string that was packed 
+                // incorrectly as binary data, without the usual trailing '\0'.
+                std::string string_data(buf, size);
+                parameters.push_back(string_data);
+            }
+        }
+    }
+    return true;
+}
+
+// static
+bool LLDispatcher::unpackLargeMessage(
+    LLMessageSystem* msg,
+    LLDispatcher::key_t& method,
+    LLUUID& invoice,
+    LLDispatcher::sparam_t& parameters)
+{
+    msg->getStringFast(_PREHASH_MethodData, _PREHASH_Method, method);
+    msg->getUUIDFast(_PREHASH_MethodData, _PREHASH_Invoice, invoice);
+    S32 count = msg->getNumberOfBlocksFast(_PREHASH_ParamList);
+    for (S32 i = 0; i < count; ++i)
+    {
+        // This method treats all Parameter List params as strings and unpacks
+        // them regardless of length. If there is binary data it is the callers 
+        // responsibility to decode it.
+        std::string param;
+        msg->getStringFast(_PREHASH_ParamList, _PREHASH_Parameter, param, i);
+        parameters.push_back(param);
+    }
+    return true;
 }
diff --git a/indra/llmessage/lldispatcher.h b/indra/llmessage/lldispatcher.h
index 9d1751f588cb646867fa743c45df031136092b11..43c63ac4dff8dc01146d3f85a72bf65f57154275 100644
--- a/indra/llmessage/lldispatcher.h
+++ b/indra/llmessage/lldispatcher.h
@@ -105,6 +105,12 @@ class LLDispatcher
 		LLUUID& invoice,
 		sparam_t& parameters);
 
+    static bool unpackLargeMessage(
+        LLMessageSystem* msg,
+        key_t& method,
+        LLUUID& invoice,
+        sparam_t& parameters);
+
 protected:
 	typedef std::map<key_t, LLDispatchHandler*> dispatch_map_t;
 	dispatch_map_t mHandlers;
diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h
index e1ccd333f152905e2cee37c731f8d4f87344e685..c13f39df9bda93e0cc263e72e1e3cc24252840d5 100644
--- a/indra/llmessage/llregionflags.h
+++ b/indra/llmessage/llregionflags.h
@@ -54,6 +54,9 @@ const U64 REGION_FLAGS_BLOCK_LAND_RESELL		= (1 << 7);
 
 // All content wiped once per night
 const U64 REGION_FLAGS_SANDBOX					= (1 << 8);
+
+const U64 REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE = (1 << 9);
+
 const U64 REGION_FLAGS_SKIP_COLLISIONS			= (1 << 12); // Pin all non agent rigid bodies
 const U64 REGION_FLAGS_SKIP_SCRIPTS				= (1 << 13);
 const U64 REGION_FLAGS_SKIP_PHYSICS				= (1 << 14); // Skip all physics
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index f8e11e324eff710a168df08a9a29e26df75763a2..fba5b7453d6c07b4165358c0b62bda622033f955 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -1376,7 +1376,9 @@ char const* const _PREHASH_RegionDenyAgeUnverified = LLMessageStringTable::getIn
 char const* const _PREHASH_AgeVerificationBlock = LLMessageStringTable::getInstance()->getString("AgeVerificationBlock");
 char const* const _PREHASH_RegionAllowAccessBlock = LLMessageStringTable::getInstance()->getString("RegionAllowAccessBlock");
 char const* const _PREHASH_RegionAllowAccessOverride = LLMessageStringTable::getInstance()->getString("RegionAllowAccessOverride");
-
+char const* const _PREHASH_ParcelEnvironmentBlock = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentBlock");
+char const* const _PREHASH_ParcelEnvironmentVersion = LLMessageStringTable::getInstance()->getString("ParcelEnvironmentVersion");
+char const* const _PREHASH_RegionAllowEnvironmentOverride = LLMessageStringTable::getInstance()->getString("RegionAllowEnvironmentOverride");
 char const* const _PREHASH_UCoord = LLMessageStringTable::getInstance()->getString("UCoord");
 char const* const _PREHASH_VCoord = LLMessageStringTable::getInstance()->getString("VCoord");
 char const* const _PREHASH_FaceIndex = LLMessageStringTable::getInstance()->getString("FaceIndex");
@@ -1392,3 +1394,4 @@ char const* const _PREHASH_AppearanceHover = LLMessageStringTable::getInstance()
 char const* const _PREHASH_HoverHeight = LLMessageStringTable::getInstance()->getString("HoverHeight");
 char const* const _PREHASH_Experience = LLMessageStringTable::getInstance()->getString("Experience");
 char const* const _PREHASH_ExperienceID = LLMessageStringTable::getInstance()->getString("ExperienceID");
+char const* const _PREHASH_LargeGenericMessage = LLMessageStringTable::getInstance()->getString("LargeGenericMessage");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 334236fb25b4c89795dee2b22b7c7ba531a07f38..4f72c01ddf2dc9afbe28e8eb29841066fbb2555f 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -1376,6 +1376,9 @@ extern char const* const _PREHASH_RegionDenyAgeUnverified;
 extern char const* const _PREHASH_AgeVerificationBlock;
 extern char const* const _PREHASH_RegionAllowAccessBlock;
 extern char const* const _PREHASH_RegionAllowAccessOverride;
+extern char const* const _PREHASH_ParcelEnvironmentBlock;
+extern char const* const _PREHASH_ParcelEnvironmentVersion;
+extern char const* const _PREHASH_RegionAllowEnvironmentOverride;
 extern char const* const _PREHASH_UCoord;
 extern char const* const _PREHASH_VCoord;
 extern char const* const _PREHASH_FaceIndex;
@@ -1391,4 +1394,6 @@ extern char const* const _PREHASH_AppearanceHover;
 extern char const* const _PREHASH_HoverHeight;
 extern char const* const _PREHASH_Experience;
 extern char const* const _PREHASH_ExperienceID;
+extern char const* const _PREHASH_LargeGenericMessage;
+
 #endif
diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp
index 8fb3054eacec737720154e1c58190d45d8c58074..c5304d2ccf69de9a7de96d5eaf341b634868f5be 100644
--- a/indra/llplugin/llpluginprocesschild.cpp
+++ b/indra/llplugin/llpluginprocesschild.cpp
@@ -258,7 +258,7 @@ void LLPluginProcessChild::sleep(F64 seconds)
 	}
 	else
 	{
-		ms_sleep((int)(seconds * 1000.0f));
+    ms_sleep((int)(seconds * 1000.0f));
 	}
 }
 
diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp
index 8f75d89e5a797b17c6b1a780cc4cf2a93c75be8c..139f48fef8055db26607f81ebd4fa1f02338a563 100644
--- a/indra/llprimitive/lldaeloader.cpp
+++ b/indra/llprimitive/lldaeloader.cpp
@@ -1784,7 +1784,7 @@ void LLDAELoader::extractTranslationViaElement( daeElement* pTranslateElement, L
 {
 	if ( pTranslateElement )
 	{
-		domTranslate* pTranslateChild = dynamic_cast<domTranslate*>( pTranslateElement );
+		domTranslate* pTranslateChild = static_cast<domTranslate*>( pTranslateElement );
 		domFloat3 translateChild = pTranslateChild->getValue();
 		LLVector3 singleJointTranslation( translateChild[0], translateChild[1], translateChild[2] );
 		transform.setTranslation( singleJointTranslation );
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index bc5dd62f457f69e6c25d8b25fe043aa62e3b5d10..53b83a40d73305d2616fe484dc065ea03ffbf797 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -1659,7 +1659,7 @@ BOOL LLLightParams::unpack(LLDataPacker &dp)
 {
 	LLColor4U color;
 	dp.unpackColor4U(color, "color");
-	setColor(LLColor4(color));
+	setLinearColor(LLColor4(color));
 
 	F32 radius;
 	dp.unpackF32(radius, "radius");
@@ -1707,7 +1707,7 @@ LLSD LLLightParams::asLLSD() const
 {
 	LLSD sd;
 	
-	sd["color"] = ll_sd_from_color4(getColor());
+	sd["color"] = ll_sd_from_color4(getLinearColor());
 	sd["radius"] = getRadius();
 	sd["falloff"] = getFalloff();
 	sd["cutoff"] = getCutoff();
@@ -1721,7 +1721,7 @@ bool LLLightParams::fromLLSD(LLSD& sd)
 	w = "color";
 	if (sd.has(w))
 	{
-		setColor( ll_color4_from_sd(sd["color"]) );
+		setLinearColor( ll_color4_from_sd(sd["color"]) );
 	} else goto fail;
 	w = "radius";
 	if (sd.has(w))
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 6fd433c3370a4e54890825c26ad2bd6cf85a45b3..b1f8112223053cd708261abbe381733e44a9e29c 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -131,8 +131,8 @@ extern const F32 LIGHT_MAX_CUTOFF;
 
 class LLLightParams : public LLNetworkData
 {
-protected:
-	LLColor4 mColor; // alpha = intensity
+private:
+	LLColor4 mColor; // linear color (not gamma corrected), alpha = intensity
 	F32 mRadius;
 	F32 mFalloff;
 	F32 mCutoff;
@@ -149,13 +149,22 @@ class LLLightParams : public LLNetworkData
 	operator LLSD() const { return asLLSD(); }
 	bool fromLLSD(LLSD& sd);
 
-	
-	void setColor(const LLColor4& color)	{ mColor = color; mColor.clamp(); }
+    // set the color by gamma corrected color value
+    //  color - gamma corrected color value (directly taken from an on-screen color swatch)
+    void setSRGBColor(const LLColor4& color) { setLinearColor(linearColor4(color)); }
+
+    // set the color by linear color value
+    //  color - linear color value (value as it appears in shaders)
+    void setLinearColor(const LLColor4& color)	{ mColor = color; mColor.clamp(); }
 	void setRadius(F32 radius)				{ mRadius = llclamp(radius, LIGHT_MIN_RADIUS, LIGHT_MAX_RADIUS); }
 	void setFalloff(F32 falloff)			{ mFalloff = llclamp(falloff, LIGHT_MIN_FALLOFF, LIGHT_MAX_FALLOFF); }
 	void setCutoff(F32 cutoff)				{ mCutoff = llclamp(cutoff, LIGHT_MIN_CUTOFF, LIGHT_MAX_CUTOFF); }
 
-	LLColor4 getColor() const				{ return mColor; }
+    // get the linear space color of this light.  This value can be fed directly to shaders
+    LLColor4 getLinearColor() const				{ return mColor; }
+    // get the sRGB (gamma corrected) color of this light, this is the value that should be displayed in the UI
+    LLColor4 getSRGBColor() const			{ return srgbColor4(mColor); }
+    
 	F32 getRadius() const					{ return mRadius; }
 	F32 getFalloff() const					{ return mFalloff; }
 	F32 getCutoff() const					{ return mCutoff; }
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index 07a0d8c402d0906338d9ee87dfc23974211dae83..47e7ad915b9b54f5ca40e70fb66fff8cc6a7c3d4 100644
--- a/indra/llrender/CMakeLists.txt
+++ b/indra/llrender/CMakeLists.txt
@@ -31,6 +31,7 @@ include_directories(SYSTEM
     )
 
 set(llrender_SOURCE_FILES
+    llatmosphere.cpp
     llcubemap.cpp
     llfontbitmapcache.cpp
     llfontfreetype.cpp
@@ -57,6 +58,7 @@ set(llrender_SOURCE_FILES
 set(llrender_HEADER_FILES
     CMakeLists.txt
 
+    llatmosphere.h
     llcubemap.h
     llfontgl.h
     llfontfreetype.h
@@ -78,6 +80,7 @@ set(llrender_HEADER_FILES
     llshadermgr.h
     lltexture.h
     lluiimage.h
+    lluiimage.inl
     llvertexbuffer.h
     llglcommonfunc.h
     )
diff --git a/indra/llrender/llatmosphere.cpp b/indra/llrender/llatmosphere.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ffc17c89f866e690c7a097c247038bef74d83739
--- /dev/null
+++ b/indra/llrender/llatmosphere.cpp
@@ -0,0 +1,290 @@
+/** 
+ * @file llatmosphere.cpp
+ * @brief LLAtmosphere integration impl
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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$
+ */
+
+#include "linden_common.h"
+
+#include "llatmosphere.h"
+#include "llfasttimer.h"
+#include "llsys.h"
+#include "llglheaders.h"
+#include "llrender.h"
+#include "llshadermgr.h"
+#include "llglslshader.h"
+
+LLAtmosphere* gAtmosphere = nullptr;
+
+// Values from "Reference Solar Spectral Irradiance: ASTM G-173", ETR column
+// (see http://rredc.nrel.gov/solar/spectra/am1.5/ASTMG173/ASTMG173.html),
+// summed and averaged in each bin (e.g. the value for 360nm is the average
+// of the ASTM G-173 values for all wavelengths between 360 and 370nm).
+// Values in W.m^-2.
+const int kLambdaMin = 360;
+const int kLambdaMax = 830;
+const double kSolarIrradiance[48] = {
+    1.11776, 1.14259, 1.01249, 1.14716, 1.72765, 1.73054, 1.6887, 1.61253,
+    1.91198, 2.03474, 2.02042, 2.02212, 1.93377, 1.95809, 1.91686, 1.8298,
+    1.8685, 1.8931, 1.85149, 1.8504, 1.8341, 1.8345, 1.8147, 1.78158, 1.7533,
+    1.6965, 1.68194, 1.64654, 1.6048, 1.52143, 1.55622, 1.5113, 1.474, 1.4482,
+    1.41018, 1.36775, 1.34188, 1.31429, 1.28303, 1.26758, 1.2367, 1.2082,
+    1.18737, 1.14683, 1.12362, 1.1058, 1.07124, 1.04992
+};
+
+// Values from http://www.iup.uni-bremen.de/gruppen/molspec/databases/
+// referencespectra/o3spectra2011/index.html for 233K, summed and averaged in
+// each bin (e.g. the value for 360nm is the average of the original values
+// for all wavelengths between 360 and 370nm). Values in m^2.
+const double kOzoneCrossSection[48] = {
+    1.18e-27, 2.182e-28, 2.818e-28, 6.636e-28, 1.527e-27, 2.763e-27, 5.52e-27,
+    8.451e-27, 1.582e-26, 2.316e-26, 3.669e-26, 4.924e-26, 7.752e-26, 9.016e-26,
+    1.48e-25, 1.602e-25, 2.139e-25, 2.755e-25, 3.091e-25, 3.5e-25, 4.266e-25,
+    4.672e-25, 4.398e-25, 4.701e-25, 5.019e-25, 4.305e-25, 3.74e-25, 3.215e-25,
+    2.662e-25, 2.238e-25, 1.852e-25, 1.473e-25, 1.209e-25, 9.423e-26, 7.455e-26,
+    6.566e-26, 5.105e-26, 4.15e-26, 4.228e-26, 3.237e-26, 2.451e-26, 2.801e-26,
+    2.534e-26, 1.624e-26, 1.465e-26, 2.078e-26, 1.383e-26, 7.105e-27
+};
+
+// From https://en.wikipedia.org/wiki/Dobson_unit, in molecules.m^-2.
+const double kDobsonUnit = 2.687e20;
+// Maximum number density of ozone molecules, in m^-3 (computed so at to get
+// 300 Dobson units of ozone - for this we divide 300 DU by the integral of
+// the ozone density profile defined below, which is equal to 15km).
+const double kMaxOzoneNumberDensity = 300.0 * kDobsonUnit / 15000.0;
+const double kRayleigh = 1.24062e-6;
+const double kRayleighScaleHeight = 8000.0;
+const double kMieScaleHeight = 1200.0;
+const double kMieAngstromAlpha = 0.0;
+const double kMieAngstromBeta = 5.328e-3;
+const double kMieSingleScatteringAlbedo = 0.9;
+const double kGroundAlbedo = 0.1;
+
+AtmosphericModelSettings::AtmosphericModelSettings()
+    : m_skyBottomRadius(6360.0f)
+    , m_skyTopRadius(6420.0f)
+    , m_sunArcRadians(0.00045f)
+    , m_mieAnisotropy(0.8f)
+{
+    DensityLayer rayleigh_density(0.0, 1.0, -1.0 / kRayleighScaleHeight, 0.0, 0.0);
+    DensityLayer mie_density(0.0, 1.0, -1.0 / kMieScaleHeight, 0.0, 0.0);
+
+    m_rayleighProfile.push_back(rayleigh_density);
+    m_mieProfile.push_back(mie_density);
+
+    // Density profile increasing linearly from 0 to 1 between 10 and 25km, and
+    // decreasing linearly from 1 to 0 between 25 and 40km. This is an approximate
+    // profile from http://www.kln.ac.lk/science/Chemistry/Teaching_Resources/
+    // Documents/Introduction%20to%20atmospheric%20chemistry.pdf (page 10).
+    m_absorptionProfile.push_back(DensityLayer(25000.0, 0.0, 0.0, 1.0 / 15000.0, -2.0 / 3.0));
+    m_absorptionProfile.push_back(DensityLayer(0.0, 0.0, 0.0, -1.0 / 15000.0, 8.0 / 3.0));
+}
+
+AtmosphericModelSettings::AtmosphericModelSettings(
+    DensityProfile& rayleighProfile,
+    DensityProfile& mieProfile,
+    DensityProfile& absorptionProfile)
+: m_skyBottomRadius(6360.0f)
+, m_skyTopRadius(6420.0f)
+, m_rayleighProfile(rayleighProfile)
+, m_mieProfile(mieProfile)
+, m_absorptionProfile(absorptionProfile)
+, m_sunArcRadians(0.00045f)
+, m_mieAnisotropy(0.8f)
+{
+}
+
+AtmosphericModelSettings::AtmosphericModelSettings(
+    F32             skyBottomRadius,
+    F32             skyTopRadius,
+    DensityProfile& rayleighProfile,
+    DensityProfile& mieProfile,
+    DensityProfile& absorptionProfile,
+    F32             sunArcRadians,
+    F32             mieAniso)
+: m_skyBottomRadius(skyBottomRadius)
+, m_skyTopRadius(skyTopRadius)
+, m_rayleighProfile(rayleighProfile)
+, m_mieProfile(mieProfile)
+, m_absorptionProfile(absorptionProfile)
+, m_sunArcRadians(sunArcRadians)
+, m_mieAnisotropy(mieAniso)
+{
+}
+
+bool AtmosphericModelSettings::operator==(const AtmosphericModelSettings& rhs) const
+{
+    if (m_skyBottomRadius != rhs.m_skyBottomRadius)
+    {
+        return false;
+    }
+
+    if (m_skyTopRadius != rhs.m_skyTopRadius)
+    {
+        return false;
+    }
+
+    if (m_sunArcRadians != rhs.m_sunArcRadians)
+    {
+        return false;
+    }
+
+    if (m_mieAnisotropy != rhs.m_mieAnisotropy)
+    {
+        return false;
+    }
+
+    if (m_rayleighProfile != rhs.m_rayleighProfile)
+    {
+        return false;
+    }
+
+    if (m_mieProfile != rhs.m_mieProfile)
+    {
+        return false;
+    }
+
+    if (m_absorptionProfile != rhs.m_absorptionProfile)
+    {
+        return false;
+    }
+
+    return true;
+}
+
+void LLAtmosphere::initClass()
+{
+    if (!gAtmosphere)
+    { 
+        gAtmosphere = new LLAtmosphere; 
+    }
+}
+
+void LLAtmosphere::cleanupClass()
+{
+    if(gAtmosphere)
+    {
+        delete gAtmosphere;
+    }
+    gAtmosphere = NULL;
+}
+
+LLAtmosphere::LLAtmosphere()
+{
+    for (int l = kLambdaMin; l <= kLambdaMax; l += 10)
+    {
+        double lambda = static_cast<double>(l) * 1e-3;  // micro-meters
+        double mie    = kMieAngstromBeta / kMieScaleHeight * pow(lambda, -kMieAngstromAlpha);
+        m_wavelengths.push_back(l);
+        m_solar_irradiance.push_back(kSolarIrradiance[(l - kLambdaMin) / 10]);
+        m_rayleigh_scattering.push_back(kRayleigh * pow(lambda, -4));
+        m_mie_scattering.push_back(mie * kMieSingleScatteringAlbedo);
+        m_mie_extinction.push_back(mie);
+        m_absorption_extinction.push_back(kMaxOzoneNumberDensity * kOzoneCrossSection[(l - kLambdaMin) / 10]);
+        m_ground_albedo.push_back(kGroundAlbedo);
+    }
+
+    AtmosphericModelSettings defaults;
+    configureAtmosphericModel(defaults);
+}
+
+LLAtmosphere::~LLAtmosphere()
+{
+    // Cease referencing textures from atmosphere::model from our LLGLTextures wrappers for same.
+    if (m_transmittance)
+    {
+        m_transmittance->setTexName(0);
+    }
+
+    if (m_scattering)
+    {
+        m_scattering->setTexName(0);
+    }
+
+    if (m_mie_scatter_texture)
+    {
+        m_mie_scatter_texture->setTexName(0);
+    }
+}
+
+bool LLAtmosphere::configureAtmosphericModel(AtmosphericModelSettings& settings)
+{
+    // TBD
+    return true;
+}
+
+LLGLTexture* LLAtmosphere::getTransmittance()
+{
+    if (!m_transmittance)
+    {
+        m_transmittance  = new LLGLTexture;
+        m_transmittance->generateGLTexture();
+        m_transmittance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
+        m_transmittance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
+        m_transmittance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+        m_transmittance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
+    }
+    return m_transmittance;
+}
+
+LLGLTexture* LLAtmosphere::getScattering()
+{
+    if (!m_scattering)
+    {
+        m_scattering = new LLGLTexture;
+        m_scattering->generateGLTexture();
+        m_scattering->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
+        m_scattering->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
+        m_scattering->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+        m_scattering->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
+    }
+    return m_scattering;
+}
+
+LLGLTexture* LLAtmosphere::getMieScattering()
+{
+    if (!m_mie_scatter_texture)
+    {
+        m_mie_scatter_texture = new LLGLTexture;
+        m_mie_scatter_texture->generateGLTexture();
+        m_mie_scatter_texture->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
+        m_mie_scatter_texture->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
+        m_mie_scatter_texture->setExplicitFormat(GL_RGB16F_ARB, GL_RGB, GL_FLOAT);
+        m_mie_scatter_texture->setTarget(GL_TEXTURE_3D, LLTexUnit::TT_TEXTURE_3D);
+    }
+    return m_mie_scatter_texture;
+}
+
+LLGLTexture* LLAtmosphere::getIlluminance()
+{
+    if (!m_illuminance)
+    {
+        m_illuminance = new LLGLTexture;
+        m_illuminance->generateGLTexture();
+        m_illuminance->setAddressMode(LLTexUnit::eTextureAddressMode::TAM_CLAMP);
+        m_illuminance->setFilteringOption(LLTexUnit::eTextureFilterOptions::TFO_BILINEAR);
+        m_illuminance->setExplicitFormat(GL_RGB32F_ARB, GL_RGB, GL_FLOAT);
+        m_illuminance->setTarget(GL_TEXTURE_2D, LLTexUnit::TT_TEXTURE);
+    }
+    return m_illuminance;
+}
diff --git a/indra/llrender/llatmosphere.h b/indra/llrender/llatmosphere.h
new file mode 100644
index 0000000000000000000000000000000000000000..572365d864ee4cb36abc53e835ae82948f3fc51f
--- /dev/null
+++ b/indra/llrender/llatmosphere.h
@@ -0,0 +1,173 @@
+/** 
+ * @file llatmosphere.h
+ * @brief LLAtmosphere class
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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$
+ */
+
+#ifndef LL_ATMOSPHERE_H
+#define LL_ATMOSPHERE_H
+
+#include "llglheaders.h"
+#include "llgltexture.h"
+
+// An atmosphere layer of width 'width' (in m), and whose density is defined as
+//   'exp_term' * exp('exp_scale' * h) + 'linear_term' * h + 'constant_term',
+// clamped to [0,1], and where h is the altitude (in m). 'exp_term' and
+// 'constant_term' are unitless, while 'exp_scale' and 'linear_term' are in
+// m^-1.
+class DensityLayer {
+ public:
+  DensityLayer()
+    : width(0.0f)
+    , exp_term(0.0f)
+    , exp_scale(0.0f)
+    , linear_term(0.0f)
+    , constant_term(0.0f)
+  {
+  }
+
+  DensityLayer(float width, float exp_term, float exp_scale, float linear_term, float constant_term)
+    : width(width)
+    , exp_term(exp_term)
+    , exp_scale(exp_scale)
+    , linear_term(linear_term)
+    , constant_term(constant_term)
+  {
+  }
+
+  bool operator==(const DensityLayer& rhs) const
+  {
+      if (width != rhs.width)
+      {
+         return false;
+      }
+
+      if (exp_term != rhs.exp_term)
+      {
+         return false;
+      }
+
+      if (exp_scale != rhs.exp_scale)
+      {
+         return false;
+      }
+
+      if (linear_term != rhs.linear_term)
+      {
+         return false;
+      }
+
+      if (constant_term != rhs.constant_term)
+      {
+         return false;
+      }
+
+      return true;
+  }
+
+  float width         = 1024.0f;
+  float exp_term      = 1.0f;
+  float exp_scale     = 1.0f;
+  float linear_term   = 1.0f;
+  float constant_term = 0.0f;
+};
+
+typedef std::vector<DensityLayer> DensityProfile;
+
+class AtmosphericModelSettings
+{
+public:
+    AtmosphericModelSettings();
+
+    AtmosphericModelSettings(
+        DensityProfile& rayleighProfile,
+        DensityProfile& mieProfile,
+        DensityProfile& absorptionProfile);
+
+    AtmosphericModelSettings(
+        F32             skyBottomRadius,
+        F32             skyTopRadius,
+        DensityProfile& rayleighProfile,
+        DensityProfile& mieProfile,
+        DensityProfile& absorptionProfile,
+        F32             sunArcRadians,
+        F32             mieAniso);
+
+    bool operator==(const AtmosphericModelSettings& rhs) const;
+
+    F32             m_skyBottomRadius;
+    F32             m_skyTopRadius;
+    DensityProfile  m_rayleighProfile;
+    DensityProfile  m_mieProfile;
+    DensityProfile  m_absorptionProfile;
+    F32             m_sunArcRadians;
+    F32             m_mieAnisotropy;
+};
+
+class LLAtmosphere
+{
+public:
+     LLAtmosphere();
+    ~LLAtmosphere();
+
+    static void initClass();
+    static void cleanupClass();
+
+    const LLAtmosphere& operator=(const LLAtmosphere& rhs)
+    {
+        LL_ERRS() << "Illegal operation!" << LL_ENDL;
+        return *this;
+    }
+
+    LLGLTexture* getTransmittance();
+    LLGLTexture* getScattering();
+    LLGLTexture* getMieScattering();
+    LLGLTexture* getIlluminance();
+
+    bool configureAtmosphericModel(AtmosphericModelSettings& settings);
+
+protected:    
+    LLAtmosphere(const LLAtmosphere& rhs)
+    {
+        *this = rhs;
+    }
+
+    LLPointer<LLGLTexture> m_transmittance;
+    LLPointer<LLGLTexture> m_scattering;
+    LLPointer<LLGLTexture> m_mie_scatter_texture;
+    LLPointer<LLGLTexture> m_illuminance;
+
+    std::vector<double> m_wavelengths;
+    std::vector<double> m_solar_irradiance;
+    std::vector<double> m_rayleigh_scattering;
+    std::vector<double> m_mie_scattering;
+    std::vector<double> m_mie_extinction;
+    std::vector<double> m_absorption_extinction;
+    std::vector<double> m_ground_albedo;
+
+    AtmosphericModelSettings m_settings;
+};
+
+extern LLAtmosphere* gAtmosphere;
+
+#endif // LL_ATMOSPHERE_H
diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp
index af4e3fdda02f57d7cff070ef4bac33a1a1544f90..5947bca670094cec0f160c7fb767c60fbdbe268f 100644
--- a/indra/llrender/llcubemap.cpp
+++ b/indra/llrender/llcubemap.cpp
@@ -43,20 +43,13 @@
 const F32 epsilon = 1e-7f;
 const U16 RESOLUTION = 64;
 
-#if LL_DARWIN
-// mipmap generation on cubemap textures seems to be broken on the Mac for at least some cards.
-// Since the cubemap is small (64x64 per face) and doesn't have any fine detail, turning off mipmaps is a usable workaround.
-const BOOL use_cube_mipmaps = FALSE;
-#else
-const BOOL use_cube_mipmaps = FALSE;  //current build works best without cube mipmaps
-#endif
-
 bool LLCubeMap::sUseCubeMaps = true;
 
-LLCubeMap::LLCubeMap()
+LLCubeMap::LLCubeMap(bool init_as_srgb)
 	: mTextureStage(0),
 	  mTextureCoordStage(0),
-	  mMatrixStage(0)
+	  mMatrixStage(0),
+	  mIssRGB(init_as_srgb)
 {
 	mTargets[0] = GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB;
 	mTargets[1] = GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB;
@@ -82,12 +75,17 @@ void LLCubeMap::initGL()
 			U32 texname = 0;
 			
 			LLImageGL::generateTextures(1, &texname);
-
+			
 			for (int i = 0; i < 6; i++)
 			{
-				mImages[i] = new LLImageGL(64, 64, 4, (use_cube_mipmaps? TRUE : FALSE));
+				mImages[i] = new LLImageGL(RESOLUTION, RESOLUTION, 4, FALSE);
+            #if USE_SRGB_DECODE
+                if (mIssRGB) {
+                    mImages[i]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
+                }
+            #endif
 				mImages[i]->setTarget(mTargets[i], LLTexUnit::TT_CUBE_MAP);
-				mRawImages[i] = new LLImageRaw(64, 64, 4);
+				mRawImages[i] = new LLImageRaw(RESOLUTION, RESOLUTION, 4);
 				mImages[i]->createGLTexture(0, mRawImages[i], texname);
 				
 				gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_CUBE_MAP, texname); 
@@ -154,7 +152,7 @@ void LLCubeMap::initGLData()
 {
 	for (int i = 0; i < 6; i++)
 	{
-		mImages[i]->setSubImage(mRawImages[i], 0, 0, 64, 64);
+		mImages[i]->setSubImage(mRawImages[i], 0, 0, RESOLUTION, RESOLUTION);
 	}
 }
 
@@ -484,7 +482,7 @@ void LLCubeMap::paintIn(LLVector3 dir[4], const LLColor4U& col)
 						td[offset + cc] = U8((td[offset + cc] + col.mV[cc]) * 0.5);
 				}
 			}
-		mImages[side]->setSubImage(mRawImages[side], 0, 0, 64, 64);
+		mImages[side]->setSubImage(mRawImages[side], 0, 0, RESOLUTION, RESOLUTION);
 	}
 }
 
diff --git a/indra/llrender/llcubemap.h b/indra/llrender/llcubemap.h
index ee2c41e02694cfc0a69196bfc0b231bfef8145f3..95b6d1209913d04b3353c10c8fd6f312e9dbeabf 100644
--- a/indra/llrender/llcubemap.h
+++ b/indra/llrender/llcubemap.h
@@ -36,8 +36,9 @@ class LLVector3;
 // Environment map hack!
 class LLCubeMap : public LLRefCount
 {
+	bool mIssRGB;
 public:
-	LLCubeMap();
+	LLCubeMap(bool init_as_srgb);
 	void init(const std::vector<LLPointer<LLImageRaw> >& rawimages);
 	void initGL();
 	void initRawData(const std::vector<LLPointer<LLImageRaw> >& rawimages);
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c0f0cec80b2c5e9fc6d84a7d6b0113f980d7784e..c01c15391de812273bea8f96c7ebcd03f19dbaa1 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -36,6 +36,7 @@
 #include "llsys.h"
 
 #include "llgl.h"
+#include "llglstates.h"
 #include "llrender.h"
 
 #include "llerror.h"
@@ -998,6 +999,12 @@ void LLGLManager::initExtensions()
 	mHassRGBFramebuffer = ExtensionExists("GL_EXT_framebuffer_sRGB", gGLHExts.mSysExts);
 #endif
 	
+#ifdef GL_EXT_texture_sRGB_decode
+    mHasTexturesRGBDecode = ExtensionExists("GL_EXT_texture_sRGB_decode", gGLHExts.mSysExts);
+#else
+    mHasTexturesRGBDecode = ExtensionExists("GL_ARB_texture_sRGB_decode", gGLHExts.mSysExts);
+#endif
+
 	mHasMipMapGeneration = mHasFramebufferObject || mGLVersion >= 1.4f;
 
 	mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
@@ -2044,7 +2051,8 @@ LLGLState::LLGLState(LLGLenum state, S32 enabled) :
 	if (mState)
 	{
 		mWasEnabled = sStateMap[state];
-		llassert(mWasEnabled == glIsEnabled(state));
+        // we can't actually assert on this as queued changes to state are not reflected by glIsEnabled
+		//llassert(mWasEnabled == glIsEnabled(state));
 		setEnabled(enabled);
 		stop_glerror();
 	}
@@ -2267,6 +2275,17 @@ LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& mode
 	}
 }
 
+void LLGLUserClipPlane::disable()
+{
+    if (mApply)
+	{
+		gGL.matrixMode(LLRender::MM_PROJECTION);
+		gGL.popMatrix();
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+	}
+    mApply = false;
+}
+
 void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
 {
 	glh::matrix4f& P = mProjection;
@@ -2295,12 +2314,7 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
 
 LLGLUserClipPlane::~LLGLUserClipPlane()
 {
-	if (mApply)
-	{
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.popMatrix();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-	}
+	disable();
 }
 
 LLGLNamePool::LLGLNamePool()
@@ -2478,27 +2492,45 @@ void LLGLDepthTest::checkState()
 	}
 }
 
-LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f P, U32 layer)
+LLGLSquashToFarClip::LLGLSquashToFarClip()
+{
+    glh::matrix4f proj = get_current_projection();
+    setProjectionMatrix(proj, 0);
+}
+
+LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer)
+{
+    setProjectionMatrix(P, layer);
+}
+
+
+void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer)
 {
 
 	F32 depth = 0.99999f - 0.0001f * layer;
 
 	for (U32 i = 0; i < 4; i++)
 	{
-		P.element(2, i) = P.element(3, i) * depth;
+		projection.element(2, i) = projection.element(3, i) * depth;
 	}
 
+    LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
+
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.pushMatrix();
-	gGL.loadMatrix(P.m);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.loadMatrix(projection.m);
+
+	gGL.matrixMode(last_matrix_mode);
 }
 
 LLGLSquashToFarClip::~LLGLSquashToFarClip()
 {
+    LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
+
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+	gGL.matrixMode(last_matrix_mode);
 }
 
 
@@ -2561,6 +2593,43 @@ void LLGLSyncFence::wait()
 #endif
 }
 
+LLGLSPipelineSkyBox::LLGLSPipelineSkyBox()
+: mAlphaTest(GL_ALPHA_TEST)
+, mCullFace(GL_CULL_FACE)
+, mSquashClip()
+{ 
+    if (!LLGLSLShader::sNoFixedFunction)
+    {
+        glDisable(GL_LIGHTING);
+        glDisable(GL_FOG);
+        glDisable(GL_CLIP_PLANE0);
+    }
+}
+
+LLGLSPipelineSkyBox::~LLGLSPipelineSkyBox()
+{
+    if (!LLGLSLShader::sNoFixedFunction)
+    {
+        glEnable(GL_LIGHTING);
+        glEnable(GL_FOG);
+        glEnable(GL_CLIP_PLANE0);
+    }
+}
+
+LLGLSPipelineDepthTestSkyBox::LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write)
+: LLGLSPipelineSkyBox()
+, mDepth(depth_test ? GL_TRUE : GL_FALSE, depth_write ? GL_TRUE : GL_FALSE, GL_LEQUAL)
+{
+
+}
+
+LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write)
+: LLGLSPipelineDepthTestSkyBox(depth_test, depth_write)    
+, mBlend(GL_BLEND)
+{ 
+    gGL.setSceneBlendType(LLRender::BT_ALPHA);
+}
+
 #if LL_WINDOWS
 // Expose desired use of high-performance graphics processor to Optimus driver
 extern "C" 
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 4c4302d05ba3e101c2cc6081ebe69b6fc428648a..a7faea7d3315396f5e875e192fa0364f7ae99b90 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -118,6 +118,7 @@ class LLGLManager
 	BOOL mHasDebugOutput;
 	BOOL mHassRGBTexture;
 	BOOL mHassRGBFramebuffer;
+    BOOL mHasTexturesRGBDecode;
 
 	// Vendor-specific extensions
 	BOOL mIsATI;
@@ -348,6 +349,7 @@ class LLGLUserClipPlane
 	~LLGLUserClipPlane();
 
 	void setPlane(F32 a, F32 b, F32 c, F32 d);
+    void disable();
 
 private:
 	bool mApply;
@@ -360,14 +362,17 @@ class LLGLUserClipPlane
   Modify and load projection matrix to push depth values to far clip plane.
 
   Restores projection matrix on destruction.
-  GL_MODELVIEW_MATRIX is active whenever program execution
-  leaves this class.
+  Saves/restores matrix mode around projection manipulation.
   Does not stack.
 */
 class LLGLSquashToFarClip
 {
 public:
-	LLGLSquashToFarClip(glh::matrix4f projection, U32 layer = 0);
+    LLGLSquashToFarClip();
+	LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0);
+
+    void setProjectionMatrix(glh::matrix4f& projection, U32 layer);
+
 	~LLGLSquashToFarClip();
 };
 
diff --git a/indra/llrender/llglcommonfunc.h b/indra/llrender/llglcommonfunc.h
index f1f8ff7bc40300c9ec33f3d106bdb2a98dc96ac1..e6d37557557a53a385713480f396a11e102b8d9d 100644
--- a/indra/llrender/llglcommonfunc.h
+++ b/indra/llrender/llglcommonfunc.h
@@ -1,5 +1,5 @@
 /**
-* @file llphoenixfunc.h
+* @file llglcommonfunc.h
 * @brief File include common opengl code snippets
 *
 * $LicenseInfo:firstyear=2003&license=viewerlgpl$
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 141ed512600bb186111ba8d1551fd6faa3ae2a77..384e5bf99fe3e87c45134d3e7771871ef4884dcf 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -37,12 +37,6 @@
 #include "OpenGL/OpenGL.h"
 #endif
 
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
-#else
-#define UNIFORM_ERRS LL_ERRS("Shader")
-#endif
-
 // Lots of STL stuff in here, using namespace std to keep things more readable
 using std::vector;
 using std::pair;
@@ -84,6 +78,12 @@ LLShaderFeatures::LLShaderFeatures()
     , hasObjectSkinning(false)
     , hasAtmospherics(false)
     , hasGamma(false)
+    , hasSrgb(false)
+    , encodesNormal(false)
+    , isDeferred(false)
+    , hasIndirect(false)
+    , hasShadows(false)
+    , hasAmbientOcclusion(false)
     , mIndexedTextureChannels(0)
     , disableTextureIndex(false)
     , hasAlphaMask(false)
@@ -344,13 +344,13 @@ void LLGLSLShader::unloadInternal()
     {
         GLhandleARB obj[1024];
         GLsizei count;
+        glGetAttachedObjectsARB(mProgramObject, 1024, &count, obj);
 
-        glGetAttachedObjectsARB(mProgramObject, sizeof(obj)/sizeof(obj[0]), &count, obj);
         for (GLsizei i = 0; i < count; i++)
         {
             glDetachObjectARB(mProgramObject, obj[i]);
-                glDeleteObjectARB(obj[i]);
-            }
+            glDeleteObjectARB(obj[i]);
+        }
 
         glDeleteObjectARB(mProgramObject);
 
@@ -448,12 +448,12 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
     }
     if( !success )
     {
-        LL_WARNS("ShaderLoading") << "Failed to link shader: " << mName << LL_ENDL;
+        LL_SHADER_LOADING_WARNS() << "Failed to link shader: " << mName << LL_ENDL;
 
         // Try again using a lower shader level;
         if (mShaderLevel > 0)
         {
-            LL_WARNS("ShaderLoading") << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
+            LL_SHADER_LOADING_WARNS() << "Failed to link using shader level " << mShaderLevel << " trying again using shader level " << (mShaderLevel - 1) << LL_ENDL;
             mShaderLevel--;
             return createShader(attributes,uniforms);
         }
@@ -485,18 +485,33 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
     return success;
 }
 
-BOOL LLGLSLShader::attachObject(std::string object)
+BOOL LLGLSLShader::attachVertexObject(std::string object_path) {
+    if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0)
+    {
+        stop_glerror();
+        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
+        stop_glerror();
+        return TRUE;
+    }
+    else
+    {
+        LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL;
+        return FALSE;
+    }
+}
+
+BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
 {
-    if (LLShaderMgr::instance()->mShaderObjects.count(object) > 0)
+    if (LLShaderMgr::instance()->mFragmentShaderObjects.count(object_path) > 0)
     {
         stop_glerror();
-        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mShaderObjects[object]);
+        glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
         stop_glerror();
         return TRUE;
     }
     else
     {
-        LL_WARNS("ShaderLoading") << "Attempting to attach shader object that hasn't been compiled: " << object << LL_ENDL;
+        LL_SHADER_LOADING_WARNS() << "Attempting to attach shader object: '" << object_path << "' that hasn't been compiled." << LL_ENDL;
         return FALSE;
     }
 }
@@ -511,7 +526,7 @@ void LLGLSLShader::attachObject(GLhandleARB object)
     }
     else
     {
-        LL_WARNS("ShaderLoading") << "Attempting to attach non existing shader object. " << LL_ENDL;
+        LL_SHADER_LOADING_WARNS() << "Attempting to attach non existing shader object. " << LL_ENDL;
     }
 }
 
@@ -690,6 +705,11 @@ void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> *
     }
 }
 
+void LLGLSLShader::clearPermutations()
+{
+    mDefines.clear();
+}
+
 void LLGLSLShader::addPermutation(std::string name, std::string value)
 {
     mDefines[name] = value;
@@ -759,18 +779,19 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 	S32 diffuseMap = glGetUniformLocationARB(mProgramObject, "diffuseMap");
 	S32 specularMap = glGetUniformLocationARB(mProgramObject, "specularMap");
 	S32 bumpMap = glGetUniformLocationARB(mProgramObject, "bumpMap");
+    S32 altDiffuseMap = glGetUniformLocationARB(mProgramObject, "altDiffuseMap");
 	S32 environmentMap = glGetUniformLocationARB(mProgramObject, "environmentMap");
 
 	std::set<S32> skip_index;
 
-	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap))
+	if (-1 != diffuseMap && (-1 != specularMap || -1 != bumpMap || -1 != environmentMap || -1 != altDiffuseMap))
 	{
 		GLenum type;
 		GLsizei length;
 		GLint size = -1;
 		char name[1024];
 
-		diffuseMap = specularMap = bumpMap = environmentMap = -1;
+		diffuseMap = altDiffuseMap = specularMap = bumpMap = environmentMap = -1;
 
 		for (S32 i = 0; i < activeCount; i++)
 		{
@@ -790,12 +811,6 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 				continue;
 			}
 
-			if (-1 == specularMap && std::string(name) == "specularMap")
-			{
-				specularMap = i;
-				continue;
-			}
-
 			if (-1 == bumpMap && std::string(name) == "bumpMap")
 			{
 				bumpMap = i;
@@ -807,6 +822,12 @@ BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
 				environmentMap = i;
 				continue;
 			}
+
+            if (-1 == altDiffuseMap && std::string(name) == "altDiffuseMap")
+			{
+				altDiffuseMap = i;
+				continue;
+			}
 		}
 
 		bool specularDiff = specularMap < diffuseMap && -1 != specularMap;
@@ -858,7 +879,7 @@ BOOL LLGLSLShader::link(BOOL suppress_errors)
 {
     BOOL success = LLShaderMgr::instance()->linkProgramObject(mProgramObject, suppress_errors);
 
-    if (!suppress_errors)
+    if (!success && !suppress_errors)
     {
         LLShaderMgr::instance()->dumpObjectLog(mProgramObject, !success, mName);
     }
@@ -916,19 +937,19 @@ void LLGLSLShader::bindNoShader(void)
     }
 }
 
-S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::bindTexture(const std::string &uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
 {
     S32 channel = 0;
     channel = getUniformLocation(uniform);
     
-    return bindTexture(channel, texture, mode);
+    return bindTexture(channel, texture, mode, colorspace);
 }
 
-S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
 {
     if (uniform < 0 || uniform >= (S32)mTexture.size())
     {
-        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
         return -1;
     }
     
@@ -937,6 +958,7 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextu
     if (uniform > -1)
     {
         gGL.getTexUnit(uniform)->bind(texture, mode);
+        gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
     }
     
     return uniform;
@@ -954,7 +976,7 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
 {
     if (uniform < 0 || uniform >= (S32)mTexture.size())
     {
-        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
         return -1;
     }
     
@@ -968,11 +990,11 @@ S32 LLGLSLShader::unbindTexture(S32 uniform, LLTexUnit::eTextureType mode)
     return uniform;
 }
 
-S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
 {
     if (uniform < 0 || uniform >= (S32)mTexture.size())
     {
-        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
         return -1;
     }
     S32 index = mTexture[uniform];
@@ -980,21 +1002,22 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
     {
         gGL.getTexUnit(index)->activate();
         gGL.getTexUnit(index)->enable(mode);
+        gGL.getTexUnit(index)->setTextureColorSpace(space);
     }
     return index;
 }
 
-S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
+S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
 {
     if (uniform < 0 || uniform >= (S32)mTexture.size())
     {
-        UNIFORM_ERRS << "Uniform out of range: " << uniform << LL_ENDL;
+        LL_SHADER_UNIFORM_ERRS() << "Uniform out of range: " << uniform << LL_ENDL;
         return -1;
     }
     S32 index = mTexture[uniform];
     if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)
     {
-        if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
+        if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space)
         {
             if (gDebugSession)
             {
@@ -1017,7 +1040,7 @@ void LLGLSLShader::uniform1i(U32 index, GLint x)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1039,7 +1062,7 @@ void LLGLSLShader::uniform1f(U32 index, GLfloat x)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1061,7 +1084,7 @@ void LLGLSLShader::uniform2f(U32 index, GLfloat x, GLfloat y)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1084,7 +1107,7 @@ void LLGLSLShader::uniform3f(U32 index, GLfloat x, GLfloat y, GLfloat z)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1107,7 +1130,7 @@ void LLGLSLShader::uniform4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1130,7 +1153,7 @@ void LLGLSLShader::uniform1iv(U32 index, U32 count, const GLint* v)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1153,7 +1176,7 @@ void LLGLSLShader::uniform1fv(U32 index, U32 count, const GLfloat* v)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1176,7 +1199,7 @@ void LLGLSLShader::uniform2fv(U32 index, U32 count, const GLfloat* v)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1199,7 +1222,7 @@ void LLGLSLShader::uniform3fv(U32 index, U32 count, const GLfloat* v)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1222,7 +1245,7 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1245,7 +1268,7 @@ void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, c
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1262,7 +1285,7 @@ void LLGLSLShader::uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, c
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
@@ -1279,7 +1302,7 @@ void LLGLSLShader::uniformMatrix3x4fv(U32 index, U32 count, GLboolean transpose,
 	{	
 		if (mUniform.size() <= index)
 		{
-			UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+			LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
 			return;
 		}
 
@@ -1296,7 +1319,7 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c
     {   
         if (mUniform.size() <= index)
         {
-            UNIFORM_ERRS << "Uniform index out of bounds." << LL_ENDL;
+            LL_SHADER_UNIFORM_ERRS() << "Uniform index out of bounds." << LL_ENDL;
             return;
         }
 
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index b56b91401323cde25fe0317dccce11bbda2e4182..7cf6d3c941f294da9fadfbd014f8f3e04f890ef8 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -48,6 +48,12 @@ class LLShaderFeatures
 	bool hasObjectSkinning;
 	bool hasAtmospherics;
 	bool hasGamma;
+    bool hasShadows;
+    bool hasAmbientOcclusion;
+	bool hasSrgb;
+    bool encodesNormal;
+    bool isDeferred;
+    bool hasIndirect;
 	S32 mIndexedTextureChannels;
 	bool disableTextureIndex;
 	bool hasAlphaMask;
@@ -96,7 +102,8 @@ class LLGLSLShader
 						std::vector<LLStaticHashedString> * uniforms,
 						U32 varying_count = 0,
 						const char** varyings = NULL);
-	BOOL attachObject(std::string object);
+    BOOL attachFragmentObject(std::string object);
+    BOOL attachVertexObject(std::string object);
 	void attachObject(GLhandleARB object);
 	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
 	BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes);
@@ -139,6 +146,7 @@ class LLGLSLShader
 	GLint getAttribLocation(U32 attrib);
 	GLint mapUniformTextureChannel(GLint location, GLenum type);
 	
+    void clearPermutations();
 	void addPermutation(std::string name, std::string value);
 	void removePermutation(std::string name);
 	
@@ -146,13 +154,13 @@ class LLGLSLShader
 	//if given texture uniform is active in the shader, 
 	//the corresponding channel will be active upon return
 	//returns channel texture is enabled in from [0-MAX)
-	S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
-	S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+	S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+    S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
 	
 	// bindTexture returns the texture unit we've bound the texture to.
 	// You can reuse the return value to unbind a texture when required.
-	S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
-	S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
+	S32 bindTexture(const std::string& uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
+	S32 bindTexture(S32 uniform, LLTexture *texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
 	S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
 	S32 unbindTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
 	
diff --git a/indra/llrender/llglstates.h b/indra/llrender/llglstates.h
index 0e2c3bcb44b6abbb70c1de85fe9e1930c19789e3..a4924eba14d23d03cfec2a7fba078023213cacb3 100644
--- a/indra/llrender/llglstates.h
+++ b/indra/llrender/llglstates.h
@@ -208,11 +208,27 @@ class LLGLSPipelineAvatar
 class LLGLSPipelineSkyBox
 { 
 protected:
-	LLGLDisable mAlphaTest, mCullFace, mFog;
+	LLGLDisable mAlphaTest;
+    LLGLDisable mCullFace;
+    LLGLSquashToFarClip mSquashClip;
 public:
-	LLGLSPipelineSkyBox()
-		: mAlphaTest(GL_ALPHA_TEST), mCullFace(GL_CULL_FACE), mFog(GL_FOG)
-	{ }
+	LLGLSPipelineSkyBox();
+   ~LLGLSPipelineSkyBox();
+};
+
+class LLGLSPipelineDepthTestSkyBox : public LLGLSPipelineSkyBox
+{ 
+public:
+	LLGLSPipelineDepthTestSkyBox(bool depth_test, bool depth_write);
+
+    LLGLDepthTest mDepth;
+};
+
+class LLGLSPipelineBlendSkyBox : public LLGLSPipelineDepthTestSkyBox 
+{ 
+public:
+	LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_write);
+    LLGLEnable mBlend;    
 };
 
 class LLGLSTracker
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index 3a6eebebbafef5b399376fce6dc1e16fa6c25f83..ad501687ed54fe91f4528a00ab5d41a5ecbbff78 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -288,6 +288,18 @@ void  LLGLTexture::setCategory(S32 category)
 	mGLTexturep->setCategory(category) ;
 }
 
+void LLGLTexture::setTexName(LLGLuint texName)
+{
+    llassert(mGLTexturep.notNull());
+    return mGLTexturep->setTexName(texName); 
+}
+
+void LLGLTexture::setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target)
+{
+    llassert(mGLTexturep.notNull());
+    return mGLTexturep->setTarget(target, bind_target); 
+}
+
 LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
 {
 	llassert(mGLTexturep.notNull()) ;
@@ -389,9 +401,11 @@ void LLGLTexture::destroyGLTexture()
 
 void LLGLTexture::setTexelsPerImage()
 {
-	S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT);
-	S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT);
-	mTexelsPerImage = (F32)fullwidth * fullheight;
+	U32 fullwidth = llmin(mFullWidth,U32(MAX_IMAGE_SIZE_DEFAULT));
+	U32 fullheight = llmin(mFullHeight,U32(MAX_IMAGE_SIZE_DEFAULT));
+	mTexelsPerImage = (U32)fullwidth * fullheight;
 }
 
+static LLUUID sStubUUID;
 
+const LLUUID& LLGLTexture::getID() const { return sStubUUID; }
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 70610d96264dd94e548e1bf1e6d604640d2aa5d0..071912c2c23231080315806313c1586b95ab6fdc 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -1,5 +1,5 @@
 /** 
- * @file llglviewertexture.h
+ * @file llgltexture.h
  * @brief Object for managing opengl textures
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
@@ -104,7 +104,7 @@ class LLGLTexture : public LLTexture
 
 	virtual void dump();	// debug info to LL_INFOS()
 
-	virtual const LLUUID& getID() const = 0;
+	virtual const LLUUID& getID() const;
 
 	void setBoostLevel(S32 level);
 	S32  getBoostLevel() { return mBoostLevel; }
@@ -133,6 +133,8 @@ class LLGLTexture : public LLTexture
 	BOOL       setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height);
 	void       setGLTextureCreated (bool initialized);
 	void       setCategory(S32 category) ;
+    void       setTexName(LLGLuint); // for forcing w/ externally created textures only
+    void       setTarget(const LLGLenum target, const LLTexUnit::eTextureType bind_target);
 
 	LLTexUnit::eTextureAddressMode getAddressMode(void) const ;
 	S32        getMaxDiscardLevel() const;
@@ -179,11 +181,11 @@ class LLGLTexture : public LLTexture
 
 protected:
 	S32 mBoostLevel;				// enum describing priority level
-	S32 mFullWidth;
-	S32 mFullHeight;
+	U32 mFullWidth;
+	U32 mFullHeight;
 	BOOL mUseMipMaps;
 	S8  mComponents;
-	F32 mTexelsPerImage;			// Texels per image.
+	U32 mTexelsPerImage;			// Texels per image.
 	mutable S8  mNeedsGLTexture;
 
 	//GL texture
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 40217b2e80ee017d44d16c9760c8032fffd0ffc1..ff743802170263af651af6c0eda16c4e29bf1d82 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -184,34 +184,47 @@ void LLImageGL::cleanupClass()
 //static
 S32 LLImageGL::dataFormatBits(S32 dataformat)
 {
-	switch (dataformat)
-	{
-	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 4;
-	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 8;
-	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 8;
-	  case GL_LUMINANCE:						return 8;
-	  case GL_ALPHA:							return 8;
-	  case GL_COLOR_INDEX:						return 8;
-	  case GL_LUMINANCE_ALPHA:					return 16;
-	  case GL_RGB:								return 24;
-	  case GL_RGB8:								return 24;
-	  case GL_RGBA:								return 32;
-	  case GL_BGRA:								return 32;		// Used for QuickTime media textures on the Mac
-	  default:
-		LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
-		return 0;
-	}
+    switch (dataformat)
+    {
+    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	        return 4;
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:    return 4;
+    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	        return 8;
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:    return 8;
+    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	        return 8;
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:    return 8;
+    case GL_LUMINANCE:						        return 8;
+    case GL_ALPHA:							        return 8;
+    case GL_COLOR_INDEX:						    return 8;
+    case GL_LUMINANCE_ALPHA:					    return 16;
+    case GL_RGB:								    return 24;
+    case GL_SRGB:								    return 24;
+    case GL_RGB8:								    return 24;
+    case GL_RGBA:								    return 32;
+    case GL_SRGB_ALPHA:						        return 32;
+    case GL_BGRA:								    return 32;		// Used for QuickTime media textures on the Mac
+    default:
+        LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
+        return 0;
+    }
 }
 
 //static
 S32 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
 {
-	if (dataformat >= GL_COMPRESSED_RGB_S3TC_DXT1_EXT &&
-		dataformat <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
-	{
-		if (width < 4) width = 4;
-		if (height < 4) height = 4;
-	}
+    switch (dataformat)
+    {
+    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+        if (width < 4) width = 4;
+        if (height < 4) height = 4;
+        break;
+    default:
+        break;
+    }
 	S32 bytes ((width*height*dataFormatBits(dataformat)+7)>>3);
 	S32 aligned = (bytes+3)&~3;
 	return aligned;
@@ -223,14 +236,19 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
 	switch (dataformat)
 	{
 	  case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:	return 3;
+	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 3;
 	  case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:	return 4;
+	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;
 	  case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:	return 4;
+	  case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
 	  case GL_LUMINANCE:						return 1;
 	  case GL_ALPHA:							return 1;
 	  case GL_COLOR_INDEX:						return 1;
 	  case GL_LUMINANCE_ALPHA:					return 2;
 	  case GL_RGB:								return 3;
+	  case GL_SRGB:								return 3;
 	  case GL_RGBA:								return 4;
+	  case GL_SRGB_ALPHA:						return 4;
 	  case GL_BGRA:								return 4;		// Used for QuickTime media textures on the Mac
 	  default:
 		LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
@@ -355,7 +373,7 @@ BOOL LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, B
 
 LLImageGL::LLImageGL(BOOL usemipmaps)
 :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
-	mSaveData(0)
+    mSaveData(0), mExternalTexture(FALSE)
 {
 	init(usemipmaps);
 	setSize(0, 0, 0);
@@ -365,7 +383,7 @@ LLImageGL::LLImageGL(BOOL usemipmaps)
 
 LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
 :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
-	mSaveData(0)
+    mSaveData(0), mExternalTexture(FALSE)
 {
 	llassert( components <= 4 );
 	init(usemipmaps);
@@ -376,7 +394,7 @@ LLImageGL::LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps)
 
 LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
 :	LLTrace::MemTrackable<LLImageGL>("LLImageGL"),
-	mSaveData(0)
+    mSaveData(0), mExternalTexture(FALSE)
 {
 	init(usemipmaps);
 	setSize(0, 0, 0);
@@ -386,12 +404,36 @@ LLImageGL::LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps)
 	createGLTexture(0, imageraw); 
 }
 
+LLImageGL::LLImageGL(
+    LLGLuint texName,
+    U32 components,
+    LLGLenum target,
+    LLGLint  formatInternal,
+    LLGLenum formatPrimary,
+    LLGLenum formatType,
+    LLTexUnit::eTextureAddressMode addressMode)
+    : LLTrace::MemTrackable<LLImageGL>("LLImageGL"), mSaveData(0), mExternalTexture(TRUE)
+{
+    init(false);
+    mTexName = texName;
+    mTarget = target;
+    mComponents = components;
+    mAddressMode = addressMode;
+    mFormatType = formatType;
+    mFormatInternal = formatInternal;
+    mFormatPrimary = formatPrimary;
+}
+
+
 LLImageGL::~LLImageGL()
 {
-	LLImageGL::cleanup();
-	sImageList.erase(this);
-	freePickMask();
-	sCount--;
+    if (!mExternalTexture)
+    {
+	    LLImageGL::cleanup();
+	    sImageList.erase(this);
+	    freePickMask();
+	    sCount--;
+    }
 }
 
 void LLImageGL::init(BOOL usemipmaps)
@@ -626,10 +668,20 @@ BOOL LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)
 {
 	LL_RECORD_BLOCK_TIME(FTM_SET_IMAGE);
 	bool is_compressed = false;
-	if (mFormatPrimary >= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT && mFormatPrimary <= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
-	{
-		is_compressed = true;
-	}
+
+    switch (mFormatPrimary)
+    {
+    case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+    case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+    case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+        is_compressed = true;
+        break;
+    default:
+        break;
+    }
 	
 	
 	
@@ -1203,10 +1255,18 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
 			case GL_RGB8:
 				intformat = GL_COMPRESSED_RGB; 
 				break;
+            case GL_SRGB:
+            case GL_SRGB8:
+                intformat = GL_COMPRESSED_SRGB;
+                break;
 			case GL_RGBA:
 			case GL_RGBA8:
 				intformat = GL_COMPRESSED_RGBA; 
 				break;
+            case GL_SRGB_ALPHA:
+            case GL_SRGB8_ALPHA8:
+                intformat = GL_COMPRESSED_SRGB_ALPHA;
+                break;
 			case GL_LUMINANCE:
 			case GL_LUMINANCE8:
 				intformat = GL_COMPRESSED_LUMINANCE;
@@ -1310,33 +1370,51 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
 
 	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;
-		}
+        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;
+        }
 
 		calcAlphaChannelOffsetAndStride() ;
 	}
@@ -1764,28 +1842,30 @@ void LLImageGL::calcAlphaChannelOffsetAndStride()
 	}
 
 	mAlphaStride = -1 ;
-	switch (mFormatPrimary)
-	{
-	case GL_LUMINANCE:
-	case GL_ALPHA:
-		mAlphaStride = 1;
-		break;
-	case GL_LUMINANCE_ALPHA:
-		mAlphaStride = 2;
-		break;
-	case GL_RGB:
-		mNeedsAlphaAndPickMask = FALSE ;
-		mIsMask = FALSE;
-		return ; //no alpha channel.
-	case GL_RGBA:
-		mAlphaStride = 4;
-		break;
-	case GL_BGRA_EXT:
-		mAlphaStride = 4;
-		break;
-	default:
-		break;
-	}
+    switch (mFormatPrimary)
+    {
+    case GL_LUMINANCE:
+    case GL_ALPHA:
+        mAlphaStride = 1;
+        break;
+    case GL_LUMINANCE_ALPHA:
+        mAlphaStride = 2;
+        break;
+    case GL_RGB:
+    case GL_SRGB:
+        mNeedsAlphaAndPickMask = FALSE;
+        mIsMask = FALSE;
+        return; //no alpha channel.
+    case GL_RGBA:
+    case GL_SRGB_ALPHA:
+        mAlphaStride = 4;
+        break;
+    case GL_BGRA_EXT:
+        mAlphaStride = 4;
+        break;
+    default:
+        break;
+    }
 
 	mAlphaOffset = -1 ;
 	if (mFormatType == GL_UNSIGNED_BYTE)
@@ -1968,12 +2048,13 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
 
 	freePickMask();
 
-	if (mFormatType != GL_UNSIGNED_BYTE ||
-	    mFormatPrimary != GL_RGBA)
-	{
-		//cannot generate a pick mask for this texture
-		return;
-	}
+    if (mFormatType != GL_UNSIGNED_BYTE ||
+        ((mFormatPrimary != GL_RGBA)
+      && (mFormatPrimary != GL_SRGB_ALPHA)))
+    {
+        //cannot generate a pick mask for this texture
+        return;
+    }
 
 #ifdef SHOW_ASSERT
 	const U32 pickSize = createPickMask(width, height);
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 2be54be062a9ef0f892b734b239b0238683ed44e..4f3d7eed0a45122a360beac5c16b4a6abca5eccb 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -84,7 +84,10 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>
 	LLImageGL(BOOL usemipmaps = TRUE);
 	LLImageGL(U32 width, U32 height, U8 components, BOOL usemipmaps = TRUE);
 	LLImageGL(const LLImageRaw* imageraw, BOOL usemipmaps = TRUE);
-	
+
+    // For wrapping textures created via GL elsewhere with our API only. Use with caution.
+    LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint  formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
+
 protected:
 	virtual ~LLImageGL();
 
@@ -234,6 +237,8 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>
 	LLGLenum mFormatType;
 	BOOL	 mFormatSwapBytes;// if true, use glPixelStorei(GL_UNPACK_SWAP_BYTES, 1)
 	
+    BOOL mExternalTexture;
+
 	// STATICS
 public:	
 	static std::set<LLImageGL*> sImageList;
@@ -279,6 +284,8 @@ class LLImageGL : public LLRefCount, public LLTrace::MemTrackable<LLImageGL>
 	void setCategory(S32 category) {mCategory = category;}
 	S32  getCategory()const {return mCategory;}
 	
+    void setTexName(GLuint texName) { mTexName = texName; }
+
 	//for debug use: show texture size distribution 
 	//----------------------------------------
 	static S32 sCurTexSizeBar ;
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 65d61819202fe6783bde380170e5f7969b71d50b..ebc4659bcfbb0a76d6e5d3329238b6806e7fc2ab 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -59,7 +59,8 @@ static const GLenum sGLTextureType[] =
 	GL_TEXTURE_2D,
 	GL_TEXTURE_RECTANGLE_ARB,
 	GL_TEXTURE_CUBE_MAP_ARB,
-	GL_TEXTURE_2D_MULTISAMPLE
+	GL_TEXTURE_2D_MULTISAMPLE,
+    GL_TEXTURE_3D
 };
 
 static const GLint sGLAddressMode[] =
@@ -104,7 +105,7 @@ LLTexUnit::LLTexUnit(S32 index)
 	mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT),
 	mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR),
 	mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA),
-	mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0),
+    mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), mTexColorSpace(TCS_LINEAR),
 	mHasMipMaps(false),
 	mIndex(index)
 {
@@ -161,6 +162,8 @@ void LLTexUnit::refreshState(void)
 		setTextureCombiner(mCurrColorOp, mCurrColorSrc1, mCurrColorSrc2, false);
 		setTextureCombiner(mCurrAlphaOp, mCurrAlphaSrc1, mCurrAlphaSrc2, true);
 	}
+
+    setTextureColorSpace(mTexColorSpace);
 }
 
 void LLTexUnit::activate(void)
@@ -218,6 +221,8 @@ void LLTexUnit::disable(void)
 		{
 			glDisable(sGLTextureType[mCurrTexType]);
 		}
+
+        setTextureColorSpace(TCS_LINEAR);
 		
 		mCurrTexType = TT_NONE;
 	}
@@ -254,7 +259,8 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
 						gl_tex->mTexOptionsDirty = false;
 						setTextureAddressMode(gl_tex->mAddressMode);
 						setTextureFilteringOption(gl_tex->mFilterOption);
-					}
+                    }
+                    setTextureColorSpace(mTexColorSpace);
 				}
 			}
 			else
@@ -329,6 +335,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind)
 			setTextureFilteringOption(texture->mFilterOption);
 			stop_glerror();
 		}
+        setTextureColorSpace(mTexColorSpace);
 	}
 
 	stop_glerror();
@@ -354,7 +361,7 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
 		{
 			activate();
 			enable(LLTexUnit::TT_CUBE_MAP);
-			mCurrTexture = cubeMap->mImages[0]->getTexName();
+            mCurrTexture = cubeMap->mImages[0]->getTexName();
 			glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, mCurrTexture);
 			mHasMipMaps = cubeMap->mImages[0]->mHasMipMaps;
 			cubeMap->mImages[0]->updateBindStats(cubeMap->mImages[0]->mTextureMemory);
@@ -363,7 +370,8 @@ bool LLTexUnit::bind(LLCubeMap* cubeMap)
 				cubeMap->mImages[0]->mTexOptionsDirty = false;
 				setTextureAddressMode(cubeMap->mImages[0]->mAddressMode);
 				setTextureFilteringOption(cubeMap->mImages[0]->mFilterOption);
-			}
+            }
+            setTextureColorSpace(mTexColorSpace);
 			return true;
 		}
 		else
@@ -414,7 +422,8 @@ bool LLTexUnit::bindManual(eTextureType type, U32 texture, bool hasMips)
 		enable(type);
 		mCurrTexture = texture;
 		glBindTexture(sGLTextureType[type], texture);
-		mHasMipMaps = hasMips;
+        mHasMipMaps = hasMips;
+        setTextureColorSpace(mTexColorSpace);
 	}
 	return true;
 }
@@ -434,6 +443,9 @@ void LLTexUnit::unbind(eTextureType type)
 	if (mCurrTexType == type)
 	{
 		mCurrTexture = 0;
+
+        // Always make sure our texture color space is reset to linear.  SRGB sampling should be opt-in in the vast majority of cases.  Also prevents color space "popping".
+        mTexColorSpace = TCS_LINEAR;
 		if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE)
 		{
 			glBindTexture(sGLTextureType[type], sWhiteTexture);
@@ -837,6 +849,28 @@ void LLTexUnit::debugTextureUnit(void)
 	}
 }
 
+void LLTexUnit::setTextureColorSpace(eTextureColorSpace space) {
+    mTexColorSpace = space;
+
+#if USE_SRGB_DECODE
+    if (gGLManager.mHasTexturesRGBDecode) {
+
+        if (space == TCS_SRGB) {
+            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+        }
+        else {
+            glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+        }
+
+        if (gDebugGL) {
+            assert_glerror();
+        }
+    }
+#endif
+    glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+
+}
+
 LLLightState::LLLightState(S32 index)
 : mIndex(index),
   mEnabled(false),
@@ -849,9 +883,12 @@ LLLightState::LLLightState(S32 index)
 	if (mIndex == 0)
 	{
 		mDiffuse.set(1,1,1,1);
+        mDiffuseB.set(0,0,0,0);
 		mSpecular.set(1,1,1,1);
 	}
 
+    mSunIsPrimary = true;
+
 	mAmbient.set(0,0,0,1);
 	mPosition.set(0,0,1,0);
 	mSpotDirection.set(0,0,-1);
@@ -894,6 +931,24 @@ void LLLightState::setDiffuse(const LLColor4& diffuse)
 	}
 }
 
+void LLLightState::setDiffuseB(const LLColor4& diffuse)
+{
+    if (mDiffuseB != diffuse)
+	{
+		++gGL.mLightHash;
+		mDiffuseB = diffuse;
+	}
+}
+
+void LLLightState::setSunPrimary(bool v)
+{
+    if (mSunIsPrimary != v)
+    {
+        ++gGL.mLightHash;
+		mSunIsPrimary = v;
+    }
+}
+
 void LLLightState::setAmbient(const LLColor4& ambient)
 {
 	if (mAmbient != ambient)
@@ -1150,8 +1205,10 @@ void LLRender::syncLightState()
 
 		LLVector4 position[8];
 		LLVector3 direction[8];
-		LLVector3 attenuation[8];
+		LLVector4 attenuation[8];
 		LLVector3 diffuse[8];
+        LLVector3 diffuse_b[8];
+        bool      sun_primary[8];
 
 		for (U32 i = 0; i < 8; i++)
 		{
@@ -1159,17 +1216,21 @@ void LLRender::syncLightState()
 
 			position[i] = light->mPosition;
 			direction[i] = light->mSpotDirection;
-			attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[3]);
+            attenuation[i].set(light->mLinearAtten, light->mQuadraticAtten, light->mSpecular.mV[2], light->mSpecular.mV[3]);
 			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->uniform3fv(LLShaderMgr::LIGHT_ATTENUATION, 8, attenuation[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);
-		//HACK -- duplicate sunlight color for compatibility with drivers that can't deal with multiple shader objects referencing the same uniform
-		shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, diffuse[0].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);
 	}
 }
 
@@ -1190,6 +1251,7 @@ void LLRender::syncMatrices()
 	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 
 	static glh::matrix4f cached_mvp;
+    static glh::matrix4f cached_inv_mdv;
 	static U32 cached_mvp_mdv_hash = 0xFFFFFFFF;
 	static U32 cached_mvp_proj_hash = 0xFFFFFFFF;
 	
@@ -1203,12 +1265,18 @@ void LLRender::syncMatrices()
 		bool mvp_done = false;
 
 		U32 i = MM_MODELVIEW;
-		if (mMatHash[i] != shader->mMatHash[i])
+		if (mMatHash[MM_MODELVIEW] != shader->mMatHash[MM_MODELVIEW])
 		{ //update modelview, normal, and MVP
-			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
+			glh::matrix4f& mat = mMatrix[MM_MODELVIEW][mMatIdx[MM_MODELVIEW]];
+
+            // if MDV has changed, update the cached inverse as well
+            if (cached_mvp_mdv_hash != mMatHash[MM_MODELVIEW])
+            {
+                cached_inv_mdv = mat.inverse();
+            }
 
-			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
-			shader->mMatHash[i] = mMatHash[i];
+			shader->uniformMatrix4fv(name[MM_MODELVIEW], 1, GL_FALSE, mat.m);
+			shader->mMatHash[MM_MODELVIEW] = mMatHash[MM_MODELVIEW];
 
 			//update normal matrix
 			S32 loc = shader->getUniformLocation(LLShaderMgr::NORMAL_MATRIX);
@@ -1216,7 +1284,7 @@ void LLRender::syncMatrices()
 			{
 				if (cached_normal_hash != mMatHash[i])
 				{
-					cached_normal = mat.inverse().transpose();
+					cached_normal = cached_inv_mdv.transpose();
 					cached_normal_hash = mMatHash[i];
 				}
 
@@ -1232,6 +1300,11 @@ void LLRender::syncMatrices()
 				shader->uniformMatrix3fv(LLShaderMgr::NORMAL_MATRIX, 1, GL_FALSE, norm_mat);
 			}
 
+            if (shader->getUniformLocation(LLShaderMgr::INVERSE_MODELVIEW_MATRIX))
+            {                
+	            shader->uniformMatrix4fv(LLShaderMgr::INVERSE_MODELVIEW_MATRIX, 1, GL_FALSE, cached_inv_mdv.m); 
+            }
+
 			//update MVP matrix
 			mvp_done = true;
 			loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
@@ -1251,14 +1324,21 @@ void LLRender::syncMatrices()
 			}
 		}
 
-
 		i = MM_PROJECTION;
-		if (mMatHash[i] != shader->mMatHash[i])
+		if (mMatHash[MM_PROJECTION] != shader->mMatHash[MM_PROJECTION])
 		{ //update projection matrix, normal, and MVP
-			glh::matrix4f& mat = mMatrix[i][mMatIdx[i]];
+			glh::matrix4f& mat = mMatrix[MM_PROJECTION][mMatIdx[MM_PROJECTION]];
 
-			shader->uniformMatrix4fv(name[i], 1, GL_FALSE, mat.m);
-			shader->mMatHash[i] = mMatHash[i];
+            // it would be nice to have this automatically track the state of the proj matrix
+            // but certain render paths (deferred lighting) require it to be mismatched *sigh*
+            //if (shader->getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX))
+            //{
+	        //    glh::matrix4f inv_proj = mat.inverse();
+	        //    shader->uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+            //}
+
+			shader->uniformMatrix4fv(name[MM_PROJECTION], 1, GL_FALSE, mat.m);
+			shader->mMatHash[MM_PROJECTION] = mMatHash[MM_PROJECTION];
 
 			if (!mvp_done)
 			{
@@ -1266,7 +1346,7 @@ void LLRender::syncMatrices()
 				S32 loc = shader->getUniformLocation(LLShaderMgr::MODELVIEW_PROJECTION_MATRIX);
 				if (loc > -1)
 				{
-					if (cached_mvp_mdv_hash != mMatHash[i] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
+					if (cached_mvp_mdv_hash != mMatHash[MM_PROJECTION] || cached_mvp_proj_hash != mMatHash[MM_PROJECTION])
 					{
 						U32 mdv = MM_MODELVIEW;
 						cached_mvp = mat;
@@ -1290,7 +1370,7 @@ void LLRender::syncMatrices()
 		}
 
 
-		if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting)
+		if (shader->mFeatures.hasLighting || shader->mFeatures.calculatesLighting || shader->mFeatures.calculatesAtmospherics)
 		{ //also sync light state
 			syncLightState();
 		}
@@ -1307,7 +1387,7 @@ void LLRender::syncMatrices()
 			GL_TEXTURE,
 		};
 
-		for (U32 i = 0; i < 2; ++i)
+		for (U32 i = 0; i < MM_TEXTURE0; ++i)
 		{
 			if (mMatHash[i] != mCurMatHash[i])
 			{
@@ -1317,11 +1397,11 @@ void LLRender::syncMatrices()
 			}
 		}
 
-		for (U32 i = 2; i < NUM_MATRIX_MODES; ++i)
+		for (U32 i = MM_TEXTURE0; i < NUM_MATRIX_MODES; ++i)
 		{
 			if (mMatHash[i] != mCurMatHash[i])
 			{
-				gGL.getTexUnit(i-2)->activate();
+				gGL.getTexUnit(i-MM_TEXTURE0)->activate();
 				glMatrixMode(mode[i]);
 				glLoadMatrixf(mMatrix[i][mMatIdx[i]].m);
 				mCurMatHash[i] = mMatHash[i];
@@ -1453,18 +1533,21 @@ void LLRender::multMatrix(const GLfloat* m)
 	}
 }
 
-void LLRender::matrixMode(U32 mode)
+void LLRender::matrixMode(eMatrixMode mode)
 {
 	if (mode == MM_TEXTURE)
 	{
-		mode = MM_TEXTURE0 + gGL.getCurrentTexUnitIndex();
+        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(mode < NUM_MATRIX_MODES);
 	mMatrixMode = mode;
 }
 
-U32 LLRender::getMatrixMode()
+LLRender::eMatrixMode LLRender::getMatrixMode()
 {
 	if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)
 	{ //always return MM_TEXTURE if current matrix mode points at any texture matrix
@@ -2331,3 +2414,85 @@ void LLRender::debugTexUnits(void)
 	LL_INFOS("TextureUnit") << "Active TexUnit Enabled : " << active_enabled << LL_ENDL;
 }
 
+
+
+glh::matrix4f copy_matrix(F32* src)
+{
+	glh::matrix4f ret;
+	ret.set_value(src);
+	return ret;
+}
+
+glh::matrix4f get_current_modelview()
+{
+	return copy_matrix(gGLModelView);
+}
+
+glh::matrix4f get_current_projection()
+{
+	return copy_matrix(gGLProjection);
+}
+
+glh::matrix4f get_last_modelview()
+{
+	return copy_matrix(gGLLastModelView);
+}
+
+glh::matrix4f get_last_projection()
+{
+	return copy_matrix(gGLLastProjection);
+}
+
+void copy_matrix(const glh::matrix4f& src, F32* dst)
+{
+	for (U32 i = 0; i < 16; i++)
+	{
+		dst[i] = src.m[i];
+	}
+}
+
+void set_current_modelview(const glh::matrix4f& mat)
+{
+	copy_matrix(mat, gGLModelView);
+}
+
+void set_current_projection(glh::matrix4f& mat)
+{
+	copy_matrix(mat, gGLProjection);
+}
+
+glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
+{
+	glh::matrix4f ret(
+		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
+		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
+		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
+		0.f, 0.f, 0.f, 1.f);
+
+	return ret;
+}
+
+glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
+{
+	GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
+
+	return glh::matrix4f(f/aspect, 0, 0, 0,
+						 0, f, 0, 0,
+						 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
+						 0, 0, -1.f, 0);
+}
+
+glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
+{
+	LLVector3 f = center-eye;
+	f.normVec();
+	up.normVec();
+	LLVector3 s = f % up;
+	LLVector3 u = s % f;
+
+	return glh::matrix4f(s[0], s[1], s[2], 0,
+					  u[0], u[1], u[2], 0,
+					  -f[0], -f[1], -f[2], 0,
+					  0, 0, 0, 1);
+	
+}
diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h
index 32bb728d8a1739e82423e8b3e6626c50c3e6e408..41f4fe40176620087a214303dd732498ed7b0e06 100644
--- a/indra/llrender/llrender.h
+++ b/indra/llrender/llrender.h
@@ -61,10 +61,11 @@ class LLTexUnit
 	typedef enum
 	{
 		TT_TEXTURE = 0,			// Standard 2D Texture
-		TT_RECT_TEXTURE,	// Non power of 2 texture
-		TT_CUBE_MAP,		// 6-sided cube map texture
+		TT_RECT_TEXTURE,	    // Non power of 2 texture
+		TT_CUBE_MAP,		    // 6-sided cube map texture
 		TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample
-		TT_NONE 		// No texture type is currently enabled
+        TT_TEXTURE_3D,          // standard 3D Texture
+		TT_NONE, 		        // No texture type is currently enabled        
 	} eTextureType;
 
 	typedef enum
@@ -130,6 +131,12 @@ class LLTexUnit
 		TBS_ONE_MINUS_CONST_ALPHA
 	} eTextureBlendSrc;
 
+    typedef enum
+    {
+        TCS_LINEAR = 0,
+        TCS_SRGB
+    } eTextureColorSpace;
+
 	LLTexUnit(S32 index);
 
 	// Refreshes renderer state of the texture unit to the cached values
@@ -152,7 +159,7 @@ class LLTexUnit
 	// Binds the LLImageGL to this texture unit 
 	// (automatically enables the unit for the LLImageGL's texture type)
 	bool bind(LLImageGL* texture, bool for_rendering = false, bool forceBind = false);
-	bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
+    bool bind(LLTexture* texture, bool for_rendering = false, bool forceBind = false);
 
 	// Binds a cubemap to this texture unit 
 	// (automatically enables the texture unit for cubemaps)
@@ -197,6 +204,10 @@ class LLTexUnit
 
 	void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
 
+    void setTextureColorSpace(eTextureColorSpace space);
+
+    eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; }
+
 protected:
 	const S32			mIndex;
 	U32					mCurrTexture;
@@ -208,6 +219,7 @@ class LLTexUnit
 	eTextureBlendOp		mCurrAlphaOp;
 	eTextureBlendSrc	mCurrAlphaSrc1;
 	eTextureBlendSrc	mCurrAlphaSrc2;
+    eTextureColorSpace  mTexColorSpace;
 	S32					mCurrColorScale;
 	S32					mCurrAlphaScale;
 	bool				mHasMipMaps;
@@ -228,6 +240,7 @@ class LLLightState
 	void enable();
 	void disable();
 	void setDiffuse(const LLColor4& diffuse);
+    void setDiffuseB(const LLColor4& diffuse);
 	void setAmbient(const LLColor4& ambient);
 	void setSpecular(const LLColor4& specular);
 	void setPosition(const LLVector4& position);
@@ -237,6 +250,7 @@ class LLLightState
 	void setSpotExponent(const F32& exponent);
 	void setSpotCutoff(const F32& cutoff);
 	void setSpotDirection(const LLVector3& direction);
+    void setSunPrimary(bool v);
 
 protected:
 	friend class LLRender;
@@ -244,6 +258,8 @@ class LLLightState
 	S32 mIndex;
 	bool mEnabled;
 	LLColor4 mDiffuse;
+    LLColor4 mDiffuseB;
+    bool     mSunIsPrimary;
 	LLColor4 mAmbient;
 	LLColor4 mSpecular;
 	LLVector4 mPosition;
@@ -264,10 +280,11 @@ class LLRender
 
 	enum eTexIndex
 	{
-		DIFFUSE_MAP = 0,
-		NORMAL_MAP,
-		SPECULAR_MAP,
-		NUM_TEXTURE_CHANNELS,
+		DIFFUSE_MAP           = 0,
+        ALTERNATE_DIFFUSE_MAP = 1,
+		NORMAL_MAP            = 1,
+		SPECULAR_MAP          = 2,        
+		NUM_TEXTURE_CHANNELS  = 3,
 	};
 
 	enum eVolumeTexIndex
@@ -360,8 +377,8 @@ class LLRender
 	void loadMatrix(const GLfloat* m);
 	void loadIdentity();
 	void multMatrix(const GLfloat* m);
-	void matrixMode(U32 mode);	
-	U32 getMatrixMode();
+	void matrixMode(eMatrixMode mode);	
+	eMatrixMode getMatrixMode();
 
 	const glh::matrix4f& getModelviewMatrix();
 	const glh::matrix4f& getProjectionMatrix();
@@ -450,7 +467,7 @@ class LLRender
 private:
 	friend class LLLightState;
 
-	U32 mMatrixMode;
+	eMatrixMode mMatrixMode;
 	U32 mMatIdx[NUM_MATRIX_MODES];
 	U32 mMatHash[NUM_MATRIX_MODES];
 	glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
@@ -495,4 +512,33 @@ extern S32 gGLViewport[4];
 
 extern LLRender gGL;
 
+// This rotation matrix moves the default OpenGL reference frame 
+// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
+const F32 OGL_TO_CFR_ROTATION[16] = {  0.f,  0.f, -1.f,  0.f, 	// -Z becomes X
+									  -1.f,  0.f,  0.f,  0.f, 	// -X becomes Y
+									   0.f,  1.f,  0.f,  0.f,	//  Y becomes Z
+									   0.f,  0.f,  0.f,  1.f };
+
+glh::matrix4f copy_matrix(F32* src);
+glh::matrix4f get_current_modelview();
+glh::matrix4f get_current_projection();
+glh::matrix4f get_last_modelview();
+glh::matrix4f get_last_projection();
+
+void copy_matrix(const glh::matrix4f& src, F32* dst);
+void set_current_modelview(const glh::matrix4f& mat);
+void set_current_projection(glh::matrix4f& mat);
+
+glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);
+glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
+glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
+
+#if LL_RELEASE_FOR_DOWNLOAD
+    #define LL_SHADER_LOADING_WARNS(...) LL_WARNS_ONCE("ShaderLoading")
+    #define LL_SHADER_UNIFORM_ERRS(...)  LL_WARNS_ONCE("Shader")
+#else
+    #define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
+    #define LL_SHADER_UNIFORM_ERRS(...)  LL_ERRS("Shader")    
+#endif
+
 #endif
diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp
index cd484b4fe901cdc7053a7bacddf1240e26fdf12e..9fb4f7f2b07d18aed7bf79ea6bf7d69cad19a89d 100644
--- a/indra/llrender/llrendertarget.cpp
+++ b/indra/llrender/llrendertarget.cpp
@@ -502,9 +502,26 @@ U32 LLRenderTarget::getNumTextures() const
 }
 
 
-void LLRenderTarget::bindTexture(U32 index, S32 channel)
+void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options)
 {
 	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_ALPHA8:
+            isSRGB = true;
+        break;
+
+        default:
+        break;
+    }
+
+    gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
+    gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);
 }
 
 void LLRenderTarget::flush(bool fetch_depth)
diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h
index 6dc84d978da0b9869e12b2d3987a1017c37e4dff..6c07ac5b1c7c8645af7e04c45fc731bdc97f3dc7 100644
--- a/indra/llrender/llrendertarget.h
+++ b/indra/llrender/llrendertarget.h
@@ -120,7 +120,7 @@ class LLRenderTarget
 	U32 getDepth(void) const { return mDepth; }
 	bool hasStencil() const { return mStencil; }
 
-	void bindTexture(U32 index, S32 channel);
+	void bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilterOptions filter_options = LLTexUnit::TFO_BILINEAR);
 
 	//flush rendering operations
 	//must be called when rendering is complete
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 643c36887041300b8fa25c5ef240c180d37f2347..13830208732d0a97c1821d16a7f290a8aedd01c0 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -25,22 +25,14 @@
  */
 
 #include "linden_common.h"
-
 #include "llshadermgr.h"
-
-#include "llfile.h"
 #include "llrender.h"
+#include "llfile.h"
 
 #if LL_DARWIN
 #include "OpenGL/OpenGL.h"
 #endif
 
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
-#else
-#define UNIFORM_ERRS LL_ERRS("Shader")
-#endif
-
 // Lots of STL stuff in here, using namespace std to keep things more readable
 using std::vector;
 using std::pair;
@@ -87,20 +79,20 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	{
 		if (features->hasWaterFog)
 		{
-			if (!shader->attachObject("windlight/atmosphericsVarsWaterV.glsl"))
+			if (!shader->attachVertexObject("windlight/atmosphericsVarsWaterV.glsl"))
 			{
 				return FALSE;
 			}
 		}
-		else if (!shader->attachObject("windlight/atmosphericsVarsV.glsl"))
+        else if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl"))
 		{
 			return FALSE;
 		}
 	}
 
-	if (features->calculatesLighting || features->atmosphericHelpers)
+	if (features->calculatesLighting || features->calculatesAtmospherics)
 	{
-		if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))
+		if (!shader->attachVertexObject("windlight/atmosphericsHelpersV.glsl"))
 		{
 			return FALSE;
 		}
@@ -110,40 +102,40 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	{
 		if (features->isSpecular)
 		{
-			if (!shader->attachObject("lighting/lightFuncSpecularV.glsl"))
+            if (!shader->attachVertexObject("lighting/lightFuncSpecularV.glsl"))
 			{
 				return FALSE;
 			}
 		
 			if (!features->isAlphaLighting)
 			{
-				if (!shader->attachObject("lighting/sumLightsSpecularV.glsl"))
+                if (!shader->attachVertexObject("lighting/sumLightsSpecularV.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			
-			if (!shader->attachObject("lighting/lightSpecularV.glsl"))
+            if (!shader->attachVertexObject("lighting/lightSpecularV.glsl"))
 			{
 				return FALSE;
 			}
 		}
 		else 
 		{
-			if (!shader->attachObject("lighting/lightFuncV.glsl"))
+            if (!shader->attachVertexObject("lighting/lightFuncV.glsl"))
 			{
 				return FALSE;
 			}
 			
 			if (!features->isAlphaLighting)
 			{
-				if (!shader->attachObject("lighting/sumLightsV.glsl"))
+                if (!shader->attachVertexObject("lighting/sumLightsV.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			
-			if (!shader->attachObject("lighting/lightV.glsl"))
+            if (!shader->attachVertexObject("lighting/lightV.glsl"))
 			{
 				return FALSE;
 			}
@@ -152,8 +144,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	
 	// NOTE order of shader object attaching is VERY IMPORTANT!!!
 	if (features->calculatesAtmospherics)
-	{
-		if (!shader->attachObject("windlight/atmosphericsV.glsl"))
+    {
+        if (!shader->attachVertexObject("windlight/atmosphericsFuncs.glsl")) {
+            return FALSE;
+        }
+
+        if (!shader->attachVertexObject("windlight/atmosphericsV.glsl"))
 		{
 			return FALSE;
 		}
@@ -161,7 +157,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 
 	if (features->hasSkinning)
 	{
-		if (!shader->attachObject("avatar/avatarSkinV.glsl"))
+        if (!shader->attachVertexObject("avatar/avatarSkinV.glsl"))
 		{
 			return FALSE;
 		}
@@ -169,7 +165,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 
 	if (features->hasObjectSkinning)
 	{
-		if (!shader->attachObject("avatar/objectSkinV.glsl"))
+        if (!shader->attachVertexObject("avatar/objectSkinV.glsl"))
 		{
 			return FALSE;
 		}
@@ -179,33 +175,95 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	// Attach Fragment Shader Features Next
 	///////////////////////////////////////
 
+// NOTE order of shader object attaching is VERY IMPORTANT!!!
+
 	if(features->calculatesAtmospherics)
 	{
 		if (features->hasWaterFog)
 		{
-			if (!shader->attachObject("windlight/atmosphericsVarsWaterF.glsl"))
+			if (!shader->attachFragmentObject("windlight/atmosphericsVarsWaterF.glsl"))
 			{
 				return FALSE;
 			}
 		}
-		else if (!shader->attachObject("windlight/atmosphericsVarsF.glsl"))
+        else if (!shader->attachFragmentObject("windlight/atmosphericsVarsF.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->calculatesLighting || features->calculatesAtmospherics)
+	{
+        if (!shader->attachFragmentObject("windlight/atmosphericsHelpersF.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    // we want this BEFORE shadows and AO because those facilities use pos/norm access
+    if (features->isDeferred)
+	{
+        if (!shader->attachFragmentObject("deferred/deferredUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->hasShadows)
+	{
+        if (!shader->attachFragmentObject("deferred/shadowUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->hasAmbientOcclusion)
+	{
+        if (!shader->attachFragmentObject("deferred/aoUtil.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->hasIndirect)
+	{
+        if (!shader->attachFragmentObject("deferred/indirect.glsl"))
 		{
 			return FALSE;
 		}
 	}
 
-	// NOTE order of shader object attaching is VERY IMPORTANT!!!
 	if (features->hasGamma)
 	{
-		if (!shader->attachObject("windlight/gammaF.glsl"))
+        if (!shader->attachFragmentObject("windlight/gammaF.glsl"))
 		{
 			return FALSE;
 		}
 	}
-	
-	if (features->hasAtmospherics)
+
+	if (features->hasSrgb)
 	{
-		if (!shader->attachObject("windlight/atmosphericsF.glsl"))
+        if (!shader->attachFragmentObject("environment/srgbF.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+    if (features->encodesNormal)
+	{
+        if (!shader->attachFragmentObject("environment/encodeNormF.glsl"))
+		{
+			return FALSE;
+		}
+	}
+
+	if (features->hasAtmospherics)
+    {
+        if (!shader->attachFragmentObject("windlight/atmosphericsFuncs.glsl")) {
+            return FALSE;
+        }
+
+        if (!shader->attachFragmentObject("windlight/atmosphericsF.glsl"))
 		{
 			return FALSE;
 		}
@@ -213,7 +271,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	
 	if (features->hasTransport)
 	{
-		if (!shader->attachObject("windlight/transportF.glsl"))
+        if (!shader->attachFragmentObject("windlight/transportF.glsl"))
 		{
 			return FALSE;
 		}
@@ -225,7 +283,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	// NOTE order of shader object attaching is VERY IMPORTANT!!!
 	if (features->hasWaterFog)
 	{
-		if (!shader->attachObject("environment/waterFogF.glsl"))
+        if (!shader->attachFragmentObject("environment/waterFogF.glsl"))
 		{
 			return FALSE;
 		}
@@ -239,14 +297,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightWaterNonIndexedF.glsl"))
 					{
 						return FALSE;
 					}
@@ -256,14 +314,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightWaterAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightWaterF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightWaterF.glsl"))
 					{
 						return FALSE;
 					}
@@ -278,14 +336,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightAlphaMaskNonIndexedF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightNonIndexedF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightNonIndexedF.glsl"))
 					{
 						return FALSE;
 					}
@@ -295,14 +353,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightF.glsl"))
 					{
 						return FALSE;
 					}
@@ -320,14 +378,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		{
 			if (features->disableTextureIndex)
 			{
-				if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			else 
 			{
-				if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyWaterF.glsl"))
 				{
 					return FALSE;
 				}
@@ -340,12 +398,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
-				else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
+                else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterNonIndexedF.glsl"))
 				{
 					return FALSE;
 				}
@@ -354,12 +412,12 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightWaterAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
-				else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl"))
+                else if (!shader->attachFragmentObject("lighting/lightFullbrightWaterF.glsl"))
 				{
 					return FALSE;
 				}
@@ -371,14 +429,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		{
 			if (features->disableTextureIndex)
 			{
-				if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyNonIndexedF.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			else 
 			{
-				if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightFullbrightShinyF.glsl"))
 				{
 					return FALSE;
 				}
@@ -393,14 +451,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightNonIndexedF.glsl"))
 					{
 						return FALSE;
 					}
@@ -410,14 +468,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 			{
 				if (features->hasAlphaMask)
 				{
-					if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightAlphaMaskF.glsl"))
 					{
 						return FALSE;
 					}
 				}
 				else
 				{
-					if (!shader->attachObject("lighting/lightFullbrightF.glsl"))
+                    if (!shader->attachFragmentObject("lighting/lightFullbrightF.glsl"))
 					{
 						return FALSE;
 					}
@@ -435,14 +493,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		{
 			if (features->disableTextureIndex)
 			{
-				if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightShinyWaterNonIndexedF.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			else 
 			{
-				if (!shader->attachObject("lighting/lightShinyWaterF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightShinyWaterF.glsl"))
 				{
 					return FALSE;
 				}
@@ -454,14 +512,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 		{
 			if (features->disableTextureIndex)
 			{
-				if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightShinyNonIndexedF.glsl"))
 				{
 					return FALSE;
 				}
 			}
 			else 
 			{
-				if (!shader->attachObject("lighting/lightShinyF.glsl"))
+                if (!shader->attachFragmentObject("lighting/lightShinyF.glsl"))
 				{
 					return FALSE;
 				}
@@ -472,14 +530,14 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 
 	if (features->mIndexedTextureChannels <= 1)
 	{
-		if (!shader->attachObject("objects/nonindexedTextureV.glsl"))
+		if (!shader->attachVertexObject("objects/nonindexedTextureV.glsl"))
 		{
 			return FALSE;
 		}
 	}
 	else
 	{
-		if (!shader->attachObject("objects/indexedTextureV.glsl"))
+        if (!shader->attachVertexObject("objects/indexedTextureV.glsl"))
 		{
 			return FALSE;
 		}
@@ -509,31 +567,56 @@ static std::string get_object_log(GLhandleARB ret)
 	return res;
 }
 
+//dump shader source for debugging
+void LLShaderMgr::dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text)
+{
+	char num_str[16]; // U32 = max 10 digits
+
+	LL_SHADER_LOADING_WARNS() << "\n";
+
+	for (U32 i = 0; i < shader_code_count; i++)
+	{
+		snprintf(num_str, sizeof(num_str), "%4d: ", i+1);
+		std::string line_number(num_str);
+		LL_CONT << line_number << shader_code_text[i];
+	}
+    LL_CONT << LL_ENDL;
+}
+
 void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string& filename) 
 {
 	std::string log = get_object_log(ret);
+    std::string fname = filename;
+    if (filename.empty())
+    {
+        fname = "unknown shader file";
+    }
 
-	if (log.length() > 0 || warns)
+	if (log.length() > 0)
 	{
-        LL_DEBUGS("ShaderLoading") << "Shader loading ";
-        
-		if (!filename.empty())
-		{
-            LL_CONT << "From " << filename << ":\n";
-		}
-        LL_CONT << log << LL_ENDL;
+        LL_SHADER_LOADING_WARNS() << "Shader loading from " << fname << LL_ENDL;
+        LL_SHADER_LOADING_WARNS() << "\n" << log << LL_ENDL;
 	}
  }
 
 GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
 {
+
+// endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl)
+#if LL_DARWIN
+    if (defines)
+    {
+        (*defines)["OLD_SELECT"] = "1";
+    }
+#endif
+
 	GLenum error = GL_NO_ERROR;
 	if (gDebugGL)
 	{
 		error = glGetError();
 		if (error != GL_NO_ERROR)
 		{
-			LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL;
+			LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL;
 		}
 	}
 	
@@ -549,6 +632,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 	S32 try_gpu_class = shader_level;
 	S32 gpu_class;
 
+    std::string open_file_name;
 	//find the most relevant file
 	for (gpu_class = try_gpu_class; gpu_class > 0; gpu_class--)
 	{	//search from the current gpu class down to class 1 to find the most relevant shader
@@ -556,18 +640,33 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		fname << getShaderDirPrefix();
 		fname << gpu_class << "/" << filename;
 		
- 		
-		file = LLFile::fopen(fname.str(), "r");		/* Flawfinder: ignore */
+        open_file_name = fname.str();
+
+        /*
+        Would be awesome, if we didn't have shaders that re-use files
+        with different environments to say, add skinning, etc
+        can't depend on cached version to have evaluate ifdefs identically...
+        if we can define a deterministic hash for the shader based on
+        all the inputs, maybe we can save some time here.
+        if (mShaderObjects.count(filename) > 0)
+        {
+            return mShaderObjects[filename];
+        }
+
+        */
+
+ 		LL_DEBUGS("ShaderLoading") << "Looking in " << open_file_name << LL_ENDL;
+		file = LLFile::fopen(open_file_name, "r");		/* Flawfinder: ignore */
 		if (file)
 		{
-			LL_DEBUGS("ShaderLoading") << "Loading file: shaders/class" << gpu_class << "/" << filename << " (Want class " << gpu_class << ")" << LL_ENDL;
+			LL_DEBUGS("ShaderLoading") << "Loading file: " << open_file_name << " (Want class " << gpu_class << ")" << LL_ENDL;            
 			break; // done
 		}
 	}
 	
 	if (file == NULL)
 	{
-		LL_WARNS("ShaderLoading") << "GLSL Shader file not found: " << filename << LL_ENDL;
+		LL_SHADER_LOADING_WARNS() << "GLSL Shader file not found: " << open_file_name << LL_ENDL;
 		return 0;
 	}
 
@@ -612,7 +711,31 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 	}
 	else
 	{  
-		if (major_version < 4)
+        if (major_version >= 4)
+        {
+            //set version to 400
+			shader_code_text[shader_code_count++] = strdup("#version 400\n");
+        }
+        else if (major_version == 3)
+        {
+            if (minor_version < 10)
+		    {
+			    shader_code_text[shader_code_count++] = strdup("#version 300\n");
+		    }
+		    else if (minor_version <= 19)
+		    {
+			    shader_code_text[shader_code_count++] = strdup("#version 310\n");
+		    }
+		    else if (minor_version <= 29)
+		    {
+			    shader_code_text[shader_code_count++] = strdup("#version 320\n");
+		    }
+            else
+            {
+                shader_code_text[shader_code_count++] = strdup("#version 330\n");
+            }
+        }
+		else
 		{
 			//set version to 1.30
 			shader_code_text[shader_code_count++] = strdup("#version 130\n");
@@ -620,10 +743,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 			extra_code_text[extra_code_count++] = strdup("precision mediump int;\n");
 			extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
 		}
-		else
-		{ //set version to 400
-			shader_code_text[shader_code_count++] = strdup("#version 400\n");
-		}
 
 		extra_code_text[extra_code_count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n");
 		extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
@@ -646,7 +765,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		extra_code_text[extra_code_count++] = strdup("#define texture2D texture\n");
 		extra_code_text[extra_code_count++] = strdup("#define textureCube texture\n");
 		extra_code_text[extra_code_count++] = strdup("#define texture2DLod textureLod\n");
-		extra_code_text[extra_code_count++] = strdup("#define	shadow2D(a,b) vec2(texture(a,b))\n");
+		extra_code_text[extra_code_count++] = strdup("#define shadow2D(a,b) vec2(texture(a,b))\n");
 		
 		if (major_version > 1 || minor_version >= 40)
 		{ //GLSL 1.40 replaces texture2DRect et al with texture
@@ -704,7 +823,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		}
 		*/
 
-		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP 1\n");
+		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP\n");
 
 		//uniform declartion
 		for (S32 i = 0; i < texture_index_channels; ++i)
@@ -763,11 +882,6 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 			LL_ERRS() << "Indexed texture rendering requires GLSL 1.30 or later." << LL_ENDL;
 		}
 	}
-	else
-	{
-		extra_code_text[extra_code_count++] = strdup("#define HAS_DIFFUSE_LOOKUP 0\n");
-	}
-
     
 	//copy file into memory
 	enum {
@@ -897,38 +1011,8 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 			{
 				//an error occured, print log
 				LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
-				dumpObjectLog(ret, TRUE, filename);
-#if LL_WINDOWS
-				std::stringstream ostr;
-				//dump shader source for debugging
-				for (GLuint i = 0; i < shader_code_count; i++)
-				{
-					ostr << i << ": " << shader_code_text[i];
-
-					if (i % 128 == 0)
-					{ //dump every 128 lines
-
-						LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL;
-						ostr = std::stringstream();
-					}
-
-				}
-
-				LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL;
-#else
-				std::string str;
-				
-				for (GLuint i = 0; i < shader_code_count; i++) {
-					str.append(shader_code_text[i]);
-					
-					if (i % 128 == 0)
-					{
-						LL_WARNS("ShaderLoading") << str << LL_ENDL;
-						str = "";
-					}
-				}
-#endif
-
+				dumpObjectLog(ret, TRUE, open_file_name);
+                dumpShaderSource(shader_code_count, shader_code_text);
 				ret = 0;
 			}
 		}
@@ -949,7 +1033,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 	if (ret)
 	{
 		// Add shader file to map
-		mShaderObjects[filename] = ret;
+        if (type == GL_VERTEX_SHADER_ARB) {
+            mVertexShaderObjects[filename] = ret;
+        }
+        else if (type == GL_FRAGMENT_SHADER_ARB) {
+            mFragmentShaderObjects[filename] = ret;
+        }
 		shader_level = try_gpu_class;
 	}
 	else
@@ -957,7 +1046,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 		if (shader_level > 1)
 		{
 			shader_level--;
-			return loadShaderFile(filename,shader_level,type, defines, texture_index_channels);
+			return loadShaderFile(filename, shader_level, type, defines, texture_index_channels);
 		}
 		LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL;	
 	}
@@ -973,7 +1062,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
 	if (!suppress_errors && success == GL_FALSE) 
 	{
 		//an error occured, print log
-		LL_WARNS("ShaderLoading") << "GLSL Linker Error:" << LL_ENDL;
+		LL_SHADER_LOADING_WARNS() << "GLSL Linker Error:" << LL_ENDL;
 	}
 
 #if LL_DARWIN
@@ -1006,7 +1095,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
 		CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fragmentGPUProcessing);
 		if (!fragmentGPUProcessing || !vertexGPUProcessing)
 		{
-			LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
+			LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;
 			success = GL_FALSE;
 			suppress_errors = FALSE;		
 		}
@@ -1017,7 +1106,7 @@ BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors)
 	LLStringUtil::toLower(log);
 	if (log.find("software") != std::string::npos)
 	{
-		LL_WARNS("ShaderLoading") << "GLSL Linker: Running in Software:" << LL_ENDL;
+		LL_SHADER_LOADING_WARNS() << "GLSL Linker: Running in Software:" << LL_ENDL;
 		success = GL_FALSE;
 		suppress_errors = FALSE;
 	}
@@ -1033,7 +1122,7 @@ BOOL LLShaderMgr::validateProgramObject(GLhandleARB obj)
 	glGetObjectParameterivARB(obj, GL_OBJECT_VALIDATE_STATUS_ARB, &success);
 	if (success == GL_FALSE)
 	{
-		LL_WARNS("ShaderLoading") << "GLSL program not valid: " << LL_ENDL;
+		LL_SHADER_LOADING_WARNS() << "GLSL program not valid: " << LL_ENDL;
 		dumpObjectLog(obj);
 	}
 	else
@@ -1067,6 +1156,7 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("projection_matrix");
 	mReservedUniforms.push_back("inv_proj");
 	mReservedUniforms.push_back("modelview_projection_matrix");
+    mReservedUniforms.push_back("inv_modelview");
 	mReservedUniforms.push_back("normal_matrix");
 	mReservedUniforms.push_back("texture_matrix0");
 	mReservedUniforms.push_back("texture_matrix1");
@@ -1109,14 +1199,17 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("color");
 		
 	mReservedUniforms.push_back("diffuseMap");
+    mReservedUniforms.push_back("altDiffuseMap");
 	mReservedUniforms.push_back("specularMap");
 	mReservedUniforms.push_back("bumpMap");
+    mReservedUniforms.push_back("bumpMap2");
 	mReservedUniforms.push_back("environmentMap");
-	mReservedUniforms.push_back("cloude_noise_texture");
+	mReservedUniforms.push_back("cloud_noise_texture");
+    mReservedUniforms.push_back("cloud_noise_texture_next");
 	mReservedUniforms.push_back("fullbright");
 	mReservedUniforms.push_back("lightnorm");
-	mReservedUniforms.push_back("sunlight_color_copy");
-	mReservedUniforms.push_back("ambient");
+	mReservedUniforms.push_back("sunlight_color");
+	mReservedUniforms.push_back("ambient_color");
 	mReservedUniforms.push_back("blue_horizon");
 	mReservedUniforms.push_back("blue_density");
 	mReservedUniforms.push_back("haze_horizon");
@@ -1175,6 +1268,7 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("spot_shadow_bias");
 	mReservedUniforms.push_back("spot_shadow_offset");
 	mReservedUniforms.push_back("sun_dir");
+    mReservedUniforms.push_back("moon_dir");
 	mReservedUniforms.push_back("shadow_res");
 	mReservedUniforms.push_back("proj_shadow_res");
 	mReservedUniforms.push_back("depth_cutoff");
@@ -1217,8 +1311,6 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("bloomMap");
 	mReservedUniforms.push_back("projectionMap");
 	mReservedUniforms.push_back("norm_mat");
-
-	mReservedUniforms.push_back("global_gamma");
 	mReservedUniforms.push_back("texture_gamma");
 	
 	mReservedUniforms.push_back("specular_color");
@@ -1232,8 +1324,8 @@ void LLShaderMgr::initAttribsAndUniforms()
 	mReservedUniforms.push_back("refTex");
 	mReservedUniforms.push_back("eyeVec");
 	mReservedUniforms.push_back("time");
-	mReservedUniforms.push_back("d1");
-	mReservedUniforms.push_back("d2");
+	mReservedUniforms.push_back("waveDir1");
+	mReservedUniforms.push_back("waveDir2");
 	mReservedUniforms.push_back("lightDir");
 	mReservedUniforms.push_back("specular");
 	mReservedUniforms.push_back("lightExp");
@@ -1265,6 +1357,34 @@ void LLShaderMgr::initAttribsAndUniforms()
 
 	mReservedUniforms.push_back("origin");
 	mReservedUniforms.push_back("display_gamma");
+
+    mReservedUniforms.push_back("inscatter");
+    mReservedUniforms.push_back("sun_size");
+    mReservedUniforms.push_back("fog_color");
+
+    mReservedUniforms.push_back("transmittance_texture");
+    mReservedUniforms.push_back("scattering_texture");
+    mReservedUniforms.push_back("single_mie_scattering_texture");
+    mReservedUniforms.push_back("irradiance_texture");
+    mReservedUniforms.push_back("blend_factor");
+    mReservedUniforms.push_back("no_atmo");
+    mReservedUniforms.push_back("moisture_level");
+    mReservedUniforms.push_back("droplet_radius");
+    mReservedUniforms.push_back("ice_level");
+    mReservedUniforms.push_back("rainbow_map");
+    mReservedUniforms.push_back("halo_map");
+    mReservedUniforms.push_back("moon_brightness");
+    mReservedUniforms.push_back("cloud_variance");
+
+    mReservedUniforms.push_back("sh_input_r");
+    mReservedUniforms.push_back("sh_input_g");
+    mReservedUniforms.push_back("sh_input_b");
+
+    mReservedUniforms.push_back("sun_moon_glow_factor");
+    mReservedUniforms.push_back("water_edge");
+    mReservedUniforms.push_back("sun_up_factor");
+    mReservedUniforms.push_back("moonlight_color");
+
 	llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
 
 	std::set<std::string> dupe_check;
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 394b38f832329964798deee031671f4b6d715fa2..127b5ce5b6875785a1de467a27fbf2bbc3724b90 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -42,6 +42,7 @@ class LLShaderMgr
 		PROJECTION_MATRIX,
 		INVERSE_PROJECTION_MATRIX,
 		MODELVIEW_PROJECTION_MATRIX,
+        INVERSE_MODELVIEW_MATRIX,
 		NORMAL_MATRIX,
 		TEXTURE_MATRIX0,
 		TEXTURE_MATRIX1,
@@ -73,10 +74,13 @@ class LLShaderMgr
 		PROJECTOR_AMBIENT_LOD,
 		DIFFUSE_COLOR,
 		DIFFUSE_MAP,
+        ALTERNATE_DIFFUSE_MAP,
 		SPECULAR_MAP,
 		BUMP_MAP,
+        BUMP_MAP2,
 		ENVIRONMENT_MAP,
 		CLOUD_NOISE_MAP,
+        CLOUD_NOISE_MAP_NEXT,
 		FULLBRIGHT,
 		LIGHTNORM,
 		SUNLIGHT_COLOR,
@@ -131,6 +135,7 @@ class LLShaderMgr
 		DEFERRED_SPOT_SHADOW_BIAS,
 		DEFERRED_SPOT_SHADOW_OFFSET,
 		DEFERRED_SUN_DIR,
+        DEFERRED_MOON_DIR,
 		DEFERRED_SHADOW_RES,
 		DEFERRED_PROJ_SHADOW_RES,
 		DEFERRED_DEPTH_CUTOFF,
@@ -168,10 +173,7 @@ class LLShaderMgr
 		DEFERRED_BLOOM,
 		DEFERRED_PROJECTION,
 		DEFERRED_NORM_MATRIX,
-
-		GLOBAL_GAMMA,
-		TEXTURE_GAMMA,
-		
+		TEXTURE_GAMMA,		
 		SPECULAR_COLOR,
 		ENVIRONMENT_INTENSITY,
 		
@@ -215,7 +217,38 @@ class LLShaderMgr
 		TERRAIN_ALPHARAMP,
 		
 		SHINY_ORIGIN,
-DISPLAY_GAMMA,
+        DISPLAY_GAMMA,
+
+        INSCATTER_RT,
+        SUN_SIZE,
+        FOG_COLOR,
+
+        // precomputed textures
+        TRANSMITTANCE_TEX,
+        SCATTER_TEX,
+        SINGLE_MIE_SCATTER_TEX,
+        ILLUMINANCE_TEX,
+        BLEND_FACTOR,
+
+        NO_ATMO,
+        MOISTURE_LEVEL,
+        DROPLET_RADIUS,
+        ICE_LEVEL,
+        RAINBOW_MAP,
+        HALO_MAP,
+
+        MOON_BRIGHTNESS,
+
+        CLOUD_VARIANCE,
+
+        SH_INPUT_L1R,
+        SH_INPUT_L1G,
+        SH_INPUT_L1B,
+
+        SUN_MOON_GLOW_FACTOR,
+        WATER_EDGE_FACTOR,
+        SUN_UP_FACTOR,
+        MOONLIGHT_COLOR,
 		END_RESERVED_UNIFORMS
 	} eGLSLReservedUniforms;
 
@@ -226,6 +259,7 @@ DISPLAY_GAMMA,
 
 	BOOL attachShaderFeatures(LLGLSLShader * shader);
 	void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE, const std::string& filename = "");
+    void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text);
 	BOOL	linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
 	BOOL	validateProgramObject(GLhandleARB obj);
 	GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
@@ -238,7 +272,8 @@ DISPLAY_GAMMA,
 
 public:
 	// Map of shader names to compiled
-	std::map<std::string, GLhandleARB> mShaderObjects;
+    std::map<std::string, GLhandleARB> mVertexShaderObjects;
+    std::map<std::string, GLhandleARB> mFragmentShaderObjects;
 
 	//global (reserved slot) shader parameters
 	std::vector<std::string> mReservedAttribs;
diff --git a/indra/llrender/lltexture.cpp b/indra/llrender/lltexture.cpp
index 90fbcec2bedaad01b3ee84d258c13707fcb4021d..6eef36216c1926380ebbe45c3ceacddc44d1cc36 100644
--- a/indra/llrender/lltexture.cpp
+++ b/indra/llrender/lltexture.cpp
@@ -29,3 +29,15 @@
 LLTexture::~LLTexture()
 {
 }
+
+S8   LLTexture::getType() const { llassert(false); return 0; }
+void LLTexture::setKnownDrawSize(S32 width, S32 height) { llassert(false); }
+bool LLTexture::bindDefaultImage(const S32 stage) { llassert(false); return false; }
+bool LLTexture::bindDebugImage(const S32 stage) { llassert(false); return false; }
+void LLTexture::forceImmediateUpdate() { llassert(false); }
+void LLTexture::setActive() { llassert(false);  }
+S32	 LLTexture::getWidth(S32 discard_level) const { llassert(false); return 0; }
+S32	 LLTexture::getHeight(S32 discard_level) const { llassert(false); return 0; }
+bool LLTexture::isActiveFetching() { llassert(false); return false; }
+LLImageGL* LLTexture::getGLTexture() const { llassert(false); return nullptr; }
+void LLTexture::updateBindStatsForTester() { }
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index 9fca8b8cd3a1544e2b05c9fd8c8a2282e082c1d6..41481fb8a722d23fd06e999ee9a9c7493ea02e59 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -58,21 +58,21 @@ class LLTexture : public virtual LLRefCount, public LLTrace::MemTrackable<LLText
 	//
 	//interfaces to access LLGLTexture
 	//
-	virtual S8         getType() const = 0 ;
-	virtual void       setKnownDrawSize(S32 width, S32 height) = 0 ;
-	virtual bool       bindDefaultImage(const S32 stage = 0) = 0 ;
-	virtual bool       bindDebugImage(const S32 stage = 0) = 0;
-	virtual void       forceImmediateUpdate() = 0 ;
-	virtual void       setActive() = 0 ;
-	virtual S32	       getWidth(S32 discard_level = -1) const = 0 ;
-	virtual S32	       getHeight(S32 discard_level = -1) const = 0 ;
-	virtual bool       isActiveFetching() = 0;
+	virtual S8         getType() const;
+	virtual void       setKnownDrawSize(S32 width, S32 height);
+	virtual bool       bindDefaultImage(const S32 stage = 0);
+	virtual bool       bindDebugImage(const S32 stage = 0);
+	virtual void       forceImmediateUpdate();
+	virtual void       setActive();
+	virtual S32	       getWidth(S32 discard_level = -1) const;
+	virtual S32	       getHeight(S32 discard_level = -1) const;
+	virtual bool       isActiveFetching();
 
 private:
 	//note: do not make this function public.
-	virtual LLImageGL* getGLTexture() const = 0 ;
+	virtual LLImageGL* getGLTexture() const;
 
-	virtual void updateBindStatsForTester() = 0 ;
+	virtual void updateBindStatsForTester();
 };
 #endif
 
diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp
index c8337feabbc69e8fd985ebea177b0925c522104f..424672fe8eceed6ea6bd35c23d982ddc7f2633c2 100644
--- a/indra/llrender/lluiimage.cpp
+++ b/indra/llrender/lluiimage.cpp
@@ -31,7 +31,6 @@
 
 // Project includes
 #include "lluiimage.h"
-#include "llrender2dutils.h"
 
 LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
 :	mName(name),
@@ -39,67 +38,29 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
 	mScaleRegion(0.f, 1.f, 1.f, 0.f),
 	mClipRegion(0.f, 1.f, 1.f, 0.f),
 	mImageLoaded(NULL),
-	mScaleStyle(SCALE_INNER)
-{}
+	mScaleStyle(SCALE_INNER),
+    mCachedW(-1),
+    mCachedH(-1)
+{
+    getTextureWidth();
+    getTextureHeight();
+}
 
 LLUIImage::~LLUIImage()
 {
 	delete mImageLoaded;
 }
 
-void LLUIImage::setClipRegion(const LLRectf& region) 
+S32 LLUIImage::getWidth() const
 { 
-	mClipRegion = region; 
+	// return clipped dimensions of actual image area
+	return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth()); 
 }
 
-void LLUIImage::setScaleRegion(const LLRectf& region) 
+S32 LLUIImage::getHeight() const
 { 
-	mScaleRegion = region; 
-}
-
-void LLUIImage::setScaleStyle(LLUIImage::EScaleStyle style)
-{
-	mScaleStyle = style;
-}
-
-//TODO: move drawing implementation inside class
-void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
-{
-	draw(x, y, getWidth(), getHeight(), color);
-}
-
-void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
-	gl_draw_scaled_image_with_border(
-		x, y, 
-		width, height, 
-		mImage, 
-		color,
-		FALSE,
-		mClipRegion,
-		mScaleRegion,
-		mScaleStyle == SCALE_INNER);
-}
-
-void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
-{
-	gl_draw_scaled_image_with_border(
-		x, y, 
-		width, height, 
-		mImage, 
-		color, 
-		TRUE,
-		mClipRegion,
-		mScaleRegion,
-		mScaleStyle == SCALE_INNER);
-}
-
-void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
-{
-	LLRect border_rect;
-	border_rect.setOriginAndSize(x, y, width, height);
-	border_rect.stretch(border_width, border_width);
-	drawSolid(border_rect, color);
+	// return clipped dimensions of actual image area
+	return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight()); 
 }
 
 void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, 
@@ -145,28 +106,7 @@ void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, c
 	} LLRender2D::getInstance()->popMatrix();
 }
 
-
-S32 LLUIImage::getWidth() const
-{ 
-	// return clipped dimensions of actual image area
-	return ll_round((F32)mImage->getWidth(0) * mClipRegion.getWidth()); 
-}
-
-S32 LLUIImage::getHeight() const
-{ 
-	// return clipped dimensions of actual image area
-	return ll_round((F32)mImage->getHeight(0) * mClipRegion.getHeight()); 
-}
-
-S32 LLUIImage::getTextureWidth() const
-{
-	return mImage->getWidth(0);
-}
-
-S32 LLUIImage::getTextureHeight() const
-{
-	return mImage->getHeight(0);
-}
+//#include "lluiimage.inl"
 
 boost::signals2::connection LLUIImage::addLoadedCallback( const image_loaded_signal_t::slot_type& cb ) 
 {
@@ -186,7 +126,6 @@ void LLUIImage::onImageLoaded()
 	}
 }
 
-
 namespace LLInitParam
 {
 	void ParamValue<LLUIImage*>::updateValueFromBlock()
diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h
index 6f47385eb0fc34b515c7147872d4cbebb2a63bf6..e462e19004b39e23c945da313069df9d36e5144d 100644
--- a/indra/llrender/lluiimage.h
+++ b/indra/llrender/lluiimage.h
@@ -36,6 +36,7 @@
 #include <boost/signals2.hpp>
 #include "llinitparam.h"
 #include "lltexture.h"
+#include "llrender2dutils.h"
 
 extern const LLColor4 UI_VERTEX_COLOR;
 
@@ -53,35 +54,46 @@ class LLUIImage : public LLRefCount
 	LLUIImage(const std::string& name, LLPointer<LLTexture> image);
 	virtual ~LLUIImage();
 
-	void setClipRegion(const LLRectf& region);
-	void setScaleRegion(const LLRectf& region);
-	void setScaleStyle(EScaleStyle style);
+	LL_FORCE_INLINE void setClipRegion(const LLRectf& region)
+    { 
+	    mClipRegion = region; 
+    }
 
-	LLPointer<LLTexture> getImage() { return mImage; }
-	const LLPointer<LLTexture>& getImage() const { return mImage; }
+	LL_FORCE_INLINE void setScaleRegion(const LLRectf& region)
+    { 
+	    mScaleRegion = region; 
+    }
 
-	void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
-	void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
-	void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+	LL_FORCE_INLINE void setScaleStyle(EScaleStyle style)
+    {
+	    mScaleStyle = style;
+    }
+
+	LL_FORCE_INLINE LLPointer<LLTexture> getImage() { return mImage; }
+	LL_FORCE_INLINE const LLPointer<LLTexture>& getImage() const { return mImage; }
+
+	LL_FORCE_INLINE void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const;
+	LL_FORCE_INLINE void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const;
+	LL_FORCE_INLINE void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
 	
-	void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
-	void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
-	void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
+	LL_FORCE_INLINE void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const;
+	LL_FORCE_INLINE void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); }
+	LL_FORCE_INLINE void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, getWidth(), getHeight(), color); }
 
-	void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
-	void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
-	void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
+	LL_FORCE_INLINE void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const;
+	LL_FORCE_INLINE void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); }
+	LL_FORCE_INLINE void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); }
 
 	void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color);
 
-	const std::string& getName() const { return mName; }
+	LL_FORCE_INLINE const std::string& getName() const { return mName; }
 
 	virtual S32 getWidth() const;
 	virtual S32 getHeight() const;
 
 	// returns dimensions of underlying textures, which might not be equal to ui image portion
-	S32 getTextureWidth() const;
-	S32 getTextureHeight() const;
+	LL_FORCE_INLINE S32 getTextureWidth() const;
+	LL_FORCE_INLINE S32 getTextureHeight() const;
 
 	boost::signals2::connection addLoadedCallback( const image_loaded_signal_t::slot_type& cb );
 
@@ -95,8 +107,12 @@ class LLUIImage : public LLRefCount
 	LLRectf					mClipRegion;
 	LLPointer<LLTexture>	mImage;
 	EScaleStyle				mScaleStyle;
+    mutable S32             mCachedW;
+    mutable S32             mCachedH;
 };
 
+#include "lluiimage.inl"
+
 namespace LLInitParam
 {
 	template<>
diff --git a/indra/llrender/lluiimage.inl b/indra/llrender/lluiimage.inl
new file mode 100644
index 0000000000000000000000000000000000000000..f5227556f0b95c61da04f83b6a327e401e6bb3e0
--- /dev/null
+++ b/indra/llrender/lluiimage.inl
@@ -0,0 +1,77 @@
+/** 
+ * @file lluiimage.inl
+ * @brief UI inline func implementation
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const
+{
+	draw(x, y, getWidth(), getHeight(), color);
+}
+
+void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+	gl_draw_scaled_image_with_border(
+		x, y, 
+		width, height, 
+		mImage, 
+		color,
+		FALSE,
+		mClipRegion,
+		mScaleRegion,
+		mScaleStyle == SCALE_INNER);
+}
+
+void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const
+{
+	gl_draw_scaled_image_with_border(
+		x, y, 
+		width, height, 
+		mImage, 
+		color, 
+		TRUE,
+		mClipRegion,
+		mScaleRegion,
+		mScaleStyle == SCALE_INNER);
+}
+
+void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const
+{
+	LLRect border_rect;
+	border_rect.setOriginAndSize(x, y, width, height);
+	border_rect.stretch(border_width, border_width);
+	drawSolid(border_rect, color);
+}
+
+// returns dimensions of underlying textures, which might not be equal to ui image portion
+S32 LLUIImage::getTextureWidth() const
+{
+    mCachedW = (mCachedW == -1) ? getWidth() : mCachedW;
+    return mCachedW;
+}
+
+S32 LLUIImage::getTextureHeight() const
+{
+    mCachedH = (mCachedH == -1) ? getHeight() : mCachedH;
+    return mCachedH;
+}
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 1312f6afda3f3e8bee997d70d10614d6215a6384..94a04d4ddb52927a95a54e065773b2e65582c789 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -660,6 +660,9 @@ void LLVertexBuffer::drawElements(U32 mode, const LLVector4a* pos, const LLVecto
 
 void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_offset) const
 {
+    llassert(start < (U32)mNumVerts);
+    llassert(end < (U32)mNumVerts);
+
 	if (start >= (U32) mNumVerts ||
 	    end >= (U32) mNumVerts)
 	{
@@ -679,6 +682,9 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
 		U16* idx = ((U16*) getIndicesPointer())+indices_offset;
 		for (U32 i = 0; i < count; ++i)
 		{
+            llassert(idx[i] >= start);
+            llassert(idx[i] <= end);
+
 			if (idx[i] < start || idx[i] > end)
 			{
 				LL_ERRS() << "Index out of range: " << idx[i] << " not in [" << start << ", " << end << "]" << LL_ENDL;
@@ -697,6 +703,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of
 			for (U32 i = start; i < end; i++)
 			{
 				S32 idx = (S32) (v[i][3]+0.25f);
+                llassert(idx >= 0);
 				if (idx < 0 || idx >= shader->mFeatures.mIndexedTextureChannels)
 				{
 					LL_ERRS() << "Bad texture index found in vertex data stream." << LL_ENDL;
@@ -942,15 +949,15 @@ S32 LLVertexBuffer::determineUsage(S32 usage)
 	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
 		if (ret_usage != GL_DYNAMIC_COPY_ARB)
 		{
-		if (sDisableVBOMapping)
-		{ //always use stream draw if VBO mapping is disabled
-			ret_usage = GL_STREAM_DRAW_ARB;
-		}
-		else
-		{
-			ret_usage = GL_DYNAMIC_DRAW_ARB;
-		}
-	}
+		    if (sDisableVBOMapping)
+		    { //always use stream draw if VBO mapping is disabled
+			    ret_usage = GL_STREAM_DRAW_ARB;
+		    }
+		    else
+		    {
+			    ret_usage = GL_DYNAMIC_DRAW_ARB;
+		    }
+	    }
 	}
 	
 	return ret_usage;
@@ -1506,10 +1513,10 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
 	llassert(newnverts >= 0);
 	llassert(newnindices >= 0);
 
-	bool sucsess = true;
+	bool success = true;
 
-	sucsess &= updateNumVerts(newnverts);		
-	sucsess &= updateNumIndices(newnindices);
+	success &= updateNumVerts(newnverts);		
+	success &= updateNumIndices(newnindices);
 	
 	if (useVBOs())
 	{
@@ -1521,7 +1528,7 @@ bool LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)
 		}
 	}
 
-	return sucsess;
+	return success;
 }
 
 bool LLVertexBuffer::useVBOs() const
@@ -2319,34 +2326,35 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
 			{
 				
 				U32 unsatisfied_mask = (required_mask & ~data_mask);
-				U32 i = 0;
 
-				while (i < TYPE_MAX)
-				{
+                for (U32 i = 0; i < TYPE_MAX; i++)
+                {
                     U32 unsatisfied_flag = unsatisfied_mask & (1 << i);
-					switch (unsatisfied_flag)
-					{
-						case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break;
-						case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break;
-						case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break;
-						case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break;
-						case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break;
-						case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break;
-						case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break;
-						case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break;
-						case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break;
-						case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break;
-						case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break;
-						case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break;
-						case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break;
-						default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL;
-					}					
-				}
-
-            if (unsatisfied_mask & (1 << TYPE_INDEX))
-            {
-               LL_INFOS() << "Missing indices" << LL_ENDL;
-            }
+                    switch (unsatisfied_flag)
+                    {
+                        case 0: break;
+                        case MAP_VERTEX: LL_INFOS() << "Missing vert pos" << LL_ENDL; break;
+                        case MAP_NORMAL: LL_INFOS() << "Missing normals" << LL_ENDL; break;
+                        case MAP_TEXCOORD0: LL_INFOS() << "Missing TC 0" << LL_ENDL; break;
+                        case MAP_TEXCOORD1: LL_INFOS() << "Missing TC 1" << LL_ENDL; break;
+                        case MAP_TEXCOORD2: LL_INFOS() << "Missing TC 2" << LL_ENDL; break;
+                        case MAP_TEXCOORD3: LL_INFOS() << "Missing TC 3" << LL_ENDL; break;
+                        case MAP_COLOR: LL_INFOS() << "Missing vert color" << LL_ENDL; break;
+                        case MAP_EMISSIVE: LL_INFOS() << "Missing emissive" << LL_ENDL; break;
+                        case MAP_TANGENT: LL_INFOS() << "Missing tangent" << LL_ENDL; break;
+                        case MAP_WEIGHT: LL_INFOS() << "Missing weight" << LL_ENDL; break;
+                        case MAP_WEIGHT4: LL_INFOS() << "Missing weightx4" << LL_ENDL; break;
+                        case MAP_CLOTHWEIGHT: LL_INFOS() << "Missing clothweight" << LL_ENDL; break;
+                        case MAP_TEXTURE_INDEX: LL_INFOS() << "Missing tex index" << LL_ENDL; break;
+                        default: LL_INFOS() << "Missing who effin knows: " << unsatisfied_flag << LL_ENDL;
+                    }
+                }
+
+                // TYPE_INDEX is beyond TYPE_MAX, so check for it individually
+                if (unsatisfied_mask & (1 << TYPE_INDEX))
+                {
+                   LL_INFOS() << "Missing indices" << LL_ENDL;
+                }
 
 				LL_ERRS() << "Shader consumption mismatches data provision." << LL_ENDL;
 			}
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index c89d7e39580712809e80f5e56e57c4594277af8a..9867bd16d6394d6982271afdefc2527108cfa83d 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -179,8 +179,8 @@ class LLVertexBuffer : public LLRefCount, public LLTrace::MemTrackable<LLVertexB
 		TYPE_WEIGHT4,
 		TYPE_CLOTHWEIGHT,
 		TYPE_TEXTURE_INDEX,
-		TYPE_MAX,
-		TYPE_INDEX,		
+		TYPE_MAX,   // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
+		TYPE_INDEX,	// TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer	
 	};
 	enum {
 		MAP_VERTEX = (1<<TYPE_VERTEX),
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index e44f57fa9f4cacb61e29821bb96e0426a9655b35..730e277decfb6a1f64957241176dab8c7e8a1ecc 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -133,8 +133,10 @@ set(llui_SOURCE_FILES
     llview.cpp
     llviewquery.cpp
     llviewereventrecorder.cpp
+    llvirtualtrackball.cpp
     llwindowshade.cpp
     llxuiparser.cpp
+    llxyvector.cpp
     )
     
 set(llui_HEADER_FILES
@@ -250,8 +252,10 @@ set(llui_HEADER_FILES
     llview.h
     llviewereventrecorder.h
     llviewquery.h
+    llvirtualtrackball.h
     llwindowshade.h
     llxuiparser.h
+    llxyvector.h
     )
 
 set_source_files_properties(${llui_HEADER_FILES}
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 4d46e0f50a5c74776a2e8ef7f925c41c12cf6c6a..abb043f4282b84df2cd878da7e829900ee8fce11 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -36,6 +36,7 @@
 #include "lluictrlfactory.h"
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
+#include "llcriticaldamp.h" // LLSmoothInterpolation
 #include "lldir.h"
 #include "lldraghandle.h"
 #include "llfloaterreg.h"
@@ -63,6 +64,10 @@
 // use this to control "jumping" behavior when Ctrl-Tabbing
 const S32 TABBED_FLOATER_OFFSET = 0;
 
+const F32 LLFloater::CONTEXT_CONE_IN_ALPHA = 0.0f;
+const F32 LLFloater::CONTEXT_CONE_OUT_ALPHA = 1.f;
+const F32 LLFloater::CONTEXT_CONE_FADE_TIME = 0.08f;
+
 namespace LLInitParam
 {
 	void TypeValues<LLFloaterEnums::EOpenPositioning>::declareValues()
@@ -2115,6 +2120,70 @@ void LLFloater::updateTitleButtons()
 	}
 }
 
+void LLFloater::drawConeToOwner(F32 &context_cone_opacity,
+                                F32 max_cone_opacity,
+                                LLView *owner_view,
+                                F32 fade_time,
+                                F32 contex_cone_in_alpha,
+                                F32 contex_cone_out_alpha)
+{
+    if (owner_view
+        && owner_view->isInVisibleChain()
+        && hasFocus()
+        && context_cone_opacity > 0.001f
+        && gFocusMgr.childHasKeyboardFocus(this))
+    {
+        // draw cone of context pointing back to owner (e.x. texture swatch)
+        LLRect owner_rect;
+        owner_view->localRectToOtherView(owner_view->getLocalRect(), &owner_rect, this);
+        LLRect local_rect = getLocalRect();
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        LLGLEnable(GL_CULL_FACE);
+        gGL.begin(LLRender::QUADS);
+        {
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+            gGL.vertex2i(local_rect.mRight, local_rect.mTop);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+
+
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_out_alpha * context_cone_opacity);
+            gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
+            gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
+            gGL.color4f(0.f, 0.f, 0.f, contex_cone_in_alpha * context_cone_opacity);
+            gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
+            gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
+        }
+        gGL.end();
+    }
+
+    if (gFocusMgr.childHasMouseCapture(getDragHandle()))
+    {
+        context_cone_opacity = lerp(context_cone_opacity, max_cone_opacity, LLSmoothInterpolation::getInterpolant(fade_time));
+    }
+    else
+    {
+        context_cone_opacity = lerp(context_cone_opacity, 0.f, LLSmoothInterpolation::getInterpolant(fade_time));
+    }
+}
+
 void LLFloater::buildButtons(const Params& floater_params)
 {
 	static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 165f67499be11baeb175569e05c1c41e32599046..f8c04e8a2fc18c5e1a5d462c5edccfda12d2006c 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -395,6 +395,15 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
 
 	virtual void	updateTitleButtons();
 
+	// Draws a cone from this floater to parent floater or view (owner)
+	// Modifies context_cone_opacity (interpolates according to fade time and returns new value)
+	void			drawConeToOwner(F32 &context_cone_opacity,
+									F32 max_cone_opacity,
+									LLView *owner_view,
+									F32 context_fade_time = CONTEXT_CONE_FADE_TIME,
+									F32 contex_cone_in_alpha = CONTEXT_CONE_IN_ALPHA,
+									F32 contex_cone_out_alpha = CONTEXT_CONE_OUT_ALPHA);
+
 private:
 	void			setForeground(BOOL b);	// called only by floaterview
 	void			cleanupHandles(); // remove handles to dead floaters
@@ -424,6 +433,10 @@ class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
 	void			updateTransparency(LLView* view, ETypeTransparency transparency_type);
 
 public:
+	static const F32 CONTEXT_CONE_IN_ALPHA;
+	static const F32 CONTEXT_CONE_OUT_ALPHA;
+	static const F32 CONTEXT_CONE_FADE_TIME;
+
 	// Called when floater is opened, passes mKey
 	// Public so external views or floaters can watch for this floater opening
 	commit_signal_t mOpenSignal;
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index b05a9807d0801f8af5747d14fe07ea1d39e5aa8e..e718fcec46038d3306bd224f167490477bd94963 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -148,7 +148,9 @@ LLFolderView::Params::Params()
 :	title("title"),
 	use_label_suffix("use_label_suffix"),
 	allow_multiselect("allow_multiselect", true),
+	allow_drag("allow_drag", true),
 	show_empty_message("show_empty_message", true),
+	suppress_folder_menu("suppress_folder_menu", false),
 	use_ellipses("use_ellipses", false),
     options_menu("options_menu", "")
 {
@@ -162,11 +164,13 @@ LLFolderView::LLFolderView(const Params& p)
 	mScrollContainer( NULL ),
 	mPopupMenuHandle(),
 	mAllowMultiSelect(p.allow_multiselect),
+	mAllowDrag(p.allow_drag),
 	mShowEmptyMessage(p.show_empty_message),
 	mShowFolderHierarchy(FALSE),
 	mRenameItem( NULL ),
 	mNeedsScroll( FALSE ),
 	mUseLabelSuffix(p.use_label_suffix),
+	mSuppressFolderMenu(p.suppress_folder_menu),
 	mPinningSelectedItem(FALSE),
 	mNeedsAutoSelect( FALSE ),
 	mAutoSelectOverride(FALSE),
@@ -1432,10 +1436,13 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
 
 	BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
 	S32 count = mSelectedItems.size();
+
 	LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
-	if (   handled
+	bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected();
+	if ((handled
 		&& ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible
-		&& menu )
+		&& menu ) &&
+		!hide_folder_menu)
 	{
 		if (mCallbackRegistrar)
         {
@@ -1449,7 +1456,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask )
 		if (mCallbackRegistrar)
         {
 			mCallbackRegistrar->popScope();
-	}
+	    }
 	}
 	else
 	{
@@ -1862,6 +1869,20 @@ void LLFolderView::updateMenu()
 	}
 }
 
+bool LLFolderView::isFolderSelected()
+{
+	selected_items_t::iterator item_iter;
+	for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter)
+	{
+		LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(*item_iter);
+		if (folder != NULL)
+		{
+			return true;
+		}
+	}
+	return false;
+}
+
 bool LLFolderView::selectFirstItem()
 {
 	for (folders_t::iterator iter = mFolders.begin();
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 2926e160d02d595d63cd3c78db8d601279196fe7..6bb5e6c02e0d4a46f3c4260fb2583a4c960deafe 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -90,9 +90,11 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 		Optional<std::string>   title;
 		Optional<bool>			use_label_suffix,
 								allow_multiselect,
+								allow_drag,
 								show_empty_message,
 								use_ellipses,
-								show_item_link_overlays;
+								show_item_link_overlays,
+								suppress_folder_menu;
 		Mandatory<LLFolderViewModelInterface*>	view_model;
 		Optional<LLFolderViewGroupedItemModel*> grouped_item_model;
         Mandatory<std::string>   options_menu;
@@ -123,6 +125,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); }
 	
 	bool getAllowMultiSelect() { return mAllowMultiSelect; }
+	bool getAllowDrag() { return mAllowDrag; }
 
 	// Close all folders in the view
 	void closeAllFolders();
@@ -259,6 +262,8 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 
 	void closeRenamer( void );
 
+	bool isFolderSelected();
+
 	bool selectFirstItem();
 	bool selectLastItem();
 	
@@ -271,6 +276,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 	selected_items_t				mSelectedItems;
 	bool							mKeyboardSelection,
 									mAllowMultiSelect,
+									mAllowDrag,
 									mShowEmptyMessage,
 									mShowFolderHierarchy,
 									mNeedsScroll,
@@ -282,7 +288,8 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler
 									mDragAndDropThisFrame,
 									mShowItemLinkOverlays,
 									mShowSelectionContext,
-									mShowSingleSelection;
+									mShowSingleSelection,
+									mSuppressFolderMenu;
 
 	// Renaming variables and methods
 	LLFolderViewItem*				mRenameItem;  // The item currently being renamed
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 2de47f1a19152f0417b4b35f4ab6713ccaca55ec..9a1f7de73b7c1f0dc848440301c7784986ab0cff 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -557,6 +557,7 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask )
 			LLFolderView* root = getRoot();
 
 		if( (x - mDragStartX) * (x - mDragStartX) + (y - mDragStartY) * (y - mDragStartY) > drag_and_drop_threshold() * drag_and_drop_threshold() 
+			&& root->getAllowDrag()
 			&& root->getCurSelectedItem()
 			&& root->startDrag())
 		{
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 3ad504d68da3b88647774489ca83a45b83fbaae0..70304cdfd245e731b024c4f37fae8f2b667bc6b3 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -96,6 +96,8 @@ LLLineEditor::Params::Params()
 	ignore_tab("ignore_tab", true),
 	is_password("is_password", false),
 	cursor_color("cursor_color"),
+	use_bg_color("use_bg_color", false),
+	bg_color("bg_color"),
 	text_color("text_color"),
 	text_readonly_color("text_readonly_color"),
 	text_tentative_color("text_tentative_color"),
@@ -150,10 +152,12 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
 	mBgImageDisabled( p.background_image_disabled ),
 	mBgImageFocused( p.background_image_focused ),
 	mShowImageFocused( p.bg_image_always_focused ),
+	mUseBgColor(p.use_bg_color),
 	mHaveHistory(FALSE),
 	mReplaceNewlinesWithSpaces( TRUE ),
 	mLabel(p.label),
 	mCursorColor(p.cursor_color()),
+	mBgColor(p.bg_color()),
 	mFgColor(p.text_color()),
 	mReadOnlyFgColor(p.text_readonly_color()),
 	mTentativeFgColor(p.text_tentative_color()),
@@ -1688,37 +1692,42 @@ void LLLineEditor::doDelete()
 
 void LLLineEditor::drawBackground()
 {
-	bool has_focus = hasFocus();
-	LLUIImage* image;
-	if ( mReadOnly )
-	{
-		image = mBgImageDisabled;
-	}
-	else if ( has_focus || mShowImageFocused)
+	F32 alpha = getCurrentTransparency();
+	if (mUseBgColor)
 	{
-		image = mBgImageFocused;
+		gl_rect_2d(getLocalRect(), mBgColor % alpha, TRUE);
 	}
 	else
 	{
-		image = mBgImage;
-	}
-
-	if (!image) return;
-	
-	F32 alpha = getCurrentTransparency();
+		bool has_focus = hasFocus();
+		LLUIImage* image;
+		if (mReadOnly)
+		{
+			image = mBgImageDisabled;
+		}
+		else if (has_focus || mShowImageFocused)
+		{
+			image = mBgImageFocused;
+		}
+		else
+		{
+			image = mBgImage;
+		}
 
-	// optionally draw programmatic border
-	if (has_focus)
-	{
-		LLColor4 tmp_color = gFocusMgr.getFocusColor();
+		if (!image) return;
+		// optionally draw programmatic border
+		if (has_focus)
+		{
+			LLColor4 tmp_color = gFocusMgr.getFocusColor();
+			tmp_color.setAlpha(alpha);
+			image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
+				tmp_color,
+				gFocusMgr.getFocusFlashWidth());
+		}
+		LLColor4 tmp_color = UI_VERTEX_COLOR;
 		tmp_color.setAlpha(alpha);
-		image->drawBorder(0, 0, getRect().getWidth(), getRect().getHeight(),
-						  tmp_color,
-						  gFocusMgr.getFocusFlashWidth());
+		image->draw(getLocalRect(), tmp_color);
 	}
-	LLColor4 tmp_color = UI_VERTEX_COLOR;
-	tmp_color.setAlpha(alpha);
-	image->draw(getLocalRect(), tmp_color);
 }
 
 void LLLineEditor::draw()
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index f775d53e63d7bde62b66b8a530b5ceed949696a9..aa5779d45f64838e16cbc0fae86a3fab8e6ad1e2 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -91,10 +91,12 @@ class LLLineEditor
 										commit_on_focus_lost,
 										ignore_tab,
 										bg_image_always_focused,
-										is_password;
+										is_password,
+										use_bg_color;
 
 		// colors
 		Optional<LLUIColor>				cursor_color,
+										bg_color,
 										text_color,
 										text_readonly_color,
 										text_tentative_color,
@@ -368,6 +370,7 @@ class LLLineEditor
 	LLTimer		mTripleClickTimer;
 
 	LLUIColor	mCursorColor;
+	LLUIColor	mBgColor;
 	LLUIColor	mFgColor;
 	LLUIColor	mReadOnlyFgColor;
 	LLUIColor	mTentativeFgColor;
@@ -388,6 +391,8 @@ class LLLineEditor
 
 	BOOL 		mShowImageFocused;
 
+	bool		mUseBgColor;
+
 	LLWString	mPreeditWString;
 	LLWString	mPreeditOverwrittenWString;
 	std::vector<S32> mPreeditPositions;
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 732fa9feb1c103b2623142531049a6891e99fc9f..5568a844943737f7d8542875efd4d7c417f1445d 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -2723,6 +2723,15 @@ void LLMenuGL::setItemVisible( const std::string& name, BOOL visible )
 	}
 }
 
+
+void LLMenuGL::setItemLabel(const std::string &name, const std::string &label)
+{
+    LLMenuItemGL *item = getItem(name);
+
+    if (item)
+        item->setLabel(label);
+}
+
 void LLMenuGL::setItemLastSelected(LLMenuItemGL* item)
 {
 	if (getVisible())
@@ -2767,6 +2776,19 @@ LLMenuItemGL* LLMenuGL::getItem(S32 number)
 	return NULL;
 }
 
+LLMenuItemGL* LLMenuGL::getItem(std::string name)
+{
+    item_list_t::iterator item_iter;
+    for (item_iter = mItems.begin(); item_iter != mItems.end(); ++item_iter)
+    {
+        if ((*item_iter)->getName() == name)
+        {
+            return (*item_iter);
+        }
+    }
+    return NULL;
+}
+
 LLMenuItemGL* LLMenuGL::getHighlightedItem()
 {
 	item_list_t::iterator item_iter;
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 78f688642ea5d0a57b746b21811abe7c1a11b7ca..1f11f26192b232da83c956076dd8df1ed22b9ee4 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -468,6 +468,8 @@ class LLMenuGL
 	void setEnabledSubMenus(BOOL enable);
 
 	void setItemVisible( const std::string& name, BOOL visible);
+
+    void setItemLabel(const std::string &name, const std::string &label);
 	
 	// sets the left,bottom corner of menu, useful for popups
 	void setLeftAndBottom(S32 left, S32 bottom);
@@ -498,6 +500,7 @@ class LLMenuGL
 	void			setItemLastSelected(LLMenuItemGL* item);	// must be in menu
 	U32				getItemCount();				// number of menu items
 	LLMenuItemGL*	getItem(S32 number);		// 0 = first item
+    LLMenuItemGL*   getItem(std::string name);
 	LLMenuItemGL*	getHighlightedItem();				
 
 	LLMenuItemGL*	highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disabled = TRUE);
diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp
index 0aa3e170754edb943ec628f3b73d7b873f87d87d..acfe4a0cba7a287db76fb1d4e7cb0f5e5ae7b93b 100644
--- a/indra/llui/llmultislider.cpp
+++ b/indra/llui/llmultislider.cpp
@@ -54,13 +54,18 @@ LLMultiSlider::SliderParams::SliderParams()
 LLMultiSlider::Params::Params()
 :	max_sliders("max_sliders", 1),
 	allow_overlap("allow_overlap", false),
+	loop_overlap("loop_overlap", false),
+	orientation("orientation"),
+	overlap_threshold("overlap_threshold", 0),
 	draw_track("draw_track", true),
 	use_triangle("use_triangle", false),
 	track_color("track_color"),
 	thumb_disabled_color("thumb_disabled_color"),
+	thumb_highlight_color("thumb_highlight_color"),
 	thumb_outline_color("thumb_outline_color"),
 	thumb_center_color("thumb_center_color"),
 	thumb_center_selected_color("thumb_center_selected_color"),
+	thumb_image("thumb_image"),
 	triangle_color("triangle_color"),
 	mouse_down_callback("mouse_down_callback"),
 	mouse_up_callback("mouse_up_callback"),
@@ -71,9 +76,9 @@ LLMultiSlider::Params::Params()
 LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 :	LLF32UICtrl(p),
 	mMouseOffset( 0 ),
-	mDragStartThumbRect( 0, getRect().getHeight(), p.thumb_width, 0 ),
 	mMaxNumSliders(p.max_sliders),
 	mAllowOverlap(p.allow_overlap),
+	mLoopOverlap(p.loop_overlap),
 	mDrawTrack(p.draw_track),
 	mUseTriangle(p.use_triangle),
 	mTrackColor(p.track_color()),
@@ -83,12 +88,22 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 	mDisabledThumbColor(p.thumb_disabled_color()),
 	mTriangleColor(p.triangle_color()),
 	mThumbWidth(p.thumb_width),
+	mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL),
 	mMouseDownSignal(NULL),
 	mMouseUpSignal(NULL)
 {
 	mValue.emptyMap();
 	mCurSlider = LLStringUtil::null;
-	
+
+	if (mOrientation == HORIZONTAL)
+	{
+		mDragStartThumbRect = LLRect(0, getRect().getHeight(), p.thumb_width, 0);
+	}
+	else
+	{
+		mDragStartThumbRect = LLRect(0, p.thumb_width, getRect().getWidth(), 0);
+	}
+
 	if (p.mouse_down_callback.isProvided())
 	{
 		setMouseDownCallback(initCommitCallback(p.mouse_down_callback));
@@ -98,6 +113,15 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 		setMouseUpCallback(initCommitCallback(p.mouse_up_callback));
 	}
 
+	if (p.overlap_threshold.isProvided() && p.overlap_threshold > mIncrement)
+    {
+        mOverlapThreshold = p.overlap_threshold - mIncrement;
+    }
+    else
+    {
+        mOverlapThreshold = 0;
+    }
+
 	for (LLInitParam::ParamIterator<SliderParams>::const_iterator it = p.sliders.begin();
 		it != p.sliders.end();
 		++it)
@@ -111,6 +135,12 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p)
 			addSlider(it->value);
 		}
 	}
+
+	if (p.thumb_image.isProvided())
+	{
+		mThumbImagep = LLUI::getUIImage(p.thumb_image());
+	}
+	mThumbHighlightColor = p.thumb_highlight_color.isProvided() ? p.thumb_highlight_color() : static_cast<LLUIColor>(gFocusMgr.getFocusColor());
 }
 
 LLMultiSlider::~LLMultiSlider()
@@ -119,6 +149,16 @@ LLMultiSlider::~LLMultiSlider()
 	delete mMouseUpSignal;
 }
 
+F32 LLMultiSlider::getNearestIncrement(F32 value) const
+{
+    value = llclamp(value, mMinValue, mMaxValue);
+
+    // Round to nearest increment (bias towards rounding down)
+    value -= mMinValue;
+    value += mIncrement / 2.0001f;
+    value -= fmod(value, mIncrement);
+    return mMinValue + value;
+}
 
 void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from_event)
 {
@@ -127,13 +167,7 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from
 		return;
 	}
 
-	value = llclamp( value, mMinValue, mMaxValue );
-
-	// Round to nearest increment (bias towards rounding down)
-	value -= mMinValue;
-	value += mIncrement/2.0001f;
-	value -= fmod(value, mIncrement);
-	F32 newValue = mMinValue + value;
+    F32 newValue = getNearestIncrement(value);
 
 	// now, make sure no overlap
 	// if we want that
@@ -143,14 +177,40 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from
 		// look at the current spot
 		// and see if anything is there
 		LLSD::map_iterator mIt = mValue.beginMap();
-		for(;mIt != mValue.endMap(); mIt++) {
-			
-			F32 testVal = (F32)mIt->second.asReal() - newValue;
-			if(testVal > -FLOAT_THRESHOLD && testVal < FLOAT_THRESHOLD &&
-				mIt->first != name) {
+
+		// increment is our distance between points, use to eliminate round error
+		F32 threshold = mOverlapThreshold + (mIncrement / 4);
+		// If loop overlap is enabled, check if we overlap with points 'after' max value (project to lower)
+		F32 loop_up_check = (mLoopOverlap && (value + threshold) > mMaxValue) ? (value + threshold - mMaxValue + mMinValue) : mMinValue - 1.0f;
+		// If loop overlap is enabled, check if we overlap with points 'before' min value (project to upper)
+		F32 loop_down_check = (mLoopOverlap && (value - threshold) < mMinValue) ? (value - threshold - mMinValue + mMaxValue) : mMaxValue + 1.0f;
+
+		for(;mIt != mValue.endMap(); mIt++)
+		{
+			F32 locationVal = (F32)mIt->second.asReal();
+			// Check nearby values
+			F32 testVal = locationVal - newValue;
+			if (testVal > -threshold
+				&& testVal < threshold
+				&& mIt->first != name)
+			{
 				hit = true;
 				break;
 			}
+			if (mLoopOverlap)
+			{
+				// Check edge overlap values
+				if (locationVal < loop_up_check)
+				{
+					hit = true;
+					break;
+				}
+				if (locationVal > loop_down_check)
+				{
+					hit = true;
+					break;
+				}
+			}
 		}
 
 		// if none found, stop
@@ -170,13 +230,26 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from
 	}
 	
 	F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue);
+	if (mOrientation == HORIZONTAL)
+	{
+		S32 left_edge = mThumbWidth/2;
+		S32 right_edge = getRect().getWidth() - (mThumbWidth/2);
 
-	S32 left_edge = mThumbWidth/2;
-	S32 right_edge = getRect().getWidth() - (mThumbWidth/2);
+		S32 x = left_edge + S32( t * (right_edge - left_edge) );
 
-	S32 x = left_edge + S32( t * (right_edge - left_edge) );
-	mThumbRects[name].mLeft = x - (mThumbWidth/2);
-	mThumbRects[name].mRight = x + (mThumbWidth/2);
+		mThumbRects[name].mLeft = x - (mThumbWidth / 2);
+		mThumbRects[name].mRight = x + (mThumbWidth / 2);
+	}
+	else
+	{
+		S32 bottom_edge = mThumbWidth/2;
+		S32 top_edge = getRect().getHeight() - (mThumbWidth/2);
+
+		S32 x = bottom_edge + S32( t * (top_edge - bottom_edge) );
+
+		mThumbRects[name].mTop = x + (mThumbWidth / 2);
+		mThumbRects[name].mBottom = x - (mThumbWidth / 2);
+	}
 }
 
 void LLMultiSlider::setValue(const LLSD& value)
@@ -196,7 +269,11 @@ void LLMultiSlider::setValue(const LLSD& value)
 
 F32 LLMultiSlider::getSliderValue(const std::string& name) const
 {
-	return (F32)mValue[name].asReal();
+	if (mValue.has(name))
+	{
+		return (F32)mValue[name].asReal();
+	}
+	return 0;
 }
 
 void LLMultiSlider::setCurSlider(const std::string& name)
@@ -206,6 +283,62 @@ void LLMultiSlider::setCurSlider(const std::string& name)
 	}
 }
 
+F32 LLMultiSlider::getSliderValueFromPos(S32 xpos, S32 ypos) const
+{
+    F32 t = 0;
+    if (mOrientation == HORIZONTAL)
+    {
+        S32 left_edge = mThumbWidth / 2;
+        S32 right_edge = getRect().getWidth() - (mThumbWidth / 2);
+
+        xpos += mMouseOffset;
+        xpos = llclamp(xpos, left_edge, right_edge);
+
+        t = F32(xpos - left_edge) / (right_edge - left_edge);
+    }
+    else
+    {
+        S32 bottom_edge = mThumbWidth / 2;
+        S32 top_edge = getRect().getHeight() - (mThumbWidth / 2);
+
+        ypos += mMouseOffset;
+        ypos = llclamp(ypos, bottom_edge, top_edge);
+
+        t = F32(ypos - bottom_edge) / (top_edge - bottom_edge);
+    }
+
+    return((t * (mMaxValue - mMinValue)) + mMinValue);
+}
+
+
+LLRect LLMultiSlider::getSliderThumbRect(const std::string& name) const
+{
+    auto it = mThumbRects.find(name);
+    if (it != mThumbRects.end())
+        return (*it).second;
+    return LLRect();
+}
+
+void LLMultiSlider::setSliderThumbImage(const std::string &name)
+{
+    if (!name.empty())
+    {
+        mThumbImagep = LLUI::getUIImage(name);
+    }
+    else
+        clearSliderThumbImage();
+}
+
+void LLMultiSlider::clearSliderThumbImage()
+{
+    mThumbImagep = NULL;
+}
+
+void LLMultiSlider::resetCurSlider()
+{
+	mCurSlider = LLStringUtil::null;
+}
+
 const std::string& LLMultiSlider::addSlider()
 {
 	return addSlider(mInitialValue);
@@ -230,7 +363,14 @@ const std::string& LLMultiSlider::addSlider(F32 val)
 	}
 
 	// add a new thumb rect
-	mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 );
+	if (mOrientation == HORIZONTAL)
+	{
+		mThumbRects[newName.str()] = LLRect(0, getRect().getHeight(), mThumbWidth, 0);
+	}
+	else
+	{
+		mThumbRects[newName.str()] = LLRect(0, mThumbWidth, getRect().getWidth(), 0);
+	}
 
 	// add the value and set the current slider to this one
 	mValue.insert(newName.str(), initVal);
@@ -242,21 +382,28 @@ const std::string& LLMultiSlider::addSlider(F32 val)
 	return mCurSlider;
 }
 
-void LLMultiSlider::addSlider(F32 val, const std::string& name)
+bool LLMultiSlider::addSlider(F32 val, const std::string& name)
 {
 	F32 initVal = val;
 
 	if(mValue.size() >= mMaxNumSliders) {
-		return;
+		return false;
 	}
 
 	bool foundOne = findUnusedValue(initVal);
 	if(!foundOne) {
-		return;
+		return false;
 	}
 
 	// add a new thumb rect
-	mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 );
+	if (mOrientation == HORIZONTAL)
+	{
+		mThumbRects[name] = LLRect(0, getRect().getHeight(), mThumbWidth, 0);
+	}
+	else
+	{
+		mThumbRects[name] = LLRect(0, mThumbWidth, getRect().getWidth(), 0);
+	}
 
 	// add the value and set the current slider to this one
 	mValue.insert(name, initVal);
@@ -264,6 +411,8 @@ void LLMultiSlider::addSlider(F32 val, const std::string& name)
 
 	// move the slider
 	setSliderValue(mCurSlider, initVal, TRUE);
+
+	return true;
 }
 
 bool LLMultiSlider::findUnusedValue(F32& initVal)
@@ -278,11 +427,13 @@ bool LLMultiSlider::findUnusedValue(F32& initVal)
 
 		// look at the current spot
 		// and see if anything is there
+		F32 threshold = mAllowOverlap ? FLOAT_THRESHOLD : mOverlapThreshold + (mIncrement / 4);
 		LLSD::map_iterator mIt = mValue.beginMap();
 		for(;mIt != mValue.endMap(); mIt++) {
 			
 			F32 testVal = (F32)mIt->second.asReal() - initVal;
-			if(testVal > -FLOAT_THRESHOLD && testVal < FLOAT_THRESHOLD) {
+			if(testVal > -threshold && testVal < threshold)
+			{
 				hit = true;
 				break;
 			}
@@ -334,10 +485,15 @@ void LLMultiSlider::deleteSlider(const std::string& name)
 
 void LLMultiSlider::clear()
 {
-	while(mThumbRects.size() > 0) {
+	while(mThumbRects.size() > 0 && mValue.size() > 0) {
 		deleteCurSlider();
 	}
 
+	if (mThumbRects.size() > 0 || mValue.size() > 0)
+	{
+		LL_WARNS() << "Failed to fully clear Multi slider" << LL_ENDL;
+	}
+
 	LLF32UICtrl::clear();
 }
 
@@ -345,14 +501,7 @@ BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask)
 {
 	if( gFocusMgr.getMouseCapture() == this )
 	{
-		S32 left_edge = mThumbWidth/2;
-		S32 right_edge = getRect().getWidth() - (mThumbWidth/2);
-
-		x += mMouseOffset;
-		x = llclamp( x, left_edge, right_edge );
-
-		F32 t = F32(x - left_edge) / (right_edge - left_edge);
-		setCurSliderValue(t * (mMaxValue - mMinValue) + mMinValue );
+		setCurSliderValue(getSliderValueFromPos(x, y));
 		onCommit();
 
 		getWindow()->setCursor(UI_CURSOR_ARROW);
@@ -360,6 +509,24 @@ BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask)
 	}
 	else
 	{
+        if (getEnabled())
+        {
+            mHoverSlider.clear();
+            std::map<std::string, LLRect>::iterator  mIt = mThumbRects.begin();
+            for (; mIt != mThumbRects.end(); mIt++)
+            {
+                if (mIt->second.pointInRect(x, y))
+                {
+                    mHoverSlider = mIt->first;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            mHoverSlider.clear();
+        }
+
 		getWindow()->setCursor(UI_CURSOR_ARROW);
 		LL_DEBUGS("UserInput") << "hover handled by " << getName() << " (inactive)" << LL_ENDL;		
 	}
@@ -416,20 +583,30 @@ BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask)
 			}
 		}
 
-		// Find the offset of the actual mouse location from the center of the thumb.
-		if (mThumbRects[mCurSlider].pointInRect(x,y))
+		if (!mCurSlider.empty())
 		{
-			mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth/2) - x;
-		}
-		else
-		{
-			mMouseOffset = 0;
-		}
+			// Find the offset of the actual mouse location from the center of the thumb.
+			if (mThumbRects[mCurSlider].pointInRect(x,y))
+			{
+				if (mOrientation == HORIZONTAL)
+				{
+					mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth / 2) - x;
+				}
+				else
+				{
+					mMouseOffset = (mThumbRects[mCurSlider].mBottom + mThumbWidth / 2) - y;
+				}
+			}
+			else
+			{
+				mMouseOffset = 0;
+			}
 
-		// Start dragging the thumb
-		// No handler needed for focus lost since this class has no state that depends on it.
-		gFocusMgr.setMouseCapture( this );
-		mDragStartThumbRect = mThumbRects[mCurSlider];				
+			// Start dragging the thumb
+			// No handler needed for focus lost since this class has no state that depends on it.
+			gFocusMgr.setMouseCapture( this );
+			mDragStartThumbRect = mThumbRects[mCurSlider];
+		}
 	}
 	make_ui_sound("UISndClick");
 
@@ -462,6 +639,13 @@ BOOL	LLMultiSlider::handleKeyHere(KEY key, MASK mask)
 	return handled;
 }
 
+/*virtual*/
+void LLMultiSlider::onMouseLeave(S32 x, S32 y, MASK mask)
+{
+    mHoverSlider.clear();
+    LLF32UICtrl::onMouseLeave(x, y, mask);
+}
+
 void LLMultiSlider::draw()
 {
 	static LLUICachedControl<S32> extra_triangle_height ("UIExtraTriangleHeight", 0);
@@ -470,6 +654,7 @@ void LLMultiSlider::draw()
 
 	std::map<std::string, LLRect>::iterator mIt;
 	std::map<std::string, LLRect>::iterator curSldrIt;
+	std::map<std::string, LLRect>::iterator hoverSldrIt;
 
 	// Draw background and thumb.
 
@@ -483,9 +668,18 @@ void LLMultiSlider::draw()
 	// Track
 	LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square");
 
-	static LLUICachedControl<S32> multi_track_height ("UIMultiTrackHeight", 0);
-	S32 height_offset = (getRect().getHeight() - multi_track_height) / 2;
-	LLRect track_rect(0, getRect().getHeight() - height_offset, getRect().getWidth(), height_offset );
+	static LLUICachedControl<S32> multi_track_height_width ("UIMultiTrackHeight", 0);
+	S32 height_offset = 0;
+	S32 width_offset = 0;
+	if (mOrientation == HORIZONTAL)
+	{
+		height_offset = (getRect().getHeight() - multi_track_height_width) / 2;
+	}
+	else
+	{
+		width_offset = (getRect().getWidth() - multi_track_height_width) / 2;
+	}
+	LLRect track_rect(width_offset, getRect().getHeight() - height_offset, getRect().getWidth() - width_offset, height_offset);
 
 
 	if(mDrawTrack)
@@ -510,10 +704,11 @@ void LLMultiSlider::draw()
 				mTriangleColor.get() % opacity, TRUE);
 		}
 	}
-	else if (!thumb_imagep)
+	else if (!thumb_imagep && !mThumbImagep)
 	{
 		// draw all the thumbs
 		curSldrIt = mThumbRects.end();
+		hoverSldrIt = mThumbRects.end();
 		for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) {
 			
 			// choose the color
@@ -522,15 +717,21 @@ void LLMultiSlider::draw()
 				
 				curSldrIt = mIt;
 				continue;
-				//curThumbColor = mThumbCenterSelectedColor;
+			}
+			if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this)
+			{
+				// draw last, after current one
+				hoverSldrIt = mIt;
+				continue;
 			}
 
 			// the draw command
 			gl_rect_2d(mIt->second, curThumbColor, TRUE);
 		}
 
-		// now draw the current slider
-		if(curSldrIt != mThumbRects.end()) {
+		// now draw the current and hover sliders
+		if(curSldrIt != mThumbRects.end())
+		{
 			gl_rect_2d(curSldrIt->second, mThumbCenterSelectedColor.get(), TRUE);
 		}
 
@@ -539,20 +740,57 @@ void LLMultiSlider::draw()
 		{
 			gl_rect_2d(mDragStartThumbRect, mThumbCenterColor.get() % opacity, FALSE);
 		}
+		else if (hoverSldrIt != mThumbRects.end())
+		{
+			gl_rect_2d(hoverSldrIt->second, mThumbCenterSelectedColor.get(), TRUE);
+		}
 	}
-	else if( gFocusMgr.getMouseCapture() == this )
+	else
 	{
-		// draw drag start
-		thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+		LLMouseHandler* capture = gFocusMgr.getMouseCapture();
+		if (capture == this)
+		{
+			// draw drag start (ghost)
+			if (mThumbImagep)
+			{
+				mThumbImagep->draw(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+			}
+			else
+			{
+				thumb_imagep->drawSolid(mDragStartThumbRect, mThumbCenterColor.get() % 0.3f);
+			}
+		}
 
 		// draw the highlight
 		if (hasFocus())
 		{
-			thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+			if (!mCurSlider.empty())
+			{
+				if (mThumbImagep)
+				{
+					mThumbImagep->drawBorder(mThumbRects[mCurSlider], mThumbHighlightColor, gFocusMgr.getFocusFlashWidth());
+				}
+				else
+				{
+					thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+				}
+			}
 		}
+        if (!mHoverSlider.empty())
+        {
+            if (mThumbImagep)
+            {
+                mThumbImagep->drawBorder(mThumbRects[mHoverSlider], mThumbHighlightColor, gFocusMgr.getFocusFlashWidth());
+            }
+            else
+            {
+                thumb_imagep->drawBorder(mThumbRects[mHoverSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
+            }
+        }
 
 		// draw the thumbs
 		curSldrIt = mThumbRects.end();
+		hoverSldrIt = mThumbRects.end();
 		for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) 
 		{
 			// choose the color
@@ -563,46 +801,68 @@ void LLMultiSlider::draw()
 				curSldrIt = mIt;
 				continue;				
 			}
+			if (mIt->first == mHoverSlider && getEnabled() && gFocusMgr.getMouseCapture() != this) 
+			{
+				// don't draw now, draw last, after current one
+				hoverSldrIt = mIt;
+				continue;
+			}
 			
 			// the draw command
-			thumb_imagep->drawSolid(mIt->second, curThumbColor);
+			if (mThumbImagep)
+			{
+				if (getEnabled())
+				{
+					mThumbImagep->draw(mIt->second);
+				}
+				else
+				{
+					mThumbImagep->draw(mIt->second, LLColor4::grey % 0.8f);
+				}
+			}
+			else if (capture == this)
+			{
+				thumb_imagep->drawSolid(mIt->second, curThumbColor);
+			}
+			else
+			{
+				thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity);
+			}
 		}
 		
-		// draw cur slider last
+		// draw cur and hover slider last
 		if(curSldrIt != mThumbRects.end()) 
 		{
-			thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
-		}
-		
-	}
-	else
-	{ 
-		// draw highlight
-		if (hasFocus())
-		{
-			thumb_imagep->drawBorder(mThumbRects[mCurSlider], gFocusMgr.getFocusColor(), gFocusMgr.getFocusFlashWidth());
-		}
-
-		// draw thumbs
-		curSldrIt = mThumbRects.end();
-		for(mIt = mThumbRects.begin(); mIt != mThumbRects.end(); mIt++) 
-		{
-			
-			// choose the color
-			curThumbColor = mThumbCenterColor.get();
-			if(mIt->first == mCurSlider) 
+			if (mThumbImagep)
 			{
-				curSldrIt = mIt;
-				continue;
-				//curThumbColor = mThumbCenterSelectedColor;
-			}				
-			
-			thumb_imagep->drawSolid(mIt->second, curThumbColor % opacity);
+				if (getEnabled())
+				{
+					mThumbImagep->draw(curSldrIt->second);
+				}
+				else
+				{
+					mThumbImagep->draw(curSldrIt->second, LLColor4::grey % 0.8f);
+				}
+			}
+			else if (capture == this)
+			{
+				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get());
+			}
+			else
+			{
+				thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
+			}
 		}
-
-		if(curSldrIt != mThumbRects.end()) 
+		if(hoverSldrIt != mThumbRects.end()) 
 		{
-			thumb_imagep->drawSolid(curSldrIt->second, mThumbCenterSelectedColor.get() % opacity);
+			if (mThumbImagep)
+			{
+				mThumbImagep->draw(hoverSldrIt->second);
+			}
+			else
+			{
+				thumb_imagep->drawSolid(hoverSldrIt->second, mThumbCenterSelectedColor.get());
+			}
 		}
 	}
 
diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h
index 2b422e89c96fe1e1ac9275229e3718da0b8e04bb..99a78d6e093071584aa73a7dc78eaa691854c572 100644
--- a/indra/llui/llmultislider.h
+++ b/indra/llui/llmultislider.h
@@ -47,16 +47,23 @@ class LLMultiSlider : public LLF32UICtrl
 		Optional<S32>	max_sliders;
 
 		Optional<bool>	allow_overlap,
+						loop_overlap,
 						draw_track,
 						use_triangle;
 
+		Optional<F32>	overlap_threshold;
+
 		Optional<LLUIColor>	track_color,
 							thumb_disabled_color,
+							thumb_highlight_color,
 							thumb_outline_color,
 							thumb_center_color,
 							thumb_center_selected_color,
 							triangle_color;
 
+		Optional<std::string>	orientation,
+								thumb_image;
+
 		Optional<CommitCallbackParam>	mouse_down_callback,
 										mouse_up_callback;
 		Optional<S32>		thumb_width;
@@ -70,16 +77,27 @@ class LLMultiSlider : public LLF32UICtrl
 	friend class LLUICtrlFactory;
 public:
 	virtual ~LLMultiSlider();
+
+    // Multi-slider rounds values to nearest increments (bias towards rounding down)
+    F32					getNearestIncrement(F32 value) const;
+
 	void				setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE);
 	F32					getSliderValue(const std::string& name) const;
+	F32					getSliderValueFromPos(S32 xpos, S32 ypos) const;
+    LLRect              getSliderThumbRect(const std::string& name) const;
+
+    void                setSliderThumbImage(const std::string &name);
+    void                clearSliderThumbImage();
+
 
 	const std::string&	getCurSlider() const					{ return mCurSlider; }
 	F32					getCurSliderValue() const				{ return getSliderValue(mCurSlider); }
 	void				setCurSlider(const std::string& name);
+	void				resetCurSlider();
 	void				setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mCurSlider, val, from_event); }
 
-	/*virtual*/ void	setValue(const LLSD& value);
-	/*virtual*/ LLSD	getValue() const		{ return mValue; }
+	/*virtual*/ void	setValue(const LLSD& value) override;
+	/*virtual*/ LLSD	getValue() const override { return mValue; }
 
 	boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb );
 	boost::signals2::connection setMouseUpCallback(	const commit_signal_t::slot_type& cb );
@@ -87,24 +105,34 @@ class LLMultiSlider : public LLF32UICtrl
 	bool				findUnusedValue(F32& initVal);
 	const std::string&	addSlider();
 	const std::string&	addSlider(F32 val);
-	void				addSlider(F32 val, const std::string& name);
+	bool				addSlider(F32 val, const std::string& name);
 	void				deleteSlider(const std::string& name);
 	void				deleteCurSlider()			{ deleteSlider(mCurSlider); }
-	void				clear();
+	/*virtual*/ void	clear() override;
+
+	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask) override;
+	/*virtual*/ BOOL	handleMouseUp(S32 x, S32 y, MASK mask) override;
+	/*virtual*/ BOOL	handleMouseDown(S32 x, S32 y, MASK mask) override;
+	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask) override;
+	/*virtual*/ void	onMouseLeave(S32 x, S32 y, MASK mask) override;
+	/*virtual*/ void	draw() override;
+
+	S32				getMaxNumSliders() { return mMaxNumSliders; }
+	S32				getCurNumSliders() { return mValue.size(); }
+	F32				getOverlapThreshold() { return mOverlapThreshold; }
+	bool			canAddSliders() { return mValue.size() < mMaxNumSliders; }
 
-	/*virtual*/ BOOL	handleHover(S32 x, S32 y, MASK mask);
-	/*virtual*/ BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
-	/*virtual*/ BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
-	/*virtual*/ BOOL	handleKeyHere(KEY key, MASK mask);
-	/*virtual*/ void	draw();
 
 protected:
 	LLSD			mValue;
 	std::string		mCurSlider;
+	std::string		mHoverSlider;
 	static S32		mNameCounter;
 
 	S32				mMaxNumSliders;
 	BOOL			mAllowOverlap;
+	BOOL			mLoopOverlap;
+	F32				mOverlapThreshold;
 	BOOL			mDrawTrack;
 	BOOL			mUseTriangle;			/// hacked in toggle to use a triangle
 
@@ -116,11 +144,15 @@ class LLMultiSlider : public LLF32UICtrl
 					mThumbRects;
 	LLUIColor		mTrackColor;
 	LLUIColor		mThumbOutlineColor;
+	LLUIColor		mThumbHighlightColor;
 	LLUIColor		mThumbCenterColor;
 	LLUIColor		mThumbCenterSelectedColor;
 	LLUIColor		mDisabledThumbColor;
 	LLUIColor		mTriangleColor;
-	
+	LLUIImagePtr	mThumbImagep; //blimps on the slider, for now no 'disabled' support
+
+	const EOrientation	mOrientation;
+
 	commit_signal_t*	mMouseDownSignal;
 	commit_signal_t*	mMouseUpSignal;
 };
diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp
index c460a08afc7341bff99eb0619466e475a3ea117c..20e2b569f1a764d1e42bc66de7aeda29ae6c47b7 100644
--- a/indra/llui/llmultisliderctrl.cpp
+++ b/indra/llui/llmultisliderctrl.cpp
@@ -53,6 +53,12 @@ LLMultiSliderCtrl::Params::Params()
 	can_edit_text("can_edit_text", false),
 	max_sliders("max_sliders", 1),
 	allow_overlap("allow_overlap", false),
+	loop_overlap("loop_overlap", false),
+	orientation("orientation"),
+	thumb_image("thumb_image"),
+	thumb_width("thumb_width"),
+	thumb_highlight_color("thumb_highlight_color"),
+	overlap_threshold("overlap_threshold", 0),
 	draw_track("draw_track", true),
 	use_triangle("use_triangle", false),
 	decimal_digits("decimal_digits", 3),
@@ -167,6 +173,19 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
 	params.increment(p.increment);
 	params.max_sliders(p.max_sliders);
 	params.allow_overlap(p.allow_overlap);
+	params.loop_overlap(p.loop_overlap);
+	if (p.overlap_threshold.isProvided())
+	{
+		params.overlap_threshold = p.overlap_threshold;
+	}
+	params.orientation(p.orientation);
+	params.thumb_image(p.thumb_image);
+	params.thumb_highlight_color(p.thumb_highlight_color);
+	if (p.thumb_width.isProvided())
+	{
+		// otherwise should be provided by template
+		params.thumb_width(p.thumb_width);
+	}
 	params.draw_track(p.draw_track);
 	params.use_triangle(p.use_triangle);
 	params.control_name(p.control_name);
@@ -213,6 +232,11 @@ void LLMultiSliderCtrl::setCurSlider(const std::string& name)
 	mCurValue = mMultiSlider->getCurSliderValue();
 }
 
+void LLMultiSliderCtrl::resetCurSlider()
+{
+	mMultiSlider->resetCurSlider();
+}
+
 BOOL LLMultiSliderCtrl::setLabelArg( const std::string& key, const LLStringExplicit& text )
 {
 	BOOL res = FALSE;
@@ -269,6 +293,17 @@ const std::string& LLMultiSliderCtrl::addSlider(F32 val)
 	return name;
 }
 
+bool LLMultiSliderCtrl::addSlider(F32 val, const std::string& name)
+{
+	bool res = mMultiSlider->addSlider(val, name);
+	if (res)
+	{
+		mCurValue = mMultiSlider->getCurSliderValue();
+		updateText();
+	}
+	return res;
+}
+
 void LLMultiSliderCtrl::deleteSlider(const std::string& name)
 {
 	mMultiSlider->deleteSlider(name);
diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h
index b6a35423765b6660f130cdd7285dfa8907f3d5fe..adb28676ecd485ee0eb28a48810a76656a25e4ae 100644
--- a/indra/llui/llmultisliderctrl.h
+++ b/indra/llui/llmultisliderctrl.h
@@ -51,14 +51,22 @@ class LLMultiSliderCtrl : public LLF32UICtrl
 								text_width;
 		Optional<bool>			show_text,
 								can_edit_text;
-		Optional<S32>			decimal_digits;
+		Optional<S32>			decimal_digits,
+								thumb_width;
 		Optional<S32>			max_sliders;	
 		Optional<bool>			allow_overlap,
+								loop_overlap,
 								draw_track,
 								use_triangle;
 
+		Optional<std::string>	orientation,
+								thumb_image;
+
+		Optional<F32>			overlap_threshold;
+
 		Optional<LLUIColor>		text_color,
-								text_disabled_color;
+								text_disabled_color,
+								thumb_highlight_color;
 
 		Optional<CommitCallbackParam>	mouse_down_callback,
 										mouse_up_callback;
@@ -74,7 +82,7 @@ class LLMultiSliderCtrl : public LLF32UICtrl
 public:
 	virtual ~LLMultiSliderCtrl();
 
-	F32				getSliderValue(const std::string& name) const;
+    F32				getSliderValue(const std::string& name) const   { return mMultiSlider->getSliderValue(name); }
 	void			setSliderValue(const std::string& name, F32 v, BOOL from_event = FALSE);
 
 	virtual void	setValue(const LLSD& value );
@@ -84,6 +92,7 @@ class LLMultiSliderCtrl : public LLF32UICtrl
 	const std::string& getCurSlider() const					{ return mMultiSlider->getCurSlider(); }
 	F32				getCurSliderValue() const				{ return mCurValue; }
 	void			setCurSlider(const std::string& name);		
+	void			resetCurSlider();
 	void			setCurSliderValue(F32 val, BOOL from_event = false) { setSliderValue(mMultiSlider->getCurSlider(), val, from_event); }
 
 	virtual void	setMinValue(const LLSD& min_value)	{ setMinValue((F32)min_value.asReal()); }
@@ -98,15 +107,28 @@ class LLMultiSliderCtrl : public LLF32UICtrl
 	void			setMaxValue(F32 max_value) {mMultiSlider->setMaxValue(max_value);}
 	void			setIncrement(F32 increment) {mMultiSlider->setIncrement(increment);}
 
+	F32				getNearestIncrement(F32 value) const { return mMultiSlider->getNearestIncrement(value); }
+	F32			    getSliderValueFromPos(S32 x, S32 y) const { return mMultiSlider->getSliderValueFromPos(x, y); }
+    LLRect          getSliderThumbRect(const std::string &name) const { return mMultiSlider->getSliderThumbRect(name); }
+
+    void            setSliderThumbImage(const std::string &name) { mMultiSlider->setSliderThumbImage(name); }
+    void            clearSliderThumbImage() { mMultiSlider->clearSliderThumbImage(); }
+
 	/// for adding and deleting sliders
 	const std::string&	addSlider();
 	const std::string&	addSlider(F32 val);
+	bool				addSlider(F32 val, const std::string& name);
 	void			deleteSlider(const std::string& name);
 	void			deleteCurSlider()			{ deleteSlider(mMultiSlider->getCurSlider()); }
 
 	F32				getMinValue() const { return mMultiSlider->getMinValue(); }
 	F32				getMaxValue() const { return mMultiSlider->getMaxValue(); }
 
+	S32				getMaxNumSliders() { return mMultiSlider->getMaxNumSliders(); }
+	S32				getCurNumSliders() { return mMultiSlider->getCurNumSliders(); }
+	F32				getOverlapThreshold() { return mMultiSlider->getOverlapThreshold(); }
+	bool			canAddSliders() { return mMultiSlider->canAddSliders(); }
+
 	void			setLabel(const std::string& label)				{ if (mLabelBox) mLabelBox->setText(label); }
 	void			setLabelColor(const LLColor4& c)			{ mTextEnabledColor = c; }
 	void			setDisabledLabelColor(const LLColor4& c)	{ mTextDisabledColor = c; }
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index ebbb951ee634b73d4adc526a7c65657a19aa105a..62df5a2c385938602bea50aca08743ad0c21f222 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -42,7 +42,6 @@ static LLDefaultChildRegistry::Register<LLSlider> r1("slider_bar");
 
 LLSlider::Params::Params()
 :	orientation ("orientation", std::string ("horizontal")),
-	track_color("track_color"),
 	thumb_outline_color("thumb_outline_color"),
 	thumb_center_color("thumb_center_color"),
 	thumb_image("thumb_image"),
@@ -60,7 +59,6 @@ LLSlider::LLSlider(const LLSlider::Params& p)
 :	LLF32UICtrl(p),
 	mMouseOffset( 0 ),
 	mOrientation ((p.orientation() == "horizontal") ? HORIZONTAL : VERTICAL),
-	mTrackColor(p.track_color()),
 	mThumbOutlineColor(p.thumb_outline_color()),
 	mThumbCenterColor(p.thumb_center_color()),
 	mThumbImage(p.thumb_image),
@@ -331,8 +329,9 @@ void LLSlider::draw()
 		highlight_rect.set(track_rect.mLeft, track_rect.mTop, track_rect.mRight, track_rect.mBottom);
 	}
 
-	trackImage->draw(track_rect, LLColor4::white % alpha);
-	trackHighlightImage->draw(highlight_rect, LLColor4::white % alpha);
+	LLColor4 color = isInEnabledChain() ? LLColor4::white % alpha : LLColor4::white % (0.6f * alpha);
+	trackImage->draw(track_rect, color);
+	trackHighlightImage->draw(highlight_rect, color);
 
 	// Thumb
 	if (hasFocus())
diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h
index 3b492d81823a34aacca689ac424c0b9314130847..484a5373b308fa1b81438d3c31f6c349e54ac0e9 100644
--- a/indra/llui/llslider.h
+++ b/indra/llui/llslider.h
@@ -38,8 +38,7 @@ class LLSlider : public LLF32UICtrl
 	{
 		Optional<std::string> orientation;
 
-		Optional<LLUIColor>	track_color,
-							thumb_outline_color,
+		Optional<LLUIColor>	thumb_outline_color,
 							thumb_center_color;
 
 		Optional<LLUIImage*>	thumb_image,
@@ -99,7 +98,6 @@ class LLSlider : public LLF32UICtrl
 	const EOrientation	mOrientation;
 
 	LLRect		mThumbRect;
-	LLUIColor	mTrackColor;
 	LLUIColor	mThumbOutlineColor;
 	LLUIColor	mThumbCenterColor;
 	
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 0056cb6dc48d45243511cb38d908d3bf0f399dbb..3b89a8ca6376e4e12261c3b19ad766c729d9fcbd 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -283,6 +283,35 @@ void LLSliderCtrl::updateText()
 	}
 }
 
+void LLSliderCtrl::updateSliderRect()
+{
+    S32 right = getRect().getWidth();
+    S32 top = getRect().getHeight();
+    S32 bottom = 0;
+    S32 left = 0;
+    static LLUICachedControl<S32> sliderctrl_spacing("UISliderctrlSpacing", 0);
+    if (mEditor)
+    {
+        LLRect editor_rect = mEditor->getRect();
+        S32 editor_width = editor_rect.getWidth();
+        editor_rect.mRight = right;
+        editor_rect.mLeft = right - editor_width;
+        mEditor->setRect(editor_rect);
+
+        right -= editor_width + sliderctrl_spacing;
+    }
+    if (mTextBox)
+    {
+        right -= mTextBox->getRect().getWidth() + sliderctrl_spacing;
+    }
+    if (mLabelBox)
+    {
+        left += mLabelBox->getRect().getWidth() + sliderctrl_spacing;
+    }
+
+    mSlider->setRect(LLRect(left, top,right,bottom));
+}
+
 // static
 void LLSliderCtrl::onEditorCommit( LLUICtrl* ctrl, const LLSD& userdata )
 {
@@ -404,6 +433,18 @@ void LLSliderCtrl::onCommit()
 	LLF32UICtrl::onCommit();
 }
 
+void LLSliderCtrl::setRect(const LLRect& rect)
+{
+    LLF32UICtrl::setRect(rect);
+    updateSliderRect();
+}
+
+//virtual
+void LLSliderCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+    LLF32UICtrl::reshape(width, height, called_from_parent);
+    updateSliderRect();
+}
 
 void LLSliderCtrl::setPrecision(S32 precision)
 {
diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h
index 2bb8668b90a2afba5bf6ef0ed138e542211da5f3..541c167717199843aeaa537e4707cf96b60bd77e 100644
--- a/indra/llui/llsliderctrl.h
+++ b/indra/llui/llsliderctrl.h
@@ -125,6 +125,9 @@ class LLSliderCtrl: public LLF32UICtrl, public ll::ui::SearchableControl
 		mSlider->setControlName(control_name, context);
 	}
 
+	/*virtual*/ void	setRect(const LLRect& rect);
+	/*virtual*/ void	reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
+
 	static void		onSliderCommit(LLUICtrl* caller, const LLSD& userdata);
 	
 	static void		onEditorCommit(LLUICtrl* ctrl, const LLSD& userdata);
@@ -146,6 +149,7 @@ class LLSliderCtrl: public LLF32UICtrl, public ll::ui::SearchableControl
 	}
 private:
 	void			updateText();
+	void			updateSliderRect();
 	void			reportInvalidData();
 
 	const LLFontGL*	mFont;
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index e1c51deba9aa0897afff8bc72dccd02c888ed1cf..9856e551cc7956c60ba723e3aff289d676ce0523 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -33,7 +33,6 @@
 #include "llcontrol.h"
 #include "llcoord.h"
 #include "llcontrol.h"
-#include "llglslshader.h"
 #include "llinitparam.h"
 #include "llregistry.h"
 #include "llrender2dutils.h"
@@ -49,7 +48,6 @@
 // for initparam specialization
 #include "llfontgl.h"
 
-
 class LLUUID;
 class LLWindow;
 class LLView;
@@ -77,7 +75,8 @@ enum EDragAndDropType
 	DAD_MESH            = 15,
 	DAD_WIDGET          = 16,
 	DAD_PERSON          = 17,
-	DAD_COUNT           = 18,   // number of types in this enum
+    DAD_SETTINGS        = 18,
+	DAD_COUNT           = 19,   // number of types in this enum
 };
 
 // Reasons for drags to be denied.
diff --git a/indra/llui/llvirtualtrackball.cpp b/indra/llui/llvirtualtrackball.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..723643dd251e9213bdfa2991440f9c01e17b8e9d
--- /dev/null
+++ b/indra/llui/llvirtualtrackball.cpp
@@ -0,0 +1,480 @@
+/**
+* @file LLVirtualTrackball.cpp
+* @author Andrey Lihatskiy
+* @brief Implementation for LLVirtualTrackball
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+// A control for positioning the sun and the moon in the celestial sphere.
+
+#include "linden_common.h"
+#include "llvirtualtrackball.h"
+#include "llstring.h"
+#include "llrect.h"
+#include "lluictrlfactory.h"
+#include "llrender.h"
+
+// Globals
+static LLDefaultChildRegistry::Register<LLVirtualTrackball> register_virtual_trackball("sun_moon_trackball");
+
+const LLVector3 VectorZero(1.0f, 0.0f, 0.0f);
+
+LLVirtualTrackball::Params::Params()
+  : border("border"),
+    image_moon_back("image_moon_back"),
+    image_moon_front("image_moon_front"),
+    image_sphere("image_sphere"),
+    image_sun_back("image_sun_back"),
+    image_sun_front("image_sun_front"),
+    btn_rotate_top("button_rotate_top"),
+    btn_rotate_bottom("button_rotate_bottom"),
+    btn_rotate_left("button_rotate_left"),
+    btn_rotate_right("button_rotate_right"),
+    thumb_mode("thumb_mode"),
+    lbl_N("labelN"),
+    lbl_S("labelS"),
+    lbl_W("labelW"),
+    lbl_E("labelE"),
+    increment_angle_mouse("increment_angle_mouse", 0.5f),
+    increment_angle_btn("increment_angle_btn", 3.0f)
+{
+}
+
+LLVirtualTrackball::LLVirtualTrackball(const LLVirtualTrackball::Params& p)
+  : LLUICtrl(p),
+    mImgMoonBack(p.image_moon_back),
+    mImgMoonFront(p.image_moon_front),
+    mImgSunBack(p.image_sun_back),
+    mImgSunFront(p.image_sun_front),
+    mImgSphere(p.image_sphere),
+    mThumbMode(p.thumb_mode() == "moon" ? ThumbMode::MOON : ThumbMode::SUN),
+    mIncrementMouse(DEG_TO_RAD * p.increment_angle_mouse()),
+    mIncrementBtn(DEG_TO_RAD * p.increment_angle_btn())
+{
+    LLRect border_rect = getLocalRect();
+    S32 centerX = border_rect.getCenterX();
+    S32 centerY = border_rect.getCenterY();
+    U32 btn_size = 32; // width & height
+    U32 axis_offset_lt = 16; // offset from the axis for left/top sides
+    U32 axis_offset_rb = btn_size - axis_offset_lt; //  and for right/bottom
+
+    LLViewBorder::Params border = p.border;
+    border.rect(border_rect);
+    mBorder = LLUICtrlFactory::create<LLViewBorder>(border);
+    addChild(mBorder);
+
+    
+    LLButton::Params btn_rt = p.btn_rotate_top;
+    btn_rt.rect(LLRect(centerX - axis_offset_lt, border_rect.mTop, centerX + axis_offset_rb, border_rect.mTop - btn_size));
+    btn_rt.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateTopClick, this));
+    btn_rt.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateTopClick, this));
+    btn_rt.mouseenter_callback.function(boost::bind(&LLVirtualTrackball::onRotateTopMouseEnter, this));
+    mBtnRotateTop = LLUICtrlFactory::create<LLButton>(btn_rt);
+    addChild(mBtnRotateTop);
+
+    LLTextBox::Params lbl_N = p.lbl_N;
+    LLRect rect_N = btn_rt.rect;
+    //rect_N.translate(btn_rt.rect().getWidth(), 0);
+    lbl_N.rect = rect_N;
+    lbl_N.initial_value(lbl_N.label());
+    mLabelN = LLUICtrlFactory::create<LLTextBox>(lbl_N);
+    addChild(mLabelN);
+
+
+    LLButton::Params btn_rr = p.btn_rotate_right;
+    btn_rr.rect(LLRect(border_rect.mRight - btn_size, centerY + axis_offset_lt, border_rect.mRight, centerY - axis_offset_rb));
+    btn_rr.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateRightClick, this));
+    btn_rr.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateRightClick, this));
+    btn_rr.mouseenter_callback.function(boost::bind(&LLVirtualTrackball::onRotateRightMouseEnter, this));
+    mBtnRotateRight = LLUICtrlFactory::create<LLButton>(btn_rr);
+    addChild(mBtnRotateRight);
+
+    LLTextBox::Params lbl_E = p.lbl_E;
+    LLRect rect_E = btn_rr.rect;
+    //rect_E.translate(0, -1 * btn_rr.rect().getHeight());
+    lbl_E.rect = rect_E;
+    lbl_E.initial_value(lbl_E.label());
+    mLabelE = LLUICtrlFactory::create<LLTextBox>(lbl_E);
+    addChild(mLabelE);
+
+
+    LLButton::Params btn_rb = p.btn_rotate_bottom;
+    btn_rb.rect(LLRect(centerX - axis_offset_lt, border_rect.mBottom + btn_size, centerX + axis_offset_rb, border_rect.mBottom));
+    btn_rb.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateBottomClick, this));
+    btn_rb.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateBottomClick, this));
+    btn_rb.mouseenter_callback.function(boost::bind(&LLVirtualTrackball::onRotateBottomMouseEnter, this));
+    mBtnRotateBottom = LLUICtrlFactory::create<LLButton>(btn_rb);
+    addChild(mBtnRotateBottom);
+
+    LLTextBox::Params lbl_S = p.lbl_S;
+    LLRect rect_S = btn_rb.rect;
+    //rect_S.translate(btn_rb.rect().getWidth(), 0);
+    lbl_S.rect = rect_S;
+    lbl_S.initial_value(lbl_S.label());
+    mLabelS = LLUICtrlFactory::create<LLTextBox>(lbl_S);
+    addChild(mLabelS);
+
+
+    LLButton::Params btn_rl = p.btn_rotate_left;
+    btn_rl.rect(LLRect(border_rect.mLeft, centerY + axis_offset_lt, border_rect.mLeft + btn_size, centerY - axis_offset_rb));
+    btn_rl.click_callback.function(boost::bind(&LLVirtualTrackball::onRotateLeftClick, this));
+    btn_rl.mouse_held_callback.function(boost::bind(&LLVirtualTrackball::onRotateLeftClick, this));
+    btn_rl.mouseenter_callback.function(boost::bind(&LLVirtualTrackball::onRotateLeftMouseEnter, this));
+    mBtnRotateLeft = LLUICtrlFactory::create<LLButton>(btn_rl);
+    addChild(mBtnRotateLeft);
+
+    LLTextBox::Params lbl_W = p.lbl_W;
+    LLRect rect_W = btn_rl.rect;
+    //rect_W.translate(0, -1* btn_rl.rect().getHeight());
+    lbl_W.rect = rect_W;
+    lbl_W.initial_value(lbl_W.label());
+    mLabelW = LLUICtrlFactory::create<LLTextBox>(lbl_W);
+    addChild(mLabelW);
+
+
+    LLPanel::Params touch_area;
+    touch_area.rect = LLRect(centerX - mImgSphere->getWidth() / 2,
+                             centerY + mImgSphere->getHeight() / 2,
+                             centerX + mImgSphere->getWidth() / 2,
+                             centerY - mImgSphere->getHeight() / 2);
+    mTouchArea = LLUICtrlFactory::create<LLPanel>(touch_area);
+    addChild(mTouchArea);
+}
+
+LLVirtualTrackball::~LLVirtualTrackball()
+{
+}
+
+BOOL LLVirtualTrackball::postBuild()
+{
+    return TRUE;
+}
+
+
+void LLVirtualTrackball::drawThumb(S32 x, S32 y, ThumbMode mode, bool upperHemi)
+{
+    LLUIImage* thumb;
+    if (mode == ThumbMode::SUN)
+    {
+        if (upperHemi)
+        {
+            thumb = mImgSunFront;
+        }
+        else
+        {
+            thumb = mImgSunBack;
+        }
+    }
+    else
+    {
+        if (upperHemi)
+        {
+            thumb = mImgMoonFront;
+        }
+        else
+        {
+            thumb = mImgMoonBack;
+        }
+    }
+    thumb->draw(LLRect(x - thumb->getWidth() / 2,
+                       y + thumb->getHeight() / 2,
+                       x + thumb->getWidth() / 2,
+                       y - thumb->getHeight() / 2));
+}
+
+bool LLVirtualTrackball::pointInTouchCircle(S32 x, S32 y) const
+{
+    S32 centerX = mTouchArea->getRect().getCenterX();
+    S32 centerY = mTouchArea->getRect().getCenterY();
+
+    bool in_circle = pow(x - centerX, 2) + pow(y - centerY, 2) <= pow(mTouchArea->getRect().getWidth() / 2, 2);
+    return in_circle;
+}
+
+void LLVirtualTrackball::draw()
+{
+    LLVector3 draw_point = VectorZero * mValue;
+
+    S32 halfwidth = mTouchArea->getRect().getWidth() / 2;
+    S32 halfheight = mTouchArea->getRect().getHeight() / 2;
+    draw_point.mV[VX] = (draw_point.mV[VX] + 1.0) * halfwidth + mTouchArea->getRect().mLeft;
+    draw_point.mV[VY] = (draw_point.mV[VY] + 1.0) * halfheight + mTouchArea->getRect().mBottom;
+    bool upper_hemisphere = (draw_point.mV[VZ] >= 0.f);
+
+    mImgSphere->draw(mTouchArea->getRect(), upper_hemisphere ? UI_VERTEX_COLOR : UI_VERTEX_COLOR % 0.5f);
+    drawThumb(draw_point.mV[VX], draw_point.mV[VY], mThumbMode, upper_hemisphere);
+
+
+    if (LLView::sDebugRects)
+    {
+        gGL.color4fv(LLColor4::red.mV);
+        gl_circle_2d(mTouchArea->getRect().getCenterX(), mTouchArea->getRect().getCenterY(), mImgSphere->getWidth() / 2, 60, false);
+        gl_circle_2d(draw_point.mV[VX], draw_point.mV[VY], mImgSunFront->getWidth() / 2, 12, false);
+    }
+
+    // hide the direction labels when disabled
+    BOOL enabled = isInEnabledChain();
+    mLabelN->setVisible(enabled);
+    mLabelE->setVisible(enabled);
+    mLabelS->setVisible(enabled);
+    mLabelW->setVisible(enabled);
+
+    LLView::draw();
+}
+
+void LLVirtualTrackball::onRotateTopClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 1, 0, 0); 
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateBottomClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, -1, 0, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateLeftClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 0, 1, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateRightClick()
+{
+    if (getEnabled())
+    {
+        LLQuaternion delta;
+        delta.setAngleAxis(mIncrementBtn, 0, -1, 0);
+        mValue *= delta;
+        setValueAndCommit(mValue);
+
+        make_ui_sound("UISndClick");
+    }
+}
+
+void LLVirtualTrackball::onRotateTopMouseEnter()
+{
+    mBtnRotateTop->setHighlight(true);
+}
+
+void LLVirtualTrackball::onRotateBottomMouseEnter()
+{
+    mBtnRotateBottom->setHighlight(true);
+}
+
+void LLVirtualTrackball::onRotateLeftMouseEnter()
+{
+    mBtnRotateLeft->setHighlight(true);
+}
+
+void LLVirtualTrackball::onRotateRightMouseEnter()
+{
+    mBtnRotateRight->setHighlight(true);
+}
+
+void LLVirtualTrackball::setValue(const LLSD& value)
+{
+	if (value.isArray() && value.size() == 4)
+    {
+        mValue.setValue(value);
+    }
+}
+
+void LLVirtualTrackball::setRotation(const LLQuaternion &value)
+{
+    mValue = value;
+}
+
+void LLVirtualTrackball::setValue(F32 x, F32 y, F32 z, F32 w)
+{
+    mValue.set(x, y, z, w);
+}
+
+void LLVirtualTrackball::setValueAndCommit(const LLQuaternion &value)
+{
+	mValue = value;
+    onCommit();
+}
+
+LLSD LLVirtualTrackball::getValue() const
+{
+    return mValue.getValue();
+}
+
+LLQuaternion LLVirtualTrackball::getRotation() const
+{
+	return mValue;
+}
+
+BOOL LLVirtualTrackball::handleHover(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        if (mDragMode == DRAG_SCROLL)
+        { // trackball (move to roll) mode
+            LLQuaternion delta;
+
+            F32 rotX = x - mPrevX;
+            F32 rotY = y - mPrevY;
+
+            if (abs(rotX) > 1)
+            {
+                F32 direction = (rotX < 0) ? -1 : 1;
+                delta.setAngleAxis(mIncrementMouse * abs(rotX), 0, direction, 0);  // changing X - rotate around Y axis
+                mValue *= delta;
+            }
+
+            if (abs(rotY) > 1)
+            {
+                F32 direction = (rotY < 0) ? 1 : -1; // reverse for Y (value increases from bottom to top)
+                delta.setAngleAxis(mIncrementMouse * abs(rotY), direction, 0, 0);  // changing Y - rotate around X axis
+                mValue *= delta;
+            }
+        }
+        else
+        { // set on click mode
+            if (!pointInTouchCircle(x, y))
+            {
+                return TRUE; // don't drag outside the circle
+            }
+
+            F32 radius = mTouchArea->getRect().getWidth() / 2;
+            F32 xx = x - mTouchArea->getRect().getCenterX();
+            F32 yy = y - mTouchArea->getRect().getCenterY();
+            F32 dist = sqrt(pow(xx, 2) + pow(yy, 2));
+
+            F32 azimuth = llclamp(acosf(xx / dist), 0.0f, F_PI);
+            F32 altitude = llclamp(acosf(dist / radius), 0.0f, F_PI_BY_TWO);
+
+            if (yy < 0)
+            {
+                azimuth = F_TWO_PI - azimuth;
+            }
+
+            LLVector3 draw_point = VectorZero * mValue;
+            if (draw_point.mV[VZ] >= 0.f)
+            {
+                if (is_approx_zero(altitude)) // don't change the hemisphere
+                {
+                    altitude = F_APPROXIMATELY_ZERO;
+                }
+                altitude *= -1;
+            }
+
+            mValue.setAngleAxis(altitude, 0, 1, 0);
+            LLQuaternion az_quat;
+            az_quat.setAngleAxis(azimuth, 0, 0, 1);
+            mValue *= az_quat;
+        }
+
+        mPrevX = x;
+        mPrevY = y;
+        onCommit();
+    }
+    return TRUE;
+}
+
+BOOL LLVirtualTrackball::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        mPrevX = 0;
+        mPrevY = 0;
+        gFocusMgr.setMouseCapture(NULL);
+        make_ui_sound("UISndClickRelease");
+    }
+    return LLView::handleMouseUp(x, y, mask);
+}
+
+BOOL LLVirtualTrackball::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+    if (pointInTouchCircle(x, y))
+    {
+        mPrevX = x;
+        mPrevY = y;
+        gFocusMgr.setMouseCapture(this);
+        mDragMode = (mask == MASK_CONTROL) ? DRAG_SCROLL : DRAG_SET;
+        make_ui_sound("UISndClick");
+    }
+    return LLView::handleMouseDown(x, y, mask);
+}
+
+BOOL LLVirtualTrackball::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+    if (pointInTouchCircle(x, y))
+    {
+
+        //make_ui_sound("UISndClick");
+    }
+    return LLView::handleRightMouseDown(x, y, mask);
+}
+
+BOOL LLVirtualTrackball::handleKeyHere(KEY key, MASK mask)
+{
+    BOOL handled = FALSE;
+    switch (key)
+    {
+    case KEY_DOWN:
+        onRotateTopClick();
+        handled = TRUE;
+        break;
+    case KEY_LEFT:
+        onRotateRightClick();
+        handled = TRUE;
+        break;
+    case KEY_UP:
+        onRotateBottomClick();
+        handled = TRUE;
+        break;
+    case KEY_RIGHT:
+        onRotateLeftClick();
+        handled = TRUE;
+        break;
+    default:
+        break;
+    }
+    return handled;
+}
+
diff --git a/indra/llui/llvirtualtrackball.h b/indra/llui/llvirtualtrackball.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d4b1ece17623018bbe5b1bcaf46831351e93659
--- /dev/null
+++ b/indra/llui/llvirtualtrackball.h
@@ -0,0 +1,160 @@
+/**
+* @file virtualtrackball.h
+* @author Andrey Lihatskiy
+* @brief Header file for LLVirtualTrackball
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+// A control for positioning the sun and the moon in the celestial sphere.
+
+#ifndef LL_LLVIRTUALTRACKBALL_H
+#define LL_LLVIRTUALTRACKBALL_H
+
+#include "lluictrl.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "llbutton.h"
+
+class LLVirtualTrackball
+    : public LLUICtrl
+{
+public:
+    enum ThumbMode
+    {
+        SUN,
+        MOON
+    };
+    enum DragMode
+    {
+        DRAG_SET,
+        DRAG_SCROLL
+    };
+
+    struct Params
+        : public LLInitParam::Block<Params, LLUICtrl::Params>
+    {
+        Optional<LLViewBorder::Params>	    border;
+        Optional<LLUIImage*>                image_moon_back,
+            image_moon_front,
+            image_sphere,
+            image_sun_back,
+            image_sun_front;
+
+        Optional<std::string>               thumb_mode;
+        Optional<F32>                       increment_angle_mouse,
+            increment_angle_btn;
+
+        Optional<LLTextBox::Params>         lbl_N,
+            lbl_S,
+            lbl_W,
+            lbl_E;
+
+        Optional<LLButton::Params>          btn_rotate_top,
+            btn_rotate_bottom,
+            btn_rotate_left,
+            btn_rotate_right;
+
+        Params();
+    };
+
+
+    virtual ~LLVirtualTrackball();
+    /*virtual*/ BOOL postBuild();
+
+    virtual BOOL    handleHover(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleMouseUp(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleMouseDown(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleRightMouseDown(S32 x, S32 y, MASK mask);
+    virtual BOOL    handleKeyHere(KEY key, MASK mask);
+
+    virtual void    draw();
+
+    virtual void    setValue(const LLSD& value);
+    void            setValue(F32 x, F32 y, F32 z, F32 w);
+    virtual LLSD    getValue() const;
+
+    void            setRotation(const LLQuaternion &value);
+    LLQuaternion    getRotation() const;
+
+protected:
+    friend class LLUICtrlFactory;
+    LLVirtualTrackball(const Params&);
+    void onEditChange();
+
+protected:
+    LLTextBox*          mNLabel;
+    LLTextBox*          mELabel;
+    LLTextBox*          mSLabel;
+    LLTextBox*          mWLabel;
+
+    LLButton*           mBtnRotateTop;
+    LLButton*           mBtnRotateBottom;
+    LLButton*           mBtnRotateLeft;
+    LLButton*           mBtnRotateRight;
+
+    LLTextBox*          mLabelN;
+    LLTextBox*          mLabelS;
+    LLTextBox*          mLabelW;
+    LLTextBox*          mLabelE;
+
+    LLPanel*            mTouchArea;
+    LLViewBorder*       mBorder;
+
+private:
+    void setValueAndCommit(const LLQuaternion &value);
+    void drawThumb(S32 x, S32 y, ThumbMode mode, bool upperHemi = true);
+    bool pointInTouchCircle(S32 x, S32 y) const;
+
+    void onRotateTopClick();
+    void onRotateBottomClick();
+    void onRotateLeftClick();
+    void onRotateRightClick();
+
+    void onRotateTopMouseEnter();
+    void onRotateBottomMouseEnter();
+    void onRotateLeftMouseEnter();
+    void onRotateRightMouseEnter();
+
+    S32 mPrevX;
+    S32 mPrevY;
+
+    LLUIImage*     mImgMoonBack;
+    LLUIImage*     mImgMoonFront;
+    LLUIImage*     mImgSunBack;
+    LLUIImage*     mImgSunFront;
+    LLUIImage*     mImgBtnRotTop;
+    LLUIImage*     mImgBtnRotLeft;
+    LLUIImage*     mImgBtnRotRight;
+    LLUIImage*     mImgBtnRotBottom;
+    LLUIImage*     mImgSphere;
+
+    LLQuaternion   mValue;
+    ThumbMode      mThumbMode;
+    DragMode       mDragMode;
+
+    F32            mIncrementMouse;
+    F32            mIncrementBtn;
+};
+
+#endif
+
diff --git a/indra/llui/llxyvector.cpp b/indra/llui/llxyvector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d7ba243e1d37c11d05195e67d417fb449d3bde5b
--- /dev/null
+++ b/indra/llui/llxyvector.cpp
@@ -0,0 +1,337 @@
+/**
+* @file llxyvector.cpp
+* @author Andrey Lihatskiy
+* @brief Implementation for LLXYVector
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+// A control that allows to set two related vector magnitudes by manipulating a single vector on a plane. 
+
+#include "linden_common.h"
+
+#include "llxyvector.h"
+
+#include "llstring.h"
+#include "llrect.h"
+
+#include "lluictrlfactory.h"
+#include "llrender.h"
+
+#include "llmath.h"
+
+// Globals
+static LLDefaultChildRegistry::Register<LLXYVector> register_xy_vector("xy_vector");
+
+
+const F32 CENTER_CIRCLE_RADIUS = 2;
+const S32 ARROW_ANGLE = 30;
+const S32 ARROW_LENGTH_LONG = 10;
+const S32 ARROW_LENGTH_SHORT = 6;
+
+LLXYVector::Params::Params()
+  : x_entry("x_entry"),
+    y_entry("y_entry"),
+    touch_area("touch_area"),
+    border("border"),
+    edit_bar_height("edit_bar_height", 18),
+    padding("padding", 4),
+    min_val_x("min_val_x", -1.0f),
+    max_val_x("max_val_x", 1.0f),
+    increment_x("increment_x", 0.05f),
+    min_val_y("min_val_y", -1.0f),
+    max_val_y("max_val_y", 1.0f),
+    increment_y("increment_y", 0.05f),
+    label_width("label_width", 16),
+    arrow_color("arrow_color", LLColor4::white),
+    ghost_color("ghost_color"),
+    area_color("area_color", LLColor4::grey4),
+    grid_color("grid_color", LLColor4::grey % 0.25f),
+    logarithmic("logarithmic", FALSE)
+{
+}
+
+LLXYVector::LLXYVector(const LLXYVector::Params& p)
+  : LLUICtrl(p),
+    mArrowColor(p.arrow_color()),
+    mAreaColor(p.area_color),
+    mGridColor(p.grid_color),
+    mMinValueX(p.min_val_x),
+    mMaxValueX(p.max_val_x),
+    mIncrementX(p.increment_x),
+    mMinValueY(p.min_val_y),
+    mMaxValueY(p.max_val_y),
+    mIncrementY(p.increment_y),
+    mLogarithmic(p.logarithmic),
+    mValueX(0),
+    mValueY(0)
+{
+    mGhostColor = p.ghost_color.isProvided() ? p.ghost_color() % 0.3f : p.arrow_color() % 0.3f;
+
+    LLRect border_rect = getLocalRect();
+    LLViewBorder::Params params = p.border;
+    params.rect(border_rect);
+    mBorder = LLUICtrlFactory::create<LLViewBorder>(params);
+    addChild(mBorder);
+
+    LLTextBox::Params x_label_params;
+    x_label_params.initial_value(p.x_entry.label());
+    x_label_params.rect = LLRect(p.padding,
+                                 border_rect.mTop - p.padding,
+                                 p.label_width,
+                                 border_rect.getHeight() - p.edit_bar_height);
+    mXLabel = LLUICtrlFactory::create<LLTextBox>(x_label_params);
+    addChild(mXLabel);
+    LLLineEditor::Params x_params = p.x_entry;
+    x_params.rect = LLRect(p.padding + p.label_width,
+                           border_rect.mTop - p.padding,
+                           border_rect.getCenterX(),
+                           border_rect.getHeight() - p.edit_bar_height);
+    x_params.commit_callback.function(boost::bind(&LLXYVector::onEditChange, this));
+    mXEntry = LLUICtrlFactory::create<LLLineEditor>(x_params);
+    mXEntry->setPrevalidateInput(LLTextValidate::validateFloat);
+    addChild(mXEntry);
+
+    LLTextBox::Params y_label_params;
+    y_label_params.initial_value(p.y_entry.label());
+    y_label_params.rect = LLRect(border_rect.getCenterX() + p.padding,
+                                 border_rect.mTop - p.padding,
+                                 border_rect.getCenterX() + p.label_width,
+                                 border_rect.getHeight() - p.edit_bar_height);
+    mYLabel = LLUICtrlFactory::create<LLTextBox>(y_label_params);
+    addChild(mYLabel);
+    LLLineEditor::Params y_params = p.y_entry;
+    y_params.rect = LLRect(border_rect.getCenterX() + p.padding + p.label_width,
+                           border_rect.getHeight() - p.padding,
+                           border_rect.getWidth() - p.padding,
+                           border_rect.getHeight() - p.edit_bar_height);
+    y_params.commit_callback.function(boost::bind(&LLXYVector::onEditChange, this));
+    mYEntry = LLUICtrlFactory::create<LLLineEditor>(y_params);
+    mYEntry->setPrevalidateInput(LLTextValidate::validateFloat);
+    addChild(mYEntry);
+
+    LLPanel::Params touch_area = p.touch_area;
+    touch_area.rect = LLRect(p.padding,
+                             border_rect.mTop - p.edit_bar_height - p.padding,
+                             border_rect.getWidth() - p.padding,
+                             p.padding);
+    mTouchArea = LLUICtrlFactory::create<LLPanel>(touch_area);
+    addChild(mTouchArea);
+}
+
+LLXYVector::~LLXYVector()
+{
+}
+
+BOOL LLXYVector::postBuild()
+{
+    mLogScaleX = (2 * log(mMaxValueX)) / mTouchArea->getRect().getWidth();
+    mLogScaleY = (2 * log(mMaxValueY)) / mTouchArea->getRect().getHeight();
+
+    return TRUE;
+}
+
+void drawArrow(S32 tailX, S32 tailY, S32 tipX, S32 tipY, LLColor4 color)
+{
+    gl_line_2d(tailX, tailY, tipX, tipY, color);
+
+    S32 dx = tipX - tailX;
+    S32 dy = tipY - tailY;
+
+    S32 arrowLength = (abs(dx) < ARROW_LENGTH_LONG && abs(dy) < ARROW_LENGTH_LONG) ? ARROW_LENGTH_SHORT : ARROW_LENGTH_LONG;
+   
+    F32 theta = std::atan2(dy, dx);
+
+    F32 rad = ARROW_ANGLE * std::atan(1) * 4 / 180;
+    F32 x = tipX - arrowLength * cos(theta + rad);
+    F32 y = tipY - arrowLength * sin(theta + rad);
+    F32 rad2 = -1 * ARROW_ANGLE * std::atan(1) * 4 / 180;
+    F32 x2 = tipX - arrowLength * cos(theta + rad2);
+    F32 y2 = tipY - arrowLength * sin(theta + rad2);
+    gl_triangle_2d(tipX, tipY, x, y, x2, y2, color, true);
+}
+
+void LLXYVector::draw()
+{
+    S32 centerX = mTouchArea->getRect().getCenterX();
+    S32 centerY = mTouchArea->getRect().getCenterY();
+    S32 pointX;
+    S32 pointY;
+
+    if (mLogarithmic)
+    {
+        pointX = (log(llabs(mValueX) + 1)) / mLogScaleX;
+        pointX *= (mValueX < 0) ? -1 : 1;
+        pointX += centerX;
+
+        pointY = (log(llabs(mValueY) + 1)) / mLogScaleY;
+        pointY *= (mValueY < 0) ? -1 : 1;
+        pointY += centerY;
+    }
+    else // linear
+    {
+        pointX = centerX + (mValueX * mTouchArea->getRect().getWidth() / (2 * mMaxValueX));
+        pointY = centerY + (mValueY * mTouchArea->getRect().getHeight() / (2 * mMaxValueY));
+    }
+
+    // fill
+    gl_rect_2d(mTouchArea->getRect(), mAreaColor, true);
+
+    // draw grid
+    gl_line_2d(centerX, mTouchArea->getRect().mTop, centerX, mTouchArea->getRect().mBottom, mGridColor);
+    gl_line_2d(mTouchArea->getRect().mLeft, centerY, mTouchArea->getRect().mRight, centerY, mGridColor);
+
+    // draw ghost
+    if (hasMouseCapture())
+    {
+        drawArrow(centerX, centerY, mGhostX, mGhostY, mGhostColor);
+    }
+    else
+    {
+        mGhostX = pointX;
+        mGhostY = pointY;
+    }
+
+    if (abs(mValueX) >= mIncrementX || abs(mValueY) >= mIncrementY)
+    {
+        // draw the vector arrow
+        drawArrow(centerX, centerY, pointX, pointY, mArrowColor);
+    }
+    else
+    {
+        // skip the arrow, set color for center circle
+        gGL.color4fv(mArrowColor.get().mV);
+    }
+
+    // draw center circle
+    gl_circle_2d(centerX, centerY, CENTER_CIRCLE_RADIUS, 12, true);
+
+    LLView::draw();
+}
+
+void LLXYVector::onEditChange()
+{
+    if (getEnabled())
+    {
+        setValueAndCommit(mXEntry->getValue().asReal(), mYEntry->getValue().asReal());
+    }
+}
+
+void LLXYVector::setValue(const LLSD& value)
+{
+    if (value.isArray())
+    {
+        setValue(value[0].asReal(), value[1].asReal());
+    }
+}
+
+void LLXYVector::setValue(F32 x, F32 y)
+{
+    mValueX = ll_round(llclamp(x, mMinValueX, mMaxValueX), mIncrementX);
+    mValueY = ll_round(llclamp(y, mMinValueY, mMaxValueY), mIncrementY);
+
+    update();
+}
+
+void LLXYVector::setValueAndCommit(F32 x, F32 y)
+{
+    if (mValueX != x || mValueY != y)
+    {
+        setValue(x, y);
+        onCommit();
+    }
+}
+
+LLSD LLXYVector::getValue() const
+{
+    LLSD value;
+    value.append(mValueX);
+    value.append(mValueY);
+    return value;
+}
+
+void LLXYVector::update()
+{
+    mXEntry->setValue(mValueX);
+    mYEntry->setValue(mValueY);
+}
+
+BOOL LLXYVector::handleHover(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        if (mLogarithmic)
+        {
+            F32 valueX = llfastpow(F_E, mLogScaleX*(llabs(x - mTouchArea->getRect().getCenterX()))) - 1;
+            valueX *= (x < mTouchArea->getRect().getCenterX()) ? -1 : 1;
+
+            F32 valueY = llfastpow(F_E, mLogScaleY*(llabs(y - mTouchArea->getRect().getCenterY()))) - 1;
+            valueY *= (y < mTouchArea->getRect().getCenterY()) ? -1 : 1;
+
+            setValueAndCommit(valueX, valueY);
+        }
+        else //linear
+        {
+            F32 valueX = 2 * mMaxValueX * F32(x - mTouchArea->getRect().getCenterX()) / mTouchArea->getRect().getWidth();
+            F32 valueY = 2 * mMaxValueY * F32(y - mTouchArea->getRect().getCenterY()) / mTouchArea->getRect().getHeight();
+
+            setValueAndCommit(valueX, valueY);
+        }
+    }
+
+    return TRUE;
+}
+
+BOOL LLXYVector::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+    if (hasMouseCapture())
+    {
+        gFocusMgr.setMouseCapture(NULL);
+        make_ui_sound("UISndClickRelease");
+    }
+
+    if (mTouchArea->getRect().pointInRect(x, y))
+    {
+        return TRUE;
+    }
+    else
+    {
+        return LLUICtrl::handleMouseUp(x, y, mask);
+    }
+}
+
+BOOL LLXYVector::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+
+    if (mTouchArea->getRect().pointInRect(x, y))
+    {
+        gFocusMgr.setMouseCapture(this);
+        make_ui_sound("UISndClick");
+
+        return TRUE;
+    }
+    else
+    {
+        return LLUICtrl::handleMouseDown(x, y, mask);
+    }
+}
+
diff --git a/indra/llui/llxyvector.h b/indra/llui/llxyvector.h
new file mode 100644
index 0000000000000000000000000000000000000000..bb3822dd260800271206c4315ee80e614a0cd424
--- /dev/null
+++ b/indra/llui/llxyvector.h
@@ -0,0 +1,122 @@
+/**
+* @file llxyvector.h
+* @author Andrey Lihatskiy
+* @brief Header file for LLXYVector
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+// A control that allows to set two related vector magnitudes by manipulating a single vector on a plane. 
+
+#ifndef LL_LLXYVECTOR_H
+#define LL_LLXYVECTOR_H
+
+#include "lluictrl.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lllineeditor.h"
+
+class LLXYVector
+    : public LLUICtrl
+{
+public:
+    struct Params
+        : public LLInitParam::Block<Params, LLUICtrl::Params>
+    {
+        Optional<LLLineEditor::Params>		x_entry;
+        Optional<LLLineEditor::Params>		y_entry;
+        Optional<LLPanel::Params>		    touch_area;
+        Optional<LLViewBorder::Params>	    border;
+        Optional<S32>		                edit_bar_height;
+        Optional<S32>		                padding;
+        Optional<S32>		                label_width;
+        Optional<F32>                       min_val_x;
+        Optional<F32>                       max_val_x;
+        Optional<F32>                       increment_x;
+        Optional<F32>                       min_val_y;
+        Optional<F32>                       max_val_y;
+        Optional<F32>                       increment_y;
+        Optional<LLUIColor>                 arrow_color;
+        Optional<LLUIColor>                 ghost_color;
+        Optional<LLUIColor>                 area_color;
+        Optional<LLUIColor>                 grid_color;
+        Optional<BOOL>                      logarithmic;
+
+        Params();
+    };
+
+
+    virtual ~LLXYVector();
+    /*virtual*/ BOOL postBuild();
+
+    virtual BOOL	handleHover(S32 x, S32 y, MASK mask);
+    virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
+    virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
+
+    virtual void	draw();
+
+    virtual void	setValue(const LLSD& value);
+    void	        setValue(F32 x, F32 y);
+    virtual LLSD	getValue() const;
+
+protected:
+    friend class LLUICtrlFactory;
+    LLXYVector(const Params&);
+    void onEditChange();
+
+protected:
+    LLTextBox*          mXLabel;
+    LLTextBox*          mYLabel;
+    LLLineEditor*		mXEntry;
+    LLLineEditor*	    mYEntry;
+    LLPanel*            mTouchArea;
+    LLViewBorder*		mBorder;
+
+private:
+    void update();
+    void setValueAndCommit(F32 x, F32 y);
+
+    F32 mValueX;
+    F32 mValueY;
+
+    F32 mMinValueX;
+    F32 mMaxValueX;
+    F32 mIncrementX;
+    F32 mMinValueY;
+    F32 mMaxValueY;
+    F32 mIncrementY;
+
+    U32 mGhostX;
+    U32 mGhostY;
+
+    LLUIColor mArrowColor;
+    LLUIColor mGhostColor;
+    LLUIColor mAreaColor;
+    LLUIColor mGridColor;
+
+    BOOL mLogarithmic;
+    F32 mLogScaleX;
+    F32 mLogScaleY;
+};
+
+#endif
+
diff --git a/indra/llxml/llxmltree.cpp b/indra/llxml/llxmltree.cpp
index ca98953f9283d90065e7d134bedcfbdfc0740681..ed9c07e1db92bdc4c07bd91ed6f86e13562c15b5 100644
--- a/indra/llxml/llxmltree.cpp
+++ b/indra/llxml/llxmltree.cpp
@@ -111,9 +111,11 @@ LLXmlTreeNode::~LLXmlTreeNode()
 	attribute_map_t::iterator iter;
 	for (iter=mAttributes.begin(); iter != mAttributes.end(); iter++)
 		delete iter->second;
-	child_list_t::iterator child_iter;
-	for (child_iter=mChildList.begin(); child_iter != mChildList.end(); child_iter++)
-		delete *child_iter;
+        for(LLXmlTreeNode* node : mChildren)
+        {
+            delete node;
+        }
+        mChildren.clear();
 }
  
 void LLXmlTreeNode::dump( const std::string& prefix )
@@ -149,15 +151,15 @@ void LLXmlTreeNode::addAttribute(const std::string& name, const std::string& val
 
 LLXmlTreeNode*	LLXmlTreeNode::getFirstChild()
 {
-	mChildListIter = mChildList.begin();
+	mChildrenIter = mChildren.begin();
 	return getNextChild();
 }
 LLXmlTreeNode*	LLXmlTreeNode::getNextChild()
 {
-	if (mChildListIter == mChildList.end())
+	if (mChildrenIter == mChildren.end())
 		return 0;
 	else
-		return *mChildListIter++;
+		return *mChildrenIter++;
 }
 
 LLXmlTreeNode* LLXmlTreeNode::getChildByName(const std::string& name)
@@ -184,7 +186,7 @@ void LLXmlTreeNode::appendContents(const std::string& str)
 void LLXmlTreeNode::addChild(LLXmlTreeNode* child)
 {
 	llassert( child );
-	mChildList.push_back( child );
+	mChildren.push_back( child );
 
 	// Add a name mapping to this node
 	LLStdStringHandle tableptr = mTree->mNodeNames.insert(child->mName);
diff --git a/indra/llxml/llxmltree.h b/indra/llxml/llxmltree.h
index a82fee041612a1697289d3c1b0b868f717dfd243..3e425c3870f712a82f17ef6e63d4d4a931576612 100644
--- a/indra/llxml/llxmltree.h
+++ b/indra/llxml/llxmltree.h
@@ -151,7 +151,7 @@ class LLXmlTreeNode
 	LLXmlTreeNode*	getParent()							{ return mParent; }
 	LLXmlTreeNode*	getFirstChild();
 	LLXmlTreeNode*	getNextChild();
-	S32				getChildCount()						{ return (S32)mChildList.size(); }
+	S32				getChildCount()						{ return (S32)mChildren.size(); }
 	LLXmlTreeNode*  getChildByName( const std::string& name );	// returns first child with name, NULL if none
 	LLXmlTreeNode*  getNextNamedChild();				// returns next child with name, NULL if none
 
@@ -177,9 +177,9 @@ class LLXmlTreeNode
 	std::string							mName;
 	std::string							mContents;
 	
-	typedef std::list<class LLXmlTreeNode *> child_list_t;
-	child_list_t						mChildList;
-	child_list_t::iterator				mChildListIter;
+	typedef std::vector<class LLXmlTreeNode *> children_t;
+	children_t                          mChildren;
+	children_t::iterator				mChildrenIter;
 	
 	typedef std::multimap<LLStdStringHandle, LLXmlTreeNode *> child_map_t;
 	child_map_t							mChildMap;		// for fast name lookups
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index c62fe1a82d47eb99f360e49453a815aa8cdd6ae9..f76012bdfa1284bf1fba8b0f2124f5d9924e55e4 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -171,7 +171,6 @@ set(viewer_SOURCE_FILES
     llcurrencyuimanager.cpp
     llcylinder.cpp
     lldateutil.cpp
-    lldaycyclemanager.cpp
     lldebugmessagebox.cpp
     lldebugview.cpp
     lldeferredsounds.cpp
@@ -194,7 +193,7 @@ set(viewer_SOURCE_FILES
     lldrawpoolwlsky.cpp
     lldynamictexture.cpp
     llemote.cpp
-    llenvmanager.cpp
+    llenvironment.cpp
     llestateinfomodel.cpp
     lleventnotifier.cpp
     lleventpoll.cpp
@@ -234,17 +233,15 @@ set(viewer_SOURCE_FILES
     llfloatercolorpicker.cpp
     llfloaterconversationlog.cpp
     llfloaterconversationpreview.cpp
-    llfloaterdeleteenvpreset.cpp
     llfloaterdeleteprefpreset.cpp
     llfloaterdestinations.cpp
-    llfloatereditdaycycle.cpp
-    llfloatereditsky.cpp
-    llfloatereditwater.cpp
-    llfloaterenvironmentsettings.cpp
+    llfloatereditextdaycycle.cpp
+    llfloaterenvironmentadjust.cpp
     llfloaterevent.cpp
     llfloaterexperiencepicker.cpp
     llfloaterexperienceprofile.cpp
     llfloaterexperiences.cpp
+    llfloaterfixedenvironment.cpp
     llfloaterfonttest.cpp
     llfloaterforgetuser.cpp
     llfloatergesture.cpp
@@ -276,6 +273,7 @@ set(viewer_SOURCE_FILES
     llfloatermodelpreview.cpp
     llfloatermodeluploadbase.cpp
     llfloatermyscripts.cpp
+    llfloatermyenvironment.cpp
     llfloaternamedesc.cpp
     llfloaternotificationsconsole.cpp
     llfloaternotificationstabbed.cpp
@@ -332,6 +330,7 @@ set(viewer_SOURCE_FILES
     llfolderviewmodelinventory.cpp
     llfollowcam.cpp
     llfriendcard.cpp
+    llflyoutcombobtn.cpp
     llgesturelistener.cpp
     llgesturemgr.cpp
     llgiveinventory.cpp
@@ -379,6 +378,7 @@ set(viewer_SOURCE_FILES
     lljoystickbutton.cpp
     lllandmarkactions.cpp
     lllandmarklist.cpp
+    lllegacyatmospherics.cpp
     lllistbrowser.cpp
     lllistcontextmenu.cpp
     lllistview.cpp
@@ -434,7 +434,10 @@ set(viewer_SOURCE_FILES
     llpanelblockedlist.cpp
     llpanelclassified.cpp
     llpanelcontents.cpp
+    llpaneleditsky.cpp
+    llpaneleditwater.cpp
     llpaneleditwearable.cpp
+    llpanelenvironment.cpp
     llpanelexperiencelisteditor.cpp
     llpanelexperiencelog.cpp
     llpanelexperiencepicker.cpp
@@ -553,6 +556,8 @@ set(viewer_SOURCE_FILES
     llsecapi.cpp
     llsechandler_basic.cpp
     llselectmgr.cpp
+    llsettingspicker.cpp
+    llsettingsvo.cpp
     llshareavatarhandler.cpp
     llsidepanelappearance.cpp
     llsidepanelinventory.cpp
@@ -617,6 +622,7 @@ set(viewer_SOURCE_FILES
     lltoolselectland.cpp
     lltoolselectrect.cpp
     lltracker.cpp
+    lltrackpicker.cpp
     lltransientdockablefloater.cpp
     lltransientfloatermgr.cpp
     lltranslate.cpp
@@ -708,19 +714,13 @@ set(viewer_SOURCE_FILES
     llvowater.cpp
     llvowlsky.cpp
     llwatchdog.cpp
-    llwaterparammanager.cpp
-    llwaterparamset.cpp
     llwearableitemslist.cpp
     llwearablelist.cpp
     llweb.cpp
     llwebprofile.cpp
     llwind.cpp
     llwindowlistener.cpp
-    llwlanimator.cpp
-    llwldaycycle.cpp
     llwlhandlers.cpp
-    llwlparammanager.cpp
-    llwlparamset.cpp
     llworld.cpp
     llworldmap.cpp
     llworldmapmessage.cpp
@@ -801,7 +801,6 @@ set(viewer_HEADER_FILES
     llcurrencyuimanager.h
     llcylinder.h
     lldateutil.h
-    lldaycyclemanager.h
     lldebugmessagebox.h
     lldebugview.h
     lldeferredsounds.h
@@ -824,7 +823,7 @@ set(viewer_HEADER_FILES
     lldrawpoolwlsky.h
     lldynamictexture.h
     llemote.h
-    llenvmanager.h
+    llenvironment.h
     llestateinfomodel.h
     lleventnotifier.h
     lleventpoll.h
@@ -865,16 +864,14 @@ set(viewer_HEADER_FILES
     llfloaterconversationlog.h
     llfloaterconversationpreview.h
     llfloaterdeleteprefpreset.h
-    llfloaterdeleteenvpreset.h
     llfloaterdestinations.h
-    llfloatereditdaycycle.h
-    llfloatereditsky.h
-    llfloatereditwater.h
-    llfloaterenvironmentsettings.h
+    llfloatereditextdaycycle.h
+    llfloaterenvironmentadjust.h
     llfloaterevent.h
     llfloaterexperiencepicker.h
     llfloaterexperienceprofile.h
     llfloaterexperiences.h
+    llfloaterfixedenvironment.h
     llfloaterfonttest.h
     llfloaterforgetuser.h
     llfloatergesture.h
@@ -909,6 +906,7 @@ set(viewer_HEADER_FILES
     llfloatermodelpreview.h
     llfloatermodeluploadbase.h
     llfloatermyscripts.h
+    llfloatermyenvironment.h
     llfloaternamedesc.h
     llfloaternotificationsconsole.h
     llfloaternotificationstabbed.h
@@ -965,6 +963,7 @@ set(viewer_HEADER_FILES
     llfolderviewmodelinventory.h
     llfollowcam.h
     llfriendcard.h
+    llflyoutcombobtn.h
     llgesturelistener.h
     llgesturemgr.h
     llgiveinventory.h
@@ -1057,7 +1056,10 @@ set(viewer_HEADER_FILES
     llpanelblockedlist.h
     llpanelclassified.h
     llpanelcontents.h
+    llpaneleditsky.h
+    llpaneleditwater.h
     llpaneleditwearable.h
+    llpanelenvironment.h
     llpanelexperiencelisteditor.h
     llpanelexperiencelog.h
     llpanelexperiencepicker.h
@@ -1175,6 +1177,8 @@ set(viewer_HEADER_FILES
     llsecapi.h
     llsechandler_basic.h
     llselectmgr.h
+    llsettingspicker.h
+    llsettingsvo.h
     llsidepanelappearance.h
     llsidepanelinventory.h
     llsidepanelinventorysubpanel.h
@@ -1240,6 +1244,7 @@ set(viewer_HEADER_FILES
     lltoolselectland.h
     lltoolselectrect.h
     lltracker.h
+    lltrackpicker.h
     lltransientdockablefloater.h
     lltransientfloatermgr.h
     lltranslate.h
@@ -1332,19 +1337,13 @@ set(viewer_HEADER_FILES
     llvowater.h
     llvowlsky.h
     llwatchdog.h
-    llwaterparammanager.h
-    llwaterparamset.h
     llwearableitemslist.h
     llwearablelist.h
     llweb.h
     llwebprofile.h
     llwind.h
     llwindowlistener.h
-    llwlanimator.h
-    llwldaycycle.h
     llwlhandlers.h
-    llwlparammanager.h
-    llwlparamset.h
     llworld.h
     llworldmap.h
     llworldmapmessage.h
@@ -2538,7 +2537,6 @@ if (LL_TESTS)
 include(LLAddBuildTest)
 SET(viewer_TEST_SOURCE_FILES
   llagentaccess.cpp
-  llwlparammanager.cpp
   )
 set_source_files_properties(
   ${viewer_TEST_SOURCE_FILES}
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 291cd91eb19d5885c979e520aea0cc5cad51dab6..4c77920fd2c5a9321491ced9a71b2ca654bf3798 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.3.9
+6.4.1
diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml
index e4e1cdcf449803925ebe6ae72e614f0e4b3a68ed..4e186292f77d6e4c3f99f035e75f3b80141c2179 100644
--- a/indra/newview/app_settings/cmd_line.xml
+++ b/indra/newview/app_settings/cmd_line.xml
@@ -407,5 +407,14 @@
       <integer>1</integer>
       <!-- Special case. Mapped to settings procedurally. -->
     </map>
+
+    <key>skipupdatecheck</key>
+    <map>
+      <key>desc</key>
+      <string>Skips update check at startup.</string>
+      <key>map-to</key>
+      <string>CmdLineSkipUpdater</string>
+    </map>
+
   </map>
 </llsd>
diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml
index 98143bbce61353b4275cec36ad8a5121e5af5c30..9a4ab8b44ba2b85599900fa95dcfa3e18e650dd7 100644
--- a/indra/newview/app_settings/commands.xml
+++ b/indra/newview/app_settings/commands.xml
@@ -263,4 +263,15 @@
            is_running_function="Floater.IsOpen"
            is_running_parameters="grid_status"
            />
+  <command name="myenvironments"
+         available_in_toybox="true"
+         is_flashing_allowed="true"
+         icon="Command_Environments_Icon"
+         label_ref="Command_Environments_Label"
+         tooltip_ref="Command_Environments_Tooltip"
+         execute_function="Floater.ToggleOrBringToFront"
+         execute_parameters="my_environments"
+         is_running_function="Floater.IsOpen"
+         is_running_parameters="my_environments"
+           />
 </commands>
diff --git a/indra/newview/app_settings/high_graphics.xml b/indra/newview/app_settings/high_graphics.xml
index c38b3fcda4a3faf85febaba157a4745236ddd39c..662f7e39dd1739742cb25140eee1f3e5fac53210 100644
--- a/indra/newview/app_settings/high_graphics.xml
+++ b/indra/newview/app_settings/high_graphics.xml
@@ -33,8 +33,6 @@
 	<!--Default for now-->
 	<RenderVolumeLODFactor value="1.125"/>
 	<!--NO SHADERS-->
-	<VertexShaderEnable value="TRUE"/>
-	<!--NO SHADERS-->
 	<WindLightUseAtmosShaders value="TRUE"/>
 	<!--Deferred Shading-->
 	<RenderDeferred value="FALSE"/>
diff --git a/indra/newview/app_settings/low_graphics.xml b/indra/newview/app_settings/low_graphics.xml
index df3f67a5a1a6345478e1ca0cafcd8bcf7dd39b66..0ee8e7a05988a3ed78101e7f064c27b1253c1a53 100644
--- a/indra/newview/app_settings/low_graphics.xml
+++ b/indra/newview/app_settings/low_graphics.xml
@@ -33,8 +33,6 @@
 	<!--Default for now-->
 	<RenderVolumeLODFactor value="1.125"/>
 	<!--NO SHADERS-->
-	<VertexShaderEnable value="FALSE"/>
-	<!--NO SHADERS-->
 	<WindLightUseAtmosShaders value="FALSE"/>
 	<!--No Deferred Shading-->
 	<RenderDeferred value="FALSE"/>
diff --git a/indra/newview/app_settings/mid_graphics.xml b/indra/newview/app_settings/mid_graphics.xml
index a10c02b79f21ccce113b709ecd7559d14a61a7f5..c89e060307a72a0777b8a863fd5f3ac1570d374f 100644
--- a/indra/newview/app_settings/mid_graphics.xml
+++ b/indra/newview/app_settings/mid_graphics.xml
@@ -33,8 +33,6 @@
 	<!--Default for now-->
 	<RenderVolumeLODFactor value="1.125"/>
 	<!--NO SHADERS-->
-	<VertexShaderEnable value="TRUE"/>
-	<!--NO SHADERS-->
 	<WindLightUseAtmosShaders value="FALSE"/>
 	<!--No Deferred Shading-->
 	<RenderDeferred value="FALSE"/>
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 3e3d6a7237866373a00cc7db757f715b5c228dd1..86c6b409de113353789a9fbc7fe65a359b0519e9 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1252,6 +1252,17 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>BulkChangeIncludeSettings</key>
+    <map>
+      <key>Comment</key>
+      <string>Bulk permission changes affect environment settings</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>BulkChangeEveryoneCopy</key>
     <map>
       <key>Comment</key>
@@ -1955,7 +1966,18 @@
       <key>Value</key>
       <string/>
     </map>
-    <key>ConnectAsGod</key>
+    <key>CmdLineSkipUpdater</key>
+    <map>
+      <key>Comment</key>
+      <string>Command line skip updater check.</string>
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+  <key>ConnectAsGod</key>
     <map>
       <key>Comment</key>
       <string>Log in a god if you have god access.</string>
@@ -6773,6 +6795,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>MouseMoon</key>
+    <map>
+      <key>Comment</key>
+      <string />
+      <key>Persist</key>
+      <integer>0</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
    <key>MuteAmbient</key>
     <map>
       <key>Comment</key>
@@ -8593,6 +8626,28 @@
     </array>
   </map>
 
+    <key>RenderAlphaBatchFullbrights</key>
+    <map>
+      <key>Comment</key>
+      <string>Render fullbright alpha content more efficiently, but with possible visual differences from prev viewers.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>RenderAlphaBatchEmissives</key>
+    <map>
+      <key>Comment</key>
+      <string>Render emissive alpha content more efficiently, but with possible visual differences from prev viewers.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>RenderAnisotropic</key>
     <map>
       <key>Comment</key>
@@ -9222,7 +9277,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>-0.008</real>
+    <real>-0.004</real>
   </map>
   <key>RenderShadowOffset</key>
   <map>
@@ -10323,6 +10378,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>RenderUseAdvancedAtmospherics</key>
+  <map>
+    <key>Comment</key>
+    <string>Use fancy precomputed atmospherics and stuff.</string>
+    <key>Persist</key>
+    <integer>1</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
   <key>RenderUseTriStrips</key>
   <map>
     <key>Comment</key>
@@ -12038,6 +12104,21 @@
       <key>Value</key>
       <real>0.300000011921</real>
     </map>
+    <key>SkyMoonDefaultPosition</key>
+    <map>
+      <key>Comment</key>
+      <string>Default position of sun in sky (direction in world coordinates)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Vector3</string>
+      <key>Value</key>
+      <array>
+        <real>-1.0</real>
+        <real>0.0</real>
+        <real>-0.1</real>
+      </array>
+    </map>
     <key>SkyNightColorShift</key>
     <map>
       <key>Comment</key>
@@ -12354,6 +12435,39 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+  <key>AmbientDisable</key>
+  <map>
+    <key>Comment</key>
+    <string>If TRUE, ambient light has no effect</string>
+    <key>Persist</key>
+    <integer>0</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>SunlightDisable</key>
+  <map>
+    <key>Comment</key>
+    <string>If TRUE, sunlight has no effect</string>
+    <key>Persist</key>
+    <integer>0</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
+  <key>LocalLightDisable</key>
+  <map>
+    <key>Comment</key>
+    <string>If TRUE, local lights have no effect</string>
+    <key>Persist</key>
+    <integer>0</integer>
+    <key>Type</key>
+    <string>Boolean</string>
+    <key>Value</key>
+    <integer>0</integer>
+  </map>
     <key>TextureDiscardLevel</key>
     <map>
       <key>Comment</key>
@@ -14202,6 +14316,7 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <!-- SL-12594 removes fixed function rendering
     <key>VertexShaderEnable</key>
     <map>
       <key>Comment</key>
@@ -14213,6 +14328,7 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <-->
     <key>VivoxAutoPostCrashDumps</key>
     <map>
       <key>Comment</key>
@@ -14895,6 +15011,28 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>sunbeacon</key>
+    <map>
+      <key>Comment</key>
+      <string>Show direction to the Sun</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
+    <key>moonbeacon</key>
+    <map>
+      <key>Comment</key>
+      <string>Show direction to the Moon</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>ShowDeviceSettings</key>
     <map>
       <key>Comment</key>
@@ -15857,6 +15995,28 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>SettingsNextOwnerModify</key>
+    <map>
+      <key>Comment</key>
+      <string>Newly created Environment setting can be modified by next owner</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
+    <key>SettingsNextOwnerTransfer</key>
+    <map>
+      <key>Comment</key>
+      <string>Newly created Environment setting can be resold or given away by next owner</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>1</integer>
+    </map>
     <key>DefaultUploadPermissionsConverted</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
index 19203ab6707879df20d56cdc4c3e678d9e2b2e09..0543a26642b1560d071dfa6e3f937278cc9d5103 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl
@@ -34,7 +34,7 @@ VARYING vec2 vary_texcoord0;
 
 uniform vec4 color;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 mat4 getSkinnedTransform();
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -62,7 +62,7 @@ void main()
 	
 	calcAtmospherics(pos.xyz);
 
-	vec4 col = calcLighting(pos.xyz, norm, color, vec4(0,0,0,0));
+	vec4 col = calcLighting(pos.xyz, norm, color);
 	vertex_color = col; 
 
 }
diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
index 82db15c3aeb0e6116a2c7d2a13c73ac6e429854c..fac1599c6b2418314f5d3b29692d6113ad8d16ae 100644
--- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl
@@ -36,7 +36,7 @@ ATTRIBUTE vec2 texcoord0;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
+vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor);
 void calcAtmospherics(vec3 inPositionEye);
 
 void main()
@@ -52,7 +52,7 @@ void main()
 	calcAtmospherics(pos.xyz);
 
 	vec4 specular = vec4(1.0);
-	vec4 color = calcLightingSpecular(pos, norm, diffuse_color, specular, vec4(0.0));	
+	vec4 color = calcLightingSpecular(pos, norm, diffuse_color, specular);	
 	vertex_color = color;
 
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index b9c8f34cb06e8df3324707276e9aa00b94c9a8bc..dc484317e9ecc8afd2f461a5cd03d53869dd7ec1 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -22,7 +22,9 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
+//class1/deferred/alphaF.glsl
+
 #extension GL_ARB_texture_rectangle : enable
 
 /*[EXTRA_CODE_HERE]*/
@@ -37,39 +39,9 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
-uniform float display_gamma;
-uniform vec4 gamma;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-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 float scene_light_strength;
 uniform mat3 env_mat;
-uniform mat3 ssao_effect_mat;
-
 uniform vec3 sun_dir;
-
-#if HAS_SHADOW
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-
-uniform vec2 shadow_res;
-
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float shadow_bias;
-
-#endif
+uniform vec3 moon_dir;
 
 #ifdef USE_DIFFUSE_TEX
 uniform sampler2D diffuseMap;
@@ -81,551 +53,254 @@ VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_norm;
 
 #ifdef USE_VERTEX_COLOR
-VARYING vec4 vertex_color;
+VARYING vec4 vertex_color; //vertex color should be treated as sRGB
 #endif
 
-vec3 vary_PositionEye;
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
+uniform mat4 proj_mat;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
-
+uniform int sun_up_factor;
 uniform vec4 light_position[8];
 uniform vec3 light_direction[8];
-uniform vec3 light_attenuation[8]; 
+uniform vec4 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
 #endif
 
-}
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
 
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
+vec2 encode_normal (vec3 n);
+vec3 scaleSoftClipFrag(vec3 l);
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten);
 
-}
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive, bool use_ao);
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+#ifdef HAS_SHADOW
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+#endif
 
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
+float getAmbientClamp();
 
-vec3 calcDirectionalLight(vec3 n, vec3 l)
+vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
 {
-	float a = max(dot(n,l),0.0);
-	a = pow(a, 1.0/1.3);
-	return vec3(a,a,a);
-}
+    vec3 col = vec3(0);
 
-vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
-{
 	//get light vector
 	vec3 lv = lp.xyz-v;
-	
+
 	//get distance
-	float d = length(lv);
-	
+	float dist = length(lv);
 	float da = 1.0;
 
-	vec3 col = vec3(0);
-
-	if (d > 0.0 && la > 0.0 && fa > 0.0)
+    /*if (dist > la)
+    {
+        return col;
+    }
+
+    clip to projector bounds
+     vec4 proj_tc = proj_mat * lp;
+
+    if (proj_tc.z < 0
+     || proj_tc.z > 1
+     || proj_tc.x < 0
+     || proj_tc.x > 1 
+     || proj_tc.y < 0
+     || proj_tc.y > 1)
+    {
+        return col;
+    }*/
+
+	if (dist > 0.0 && la > 0.0)
 	{
+        dist /= la;
+
 		//normalize light vector
 		lv = normalize(lv);
 	
 		//distance attenuation
-		float dist = d/la;
 		float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
 		dist_atten *= dist_atten;
-		dist_atten *= 2.0;
+        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 *= max(dot(n, lv), 0.0);		
-
-		float lit = max(da * dist_atten,0.0);
-
-		col = light_col * lit * diffuse;
-
-		// no spec for alpha shader...
-	}
-
-	return max(col, vec3(0.0,0.0,0.0));
+		da *= dot(n, lv);
+        da = max(0.0, da);
+
+		float lit = 0.0f;
+
+        float amb_da = 0.0;//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 work out why this blows out in many setups...
+        //col.rgb += amb_da * light_col * diffuse;
+
+        // no spec for alpha shader...
+    }
+    col = max(col, vec3(0));
+    return col;
 }
 
-#if HAS_SHADOW
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
+void main() 
 {
-	stc.xyz /= stc.w;
-	stc.z += shadow_bias;
-		
-	stc.x = floor(stc.x*shadow_res.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
-	
-	float cs = shadow2D(shadowMap, stc.xyz).x;
-	float shadow = cs;
-	
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-                       
-    return shadow*0.2;
-}
-#endif
+    vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+    frag *= screen_res;
+    
+    vec4 pos = vec4(vary_position, 1.0);
+    vec3 norm = vary_norm;
 
-#ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
+    float shadow = 1.0f;
 
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
+#ifdef HAS_SHADOW
+    shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
 #endif
 
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(0);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//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;
-	
-	//increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
+#ifdef USE_DIFFUSE_TEX
+    vec4 diffuse_tap = texture2D(diffuseMap,vary_texcoord0.xy);
+#endif
 
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
+#ifdef USE_INDEXED_TEX
+    vec4 diffuse_tap = diffuseLookup(vary_texcoord0.xy);
+#endif
 
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
+    vec4 diffuse_srgb = diffuse_tap;
+    vec4 diffuse_linear = vec4(srgb_to_linear(diffuse_srgb.rgb), diffuse_srgb.a);
 
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
+#ifdef FOR_IMPOSTOR
+    vec4 color;
+    color.rgb = diffuse_srgb.rgb;
+    color.a = 1.0;
+
+    float final_alpha = diffuse_srgb.a * vertex_color.a;
+    diffuse_srgb.rgb *= vertex_color.rgb;
+    diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb); 
+    
+    // Insure we don't pollute depth with invis pixels in impostor rendering
+    //
+    if (final_alpha < 0.01)
+    {
+        discard;
+    }
+#else
+    
+    vec3 light_dir = (sun_up_factor == 1) ? sun_dir: moon_dir;
 
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
+    float final_alpha = diffuse_linear.a;
 
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f));
-}
+#ifdef USE_VERTEX_COLOR
+    final_alpha *= vertex_color.a;
+    diffuse_srgb.rgb *= vertex_color.rgb;
+    diffuse_linear.rgb = srgb_to_linear(diffuse_srgb.rgb);
+#endif
 
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity);
-}
+    vec3 sunlit;
+    vec3 amblit;
+    vec3 additive;
+    vec3 atten;
 
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-    vec3 zeroes = vec3(0.0f, 0.0f, 0.0f);
-    vec3 ones   = vec3(1.0f, 1.0f, 1.0f);
+    calcAtmosphericVars(pos.xyz, light_dir, 1.0, sunlit, amblit, additive, atten, false);
 
-	light = ones - clamp(light, zeroes, ones);
-	light = ones - pow(light, gamma.xxx);
+    vec2 abnormal = encode_normal(norm.xyz);
 
-	return light;
-}
+    float da = dot(norm.xyz, light_dir.xyz);
+          da = clamp(da, -1.0, 1.0);
+          da = pow(da, 1.0/1.3);
+ 
+    float final_da = da;
+          final_da = clamp(final_da, 0.0f, 1.0f);
 
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
+    vec4 color = vec4(0.0);
 
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
+    color.a   = final_alpha;
 
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
+    float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
+    ambient *= 0.5;
+    ambient *= ambient;
+    ambient = (1.0 - ambient);
 
-void main() 
-{
-	vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
-	frag *= screen_res;
-	
-	vec4 pos = vec4(vary_position, 1.0);
-	
-	float shadow = 1.0;
-
-#if HAS_SHADOW
-	vec4 spos = pos;
-		
-	if (spos.z > -shadow_clip.w)
-	{	
-		shadow = 0.0;
-
-		vec4 lpos;
-		
-		vec4 near_split = shadow_clip*-0.75;
-		vec4 far_split = shadow_clip*-1.25;
-		vec4 transition_domain = near_split-far_split;
-		float weight = 0.0;
-
-		if (spos.z < near_split.z)
-		{
-			lpos = shadow_matrix[3]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap3, lpos)*w;
-			weight += w;
-			shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-		}
-
-		if (spos.z < near_split.y && spos.z > far_split.z)
-		{
-			lpos = shadow_matrix[2]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap2, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z < near_split.x && spos.z > far_split.y)
-		{
-			lpos = shadow_matrix[1]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-			shadow += pcfShadow(shadowMap1, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z > far_split.x)
-		{
-			lpos = shadow_matrix[0]*spos;
-							
-			float w = 1.0;
-			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-			shadow += pcfShadow(shadowMap0, lpos)*w;
-			weight += w;
-		}
-		
-
-		shadow /= weight;
-	}
-	else
-	{
-		shadow = 1.0;
-	}
-#endif
+    vec3 sun_contrib = min(final_da, shadow) * sunlit;
 
-#ifdef USE_INDEXED_TEX
-	vec4 diff = diffuseLookup(vary_texcoord0.xy);
-#else
-	vec4 diff = texture2D(diffuseMap,vary_texcoord0.xy);
+#if !defined(AMBIENT_KILL)
+    color.rgb = amblit;
+    color.rgb *= ambient;
 #endif
 
-#ifdef FOR_IMPOSTOR
-	vec4 color;
-	color.rgb = diff.rgb;
-	color.a = 1.0;
+vec3 post_ambient = color.rgb;
 
-#ifdef USE_VERTEX_COLOR
-	float final_alpha = diff.a * vertex_color.a;
-	diff.rgb *= vertex_color.rgb;
-#else
-	float final_alpha = diff.a;
-#endif
-	
-	// Insure we don't pollute depth with invis pixels in impostor rendering
-	//
-	if (final_alpha < 0.01)
-	{
-		discard;
-	}
-#else
-	
-#ifdef USE_VERTEX_COLOR
-	float final_alpha = diff.a * vertex_color.a;
-	diff.rgb *= vertex_color.rgb;
-#else
-	float final_alpha = diff.a;
+#if !defined(SUNLIGHT_KILL)
+    color.rgb += sun_contrib;
 #endif
 
+vec3 post_sunlight = color.rgb;
 
-	vec4 gamma_diff = diff;	
-	diff.rgb = srgb_to_linear(diff.rgb);
+    color.rgb *= diffuse_srgb.rgb;
 
-	vec3 norm = vary_norm; 
+vec3 post_diffuse = color.rgb;
 
-	calcAtmospherics(pos.xyz, 1.0);
+    color.rgb = atmosFragLighting(color.rgb, additive, atten);
 
-	vec2 abnormal	= encode_normal(norm.xyz);
-		 norm.xyz   = decode_normal(abnormal.xy);
+vec3 post_atmo = color.rgb;
 
-	float da = dot(norm.xyz, sun_dir.xyz);
+    vec4 light = vec4(0,0,0,0);
+    
+    color.rgb = scaleSoftClipFrag(color.rgb);
 
-    float final_da = da;
-          final_da = min(final_da, shadow);
-          final_da = max(final_da, 0.0f);
-		  final_da = min(final_da, 1.0f);
-		  final_da = pow(final_da, 1.0/1.3);
+    //convert to linear before applying local lights
+    color.rgb = srgb_to_linear(color.rgb);
 
-	vec4 color = vec4(0,0,0,0);
+   #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diffuse_linear.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, light_attenuation[i].w);
 
-	color.rgb = atmosAmbient(color.rgb);
-	color.a   = final_alpha;
-
-	float ambient = abs(da);
-	ambient *= 0.5;
-	ambient *= ambient;
-	ambient = (1.0-ambient);
-
-	color.rgb *= ambient;
-	color.rgb += atmosAffectDirectionalLight(final_da);
-	color.rgb *= gamma_diff.rgb;
-
-	//color.rgb = mix(diff.rgb, color.rgb, final_alpha);
-	
-	color.rgb = atmosLighting(color.rgb);
-	color.rgb = scaleSoftClip(color.rgb);
+    LIGHT_LOOP(1)
+    LIGHT_LOOP(2)
+    LIGHT_LOOP(3)
+    LIGHT_LOOP(4)
+    LIGHT_LOOP(5)
+    LIGHT_LOOP(6)
+    LIGHT_LOOP(7)
 
-	vec4 light = vec4(0,0,0,0);
-
-	color.rgb = srgb_to_linear(color.rgb);
-	
-   #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, diff.rgb, pos.xyz, norm, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z);
-
-	LIGHT_LOOP(1)
-	LIGHT_LOOP(2)
-	LIGHT_LOOP(3)
-	LIGHT_LOOP(4)
-	LIGHT_LOOP(5)
-	LIGHT_LOOP(6)
-	LIGHT_LOOP(7)
-
-	// keep it linear
-	//
-	color.rgb += light.rgb;
-
-	// straight to display gamma, we're post-deferred
-	//
-	color.rgb = linear_to_srgb(color.rgb);
+    // sum local light contrib in linear colorspace
+#if !defined(LOCAL_LIGHT_KILL)
+    color.rgb += light.rgb;
+#endif
+    // back to sRGB as we're going directly to the final RT post-deferred gamma correction
+    color.rgb = linear_to_srgb(color.rgb);
+
+//color.rgb = amblit;
+//color.rgb = vec3(ambient);
+//color.rgb = sunlit;
+//color.rgb = vec3(final_da);
+//color.rgb = post_ambient;
+//color.rgb = post_sunlight;
+//color.rgb = sun_contrib;
+//color.rgb = diffuse_srgb.rgb;
+//color.rgb = post_diffuse;
+//color.rgb = post_atmo;
 
 #ifdef WATER_FOG
-	color = applyWaterFogDeferred(pos.xyz, color);
-#endif
+    color = applyWaterFogView(pos.xyz, color);
+#endif // WATER_FOG
 
 #endif
-
-	frag_color = color;
+    
+    frag_color = color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..23adbded5e16fe884285fa35801aebf9b2ded8c1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/aoUtil.glsl
@@ -0,0 +1,123 @@
+/** 
+ * @file class1/deferred/aoUtil.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$
+ */
+
+uniform sampler2D       noiseMap;
+uniform sampler2DRect   normalMap;
+uniform sampler2DRect   depthMap;
+
+uniform float ssao_radius;
+uniform float ssao_max_radius;
+uniform float ssao_factor;
+uniform float ssao_factor_inv;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec2 getScreenCoordinateAo(vec2 screenpos)
+{
+    vec2 sc = screenpos.xy * 2.0;
+    if (screen_res.x > 0 && screen_res.y > 0)
+    {
+       sc /= screen_res;
+    }
+    return sc - vec2(1.0, 1.0);
+}
+
+float getDepthAo(vec2 pos_screen)
+{
+    float depth = texture2DRect(depthMap, pos_screen).r;
+    return depth;
+}
+
+vec4 getPositionAo(vec2 pos_screen)
+{
+    float depth = getDepthAo(pos_screen);
+    vec2 sc = getScreenCoordinateAo(pos_screen);
+    vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+    vec4 pos = inv_proj * ndc;
+    pos /= pos.w;
+    pos.w = 1.0;
+    return pos;
+}
+
+vec2 getKern(int i)
+{
+    vec2 kern[8];
+    // exponentially (^2) distant occlusion samples spread around origin
+    kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+    kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+    kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+    kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+    kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+    kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+    kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+    kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+       
+    return kern[i];
+}
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen)
+{
+    float ret = 1.0;
+    vec3 pos_world = pos.xyz;
+    vec2 noise_reflect = texture2D(noiseMap, pos_screen.xy/128.0).xy;
+        
+    float angle_hidden = 0.0;
+    float points = 0;
+        
+    float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+    
+    // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+    for (int i = 0; i < 8; i++)
+    {
+        vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
+        vec3 samppos_world = getPositionAo(samppos_screen).xyz; 
+        
+        vec3 diff = pos_world - samppos_world;
+        float dist2 = dot(diff, diff);
+            
+        // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+        // --> solid angle shrinking by the square of distance
+        //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+        //(k should vary inversely with # of samples, but this is taken care of later)
+        
+        float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
+        angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
+            
+        // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
+        float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
+        points = points + diffz_val;
+    }
+        
+    angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
+    
+    float points_val = (points > 0.0) ? 1.0 : 0.0;
+    ret = (1.0 - (points_val * angle_hidden));
+
+    ret = max(ret, 0.0);
+    return min(ret, 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
index 22c9a4d14e3d88137df21be5e1e4139713b12b31..8e9a5fcd41853a029504b0c94981a080693f4b71 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl
@@ -22,6 +22,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
index 3f90600acefdc2d5915284c7243bee9cd8f13598..0fa0edfd6716c4bee8da6b3cadbc8328144fbb0b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl
@@ -41,7 +41,7 @@ void main()
 	
 
 	vec4 p = projection_matrix * vec4(pos, 1.0);
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 	p.z = max(p.z, -p.w+0.01);
 	gl_Position = p;
 #else
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl
index c8ddefac266f1679d90ed5c7a4c156b0cad1bc4e..bbdc8fdd1ca1caa7b6df5c31f6a4d80e0aa2f2e3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaNoColorV.glsl
@@ -29,17 +29,13 @@ ATTRIBUTE vec3 position;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
 mat4 getSkinnedTransform();
 void calcAtmospherics(vec3 inPositionEye);
 
 float calcDirectionalLight(vec3 n, vec3 l);
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
-vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
 
 VARYING vec3 vary_position;
 VARYING vec3 vary_ambient;
@@ -59,41 +55,7 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-float calcDirectionalLight(vec3 n, vec3 l)
-{
-        float a = max(dot(n,l),0.0);
-        return a;
-}
-
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
-{
-	//get light vector
-	vec3 lv = lp.xyz-v;
-	
-	//get distance
-	float d = dot(lv,lv);
-	
-	float da = 0.0;
-
-	if (d > 0.0 && la > 0.0 && fa > 0.0)
-	{
-		//normalize light vector
-		lv = normalize(lv);
-	
-		//distance attenuation
-		float dist2 = d/la;
-		da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
-
-		// spotlight coefficient.
-		float spot = max(dot(-ln, lv), is_pointlight);
-		da *= spot*spot; // GL_SPOT_EXPONENT=2
-
-		//angular attenuation
-		da *= max(dot(n, lv), 0.0);		
-	}
-
-	return da;	
-}
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight);
 
 void main()
 {
@@ -137,7 +99,7 @@ void main()
 	col.rgb = vec3(0,0,0);
 
 	// Add windlight lights
-	col.rgb = atmosAmbient(vec3(0.));
+	col.rgb = atmosAmbient();
 	
 	vary_ambient = col.rgb*color.rgb;
 	vary_directional = color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, light_position[0].xyz), 0.0));
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
index 662c762bca2e408b20aa3fbecd217f29d616cf4d..60d83cc62328e1697584efa7e175133031e03826 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -36,11 +38,7 @@ uniform float minimum_alpha;
 VARYING vec3 vary_normal;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
index b809b73973bdf813d0401694bf350674e4074df2..50020a50d8a3c8485be7191c8bcccba64b206ec4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl
@@ -22,7 +22,9 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
+/*[EXTRA_CODE_HERE]*/ 
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
@@ -31,7 +33,7 @@ out vec4 frag_color;
 
 uniform sampler2D diffuseMap;
 
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 VARYING vec4 post_pos;
 #endif
 
@@ -39,7 +41,7 @@ void main()
 {
 	frag_color = vec4(1,1,1,1);
 
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
 #endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
index bde1ad4e9f81cf70517257024554dd98fc0d33e9..91b25613e0e319cbf6b547c0610f74171b7ffe2e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl
@@ -31,7 +31,7 @@ ATTRIBUTE vec3 position;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
 
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 VARYING vec4 post_pos;
 #endif
 
@@ -53,7 +53,7 @@ void main()
 	norm = normalize(norm);
 	
 	pos = projection_matrix * pos;
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 	post_pos = pos;
 
 	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index cbd8d2ebfc8d6d4e444bc7246673f7f085a7cd9f..596d0274af3061d3fc4e7aebdfbb077f64788d15 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -33,7 +33,6 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
-uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 
@@ -45,100 +44,68 @@ uniform float kern_scale;
 
 VARYING vec2 vary_fragcoord;
 
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
 void main() 
 {
     vec2 tc = vary_fragcoord.xy;
-	vec3 norm = texture2DRect(normalMap, tc).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-
-	vec3 pos = getPosition(tc).xyz;
-	vec4 ccol = texture2DRect(lightMap, tc).rgba;
-	
-	vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-	dlt /= max(-pos.z*dist_factor, 1.0);
-	
-	vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
-	vec4 col = defined_weight.xyxx * ccol;
-
-	// relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
-	float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
-
-	// perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
-	float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
-	tc_mod -= floor(tc_mod);
-	tc_mod *= 2.0;
-	tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
-
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 samptc = tc + kern[i].z*dlt;
-	    vec3 samppos = getPosition(samptc).xyz; 
-
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		
-		if (d*d <= pointplanedist_tolerance_pow2)
-		{
-			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-
-	for (int i = 1; i < 4; i++)
-	{
-		vec2 samptc = tc - kern[i].z*dlt;
-	    vec3 samppos = getPosition(samptc).xyz; 
-
-		float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
-		
-		if (d*d <= pointplanedist_tolerance_pow2)
-		{
-			col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
-			defined_weight += kern[i].xy;
-		}
-	}
-
-	col /= defined_weight.xyxx;
-	col.y *= col.y;
-	
-	frag_color = col;
+    vec3 norm = getNorm(tc);
+    vec3 pos = getPosition(tc).xyz;
+    vec4 ccol = texture2DRect(lightMap, tc).rgba;
+    
+    vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
+    dlt /= max(-pos.z*dist_factor, 1.0);
+    
+    vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+    vec4 col = defined_weight.xyxx * ccol;
+
+    // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+    float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+    // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+    float tc_mod = 0.5*(tc.x + tc.y); // mod(tc.x+tc.y,2)
+    tc_mod -= floor(tc_mod);
+    tc_mod *= 2.0;
+    tc += ( (tc_mod - 0.5) * kern[1].z * dlt * 0.5 );
+
+    for (int i = 1; i < 4; i++)
+    {
+        vec2 samptc = tc + kern[i].z*dlt;
+        vec3 samppos = getPosition(samptc).xyz; 
+
+        float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+        
+        if (d*d <= pointplanedist_tolerance_pow2)
+        {
+            col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+            defined_weight += kern[i].xy;
+        }
+    }
+
+    for (int i = 1; i < 4; i++)
+    {
+        vec2 samptc = tc - kern[i].z*dlt;
+        vec3 samppos = getPosition(samptc).xyz; 
+
+        float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+        
+        if (d*d <= pointplanedist_tolerance_pow2)
+        {
+            col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
+            defined_weight += kern[i].xy;
+        }
+    }
+
+    col /= defined_weight.xyxx;
+    col.y *= col.y;
+    
+    frag_color = col;
 
 #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.
-	vec3 dummy1 = kern[0];
-	vec3 dummy2 = kern[3];
+    // 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.
+    vec3 dummy1 = kern[0];
+    vec3 dummy2 = kern[3];
 #endif
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
index 58fb01d2004914159f970d80830e453a112d296b..b5677a07ee666db52d54b3291e5637e035ce5cf3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl
@@ -22,6 +22,8 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
+
+/*[EXTRA_CODE_HERE]*/
  
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
@@ -40,11 +42,7 @@ VARYING vec3 vary_mat2;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..0157d166e0d901d54a4fe6cd71231f7238cf99c7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowF.glsl
@@ -0,0 +1,127 @@
+/** 
+ * @file class3/deferred/cloudsF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING float vary_CloudDensity;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+
+uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 sunlight_color;
+uniform vec4 cloud_color;
+uniform float cloud_shadow;
+uniform float cloud_scale;
+uniform float cloud_variance;
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+
+#if !defined(DEPTH_CLAMP)
+VARYING vec4 post_pos;
+#endif
+
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return normalize(cloud_noise_sample);
+}
+
+void main()
+{
+    // Set variables
+    vec2 uv1 = vary_texcoord0.xy;
+    vec2 uv2 = vary_texcoord1.xy;
+    vec2 uv3 = vary_texcoord2.xy;
+    float cloudDensity = 2.0 * (cloud_shadow - 0.25);
+
+    if (cloud_scale >= 0.0001)
+    {
+        vec2 uv4 = vary_texcoord3.xy;
+    
+        vec2 disturbance  = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+        vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+    
+        // Offset texture coords
+        uv1 += cloud_pos_density1.xy + (disturbance * 0.2);    //large texture, visible density
+        uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+        uv3 += cloud_pos_density2.xy;   //small texture, visible density
+        uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+    
+        float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
+    
+        cloudDensity *= 1.0 - (density_variance * density_variance);
+    
+        // Compute alpha1, the main cloud opacity
+        float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+        alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha1 = 1. - alpha1 * alpha1;
+        alpha1 = 1. - alpha1 * alpha1;  
+    
+        if (alpha1 < 0.001f)
+        {
+            discard;
+        }
+    
+        // Compute alpha2, for self shadowing effect
+        // (1 - alpha2) will later be used as percentage of incoming sunlight
+        float alpha2 = (cloudNoise(uv2).x - 0.5);
+        alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha2 = 1. - alpha2;
+        alpha2 = 1. - alpha2 * alpha2;  
+    
+        frag_color = vec4(alpha1, alpha1, alpha1, 1);
+    }
+    else
+    {
+        frag_color = vec4(1);
+    }
+
+#if !defined(DEPTH_CLAMP)
+    gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..effb070f934ed4422f333c5b3cca100d0357742c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudShadowV.glsl
@@ -0,0 +1,63 @@
+/** 
+ * @file cloudShadowV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+	pos = modelview_projection_matrix * pre_pos;
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+	vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
index 1d8ca04ccd3ff27d7a783f82a537bcc27f896549..ae1ac5de7f07e55644fee8016149f4c0ec6a8676 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLCloudsF.glsl
+ * @file class1\deferred\cloudsF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,7 +22,7 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+/*[EXTRA_CODE_HERE]*/ 
 
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
@@ -39,69 +39,93 @@ VARYING vec4 vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
 
 uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
 uniform vec4 cloud_pos_density1;
 uniform vec4 cloud_pos_density2;
-uniform vec4 gamma;
+uniform float cloud_scale;
+uniform float cloud_variance;
 
 VARYING vec2 vary_texcoord0;
 VARYING vec2 vary_texcoord1;
 VARYING vec2 vary_texcoord2;
 VARYING vec2 vary_texcoord3;
+VARYING float altitude_blend_factor;
 
 /// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
+vec3 scaleSoftClip(vec3 light);
 
-	return light;
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return cloud_noise_sample;
 }
 
 void main()
 {
-	// Set variables
-	vec2 uv1 = vary_texcoord0.xy;
-	vec2 uv2 = vary_texcoord1.xy;
-
-	vec4 cloudColorSun = vary_CloudColorSun;
-	vec4 cloudColorAmbient = vary_CloudColorAmbient;
-	float cloudDensity = vary_CloudDensity;
-	vec2 uv3 = vary_texcoord2.xy;
-	vec2 uv4 = vary_texcoord3.xy;
-
-	// Offset texture coords
-	uv1 += cloud_pos_density1.xy;	//large texture, visible density
-	uv2 += cloud_pos_density1.xy;	//large texture, self shadow
-	uv3 += cloud_pos_density2.xy;	//small texture, visible density
-	uv4 += cloud_pos_density2.xy;	//small texture, self shadow
-
-
-	// Compute alpha1, the main cloud opacity
-	float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z;
-	alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.);
-
-	// And smooth
-	alpha1 = 1. - alpha1 * alpha1;
-	alpha1 = 1. - alpha1 * alpha1;	
-
-
-	// Compute alpha2, for self shadowing effect
-	// (1 - alpha2) will later be used as percentage of incoming sunlight
-	float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5);
-	alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
-
-	// And smooth
-	alpha2 = 1. - alpha2;
-	alpha2 = 1. - alpha2 * alpha2;	
-
-	// Combine
-	vec4 color;
-	color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
-	color *= 2.;
-
-	/// Gamma correct for WL (soft clip effect).
-	frag_data[0] = vec4(scaleSoftClip(color.rgb), alpha1);
-	frag_data[1] = vec4(0.0,0.0,0.0,0.0);
-	frag_data[2] = vec4(0,0,1,0);
+    // Set variables
+    vec2 uv1 = vary_texcoord0.xy;
+    vec2 uv2 = vary_texcoord1.xy;
+
+    vec4 cloudColorSun = vary_CloudColorSun;
+    vec4 cloudColorAmbient = vary_CloudColorAmbient;
+    float cloudDensity = vary_CloudDensity;
+    vec2 uv3 = vary_texcoord2.xy;
+    vec2 uv4 = vary_texcoord3.xy;
+
+    if (cloud_scale < 0.001)
+    {
+        discard;
+    }
+
+    vec2 disturbance  = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+    vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+
+    // Offset texture coords
+    uv1 += cloud_pos_density1.xy + (disturbance * 0.2);    //large texture, visible density
+    uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+    uv3 += cloud_pos_density2.xy;   //small texture, visible density
+    uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+
+    float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
+
+    cloudDensity *= 1.0 - (density_variance * density_variance);
+
+    // Compute alpha1, the main cloud opacity
+
+    float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+    alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
+
+    // And smooth
+    alpha1 = 1. - alpha1 * alpha1;
+    alpha1 = 1. - alpha1 * alpha1;  
+
+    alpha1 *= altitude_blend_factor;
+    alpha1 = clamp(alpha1, 0.0, 1.0);
+
+    // Compute alpha2, for self shadowing effect
+    // (1 - alpha2) will later be used as percentage of incoming sunlight
+    float alpha2 = (cloudNoise(uv2).x - 0.5);
+    alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+
+    // And smooth
+    alpha2 = 1. - alpha2;
+    alpha2 = 1. - alpha2 * alpha2;  
+
+    // Combine
+    vec4 color;
+    color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
+    color.rgb= max(vec3(0), color.rgb);
+    color.rgb *= 2.0;
+    color.rgb = scaleSoftClip(color.rgb);
+
+    /// Gamma correct for WL (soft clip effect).
+    frag_data[0] = vec4(color.rgb, alpha1);
+    frag_data[1] = vec4(0.0,0.0,0.0,0.0);
+    frag_data[2] = vec4(0,0,0,1);
+
+    gl_FragDepth = 0.99995f;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index 17f425475c85e1ad4606b6645c3c4d797fa4ff0f..caa4fe1f65c5188c9ea15a231fb6165e0956fca9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -41,13 +41,16 @@ 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 ambient;
+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;
@@ -58,22 +61,40 @@ uniform float density_multiplier;
 uniform float max_y;
 
 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\lllegacyatmospherics.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.)
 	{
@@ -81,6 +102,7 @@ void main()
 	}
 	else
 	{
+		altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
 		P *= (-32000. / P.y);
 	}
 
@@ -93,16 +115,18 @@ void main()
 	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)) * (density_multiplier * max_y);
+	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
 
 	// Calculate relative weights
-	temp1 = blue_density + haze_density;
+	temp1 = abs(blue_density) + vec4(abs(haze_density));
 	blue_weight = blue_density / temp1;
 	haze_weight = haze_density / temp1;
 
@@ -112,7 +136,7 @@ void main()
 	sunlight *= exp( - light_atten * temp2.y);
 
 	// Distance
-	temp2.z = Plen * density_multiplier;
+	temp2.z = Plen * dens_mul;
 
 	// Transparency (-> temp1)
 	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -131,11 +155,13 @@ void main()
 	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;
+	vec4 tmpAmbient = ambient_color;
 	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
 
 	// Dim sunlight by cloud shadow percentage
@@ -147,8 +173,6 @@ void main()
 			 );	
 
 	// CLOUDS
-
-	sunlight = sunlight_color;
 	temp2.y = max(0., lightnorm.y * 2.);
 	temp2.y = 1. / temp2.y;
 	sunlight *= exp( - light_atten * temp2.y);
@@ -167,19 +191,6 @@ void main()
 	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;
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
index fef1c5a5848c7feb0a8b26d86ecf12887bcbfeda..079d8458c939f27f580067f87e18286212a4a813 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cofF.glsl
@@ -50,15 +50,6 @@ uniform vec2 screen_res;
 
 VARYING vec2 vary_fragcoord;
 
-float getDepth(vec2 pos_screen)
-{
-	float z = texture2DRect(depthMap, pos_screen.xy).r;
-	z = z*2.0-1.0;
-	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
-	vec4 p = inv_proj*ndc;
-	return p.z/p.w;
-}
-
 float calc_cof(float depth)
 {
 	float sc = (depth-focal_distance)/-depth*blur_constant;
@@ -77,8 +68,12 @@ float calc_cof(float depth)
 void main() 
 {
 	vec2 tc = vary_fragcoord.xy;
-	
-	float depth = getDepth(tc);
+
+    float z = texture2DRect(depthMap, tc).r;
+	z = z*2.0-1.0;
+	vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+	vec4 p = inv_proj*ndc;
+	float depth = p.z/p.w;
 	
 	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e27bbce0948765fa3bf89e0fe860bffb3ab5925f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/deferredUtil.glsl
@@ -0,0 +1,79 @@
+/** 
+ * @file class1/deferred/deferredUtil.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$
+ */
+
+uniform sampler2DRect   normalMap;
+uniform sampler2DRect   depthMap;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec2 getScreenCoordinate(vec2 screenpos)
+{
+    vec2 sc = screenpos.xy * 2.0;
+    if (screen_res.x > 0 && screen_res.y > 0)
+    {
+       sc /= screen_res;
+    }
+    return sc - vec2(1.0, 1.0);
+}
+
+vec3 getNorm(vec2 screenpos)
+{
+   vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
+   vec2 fenc = enc*4-2;
+   float f = dot(fenc,fenc);
+   float g = sqrt(1-f/4);
+   vec3 n;
+   n.xy = fenc*g;
+   n.z = 1-f/2;
+   return n;
+}
+
+float getDepth(vec2 pos_screen)
+{
+    float depth = texture2DRect(depthMap, pos_screen).r;
+    return depth;
+}
+
+vec4 getPosition(vec2 pos_screen)
+{
+    float depth = getDepth(pos_screen);
+    vec2 sc = getScreenCoordinate(pos_screen);
+    vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+    vec4 pos = inv_proj * ndc;
+    pos /= pos.w;
+    pos.w = 1.0;
+    return pos;
+}
+
+vec4 getPositionWithDepth(vec2 pos_screen, float depth)
+{
+    vec2 sc = getScreenCoordinate(pos_screen);
+    vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+    vec4 pos = inv_proj * ndc;
+    pos /= pos.w;
+    pos.w = 1.0;
+    return pos;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
index 7930b5d18be81a4fe3558324ff4240db66e4f2fd..b328ee94832d5bb7cc75d9b6af25e56e5a83c916 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -37,11 +39,7 @@ VARYING vec3 vary_normal;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
index 8525e13333eaa9fff6c2fd5d90b3655d2ef93b34..fc5c86b4d69b1753f44dc49ec7ba695141c489cc 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -36,11 +38,7 @@ uniform float minimum_alpha;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
index 37d70a2412b24761fb64e8e82578452a445ba7db..1bb8eb8bd054f409dc1cb6863331cf34da38a9f9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskNoColorF.glsl
@@ -23,6 +23,7 @@
  * $/LicenseInfo$
  */
  
+/*[EXTRA_CODE_HERE]*/
 
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
@@ -37,11 +38,7 @@ uniform sampler2D diffuseMap;
 VARYING vec3 vary_normal;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
index 6befb1bd8b7347e10107ae86257c1b9020ac1dc5..8319e61242f363751a28259e402212640163087e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl
@@ -22,6 +22,8 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
+
+/*[EXTRA_CODE_HERE]*/
  
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
@@ -35,11 +37,7 @@ VARYING vec3 vary_normal;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
index adc361d7a2b1409863450df01437c9598ba3652e..ccd1df84f9559313a33be66c67ff1d086b96085a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -33,17 +35,13 @@ VARYING vec3 vary_normal;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
+vec2 encode_normal(vec3 n);
+vec3 linear_to_srgb(vec3 c);
 
 void main() 
 {
 	vec3 col = vertex_color.rgb * diffuseLookup(vary_texcoord0.xy).rgb;
-	
+
 	vec3 spec;
 	spec.rgb = vec3(vertex_color.a);
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl
index 0ffca8515c30cad38239e2849c8cf930827c3fd8..f0522850de8c234e2b17b64a1051720b9fcc054b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveF.glsl
@@ -44,7 +44,6 @@ void main()
 	float shadow = 1.0;
 
 	vec4 color = diffuseLookup(vary_texcoord0.xy)*vertex_color;
-	color.rgb = pow(color.rgb, vec3(2.2));
 	color.rgb = fullbrightAtmosTransport(color.rgb);
 
 	color.rgb = fullbrightScaleSoftClip(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
index 115b04797f8a1bfc346cc14057f08d77f9d47d82..5e4f08b0174b4e3b7aa650f7e2a4a1c693e5dfc0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/emissiveV.glsl
@@ -34,11 +34,8 @@ ATTRIBUTE vec2 texcoord0;
 
 void calcAtmospherics(vec3 inPositionEye);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
-vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
-
 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
index 756e625d073718cc184ace09f83aa8878da3d02a..57420158ca2b21f26ab7c64e82a421803bb6d32a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file fullbrightF.glsl
+ * @file deferred/fullbrightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -33,7 +33,7 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
-#if !HAS_DIFFUSE_LOOKUP
+#if !defined(HAS_DIFFUSE_LOOKUP)
 uniform sampler2D diffuseMap;
 #endif
 
@@ -41,108 +41,22 @@ VARYING vec3 vary_position;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
 #endif
 
-}
-
-vec3 fullbrightAtmosTransportDeferred(vec3 light)
-{
-	return light;
-}
-
-vec3 fullbrightScaleSoftClipDeferred(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
+vec3 srgb_to_linear(vec3 cs);
+vec3 linear_to_srgb(vec3 cl);
+vec3 fullbrightAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
 
 #ifdef HAS_ALPHA_MASK
 uniform float minimum_alpha;
 #endif
 
-#ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
-#endif
-
 void main() 
 {
-#if HAS_DIFFUSE_LOOKUP
+#ifdef HAS_DIFFUSE_LOOKUP
 	vec4 color = diffuseLookup(vary_texcoord0.xy);
 #else
 	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
@@ -158,19 +72,14 @@ void main()
 #endif
 
 	color.rgb *= vertex_color.rgb;
-	color.rgb = srgb_to_linear(color.rgb);
-	color.rgb = fullbrightAtmosTransportDeferred(color.rgb);
-	color.rgb = fullbrightScaleSoftClipDeferred(color.rgb);
-	
-	color.rgb = linear_to_srgb(color.rgb);
 
 #ifdef WATER_FOG
 	vec3 pos = vary_position;
-	vec4 fogged = applyWaterFogDeferred(pos, vec4(color.rgb, final_alpha));
+	vec4 fogged = applyWaterFogView(pos, vec4(color.rgb, final_alpha));
 	color.rgb = fogged.rgb;
 	color.a   = fogged.a;
 #else
-	color.a   = final_alpha;
+    color.a   = final_alpha;
 #endif
 
 	frag_color.rgb = color.rgb;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index b0db9876d30a49f82f792c09ad524d5797117901..bd0ad3bce80bf49604cb1eccd97b81dc841fccba 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -23,7 +23,7 @@
  * $/LicenseInfo$
  */
  
-
+/*[EXTRA_CODE_HERE]*/
 
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
@@ -31,41 +31,57 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
-#ifndef diffuseLookup
+#ifndef HAS_DIFFUSE_LOOKUP
 uniform sampler2D diffuseMap;
 #endif
 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_texcoord1;
+VARYING vec4 vary_position;
 
 uniform samplerCube environmentMap;
 
 vec3 fullbrightShinyAtmosTransport(vec3 light);
+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 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
+
+
 void main()
 {
-#if HAS_DIFFUSE_LOOKUP
+#ifdef HAS_DIFFUSE_LOOKUP
 	vec4 color = diffuseLookup(vary_texcoord0.xy);
 #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;
+
+	calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
 	
 	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
-	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a);
+	float env_intensity = vertex_color.a;
+	color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
 
-	color.rgb = pow(color.rgb,vec3(2.2f,2.2f,2.2f));
+	//color.rgb = srgb_to_linear(color.rgb);
 	
-	color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+	color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
 	color.rgb = fullbrightScaleSoftClip(color.rgb);
 
 	color.a = 1.0;
 
-	color.rgb = pow(color.rgb, vec3(1.0/2.2));
+	//color.rgb = linear_to_srgb(color.rgb);
 
 	frag_color = color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
index 34bd8d445a0eb532d77e10ea45897715bc369c65..8f6eb7966821415448a1968d6d5605c7b4e05b75 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
@@ -45,7 +45,7 @@ ATTRIBUTE vec2 texcoord0;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_texcoord1;
-
+VARYING vec4 vary_position;
 
 void main()
 {
@@ -53,7 +53,7 @@ void main()
 	vec4 vert = vec4(position.xyz,1.0);
 	passTextureIndex();
 	vec4 pos = (modelview_matrix * vert);
-	gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+	vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
 	vec3 norm = normalize(normal_matrix * normal);
 	vec3 ref = reflect(pos.xyz, -norm);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index 8e899e3e0f32df89f36b81531d979ced9b57f534..bdf3546aa5f7b5c052af16032593115f56ce6cba 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -35,10 +35,8 @@ ATTRIBUTE vec2 texcoord0;
 
 void calcAtmospherics(vec3 inPositionEye);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
-vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
 
 #ifdef WATER_FOG
 VARYING vec3 vary_position;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index f8fdde43f9fe80a960de67e7b49d9503914c176d..d29e8a9423ab73f3b058c0a323251cfe3499bd04 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -38,42 +40,6 @@ uniform sampler2D specularMap;
 
 VARYING vec2 vary_texcoord0;
 
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
 void main() 
 {
 	vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
@@ -86,8 +52,6 @@ void main()
 	vec4 norm = texture2D(normalMap,   vary_texcoord0.xy);
 	vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
 
-	col.rgb = linear_to_srgb(col.rgb);
-
 	frag_data[0] = vec4(col.rgb, 0.0);
 	frag_data[1] = spec;
 	frag_data[2] = vec4(norm.xy,0,0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/indirect.glsl b/indra/newview/app_settings/shaders/class1/deferred/indirect.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..49bfa660f8446c29dbd8b5117499962bb969a7bd
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/indirect.glsl
@@ -0,0 +1,30 @@
+/** 
+ * @file class1/deferred/indirect.glsl
+ *
+ * $LicenseInfo:firstyear=2018&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$
+ */
+
+vec3 getIndirect(vec3 ambient, vec3 norm, vec3 pos, vec2 pos_screen)
+{
+    return ambient;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
index dcf474824dab414bc5e36506e35f85369265a7d4..be1003a7e0cb957974114facd8f5f02cf7bf6b36 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl
@@ -22,8 +22,8 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-uniform sampler2DRect diffuseMap;
+
+/*[EXTRA_CODE_HERE]*/
 
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
@@ -31,6 +31,7 @@ out vec4 frag_color;
 #define frag_color gl_FragColor
 #endif
 
+uniform sampler2DRect diffuseMap;
 VARYING vec2 vary_fragcoord;
 
 void main() 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 07d28ed4cdd2df2ea7ec7f8376fb0c3209640471..0afd1a96720e026652903eeb17057c4173e187d2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -1,788 +1,439 @@
-/** 
- * @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$
- */
- 
-#define DIFFUSE_ALPHA_MODE_IGNORE	0
-#define DIFFUSE_ALPHA_MODE_BLEND	1
-#define DIFFUSE_ALPHA_MODE_MASK		2
-#define DIFFUSE_ALPHA_MODE_EMISSIVE 3
-
-uniform float emissive_brightness;
-uniform float display_gamma;
-
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-#if HAS_SUN_SHADOW
-
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform vec2 shadow_res;
-uniform float shadow_bias;
-
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc)
-{
-	stc.xyz /= stc.w;
-	stc.z += shadow_bias;
-		
-	stc.x = floor(stc.x*shadow_res.x + fract(stc.y*shadow_res.y*12345))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
-	
-	float cs = shadow2D(shadowMap, stc.xyz).x;
-	float shadow = cs;
-	
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-                       
-    return shadow*0.2;
-}
-
-#endif
-
-uniform samplerCube environmentMap;
-uniform sampler2D	  lightFunc;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-//uniform vec4 camPosWorld;
-uniform vec4 gamma;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-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 float scene_light_strength;
-uniform mat3 env_mat;
-uniform mat3 ssao_effect_mat;
-
-uniform vec3 sun_dir;
-VARYING vec2 vary_fragcoord;
-
-VARYING vec3 vary_position;
-
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-uniform vec4 light_position[8];
-uniform vec3 light_direction[8];
-uniform vec3 light_attenuation[8]; 
-uniform vec3 light_diffuse[8];
-
-#ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
-#endif
-
-vec3 calcDirectionalLight(vec3 n, vec3 l)
-{
-	float a = max(dot(n,l),0.0);
-	return vec3(a,a,a);
-}
-
-
-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)
-{
-	//get light vector
-	vec3 lv = lp.xyz-v;
-	
-	//get distance
-	float d = length(lv);
-	
-	float da = 1.0;
-
-	vec3 col = vec3(0,0,0);
-
-	if (d > 0.0 && la > 0.0 && fa > 0.0)
-	{
-		//normalize light vector
-		lv = normalize(lv);
-	
-		//distance attenuation
-		float dist = d/la;
-		float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
-		dist_atten *= dist_atten;
-		dist_atten *= 2.0;
-
-		// spotlight coefficient.
-		float spot = max(dot(-ln, lv), is_pointlight);
-		da *= spot*spot; // GL_SPOT_EXPONENT=2
-
-		//angular attenuation
-		da *= max(dot(n, lv), 0.0);		
-		
-		float lit = max(da * dist_atten, 0.0);
-
-		col = light_col*lit*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;
-				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);
-				//col += spec.rgb;
-			}
-		}
-	}
-
-	return max(col, vec3(0.0,0.0,0.0));	
-
-}
-
-vec4 getPosition_d(vec2 pos_screen, float depth)
-{
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-#ifndef WATER_FOG
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-#endif
-
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
-
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
-
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(0);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//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;
-	
-	//increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
-
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * vec3(scene_light_strength, scene_light_strength, scene_light_strength));
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + (light * vec3(0.5f, 0.5f, 0.5f));
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * vec3(lightIntensity, lightIntensity, lightIntensity);
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-    vec3 zeroes = vec3(0.0f, 0.0f, 0.0f);
-    vec3 ones   = vec3(1.0f, 1.0f, 1.0f);
-
-	light = ones - clamp(light, zeroes, ones);
-	light = ones - pow(light, gamma.xxx);
-
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
-
-#else
-#ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
-#else
-#define frag_data gl_FragData
-#endif
-#endif
-
-uniform sampler2D diffuseMap;
-
-#if HAS_NORMAL_MAP
-uniform sampler2D bumpMap;
-#endif
-
-#if 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
-
-#if 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)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-void main() 
-{
-	vec4 diffcol = texture2D(diffuseMap, vary_texcoord0.xy);
-	diffcol.rgb *= vertex_color.rgb;
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_MASK)
-	if (diffcol.a < minimum_alpha)
-	{
-		discard;
-	}
-#endif
-
-#if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-	vec3 gamma_diff = diffcol.rgb;
-	diffcol.rgb = srgb_to_linear(diffcol.rgb);
-#endif
-
-#if 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
-
-#if 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 = tnorm;
-    norm.xyz = normalize(norm.xyz);
-
-	vec2 abnormal	= encode_normal(norm.xyz);
-		 norm.xyz   = decode_normal(abnormal.xy);
-
-	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;
-#if 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 RGBA
-	vec3 pos = vary_position;
-
-#if HAS_SUN_SHADOW
-	float shadow = 0.0;
-	
-	vec4 spos = vec4(pos,1.0);
-		
-	if (spos.z > -shadow_clip.w)
-	{	
-		vec4 lpos;
-		
-		vec4 near_split = shadow_clip*-0.75;
-		vec4 far_split = shadow_clip*-1.25;
-		vec4 transition_domain = near_split-far_split;
-		float weight = 0.0;
-
-		if (spos.z < near_split.z)
-		{
-			lpos = shadow_matrix[3]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap3, lpos)*w;
-			weight += w;
-			shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-		}
-
-		if (spos.z < near_split.y && spos.z > far_split.z)
-		{
-			lpos = shadow_matrix[2]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-			w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-			shadow += pcfShadow(shadowMap2, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z < near_split.x && spos.z > far_split.y)
-		{
-			lpos = shadow_matrix[1]*spos;
-			
-			float w = 1.0;
-			w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-			w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-			shadow += pcfShadow(shadowMap1, lpos)*w;
-			weight += w;
-		}
-
-		if (spos.z > far_split.x)
-		{
-			lpos = shadow_matrix[0]*spos;
-							
-			float w = 1.0;
-			w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-			shadow += pcfShadow(shadowMap0, lpos)*w;
-			weight += w;
-		}
-		
-
-		shadow /= weight;
-	}
-	else
-	{
-		shadow = 1.0;
-	}
-#else
-	float shadow = 1.0;
-#endif
-
-	spec = final_specular;
-	vec4 diffuse = final_color;
-	float envIntensity = final_normal.z;
-
-    vec3 col = vec3(0.0f,0.0f,0.0f);
-
-	float bloom = 0.0;
-	calcAtmospherics(pos.xyz, 1.0);
-	
-	vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
-	float da =dot(norm.xyz, sun_dir.xyz);
-
-    float final_da = da;
-          final_da = min(final_da, shadow);
-          //final_da = max(final_da, diffuse.a);
-          final_da = max(final_da, 0.0f);
-		  final_da = min(final_da, 1.0f);
-		  final_da = pow(final_da, 1.0/1.3);
-
-	col.rgb = atmosAmbient(col);
-	
-	float ambient = min(abs(da), 1.0);
-	ambient *= 0.5;
-	ambient *= ambient;
-	ambient = (1.0-ambient);
-
-	col.rgb *= ambient;
-
-	col.rgb = col.rgb + atmosAffectDirectionalLight(final_da);
-
-	col.rgb *= gamma_diff.rgb;
-	
-
-	float glare = 0.0;
-
-	if (spec.a > 0.0) // specular reflection
-	{
-		// the old infinite-sky shiny reflection
-		//
-				
-		float sa = dot(refnormpersp, sun_dir.xyz);
-		vec3 dumbshiny = vary_SunlitColor*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);
-
-		col += spec_contrib;
-	}
-
-
-	col = mix(col.rgb, diffcol.rgb, diffuse.a);
-
-	if (envIntensity > 0.0)
-	{
-		//add environmentmap
-		vec3 env_vec = env_mat * refnormpersp;
-		
-		vec3 refcol = textureCube(environmentMap, env_vec).rgb;
-
-		col = mix(col.rgb, refcol, 
-			envIntensity);  
-
-		float cur_glare = max(refcol.r, refcol.g);
-		cur_glare = max(cur_glare, refcol.b);
-		cur_glare *= envIntensity*4.0;
-		glare += cur_glare;
-	}
-
-	//col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
-	//col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col),  diffuse.a);
-
-	col = atmosLighting(col);
-	col = scaleSoftClip(col);
-
-	//convert to linear space before adding local lights
-	col = srgb_to_linear(col);
-
-	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_LOOP(1)
-		LIGHT_LOOP(2)
-		LIGHT_LOOP(3)
-		LIGHT_LOOP(4)
-		LIGHT_LOOP(5)
-		LIGHT_LOOP(6)
-		LIGHT_LOOP(7)
-
-	col.rgb += light.rgb;
-
-	glare = min(glare, 1.0);
-	float al = max(diffcol.a,glare)*vertex_color.a;
-
-	//convert to gamma space for display on screen
-	col.rgb = linear_to_srgb(col.rgb);
-
-#ifdef WATER_FOG
-	vec4 temp = applyWaterFogDeferred(pos, vec4(col.rgb, al));
-	col.rgb = temp.rgb;
-	al = temp.a;
-#endif
-
-	frag_color.rgb = col.rgb;
-	frag_color.a   = al;
-
-#else
-	frag_data[0] = final_color;
-	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
+    {
+#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
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
index 393d1e69da76417d2f2b63f170ac1fff80a13c5f..7e29ada2055633be320c9d8e4fa31ebbcbb0eb0a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialV.glsl
@@ -28,7 +28,7 @@
 #define DIFFUSE_ALPHA_MODE_MASK 2
 #define DIFFUSE_ALPHA_MODE_EMISSIVE 3
 
-#if HAS_SKIN
+#ifdef HAS_SKIN
 uniform mat4 modelview_matrix;
 uniform mat4 projection_matrix;
 mat4 getObjectSkinnedTransform();
@@ -39,7 +39,7 @@ uniform mat4 modelview_projection_matrix;
 
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
 
-#if !HAS_SKIN
+#if !defined(HAS_SKIN)
 uniform mat4 modelview_matrix;
 #endif
 
@@ -55,7 +55,7 @@ ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
 
 
-#if HAS_NORMAL_MAP
+#ifdef HAS_NORMAL_MAP
 ATTRIBUTE vec4 tangent;
 ATTRIBUTE vec2 texcoord1;
 
@@ -68,7 +68,7 @@ VARYING vec2 vary_texcoord1;
 VARYING vec3 vary_normal;
 #endif
 
-#if HAS_SPECULAR_MAP
+#ifdef HAS_SPECULAR_MAP
 ATTRIBUTE vec2 texcoord2;
 VARYING vec2 vary_texcoord2;
 #endif
@@ -78,7 +78,7 @@ VARYING vec2 vary_texcoord0;
 
 void main()
 {
-#if HAS_SKIN
+#ifdef HAS_SKIN
 	mat4 mat = getObjectSkinnedTransform();
 
 	mat = modelview_matrix * mat;
@@ -99,17 +99,17 @@ void main()
 	
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	
-#if HAS_NORMAL_MAP
+#ifdef HAS_NORMAL_MAP
 	vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy;
 #endif
 
-#if HAS_SPECULAR_MAP
+#ifdef HAS_SPECULAR_MAP
 	vary_texcoord2 = (texture_matrix0 * vec4(texcoord2,0,1)).xy;
 #endif
 
-#if HAS_SKIN
+#ifdef HAS_SKIN
 	vec3 n = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
-#if HAS_NORMAL_MAP
+#ifdef HAS_NORMAL_MAP
 	vec3 t = normalize((mat*vec4(tangent.xyz+position.xyz,1.0)).xyz-pos.xyz);
 	vec3 b = cross(n, t)*tangent.w;
 	
@@ -121,7 +121,7 @@ vary_normal  = n;
 #endif //HAS_NORMAL_MAP
 #else //HAS_SKIN
 	vec3 n = normalize(normal_matrix * normal);
-#if HAS_NORMAL_MAP
+#ifdef HAS_NORMAL_MAP
 	vec3 t = normalize(normal_matrix * tangent.xyz);
 	vec3 b = cross(n,t)*tangent.w;
 	//vec3 t = cross(b,n) * binormal.w;
@@ -137,7 +137,7 @@ vary_normal  = n;
 	vertex_color = diffuse_color;
 
 #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND)
-#if !HAS_SKIN
+#if !defined(HAS_SKIN)
 	vary_position = (modelview_matrix*vec4(position.xyz, 1.0)).xyz;
 #endif
 #endif
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..80f232948acd4a3d1bdc4e60e83c95d555c36941
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonF.glsl
@@ -0,0 +1,74 @@
+/** 
+ * @file moonF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+uniform vec4 color;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform vec3 lumWeights;
+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);
+
+    // 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);
+
+    vec4 light_color = max(sunlight_color, moonlight_color);
+    float mix = 1.0 - dot(normalize(light_color.rgb), luma_weights);
+
+    vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0  - 1.0;
+    c.rgb = pow(c.rgb, exp);
+
+    //c.rgb *= moonlight_color.rgb;
+
+    frag_data[0] = vec4(c.rgb, c.a);
+    frag_data[1] = vec4(0.0);
+    frag_data[2] = vec4(0.0f);
+
+    gl_FragDepth = 0.999985f;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e1bac4f248081f80740689aaf4399f36d9c9cf2b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/moonV.glsl
@@ -0,0 +1,49 @@
+/** 
+ * @file moonV.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$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+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 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 9974f8f31b93df55f37889b4a0b2bbd7eb3fc37e..0d1cc817866ad5d07da80ed3a1f251888808bb29 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -36,7 +36,6 @@ out vec4 frag_color;
 uniform sampler2DRect depthMap;
 uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
-uniform sampler2DRect normalMap;
 uniform samplerCube environmentMap;
 uniform sampler2D noiseMap;
 uniform sampler2D lightFunc;
@@ -57,38 +56,17 @@ uniform float far_z;
 
 uniform mat4 inv_proj;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
+vec3 srgb_to_linear(vec3 c);
 
 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)
@@ -96,14 +74,13 @@ void main()
 		discard;
 	}
 	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-	norm = normalize(norm);
+	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 out_col = vec3(0,0,0);
 	vec3 npos = normalize(-pos);
 
 	// As of OSX 10.6.7 ATI Apple's crash when using a variable size loop
@@ -123,6 +100,9 @@ void main()
 			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;
@@ -159,7 +139,7 @@ void main()
 		}
 	}
 	}
-	
+#endif
 	
 	frag_color.rgb = out_col;
 	frag_color.a = 0.0;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index 3a3e871adea025f17cb114e16f53505a8e5d0688..9bba45bc4ea1f7163724d264430efcd1d3f19c20 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -30,14 +30,14 @@
 #extension GL_ARB_texture_rectangle : enable
 #extension GL_ARB_shader_texture_lod : enable
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
 #define frag_color gl_FragColor
 #endif
 
-/*[EXTRA_CODE_HERE]*/
-
 uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
 uniform sampler2DRect depthMap;
@@ -71,60 +71,8 @@ VARYING vec4 vary_fragcoord;
 uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
+vec3 getNorm(vec2 pos_screen);
+vec3 srgb_to_linear(vec3 c);
 
 vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
@@ -178,22 +126,15 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
+	vec3 col = vec3(0,0,0);
+
+#if defined(LOCAL_LIGHT_KILL)
+    discard;
+#else
 	vec4 frag = vary_fragcoord;
 	frag.xyz /= frag.w;
 	frag.xyz = frag.xyz*0.5+0.5;
@@ -208,12 +149,9 @@ void main()
 		discard;
 	}
 		
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-	float envIntensity = norm.z;
+	float envIntensity = texture2DRect(normalMap, frag.xy).z;
+	vec3 norm = getNorm(frag.xy);
 
-	norm = decode_normal(norm.xy);
-	
-	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
 	
 	vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
@@ -225,25 +163,33 @@ void main()
 	proj_tc.xyz /= proj_tc.w;
 	
 	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+	float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
 	dist_atten *= dist_atten;
 	dist_atten *= 2.0;
+	
 
 	if (dist_atten <= 0.0)
 	{
 		discard;
 	}
 	
+	float noise = texture2D(noiseMap, frag.xy/128.0).b;
+	dist_atten *= noise;
+
 	lv = proj_origin-pos.xyz;
 	lv = normalize(lv);
 	float da = dot(norm, lv);
 		
-	vec3 col = vec3(0,0,0);
 		
 	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+    // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
+    //          We can't switch to linear here unless we do it everywhere*
+	// *gbuffer is sRGB, convert to linear whenever sampling from it
+    diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
+
 	vec3 dlit = vec3(0, 0, 0);
 	
-	float noise = texture2D(noiseMap, frag.xy/128.0).b;
+	
 	if (proj_tc.z > 0.0 &&
 		proj_tc.x < 1.0 &&
 		proj_tc.y < 1.0 &&
@@ -262,7 +208,7 @@ void main()
 		
 			dlit = color.rgb * plcol.rgb * plcol.a;
 			
-			lit = da * dist_atten * noise;
+			lit = da * dist_atten;
 			
 			col = dlit*lit*diff_tex;
 			amb_da += (da*0.5)*proj_ambiance;
@@ -304,7 +250,7 @@ void main()
 			col += dlit*scol*spec.rgb;
 			//col += spec.rgb;
 		}
-	}	
+	}
 
 	if (envIntensity > 0.0)
 	{
@@ -334,7 +280,9 @@ void main()
 			}
 		}
 	}
-	
+#endif
+
+	//output linear, sum of lights will be gamma corrected later	
 	frag_color.rgb = col;	
 	frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index aba4a017547b4a40453c3c6f054b359ef2faaa27..d805c9ea48a97436011da003cfcf343a34883595 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -56,103 +56,78 @@ uniform vec2 screen_res;
 uniform mat4 inv_proj;
 uniform vec4 viewport;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = (pos_screen.xy-viewport.xy)*2.0;
-	sc /= viewport.zw;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec3 getNorm(vec2 pos_screen);
+vec4 getPosition(vec2 pos_screen);
+vec3 srgb_to_linear(vec3 c);
 
 void main() 
 {
-	vec4 frag = vary_fragcoord;
-	frag.xyz /= frag.w;
-	frag.xyz = frag.xyz*0.5+0.5;
-	frag.xy *= screen_res;
-	
-	vec3 pos = getPosition(frag.xy).xyz;
-	vec3 lv = trans_center.xyz-pos;
-	float dist = length(lv);
-	dist /= size;
-	if (dist > 1.0)
-	{
-		discard;
-	}
-	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-	float da = dot(norm, lv);
-	if (da < 0.0)
-	{
-		discard;
-	}
-	
-	norm = normalize(norm);
-	lv = normalize(lv);
-	da = dot(norm, lv);
-	
-	float noise = texture2D(noiseMap, frag.xy/128.0).b;
-	
-	vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
-	float fa = falloff+1.0;
-	float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
-	dist_atten *= dist_atten;
-	dist_atten *= 2.0;
-	
-	float lit = da * dist_atten * noise;
-
-	col = color.rgb*lit*col;
-
-	vec4 spec = texture2DRect(specularRect, frag.xy);
-	if (spec.a > 0.0)
-	{
-		lit = min(da*6.0, 1.0) * dist_atten;
-
-		vec3 npos = -normalize(pos);
-		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*color.rgb*spec.rgb;
-		}
-	}
-	
-	if (dot(col, col) <= 0.0)
-	{
-		discard;
-	}
-		
-	frag_color.rgb = col;	
-	frag_color.a = 0.0;
+    vec4 frag = vary_fragcoord;
+    frag.xyz /= frag.w;
+    frag.xyz = frag.xyz*0.5+0.5;
+    frag.xy *= screen_res;
+    
+    vec3 pos = getPosition(frag.xy).xyz;
+    vec3 lv = trans_center.xyz-pos;
+    float dist = length(lv);
+    dist /= size;
+    if (dist > 1.0)
+    {
+        discard;
+    }
+    
+    vec3 norm = getNorm(frag.xy);
+
+    float da = dot(norm, lv);
+    if (da < 0.0)
+    {
+        discard;
+    }
+    
+    lv = normalize(lv);
+    da = dot(norm, lv);
+    
+    float noise = texture2D(noiseMap, frag.xy/128.0).b;
+    
+    vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
+    col.rgb = srgb_to_linear(col.rgb);
+
+    float fa = falloff+1.0;
+    float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
+    dist_atten *= dist_atten;
+    dist_atten *= 2.0;
+    
+    float lit = da * dist_atten * noise;
+
+    col = color.rgb*lit*col;
+
+    vec4 spec = texture2DRect(specularRect, frag.xy);
+    if (spec.a > 0.0)
+    {
+        lit = min(da*6.0, 1.0) * dist_atten;
+
+        vec3 npos = -normalize(pos);
+        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*color.rgb*spec.rgb;
+        }
+    }
+    
+    if (dot(col, col) <= 0.0)
+    {
+        discard;
+    }
+//col.rgb = vec3(0);        
+    frag_color.rgb = col;   
+    frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
index a5625fbc16e1f567a41ff5f806ab187481a039ee..3da853144280848748666a7eced8a6c4418bf64e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file pointLightF.glsl
+ * @file pointLightV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index 6669947d1b3b214633f30cf8cb6dcd425922662c..cd37a34e0d0f49b0c7cfad9dead5733857bb11a5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -37,33 +37,16 @@ uniform sampler2DRect diffuseRect;
 
 uniform vec2 screen_res;
 VARYING vec2 vary_fragcoord;
-
 uniform float display_gamma;
 
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
+vec3 linear_to_srgb(vec3 cl);
 
 void main() 
 {
-	vec4 diff = texture2DRect(diffuseRect, vary_fragcoord);
-	diff.rgb = linear_to_srgb(diff.rgb);
-	frag_color = diff;
+    //this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
+    vec4 diff = texture2DRect(diffuseRect, vary_fragcoord);
+    //diff.rgb = pow(diff.rgb, vec3(display_gamma));
+    diff.rgb = linear_to_srgb(diff.rgb);
+    frag_color = diff;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
index 018ced4cadb0f108c788cabe0e1e58f2b613ae4c..cf994d35470a7ef4f22ab6c507d7cb2b5e7c94e9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
  #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
@@ -47,18 +49,7 @@ VARYING vec2 vary_fragcoord;
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..44f2a73e1f0b88bb5a2c79b96a8220aa5b07a46f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendF.glsl
@@ -0,0 +1,55 @@
+/** 
+ * @file shadowAlphaMaskF.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING float pos_w;
+
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void main() 
+{
+	float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
+
+	frag_color = vec4(alpha, alpha, alpha, 1);
+	
+#if !defined(DEPTH_CLAMP)
+	gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..f45c343066623438889e5bcc5ce522edc04df017
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaBlendV.glsl
@@ -0,0 +1,67 @@
+/** 
+ * @file shadowAlphaMaskV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING float pos_w;
+
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+	vec4 pos = modelview_projection_matrix * pre_pos;
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+	pos_w = pos.w;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+	vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
index 91a96977f06c15dd306fdf64d8360b7bae9c4e70..9b8df0a5a462ae3d2b187e43fc60e7e4ccf2bf2e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
@@ -31,19 +33,25 @@ out vec4 frag_color;
 
 uniform sampler2D diffuseMap;
 
-#if !DEPTH_CLAMP
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
+VARYING vec4 post_pos;
 VARYING float target_pos_x;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
+uniform float minimum_alpha;
 
 void main() 
 {
-	float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
+	float alpha = diffuseLookup(vary_texcoord0.xy).a;
+
+    // mask cutoff 0 -> no shadow SL-11051
+    if (minimum_alpha == 0)
+    {
+        discard;
+    }
+
+#if !defined(IS_FULLBRIGHT)
+    alpha *= vertex_color.a;
+#endif
 
 	if (alpha < 0.05) // treat as totally transparent
 	{
@@ -52,7 +60,7 @@ void main()
 
 	if (alpha < 0.88) // treat as semi-transparent
 	{
-	  if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+	  if (fract(0.5*floor(target_pos_x / post_pos.w )) < 0.25)
 	  {
 	    discard;
 	  }
@@ -60,7 +68,7 @@ void main()
 
 	frag_color = vec4(1,1,1,1);
 	
-#if !DEPTH_CLAMP
-	gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
+#if !defined(DEPTH_CLAMP)
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
 #endif
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
index 11411a605c69d04774360a525579aae4d5e449a6..b6a0f0b16519882df0435fd6fef635764b197fce 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl
@@ -31,12 +31,7 @@ ATTRIBUTE vec3 position;
 ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
 
-#if !DEPTH_CLAMP
-VARYING float pos_zd2;
-#endif
-
-VARYING float pos_w;
-
+VARYING vec4 post_pos;
 VARYING float target_pos_x;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
@@ -50,11 +45,9 @@ void main()
 	vec4 pos = modelview_projection_matrix * pre_pos;
 	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
 
-	pos_w = pos.w;
+	post_pos = pos;
 
-#if !DEPTH_CLAMP
-	pos_zd2 = pos.z * 0.5;
-	
+#if !defined(DEPTH_CLAMP)
 	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
 #else
 	gl_Position = pos;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
index ef153dfc5be3d3cb92838d8efdd1c72ea1d9ba47..0e74d2eb8a64d72392f9aae68dda25880f63754f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowCubeV.glsl
@@ -27,7 +27,7 @@ uniform mat4 modelview_projection_matrix;
 
 ATTRIBUTE vec3 position;
 
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 VARYING vec4 post_pos;
 #endif
 
@@ -40,7 +40,7 @@ void main()
 	vec3 p = position*box_size+box_center;
 	vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
 
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 	post_pos = pos;
 
 	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
index 3d1b1828755a2a5e54723efa9c6f32f078e415d1..1ea96918bba99da27a6c3fc1f3c28f106f5b9716 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl
@@ -23,21 +23,21 @@
  * $/LicenseInfo$
  */
  
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
 #define frag_color gl_FragColor
 #endif
 
-#if !DEPTH_CLAMP
 VARYING vec4 post_pos;
-#endif
 
 void main() 
 {
 	frag_color = vec4(1,1,1,1);
 	
-#if !DEPTH_CLAMP
+#if !defined(DEPTH_CLAMP)
 	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
 #endif
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..41342203063163d04556e1c2685e9ba5db6f90ca
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
@@ -0,0 +1,221 @@
+/** 
+ * @file class1/deferred/shadowUtil.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$
+ */
+
+uniform sampler2DRect   normalMap;
+uniform sampler2DRect   depthMap;
+uniform sampler2DShadow shadowMap0;
+uniform sampler2DShadow shadowMap1;
+uniform sampler2DShadow shadowMap2;
+uniform sampler2DShadow shadowMap3;
+uniform sampler2DShadow shadowMap4;
+uniform sampler2DShadow shadowMap5;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float shadow_bias;
+uniform float shadow_offset;
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+uniform int sun_up_factor;
+
+float pcfShadow(sampler2DShadow shadowMap, vec3 norm, vec4 stc, float bias_mul, vec2 pos_screen, vec3 light_dir)
+{
+    float offset = shadow_bias * bias_mul;
+    stc.xyz /= stc.w;
+    stc.z += offset * 2.0;
+    stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*shadow_res.y))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
+    float cs = shadow2D(shadowMap, stc.xyz).x;
+    float shadow = cs * 4.0;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3( 1.5/shadow_res.x,  0.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3( 0.5/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x,  1.5/shadow_res.y, 0.0)).x;
+    return clamp(shadow * 0.125, 0.0, 1.0);
+}
+
+float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2 pos_screen)
+{
+    stc.xyz /= stc.w;
+    stc.z += spot_shadow_bias * bias_scale;
+    stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
+
+    float cs = shadow2D(shadowMap, stc.xyz).x;
+    float shadow = cs;
+
+    vec2 off = 1.0/proj_shadow_res;
+    off.y *= 1.5;
+    
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
+    shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
+    return shadow*0.2;
+}
+
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
+{
+    float shadow = 0.0f;
+    vec3 light_dir = normalize((sun_up_factor == 1) ? sun_dir : moon_dir);
+
+    float dp_directional_light = max(0.0, dot(norm.xyz, light_dir));
+          dp_directional_light = clamp(dp_directional_light, 0.0, 1.0);
+
+    vec3 shadow_pos = pos.xyz;
+
+    vec3 offset = light_dir.xyz * (1.0 - dp_directional_light);
+
+    shadow_pos += offset * shadow_offset * 2.0;
+
+    vec4 spos = vec4(shadow_pos.xyz, 1.0);
+
+    if (spos.z > -shadow_clip.w)
+    {   
+        vec4 lpos;
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        if (spos.z < near_split.z)
+        {
+            lpos = shadow_matrix[3]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+            //w = clamp(w, 0.0, 1.0);
+            float contrib = pcfShadow(shadowMap3, norm, lpos, 1.0, pos_screen, light_dir)*w;
+            //if (contrib > 0)
+            {
+                shadow += contrib;
+                weight += w;
+            }
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        if (spos.z < near_split.y && spos.z > far_split.z)
+        {
+            lpos = shadow_matrix[2]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
+            w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
+            //w = clamp(w, 0.0, 1.0);
+            float contrib = pcfShadow(shadowMap2, norm, lpos, 1.0, pos_screen, light_dir)*w;
+            //if (contrib > 0)
+            {
+                shadow += contrib;
+                weight += w;
+            }
+        }
+
+        if (spos.z < near_split.x && spos.z > far_split.y)
+        {
+            lpos = shadow_matrix[1]*spos;
+            
+            float w = 1.0;
+            w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
+            w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
+            //w = clamp(w, 0.0, 1.0);
+            float contrib = pcfShadow(shadowMap1, norm, lpos, 1.0, pos_screen, light_dir)*w;
+            //if (contrib > 0)
+            {
+                shadow += contrib;
+                weight += w;
+            }
+        }
+
+        if (spos.z > far_split.x)
+        {
+            lpos = shadow_matrix[0]*spos;
+                            
+            float w = 1.0;
+            w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
+            //w = clamp(w, 0.0, 1.0);
+            float contrib = pcfShadow(shadowMap0, norm, lpos, 1.0, pos_screen, light_dir)*w;
+            //if (contrib > 0)
+            {
+                shadow += contrib;
+                weight += w;
+            }
+        }
+
+        shadow /= weight;
+    }
+    else
+    {
+        return 1.0f; // lit beyond the far split...
+    }
+    //shadow = min(dp_directional_light,shadow);
+    return shadow;
+}
+
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
+{
+    float shadow = 0.0f;
+    pos += norm * spot_shadow_offset;
+
+    vec4 spos = vec4(pos,1.0);
+    if (spos.z > -shadow_clip.w)
+    {   
+        vec4 lpos;
+        
+        vec4 near_split = shadow_clip*-0.75;
+        vec4 far_split = shadow_clip*-1.25;
+        vec4 transition_domain = near_split-far_split;
+        float weight = 0.0;
+
+        {
+            float w = 1.0;
+            w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
+
+            if (index == 0)
+            {        
+                lpos = shadow_matrix[4]*spos;
+                shadow += pcfSpotShadow(shadowMap4, lpos, 0.8, spos.xy)*w;
+            }
+            else
+            {
+                lpos = shadow_matrix[5]*spos;
+                shadow += pcfSpotShadow(shadowMap5, lpos, 0.8, spos.xy)*w;
+            }
+            weight += w;
+            shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
+        }
+
+        shadow /= weight;
+    }
+    else
+    {
+        shadow = 1.0f;
+    }
+    return shadow;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
index cc77a4cea059729e64d2c67cefc9cb5032c8cb48..72bd0f0f34e5b7393191afe7d6c5ae854d30c484 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl
@@ -27,20 +27,19 @@ uniform mat4 modelview_projection_matrix;
 
 ATTRIBUTE vec3 position;
 
-#if !DEPTH_CLAMP
 VARYING vec4 post_pos;
-#endif
 
 void main()
 {
 	//transform vertex
 	vec4 pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
 	
-#if !DEPTH_CLAMP
 	post_pos = pos;
 
+#if !defined(DEPTH_CLAMP)
 	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
 #else
 	gl_Position = pos;
 #endif
+
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
index 22f4729e2e3f8a8e7f9af025e5ce65f72a20d4f9..331249dc33b509b52648944fa4363a81392a4f24 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLSkyF.glsl
+ * @file class1/deferred/skyF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
  
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -35,32 +37,28 @@ out vec4 frag_data[3];
 
 VARYING vec4 vary_HazeColor;
 
-uniform sampler2D cloud_noise_texture;
-uniform vec4 gamma;
-
 /// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
+vec3 scaleSoftClip(vec3 light);
+vec3 srgb_to_linear(vec3 c);
 
 void main()
 {
-	// Potential Fill-rate optimization.  Add cloud calculation 
-	// back in and output alpha of 0 (so that alpha culling kills 
-	// the fragment) if the sky wouldn't show up because the clouds 
-	// are fully opaque.
+    // Potential Fill-rate optimization.  Add cloud calculation 
+    // back in and output alpha of 0 (so that alpha culling kills 
+    // the fragment) if the sky wouldn't show up because the clouds 
+    // are fully opaque.
+
+    vec4 color;
+    color = vary_HazeColor;
+
+    color.rgb *= 2.;
+    color.rgb = scaleSoftClip(color.rgb);
 
-	vec4 color;
-	color = vary_HazeColor;
-	color *= 2.;
+    /// Gamma correct for WL (soft clip effect).
+    frag_data[0] = vec4(color.rgb, 0.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
 
-	/// Gamma correct for WL (soft clip effect).
-	frag_data[0] = vec4(scaleSoftClip(color.rgb), 1.0);
-	frag_data[1] = vec4(0.0,0.0,0.0,0.0);
-	frag_data[2] = vec4(0.5,0.5,0.0,1.0); //1.0 in norm.w masks off fog
+    gl_FragDepth = 0.99999f;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
index 7c02d31d436e5446be6648dccae7010f17fcdb5b..ead754ec76184e1ef81c3aed376c1329ebbac909 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl
@@ -39,7 +39,9 @@ uniform vec3 camPosLocal;
 
 uniform vec4 lightnorm;
 uniform vec4 sunlight_color;
-uniform vec4 ambient;
+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;
@@ -47,21 +49,28 @@ uniform float haze_density;
 
 uniform float cloud_shadow;
 uniform float density_multiplier;
+uniform float distance_multiplier;
 uniform float max_y;
 
 uniform vec4 glow;
+uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
 
+// 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\lllegacyatmospherics.cpp
 void main()
 {
 
 	// World / view / projection
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+    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);
-	//vec3 P = position.xyz + vec3(0,50,0);
 
 	// Set altitude
 	if (P.y > 0.)
@@ -75,39 +84,40 @@ void main()
 
 	// Can normalize then
 	vec3 Pn = normalize(P);
-	float  Plen = length(P);
+
+	float Plen = length(P);
 
 	// Initialize temp variables
 	vec4 temp1 = vec4(0.);
 	vec4 temp2 = vec4(0.);
 	vec4 blue_weight;
 	vec4 haze_weight;
-	vec4 sunlight = sunlight_color;
+	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)) * (density_multiplier * max_y);
+	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
 
 	// Calculate relative weights
-	temp1 = blue_density + haze_density;
+	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);
+    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 * density_multiplier;
+	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);
-
+    // 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);
@@ -123,35 +133,33 @@ void main()
 	// Add "minimum anti-solar illumination"
 	temp2.x += .25;
 
+    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
+                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
+             );
 
-	// Haze color above cloud
-	vary_HazeColor = (	  blue_horizon * blue_weight * (sunlight + ambient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)
-			 );	
 
+    // Final atmosphere additive
+    color *= (1. - temp1);
 
 	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient;
-	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
+	vec4 tmpAmbient = ambient_color;
+	tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; 
 
 	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1. - cloud_shadow);
+	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)
 			 );	
 
-	// Final atmosphere additive
-	vary_HazeColor *= (1. - temp1);
-	
 	// Attenuate cloud color by atmosphere
 	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
 
 	// At horizon, blend high altitude sky color towards the darker color below the clouds
-	vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1));
-	
-	// won't compile on mac without this being set
-	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+	color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+
+    // Haze color above cloud
+	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 03bdb754b57b22f057746cb8d5a5a7ef9ac9d8c8..a5804220bc069a0ac8dca479953699e454e1ad16 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file softenLightF.glsl
+ * @file class1/deferred/softenLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -36,442 +36,161 @@ out vec4 frag_color;
 
 uniform sampler2DRect diffuseRect;
 uniform sampler2DRect specularRect;
-uniform sampler2DRect positionMap;
 uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 uniform sampler2DRect depthMap;
 uniform samplerCube environmentMap;
-uniform sampler2D	  lightFunc;
+uniform sampler2D     lightFunc;
 
 uniform float blur_size;
 uniform float blur_fidelity;
 
 // Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-//uniform vec4 camPosWorld;
-uniform vec4 gamma;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-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 float global_gamma;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
-uniform mat3 ssao_effect_mat;
 
 uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform int sun_up_factor;
 VARYING vec2 vary_fragcoord;
 
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition_d(vec2 pos_screen, float depth)
-{
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).a;
-	return getPosition_d(pos_screen, depth);
-}
-
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
+vec3 getNorm(vec2 pos_screen);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
 
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
+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 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
 
 #ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
+vec4 applyWaterFogView(vec3 pos, vec4 color);
 #endif
 
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(0);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//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;
-	
-	//increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
-
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-
-
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / scene_light_strength );
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * scene_light_strength);
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + light / 2.0;
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * lightIntensity;
-}
-
-vec3 scaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
-
-
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
-}
-
 void main() 
 {
-	vec2 tc = vary_fragcoord.xy;
-	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec3 pos = getPosition_d(tc, depth).xyz;
-	vec4 norm = texture2DRect(normalMap, tc);
-	float envIntensity = norm.z;
-	norm.xyz = decode_normal(norm.xy); // unpack norm
-		
-	float da = dot(norm.xyz, sun_dir.xyz);
-
-	float final_da = max(0.0,da);
-          final_da = min(final_da, 1.0f);
-	      final_da = pow(final_da, 1.0/1.3);
-
-	vec4 diffuse = texture2DRect(diffuseRect, tc);
-
-	//convert to gamma space
-	diffuse.rgb = linear_to_srgb(diffuse.rgb);
-
-	vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-	vec3 col;
-	float bloom = 0.0;
-	{
-		calcAtmospherics(pos.xyz, 1.0);
-	
-		col = atmosAmbient(vec3(0));
-		float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
-		ambient *= 0.5;
-		ambient *= ambient;
-		ambient = (1.0-ambient);
-
-		col.rgb *= ambient;
-
-		col += atmosAffectDirectionalLight(final_da);	
-	
-		col *= diffuse.rgb;
-	
-		vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
-		if (spec.a > 0.0) // specular reflection
-		{
-			// the old infinite-sky shiny reflection
-			//
-			
-			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = vary_SunlitColor*(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;
-			col += spec_contrib;
-		}
-		
-		
-		col = mix(col.rgb, diffuse.rgb, diffuse.a);
-				
-		if (envIntensity > 0.0)
-		{ //add environmentmap
-			vec3 env_vec = env_mat * refnormpersp;
-			
-			
-			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
-
-			col = mix(col.rgb, refcol, 
-				envIntensity);  
-		}
-				
-		if (norm.w < 0.5)
-		{
-			col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
-			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
-		}
-
-		#ifdef WATER_FOG
-			vec4 fogged = applyWaterFogDeferred(pos,vec4(col, bloom));
-			col = fogged.rgb;
-			bloom = fogged.a;
-		#endif
-
-		col = srgb_to_linear(col);
-
-		//col = vec3(1,0,1);
-		//col.g = envIntensity;
-	}
-
-	frag_color.rgb = col.rgb;
-	frag_color.a = bloom;
-}
+    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);
+    
+    vec4 diffuse = texture2DRect(diffuseRect, tc);
+
+    //convert to gamma space
+    //diffuse.rgb = linear_to_srgb(diffuse.rgb);
+
+    vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+    vec3 color = vec3(0);
+    float bloom = 0.0;
+    {
+        float ambocc = 1.0; // no AO...
+
+        vec3 sunlit;
+        vec3 amblit;
+        vec3 additive;
+        vec3 atten;
+    
+        calcAtmosphericVars(pos.xyz, light_dir, ambocc, sunlit, amblit, additive, atten, false);
+
+        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 = da * 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
 
+        }
+       
+       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
+
+    }
+
+// linear debuggables
+//color.rgb = vec3(final_da);
+//color.rgb = vec3(ambient);
+//color.rgb = vec3(scol);
+//color.rgb = diffuse_srgb.rgb;
+
+    // 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;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
index b59fcbe0176e32582efff8bff94401a82b74b98e..8891315e1563b6b0054a6a3018f05cc21ecab46b 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file softenLightF.glsl
+ * @file softenLightV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -29,12 +29,17 @@ ATTRIBUTE vec3 position;
 
 uniform vec2 screen_res;
 
+void setAtmosAttenuation(vec3 c);
+void setAdditiveColor(vec3 c);
+
 VARYING vec2 vary_fragcoord;
 void main()
 {
-	//transform vertex
-	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
-	gl_Position = pos; 
-	
-	vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+    //transform vertex
+    vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+    gl_Position = pos; 
+    // appease OSX GLSL compiler/linker by touching all the varyings we said we would
+    setAtmosAttenuation(vec3(1));
+    setAdditiveColor(vec3(0));
+    vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
index f1aec315ccce78c9cc6cb4dda7edaebc845513fc..694b19cdfb7ca64471ca9d717f758dbdde3071e4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl
@@ -70,64 +70,8 @@ uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-vec4 correctWithGamma(vec4 col)
-{
-	return vec4(srgb_to_linear(col.rgb), col.a);
-}
+vec3 getNorm(vec2 pos_screen);
+vec3 srgb_to_linear(vec3 c);
 
 vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
@@ -152,7 +96,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
+	ret.rgb = srgb_to_linear(ret.rgb);
 	
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
@@ -170,7 +114,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
+	ret.rgb = srgb_to_linear(ret.rgb);
 	
 	vec2 dist = tc-vec2(0.5);
 	
@@ -181,22 +125,15 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
+	vec3 col = vec3(0,0,0);
+
+#if defined(LOCAL_LIGHT_KILL)
+    discard;
+#else
 	vec4 frag = vary_fragcoord;
 	frag.xyz /= frag.w;
 	frag.xyz = frag.xyz*0.5+0.5;
@@ -210,12 +147,10 @@ void main()
 	{
 		discard;
 	}
-	
 		
 	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
 	float envIntensity = norm.z;
-	norm = decode_normal(norm.xy);
-	
+	norm = getNorm(frag.xy);
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
 	
@@ -241,13 +176,11 @@ void main()
 	lv = normalize(lv);
 	float da = dot(norm, lv);
 		
-	vec3 col = vec3(0,0,0);
-		
 	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
-		
-	vec4 spec = texture2DRect(specularRect, frag.xy);
+	//light shaders output linear and are gamma corrected later in postDeferredGammaCorrectF.glsl
+    diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
 
-	
+	vec4 spec = texture2DRect(specularRect, frag.xy);
 
 	float noise = texture2D(noiseMap, frag.xy/128.0).b;
 	vec3 dlit = vec3(0, 0, 0);
@@ -284,7 +217,6 @@ void main()
 		amb_da = min(amb_da, 1.0-lit);
 		col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a*diff_tex.rgb;
 	}
-	
 
 	if (spec.a > 0.0)
 	{
@@ -311,7 +243,6 @@ void main()
 		}
 	}	
 
-
 	if (envIntensity > 0.0)
 	{
 		vec3 ref = reflect(normalize(pos), norm);
@@ -340,7 +271,9 @@ void main()
 			}
 		}
 	}
-	
+#endif
+
+	//col.r = 1.0;
 	frag_color.rgb = col;	
 	frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
index 821058804c9e2ef3ef7bd05f323f8546cc69606f..bac79a9fdc73d30f404020d8701c91abd64eddf9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -31,14 +33,35 @@ out vec4 frag_data[3];
 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
+VARYING vec2 screenpos;
 
 uniform sampler2D diffuseMap;
+uniform sampler2D altDiffuseMap;
+uniform float blend_factor;
+uniform float custom_alpha;
+uniform float time;
+
+float twinkle(){
+    float d = fract(screenpos.x + screenpos.y);
+    return abs(d);
+}
 
 void main() 
 {
-	vec4 col = vertex_color * texture2D(diffuseMap, vary_texcoord0.xy);
-	
-	frag_data[0] = col;
-	frag_data[1] = vec4(0,0,0,0);
-	frag_data[2] = vec4(0,0,1,0);	
+    vec4 col_a = texture2D(diffuseMap, vary_texcoord0.xy);
+    vec4 col_b = texture2D(diffuseMap, vary_texcoord0.xy);
+    vec4 col = mix(col_b, col_a, blend_factor);
+    col.rgb *= vertex_color.rgb;
+ 
+    float factor = smoothstep(0.0f, 0.9f, custom_alpha);
+
+    col.a = (col.a * factor) * 32.0f;
+    col.a *= twinkle();
+
+    frag_data[0] = col;
+    frag_data[1] = vec4(0.0f);
+    frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+
+    gl_FragDepth = 0.99995f;
 }
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
index 8bc5b063799a77d7edc481fc0283c1577dc319c0..bb2a2ee72b1681098e03000b452902da65dccd9c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl
@@ -25,6 +25,7 @@
 
 uniform mat4 texture_matrix0;
 uniform mat4 modelview_projection_matrix;
+uniform float time;
 
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec4 diffuse_color;
@@ -32,11 +33,20 @@ ATTRIBUTE vec2 texcoord0;
 
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
+VARYING vec2 screenpos;
 
 void main()
 {
 	//transform vertex
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); 
+    vec4 pos = modelview_projection_matrix * vec4(position, 1.0);
+
+// bias z to fix SL-9806 and get stars to depth test against clouds
+    pos.z += 0.001f;
+
+	gl_Position = pos;
+
+    float t = mod(time, 1.25f);
+    screenpos = position.xy * vec2(t, t);
 	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
 	vertex_color = diffuse_color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..454af2a9bcee478fbe107402a564d52a32a5328c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
@@ -0,0 +1,68 @@
+/** 
+ * @file sunDiscF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+vec3 srgb_to_linear(vec3 c);
+vec3 fullbrightAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+uniform sampler2D diffuseMap;
+uniform sampler2D altDiffuseMap;
+uniform float blend_factor; // interp factor between sunDisc A/B
+VARYING vec2 vary_texcoord0;
+VARYING float sun_fade;
+
+void main() 
+{
+    vec4 sunDiscA = texture2D(diffuseMap, vary_texcoord0.xy);
+    vec4 sunDiscB = texture2D(altDiffuseMap, vary_texcoord0.xy);
+    vec4 c     = mix(sunDiscA, sunDiscB, blend_factor);
+
+    c.rgb = srgb_to_linear(c.rgb);
+    c.rgb = clamp(c.rgb, vec3(0), vec3(1));
+    c.rgb = pow(c.rgb, vec3(0.7f));
+
+    //c.rgb = fullbrightAtmosTransport(c.rgb);
+    c.rgb = fullbrightScaleSoftClip(c.rgb);
+
+    // SL-9806 stars poke through
+    //c.a *= sun_fade;
+
+    frag_data[0] = c;
+    frag_data[1] = vec4(0.0f);
+    frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+
+    gl_FragDepth = 0.999988f;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..0d117c6bc7f467589f14d12e2662ed9de8a4ce04
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscV.glsl
@@ -0,0 +1,52 @@
+/** 
+ * @file sunDiscV.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$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_texcoord0;
+VARYING float sun_fade;
+
+void calcAtmospherics(vec3 eye_pos);
+
+void main()
+{
+    //transform vertex
+    vec3 offset = vec3(0, 0, 50);
+    vec4 vert = vec4(position.xyz - offset, 1.0);
+    vec4 pos  = modelview_projection_matrix*vert;
+
+    sun_fade = smoothstep(0.3, 1.0, (position.z + 50) / 512.0f);
+
+    gl_Position = pos;
+    
+    calcAtmospherics(pos.xyz);
+
+    vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 930255729b0cc06f176be1f206aa0786a4862ee0..15f141cbe587067058b5e45b2018f0e50cdf07e6 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -35,103 +35,16 @@ out vec4 frag_color;
 
 //class 1 -- no shadow, SSAO only
 
-uniform sampler2DRect depthMap;
 uniform sampler2DRect normalMap;
-uniform sampler2D noiseMap;
-
 
 // Inputs
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
-
 VARYING vec2 vary_fragcoord;
 
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec3 getNorm(vec2 pos_screen);
+vec4 getPosition(vec2 pos_screen);
 
 //calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
-	float ret = 1.0;
-	
-	vec2 kern[8];
-	// exponentially (^2) distant occlusion samples spread around origin
-	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-
-	vec2 pos_screen = vary_fragcoord.xy;
-	vec3 pos_world = pos.xyz;
-	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
-		
-	float angle_hidden = 0.0;
-	int points = 0;
-		
-	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
-		
-	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
-	for (int i = 0; i < 8; i++)
-	{
-		vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
-		vec3 samppos_world = getPosition(samppos_screen).xyz; 
-			
-		vec3 diff = pos_world - samppos_world;
-		float dist2 = dot(diff, diff);
-			
-		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
-		// --> solid angle shrinking by the square of distance
-		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
-		//(k should vary inversely with # of samples, but this is taken care of later)
-			
-		angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
-			
-		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
-		points = points + int(diff.z > -1.0);
-	}
-		
-	angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
-		
-	ret = (1.0 - (float(points != 0) * angle_hidden));
-	
-	return min(ret, 1.0);
-}
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
 
 void main() 
 {
@@ -139,13 +52,11 @@ void main()
 	
 	//try doing an unproject here
 	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy);
-		
+	vec4 pos  = getPosition(pos_screen);
+	vec3 norm = getNorm(pos_screen);
+
 	frag_color[0] = 1.0;
-	frag_color[1] = calcAmbientOcclusion(pos, norm);
+	frag_color[1] = calcAmbientOcclusion(pos, norm, pos_screen);
 	frag_color[2] = 1.0; 
 	frag_color[3] = 1.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
index 52a429465f31ab6cffb837ffa9f0ff23d0de06b3..6b6eed9db8805c7eab8d1cfb9ab29e25f6b861f5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file terrainF.glsl
+ * @file class1\deferred\terrainF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
  
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -35,33 +37,32 @@ uniform sampler2D detail_2;
 uniform sampler2D detail_3;
 uniform sampler2D alpha_ramp;
 
+VARYING vec3 pos;
 VARYING vec3 vary_normal;
 VARYING vec4 vary_texcoord0;
 VARYING vec4 vary_texcoord1;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main()
 {
-	/// Note: This should duplicate the blending functionality currently used for the terrain rendering.
-	
-	vec4 color0 = texture2D(detail_0, vary_texcoord0.xy);
-	vec4 color1 = texture2D(detail_1, vary_texcoord0.xy);
-	vec4 color2 = texture2D(detail_2, vary_texcoord0.xy);
-	vec4 color3 = texture2D(detail_3, vary_texcoord0.xy);
+    /// Note: This should duplicate the blending functionality currently used for the terrain rendering.
+    
+    vec4 color0 = texture2D(detail_0, vary_texcoord0.xy);
+    vec4 color1 = texture2D(detail_1, vary_texcoord0.xy);
+    vec4 color2 = texture2D(detail_2, vary_texcoord0.xy);
+    vec4 color3 = texture2D(detail_3, vary_texcoord0.xy);
 
-	float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a;
-	float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a;
-	float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a;
-	vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal );
-	
-	frag_data[0] = vec4(outColor.rgb, 0.0);
-	frag_data[1] = vec4(0,0,0,0);
-	vec3 nvn = normalize(vary_normal);
-	frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
+    float alpha1 = texture2D(alpha_ramp, vary_texcoord0.zw).a;
+    float alpha2 = texture2D(alpha_ramp,vary_texcoord1.xy).a;
+    float alphaFinal = texture2D(alpha_ramp, vary_texcoord1.zw).a;
+    vec4 outColor = mix( mix(color3, color2, alpha2), mix(color1, color0, alpha1), alphaFinal );
+   
+    outColor.a = 0.0; // yes, downstream atmospherics 
+    
+    frag_data[0] = outColor;
+    frag_data[1] = vec4(0.0,0.0,0.0,-1.0);
+    vec3 nvn = normalize(vary_normal);
+    frag_data[2] = vec4(encode_normal(nvn.xyz), 0.0, 0.0);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
index 5effee4e4eabd76c2940129ebf68afb46f0febda..f42cb6ff6dbaf637be15ad99c6d857a281347333 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file terrainV.glsl
+ * @file class1\environment\terrainV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -33,8 +33,8 @@ ATTRIBUTE vec4 diffuse_color;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec2 texcoord1;
 
+VARYING vec3 pos;
 VARYING vec3 vary_normal;
-
 VARYING vec4 vary_texcoord0;
 VARYING vec4 vary_texcoord1;
 
@@ -43,31 +43,35 @@ uniform vec4 object_plane_t;
 
 vec4 texgen_object(vec4  vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
 {
-	vec4 tcoord;
-	
-	tcoord.x = dot(vpos, tp0);
-	tcoord.y = dot(vpos, tp1);
-	tcoord.z = tc.z;
-	tcoord.w = tc.w;
-	
-	tcoord = mat * tcoord; 
-	
-	return tcoord; 
+    vec4 tcoord;
+    
+    tcoord.x = dot(vpos, tp0);
+    tcoord.y = dot(vpos, tp1);
+    tcoord.z = tc.z;
+    tcoord.w = tc.w;
+    
+    tcoord = mat * tcoord; 
+    
+    return tcoord; 
 }
 
 void main()
 {
-	//transform vertex
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-			
-	vary_normal = normalize(normal_matrix * normal);
-	
-	// Transform and pass tex coords
- 	vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy;
-	
-	vec4 t = vec4(texcoord1,0,1);
-	
-	vary_texcoord0.zw = t.xy;
-	vary_texcoord1.xy = t.xy-vec2(2.0, 0.0);
-	vary_texcoord1.zw = t.xy-vec2(1.0, 0.0);
+    //transform vertex
+    vec4 pre_pos = vec4(position.xyz, 1.0);
+    vec4 t_pos = modelview_projection_matrix * pre_pos;
+
+    gl_Position = t_pos;
+    pos = t_pos.xyz;
+
+    vary_normal = normalize(normal_matrix * normal);
+    
+    // Transform and pass tex coords
+    vary_texcoord0.xy = texgen_object(vec4(position, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy;
+    
+    vec4 t = vec4(texcoord1,0,1);
+    
+    vary_texcoord0.zw = t.xy;
+    vary_texcoord1.xy = t.xy-vec2(2.0, 0.0);
+    vary_texcoord1.zw = t.xy-vec2(1.0, 0.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
index 808750496f96e62263130f173814bf4530c1790b..89e354558a219c2cfdb10bb567e2830bea2c48b4 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -37,11 +39,7 @@ VARYING vec2 vary_texcoord0;
 
 uniform float minimum_alpha;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
index d4d2f5f5713a8c26c735d146597fbd61c03b0238..e34d75ba1d5efff05970e3f46ead131732b1bdb0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
index 78f841c73314ece6b65658efcf9701700339ea87..9a5debb3c125729cacd1f0d4ef47eed7efc3e908 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
@@ -23,6 +23,8 @@
  * $/LicenseInfo$
  */
  
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_data[3];
 #else
@@ -56,84 +58,7 @@ VARYING vec4 refCoord;
 VARYING vec4 littleWave;
 VARYING vec4 view;
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec4 applyWaterFog(vec4 color, vec3 viewVec)
-{
-	//normalize view vector
-	vec3 view = normalize(viewVec);
-	float es = -view.z;
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	//get object depth
-	float depth = length(viewVec);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	//return vec4(1.0, 0.0, 1.0, 1.0);
-	return color * D + kc * L;
-	//depth /= 10.0;
-	//return vec4(depth,depth,depth,0.0);
-}
+vec2 encode_normal(vec3 n);
 
 void main() 
 {
@@ -151,7 +76,7 @@ void main()
 		
 	vec4 fb = texture2D(screenTex, distort);
 
-	frag_data[0] = vec4(linear_to_srgb(fb.rgb), 1.0); // diffuse
+	frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
 	frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
-	frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace
+	frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, env intens, atmo kill
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 37dcd3ad3493178602a7a5b396aa8b6a75d89dee..a157e9c017bfd8fdabb4328357eca58f0f77afea 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file waterF.glsl
+ * @file class1/deferred/waterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -37,17 +37,10 @@ vec3 scaleSoftClip(vec3 inColor);
 vec3 atmosTransport(vec3 inColor);
 
 uniform sampler2D bumpMap;   
+uniform sampler2D bumpMap2;
+uniform float blend_factor;
 uniform sampler2D screenTex;
 uniform sampler2D refTex;
-uniform sampler2DRectShadow shadowMap0;
-uniform sampler2DRectShadow shadowMap1;
-uniform sampler2DRectShadow shadowMap2;
-uniform sampler2DRectShadow shadowMap3;
-uniform sampler2D noiseMap;
-
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-
 uniform float sunAngle;
 uniform float sunAngle2;
 uniform vec3 lightDir;
@@ -62,6 +55,7 @@ uniform float fresnelOffset;
 uniform float blurMultiplier;
 uniform vec2 screen_res;
 uniform mat4 norm_mat; //region space to screen space
+uniform int water_edge;
 
 //bigWave is (refCoord.w, view.w);
 VARYING vec4 refCoord;
@@ -69,111 +63,89 @@ VARYING vec4 littleWave;
 VARYING vec4 view;
 VARYING vec4 vary_position;
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
+vec2 encode_normal(vec3 n);
+vec3 scaleSoftClip(vec3 l);
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
 
-vec2 encode_normal(vec3 n)
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
 {
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
+    vec3 n = mix(bump1, bump2, blend_factor);
+    return n;
 }
 
 void main() 
 {
-	vec4 color;
-	float dist = length(view.xy);
-	
-	//normalize view vector
-	vec3 viewVec = normalize(view.xyz);
-	
-	//get wave normals
-	vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
-	vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
-	vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-	//get base fresnel components	
-	
-	vec3 df = vec3(
-					dot(viewVec, wave1),
-					dot(viewVec, (wave2 + wave3) * 0.5),
-					dot(viewVec, wave3)
-				 ) * fresnelScale + fresnelOffset;
-	df *= df;
-		    
-	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-	
-	float dist2 = dist;
-	dist = max(dist, 5.0);
-	
-	float dmod = sqrt(dist);
-	
-	vec2 dmod_scale = vec2(dmod*dmod, dmod);
-	
-	//get reflected color
-	vec2 refdistort1 = wave1.xy*normScale.x;
-	vec2 refvec1 = distort+refdistort1/dmod_scale;
-	vec4 refcol1 = texture2D(refTex, refvec1);
-	
-	vec2 refdistort2 = wave2.xy*normScale.y;
-	vec2 refvec2 = distort+refdistort2/dmod_scale;
-	vec4 refcol2 = texture2D(refTex, refvec2);
-	
-	vec2 refdistort3 = wave3.xy*normScale.z;
-	vec2 refvec3 = distort+refdistort3/dmod_scale;
-	vec4 refcol3 = texture2D(refTex, refvec3);
-
-	vec4 refcol = refcol1 + refcol2 + refcol3;
-	float df1 = df.x + df.y + df.z;
+    vec4 color;
+    float dist = length(view.xyz);
+    
+    //normalize view vector
+    vec3 viewVec = normalize(view.xyz);
+    
+    //get wave normals
+    vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+    vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+    //get base fresnel components   
+    
+    vec3 df = vec3(
+                    dot(viewVec, wave1),
+                    dot(viewVec, (wave2 + wave3) * 0.5),
+                    dot(viewVec, wave3)
+                 ) * fresnelScale + fresnelOffset;
+    df *= df;
+            
+    vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+    
+    float dist2 = dist;
+    dist = max(dist, 5.0);
+    
+    float dmod = sqrt(dist);
+    
+    vec2 dmod_scale = vec2(dmod*dmod, dmod);
+    
+    //get reflected color
+    vec2 refdistort1 = wave1.xy*normScale.x;
+    vec2 refvec1 = distort+refdistort1/dmod_scale;
+    vec4 refcol1 = texture2D(refTex, refvec1);
+    
+    vec2 refdistort2 = wave2.xy*normScale.y;
+    vec2 refvec2 = distort+refdistort2/dmod_scale;
+    vec4 refcol2 = texture2D(refTex, refvec2);
+    
+    vec2 refdistort3 = wave3.xy*normScale.z;
+    vec2 refvec3 = distort+refdistort3/dmod_scale;
+    vec4 refcol3 = texture2D(refTex, refvec3);
+
+    vec4 refcol = refcol1 + refcol2 + refcol3;
+    float df1 = df.x + df.y + df.z;
 	refcol *= df1 * 0.333;
-	
-	vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
-	wavef.z *= max(-viewVec.z, 0.1);
-	wavef = normalize(wavef);
-	
-	float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-	
-	vec2 refdistort4 = wavef.xy*0.125;
-	refdistort4.y -= abs(refdistort4.y);
-	vec2 refvec4 = distort+refdistort4/dmod;
-	float dweight = min(dist2*blurMultiplier, 1.0);
-	vec4 baseCol = texture2D(refTex, refvec4);
-
-	refcol = mix(baseCol*df2, refcol, dweight);
-
-	//get specular component
+    
+    vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+    wavef.z *= max(-viewVec.z, 0.1);
+    wavef = normalize(wavef);
+    
+    float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
+    
+    vec2 refdistort4 = wavef.xy*0.125;
+    refdistort4.y -= abs(refdistort4.y);
+    vec2 refvec4 = distort+refdistort4/dmod;
+    float dweight = min(dist2*blurMultiplier, 1.0);
+    vec4 baseCol = texture2D(refTex, refvec4);
+
+    refcol = mix(baseCol*df2, refcol, dweight);
+
+    //get specular component
 	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
 		
 	//harden specular
@@ -186,19 +158,27 @@ void main()
 	
 	//mix with reflection
 	// Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
-	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
+	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999f);
 	
 	vec4 pos = vary_position;
 	
 	color.rgb += spec * specular;
-	
+
 	color.rgb = atmosTransport(color.rgb);
 	color.rgb = scaleSoftClip(color.rgb);
+    
 	color.a   = spec * sunAngle2;
-
+    
 	vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
-	
-	frag_data[0] = vec4(color.rgb, color); // diffuse
-	frag_data[1] = vec4(0);		// speccolor, spec
-	frag_data[2] = vec4(encode_normal(screenspacewavef.xyz*0.5+0.5), 0.05, 0);// normalxy, 0, 0
+
+	//frag_data[0] = color;
+
+    // TODO: The non-obvious assignment below is copied from the pre-EEP WL shader code
+    //       Unfortunately, fixing it causes a mismatch for EEP, and so it remains...  for now
+    //       SL-12975 (unfix pre-EEP broken alpha)
+    frag_data[0] = vec4(color.rgb, color);  // Effectively, color.rgbr
+
+
+    frag_data[1] = vec4(0);		// speccolor, spec
+	frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.05, 0);// normalxy, 0, 0
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
index 9734acf005a372378eff057667cb4bfea6033210..8863869e442a4f3d89f8108575766c52f43e3696 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl
@@ -31,8 +31,8 @@ ATTRIBUTE vec3 position;
 
 void calcAtmospherics(vec3 inPositionEye);
 
-uniform vec2 d1;
-uniform vec2 d2;
+uniform vec2 waveDir1;
+uniform vec2 waveDir2;
 uniform float time;
 uniform vec3 eyeVec;
 uniform float waterHeight;
@@ -88,10 +88,10 @@ void main()
 	calcAtmospherics(pos.xyz);
 		
 	//pass wave parameters to pixel shader
-	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + d1 * time * 0.055;
+	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + waveDir1 * time * 0.055;
 	//get two normal map (detail map) texture coordinates
-	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + d2 * time * 0.13;
-	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
+	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + waveDir2 * time * 0.13;
+	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + waveDir1 * time * 0.1;
 	view.w = bigWave.y;
 	refCoord.w = bigWave.x;
 	
diff --git a/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..50e781fa7867dc6e9755b04994c72b0135ce522c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/environment/encodeNormF.glsl
@@ -0,0 +1,31 @@
+/**
+ * @file encodeNormF.glsl
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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$
+ */
+
+vec2 encode_normal(vec3 n)
+{
+	float f = sqrt(8 * n.z + 8);
+	return n.xy / f + 0.5;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
similarity index 67%
rename from indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl
rename to indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
index 6cc1e6e798d64c31268cac2f4c24a61f7f19cf6c..4a8b892c3ae99a5fd3aa313f419bf72bbb2f4d7e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/srgb_mac.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file srgb.glsl
+ * @file srgbF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -27,14 +27,18 @@ vec3 srgb_to_linear(vec3 cs)
 {
 	vec3 low_range = cs / vec3(12.92);
 	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-
 	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
 
+#ifdef OLD_SELECT
 	vec3 result;
 	result.r = lte.r ? low_range.r : high_range.r;
 	result.g = lte.g ? low_range.g : high_range.g;
 	result.b = lte.b ? low_range.b : high_range.b;
     return result;
+#else
+	return mix(high_range, low_range, lte);
+#endif
+
 }
 
 vec3 linear_to_srgb(vec3 cl)
@@ -42,13 +46,39 @@ vec3 linear_to_srgb(vec3 cl)
 	cl = clamp(cl, vec3(0), vec3(1));
 	vec3 low_range  = cl * 12.92;
 	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-
 	bvec3 lt = lessThan(cl,vec3(0.0031308));
 
+#ifdef OLD_SELECT
 	vec3 result;
 	result.r = lt.r ? low_range.r : high_range.r;
 	result.g = lt.g ? low_range.g : high_range.g;
 	result.b = lt.b ? low_range.b : high_range.b;
-	return result;
+    return result;
+#else
+	return mix(high_range, low_range, lt);
+#endif
+
+}
+
+vec3 ColorFromRadiance(vec3 radiance)
+{
+    return vec3(1.0) - exp(-radiance * 0.0001);
 }
 
+vec3 rgb2hsv(vec3 c)
+{
+    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+    float d = q.x - min(q.w, q.y);
+    float e = 1.0e-10;
+    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+vec3 hsv2rgb(vec3 c)
+{
+    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
index 668a710c042dfe375ee912ecf26f31010d3fc9b1..6b68ed41697209a9ca7fd4fa49c401a72873b7d0 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl
@@ -1,5 +1,5 @@
 /**
- * @file terrainF.glsl
+ * @file class1\environment\terrainF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
index 4d6f0c67a53587f8fba0aec1ad8027b6ea789e2d..ef27848d37dba5cbcb86c92d99900a32cb2d5234 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file terrainV.glsl
+ * @file class1\environment\terrainV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -35,6 +35,7 @@ ATTRIBUTE vec3 position;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec2 texcoord1;
+ATTRIBUTE vec4 diffuse_color;
 
 VARYING vec4 vertex_color;
 VARYING vec4 vary_texcoord0;
@@ -42,7 +43,7 @@ VARYING vec4 vary_texcoord1;
 
 void calcAtmospherics(vec3 inPositionEye);
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 
 vec4 texgen_object(vec4  vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
 {
@@ -71,7 +72,7 @@ void main()
 	/// Potentially better without it for water.
 	pos /= pos.w;
 
-	vec4 color = calcLighting(pos.xyz, norm, vec4(1), vec4(0));
+	vec4 color = calcLighting(pos.xyz, norm, /*diffuse_color*/vec4(1));
 	
 	vertex_color = color;
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
index a956562396039548aa5f72c0ef45cab2749be1c8..e53bb4617732ea48a4be4087d20abfd0692e1bef 100644
--- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl
@@ -1,5 +1,5 @@
 /**
- * @file terrainWaterF.glsl
+ * @file class1\environment\terrainWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -64,4 +64,3 @@ void main()
 	outColor = applyWaterFog(outColor);
 	frag_color = outColor;
 }
-
diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..a075cfeef2433f66210d86418fa60ea2432946ff
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterV.glsl
@@ -0,0 +1,84 @@
+/**
+ * @file class1\environment\terrainV.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$
+ */
+
+uniform mat3 normal_matrix;
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+uniform vec4 object_plane_t;
+uniform vec4 object_plane_s;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+ATTRIBUTE vec2 texcoord1;
+ATTRIBUTE vec4 diffuse_color;
+
+VARYING vec4 vertex_color;
+VARYING vec4 vary_texcoord0;
+VARYING vec4 vary_texcoord1;
+
+void calcAtmospherics(vec3 inPositionEye);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
+
+vec4 texgen_object(vec4  vpos, vec4 tc, mat4 mat, vec4 tp0, vec4 tp1)
+{
+	vec4 tcoord;
+	
+	tcoord.x = dot(vpos, tp0);
+	tcoord.y = dot(vpos, tp1);
+	tcoord.z = tc.z;
+	tcoord.w = tc.w;
+	
+	tcoord = mat * tcoord; 
+	
+	return tcoord; 
+}
+
+void main()
+{
+	//transform vertex
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+	vec4 pos = modelview_matrix * vec4(position.xyz, 1.0);
+	vec3 norm = normalize(normal_matrix * normal);
+
+	calcAtmospherics(pos.xyz);
+
+	vec4 color = calcLighting(pos.xyz, norm, vec4(1.0));
+
+	vertex_color.rgb = color.rgb;
+
+	// Transform and pass tex coords
+ 	vary_texcoord0.xy = texgen_object(vec4(position.xyz, 1.0), vec4(texcoord0,0,1), texture_matrix0, object_plane_s, object_plane_t).xy;
+	
+	vec4 t = vec4(texcoord1,0,1);
+	
+	vary_texcoord0.zw = t.xy;
+	vary_texcoord1.xy = t.xy-vec2(2.0, 0.0);
+	vary_texcoord1.zw = t.xy-vec2(1.0, 0.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
index 0d8dab0a4191bd347c4ffb559118a2f578330373..8c8bd6d0d5cbd506b10dcfb7aad8851002de69cb 100644
--- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
@@ -1,5 +1,5 @@
 /**
- * @file underWaterF.glsl
+ * @file class1\environment\underWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -47,7 +47,6 @@ uniform float kd;
 uniform vec4 waterPlane;
 uniform vec3 eyeVec;
 uniform vec4 waterFogColor;
-uniform float waterFogDensity;
 uniform float waterFogKS;
 uniform vec2 screenRes;
 
@@ -56,41 +55,7 @@ VARYING vec4 refCoord;
 VARYING vec4 littleWave;
 VARYING vec4 view;
 
-vec4 applyWaterFog(vec4 color, vec3 viewVec)
-{
-	//normalize view vector
-	vec3 view = normalize(viewVec);
-	float es = -view.z;
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	//get object depth
-	float depth = length(viewVec);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	//return vec4(1.0, 0.0, 1.0, 1.0);
-	return color * D + kc * L;
-	//depth /= 10.0;
-	//return vec4(depth,depth,depth,0.0);
-}
+vec4 applyWaterFogView(vec3 pos, vec4 color);
 
 void main() 
 {
@@ -108,5 +73,5 @@ void main()
 		
 	vec4 fb = texture2D(screenTex, distort);
 	
-	frag_color = applyWaterFog(fb,view.xyz);
+	frag_color = applyWaterFogView(view.xyz, fb);
 }
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index 79bffab745cb2e17869a0bcf1cbec60d5704da7d..d37099712354ccb98865ac4b14bf28d7e9fe410a 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -32,7 +32,9 @@ out vec4 frag_color;
 vec3 scaleSoftClip(vec3 inColor);
 vec3 atmosTransport(vec3 inColor);
 
-uniform sampler2D bumpMap;   
+uniform sampler2D bumpMap;
+uniform sampler2D bumpMap2;
+uniform float     blend_factor;
 uniform sampler2D screenTex;
 uniform sampler2D refTex;
 
@@ -55,6 +57,13 @@ VARYING vec4 refCoord;
 VARYING vec4 littleWave;
 VARYING vec4 view;
 
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+    vec3 n = mix(bump1, bump2, blend_factor);
+    return n;
+}
+
+
 void main() 
 {
 	vec4 color;
@@ -65,9 +74,21 @@ void main()
 	vec3 viewVec = normalize(view.xyz);
 	
 	//get wave normals
-	vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
-	vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
-	vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+    vec2 bigwave = vec2(refCoord.w, view.w);
+    vec3 wave1_a = texture2D(bumpMap, bigwave      ).xyz*2.0-1.0;
+    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+    vec3 wave1_b = texture2D(bumpMap2, bigwave      ).xyz*2.0-1.0;
+    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+
 	//get base fresnel components	
 	
 	vec3 df = vec3(
@@ -136,6 +157,12 @@ void main()
 	color.rgb = atmosTransport(color.rgb);
 	color.rgb = scaleSoftClip(color.rgb);
 	color.a = spec * sunAngle2;
-
+	
 	frag_color = color;
+
+#if defined(WATER_EDGE)
+    gl_FragDepth = 0.9999847f;
+#endif
+	
 }
+
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index 4bdfce9260c77145dcb244b561d87ce1a4230ea7..df640cba05ee24acd0288a1f6ae569f83f7c5545 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -1,5 +1,5 @@
 /**
- * @file waterFogF.glsl
+ * @file class1\environment\waterFogF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -25,7 +25,6 @@
  
 
 
-uniform vec4 lightnorm;
 uniform vec4 waterPlane;
 uniform vec4 waterFogColor;
 uniform float waterFogDensity;
@@ -33,42 +32,48 @@ uniform float waterFogKS;
 
 vec3 getPositionEye();
 
-vec4 applyWaterFog(vec4 color)
+vec4 applyWaterFogView(vec3 pos, vec4 color)
 {
-	//normalize view vector
-	vec3 view = normalize(getPositionEye());
-	float es = -(dot(view, waterPlane.xyz));
+    vec3 view = normalize(pos);
+    //normalize view vector
+    float es = -(dot(view, waterPlane.xyz));
+
+    //find intersection point with water plane and eye vector
+    
+    //get eye depth
+    float e0 = max(-waterPlane.w, 0.0);
+    
+    vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
+    
+    //get object depth
+    float depth = length(pos - int_v);
+        
+    //get "thickness" of water
+    float l = max(depth, 0.1);
+
+    float kd = waterFogDensity;
+    float ks = waterFogKS;
+    vec4 kc = waterFogColor;
+    
+    float F = 0.98;
+    
+    float t1 = -kd * pow(F, ks * e0);
+    float t2 = kd + ks * es;
+    float t3 = pow(F, t2*l) - 1.0;
+    
+    float L = min(t1/t2*t3, 1.0);
+    
+    float D = pow(0.98, l*kd);
+    
+    color.rgb = color.rgb * D + kc.rgb * L;
+    color.a = kc.a + color.a;
 
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(getPositionEye() - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
+    return color;
+}
 
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
+vec4 applyWaterFog(vec4 color)
+{
+    //normalize view vector
+    return applyWaterFogView(getPositionEye(), color);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index 352cea7aaabcee7dc2e79aeaae496d99ba53fcf1..cc41e3f740df6d9076d8de788ad30c8240b6acd9 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file waterV.glsl
+ * @file class1\environment\waterV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -31,8 +31,8 @@ ATTRIBUTE vec3 position;
 
 void calcAtmospherics(vec3 inPositionEye);
 
-uniform vec2 d1;
-uniform vec2 d2;
+uniform vec2 waveDir1;
+uniform vec2 waveDir2;
 uniform float time;
 uniform vec3 eyeVec;
 uniform float waterHeight;
@@ -86,10 +86,10 @@ void main()
 	
 	
 	//pass wave parameters to pixel shader
-	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + d1 * time * 0.055;
+	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + waveDir1 * time * 0.055;
 	//get two normal map (detail map) texture coordinates
-	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + d2 * time * 0.13;
-	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
+	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + waveDir2 * time * 0.13;
+	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + waveDir1 * time * 0.1;
 	view.w = bigWave.y;
 	refCoord.w = bigWave.x;
 	
diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl
index a96d04cc39d194f063e78af0fa79bdce330aefcf..f6b31a59560e06d87628032676a05c0cfd157a12 100644
--- a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl
@@ -38,7 +38,9 @@ VARYING vec2 vary_texcoord0;
 
 void main() 
 {
-	vec4 color = vertex_color*texture2D(diffuseMap, vary_texcoord0.xy);
-	color.a *= custom_alpha;
+	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
+    color.rgb = pow(color.rgb, vec3(0.45));
+    color.rgb *= vertex_color.rgb;
+	color.a *= max(custom_alpha, vertex_color.a);
 	frag_color = color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
index 5c088b3a3c43571a71a94da8cc4226be74e5cba2..b5bbbb5c738df8a34770473f70b9844db1d4eb67 100644
--- a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl
@@ -25,14 +25,14 @@
 
 #extension GL_ARB_texture_rectangle : enable
 
+/*[EXTRA_CODE_HERE]*/
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
 #define frag_color gl_FragColor
 #endif
 
-/*[EXTRA_CODE_HERE]*/
-
 uniform sampler2D glowMap;
 uniform sampler2DRect screenMap;
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
index cad5b9ff043b63d417eb5870a2f1fab88782d9f3..f665394b46b06c199e34a8793db3657b3367252c 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightAlphaMaskF.glsl
+ * @file class1\lighting\lightAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
index 89181828536bb6dd06eb76a5022abaf53d73f95d..b768d609f476b5a6061e1041deb6f95e49533045 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightAlphaMaskNonIndexedF.glsl
+ * @file class1\lighting\lightAlphaMaskNonIndexedF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
index d6ebfcb82575825214fe6227ef9b48550ca05f84..9fd189358be03342fdfad33ee34ea5825e36b595 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightF.glsl
+ * @file class1\lighting\lightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
index 5740987ab1cdbfcfe95abab93b53e90e4687c6fc..46390e4a0e4976446b1a3432a4155acc9d8e0425 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightAlphaMaskF.glsl
+ * @file class1\lighting\lightFullbrightAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index c8771a3f1eac8e728eb1a4df67de179d1ee889fd..b967709c57ce41e65aa0f3473fdded811619adca 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightF.glsl
+ * @file class1\lighting\lightFullbrightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl
index f72f20b03d754dc13c4fff8447e50df1910f333c..e8e71beb443724f1b801d8a0b2d7e830df9a1c72 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightNonIndexedAlphaMaskF.glsl
+ * @file class1\lighting\lightFullbrightNonIndexedAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl
index 2738ff89477dd03137952fc2da033fc5920c1e4a..11a091908650fda348f0c9d78b7a289a8262d9b0 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightF.glsl
+ * @file class1\lighting\lightFullbrightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index c8282e9a51eafe3a7859e798ccdca204be3208c7..567811cd75afec893025e9a282017bcdbd2aa4ad 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightShinyF.glsl
+ * @file class1\lighting\lightFullbrightShinyF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -44,7 +44,7 @@ void fullbright_shiny_lighting()
 	color.rgb *= vertex_color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
-	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a);
+	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);
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl
index e7dbd4bbd2d3954c0b5cfd90659cd79b8c4bcb68..311845334290d6b1ee7d8585c03a81d7e9afe056 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightShinyF.glsl
+ * @file class1\lighting\lightFullbrightShinyF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
index 5886fc65bea8ec8adc90857756419a1906893dab..f78e5e0e8ae7dd89109c161bee3181a75cc507d1 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightShinyWaterF.glsl
+ * @file class1\lighting\lightFullbrightShinyWaterF.glsl
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
index cddc7d8df80f05e0b4fe2c507b49f4bcbf3e0331..90668bd2b6bb6d16c62043dca7dce5246e96bee2 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightShinyWaterF.glsl
+ * @file class1\lighting\lightFullbrightShinyWaterF.glsl
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
index 6dd3bb937f175f72748fbe8848881a44e78649cf..d04cd79f4b9406032c6370b64cc89b8c760a5602 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightWaterAlphaMaskF.glsl
+ * @file class1\lighting\lightFullbrightWaterAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
index d3dacf9bc4d81e65f7cd91eda199da74440a4d66..27880b720cc485d6856c191b6c2c638bf3181bd8 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightWaterF.glsl
+ * @file class1\lighting\lightFullbrightWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
index 63f92a88440771fc3fe29025750e3d6d7f86b429..3b9c04b22b9938bbc031fa82b4f405010f59d2df 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightWaterNonIndexedAlphaMaskF.glsl
+ * @file class1\lighting\lightFullbrightWaterNonIndexedAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl
index 0e68091e7cbc76f270e8fd02941f9aafcdfabe38..e9fd8ac820ba0a17f8f6e076fb536a86112bd875 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFullbrightWaterF.glsl
+ * @file class1\lighting\lightFullbrightWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
index 85cddc647d269d69d828c6da4eb63b0e2a26fd67..13a6dde4aadd2ed6ed718b5bc746fbfe3dfdb973 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFuncSpecularV.glsl
+ * @file class1/lighting\lightFuncSpecularV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,14 +23,6 @@
  * $/LicenseInfo$
  */
  
-
-
-float calcDirectionalLight(vec3 n, vec3 l)
-{
-	float a = max(dot(n,l),0.0);
-	return a;
-}
-
 float calcDirectionalSpecular(vec3 view, vec3 n, vec3 l)
 {
 	return pow(max(dot(reflect(view, n),l), 0.0),8.0);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
index a9288b3df68dd9d5480ec67bef28166be8a75c5b..45701002b87ff65158e2a3e2dbaf4ca016aa11a9 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightFuncV.glsl
+ * @file class1\lighting\lightFuncV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -32,8 +32,7 @@ float calcDirectionalLight(vec3 n, vec3 l)
 	return a;
 }
 
-
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight)
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
 {
 	//get light vector
 	vec3 lv = lp.xyz-v;
@@ -54,6 +53,6 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa
 	//angular attenuation
 	da *= calcDirectionalLight(n, lv);
 
-	return da;	
+	return da;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl
index 0aca768021bf6fbb8a7818b6e92bcb5ac51dfcbd..f9c7ad2ab37a345866e26ea2800ff2853408ca2d 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightF.glsl
+ * @file class1\lighting\lightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
index 9208c148efa48a76d34ea5781b30917e33a7a4ef..f621a0078502f0c0bfed2498e2b038608493477a 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightShinyF.glsl
+ * @file class1\lighting\lightShinyF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -45,7 +45,7 @@ void shiny_lighting()
 	color.rgb *= vertex_color.rgb;
 	
 	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
-	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a);
+	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
 
 	color.rgb = atmosLighting(color.rgb);
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl
index 92628faa68a64b8da9b6fed87fafeb109039964c..2b6f41400535dd12e7956dd2325ba134fd7944af 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightShinyF.glsl
+ * @file class1\lighting\lightShinyF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
index 61841674e211ad2718a3f7bd83e894d877838337..0f3371eba97e01b70e184663bd21be76b4cb6e8b 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightShinyWaterF.glsl
+ * @file class1\lighting\lightShinyWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl
index 0b6e835fd06659e66fd35b529e244dda2bb2d6c4..c607fa64cb78b6ccb9e354446576ff30a9ea7027 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightShinyWaterF.glsl
+ * @file class1\lighting\lightShinyWaterNonIndexedF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
index 24bf9b3cee5168a8cfc7928b545eddc39e8a9736..06aed40e26aec68c622feba5256bd94a6c1229f0 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightSpecularV.glsl
+ * @file class1\lighting\lightSpecularV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -27,10 +27,10 @@
 
 // All lights, no specular highlights
 
-vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
+vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor);
 
-vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
+vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor)
 {
-	return sumLightsSpecular(pos, norm, color, specularColor, baseCol);
+	return sumLightsSpecular(pos, norm, color, specularColor);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
index 8045809b82c6cc6e18b4fdfeefa9ec26ed35c706..5e39d1629d20355eee7c3b0d80ee4f89c89df692 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightV.glsl
+ * @file class1\lighting\lightV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -26,11 +26,18 @@
 
 
 // All lights, no specular highlights
+vec3 atmosAmbient();
+vec4 sumLights(vec3 pos, vec3 norm, vec4 color);
+float getAmbientClamp();
 
-vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight);
-
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color)
 {
-	return sumLights(pos, norm, color, baseLight);
+	vec4 c = sumLights(pos, norm, color);
+
+#if !defined(AMBIENT_KILL)
+    c.rgb += atmosAmbient() * color.rgb * 0.5 * getAmbientClamp();
+#endif
+
+    return c;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
index 3426fea52fa2e2023f8465539541c4a29e27730b..09167972595d10c37502aa581fe149a4a7e3d372 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightWaterAlphaMaskF.glsl
+ * @file class1\lighting\lightWaterAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
index d9faa9b314273dbda5c177279df800dbc55a5ded..f2a84f1d42f66e14021be957f67c39dbae148d20 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightWaterAlphaMaskNonIndexedF.glsl
+ * @file class1\lighting\lightWaterAlphaMaskNonIndexedF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
index 00609e93cd3a9185a261071fd29214caed5d2b51..57ed993a6642442572e0e01549cd707227fe2c4c 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightWaterF.glsl
+ * @file class1\lighting\lightWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl
index 13ecb7a6368fa0016e6386c895014cd14deb4d65..af5da1411ba08f7cb920caf036609d6111b29c3d 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterNonIndexedF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file lightWaterF.glsl
+ * @file class1\lighting\lightWaterNonIndexedF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
index 7059ff31aed4b7fa8ffb0661c2e6fc98ad939f46..7c3697c33344c40c79d6b6aaeb521465971d8645 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsSpecularV.glsl
+ * @file class1\lighting\sumLightsSpecularV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -26,7 +26,7 @@
 
 
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 atmosGetDiffuseSunlightColor();
 vec3 scaleDownLight(vec3 light);
@@ -34,7 +34,7 @@ vec3 scaleDownLight(vec3 light);
 uniform vec4 light_position[8];
 uniform vec3 light_diffuse[8];
 
-vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
+vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor)
 {
 	vec4 col = vec4(0,0,0, color.a);
 		
@@ -45,8 +45,8 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor
 
 	col.rgb += light_diffuse[1].rgb * calcDirectionalLightSpecular(specularColor, view, norm, light_position[1].xyz,light_diffuse[1].rgb, 1.0);
 	col.rgb = scaleDownLight(col.rgb);
-	col.rgb += atmosAmbient(baseCol.rgb);
-	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz,atmosGetDiffuseSunlightColor()*baseCol.a, 1.0));
+	col.rgb += atmosAmbient();
+	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz, atmosGetDiffuseSunlightColor(), 1.0));
 
 	col.rgb = min(col.rgb * color.rgb, 1.0);
 	specularColor.rgb = min(specularColor.rgb * specularSum.rgb, 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
index 41288c21c19c4be8a7ecc5052b108bb74fd690d3..0c3ea4231e97b820ae0232f522fef6960fcd2cb3 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsV.glsl
+ * @file class1\lighting\sumLightsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -28,22 +28,27 @@ uniform vec3 light_diffuse[8];
 
 float calcDirectionalLight(vec3 n, vec3 l);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
 
-vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
+vec4 sumLights(vec3 pos, vec3 norm, vec4 color)
 {
-	vec4 col;
+	vec4 col = vec4(0);
 	col.a = color.a;
 	
 	col.rgb = light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz);
 	col.rgb = scaleDownLight(col.rgb);
-	col.rgb += atmosAmbient(baseLight.rgb);
+
+#if defined(LOCAL_LIGHT_KILL)
+    col.rgb = vec3(0);
+#endif
+
+#if !defined(SUNLIGHT_KILL)
 	col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz));
-	
+#endif
+
 	col.rgb = min(col.rgb*color.rgb, 1.0);
-	
 	return col;	
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
index a54c0caf81079e22e56e76a98257b1ea99a231bc..31a262f1db1e337aedd90f09795257d247f92649 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file fullbrightF.glsl
+ * @file objects/fullbrightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
index 79b552ee1a9656fcb18a5e93d406ab30cd8d2b6c..1e244d9dfdae3d0e1ef7920ba3ff2b58c0e75431 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
@@ -35,6 +35,7 @@ ATTRIBUTE vec2 texcoord0;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_texcoord1;
+VARYING vec4 vary_position;
 
 
 void calcAtmospherics(vec3 inPositionEye);
@@ -46,6 +47,9 @@ void main()
 	
 	mat = modelview_matrix * mat;
 	vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+
+    mat4 mvp = modelview_matrix * projection_matrix;
+    vary_position = mvp * vec4(position, 1.0);
 	
 	vec4 norm = vec4(position.xyz, 1.0);
 	norm.xyz += normal.xyz;
diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
index 7f3f84398b102ab07dd68c2106a67fc2a9509408..88959266c8ad04edc1b147c1b51af3cda8385db4 100644
--- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl
@@ -52,7 +52,7 @@ float calcDirectionalLight(vec3 n, vec3 l)
 }
 
 
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight)
+float calcLocalLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight)
 {
 	//get light vector
 	vec3 lv = lp.xyz-v;
@@ -91,8 +91,8 @@ void main()
 
 	// Collect normal lights (need to be divided by two, as we later multiply by 2)
 	col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz);
-	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
-	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
+	col.rgb += light_diffuse[2].rgb*calcLocalLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
+	col.rgb += light_diffuse[3].rgb*calcLocalLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
 		
 	vertex_color = col*color;
 }
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
index 591d6fc5c94853c3e4d833085a1e9209139b9ec9..727bae19c06f70d3050afce866eb15cc6b0718f4 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
@@ -36,7 +36,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_texcoord1;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 mat4 getObjectSkinnedTransform();
 
@@ -59,7 +59,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color, vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color);
 	vertex_color = color;
 	
 	gl_Position = projection_matrix*vec4(pos, 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
index fdb3453cc581dafaee3aaa16dfc32ef01da119a9..4ba8194d0384571a09e3597b137994f205149592 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
@@ -39,7 +39,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 VARYING vec3 vary_texcoord1;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -61,5 +61,5 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vertex_color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.0));	
+	vertex_color = calcLighting(pos.xyz, norm, diffuse_color);	
 }
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleNoColorV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleNoColorV.glsl
index 0be52a52af3a91ff13a030c3ee13488476f86e62..22821a2f76c45fb7ee837a4e5badfdab31f7f7eb 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleNoColorV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleNoColorV.glsl
@@ -38,7 +38,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 
 void main()
@@ -52,7 +52,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 col = calcLighting(pos.xyz, norm, color, vec4(0.));
+	vec4 col = calcLighting(pos.xyz, norm, color);
 	vertex_color = col;
 
 	
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleNonIndexedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleNonIndexedV.glsl
index cb80697d154a7dcb3c8eeef3c51f895e71651a9f..e605676819a4e3cbf9fefd7a6ecc28ed2fd7cdac 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleNonIndexedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleNonIndexedV.glsl
@@ -37,7 +37,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 
 void main()
@@ -54,7 +54,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm, diffuse_color);
 	vertex_color = color;
 
 	
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
index 1c6e53b1879c1a84e6a8b0bf9e12b4476530ed55..df31b5a79f149f344d3cd4ef80bcc540576fd57f 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
@@ -35,7 +35,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 mat4 getObjectSkinnedTransform();
 
@@ -56,7 +56,7 @@ void main()
 		
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color, vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color);
 	vertex_color = color;
 	
 	gl_Position = projection_matrix*vec4(pos, 1.0);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleTexGenV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleTexGenV.glsl
index d4dee78793eeebd502a4775969d41373f5d1f74e..945f80f31ecff47e492e1a15c75bc455c5e7b649 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleTexGenV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleTexGenV.glsl
@@ -37,7 +37,7 @@ uniform vec4 color;
 uniform vec4 object_plane_t;
 uniform vec4 object_plane_s;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 
 VARYING vec4 vertex_color;
@@ -70,7 +70,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm, color, vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm, color);
 	vertex_color = color;
 
 	
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index 37a20383e2c8499eaba3d370b63f7edab9958de9..a59bd9c0a684e7e7cd9c757838ac850d37deb975 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -34,7 +34,7 @@ ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec3 normal;
 ATTRIBUTE vec4 diffuse_color;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 
 
@@ -57,7 +57,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm, diffuse_color, vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm, diffuse_color);
 	vertex_color = color;
 
 	
diff --git a/indra/newview/app_settings/shaders/class1/objects/treeV.glsl b/indra/newview/app_settings/shaders/class1/objects/treeV.glsl
index fa01a27ec0aea2fdc9acfb17536a72617661057e..0227e6e3b840395c86c27f4c1d071a8f40929a1a 100644
--- a/indra/newview/app_settings/shaders/class1/objects/treeV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/treeV.glsl
@@ -31,8 +31,9 @@ uniform mat4 modelview_projection_matrix;
 ATTRIBUTE vec3 position;
 ATTRIBUTE vec2 texcoord0;
 ATTRIBUTE vec3 normal;
+ATTRIBUTE vec4 diffuse_color;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 void calcAtmospherics(vec3 inPositionEye);
 
 VARYING vec4 vertex_color;
@@ -53,8 +54,6 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 
-	vec4 color = calcLighting(pos.xyz, norm, vec4(1,1,1,1), vec4(0.));
+	vec4 color = calcLighting(pos.xyz, norm, diffuse_color);
 	vertex_color = color;
-
-	
 }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
index aacc503e1337e5109060f31880277d1cb484d496..4e0618e27614897c3135b961adff1a4c5443094d 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericsF.glsl
+ * @file class1\windlight\atmosphericsF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,11 +23,26 @@
  * $/LicenseInfo$
  */
  
+vec3 atmosFragAmbient(vec3 light, vec3 sunlit)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
+}
 
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
+}
+
+vec3 atmosFragAffectDirectionalLight(float light, vec3 sunlit)
+{
+   return light * sunlit;
+}
 
 vec3 atmosLighting(vec3 light)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-	return light;
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..dcb02bd1c17c6b5d7951dacd99e84e8058d0eadf
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsFuncs.glsl
@@ -0,0 +1,154 @@
+/** 
+ * @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 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 float scene_light_strength;
+uniform mat3 ssao_effect_mat;
+uniform int no_atmo;
+uniform float sun_moon_glow_factor;
+
+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) {
+
+    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); 
+
+    vec3 tmpLightnorm = lightnorm.xyz;
+
+    vec3 Pn = normalize(P);
+    float Plen = length(P);
+
+    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;
+
+    float dens_mul = density_multiplier;
+    float dist_mul = distance_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);
+        //I had thought blue_density and haze_density should have equal weighting,
+        //but attenuation due to haze_density tends to seem too strong
+
+    temp1 = blue_density + vec4(haze_density);
+    blue_weight = blue_density / temp1;
+    haze_weight = vec4(haze_density) / temp1;
+
+    //(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);
+
+    // main atmospheric scattering line integral
+    temp2.z = Plen * dens_mul;
+
+    // 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);
+
+    //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);
+
+    // 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
+    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);
+     */
+    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));
+
+    //brightness of surface both sunlight and ambient
+    sunlit = sunlight.rgb * 0.5;
+    amblit = tmpAmbient.rgb * .25;
+    additive *= vec3(1.0 - temp1);
+}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..206a51db27c2d61cee4b74e431a53cd6f93c2065
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersF.glsl
@@ -0,0 +1,51 @@
+/** 
+ * @file class1\windlight\atmosphericsHelpersF.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 vec4 sunlight_color;
+uniform vec4 light_ambient;
+uniform int no_atmo;
+
+vec3 atmosAmbient()
+{
+    if (no_atmo == 1) return vec3(0.16);
+    return light_ambient.rgb;
+}
+
+vec3 atmosAffectDirectionalLight(float lightIntensity)
+{
+    return sunlight_color.rgb * lightIntensity;
+}
+
+vec3 atmosGetDiffuseSunlightColor()
+{
+    return sunlight_color.rgb;
+}
+
+vec3 scaleDownLight(vec3 light)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
index 6ff860362c28285ccd8a838160a102227374a26a..c266f9732fa6dcacb25b64fa223675b7f46d4630 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericsHelpersV.glsl 
+ * @file class1\windlight\atmosphericsHelpersV.glsl 
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,33 +23,35 @@
  * $/LicenseInfo$
  */
  
-uniform vec4 sunlight_color_copy;
+uniform vec4 sunlight_color;
 uniform vec4 light_ambient;
+uniform int no_atmo;
 
-vec3 atmosAmbient(vec3 light)
+vec3 atmosAmbient()
 {
-	return light + light_ambient.rgb;
+    if (no_atmo == 1) return vec3(0.66);
+    return light_ambient.rgb;
 }
 
 vec3 atmosAffectDirectionalLight(float lightIntensity)
 {
-	return sunlight_color_copy.rgb * lightIntensity;
+    return sunlight_color.rgb * lightIntensity;
 }
 
 vec3 atmosGetDiffuseSunlightColor()
 {
-	return sunlight_color_copy.rgb;
+    return sunlight_color.rgb;
 }
 
 vec3 scaleDownLight(vec3 light)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-	return light;
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
 }
 
 vec3 scaleUpLight(vec3 light)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-	return light;
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
index 76d7d5059d0425ce644a8e6beae67fa6a431deb2..20457ad125377895c267d7bfbca87110a782755e 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericsV.glsl 
+ * @file class1\windlight\atmosphericsV.glsl 
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -29,7 +29,7 @@ void setPositionEye(vec3 v);
 
 void calcAtmospherics(vec3 inPositionEye)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-	setPositionEye(inPositionEye);
+    /* stub function for fallback compatibility on class1 hardware */
+    setPositionEye(inPositionEye);
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
index 8bdae328bde8a0c6b79abf657384757a5e9ed0dd..a0699affbf078c73ad0d3c7b26817cc9b379bddf 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsF.glsl
+ * @file class1\windlight\atmosphericVarsF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
index 8ec9ae617caf4d97face8cd387d178424575d288..bd1d150fc81956fdcb110ede0ccafa552be0f8e9 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsV.glsl
+ * @file class1\windlight\atmosphericVarsV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
index 636d4af006f164fba5d97f7471ef97c9394e4843..5dc086ab1e05d38241db5d7bebe8711a603e05cb 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsWaterF.glsl
+ * @file class1\windlight\atmosphericVarsWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
index 8afcc20f6d190f903a0e95863eda7d62f53c2cdd..e59eca265a80d85810e27f2c4e5e6475e77d1607 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsWaterV.glsl
+ * @file class1\windlight\atmosphericVarsWaterV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..82fad4db5a6c536df68cb963e4f4413985518622
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowF.glsl
@@ -0,0 +1,127 @@
+/** 
+ * @file class1/windlight/cloudShadowF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING float vary_CloudDensity;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+
+uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 sunlight_color;
+uniform vec4 cloud_color;
+uniform float cloud_shadow;
+uniform float cloud_scale;
+uniform float cloud_variance;
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+
+#if !defined(DEPTH_CLAMP)
+VARYING vec4 post_pos;
+#endif
+
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return normalize(cloud_noise_sample);
+}
+
+void main()
+{
+    if (cloud_scale >= 0.0001)
+    {
+        // Set variables
+        vec2 uv1 = vary_texcoord0.xy;
+        vec2 uv2 = vary_texcoord1.xy;
+        vec2 uv3 = vary_texcoord2.xy;
+        float cloudDensity = 2.0 * (cloud_shadow - 0.25);
+    
+        vec2 uv4 = vary_texcoord3.xy;
+    
+        vec2 disturbance  = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+        vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+    
+        // Offset texture coords
+        uv1 += cloud_pos_density1.xy + (disturbance * 0.2);    //large texture, visible density
+        uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+        uv3 += cloud_pos_density2.xy;   //small texture, visible density
+        uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+    
+        float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
+    
+        cloudDensity *= 1.0 - (density_variance * density_variance);
+    
+        // Compute alpha1, the main cloud opacity
+        float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+        alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha1 = 1. - alpha1 * alpha1;
+        alpha1 = 1. - alpha1 * alpha1;  
+    
+        if (alpha1 < 0.001f)
+        {
+            discard;
+        }
+    
+        // Compute alpha2, for self shadowing effect
+        // (1 - alpha2) will later be used as percentage of incoming sunlight
+        float alpha2 = (cloudNoise(uv2).x - 0.5);
+        alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha2 = 1. - alpha2;
+        alpha2 = 1. - alpha2 * alpha2;  
+    
+        frag_color = vec4(alpha1, alpha1, alpha1, 1);
+    }
+    else
+    {
+        frag_color = vec4(1);
+    }
+
+#if !defined(DEPTH_CLAMP)
+    gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..09b6004481b2965a74fdd638618a8cd67933cdba
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/cloudShadowV.glsl
@@ -0,0 +1,61 @@
+/** 
+ * @file class1\windlight\cloudShadowV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+	pos = modelview_projection_matrix * pre_pos;
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
index 62f4e514494fd6492ba3d7e6ce10280b39279b55..fc51e811773c6ffe0a86927d1dee06b840c5591d 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file gammaF.glsl
+ * @file class1\windlight\gammaF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,17 +23,30 @@
  * $/LicenseInfo$
  */
  
+uniform int no_atmo;
 
-
-uniform vec4 gamma;
+vec3 scaleSoftClipFrag(vec3 light)
+{
+	// For compatibility with lower cards. Do nothing.
+	return light;
+}
 
 /// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	// For compatibility with lower cards. Do nothing.
+vec3 scaleSoftClip(vec3 light)
+{
+	// For compatibility with lower cards. Do nothing
+	return light;
+}
+
+vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 additive, vec3 atten)
+{
+	// For compatibility with lower cards. Do nothing
 	return light;
 }
 
-vec3 fullbrightScaleSoftClip(vec3 light) {
-	return scaleSoftClip(light);
+vec3 fullbrightScaleSoftClip(vec3 light)
+{
+	// For compatibility with lower cards. Do nothing
+    return light;
 }
 
diff --git a/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..24f3992e32fa6fbbdb3c419816f5b134af9598a1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonF.glsl
@@ -0,0 +1,64 @@
+/** 
+ * @file class1\wl\moonF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform vec4 color;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform vec3 lumWeights;
+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;
+
+void main() 
+{
+    vec4 moonA = texture2D(diffuseMap, vary_texcoord0.xy);
+    vec4 moonB = texture2D(altDiffuseMap, vary_texcoord0.xy);
+    vec4 c     = mix(moonA, moonB, blend_factor);
+
+    // 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);
+
+    vec3 exp = vec3(1.0 - mix * moon_brightness) * 2.0 - 1.0;
+    c.rgb = pow(c.rgb, exp);
+    //c.rgb *= moonlight_color.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
new file mode 100644
index 0000000000000000000000000000000000000000..8cd4b2ef4794611625a16d606cc5c27d8b629d4a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/moonV.glsl
@@ -0,0 +1,49 @@
+/** 
+ * @file class1\wl\moonV.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$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+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 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/class1/windlight/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b9ae7a02262b01cc62aa485f142168418cc10aa9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl
@@ -0,0 +1,59 @@
+/** 
+ * @file class1\wl\sunDiscF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+vec3 fullbrightAtmosTransport(vec3 light);
+vec3 fullbrightScaleSoftClip(vec3 light);
+
+uniform sampler2D diffuseMap;
+uniform sampler2D altDiffuseMap;
+uniform float blend_factor; // interp factor between sun A/B
+VARYING vec2 vary_texcoord0;
+VARYING float sun_fade;
+
+void main() 
+{
+    vec4 sunA = texture2D(diffuseMap, vary_texcoord0.xy);
+    vec4 sunB = texture2D(altDiffuseMap, vary_texcoord0.xy);
+    vec4 c     = mix(sunA, sunB, blend_factor);
+
+// SL-9806 stars poke through
+//    c.a *= sun_fade;
+
+    c.rgb = pow(c.rgb, vec3(0.7f));
+    c.rgb = fullbrightAtmosTransport(c.rgb);
+    c.rgb = fullbrightScaleSoftClip(c.rgb);
+    frag_color = c;
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/windlight/sunDiscV.glsl b/indra/newview/app_settings/shaders/class1/windlight/sunDiscV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6c0e795f6b34cde7b047db75e520eb95a9084b7a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/windlight/sunDiscV.glsl
@@ -0,0 +1,51 @@
+/** 
+ * @file class1\wl\sunDiscV.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$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_texcoord0;
+VARYING float sun_fade;
+
+void calcAtmospherics(vec3 eye_pos);
+
+void main()
+{
+    //transform vertex
+    vec3 offset = vec3(0, 0, 50);
+    vec4 vert = vec4(position.xyz - offset, 1.0);
+    vec4 pos = modelview_projection_matrix*vert;
+
+    sun_fade = smoothstep(0.3, 1.0, (position.z + 50) / 512.0f);
+    gl_Position = pos;
+    
+    calcAtmospherics(pos.xyz);
+
+    vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
index 7c95ecdb140f2204f3571def0ea6b0ed76a05454..a937d9fa99ec959372dc5e8d260a7c49093c7393 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file transportF.glsl
+ * @file class1/windlight/transportF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,25 +22,35 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
 
+uniform int no_atmo;
 
-vec3 atmosTransport(vec3 light)
+vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
 {
-	/* stub function for fallback compatibility on class1 hardware */
+    /* stub function for fallback compatibility on class1 hardware */
 	return light;
 }
 
-vec3 fullbrightAtmosTransport(vec3 light)
+vec3 atmosTransport(vec3 light)
 {
 	/* stub function for fallback compatibility on class1 hardware */
-	return light;
+    return light;
+}
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
 }
 
+vec3 fullbrightAtmosTransport(vec3 light)
+{
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
+}
 
 vec3 fullbrightShinyAtmosTransport(vec3 light)
 {
-	/* stub function for fallback compatibility on class1 hardware */
-	return light;
+    /* stub function for fallback compatibility on class1 hardware */
+    return light;
 }
-
diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
index 5af9f5c902b3ee23e27cf7c1ad63808644fdbfa2..563c5f562b954b3806848da741a1e41aa0f3991e 100644
--- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
+++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl
@@ -37,7 +37,7 @@ VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
 
-vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol);
+vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor);
 void calcAtmospherics(vec3 inPositionEye);
 
 void main()
@@ -53,7 +53,7 @@ void main()
 	
 	// vec4 specular = specularColor;
 	vec4 specular = vec4(1.0);
-	vec4 color = calcLightingSpecular(pos, norm, diffuse_color, specular, vec4(0.0));
+	vec4 color = calcLightingSpecular(pos, norm, diffuse_color, specular);
 			
 	vertex_color = color;
 	
diff --git a/indra/newview/app_settings/shaders/class2/deferred/indirect.glsl b/indra/newview/app_settings/shaders/class2/deferred/indirect.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..67b98e0fb13700ae642dd42cd5daef0081f8e10f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/indirect.glsl
@@ -0,0 +1,32 @@
+/** 
+ * @file class2/deferred/indirect.glsl
+ *
+ * $LicenseInfo:firstyear=2018&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$
+ */
+
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
+
+vec3 getIndirect(vec3 ambient, vec3 norm, vec4 pos, vec2 pos_screen)
+{
+    return ambient * calcAmbientOcclusion(pos, norm, pos_screen);
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index b9bb522842e3bced03a5164fddc407711419f544..5d7a28c359284de7a8836e313c7c987123e85f4c 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -71,294 +71,233 @@ uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 correctWithGamma(vec4 col)
-{
-	return vec4(srgb_to_linear(col.rgb), col.a);
-}
+vec3 srgb_to_linear(vec3 cs);
+vec3 getNorm(vec2 pos_screen);
 
 vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
-	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret.rgb = srgb_to_linear(ret.rgb);
-	
-	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-	
-	float det = min(lod/(proj_lod*0.5), 1.0);
-	
-	float d = min(dist.x, dist.y);
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    ret.rgb = srgb_to_linear(ret.rgb);
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
     
     d *= min(1, d * (proj_lod - lod));
-	
-	float edge = 0.25*det;
     
-	ret *= clamp(d/edge, 0.0, 1.0);
-	
-	return ret;
+    float edge = 0.25*det;
+    
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
 }
 
 vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
-	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
-
-	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
-	
-	float det = min(lod/(proj_lod*0.5), 1.0);
-	
-	float d = min(dist.x, dist.y);
-	
-	float edge = 0.25*det;
-		
-	ret *= clamp(d/edge, 0.0, 1.0);
-	
-	return ret;
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    ret.rgb = srgb_to_linear(ret.rgb);
+
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
+    
+    float edge = 0.25*det;
+        
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
 }
 
 vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
-	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
-
-	vec2 dist = tc-vec2(0.5);
-	
-	float d = dot(dist,dist);
-		
-	ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
-	
-	return ret;
-}
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    ret.rgb = srgb_to_linear(ret.rgb);
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
+    vec2 dist = tc-vec2(0.5);
+    
+    float d = dot(dist,dist);
+        
+    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+    
+    return ret;
 }
 
+vec4 getPosition(vec2 pos_screen);
+
 void main() 
 {
-	vec4 frag = vary_fragcoord;
-	frag.xyz /= frag.w;
-	frag.xyz = frag.xyz*0.5+0.5;
-	frag.xy *= screen_res;
-	
-	vec3 pos = getPosition(frag.xy).xyz;
-	vec3 lv = center.xyz-pos.xyz;
-	float dist = length(lv);
-	dist /= size;
-	if (dist > 1.0)
-	{
-		discard;
-	}
-	
-	float shadow = 1.0;
-	
-	if (proj_shadow_idx >= 0)
-	{
-		vec4 shd = texture2DRect(lightMap, frag.xy);
-		float sh[2];
-		sh[0] = shd.b;
-		sh[1] = shd.a;
-		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
-	}
-	
-	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
-	
-	float envIntensity = norm.z;
-
-	norm = decode_normal(norm.xy);
-	
-	norm = normalize(norm);
-	float l_dist = -dot(lv, proj_n);
-	
-	vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
-	if (proj_tc.z < 0.0)
-	{
-		discard;
-	}
-	
-	proj_tc.xyz /= proj_tc.w;
-	
-	float fa = falloff+1.0;
-	float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
-	dist_atten *= dist_atten;
-	dist_atten *= 2.0;
-	if (dist_atten <= 0.0)
-	{
-		discard;
-	}
-	
-	lv = proj_origin-pos.xyz;
-	lv = normalize(lv);
-	float da = dot(norm, lv);
-
-	vec3 col = vec3(0,0,0);
-		
-	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
-	
-	vec4 spec = texture2DRect(specularRect, frag.xy);
-
-	vec3 dlit = vec3(0, 0, 0);
-
-	float noise = texture2D(noiseMap, frag.xy/128.0).b;
-	if (proj_tc.z > 0.0 &&
-		proj_tc.x < 1.0 &&
-		proj_tc.y < 1.0 &&
-		proj_tc.x > 0.0 &&
-		proj_tc.y > 0.0)
-	{
-		float amb_da = proj_ambiance;
-		float lit = 0.0;
-
-		if (da > 0.0)
-		{
-			lit = da * dist_atten * noise;
-
-			float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
-			float lod = diff * proj_lod;
-			
-			vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
-		
-			dlit = color.rgb * plcol.rgb * plcol.a;
-			
-			col = dlit*lit*diff_tex*shadow;
-			amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
-		}
-		
-		//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
-		vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
-							
-		amb_da += (da*da*0.5+0.5)*proj_ambiance;
-				
-		amb_da *= dist_atten * noise;
-			
-		amb_da = min(amb_da, 1.0-lit);
-			
-		col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
-	}
-	
-
-	if (spec.a > 0.0)
-	{
-		vec3 npos = -normalize(pos);
-		dlit *= 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 += dlit*scol*spec.rgb*shadow;
-			//col += spec.rgb;
-		}
-	}	
-	
-	
-	
-	
-
-	if (envIntensity > 0.0)
-	{
-		vec3 ref = reflect(normalize(pos), norm);
-		
-		//project from point pos in direction ref to plane proj_p, proj_n
-		vec3 pdelta = proj_p-pos;
-		float ds = dot(ref, proj_n);
-		
-		if (ds < 0.0)
-		{
-			vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
-			
-			vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
-
-			if (stc.z > 0.0)
-			{
+
+    vec3 col = vec3(0,0,0);
+
+#if defined(LOCAL_LIGHT_KILL)
+    discard;
+#else
+    vec4 frag = vary_fragcoord;
+    frag.xyz /= frag.w;
+    frag.xyz = frag.xyz*0.5+0.5;
+    frag.xy *= screen_res;
+    
+    vec3 pos = getPosition(frag.xy).xyz;
+    vec3 lv = center.xyz-pos.xyz;
+    float dist = length(lv);
+
+    if (dist >= size)
+    {
+        discard;
+    }
+    dist /= size;
+
+    float shadow = 1.0;
+    
+    if (proj_shadow_idx >= 0)
+    {
+        vec4 shd = texture2DRect(lightMap, frag.xy);
+        shadow = (proj_shadow_idx==0)?shd.b:shd.a;
+        shadow += shadow_fade;
+        shadow = clamp(shadow, 0.0, 1.0);        
+    }
+    
+    vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+    
+    float envIntensity = norm.z;
+
+    norm = getNorm(frag.xy);
+    
+    norm = normalize(norm);
+    float l_dist = -dot(lv, proj_n);
+    
+    vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+    if (proj_tc.z < 0.0)
+    {
+        discard;
+    }
+    
+    proj_tc.xyz /= proj_tc.w;
+    
+    float fa = falloff+1.0;
+    float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+    dist_atten *= dist_atten;
+    dist_atten *= 2.0;
+    if (dist_atten <= 0.0)
+    {
+        discard;
+    }
+    
+    lv = proj_origin-pos.xyz;
+    lv = normalize(lv);
+    float da = dot(norm, lv);
+        
+    vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
+    // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
+    //          We can't switch to linear here unless we do it everywhere*
+    // *gbuffer IS sRGB, convert to linear since this shader outputs linear
+    diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
+ 
+    vec4 spec = texture2DRect(specularRect, frag.xy);
+
+    vec3 dlit = vec3(0, 0, 0);
+
+    float noise = texture2D(noiseMap, frag.xy/128.0).b;
+    if (proj_tc.z > 0.0 &&
+        proj_tc.x < 1.0 &&
+        proj_tc.y < 1.0 &&
+        proj_tc.x > 0.0 &&
+        proj_tc.y > 0.0)
+    {
+        float amb_da = proj_ambiance;
+        float lit = 0.0;
+
+        if (da > 0.0)
+        {
+            lit = da * dist_atten * noise;
+
+            float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+            float lod = diff * proj_lod;
+            
+            vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+        
+            dlit = color.rgb * plcol.rgb * plcol.a;
+            
+            col = dlit*lit*diff_tex*shadow;
+
+            // unshadowed for consistency between forward and deferred?
+            amb_da += (da*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+        }
+        
+        //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+        vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+
+        // use unshadowed for consistency between forward and deferred?
+        amb_da += (da*da*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
+        amb_da *= dist_atten * noise;
+        amb_da = min(amb_da, 1.0-lit);
+
+        col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+    }
+    
+
+    if (spec.a > 0.0)
+    {
+        vec3 npos = -normalize(pos);
+        dlit *= 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);
+            vec3 speccol = dlit*scol*spec.rgb*shadow;
+            speccol = clamp(speccol, vec3(0), vec3(1));
+            col += speccol;
+        }
+    }   
+
+    if (envIntensity > 0.0)
+    {
+        vec3 ref = reflect(normalize(pos), norm);
+        
+        //project from point pos in direction ref to plane proj_p, proj_n
+        vec3 pdelta = proj_p-pos;
+        float ds = dot(ref, proj_n);
+        
+        if (ds < 0.0)
+        {
+            vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+            
+            vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+            if (stc.z > 0.0)
+            {
                 stc /= stc.w;
-								
-				if (stc.x < 1.0 &&
-					stc.y < 1.0 &&
-					stc.x > 0.0 &&
-					stc.y > 0.0)
-				{
-					col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
-				}
-			}
-		}
-	}
-
-	//not sure why, but this line prevents MATBUG-194
-	col = max(col, vec3(0.0));
-
-	frag_color.rgb = col;	
-	frag_color.a = 0.0;
+                                
+                if (stc.x < 1.0 &&
+                    stc.y < 1.0 &&
+                    stc.x > 0.0 &&
+                    stc.y > 0.0)
+                {
+                    col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+                }
+            }
+        }
+    }
+#endif
+
+    //not sure why, but this line prevents MATBUG-194
+    col = max(col, vec3(0.0));
+
+    //output linear
+    frag_color.rgb = col;
+    frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..1dce85a83b0ed14eea22f039ca8dd13d4e6454a6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
@@ -0,0 +1,204 @@
+/** 
+ * @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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+// SKY ////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// 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 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 float sun_moon_glow_factor;
+
+uniform vec4 cloud_color;
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+VARYING vec3 pos;
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+uniform sampler2D rainbow_map;
+uniform sampler2D halo_map;
+
+uniform float moisture_level;
+uniform float droplet_radius;
+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;
+}
+
+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;
+}
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light);
+
+void main()
+{
+
+    // World / view / projection
+    // Get relative position
+    vec3 P = pos.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);
+
+    // 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
+
+    // Add "minimum anti-solar illumination"
+    temp2.x += .25;
+
+    temp2.x *= sun_moon_glow_factor;
+
+    // Haze color above cloud
+    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
+                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
+             ); 
+
+    // Final atmosphere additive
+    color *= (1. - temp1);
+
+    // 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));
+
+    // Haze color below cloud
+    vec4 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
+                + (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)
+             ); 
+
+    
+    
+    // Attenuate cloud color by atmosphere
+    temp1 = sqrt(temp1);    //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.rgb += rainbow(optic_d);
+
+    color.rgb += halo_22;
+
+    color.rgb *= 2.;
+    color.rgb = scaleSoftClip(color.rgb);
+
+    /// 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
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..bcf775577ab2dc11bacd4f31bf230da392bf1b42
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl
@@ -0,0 +1,42 @@
+/** 
+ * @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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+// SKY ////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+VARYING vec3 pos;
+
+void main()
+{
+
+	// World / view / projection
+    pos = position.xyz;
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index f7832521facdf2c56c437977789395ac9f1ed32b..b0dff0c62839c89935e2079b6f2118172eb083d2 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file softenLightF.glsl
+ * @file class2/deferred/softenLightF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,8 +22,9 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
 #extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
 
 /*[EXTRA_CODE_HERE]*/
 
@@ -39,456 +40,161 @@ uniform sampler2DRect normalMap;
 uniform sampler2DRect lightMap;
 uniform sampler2DRect depthMap;
 uniform samplerCube environmentMap;
-uniform sampler2D	  lightFunc;
+uniform sampler2D     lightFunc;
 
 uniform float blur_size;
 uniform float blur_fidelity;
 
 // Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-//uniform vec4 camPosWorld;
-uniform vec4 gamma;
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-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 float global_gamma;
-uniform float scene_light_strength;
 uniform mat3 env_mat;
-uniform vec4 shadow_clip;
-uniform mat3 ssao_effect_mat;
 
 uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform int sun_up_factor;
 VARYING vec2 vary_fragcoord;
 
-vec3 vary_PositionEye;
-
-vec3 vary_SunlitColor;
-vec3 vary_AmblitColor;
-vec3 vary_AdditiveColor;
-vec3 vary_AtmosAttenuation;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition_d(vec2 pos_screen, float depth)
-{
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{ //get position in screen space (world units) given window coordinate and depth map
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	return getPosition_d(pos_screen, depth);
-}
-
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
-vec3 getSunlitColor()
-{
-	return vary_SunlitColor;
-}
-vec3 getAmblitColor()
-{
-	return vary_AmblitColor;
-}
-vec3 getAdditiveColor()
-{
-	return vary_AdditiveColor;
-}
-vec3 getAtmosAttenuation()
-{
-	return vary_AtmosAttenuation;
-}
-
-void setPositionEye(vec3 v)
-{
-	vary_PositionEye = v;
-}
-
-void setSunlitColor(vec3 v)
-{
-	vary_SunlitColor = v;
-}
-
-void setAmblitColor(vec3 v)
-{
-	vary_AmblitColor = v;
-}
-
-void setAdditiveColor(vec3 v)
-{
-	vary_AdditiveColor = v;
-}
+vec3 getNorm(vec2 pos_screen);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
 
-void setAtmosAttenuation(vec3 v)
-{
-	vary_AtmosAttenuation = v;
-}
+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);
 
-void calcAtmospherics(vec3 inPositionEye, float ambFactor) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(0);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//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;
-	
-	//increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * 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(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a);
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-
-	//brightness of surface both sunlight and ambient
-	/*setSunlitColor(pow(vec3(sunlight * .5), vec3(global_gamma)) * global_gamma);
-	setAmblitColor(pow(vec3(tmpAmbient * .25), vec3(global_gamma)) * global_gamma);
-	setAdditiveColor(pow(getAdditiveColor() * vec3(1.0 - temp1), vec3(global_gamma)) * global_gamma);*/
-
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-}
+vec3 linear_to_srgb(vec3 c);
+vec3 srgb_to_linear(vec3 c);
 
 #ifdef WATER_FOG
-uniform vec4 waterPlane;
-uniform vec4 waterFogColor;
-uniform float waterFogDensity;
-uniform float waterFogKS;
-
-vec4 applyWaterFogDeferred(vec3 pos, vec4 color)
-{
-	//normalize view vector
-	vec3 view = normalize(pos);
-	float es = -(dot(view, waterPlane.xyz));
-
-	//find intersection point with water plane and eye vector
-	
-	//get eye depth
-	float e0 = max(-waterPlane.w, 0.0);
-	
-	vec3 int_v = waterPlane.w > 0.0 ? view * waterPlane.w/es : vec3(0.0, 0.0, 0.0);
-	
-	//get object depth
-	float depth = length(pos - int_v);
-		
-	//get "thickness" of water
-	float l = max(depth, 0.1);
-
-	float kd = waterFogDensity;
-	float ks = waterFogKS;
-	vec4 kc = waterFogColor;
-	
-	float F = 0.98;
-	
-	float t1 = -kd * pow(F, ks * e0);
-	float t2 = kd + ks * es;
-	float t3 = pow(F, t2*l) - 1.0;
-	
-	float L = min(t1/t2*t3, 1.0);
-	
-	float D = pow(0.98, l*kd);
-	
-	color.rgb = color.rgb * D + kc.rgb * L;
-	color.a = kc.a + color.a;
-	
-	return color;
-}
+vec4 applyWaterFogView(vec3 pos, vec4 color);
 #endif
 
-vec3 atmosLighting(vec3 light)
-{
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
-}
-
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
-	return light;
-}
-
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
-}
-
-
-
-vec3 atmosGetDiffuseSunlightColor()
-{
-	return getSunlitColor();
-}
-
-vec3 scaleDownLight(vec3 light)
-{
-	return (light / scene_light_strength );
-}
-
-vec3 scaleUpLight(vec3 light)
-{
-	return (light * scene_light_strength);
-}
-
-vec3 atmosAmbient(vec3 light)
-{
-	return getAmblitColor() + light / 2.0;
-}
-
-vec3 atmosAffectDirectionalLight(float lightIntensity)
-{
-	return getSunlitColor() * lightIntensity;
-}
-
-vec3 scaleSoftClip(vec3 light)
+void main() 
 {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
-
+    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);
+    
+    vec4 diffuse = texture2DRect(diffuseRect, tc);
+    
+    vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+
+    vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+    scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
+
+    float scol = max(scol_ambocc.r, diffuse.a); 
+
+    float ambocc = scol_ambocc.g;
+
+    vec3 color = vec3(0);
+    float bloom = 0.0;
+    {
+        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
 
-vec3 fullbrightScaleSoftClip(vec3 light)
-{
-	//soft clip effect:
-	return light;
+        }
+       
+       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
+
+    }
+
+// linear debuggables
+//color.rgb = vec3(final_da);
+//color.rgb = vec3(ambient);
+//color.rgb = vec3(scol);
+//color.rgb = diffuse_srgb.rgb;
+
+    // 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;
 }
 
-void main() 
-{
-	vec2 tc = vary_fragcoord.xy;
-	float depth = texture2DRect(depthMap, tc.xy).r;
-	vec3 pos = getPosition_d(tc, depth).xyz;
-	vec4 norm = texture2DRect(normalMap, tc);
-	float envIntensity = norm.z;
-	norm.xyz = decode_normal(norm.xy); // unpack norm
-		
-	float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
-
-	float light_gamma = 1.0/1.3;
-	da = pow(da, light_gamma);
-
-
-	vec4 diffuse = texture2DRect(diffuseRect, tc);
-
-	//convert to gamma space
-	diffuse.rgb = linear_to_srgb(diffuse.rgb);
-	
-	vec3 col;
-	float bloom = 0.0;
-	{
-		vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
-		
-		vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
-		scol_ambocc = pow(scol_ambocc, vec2(light_gamma));
-
-		float scol = max(scol_ambocc.r, diffuse.a); 
-
-		
-
-		float ambocc = scol_ambocc.g;
-	
-		calcAtmospherics(pos.xyz, ambocc);
-	
-		col = atmosAmbient(vec3(0));
-		float ambient = min(abs(dot(norm.xyz, sun_dir.xyz)), 1.0);
-		ambient *= 0.5;
-		ambient *= ambient;
-		ambient = (1.0-ambient);
-
-		col.rgb *= ambient;
-
-		col += atmosAffectDirectionalLight(max(min(da, scol), 0.0));
-	
-		col *= diffuse.rgb;
-	
-		vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
-
-		if (spec.a > 0.0) // specular reflection
-		{
-			// the old infinite-sky shiny reflection
-			//
-			
-			float sa = dot(refnormpersp, sun_dir.xyz);
-			vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*(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;
-			col += spec_contrib;
-		}
-	
-		
-		col = mix(col, diffuse.rgb, diffuse.a);
-
-		if (envIntensity > 0.0)
-		{ //add environmentmap
-			vec3 env_vec = env_mat * refnormpersp;
-			
-			vec3 refcol = textureCube(environmentMap, env_vec).rgb;
-
-			col = mix(col.rgb, refcol, 
-				envIntensity);  
-
-		}
-						
-		if (norm.w < 0.5)
-		{
-			col = mix(atmosLighting(col), fullbrightAtmosTransport(col), diffuse.a);
-			col = mix(scaleSoftClip(col), fullbrightScaleSoftClip(col), diffuse.a);
-		}
-
-		#ifdef WATER_FOG
-			vec4 fogged = applyWaterFogDeferred(pos,vec4(col, bloom));
-			col = fogged.rgb;
-			bloom = fogged.a;
-		#endif
-
-		col = srgb_to_linear(col);
-
-		//col = vec3(1,0,1);
-		//col.g = envIntensity;
-	}
-	
-	frag_color.rgb = col;
-	frag_color.a = bloom;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
index c840d727843a95a9f2049dcf827eccb93d6519f3..bd11aa3f05865f385d1ad22f17f5dfa038a8f3f7 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl
@@ -31,12 +31,19 @@ uniform vec2 screen_res;
 
 VARYING vec2 vary_fragcoord;
 
+// forwards
+void setAtmosAttenuation(vec3 c);
+void setAdditiveColor(vec3 c);
+
 void main()
 {
 	//transform vertex
 	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
 	gl_Position = pos; 
-	
-	
+
+    // appease OSX GLSL compiler/linker by touching all the varyings we said we would
+    setAtmosAttenuation(vec3(1));
+    setAdditiveColor(vec3(0));
+
 	vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 81af1fdc8a217cc7902f16468f60599e2e9bf12a..5ab0b5c5b4d9ff0ccca3c74d77eab178f4dd52b5 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -71,70 +71,14 @@ uniform vec2 screen_res;
 
 uniform mat4 inv_proj;
 
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lte.r ? low_range.r : high_range.r;
-	result.g = lte.g ? low_range.g : high_range.g;
-	result.b = lte.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lte);
-#endif
-
-}
-
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-
-#ifdef OLD_SELECT
-	vec3 result;
-	result.r = lt.r ? low_range.r : high_range.r;
-	result.g = lt.g ? low_range.g : high_range.g;
-	result.b = lt.b ? low_range.b : high_range.b;
-    return result;
-#else
-	return mix(high_range, low_range, lt);
-#endif
-
-}
-
-vec4 correctWithGamma(vec4 col)
-{
-	return vec4(srgb_to_linear(col.rgb), col.a);
-}
+vec3 getNorm(vec2 pos_screen);
+vec3 srgb_to_linear(vec3 c);
 
 vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
 	ret.rgb = srgb_to_linear(ret.rgb);
-	
+
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
 	float det = min(lod/(proj_lod*0.5), 1.0);
@@ -153,7 +97,7 @@ vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
 vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
+	ret.rgb = srgb_to_linear(ret.rgb);
 	
 	vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
 	
@@ -171,7 +115,7 @@ vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
 vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 {
 	vec4 ret = texture2DLod(projectionMap, tc, lod);
-	ret = correctWithGamma(ret);
+	ret.rgb = srgb_to_linear(ret.rgb);
 	
 	vec2 dist = tc-vec2(0.5);
 	
@@ -182,22 +126,15 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
 	return ret;
 }
 
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
+vec4 getPosition(vec2 pos_screen);
 
 void main() 
 {
+	vec3 col = vec3(0,0,0);
+
+#if defined(LOCAL_LIGHT_KILL)
+    discard;
+#else
 	vec4 frag = vary_fragcoord;
 	frag.xyz /= frag.w;
 	frag.xyz = frag.xyz*0.5+0.5;
@@ -206,26 +143,26 @@ void main()
 	vec3 pos = getPosition(frag.xy).xyz;
 	vec3 lv = trans_center.xyz-pos.xyz;
 	float dist = length(lv);
+
+    if (dist >= size)
+    {
+        discard;
+    }
 	dist /= size;
-	if (dist > 1.0)
-	{
-		discard;
-	}
-	
+
 	float shadow = 1.0;
 	
 	if (proj_shadow_idx >= 0)
 	{
 		vec4 shd = texture2DRect(lightMap, frag.xy);
-		float sh[2];
-		sh[0] = shd.b;
-		sh[1] = shd.a;
-		shadow = min(sh[proj_shadow_idx]+shadow_fade, 1.0);
+        shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
+        shadow += shadow_fade;
+		shadow = clamp(shadow, 0.0, 1.0);        
 	}
 	
 	vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
 	float envIntensity = norm.z;
-	norm = decode_normal(norm.xy);
+	norm = getNorm(frag.xy);
 	
 	norm = normalize(norm);
 	float l_dist = -dot(lv, proj_n);
@@ -252,12 +189,8 @@ void main()
 	lv = normalize(lv);
 	float da = dot(norm, lv);
 		
-	vec3 col = vec3(0,0,0);
-		
-	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
-		
+	vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
 	vec4 spec = texture2DRect(specularRect, frag.xy);
-
 	vec3 dlit = vec3(0, 0, 0);
 
 	float noise = texture2D(noiseMap, frag.xy/128.0).b;
@@ -280,23 +213,21 @@ void main()
 			vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
 		
 			dlit = color.rgb * plcol.rgb * plcol.a;
-			
+		
 			col = dlit*lit*diff_tex*shadow;
-			amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+
+			amb_da += (da*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
 		}
 		
 		//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
 		vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
 							
-		amb_da += (da*da*0.5+0.5)*proj_ambiance;
-				
+		amb_da += (da*da*0.5+0.5) /* * (1.0-shadow) */ * proj_ambiance;
 		amb_da *= dist_atten * noise;
-			
 		amb_da = min(amb_da, 1.0-lit);
-			
-		col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
-	}
 	
+	    col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+	}
 
 	if (spec.a > 0.0)
 	{
@@ -317,14 +248,11 @@ void main()
 		if (nh > 0.0)
 		{
 			float scol = fres*texture2D(lightFunc, vec2(nh, spec.a)).r*gt/(nh*da);
-			col += dlit*scol*spec.rgb*shadow;
-			//col += spec.rgb;
+			vec3 speccol = dlit*scol*spec.rgb*shadow;
+            speccol = clamp(speccol, vec3(0), vec3(1));
+			col += speccol;
 		}
 	}	
-	
-	
-	
-	
 
 	if (envIntensity > 0.0)
 	{
@@ -354,10 +282,12 @@ void main()
 			}
 		}
 	}
+#endif
 	
 	//not sure why, but this line prevents MATBUG-194
 	col = max(col, vec3(0.0));
 
+	//output linear colors as gamma correction happens down stream
 	frag_color.rgb = col;	
 	frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index 265da8df99c0910c5112acd0bfd3df78fb457a98..8abdeae5aebf3caeffcf0de8a210b42bb029fab6 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -35,228 +35,26 @@ out vec4 frag_color;
 
 //class 2, shadows, no SSAO
 
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-uniform sampler2DShadow shadowMap4;
-uniform sampler2DShadow shadowMap5;
-
-
 // Inputs
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
-
 VARYING vec2 vary_fragcoord;
 
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-uniform vec2 proj_shadow_res;
 uniform vec3 sun_dir;
-
-uniform vec2 shadow_res;
 uniform float shadow_bias;
-uniform float shadow_offset;
-
-uniform float spot_shadow_bias;
-uniform float spot_shadow_offset;
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
-{
-	stc.xyz /= stc.w;
-	stc.z += shadow_bias;
-
-	stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x; // add some jitter to X sample pos according to Y to disguise the snapping going on here
-	float cs = shadow2D(shadowMap, stc.xyz).x;
 
-	float shadow = cs;
+vec3 getNorm(vec2 pos_screen);
+vec4 getPosition(vec2 pos_screen);
 
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-
-			
-    return shadow*0.2;
-}
-
-float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
-{
-	stc.xyz /= stc.w;
-	stc.z += spot_shadow_bias*scl;
-	stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
-
-	float cs = shadow2D(shadowMap, stc.xyz).x;
-	float shadow = cs;
-
-	vec2 off = 1.0/proj_shadow_res;
-	off.y *= 1.5;
-	
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
-
-        return shadow*0.2;
-}
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;
-	
-	//try doing an unproject here
-	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-		
-	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
-	{
-		frag_color = vec4(0.0); // doesn't matter
-		return;
-	}*/
-	
-	float shadow = 0.0;
-	float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz));
-	
-	vec3 shadow_pos = pos.xyz;
-	vec3 offset = sun_dir.xyz * (1.0-dp_directional_light);
-	
-	vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
-	
-	if (spos.z > -shadow_clip.w)
-	{	
-		if (dp_directional_light == 0.0)
-		{
-			// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
-			shadow = 0.0;
-		}
-		else
-		{
-			vec4 lpos;
-			
-			vec4 near_split = shadow_clip*-0.75;
-			vec4 far_split = shadow_clip*-1.25;
-			vec4 transition_domain = near_split-far_split;
-			float weight = 0.0;
-
-			if (spos.z < near_split.z)
-			{
-				lpos = shadow_matrix[3]*spos;
-				
-				float w = 1.0;
-				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
-				weight += w;
-				shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-			}
-
-			if (spos.z < near_split.y && spos.z > far_split.z)
-			{
-				lpos = shadow_matrix[2]*spos;
-				
-				float w = 1.0;
-				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
-				weight += w;
-			}
-
-			if (spos.z < near_split.x && spos.z > far_split.y)
-			{
-				lpos = shadow_matrix[1]*spos;
-
-				float w = 1.0;
-				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-				w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-				shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
-				weight += w;
-			}
-
-			if (spos.z > far_split.x)
-			{
-				lpos = shadow_matrix[0]*spos;
-				
-				float w = 1.0;
-				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-				shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
-				weight += w;
-			}
-		
-
-			shadow /= weight;
-
-			// take the most-shadowed value out of these two:
-			//  * the blurred sun shadow in the light (shadow) map
-			//  * an unblurred dot product between the sun and this norm
-			// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
-			shadow = min(shadow, dp_directional_light);
-			
-			//lpos.xy /= lpos.w*32.0;
-			//if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
-			//{
-			//	shadow = 0.0;
-			//}
-			
-		}
-	}
-	else
-	{
-		// more distant than the shadow map covers
-		shadow = 1.0;
-	}
-	
-	frag_color[0] = shadow;
-	frag_color[1] = 1.0;
-	
-	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
-	
-	//spotlight shadow 1
-	vec4 lpos = shadow_matrix[4]*spos;
-	frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen); 
-	
-	//spotlight shadow 2
-	lpos = shadow_matrix[5]*spos;
-	frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen); 
-
-	//frag_color.rgb = pos.xyz;
-	//frag_color.b = shadow;
+    vec2 pos_screen = vary_fragcoord.xy;
+    vec4 pos        = getPosition(pos_screen);
+    vec3 norm       = getNorm(pos_screen);
+
+    frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
+    frag_color.g = 1.0f;
+    frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen); 
+    frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index 5c6fe30daa221562cfa8207b5e668ff86eaf2477..64d99bae2c86336d4334bd21b80cc96d904db476 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file sunLightSSAOF.glsl
+ * @file class2/deferred/sunLightSSAOF.glsl
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
@@ -34,290 +34,24 @@ out vec4 frag_color;
 
 //class 2 -- shadows and SSAO
 
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-uniform sampler2DShadow shadowMap4;
-uniform sampler2DShadow shadowMap5;
-uniform sampler2D noiseMap;
-
-
 // Inputs
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform float ssao_radius;
-uniform float ssao_max_radius;
-uniform float ssao_factor;
-uniform float ssao_factor_inv;
-
 VARYING vec2 vary_fragcoord;
 
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-uniform vec2 proj_shadow_res;
-uniform vec3 sun_dir;
-
-uniform vec2 shadow_res;
-
-uniform float shadow_bias;
-uniform float shadow_offset;
-
-uniform float spot_shadow_bias;
-uniform float spot_shadow_offset;
-
-vec2 encode_normal(vec3 n)
-{
-	float f = sqrt(8 * n.z + 8);
-	return n.xy / f + 0.5;
-}
-
-vec3 decode_normal (vec2 enc)
-{
-    vec2 fenc = enc*4-2;
-    float f = dot(fenc,fenc);
-    float g = sqrt(1-f/4);
-    vec3 n;
-    n.xy = fenc*g;
-    n.z = 1-f/2;
-    return n;
-}
-
-vec4 getPosition(vec2 pos_screen)
-{
-	float depth = texture2DRect(depthMap, pos_screen.xy).r;
-	vec2 sc = pos_screen.xy*2.0;
-	sc /= screen_res;
-	sc -= vec2(1.0,1.0);
-	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
-	vec4 pos = inv_proj * ndc;
-	pos /= pos.w;
-	pos.w = 1.0;
-	return pos;
-}
-
-vec2 getKern(int i)
-{
-	vec2 kern[8];
-	// exponentially (^2) distant occlusion samples spread around origin
-	kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
-	kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
-	kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
-	kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
-	kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
-	kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
-	kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
-	kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
-       
-	return kern[i];
-}
-
-//calculate decreases in ambient lighting when crowded out (SSAO)
-float calcAmbientOcclusion(vec4 pos, vec3 norm)
-{
-	float ret = 1.0;
-
-	vec2 pos_screen = vary_fragcoord.xy;
-	vec3 pos_world = pos.xyz;
-	vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
-		
-	float angle_hidden = 0.0;
-	float points = 0;
-		
-	float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
-	
-	// it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
-	for (int i = 0; i < 8; i++)
-	{
-		vec2 samppos_screen = pos_screen + scale * reflect(getKern(i), noise_reflect);
-		vec3 samppos_world = getPosition(samppos_screen).xyz; 
-		
-		vec3 diff = pos_world - samppos_world;
-		float dist2 = dot(diff, diff);
-			
-		// assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
-		// --> solid angle shrinking by the square of distance
-		//radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
-		//(k should vary inversely with # of samples, but this is taken care of later)
-		
-		float funky_val = (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) ? 1.0 : 0.0;
-		angle_hidden = angle_hidden + funky_val * min(1.0/dist2, ssao_factor_inv);
-			
-		// 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion" 
-		float diffz_val = (diff.z > -1.0) ? 1.0 : 0.0;
-		points = points + diffz_val;
-	}
-		
-	angle_hidden = min(ssao_factor*angle_hidden/points, 1.0);
-	
-	float points_val = (points > 0.0) ? 1.0 : 0.0;
-	ret = (1.0 - (points_val * angle_hidden));
-
-	ret = max(ret, 0.0);
-	return min(ret, 1.0);
-}
-
-float pcfShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
-{
-	stc.xyz /= stc.w;
-	stc.z += shadow_bias;
-
-	stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*0.666666666))/shadow_res.x;
-	float cs = shadow2D(shadowMap, stc.xyz).x;
-	
-	float shadow = cs;
-	
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(2.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(1.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-1.0/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
-    shadow += shadow2D(shadowMap, stc.xyz+vec3(-2.0/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
-	         
-        return shadow*0.2;
-}
-
-float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float scl, vec2 pos_screen)
-{
-	stc.xyz /= stc.w;
-	stc.z += spot_shadow_bias*scl;
-	stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
-		
-	float cs = shadow2D(shadowMap, stc.xyz).x;
-	float shadow = cs;
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
 
-	vec2 off = 1.0/proj_shadow_res;
-	off.y *= 1.5;
-	
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
-	shadow += shadow2D(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
-
-        return shadow*0.2;
-}
+float sampleDirectionalShadow(vec3 shadow_pos, vec3 norm, vec2 pos_screen);
+float sampleSpotShadow(vec3 shadow_pos, vec3 norm, int index, vec2 pos_screen);
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
 
 void main() 
 {
-	vec2 pos_screen = vary_fragcoord.xy;
-	
-	//try doing an unproject here
-	
-	vec4 pos = getPosition(pos_screen);
-	
-	vec3 norm = texture2DRect(normalMap, pos_screen).xyz;
-	norm = decode_normal(norm.xy); // unpack norm
-		
-	/*if (pos.z == 0.0) // do nothing for sky *FIX: REMOVE THIS IF/WHEN THE POSITION MAP IS BEING USED AS A STENCIL
-	{
-		frag_color = vec4(0.0); // doesn't matter
-		return;
-	}*/
-	
-	float shadow = 0.0;
-	float dp_directional_light = max(0.0, dot(norm, sun_dir.xyz));
-	
-	vec3 shadow_pos = pos.xyz;
-	vec3 offset = sun_dir.xyz * (1.0-dp_directional_light);
-	
-	vec4 spos = vec4(shadow_pos+offset*shadow_offset, 1.0);
-	
-	if (spos.z > -shadow_clip.w)
-	{	
-		if (dp_directional_light == 0.0)
-		{
-			// if we know this point is facing away from the sun then we know it's in shadow without having to do a squirrelly shadow-map lookup
-			shadow = 0.0;
-		}
-		else
-		{
-			vec4 lpos;
-
-			vec4 near_split = shadow_clip*-0.75;
-			vec4 far_split = shadow_clip*-1.25;
-			vec4 transition_domain = near_split-far_split;
-			float weight = 0.0;
-
-			if (spos.z < near_split.z)
-			{
-				lpos = shadow_matrix[3]*spos;
-				
-				float w = 1.0;
-				w -= max(spos.z-far_split.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap3, lpos, 0.25, pos_screen)*w;
-				weight += w;
-				shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
-			}
-
-			if (spos.z < near_split.y && spos.z > far_split.z)
-			{
-				lpos = shadow_matrix[2]*spos;
-				
-				float w = 1.0;
-				w -= max(spos.z-far_split.y, 0.0)/transition_domain.y;
-				w -= max(near_split.z-spos.z, 0.0)/transition_domain.z;
-				shadow += pcfShadow(shadowMap2, lpos, 0.5, pos_screen)*w;
-				weight += w;
-			}
-
-			if (spos.z < near_split.x && spos.z > far_split.y)
-			{
-				lpos = shadow_matrix[1]*spos;
-				
-				float w = 1.0;
-				w -= max(spos.z-far_split.x, 0.0)/transition_domain.x;
-				w -= max(near_split.y-spos.z, 0.0)/transition_domain.y;
-				shadow += pcfShadow(shadowMap1, lpos, 0.75, pos_screen)*w;
-				weight += w;
-			}
-
-			if (spos.z > far_split.x)
-			{
-				lpos = shadow_matrix[0]*spos;
-								
-				float w = 1.0;
-				w -= max(near_split.x-spos.z, 0.0)/transition_domain.x;
-				
-				shadow += pcfShadow(shadowMap0, lpos, 1.0, pos_screen)*w;
-				weight += w;
-			}
-		
-
-			shadow /= weight;
-
-			// take the most-shadowed value out of these two:
-			//  * the blurred sun shadow in the light (shadow) map
-			//  * an unblurred dot product between the sun and this norm
-			// the goal is to err on the side of most-shadow to fill-in shadow holes and reduce artifacting
-			shadow = min(shadow, dp_directional_light);
-			
-			//lpos.xy /= lpos.w*32.0;
-			//if (fract(lpos.x) < 0.1 || fract(lpos.y) < 0.1)
-			//{
-			//	shadow = 0.0;
-			//}
-			
-		}
-	}
-	else
-	{
-		// more distant than the shadow map covers
-		shadow = 1.0;
-	}
-	
-	frag_color[0] = shadow;
-	frag_color[1] = calcAmbientOcclusion(pos, norm);
-	
-	spos = vec4(shadow_pos+norm*spot_shadow_offset, 1.0);
-	
-	//spotlight shadow 1
-	vec4 lpos = shadow_matrix[4]*spos;
-	frag_color[2] = pcfSpotShadow(shadowMap4, lpos, 0.8, pos_screen);
-	
-	//spotlight shadow 2
-	lpos = shadow_matrix[5]*spos;
-	frag_color[3] = pcfSpotShadow(shadowMap5, lpos, 0.8, pos_screen);
+    vec2 pos_screen = vary_fragcoord.xy;
+    vec4 pos  = getPosition(pos_screen);
+    vec3 norm = getNorm(pos_screen);
 
-	//frag_color.rgb = pos.xyz;
-	//frag_color.b = shadow;
+    frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
+    frag_color.g = calcAmbientOcclusion(pos, norm, pos_screen);
+    frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
+    frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
 }
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
index 3acf9fe883fa0644defbe7c297c0e44304faef11..89d9d1bde37a1ce660e6fa0a83f658cf66438f03 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsV.glsl
+ * @file class2\lighting\sumLightsSpecularV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -28,16 +28,16 @@
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
 vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 atmosGetDiffuseSunlightColor();
 vec3 scaleDownLight(vec3 light);
 
 uniform vec4 light_position[8];
-uniform vec3 light_attenuation[8]; 
+uniform vec4 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
+vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor)
 {
 	vec4 col = vec4(0.0, 0.0, 0.0, color.a);
 	
@@ -53,8 +53,8 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor
 	col.rgb = scaleDownLight(col.rgb);
 						
 	// Add windlight lights
-	col.rgb += atmosAmbient(baseCol.rgb);
-	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz,atmosGetDiffuseSunlightColor()*baseCol.a, 1.0));
+	col.rgb += atmosAmbient();
+	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz, atmosGetDiffuseSunlightColor(), 1.0));
 
 	col.rgb = min(col.rgb*color.rgb, 1.0);
 	specularColor.rgb = min(specularColor.rgb*specularSum.rgb, 1.0);
diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
index c9987ef3b946e5f317ec5cc5a42bab1e28410f1f..30ca88afd2ee29705272de05576b00fdef6f0253 100644
--- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsV.glsl
+ * @file class2\lighting\sumLightsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,9 +24,8 @@
  */
  
 float calcDirectionalLight(vec3 n, vec3 l);
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight);
 
-vec3 atmosAmbient(vec3 light);
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
 
@@ -35,24 +34,27 @@ uniform vec3 light_direction[8];
 uniform vec3 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
+vec4 sumLights(vec3 pos, vec3 norm, vec4 color)
 {
 	vec4 col = vec4(0.0, 0.0, 0.0, color.a);
 	
 	// Collect normal lights (need to be divided by two, as we later multiply by 2)
 	col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz);
-
-	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
-	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
-
+	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z);
+	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z);
 	col.rgb = scaleDownLight(col.rgb);
 
+#if defined(LOCAL_LIGHT_KILL)
+    col.rgb = vec3(0);
+i#endif
+
 	// Add windlight lights
-	col.rgb += atmosAmbient(baseLight.rgb);
 	col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz));
-				
+
+#if !defined(SUNLIGHT_KILL)
 	col.rgb = min(col.rgb*color.rgb, 1.0);
-	
+#endif
+
 	return col;	
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
index fea3cbf69b5ec638486dbbf8b2a4a668d824af4d..ee9c990b12e5b858a2afda2585fc7294646e1892 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericsF.glsl
+ * @file class2\wl\atmosphericsF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,23 +22,25 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-
-
-//////////////////////////////////////////////////////////
-// The fragment shader for the terrain atmospherics
-//////////////////////////////////////////////////////////
 
 vec3 getAdditiveColor();
 vec3 getAtmosAttenuation();
+vec3 scaleSoftClipFrag(vec3 light);
 
-uniform sampler2D cloudMap;
-uniform vec4 cloud_pos_density1;
+uniform int no_atmo;
 
-vec3 atmosLighting(vec3 light)
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
 {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor();
-	return (2.0 * light);
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+    light *= atten.r;
+    light += additive;
+    return light * 2.0;
 }
 
+vec3 atmosLighting(vec3 light)
+{
+    return atmosFragLighting(light, getAdditiveColor(), getAtmosAttenuation());
+}
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..5788871744ab90e42101c72b554ba7fc2423a95c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersF.glsl
@@ -0,0 +1,46 @@
+/**
+ * @file class2\wl\atmosphericsHelpersV.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$
+ */
+
+// Output variables
+
+uniform float scene_light_strength;
+uniform int no_atmo;
+
+vec3 atmosFragAmbient(vec3 light, vec3 amblit)
+{
+    if (no_atmo == 1) return light;
+    return amblit + light / 2.0;
+}
+
+vec3 atmosFragAffectDirectionalLight(float lightIntensity, vec3 sunlit)
+{
+    return sunlit * lightIntensity;
+}
+
+vec3 scaleDownLightFrag(vec3 light)
+{
+    return (light / scene_light_strength );
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
index 62a034ce052cb800990f079149e854d4f816337f..9c42b84ecac61503494deebe12c49f1c35a3e6be 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file atmosphericsHelpersV.glsl
+ * @file class2\wl\atmosphericsHelpersV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -33,29 +33,31 @@ vec3 getAtmosAttenuation();
 vec3 getPositionEye();
 
 uniform float scene_light_strength;
+uniform int no_atmo;
 
-vec3 atmosAmbient(vec3 light)
+vec3 atmosAmbient()
 {
-	return getAmblitColor() + light / 2.0;
+    if (no_atmo == 1) return vec3(0.16);
+    return getAmblitColor();
 }
 
 vec3 atmosAffectDirectionalLight(float lightIntensity)
 {
-	return getSunlitColor() * lightIntensity;
+    return getSunlitColor() * lightIntensity;
 }
 
 vec3 atmosGetDiffuseSunlightColor()
 {
-	return getSunlitColor();
+    return getSunlitColor();
 }
 
 vec3 scaleDownLight(vec3 light)
 {
-	return (light / scene_light_strength );
+    return (light / scene_light_strength );
 }
 
 vec3 scaleUpLight(vec3 light)
 {
-	return (light * scene_light_strength);
+    return (light * scene_light_strength);
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
index d174805cc08c739c70b2255b4aafbdc096547dc9..4c418e414f2f4670bb90e4ef277a9c0c9494c45f 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file atmosphericsV.glsl
+ * @file class2\wl\atmosphericsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,10 +22,14 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-
 
 // VARYING param funcs
+
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform int sun_up_factor;
+
 void setSunlitColor(vec3 v);
 void setAmblitColor(vec3 v);
 void setAdditiveColor(vec3 v);
@@ -34,124 +38,19 @@ void setPositionEye(vec3 v);
 
 vec3 getAdditiveColor();
 
-//VARYING vec4 vary_CloudUVs;
-//VARYING float vary_CloudDensity;
-
-// Inputs
-uniform vec4 morphFactor;
-uniform vec3 camPosLocal;
-//uniform vec4 camPosWorld;
-
-uniform vec4 lightnorm;
-uniform vec4 sunlight_color;
-uniform vec4 ambient;
-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;
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
 
 void calcAtmospherics(vec3 inPositionEye) {
-
-	vec3 P = inPositionEye;
-	setPositionEye(P);
-	
-	//(TERRAIN) limit altitude
-	if (P.y > max_y) P *= (max_y / P.y);
-	if (P.y < -max_y) P *= (-max_y / P.y);
-
-	vec3 tmpLightnorm = lightnorm.xyz;
-
-	vec3 Pn = normalize(P);
-	float  Plen = length(P);
-
-	vec4 temp1 = vec4(0);
-	vec3 temp2 = vec3(0);
-	vec4 blue_weight;
-	vec4 haze_weight;
-	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);
-		//I had thought blue_density and haze_density should have equal weighting,
-		//but attenuation due to haze_density tends to seem too strong
-
-	temp1 = blue_density + vec4(haze_density);
-	blue_weight = blue_density / temp1;
-	haze_weight = vec4(haze_density) / temp1;
-
-	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)
-	temp2.y = max(0.0, tmpLightnorm.y);
-	temp2.y = 1. / temp2.y;
-	sunlight *= exp( - light_atten * temp2.y);
-
-	// main atmospheric scattering line integral
-	temp2.z = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati
-	// compiler gets confused.
-	temp1 = exp(-temp1 * temp2.z * distance_multiplier);
-
-	//final atmosphere attenuation factor
-	setAtmosAttenuation(temp1.rgb);
-	//vary_AtmosAttenuation = distance_multiplier / 10000.;
-	//vary_AtmosAttenuation = density_multiplier * 100.;
-	//vary_AtmosAttenuation = vec4(Plen / 100000., 0., 0., 1.);
-
-	//compute haze glow
-	//(can use temp2.x as temp because we haven't used it yet)
-	temp2.x = dot(Pn, tmpLightnorm.xyz);
-	temp2.x = 1. - temp2.x;
-		//temp2.x is 0 at the sun and increases away from sun
-	temp2.x = max(temp2.x, .03);	//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;
-
-
-	//increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;
-
-	//haze color
-	setAdditiveColor(
-		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient)
-	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x
-		  + tmpAmbient)));
-	
-	//brightness of surface both sunlight and ambient
-	setSunlitColor(vec3(sunlight * .5));
-	setAmblitColor(vec3(tmpAmbient * .25));
-	setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1));
-
-	// vary_SunlitColor = vec3(0);
-	// vary_AmblitColor = vec3(0);
-	// vary_AdditiveColor = vec4(Pn, 1.0);
-
-	/*
-	const float cloudShadowScale = 100.;
-	// Get cloud uvs for shadowing
-	vec3 cloudPos = inPositionEye + camPosWorld - cloudShadowScale / 2.;
-	vary_CloudUVs.xy = cloudPos.xz / cloudShadowScale;
-
-	// We can take uv1 and multiply it by (TerrainSpan / CloudSpan)
-//	cloudUVs *= (((worldMaxZ - worldMinZ) * 20) /40000.);
-	vary_CloudUVs *= (10000./40000.);
-
-	// Offset by sun vector * (CloudAltitude / CloudSpan)
-	vary_CloudUVs.x += tmpLightnorm.x / tmpLightnorm.y * (3000./40000.);
-	vary_CloudUVs.y += tmpLightnorm.z / tmpLightnorm.y * (3000./40000.);
-	*/
+    vec3 P = inPositionEye;
+    setPositionEye(P);
+    vec3 tmpsunlit = vec3(1);
+    vec3 tmpamblit = vec3(1);
+    vec3 tmpaddlit = vec3(1);
+    vec3 tmpattenlit = vec3(1);
+	vec3 light_dir = (sun_up_factor == 1) ? sun_dir : moon_dir;	
+    calcAtmosphericVars(inPositionEye, light_dir, 1, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit, false);
+    setSunlitColor(tmpsunlit);
+    setAmblitColor(tmpamblit);
+    setAdditiveColor(tmpaddlit);
+    setAtmosAttenuation(tmpattenlit);
 }
-
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
index 765b0927c3acc27cf0f87f8fc558b0ec5bddd5a8..d758f85d713eafb34643c126c6212f17ef6fa136 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVars.glsl
+ * @file class2\wl\atmosphericVars.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,7 +24,6 @@
  */
  
 
-VARYING vec3 vary_SunlitColor;
 VARYING vec3 vary_AdditiveColor;
 VARYING vec3 vary_AtmosAttenuation;
 
@@ -32,14 +31,17 @@ vec3 getSunlitColor()
 {
 	return vec3(0,0,0);
 }
+
 vec3 getAmblitColor()
 {
 	return vec3(0,0,0);
 }
+
 vec3 getAdditiveColor()
 {
 	return vary_AdditiveColor;
 }
+
 vec3 getAtmosAttenuation()
 {
 	return vec3(vary_AtmosAttenuation);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
index 99dbee15eed4006818f8f5a730990e86f68a3990..31109aed31a77967109eb8fccc9cd7dc8c031c1f 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVars.glsl
+ * @file class2\wl\atmosphericVars.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterF.glsl
index 163ef26444615a51a7ce25e698adaefe57b0e1ae..22e16b7e0fa635cb74a548150e84b6eff5d2028a 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsWaterF.glsl
+ * @file class2\wl\atmosphericVarsWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterV.glsl
index 553f6752e631ed1af2b6f4b2f482a956a3edbbc7..0f2a3ee527e658c0d3f55884d0027e8cca8c9b6e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsWaterV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file atmosphericVarsWaterV.glsl
+ * @file class2\wl\atmosphericVarsWaterV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
index 96c70651b1135523aa44e7dcbf0c66914fe9b7bf..75bf8730df46e3efcdff262cc488f1518a564a2e 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLCloudsF.glsl
+ * @file class2\wl\cloudsF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,11 +22,13 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
+/*[EXTRA_CODE_HERE]*/ 
+
 #ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_color;
+out vec4 frag_data[3];
 #else
-#define frag_color gl_FragColor
+#define frag_data gl_FragData
 #endif
 
 /////////////////////////////////////////////////////////////////////////
@@ -36,69 +38,96 @@ out vec4 frag_color;
 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;
 
 uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
 uniform vec4 cloud_pos_density1;
 uniform vec4 cloud_pos_density2;
-uniform vec4 gamma;
+uniform float cloud_scale;
+uniform float cloud_variance;
+
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+VARYING float altitude_blend_factor;
 
 /// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
+vec3 scaleSoftClip(vec3 light);
 
-	return light;
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return cloud_noise_sample;
 }
 
 void main()
 {
-	// Set variables
-	vec2 uv1 = vary_texcoord0.xy;
-	vec2 uv2 = vary_texcoord1.xy;
+    // Set variables
+    vec2 uv1 = vary_texcoord0.xy;
+    vec2 uv2 = vary_texcoord1.xy;
+
+    vec4 cloudColorSun = vary_CloudColorSun;
+    vec4 cloudColorAmbient = vary_CloudColorAmbient;
+    float cloudDensity = vary_CloudDensity;
+    vec2 uv3 = vary_texcoord2.xy;
+    vec2 uv4 = vary_texcoord3.xy;
+
+    if (cloud_scale < 0.001)
+    {
+        discard;
+    }
+
+    vec2 disturbance  = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+    vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+
+    // Offset texture coords
+    uv1 += cloud_pos_density1.xy + (disturbance * 0.2);    //large texture, visible density
+    uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+    uv3 += cloud_pos_density2.xy;   //small texture, visible density
+    uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+
+    float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
 
-	vec4 cloudColorSun = vary_CloudColorSun;
-	vec4 cloudColorAmbient = vary_CloudColorAmbient;
-	float cloudDensity = vary_CloudDensity;
-	vec2 uv3 = vary_texcoord2.xy;
-	vec2 uv4 = vary_texcoord3.xy;
+    cloudDensity *= 1.0 - (density_variance * density_variance);
 
-	// Offset texture coords
-	uv1 += cloud_pos_density1.xy;	//large texture, visible density
-	uv2 += cloud_pos_density1.xy;	//large texture, self shadow
-	uv3 += cloud_pos_density2.xy;	//small texture, visible density
-	uv4 += cloud_pos_density2.xy;	//small texture, self shadow
+    // Compute alpha1, the main cloud opacity
 
+    float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+    alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
 
-	// Compute alpha1, the main cloud opacity
-	float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z;
-	alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.);
+    // And smooth
+    alpha1 = 1. - alpha1 * alpha1;
+    alpha1 = 1. - alpha1 * alpha1;  
 
-	// And smooth
-	alpha1 = 1. - alpha1 * alpha1;
-	alpha1 = 1. - alpha1 * alpha1;	
+    alpha1 *= altitude_blend_factor;
 
+    //if (alpha1 < 0.001f)
+    //{
+    //    discard;
+    //}
 
-	// Compute alpha2, for self shadowing effect
-	// (1 - alpha2) will later be used as percentage of incoming sunlight
-	float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5);
-	alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+    // Compute alpha2, for self shadowing effect
+    // (1 - alpha2) will later be used as percentage of incoming sunlight
+    float alpha2 = (cloudNoise(uv2).x - 0.5);
+    alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
 
-	// And smooth
-	alpha2 = 1. - alpha2;
-	alpha2 = 1. - alpha2 * alpha2;	
+    // And smooth
+    alpha2 = 1. - alpha2;
+    alpha2 = 1. - alpha2 * alpha2;  
 
-	// Combine
-	vec4 color;
-	color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
-	color *= 2.;
+    // Combine
+    vec4 color;
+    color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient);
+    color.rgb *= 2.;
+    color.rgb = scaleSoftClip(color.rgb);
 
-	/// Gamma correct for WL (soft clip effect).
-	frag_color.rgb = scaleSoftClip(color.rgb);
-	frag_color.a = alpha1;
+    /// Gamma correct for WL (soft clip effect).
+    frag_data[0] = vec4(color.rgb, alpha1);
+    frag_data[1] = vec4(0.0,0.0,0.0,0.0);
+    frag_data[2] = vec4(0,0,0,1);
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index c1dd45cd6729e9fbb3b9c7b6e849222cecf9a215..2c1475d5478872d28080826443919bcfa81c52a2 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLCloudsV.glsl
+ * @file class2\wl\cloudsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -40,13 +40,16 @@ 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 ambient;
+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;
@@ -57,6 +60,7 @@ uniform float density_multiplier;
 uniform float max_y;
 
 uniform vec4 glow;
+uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
 
@@ -73,6 +77,9 @@ void main()
 	// Get relative position
 	vec3 P = 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.)
 	{
@@ -92,16 +99,18 @@ void main()
 	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)) * (density_multiplier * max_y);
+	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
 
 	// Calculate relative weights
-	temp1 = blue_density + haze_density;
+	temp1 = abs(blue_density) + vec4(abs(haze_density));
 	blue_weight = blue_density / temp1;
 	haze_weight = haze_density / temp1;
 
@@ -111,7 +120,7 @@ void main()
 	sunlight *= exp( - light_atten * temp2.y);
 
 	// Distance
-	temp2.z = Plen * density_multiplier;
+	temp2.z = Plen * dens_mul;
 
 	// Transparency (-> temp1)
 	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati
@@ -130,11 +139,13 @@ void main()
 	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;
+	vec4 tmpAmbient = ambient_color;
 	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
 
 	// Dim sunlight by cloud shadow percentage
@@ -146,8 +157,6 @@ void main()
 			 );	
 
 	// CLOUDS
-
-	sunlight = sunlight_color;
 	temp2.y = max(0., lightnorm.y * 2.);
 	temp2.y = 1. / temp2.y;
 	sunlight *= exp( - light_atten * temp2.y);
diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
index 478373d729c631fbfa2198d75c35d48148087ab4..68db7fcbb18d5c636124aaa1a0f3978ed9f58325 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file gammaF.glsl
+ * @file class2\wl\gammaF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -22,23 +22,37 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-
-
-uniform vec4 gamma;
+uniform float gamma;
+uniform int no_atmo;
 
 vec3 getAtmosAttenuation();
+vec3 getAdditiveColor();
 
-/// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
+vec3 scaleSoftClipFrag(vec3 light)
+{
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+    //soft clip effect:
+    light = 1. - clamp(light, vec3(0.), vec3(1.));
+    light = 1. - pow(light, vec3(gamma)); // s/b inverted already CPU-side
+    return light;
+}
+
+vec3 scaleSoftClip(vec3 light)
+{
+    return scaleSoftClipFrag(light);
+}
 
-	return light;
+vec3 fullbrightScaleSoftClipFrag(vec3 light, vec3 add, vec3 atten)
+{
+    //return mix(scaleSoftClipFrag(light.rgb), add, atten);
+    return scaleSoftClipFrag(light.rgb);
 }
 
-vec3 fullbrightScaleSoftClip(vec3 light) {
-	return mix(scaleSoftClip(light.rgb), light.rgb, getAtmosAttenuation());
+vec3 fullbrightScaleSoftClip(vec3 light)
+{
+    return fullbrightScaleSoftClipFrag(light, getAdditiveColor(), getAtmosAttenuation());
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
index e2a2367626a339a5ca71e9801ddd375b03c48b7d..71463494530ade8f017e828d552c1da3c47a9482 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLSkyF.glsl
+ * @file class2/windlight/skyF.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -35,17 +35,8 @@ out vec4 frag_color;
 
 VARYING vec4 vary_HazeColor;
 
-uniform sampler2D cloud_noise_texture;
-uniform vec4 gamma;
-
 /// Soft clips the light with a gamma correction
-vec3 scaleSoftClip(vec3 light) {
-	//soft clip effect:
-	light = 1. - clamp(light, vec3(0.), vec3(1.));
-	light = 1. - pow(light, gamma.xxx);
-
-	return light;
-}
+vec3 scaleSoftClip(vec3 light);
 
 void main()
 {
@@ -56,8 +47,7 @@ void main()
 
 	vec4 color;
 	color = vary_HazeColor;
-	color *= 2.;
-
+	color.rgb *= 2.;
 	/// Gamma correct for WL (soft clip effect).
 	frag_color.rgb = scaleSoftClip(color.rgb);
 	frag_color.a = 1.0;
diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
index 3788ddaf2d4f37b53817790468b01d718fc82d32..0d141342ce239d7c095446fbadaf1c41da7caf0b 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file WLSkyV.glsl
+ * @file class2\wl\skyV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -39,7 +39,9 @@ uniform vec3 camPosLocal;
 
 uniform vec4 lightnorm;
 uniform vec4 sunlight_color;
-uniform vec4 ambient;
+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;
@@ -47,9 +49,11 @@ uniform float haze_density;
 
 uniform float cloud_shadow;
 uniform float density_multiplier;
+uniform float distance_multiplier;
 uniform float max_y;
 
 uniform vec4 glow;
+uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
 
@@ -57,11 +61,12 @@ void main()
 {
 
 	// World / view / projection
-	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+    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);
-	//vec3 P = position.xyz + vec3(0,50,0);
 
 	// Set altitude
 	if (P.y > 0.)
@@ -75,38 +80,40 @@ void main()
 
 	// Can normalize then
 	vec3 Pn = normalize(P);
-	float  Plen = length(P);
+
+	float Plen = length(P);
 
 	// Initialize temp variables
 	vec4 temp1 = vec4(0.);
 	vec4 temp2 = vec4(0.);
 	vec4 blue_weight;
 	vec4 haze_weight;
-	vec4 sunlight = sunlight_color;
+	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)) * (density_multiplier * max_y);
+	light_atten = (blue_density + vec4(haze_density * 0.25)) * (dens_mul * max_y);
 
 	// Calculate relative weights
-	temp1 = blue_density + haze_density;
+	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);
+    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 * density_multiplier;
+	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);
-
+    // 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);
@@ -122,35 +129,33 @@ void main()
 	// Add "minimum anti-solar illumination"
 	temp2.x += .25;
 
+    vec4 color = (    blue_horizon * blue_weight * (sunlight + ambient_color)
+                + (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient_color)
+             );
 
-	// Haze color above cloud
-	vary_HazeColor = (	  blue_horizon * blue_weight * (sunlight + ambient)
-				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)
-			 );	
 
+    // Final atmosphere additive
+    color *= (1. - temp1);
 
 	// Increase ambient when there are more clouds
-	vec4 tmpAmbient = ambient;
-	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
+	vec4 tmpAmbient = ambient_color;
+	tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; 
 
 	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1. - cloud_shadow);
+	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)
 			 );	
 
-	// Final atmosphere additive
-	vary_HazeColor *= (1. - temp1);
-	
 	// Attenuate cloud color by atmosphere
 	temp1 = sqrt(temp1);	//less atmos opacity (more transparency) below clouds
 
 	// At horizon, blend high altitude sky color towards the darker color below the clouds
-	vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1));
-	
-	// won't compile on mac without this being set
-	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+	color += (additiveColorBelowCloud - color) * (1. - sqrt(temp1));
+
+    // Haze color above cloud
+	vary_HazeColor = color;	
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
index 8a8e4cb0f68a582e9586b2cae51d3a295351078d..b53a2e237f332bfb2e39157cf9c5b74b47399e32 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file transportF.glsl
+ * @file class2\wl\transportF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -30,24 +30,33 @@
 vec3 getAdditiveColor();
 vec3 getAtmosAttenuation();
 
-uniform sampler2D cloudMap;
-uniform vec4 cloud_pos_density1;
+uniform int no_atmo;
 
-vec3 atmosTransport(vec3 light) {
-	light *= getAtmosAttenuation().r;
-	light += getAdditiveColor() * 2.0;
+vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    light *= atten.r;
+	light += additive * 2.0;
 	return light;
 }
 
-vec3 fullbrightAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
-
-	return mix(atmosTransport(light.rgb), light.rgb + getAdditiveColor().rgb, brightness * brightness);
+vec3 atmosTransport(vec3 light)
+{
+     return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
 }
 
-vec3 fullbrightShinyAtmosTransport(vec3 light) {
-	float brightness = dot(light.rgb, vec3(0.33333));
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    float brightness = dot(light.rgb * 0.5, vec3(0.3333)) + 0.1;    
+    return mix(atmosTransportFrag(light.rgb, additive, atten), light.rgb + additive, brightness * brightness);
+}
 
-	return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
+vec3 fullbrightAtmosTransport(vec3 light)
+{
+    return fullbrightAtmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
 }
 
+vec3 fullbrightShinyAtmosTransport(vec3 light)
+{
+    float brightness = dot(light.rgb, vec3(0.33333));
+    return mix(atmosTransport(light.rgb), (light.rgb + getAdditiveColor().rgb) * (2.0 - brightness), brightness * brightness);
+}
diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
index 721054b5adb20ca41550baa1f2dcdddc214a6c2e..df9704ec25d893923f6672d6b0a24cd708aec28e 100644
--- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
+++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl
@@ -33,7 +33,7 @@ ATTRIBUTE vec4 clothing;
 VARYING vec4 vertex_color;
 VARYING vec2 vary_texcoord0;
 
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol);
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
 mat4 getSkinnedTransform();
 void calcAtmospherics(vec3 inPositionEye);
 
@@ -127,7 +127,7 @@ void main()
 
 	calcAtmospherics(pos.xyz);
 	
-	vec4 col = calcLighting(pos.xyz, norm, color, vec4(0.0));			
+	vec4 col = calcLighting(pos.xyz, norm, color);			
 	vertex_color = col; 
 					
 	gl_Position = projection_matrix * pos;
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..d973326f9353e790d72aa7eeaf7494db7513a8eb
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowF.glsl
@@ -0,0 +1,44 @@
+/** 
+ * @file avatarShadowF.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]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 pos;
+VARYING vec2 vary_texcoord0;
+
+vec4 computeMoments(float depth, float a);
+
+void main() 
+{
+    frag_color = computeMoments(length(pos), 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..1a655e64671577f23718b263f2e1fdddf3ab7ed4
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/attachmentShadowV.glsl
@@ -0,0 +1,49 @@
+/** 
+ * @file attachmentShadowV.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$
+ */
+
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+uniform mat4 texture_matrix0;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+mat4 getObjectSkinnedTransform();
+
+VARYING vec4 pos;
+
+void main()
+{
+	//transform vertex
+	mat4 mat = getObjectSkinnedTransform();
+	
+	mat = modelview_matrix * mat;
+	pos = (mat*vec4(position.xyz, 1.0));
+	pos = projection_matrix * vec4(pos.xyz, 1.0);
+
+#if !defined(DEPTH_CLAMP)
+	pos.z = max(pos.z, -pos.w+0.01);
+#endif
+	gl_Position = pos;
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
similarity index 66%
rename from indra/newview/app_settings/shaders/class1/deferred/srgb.glsl
rename to indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
index 587f3d5a944587f4166b94b9a68eefff0464d6d5..48eefc7a73c7ccb9f4b86459925b63b8087ac901 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/srgb.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file srgb.glsl
+ * @file avatarShadowF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -23,24 +23,30 @@
  * $/LicenseInfo$
  */
 
-vec3 srgb_to_linear(vec3 cs)
-{
-	vec3 low_range = cs / vec3(12.92);
-	vec3 high_range = pow((cs+vec3(0.055))/vec3(1.055), vec3(2.4));
+/*[EXTRA_CODE_HERE]*/ 
 
-	bvec3 lte = lessThanEqual(cs,vec3(0.04045));
-	return mix(high_range, low_range, lte);
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
 
-}
+uniform sampler2D diffuseMap;
 
-vec3 linear_to_srgb(vec3 cl)
-{
-	cl = clamp(cl, vec3(0), vec3(1));
-	vec3 low_range  = cl * 12.92;
-	vec3 high_range = 1.055 * pow(cl, vec3(0.41666)) - 0.055;
+#if !defined(DEPTH_CLAMP)
+VARYING vec4 post_pos;
+#endif
 
-	bvec3 lt = lessThan(cl,vec3(0.0031308));
-	return mix(high_range, low_range, lt);
+VARYING vec4 pos;
+
+vec4 computeMoments(float depth, float a);
+
+void main() 
+{
+    frag_color = computeMoments(length(pos), 1.0);
 
+#if !defined(DEPTH_CLAMP)
+	gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0);
+#endif
 }
 
diff --git a/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..164b355f2088cc42b69a2e5d5841be5762be5d77
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/avatarShadowV.glsl
@@ -0,0 +1,68 @@
+/** 
+ * @file avatarShadowV.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$
+ */
+ 
+uniform mat4 projection_matrix;
+
+mat4 getSkinnedTransform();
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec3 normal;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING vec4 post_pos;
+#endif
+
+VARYING vec4 pos;
+
+void main()
+{
+	vec3 norm;
+	
+	vec4 pos_in = vec4(position.xyz, 1.0);
+	mat4 trans = getSkinnedTransform();
+
+	pos.x = dot(trans[0], pos_in);
+	pos.y = dot(trans[1], pos_in);
+	pos.z = dot(trans[2], pos_in);
+	pos.w = 1.0;
+	
+	norm.x = dot(trans[0].xyz, normal);
+	norm.y = dot(trans[1].xyz, normal);
+	norm.z = dot(trans[2].xyz, normal);
+	norm = normalize(norm);
+	
+	pos = projection_matrix * pos;
+
+#if !defined(DEPTH_CLAMP)
+	post_pos = pos;
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+
+}
+
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..32210f60dc25a1f043aae0a00fe63da42b8a974c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowF.glsl
@@ -0,0 +1,119 @@
+/** 
+ * @file class3/deferred/cloudsF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING float vary_CloudDensity;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+
+uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 cloud_color;
+uniform float cloud_shadow;
+uniform float cloud_scale;
+uniform float cloud_variance;
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return normalize(cloud_noise_sample);
+}
+
+vec4 computeMoments(float depth, float alpha);
+
+void main()
+{
+    if (cloud_scale >= 0.001)
+    {
+        // Set variables
+        vec2 uv1 = vary_texcoord0.xy;
+        vec2 uv2 = vary_texcoord1.xy;
+        vec2 uv3 = vary_texcoord2.xy;
+        float cloudDensity = 2.0 * (cloud_shadow - 0.25);
+    
+        vec2 uv4 = vary_texcoord3.xy;
+    
+        vec2 disturbance  = vec2(cloudNoise(uv1 / 8.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+        vec2 disturbance2 = vec2(cloudNoise((uv1 + uv3) / 4.0f).x, cloudNoise((uv4 + uv2) / 8.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+    
+        // Offset texture coords
+        uv1 += cloud_pos_density1.xy + (disturbance * 0.2);    //large texture, visible density
+        uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+        uv3 += cloud_pos_density2.xy;   //small texture, visible density
+        uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+    
+        float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0 + disturbance2.x + disturbance2.y) * 4.0);
+    
+        cloudDensity *= 1.0 - (density_variance * density_variance);
+    
+        // Compute alpha1, the main cloud opacity
+        float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+        alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha1 = 1. - alpha1 * alpha1;
+        alpha1 = 1. - alpha1 * alpha1;  
+    
+        if (alpha1 < 0.001f)
+        {
+            discard;
+        }
+    
+        // Compute alpha2, for self shadowing effect
+        // (1 - alpha2) will later be used as percentage of incoming sunlight
+        float alpha2 = (cloudNoise(uv2).x - 0.5);
+        alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+    
+        // And smooth
+        alpha2 = 1. - alpha2;
+        alpha2 = 1. - alpha2 * alpha2;  
+    
+        frag_color = computeMoments(length(pos), alpha1);
+    }
+    else
+    {
+        frag_color = vec4(0);
+    }
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..effb070f934ed4422f333c5b3cca100d0357742c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudShadowV.glsl
@@ -0,0 +1,63 @@
+/** 
+ * @file cloudShadowV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING vec2 vary_texcoord0;
+VARYING vec4 vertex_color;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+	pos = modelview_projection_matrix * pre_pos;
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+	vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e40d7e7c75381f3678f5721492e2a322b737b2b8
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsF.glsl
@@ -0,0 +1,166 @@
+/** 
+ * @file class3/deferred/cloudsF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// The fragment shader for the sky
+/////////////////////////////////////////////////////////////////////////
+
+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 vec3 vary_pos;
+
+uniform sampler2D cloud_noise_texture;
+uniform sampler2D cloud_noise_texture_next;
+uniform float blend_factor;
+uniform vec4 cloud_pos_density1;
+uniform vec4 cloud_pos_density2;
+uniform vec4 cloud_color;
+uniform float cloud_shadow;
+uniform float cloud_scale;
+uniform float cloud_variance;
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
+
+/// Soft clips the light with a gamma correction
+vec3 scaleSoftClip(vec3 light);
+
+vec4 cloudNoise(vec2 uv)
+{
+   vec4 a = texture2D(cloud_noise_texture, uv);
+   vec4 b = texture2D(cloud_noise_texture_next, uv);
+   vec4 cloud_noise_sample = mix(a, b, blend_factor);
+   return cloud_noise_sample;
+}
+
+void main()
+{
+    // Set variables
+    vec2 uv1 = vary_texcoord0.xy;
+    vec2 uv2 = vary_texcoord1.xy;
+    vec2 uv3 = vary_texcoord2.xy;
+    float cloudDensity = 2.0 * (cloud_shadow - 0.25);
+
+    if (cloud_scale < 0.001)
+    {
+        discard;
+    }
+
+    vec2 uv4 = vary_texcoord3.xy;
+
+    vec2 disturbance = vec2(cloudNoise(uv1 / 16.0f).x, cloudNoise((uv3 + uv1) / 16.0f).x) * cloud_variance * (1.0f - cloud_scale * 0.25f);
+
+    // Offset texture coords
+    uv1 += cloud_pos_density1.xy + (disturbance * 0.2); //large texture, visible density
+    uv2 += cloud_pos_density1.xy;   //large texture, self shadow
+    uv3 += cloud_pos_density2.xy; //small texture, visible density
+    uv4 += cloud_pos_density2.xy;   //small texture, self shadow
+
+    float density_variance = min(1.0, (disturbance.x* 2.0 + disturbance.y* 2.0) * 4.0);
+
+    cloudDensity *= 1.0 - (density_variance * density_variance);
+
+    // Compute alpha1, the main cloud opacity
+    float alpha1 = (cloudNoise(uv1).x - 0.5) + (cloudNoise(uv3).x - 0.5) * cloud_pos_density2.z;
+    alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10 * cloud_pos_density1.z, 1.);
+
+    // And smooth
+    alpha1 = 1. - alpha1 * alpha1;
+    alpha1 = 1. - alpha1 * alpha1;  
+
+    if (alpha1 < 0.001f)
+    {
+        discard;
+    }
+
+    // Compute alpha2, for self shadowing effect
+    // (1 - alpha2) will later be used as percentage of incoming sunlight
+    float alpha2 = (cloudNoise(uv2).x - 0.5);
+    alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.);
+
+    // And smooth
+    alpha2 = 1. - alpha2;
+    alpha2 = 1. - alpha2 * alpha2;  
+
+    vec3 view_ray = vary_pos.xyz + camPosLocal;
+
+    vec3 view_direction = normalize(view_ray);
+    vec3 sun_direction  = normalize(sun_dir);
+    vec3 earth_center   = vec3(0, 0, -6360.0f);
+    vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
+
+    vec3 transmittance;
+    vec3 radiance_sun  = GetSkyLuminance(camPos, view_direction, 1.0 - alpha1, sun_direction, transmittance);
+
+    vec3 sun_color = vec3(1.0) - exp(-radiance_sun * 0.0001);
+
+    // Combine
+    vec4 color;
+
+    vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
+
+    vec4 l1r = texture2D(sh_input_r, vec2(0,0));
+    vec4 l1g = texture2D(sh_input_g, vec2(0,0));
+    vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+
+    vec3 sun_indir = vec3(-view_direction.xy, view_direction.z);
+    vec3 amb = vec3(dot(l1r, l1tap * vec4(1, sun_indir)),
+                    dot(l1g, l1tap * vec4(1, sun_indir)),
+                    dot(l1b, l1tap * vec4(1, sun_indir)));
+
+
+    amb = max(vec3(0), amb);
+
+    color.rgb = sun_color * cloud_color.rgb * (1. - alpha2);
+    color.rgb = pow(color.rgb, vec3(1.0 / 2.2));
+    color.rgb += amb;
+
+    frag_data[0] = vec4(color.rgb, alpha1);
+    frag_data[1] = vec4(0);
+    frag_data[2] = vec4(0,1,0,1);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..71e422ddf06598fdde9bb87cafc2ae9772ac25e1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/cloudsV.glsl
@@ -0,0 +1,70 @@
+/** 
+ * @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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+uniform mat4 modelview_matrix;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+//////////////////////////////////////////////////////////////////////////
+// The vertex shader for creating the atmospheric sky
+///////////////////////////////////////////////////////////////////////////////
+
+// Output parameters
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
+VARYING vec3 vary_pos;
+
+// Inputs
+uniform float cloud_scale;
+uniform vec4  lightnorm;
+uniform vec3  camPosLocal;
+
+void main()
+{
+    vary_pos = position;
+
+    // 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 /= max(0.001, 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.;
+
+    // END CLOUDS
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..e27bbce0948765fa3bf89e0fe860bffb3ab5925f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/deferredUtil.glsl
@@ -0,0 +1,79 @@
+/** 
+ * @file class1/deferred/deferredUtil.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$
+ */
+
+uniform sampler2DRect   normalMap;
+uniform sampler2DRect   depthMap;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+vec2 getScreenCoordinate(vec2 screenpos)
+{
+    vec2 sc = screenpos.xy * 2.0;
+    if (screen_res.x > 0 && screen_res.y > 0)
+    {
+       sc /= screen_res;
+    }
+    return sc - vec2(1.0, 1.0);
+}
+
+vec3 getNorm(vec2 screenpos)
+{
+   vec2 enc = texture2DRect(normalMap, screenpos.xy).xy;
+   vec2 fenc = enc*4-2;
+   float f = dot(fenc,fenc);
+   float g = sqrt(1-f/4);
+   vec3 n;
+   n.xy = fenc*g;
+   n.z = 1-f/2;
+   return n;
+}
+
+float getDepth(vec2 pos_screen)
+{
+    float depth = texture2DRect(depthMap, pos_screen).r;
+    return depth;
+}
+
+vec4 getPosition(vec2 pos_screen)
+{
+    float depth = getDepth(pos_screen);
+    vec2 sc = getScreenCoordinate(pos_screen);
+    vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+    vec4 pos = inv_proj * ndc;
+    pos /= pos.w;
+    pos.w = 1.0;
+    return pos;
+}
+
+vec4 getPositionWithDepth(vec2 pos_screen, float depth)
+{
+    vec2 sc = getScreenCoordinate(pos_screen);
+    vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
+    vec4 pos = inv_proj * ndc;
+    pos /= pos.w;
+    pos.w = 1.0;
+    return pos;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl b/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..cdaff4b09f7eb2950cd0a6db34ee837343deb00d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/depthToShadowVolumeG.glsl
@@ -0,0 +1,202 @@
+/** 
+ * @file depthToShadowVolumeG.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+#extension GL_ARB_geometry_shader4  : enable
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+layout (triangles) in;
+layout (triangle_strip, max_vertices = 128) out;
+
+uniform sampler2DRect depthMap;
+uniform mat4 shadowMatrix[6]; 
+uniform vec4 lightpos;
+
+VARYING vec2 vary_texcoord0;
+
+out vec3 to_vec;
+
+void cross_products(out vec4 ns[3], int a, int b, int c)
+{
+   ns[0] = cross(gl_PositionIn[b].xyz - gl_PositionIn[a].xyz, gl_PositionIn[c].xyz - gl_PositionIn[a].xyz);
+   ns[1] = cross(gl_PositionIn[c].xyz - gl_PositionIn[b].xyz, gl_PositionIn[a].xyz - gl_PositionIn[b].xyz);
+   ns[2] = cross(gl_PositionIn[a].xyz - gl_PositionIn[c].xyz, gl_PositionIn[b].xyz - gl_PositionIn[c].xyz);
+}
+
+vec3 getLightDirection(vec4 lightpos, vec3 pos)
+{
+
+    vec3 lightdir = lightpos.xyz - lightpos.w * pos;
+    return lightdir;
+}
+
+void emitTri(vec4 v[3])
+{
+    gl_Position = proj_matrix * v[0];
+    EmitVertex();
+
+    gl_Position = proj_matrix * v[1];
+    EmitVertex();
+
+    gl_Position = proj_matrix * v[2];
+    EmitVertex();
+
+    EndPrimitive();
+}
+
+void emitQuad(vec4 v[4]
+{
+    // Emit a quad as a triangle strip.
+    gl_Position = proj_matrix*v[0];
+    EmitVertex();
+
+    gl_Position = proj_matrix*v[1];
+    EmitVertex();
+
+    gl_Position = proj_matrix*v[2];
+    EmitVertex();
+
+    gl_Position = proj_matrix*v[3];
+    EmitVertex(); 
+
+    EndPrimitive();
+}
+
+void emitPrimitives(int layer)
+{
+    int i = layer;
+    gl_Layer = i;
+
+    vec4 depth1 = vec4(texture2DRect(depthMap, tc0).rg, texture2DRect(depthMap, tc1).rg));
+    vec3 depth2 = vec4(texture2DRect(depthMap, tc2).rg, texture2DRect(depthMap, tc3).rg));
+    vec3 depth3 = vec4(texture2DRect(depthMap, tc4).rg, texture2DRect(depthMap, tc5).rg));
+    vec3 depth4 = vec4(texture2DRect(depthMap, tc6).rg, texture2DRect(depthMap, tc7).rg));
+
+    depth1 = min(depth1, depth2);
+    depth1 = min(depth1, depth3);
+    depth1 = min(depth1, depth4);
+
+    vec2 depth = min(depth1.xy, depth1.zw);
+
+    int side = sqrt(gl_VerticesIn);
+
+    for (int j = 0; j < side; j++)
+    {
+        for (int k = 0; k < side; ++k)
+        {
+            vec3 pos = gl_PositionIn[(j * side) + k].xyz;
+            vec4 v = shadowMatrix[i] * vec4(pos, 1.0);
+            gl_Position = v;
+            to_vec = pos - light_position.xyz * depth;
+            EmitVertex();
+        }
+
+        EndPrimitive();
+    }
+
+    vec3 norms[3]; // Normals
+    vec3 lightdir3]; // Directions toward light
+
+    vec4 v[4]; // Temporary vertices
+
+    vec4 or_pos[3] =
+    {  // Triangle oriented toward light source
+        gl_PositionIn[0],
+        gl_PositionIn[2],
+        gl_PositionIn[4]
+    };
+
+    // Compute normal at each vertex.
+    cross_products(n, 0, 2, 4);
+
+    // Compute direction from vertices to light.
+    lightdir[0] = getLightDirection(lightpos, gl_PositionIn[0].xyz);
+    lightdir[1] = getLightDirection(lightpos, gl_PositionIn[2].xyz);
+    lightdir[2] = getLightDirection(lightpos, gl_PositionIn[4].xyz);
+
+    // Check if the main triangle faces the light.
+    bool faces_light = true;
+    if (!(dot(ns[0],d[0]) > 0
+         |dot(ns[1],d[1]) > 0
+         |dot(ns[2],d[2]) > 0))
+    {
+        // Flip vertex winding order in or_pos.
+        or_pos[1] = gl_PositionIn[4];
+        or_pos[2] = gl_PositionIn[2];
+        faces_light = false;
+    }
+
+    // Near cap: simply render triangle.
+    emitTri(or_pos);
+
+    // Far cap: extrude positions to infinity.
+    v[0] =vec4(lightpos.w * or_pos[0].xyz - lightpos.xyz,0);
+    v[1] =vec4(lightpos.w * or_pos[2].xyz - lightpos.xyz,0);
+    v[2] =vec4(lightpos.w * or_pos[1].xyz - lightpos.xyz,0);
+
+    emitTri(v);
+
+    // Loop over all edges and extrude if needed.
+    for ( int i=0; i<3; i++ ) 
+    {
+       // Compute indices of neighbor triangle.
+       int v0 = i*2;
+       int nb = (i*2+1);
+       int v1 = (i*2+2) % 6;
+       cross_products(n, v0, nb, v1);
+
+       // Compute direction to light, again as above.
+       d[0] =lightpos.xyz-lightpos.w*gl_PositionIn[v0].xyz;
+       d[1] =lightpos.xyz-lightpos.w*gl_PositionIn[nb].xyz;
+       d[2] =lightpos.xyz-lightpos.w*gl_PositionIn[v1].xyz;
+
+       bool is_parallel = gl_PositionIn[nb].w < 1e-5;
+
+       // Extrude the edge if it does not have a
+       // neighbor, or if it's a possible silhouette.
+       if (is_parallel ||
+          ( faces_light != (dot(ns[0],d[0])>0 ||
+                            dot(ns[1],d[1])>0 ||
+                            dot(ns[2],d[2])>0) ))
+       {
+           // Make sure sides are oriented correctly.
+           int i0 = faces_light ? v0 : v1;
+           int i1 = faces_light ? v1 : v0;
+
+           v[0] = gl_PositionIn[i0];
+           v[1] = vec4(lightpos.w*gl_PositionIn[i0].xyz - lightpos.xyz, 0);
+           v[2] = gl_PositionIn[i1];
+           v[3] = vec4(lightpos.w*gl_PositionIn[i1].xyz - lightpos.xyz, 0);
+
+           emitQuad(v);
+       }
+    }
+}
+
+void main()
+{
+    // Output
+    emitPrimitives(0);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..34d26cddea8b452893fa22e9436fb2754a3d35a4
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShF.glsl
@@ -0,0 +1,70 @@
+/** 
+ * @file class3/deferred/gatherSkyShF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+VARYING vec2 vary_frag;
+
+uniform vec2 screen_res;
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+void main()
+{
+    vec2 offset	  = vec2(2.0) / screen_res;
+
+    vec4 r = vec4(0);
+    vec4 g = vec4(0);
+    vec4 b = vec4(0);
+
+    vec2 tc = vary_frag * 2.0;
+
+	r += texture2D(sh_input_r, tc + vec2(0,        0));
+	r += texture2D(sh_input_r, tc + vec2(offset.x, 0));
+	r += texture2D(sh_input_r, tc + vec2(0,        offset.y));
+	r += texture2D(sh_input_r, tc + vec2(offset.x, offset.y));
+    r /= 4.0f;
+
+	g += texture2D(sh_input_g, tc + vec2(0,        0));
+	g += texture2D(sh_input_g, tc + vec2(offset.x, 0));
+	g += texture2D(sh_input_g, tc + vec2(0,        offset.y));
+	g += texture2D(sh_input_g, tc + vec2(offset.x, offset.y));
+    g /= 4.0f;
+
+	b += texture2D(sh_input_b, tc + vec2(0,        0));
+	b += texture2D(sh_input_b, tc + vec2(offset.x, 0));
+	b += texture2D(sh_input_b, tc + vec2(0,        offset.y));
+	b += texture2D(sh_input_b, tc + vec2(offset.x, offset.y));
+    b /= 4.0f;
+
+    frag_data[0] = r;
+    frag_data[1] = g;
+    frag_data[2] = b;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..337c8a50fe5985e8a9591534898ef49239a9eef7
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/gatherSkyShV.glsl
@@ -0,0 +1,40 @@
+/** 
+ * @file gatherSkyShV.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$
+ */
+ 
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_frag;
+uniform vec2 screen_res;
+
+void main()
+{
+    // pass through untransformed fullscreen pos
+    float oo_divisor = screen_res.x / 64.0;
+    vec3 pos = (position.xyz * oo_divisor) + vec3(oo_divisor - 1, oo_divisor - 1, 0);
+	gl_Position = vec4(pos.xyz, 1.0);
+    vary_frag = texcoord0 * oo_divisor;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl b/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..d5d91c88f07c78a6159f68f1c819cdcdf8a4e324
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/genSkyShF.glsl
@@ -0,0 +1,111 @@
+/** 
+ * @file class3/deferred/genSkyShF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+VARYING vec2 vary_frag;
+
+uniform vec3 sun_dir;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
+
+vec3 calcDirection(vec2 tc)
+{
+     float phi = tc.y * 2.0 * 3.14159265;
+     float cosTheta = sqrt(1.0 - tc.x);
+     float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
+     return vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);
+}
+
+// reverse mapping above to convert a hemisphere direction into phi/theta values
+void getPhiAndThetaFromDirection(vec3 dir, out float phi, out float theta)
+{
+     float sin_theta;
+     float cos_theta;
+     cos_theta = dir.z;
+     theta     = acos(cos_theta);
+     sin_theta = sin(theta);
+     phi       = abs(sin_theta) > 0.0001 ? acos(dir.x / sin_theta) : 1.0;
+}
+
+// reverse mapping above to convert a hemisphere direction into an SH texture sample pos
+vec2 calcShUvFromDirection(vec3 dir)
+{
+    vec2 uv;
+    float phi;
+    float theta;
+    getPhiAndThetaFromDirection(dir, phi, theta);
+    uv.y = phi   / 2.0 * 3.14159265;
+    uv.x = theta / 2.0 * 3.14159265;
+    return uv;
+}
+
+void projectToL1(vec3 n, vec3 c, vec4 basis, out vec4 coeffs[3])
+{
+    coeffs[0] = vec4(basis.x, n * basis.yzw * c.r);
+    coeffs[1] = vec4(basis.x, n * basis.yzw * c.g);
+    coeffs[2] = vec4(basis.x, n * basis.yzw * c.b);
+}
+
+void main()
+{
+    float Y00 = sqrt(1.0 / 3.14159265) * 0.5;
+    float Y1x = sqrt(3.0 / 3.14159265) * 0.5;
+    float Y1y = Y1x;
+    float Y1z = Y1x;
+
+    vec4 L1 = vec4(Y00, Y1x, Y1y, Y1z);
+
+    vec3 view_direction = calcDirection(vary_frag);
+    vec3 sun_direction  = normalize(sun_dir);
+    vec3 cam_pos        = vec3(0, 0, 6360);
+
+    vec3 transmittance;
+    vec3 radiance = GetSkyLuminance(cam_pos, view_direction, 0.0f, sun_direction, transmittance);
+
+    vec3 color = vec3(1.0) - exp(-radiance * 0.0001);
+
+    color = pow(color, vec3(1.0/2.2));
+
+    vec4 coeffs[3];
+    coeffs[0] = vec4(0);
+    coeffs[1] = vec4(0);
+    coeffs[2] = vec4(0);
+
+    projectToL1(view_direction, color.rgb, L1, coeffs);
+
+    frag_data[0] = coeffs[0];
+    frag_data[1] = coeffs[1];
+    frag_data[2] = coeffs[2];
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl b/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b466883dc7e23ea80bf0f740f698f3b80a39c024
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/genSkyShV.glsl
@@ -0,0 +1,37 @@
+/** 
+ * @file genSkyShV.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$
+ */
+ 
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_frag;
+
+void main()
+{
+    // pass through untransformed fullscreen pos
+	gl_Position = vec4(position.xyz, 1.0);
+    vary_frag = texcoord0;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl b/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..33c5667cae9fe4203a173727e56809c71d8d525a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/indirect.glsl
@@ -0,0 +1,44 @@
+/** 
+ * @file class3/deferred/indirect.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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]*/
+
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+vec3 GetIndirect(vec3 norm)
+{
+    vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
+    vec4 l1r = texture2D(sh_input_r, vec2(0,0));
+    vec4 l1g = texture2D(sh_input_g, vec2(0,0));
+    vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+    vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
+                         dot(l1g, l1tap * vec4(1, norm.xyz)),
+                         dot(l1b, l1tap * vec4(1, norm.xyz)));
+    indirect = clamp(indirect, vec3(0), vec3(1.0));
+    return indirect;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..8bb3f07fc6450457928e4123bf57525fb70a9d9d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl
@@ -0,0 +1,117 @@
+/** 
+ * @file lightInfo.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$
+ */
+
+struct DirectionalLightInfo
+{
+    vec4 pos;
+    float depth;
+    vec4 normal;
+    vec3 normalizedLightDirection;
+    vec3 normalizedToLight;
+    float lightIntensity;
+    vec3 lightDiffuseColor;
+    float specExponent;
+    float shadow;
+};
+
+struct SpotLightInfo
+{
+    vec4 pos;
+    float depth;
+    vec4 normal;
+    vec3 normalizedLightDirection;
+    vec3 normalizedToLight;
+    float lightIntensity;
+    float attenuation;
+    float distanceToLight;
+    vec3 lightDiffuseColor;
+    float innerHalfAngleCos;
+    float outerHalfAngleCos;
+    float spotExponent;
+    float specExponent;
+    float shadow;
+};
+
+struct PointLightInfo
+{
+    vec4 pos;
+    float depth;
+    vec4 normal;
+    vec3 normalizedToLight;
+    float lightIntensity;
+    float attenuation;
+    float distanceToLight;
+    vec3 lightDiffuseColor;
+    float lightRadius;
+    float specExponent;
+    vec3 worldspaceLightDirection;
+    float shadow;
+};
+
+float attenuate(float attenuationSelection, float distanceToLight)
+{
+// LLRENDER_REVIEW
+// sh/could eventually consume attenuation func defined in texture
+    return (attenuationSelection == 0.0f) ? 1.0f : // none
+           (attenuationSelection <  1.0f) ? (1.0f / distanceToLight) : // linear atten 
+           (attenuationSelection <  2.0f) ? (1.0f / (distanceToLight*distanceToLight)) // quadratic atten
+										  : (1.0f / (distanceToLight*distanceToLight*distanceToLight));	// cubic atten    
+}
+
+
+vec3 lightDirectional(struct DirectionalLightInfo dli)
+{
+    float lightIntensity = dli.lightIntensity;
+	lightIntensity *= dot(dli.normal.xyz, dli.normalizedLightDirection);
+    //lightIntensity *= directionalShadowSample(vec4(dli.pos.xyz, 1.0f), dli.depth, dli.directionalShadowMap, dli.directionalShadowMatrix);
+	return lightIntensity * dli.lightDiffuseColor;
+}
+
+
+vec3 lightSpot(struct SpotLightInfo sli)    
+{
+	float penumbraRange = (sli.outerHalfAngleCos - sli.innerHalfAngleCos);
+    float coneAngleCos = max(dot(sli.normalizedLightDirection, sli.normalizedToLight), 0.0);
+	float coneAttenFactor = (coneAngleCos <= sli.outerHalfAngleCos) ? 1.0f : pow(smoothstep(1,0, sli.outerHalfAngleCos / penumbraRange), sli.spotExponent);
+    float distanceAttenuation = attenuate(sli.attenuation, sli.distanceToLight);
+    float lightIntensity = sli.lightIntensity;
+    lightIntensity *= distanceAttenuation;
+	lightIntensity *= max(dot(sli.normal.xyz, sli.normalizedLightDirection), 0.0);
+	lightIntensity *= coneAttenFactor;
+    lightIntensity *= sli.shadow;
+	return lightIntensity * sli.lightDiffuseColor;
+}
+
+vec3 lightPoint(struct PointLightInfo pli)
+{
+    float padRadius = pli.lightRadius * 0.1; // distance for which to perform smoothed dropoff past light radius
+	float distanceAttenuation =	attenuate(pli.attenuation, pli.distanceToLight);
+    float lightIntensity = pli.lightIntensity;
+    lightIntensity*= distanceAttenuation;    
+	lightIntensity *= clamp((padRadius - pli.distanceToLight + pli.lightRadius) / padRadius, 0.0, 1.0);
+    lightIntensity *= pli.shadow;
+    lightIntensity *= max(dot(pli.normal.xyz, pli.normalizedToLight), 0.0);
+	return lightIntensity * pli.lightDiffuseColor;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9d62b9d1804c3aee451874c7e000b70f2ab87e73
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/multiSpotLightF.glsl
@@ -0,0 +1,291 @@
+/** 
+ * @file multiSpotLightF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D projectionMap;
+uniform sampler2D lightFunc;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+uniform vec3 center;
+uniform float size;
+uniform vec3 color;
+uniform float falloff;
+
+VARYING vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec3 getNorm(vec2 pos_screen);
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
+    
+    d *= min(1, d * (proj_lod - lod));
+    
+    float edge = 0.25*det;
+    
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
+    
+    float edge = 0.25*det;
+        
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+
+    vec2 dist = tc-vec2(0.5);
+    
+    float d = dot(dist,dist);
+        
+    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+    
+    return ret;
+}
+
+
+vec4 getPosition(vec2 pos_screen);
+
+void main() 
+{
+    vec4 frag = vary_fragcoord;
+    frag.xyz /= frag.w;
+    frag.xyz = frag.xyz*0.5+0.5;
+    frag.xy *= screen_res;
+    
+    vec3 pos = getPosition(frag.xy).xyz;
+    vec3 lv = center.xyz-pos.xyz;
+    float dist = length(lv);
+    dist /= size;
+    if (dist > 1.0)
+    {
+        discard;
+    }
+    
+    float shadow = 1.0;
+    
+    if (proj_shadow_idx >= 0)
+    {
+        vec4 shd = texture2DRect(lightMap, frag.xy);
+        shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
+        shadow += shadow_fade;
+        shadow = clamp(shadow, 0.0, 1.0);        
+    }
+    
+    vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+    
+    float envIntensity = norm.z;
+
+    norm = getNorm(frag.xy);
+    
+    norm = normalize(norm);
+    float l_dist = -dot(lv, proj_n);
+    
+    vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+    if (proj_tc.z < 0.0)
+    {
+        discard;
+    }
+    
+    proj_tc.xyz /= proj_tc.w;
+    
+    float fa = (falloff*0.5)+1.0;
+    float dist_atten = min(1.0-(dist-1.0*(1.0-fa))/fa, 1.0);
+    dist_atten *= dist_atten;
+    dist_atten *= 2.0;
+    if (dist_atten <= 0.0)
+    {
+        discard;
+    }
+    
+    lv = proj_origin-pos.xyz;
+    lv = normalize(lv);
+    float da = dot(norm, lv);
+
+    vec3 col = vec3(0,0,0);
+        
+    vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
+    
+    vec4 spec = texture2DRect(specularRect, frag.xy);
+
+    vec3 dlit = vec3(0, 0, 0);
+
+    float noise = texture2D(noiseMap, frag.xy/128.0).b;
+    if (proj_tc.z > 0.0 &&
+        proj_tc.x < 1.0 &&
+        proj_tc.y < 1.0 &&
+        proj_tc.x > 0.0 &&
+        proj_tc.y > 0.0)
+    {
+        float amb_da = proj_ambiance;
+        float lit = 0.0;
+
+        if (da > 0.0)
+        {
+            lit = da * dist_atten * noise;
+
+            float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+            float lod = diff * proj_lod;
+            
+            vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+        
+            dlit = color.rgb * plcol.rgb * plcol.a;
+            
+            col = dlit*lit*diff_tex*shadow;
+            amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+        }
+        
+        //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+        vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+                            
+        amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
+                
+        amb_da *= dist_atten * noise;
+            
+        amb_da = min(amb_da, 1.0-lit);
+            
+        col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+    }
+    
+
+    if (spec.a > 0.0)
+    {
+        vec3 npos = -normalize(pos);
+        dlit *= 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 += dlit*scol*spec.rgb*shadow;
+            //col += spec.rgb;
+        }
+    }   
+
+    if (envIntensity > 0.0)
+    {
+        vec3 ref = reflect(normalize(pos), norm);
+        
+        //project from point pos in direction ref to plane proj_p, proj_n
+        vec3 pdelta = proj_p-pos;
+        float ds = dot(ref, proj_n);
+        
+        if (ds < 0.0)
+        {
+            vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+            
+            vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+            if (stc.z > 0.0)
+            {
+                stc /= stc.w;
+                                
+                if (stc.x < 1.0 &&
+                    stc.y < 1.0 &&
+                    stc.x > 0.0 &&
+                    stc.y > 0.0)
+                {
+                    col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+                }
+            }
+        }
+    }
+
+    //not sure why, but this line prevents MATBUG-194
+    col = max(col, vec3(0.0));
+
+    col = scaleDownLight(col);
+
+    //output linear space color as gamma correction happens down stream
+    frag_color.rgb = col;   
+    frag_color.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl b/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..ca9ce3a2e1b818aca6e25d07a1b43f24094d4efa
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/pointShadowBlurF.glsl
@@ -0,0 +1,37 @@
+/** 
+ * @file pointShadowBlur.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$
+ */
+
+uniform samplerCube cube_map; 
+
+in vec3 to_vec;
+
+out vec4 fragColor;
+
+void main() 
+{
+	vec4 vcol = texture(cube_map, to_vec);
+	fragColor = vec4(vcol.rgb, 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..c8991f7a181adcc13efca7b69df099acce572d97
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shVisF.glsl
@@ -0,0 +1,73 @@
+/** 
+ * @file class3/deferred/shVisF.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$
+ */
+
+#ifdef DEFINE_GL_FRAGCOLOR
+    out vec4 frag_color;
+#else
+    #define frag_color gl_FragColor
+#endif
+
+/////////////////////////////////////////////////////////////////////////
+// Fragment shader for L1 SH debug rendering
+/////////////////////////////////////////////////////////////////////////
+
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+uniform mat3 inv_modelviewprojection;
+
+VARYING vec4 vary_pos;
+
+void main(void) 
+{
+    vec2 coord = vary_pos.xy + vec2(0.5,0.5);
+
+    coord.x *= (1.6/0.9);
+
+    if (dot(coord, coord) > 0.25)
+    {
+        discard;
+    }
+
+    vec4 n = vec4(coord*2.0, 0.0, 1);
+    //n.y = -n.y;
+    n.z = sqrt(max(1.0-n.x*n.x-n.y*n.y, 0.0));
+    //n.xyz = inv_modelviewprojection * n.xyz;
+
+    vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
+    vec4 l1r = texture2D(sh_input_r, vec2(0,0));
+    vec4 l1g = texture2D(sh_input_g, vec2(0,0));
+    vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+    vec3 indirect = vec3(
+                      dot(l1r, l1tap * n),
+                      dot(l1g, l1tap * n),
+                      dot(l1b, l1tap * n));
+
+    //indirect = pow(indirect, vec3(0.45));
+    indirect *= 3.0;
+
+	frag_color = vec4(indirect, 1.0);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..8f32dfde79d4f84e2fe38bb7c84cf3140a02b0da
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shVisV.glsl
@@ -0,0 +1,33 @@
+/** 
+ * @file class3/deferred/shVisV.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$
+ */
+ATTRIBUTE vec3 position;
+VARYING vec4 vary_pos;
+
+void main()
+{
+    // Output
+    vary_pos = vec4(position, 1);
+    gl_Position = vary_pos;
+}
diff --git a/indra/newview/llfloaterdeleteenvpreset.h b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl
similarity index 53%
rename from indra/newview/llfloaterdeleteenvpreset.h
rename to indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl
index 1211505273aff21acee891a96ac91f51cb563450..345c07a354e407f21ae05d01998b7966fa485974 100644
--- a/indra/newview/llfloaterdeleteenvpreset.h
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendF.glsl
@@ -1,6 +1,5 @@
 /** 
- * @file llfloaterdeleteenvpreset.h
- * @brief Floater to delete a water / sky / day cycle preset.
+ * @file shadowAlphaMaskF.glsl
  *
  * $LicenseInfo:firstyear=2011&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -24,39 +23,36 @@
  * $/LicenseInfo$
  */
 
-#ifndef LL_LLFLOATERDELETEENVPRESET_H
-#define LL_LLFLOATERDELETEENVPRESET_H
+/*[EXTRA_CODE_HERE]*/
 
-#include "llfloater.h"
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
 
-class LLComboBox;
+uniform sampler2D diffuseMap;
 
-class LLFloaterDeleteEnvPreset : public LLFloater
-{
-	LOG_CLASS(LLFloaterDeleteEnvPreset);
-
-public:
-	LLFloaterDeleteEnvPreset(const LLSD &key);
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
 
-	/*virtual*/	BOOL	postBuild();
-	/*virtual*/ void	onOpen(const LLSD& key);
+VARYING float pos_w;
 
-	void onBtnDelete();
-	void onBtnCancel();
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+VARYING vec3 pos;
 
-private:
-	void populatePresetsList();
-	void populateWaterPresetsList();
-	void populateSkyPresetsList();
-	void populateDayCyclesList();
+vec4 computeMoments(float depth, float a);
 
-	void postPopulate();
-
-	void onDeleteDayCycleConfirmation();
-	void onDeleteSkyPresetConfirmation();
-	void onDeleteWaterPresetConfirmation();
+void main() 
+{
+	float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
 
-	LLComboBox* mPresetCombo;
-};
+    frag_color = computeMoments(length(pos), float a);
 
-#endif // LL_LLFLOATERDELETEENVPRESET_H
+#if !defined(DEPTH_CLAMP)
+	gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..af1461c297c7c332d63c7be1c4f1fa5e030e8214
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaBlendV.glsl
@@ -0,0 +1,66 @@
+/** 
+ * @file shadowAlphaMaskV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING float target_pos_x;
+VARYING vec4 pos;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+	vec4 pos = modelview_projection_matrix * pre_pos;
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+	pos_w = pos.w;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+	vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..50f1ffd6266ba9c873856b72b1a5d835d03c7655
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskF.glsl
@@ -0,0 +1,74 @@
+/** 
+ * @file class3/deferred/shadowAlphaMaskF.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING float pos_w;
+
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+vec4 getPosition(vec2 screen_coord);
+vec4 computeMoments(float depth, float a);
+
+void main() 
+{
+    vec4 pos = getPosition(vary_texcoord0.xy);
+
+    float alpha = diffuseLookup(vary_texcoord0.xy).a * vertex_color.a;
+
+    if (alpha < 0.05) // treat as totally transparent
+    {
+        discard;
+    }
+
+    if (alpha < 0.88) // treat as semi-transparent
+    {
+        if (fract(0.5*floor(target_pos_x / pos_w )) < 0.25)
+        {
+            discard;
+        }
+    }
+
+    frag_color = computeMoments(length(pos.xyz), alpha);
+    
+#if !defined(DEPTH_CLAMP)
+    gl_FragDepth = max(pos_zd2/pos_w+0.5, 0.0);
+#endif
+
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6a646f5e9e95a5da561b61e3ec628879914cf8c1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowAlphaMaskV.glsl
@@ -0,0 +1,67 @@
+/** 
+ * @file class3/deferred/shadowAlphaMaskV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+uniform float shadow_target_width;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec4 diffuse_color;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+
+	pos = modelview_projection_matrix * pre_pos;
+
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	passTextureIndex();
+
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
+	vertex_color = diffuse_color;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..db8c75fb8ad4a6d1016e9a1864176b04a0697e2c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowCubeV.glsl
@@ -0,0 +1,50 @@
+/** 
+ * @file class3/deferred/shadowCubeV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+#if !defined(DEPTH_CLAMP)
+VARYING vec4 post_pos;
+#endif
+
+uniform vec3 box_center;
+uniform vec3 box_size;
+
+void main()
+{
+	//transform vertex
+	vec3 p = position*box_size+box_center;
+	vec4 pos = modelview_projection_matrix*vec4(p.xyz, 1.0);
+
+#if !defined(DEPTH_CLAMP)
+	post_pos = pos;
+
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..3350267130b69b9ae99d0ad21e6e081ed31e1f07
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowF.glsl
@@ -0,0 +1,49 @@
+/** 
+ * @file class3/deferred/shadowF.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2D diffuseMap;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+
+vec4 computeMoments(float depth, float a);
+
+void main() 
+{
+    frag_color = computeMoments(length(pos), 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..2f69a353e869cc700d097ff80764e8a4e53ade2d
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowUtil.glsl
@@ -0,0 +1,157 @@
+/** 
+ * @file class3/deferred/shadowUtil.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$
+ */
+
+uniform sampler2D       shadowMap0;
+uniform sampler2D       shadowMap1;
+uniform sampler2D       shadowMap2;
+uniform sampler2D       shadowMap3;
+uniform sampler2D       shadowMap4;
+uniform sampler2D       shadowMap5;
+
+uniform vec3 sun_dir;
+uniform vec3 moon_dir;
+uniform vec2 shadow_res;
+uniform vec2 proj_shadow_res;
+uniform mat4 shadow_matrix[6];
+uniform vec4 shadow_clip;
+uniform float shadow_bias;
+
+uniform float spot_shadow_bias;
+uniform float spot_shadow_offset;
+
+float getDepth(vec2 screenpos);
+vec3 getNorm(vec2 screenpos);
+vec4 getPosition(vec2 pos_screen);
+
+float ReduceLightBleeding(float p_max, float Amount)
+{
+    return smoothstep(Amount, 1, p_max);
+}
+
+float ChebyshevUpperBound(vec2 m, float t, float min_v, float Amount)
+{
+    float p = (t <= m.x) ? 1.0 : 0.0;
+
+    float v = m.y - (m.x*m.x);
+    v = max(v, min_v);
+
+    float d = t - m.x;
+
+    float p_max = v / (v + d*d);
+
+    p_max = ReduceLightBleeding(p_max, Amount);
+
+    return max(p, p_max);
+}
+
+vec4 computeMoments(float depth, float a)
+{
+    float m1 = depth;
+    float dx = dFdx(depth);
+    float dy = dFdy(depth);
+    float m2 = m1*m1 + 0.25 * a * (dx*dx + dy*dy);
+    return vec4(m1, m2, a, max(dx, dy));
+}
+
+float vsmDirectionalSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
+{
+    vec4 lpos = shadowMatrix * stc;
+    vec4 moments = texture2D(shadowMap, lpos.xy);
+    return ChebyshevUpperBound(moments.rg, depth - shadow_bias * 256.0f, 0.125, 0.9);
+}
+
+float vsmSpotSample(vec4 stc, float depth, sampler2D shadowMap, mat4 shadowMatrix)
+{
+    vec4 lpos = shadowMatrix * stc;
+    vec4 moments = texture2D(shadowMap, lpos.xy);
+    lpos.xyz /= lpos.w;
+    lpos.xy *= 0.5;
+    lpos.xy += 0.5;
+    return ChebyshevUpperBound(moments.rg, depth - spot_shadow_bias * 16.0f, 0.125, 0.9);
+}
+
+#if VSM_POINT_SHADOWS
+float vsmPointSample(float lightDistance, vec3 lightDirection, samplerCube shadow_cube_map)
+{
+    vec4 moments = textureCube(shadow_cube_map, light_direction);
+    return ChebyshevUpperBound(moments.rg, light_distance, 0.01, 0.25);
+}
+#endif
+
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen)
+{
+	if (pos.z < -shadow_clip.w)
+    {
+        discard;
+    }
+
+    float depth = getDepth(pos_screen);
+
+    vec4 spos       = vec4(pos,1.0);
+    vec4 near_split = shadow_clip*-0.75;
+    vec4 far_split  = shadow_clip*-1.25;
+
+    float shadow = 0.0f;
+    float weight = 1.0;
+
+    if (spos.z < near_split.z)
+    {
+        shadow += vsmDirectionalSample(spos, depth, shadowMap3, shadow_matrix[3]);
+        weight += 1.0f;
+    }
+    if (spos.z < near_split.y)
+    {
+        shadow += vsmDirectionalSample(spos, depth, shadowMap2, shadow_matrix[2]);
+        weight += 1.0f;
+    }
+    if (spos.z < near_split.x)
+    {
+        shadow += vsmDirectionalSample(spos, depth, shadowMap1, shadow_matrix[1]);
+        weight += 1.0f;
+    }
+    if (spos.z > far_split.x)
+    {
+        shadow += vsmDirectionalSample(spos, depth, shadowMap0, shadow_matrix[0]);
+        weight += 1.0f;
+    }
+
+    shadow /= weight;
+
+    return shadow;
+}
+
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen)
+{
+	if (pos.z < -shadow_clip.w)
+    {
+        discard;
+    }
+
+    float depth = getDepth(pos_screen);
+
+    pos += norm * spot_shadow_offset;
+    return vsmSpotSample(vec4(pos, 1.0), depth, (index == 0) ? shadowMap4 : shadowMap5, shadow_matrix[4 + index]);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6577fe0ecfe61f2adea98a0bc3bbff9ac7386595
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/shadowV.glsl
@@ -0,0 +1,62 @@
+/** 
+ * @file class3/deferred/shadowV.glsl
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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;
+uniform float shadow_target_width;
+uniform mat4 texture_matrix0;
+
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+#if !defined(DEPTH_CLAMP)
+VARYING float pos_zd2;
+#endif
+
+VARYING vec4 pos;
+VARYING float target_pos_x;
+VARYING vec4 vertex_color;
+VARYING vec2 vary_texcoord0;
+
+void passTextureIndex();
+
+void main()
+{
+	//transform vertex
+	vec4 pre_pos = vec4(position.xyz, 1.0);
+
+	pos = modelview_projection_matrix * pre_pos;
+
+	target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+#if !defined(DEPTH_CLAMP)
+	pos_zd2 = pos.z * 0.5;
+	
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+	gl_Position = pos;
+#endif
+	
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..6de01cb667c3e6bc9f55a1d96493a5d84ea51420
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
@@ -0,0 +1,111 @@
+/** 
+ * @file class3/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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+VARYING vec2 vary_frag;
+
+uniform vec3 camPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+uniform float far_z;
+uniform mat4 inv_proj;
+uniform mat4 inv_modelview;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+uniform sampler2D rainbow_map;
+uniform sampler2D halo_map;
+
+uniform float moisture_level;
+uniform float droplet_radius;
+uniform float ice_level;
+
+vec3 GetSolarLuminance();
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
+vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
+
+vec3 ColorFromRadiance(vec3 radiance);
+vec3 rainbow(float d)
+{
+   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)
+{
+   float v = sqrt(max(0, 1 - (d*d)));
+   return texture2D(halo_map, vec2(0, v)).rgb * ice_level;
+}
+
+void main()
+{
+    vec3 pos      = vec3((vary_frag * 2.0) - vec2(1.0, 1.0f), 1.0);
+    vec4 view_pos = (inv_proj * vec4(pos, 1.0f));
+
+    view_pos /= view_pos.w;
+
+    vec3 view_ray = (inv_modelview * vec4(view_pos.xyz, 0.0f)).xyz + camPosLocal;
+
+    vec3 view_direction = normalize(view_ray);
+    vec3 sun_direction  = normalize(sun_dir);
+    vec3 earth_center   = vec3(0, 0, -6360.0f);
+    vec3 camPos = (camPosLocal / 1000.0f) - earth_center;
+
+    vec3 transmittance;
+    vec3 radiance_sun  = GetSkyLuminance(camPos, view_direction, 0.0f, sun_direction, transmittance);
+    vec3 solar_luminance = GetSolarLuminance();
+
+    // If the view ray intersects the Sun, add the Sun radiance.
+    float s = dot(view_direction, sun_direction);
+
+    // cheesy solar disc...
+    if (s >= (sun_size * 0.999))
+    {
+        radiance_sun += pow(smoothstep(0.0, 1.3, (s - (sun_size * 0.9))), 2.0) * solar_luminance * transmittance;
+    }
+    s = smoothstep(0.9, 1.0, s) * 16.0f;
+
+    vec3 color = ColorFromRadiance(radiance_sun);
+
+    float optic_d = dot(view_direction, sun_direction);
+    vec3 halo_22 = halo22(optic_d);
+
+    color.rgb += rainbow(optic_d) * optic_d;
+    color.rgb += halo_22;
+
+    color = pow(color, vec3(1.0/2.2));
+
+    frag_data[0] = vec4(color, 1.0 + s);
+    frag_data[1] = vec4(0.0);
+    frag_data[2] = vec4(0.0, 1.0, 0.0, 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..2eb222ada4aab9b8b68138b1dc876f2d02cf279a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/skyV.glsl
@@ -0,0 +1,37 @@
+/** 
+ * @file class3/deferred/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$
+ */
+ 
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec2 vary_frag;
+
+void main()
+{
+    // pass through untransformed fullscreen pos at back of frustum for proper sky depth testing
+	gl_Position = vec4(position.xy, 1.0f, 1.0);
+    vary_frag = texcoord0;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..7ed9e7b4fc60068a51faaa59498d353138b919f1
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -0,0 +1,177 @@
+/** 
+ * @file class3/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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect normalMap;
+uniform sampler2DRect lightMap;
+uniform sampler2DRect depthMap;
+uniform sampler2D     lightFunc;
+
+uniform samplerCube environmentMap;
+uniform float blur_size;
+uniform float blur_fidelity;
+
+// Inputs
+uniform vec4 morphFactor;
+uniform vec3 camPosLocal;
+uniform float cloud_shadow;
+uniform float max_y;
+uniform vec4 glow;
+uniform mat3 env_mat;
+uniform vec4 shadow_clip;
+
+uniform vec3 sun_dir;
+VARYING vec2 vary_fragcoord;
+
+uniform mat4 inv_proj;
+uniform mat4 inv_modelview;
+
+uniform vec2 screen_res;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D single_mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+
+uniform sampler2D sh_input_r;
+uniform sampler2D sh_input_g;
+uniform sampler2D sh_input_b;
+
+vec3 GetSunAndSkyIrradiance(vec3 camPos, vec3 norm, vec3 dir, out vec3 sky_irradiance);
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 dir, out vec3 transmittance);
+vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir, out vec3 transmittance);
+
+vec3 ColorFromRadiance(vec3 radiance);
+vec4 getPositionWithDepth(vec2 pos_screen, float depth);
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
+
+#ifdef WATER_FOG
+vec4 applyWaterFogView(vec3 pos, vec4 color);
+#endif
+
+void main() 
+{
+    vec2 tc = vary_fragcoord.xy;
+    float depth = texture2DRect(depthMap, tc.xy).r;
+    vec3 pos = getPositionWithDepth(tc, depth).xyz;
+    vec4 norm = texture2DRect(normalMap, tc);
+    float envIntensity = norm.z;
+    norm.xyz = getNorm(tc);
+
+    float da = max(dot(norm.xyz, sun_dir.xyz), 0.0);
+
+    vec4 diffuse = texture2DRect(diffuseRect, tc); // sRGB
+    diffuse.rgb = srgb_to_linear(diffuse.rgb);
+
+    vec3 col;
+    float bloom = 0.0;
+    {
+        vec3 camPos = (camPosLocal / 1000.0f) + vec3(0, 0, 6360.0f);
+
+        vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
+        
+        vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
+
+        float scol = max(scol_ambocc.r, diffuse.a); 
+
+        float ambocc = scol_ambocc.g;
+
+        vec4 l1tap = vec4(1.0/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265), sqrt(3)/sqrt(4*3.14159265));
+        vec4 l1r = texture2D(sh_input_r, vec2(0,0));
+        vec4 l1g = texture2D(sh_input_g, vec2(0,0));
+        vec4 l1b = texture2D(sh_input_b, vec2(0,0));
+
+        vec3 indirect = vec3(dot(l1r, l1tap * vec4(1, norm.xyz)),
+                             dot(l1g, l1tap * vec4(1, norm.xyz)),
+                             dot(l1b, l1tap * vec4(1, norm.xyz)));
+
+        indirect = clamp(indirect, vec3(0), vec3(1.0));
+
+        vec3 transmittance;
+        vec3 sky_irradiance;
+        vec3 sun_irradiance = GetSunAndSkyIrradiance(camPos, norm.xyz, sun_dir, sky_irradiance);
+        vec3 inscatter = GetSkyLuminanceToPoint(camPos, (pos / 1000.f) + vec3(0, 0, 6360.0f), scol, sun_dir, transmittance);
+
+        vec3 radiance   = scol * (sun_irradiance + sky_irradiance) + inscatter;
+        vec3 atmo_color = ColorFromRadiance(radiance);
+
+        col = atmo_color + indirect;
+        col *= transmittance;
+        col *= diffuse.rgb;
+
+        vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
+
+        if (spec.a > 0.0) // specular reflection
+        {
+            // the old infinite-sky shiny reflection
+            //
+            float sa = dot(refnormpersp, sun_dir.xyz);
+            vec3 dumbshiny = scol * texture2D(lightFunc, vec2(sa, spec.a)).r * atmo_color;
+            
+            // add the two types of shiny together
+            vec3 spec_contrib = dumbshiny * spec.rgb * 0.25;
+            bloom = dot(spec_contrib, spec_contrib);
+            col += spec_contrib;
+        }
+
+        col = mix(col, diffuse.rgb, diffuse.a);
+
+        if (envIntensity > 0.0)
+        { //add environmentmap
+            vec3 env_vec = env_mat * refnormpersp;
+            vec3 sun_direction  = (inv_modelview * vec4(sun_dir, 1.0)).xyz;
+            vec3 radiance_sun  = GetSkyLuminance(camPos, env_vec, 0.0f, sun_direction, transmittance);
+            vec3 refcol = ColorFromRadiance(radiance_sun);
+            col = mix(col.rgb, refcol, envIntensity);
+        }
+                        
+        /*if (norm.w < 0.5)
+        {
+            col = scaleSoftClipFrag(col);
+        }*/
+
+        #ifdef WATER_FOG
+            vec4 fogged = applyWaterFogView(pos,vec4(col, bloom));
+            col = fogged.rgb;
+            bloom = fogged.a;
+        #endif
+    }
+
+    //output linear since gamma correction happens down stream
+    frag_color.rgb = col;
+    frag_color.a = bloom;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..9d872b8df81951912ebbd5091af838f18d9b6cf6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl
@@ -0,0 +1,38 @@
+/** 
+ * @file class3/deferred/softenLightV.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$
+ */
+ATTRIBUTE vec3 position;
+
+VARYING vec2 vary_fragcoord;
+
+uniform mat4 modelview_projection_matrix;
+uniform vec2 screen_res;
+
+void main()
+{
+	//transform vertex
+	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	gl_Position = pos; 
+	vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..56b0f4e5cecedc5f349c6f0f03afdadb472f0930
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/spotLightF.glsl
@@ -0,0 +1,287 @@
+/** 
+ * @file spotLightF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+#extension GL_ARB_shader_texture_lod : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect specularRect;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform samplerCube environmentMap;
+uniform sampler2DRect lightMap;
+uniform sampler2D noiseMap;
+uniform sampler2D projectionMap;
+uniform sampler2D lightFunc;
+
+uniform mat4 proj_mat; //screen space to light space
+uniform float proj_near; //near clip for projection
+uniform vec3 proj_p; //plane projection is emitting from (in screen space)
+uniform vec3 proj_n;
+uniform float proj_focus; //distance from plane to begin blurring
+uniform float proj_lod;  //(number of mips in proj map)
+uniform float proj_range; //range between near clip and far clip plane of projection
+uniform float proj_ambient_lod;
+uniform float proj_ambiance;
+uniform float near_clip;
+uniform float far_clip;
+
+uniform vec3 proj_origin; //origin of projection to be used for angular attenuation
+uniform float sun_wash;
+uniform int proj_shadow_idx;
+uniform float shadow_fade;
+
+uniform float size;
+uniform vec3 color;
+uniform float falloff;
+
+VARYING vec3 trans_center;
+VARYING vec4 vary_fragcoord;
+uniform vec2 screen_res;
+
+uniform mat4 inv_proj;
+
+vec3 getNorm(vec2 pos_screen);
+
+vec4 texture2DLodSpecular(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
+    
+    d *= min(1, d * (proj_lod - lod));
+    
+    float edge = 0.25*det;
+    
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
+}
+
+vec4 texture2DLodDiffuse(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    
+    vec2 dist = vec2(0.5) - abs(tc-vec2(0.5));
+    
+    float det = min(lod/(proj_lod*0.5), 1.0);
+    
+    float d = min(dist.x, dist.y);
+    
+    float edge = 0.25*det;
+        
+    ret *= clamp(d/edge, 0.0, 1.0);
+    
+    return ret;
+}
+
+vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod)
+{
+    vec4 ret = texture2DLod(projectionMap, tc, lod);
+    
+    vec2 dist = tc-vec2(0.5);
+    
+    float d = dot(dist,dist);
+        
+    ret *= min(clamp((0.25-d)/0.25, 0.0, 1.0), 1.0);
+    
+    return ret;
+}
+
+
+vec4 getPosition(vec2 pos_screen);
+
+void main() 
+{
+    vec4 frag = vary_fragcoord;
+    frag.xyz /= frag.w;
+    frag.xyz = frag.xyz*0.5+0.5;
+    frag.xy *= screen_res;
+    
+    vec3 pos = getPosition(frag.xy).xyz;
+    vec3 lv = trans_center.xyz-pos.xyz;
+    float dist = length(lv);
+    dist /= size;
+    if (dist > 1.0)
+    {
+        discard;
+    }
+    
+    float shadow = 1.0;
+    
+    if (proj_shadow_idx >= 0)
+    {
+        vec4 shd = texture2DRect(lightMap, frag.xy);
+        shadow = (proj_shadow_idx == 0) ? shd.b : shd.a;
+        shadow += shadow_fade;
+        shadow = clamp(shadow, 0.0, 1.0);
+    }
+    
+    vec3 norm = texture2DRect(normalMap, frag.xy).xyz;
+    float envIntensity = norm.z;
+    norm = getNorm(frag.xy);
+    
+    norm = normalize(norm);
+    float l_dist = -dot(lv, proj_n);
+    
+    vec4 proj_tc = (proj_mat * vec4(pos.xyz, 1.0));
+    if (proj_tc.z < 0.0)
+    {
+        discard;
+    }
+    
+    proj_tc.xyz /= proj_tc.w;
+    
+    float fa = (falloff*0.5) + 1.0;
+    float dist_atten = min(1.0 - (dist - 1.0 * (1.0 - fa)) / fa, 1.0);
+    dist_atten *= dist_atten;
+    dist_atten *= 2.0;
+
+    if (dist_atten <= 0.0)
+    {
+        discard;
+    }
+    
+    lv = proj_origin-pos.xyz;
+    lv = normalize(lv);
+    float da = dot(norm, lv);
+        
+    vec3 col = vec3(0,0,0);
+        
+    vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
+        
+    vec4 spec = texture2DRect(specularRect, frag.xy);
+
+    vec3 dlit = vec3(0, 0, 0);
+
+    float noise = texture2D(noiseMap, frag.xy/128.0).b;
+    if (proj_tc.z > 0.0 &&
+        proj_tc.x < 1.0 &&
+        proj_tc.y < 1.0 &&
+        proj_tc.x > 0.0 &&
+        proj_tc.y > 0.0)
+    {
+        float amb_da = proj_ambiance;
+        float lit = 0.0;
+        
+        if (da > 0.0)
+        {
+            lit = da * dist_atten * noise;
+
+            float diff = clamp((l_dist-proj_focus)/proj_range, 0.0, 1.0);
+            float lod = diff * proj_lod;
+            
+            vec4 plcol = texture2DLodDiffuse(projectionMap, proj_tc.xy, lod);
+        
+            dlit = color.rgb * plcol.rgb * plcol.a;
+            
+            col = dlit*lit*diff_tex*shadow;
+            amb_da += (da*0.5)*(1.0-shadow)*proj_ambiance;
+        }
+        
+        //float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
+        vec4 amb_plcol = texture2DLodAmbient(projectionMap, proj_tc.xy, proj_lod);
+                            
+        amb_da += (da*da*0.5+0.5)*(1.0-shadow)*proj_ambiance;
+                
+        amb_da *= dist_atten * noise;
+            
+        amb_da = min(amb_da, 1.0-lit);
+            
+        col += amb_da*color.rgb*diff_tex.rgb*amb_plcol.rgb*amb_plcol.a;
+    }
+    
+
+    if (spec.a > 0.0)
+    {
+        dlit *= min(da*6.0, 1.0) * dist_atten;
+        vec3 npos = -normalize(pos);
+
+        //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 += dlit*scol*spec.rgb*shadow;
+        }
+    }   
+    
+
+    if (envIntensity > 0.0)
+    {
+        vec3 ref = reflect(normalize(pos), norm);
+        
+        //project from point pos in direction ref to plane proj_p, proj_n
+        vec3 pdelta = proj_p-pos;
+        float ds = dot(ref, proj_n);
+        
+        if (ds < 0.0)
+        {
+            vec3 pfinal = pos + ref * dot(pdelta, proj_n)/ds;
+            
+            vec4 stc = (proj_mat * vec4(pfinal.xyz, 1.0));
+
+            if (stc.z > 0.0)
+            {
+                stc /= stc.w;
+                                
+                if (stc.x < 1.0 &&
+                    stc.y < 1.0 &&
+                    stc.x > 0.0 &&
+                    stc.y > 0.0)
+                {
+                    col += color.rgb * texture2DLodSpecular(projectionMap, stc.xy, (1 - spec.a) * (proj_lod * 0.6)).rgb * shadow * envIntensity;
+                }
+            }
+        }
+    }
+    
+    //not sure why, but this line prevents MATBUG-194
+    col = max(col, vec3(0.0));
+
+    frag_color.rgb = col;   
+    frag_color.a = 0.0;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..112b498c9029878cbf8755dcf7bd9c4f8191c8a0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightF.glsl
@@ -0,0 +1,57 @@
+/** 
+ * @file class3\deferred\sunLightF.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$
+ */
+
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+//class 2, shadows, no SSAO
+
+// Inputs
+VARYING vec2 vary_fragcoord;
+
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
+
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen); 
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen); 
+
+void main() 
+{
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec4 pos = getPosition(pos_screen);
+	vec3 norm = getNorm(pos_screen);
+
+	frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
+	frag_color.g = 1.0f;
+    frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
+    frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..342a2ff3ede256469bdc4f2688317245e9f2904c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightSSAOF.glsl
@@ -0,0 +1,61 @@
+/** 
+ * @file class3\deferred\sunLightSSAOF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+//class 2 -- shadows and SSAO
+
+// Inputs
+VARYING vec2 vary_fragcoord;
+
+uniform vec3 sun_dir;
+
+vec4 getPosition(vec2 pos_screen);
+vec3 getNorm(vec2 pos_screen);
+
+float sampleDirectionalShadow(vec3 pos, vec3 norm, vec2 pos_screen);
+float sampleSpotShadow(vec3 pos, vec3 norm, int index, vec2 pos_screen);
+
+//calculate decreases in ambient lighting when crowded out (SSAO)
+float calcAmbientOcclusion(vec4 pos, vec3 norm, vec2 pos_screen);
+
+void main() 
+{
+	vec2 pos_screen = vary_fragcoord.xy;
+	vec4 pos        = getPosition(pos_screen);
+	vec3 norm       = getNorm(pos_screen);
+
+	frag_color.r = sampleDirectionalShadow(pos.xyz, norm, pos_screen);
+    frag_color.b = calcAmbientOcclusion(pos, norm, pos_screen);
+    frag_color.b = sampleSpotShadow(pos.xyz, norm, 0, pos_screen);
+    frag_color.a = sampleSpotShadow(pos.xyz, norm, 1, pos_screen);
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..bc5eb5181d0317864c5982fc27b17366760462e6
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/sunLightV.glsl
@@ -0,0 +1,41 @@
+/** 
+ * @file sunLightV.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$
+ */
+
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+VARYING vec2 vary_fragcoord;
+
+uniform vec2 screen_res;
+
+void main()
+{
+	//transform vertex
+	vec4 pos = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	gl_Position = pos; 
+	
+	vary_fragcoord = (pos.xy * 0.5 + 0.5)*screen_res;	
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..41673d16694fa63f925fb69d89ba416692720a05
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeShadowF.glsl
@@ -0,0 +1,59 @@
+/** 
+ * @file treeShadowF.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$
+ */
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform float minimum_alpha;
+
+uniform sampler2D diffuseMap;
+
+VARYING vec4 pos;
+VARYING vec2 vary_texcoord0;
+
+vec4 computeMoments(float d, float a);
+
+void main() 
+{
+	float alpha = texture2D(diffuseMap, vary_texcoord0.xy).a;
+
+	if (alpha < minimum_alpha)
+	{
+		discard;
+	}
+
+    frag_color = computeMoments(length(pos), 1.0);
+
+#if !defined(DEPTH_CLAMP)
+	gl_FragDepth = max(pos.z/pos.w*0.5+0.5, 0.0);
+#endif
+
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..15e769ac10f97383074d1e8c613ece6f3e04cd12
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/treeShadowV.glsl
@@ -0,0 +1,43 @@
+/** 
+ * @file treeShadowV.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$
+ */
+
+uniform mat4 texture_matrix0;
+uniform mat4 modelview_projection_matrix;
+ 
+ATTRIBUTE vec3 position;
+ATTRIBUTE vec2 texcoord0;
+
+VARYING vec4 pos;
+VARYING vec2 vary_texcoord0;
+
+void main()
+{
+	//transform vertex
+	pos = modelview_projection_matrix*vec4(position.xyz, 1.0);
+
+	gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+	
+	vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..540226e672abd571b963f8fb685b2a5a21641bcb
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/underWaterF.glsl
@@ -0,0 +1,115 @@
+/**
+ * @file underWaterF.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]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+uniform sampler2D diffuseMap;
+uniform sampler2D bumpMap;   
+uniform sampler2D screenTex;
+uniform sampler2D refTex;
+uniform sampler2D screenDepth;
+
+uniform vec4 fogCol;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform vec2 fbScale;
+uniform float refScale;
+uniform float znear;
+uniform float zfar;
+uniform float kd;
+uniform vec4 waterPlane;
+uniform vec3 eyeVec;
+uniform vec4 waterFogColor;
+uniform float waterFogDensity;
+uniform float waterFogKS;
+uniform vec2 screenRes;
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+
+vec2 encode_normal(vec3 n);
+
+vec4 applyWaterFog(vec4 color, vec3 viewVec)
+{
+	//normalize view vector
+	vec3 view = normalize(viewVec);
+	float es = -view.z;
+
+	//find intersection point with water plane and eye vector
+	
+	//get eye depth
+	float e0 = max(-waterPlane.w, 0.0);
+	
+	//get object depth
+	float depth = length(viewVec);
+		
+	//get "thickness" of water
+	float l = max(depth, 0.1);
+
+	float kd = waterFogDensity;
+	float ks = waterFogKS;
+	vec4 kc = waterFogColor;
+	
+	float F = 0.98;
+	
+	float t1 = -kd * pow(F, ks * e0);
+	float t2 = kd + ks * es;
+	float t3 = pow(F, t2*l) - 1.0;
+	
+	float L = min(t1/t2*t3, 1.0);
+	
+	float D = pow(0.98, l*kd);
+	return color * D + kc * L;
+}
+
+void main() 
+{
+	vec4 color;
+	    
+	//get detail normals
+	vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+	vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+	vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;    
+	vec3 wavef = normalize(wave1+wave2+wave3);
+	
+	//figure out distortion vector (ripply)   
+	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+	distort = distort+wavef.xy*refScale;
+		
+	vec4 fb = texture2D(screenTex, distort);
+
+	frag_data[0] = vec4(fb.rgb, 1.0); // diffuse
+	frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
+	frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..c65cf48c673355e681336dc029b85bdec79f8b9c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/waterF.glsl
@@ -0,0 +1,174 @@
+/** 
+ * @file waterF.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$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#endif
+
+uniform sampler2D bumpMap;   
+uniform sampler2D bumpMap2;
+uniform float blend_factor;
+uniform sampler2D screenTex;
+uniform sampler2D refTex;
+
+uniform float sunAngle;
+uniform float sunAngle2;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform float refScale;
+uniform float kd;
+uniform vec2 screenRes;
+uniform vec3 normScale;
+uniform float fresnelScale;
+uniform float fresnelOffset;
+uniform float blurMultiplier;
+uniform vec2 screen_res;
+uniform mat4 norm_mat; //region space to screen space
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+VARYING vec4 vary_position;
+
+vec3 scaleSoftClip(vec3 c);
+vec2 encode_normal(vec3 n);
+
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+    //vec3 normal   = bump1.xyz * vec3( 2.0,  2.0, 2.0) - vec3(1.0, 1.0,  0.0);
+    //vec3 normal2  = bump2.xyz * vec3(-2.0, -2.0, 2.0) + vec3(1.0, 1.0, -1.0);
+    //vec3 n        = normalize(normal * dot(normal, normal2) - (normal2 * normal.z));
+    vec3 n = normalize(mix(bump1, bump2, blend_factor));
+    return n;
+}
+
+void main() 
+{
+	vec4 color;
+	float dist = length(view.xy);
+	
+	//normalize view vector
+	vec3 viewVec = normalize(view.xyz);
+	
+	//get wave normals
+	vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+	vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+	vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+	vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+	vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+	vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+	//get base fresnel components	
+	
+	vec3 df = vec3(
+					dot(viewVec, wave1),
+					dot(viewVec, (wave2 + wave3) * 0.5),
+					dot(viewVec, wave3)
+				 ) * fresnelScale + fresnelOffset;
+	df *= df;
+		    
+	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+	
+	float dist2 = dist;
+	dist = max(dist, 5.0);
+	
+	float dmod = sqrt(dist);
+	
+	vec2 dmod_scale = vec2(dmod*dmod, dmod);
+	
+	//get reflected color
+	vec2 refdistort1 = wave1.xy*normScale.x;
+	vec2 refvec1 = distort+refdistort1/dmod_scale;
+	vec4 refcol1 = texture2D(refTex, refvec1);
+	
+	vec2 refdistort2 = wave2.xy*normScale.y;
+	vec2 refvec2 = distort+refdistort2/dmod_scale;
+	vec4 refcol2 = texture2D(refTex, refvec2);
+	
+	vec2 refdistort3 = wave3.xy*normScale.z;
+	vec2 refvec3 = distort+refdistort3/dmod_scale;
+	vec4 refcol3 = texture2D(refTex, refvec3);
+
+	vec4 refcol = refcol1 + refcol2 + refcol3;
+	float df1 = df.x + df.y + df.z;
+	refcol *= df1 * 0.333;
+	
+	vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+	wavef.z *= max(-viewVec.z, 0.1);
+	wavef = normalize(wavef);
+	
+	float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
+	
+	vec2 refdistort4 = wavef.xy*0.125;
+	refdistort4.y -= abs(refdistort4.y);
+	vec2 refvec4 = distort+refdistort4/dmod;
+	float dweight = min(dist2*blurMultiplier, 1.0);
+	vec4 baseCol = texture2D(refTex, refvec4);
+
+	refcol = mix(baseCol*df2, refcol, dweight);
+
+	//get specular component
+	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+		
+	//harden specular
+	spec = pow(spec, 128.0);
+
+	//figure out distortion vector (ripply)   
+	vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+		
+	vec4 fb = texture2D(screenTex, distort2);
+	
+	//mix with reflection
+	// Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
+	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
+
+    color.rgb *= 2.0f;
+    color.rgb = scaleSoftClip(color.rgb);
+	
+	vec4 pos = vary_position;
+	
+	color.rgb += spec * specular;
+	color.a    = spec * sunAngle2;
+    
+	vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
+	
+	frag_data[0] = vec4(color.rgb, color); // diffuse
+	frag_data[1] = vec4(spec * specular, spec);		// speccolor, spec
+	frag_data[2] = vec4(encode_normal(wavef.xyz), 0.05, 0);// normalxy, 0, 0
+}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..02000d90ca4740dd8da18718713d724de169d72c
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/deferred/waterV.glsl
@@ -0,0 +1,95 @@
+/** 
+ * @file waterV.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$
+ */
+
+uniform mat4 modelview_matrix;
+uniform mat4 modelview_projection_matrix;
+
+ATTRIBUTE vec3 position;
+
+
+uniform vec2 d1;
+uniform vec2 d2;
+uniform float time;
+uniform vec3 eyeVec;
+uniform float waterHeight;
+
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+
+VARYING vec4 vary_position;
+
+float wave(vec2 v, float t, float f, vec2 d, float s) 
+{
+   return (dot(d, v)*f + t*s)*f;
+}
+
+void main()
+{
+	//transform vertex
+	vec4 pos = vec4(position.xyz, 1.0);
+	mat4 modelViewProj = modelview_projection_matrix;
+	
+	vec4 oPosition;
+		    
+	//get view vector
+	vec3 oEyeVec;
+	oEyeVec.xyz = pos.xyz-eyeVec;
+		
+	float d = length(oEyeVec.xy);
+	float ld = min(d, 2560.0);
+	
+	pos.xy = eyeVec.xy + oEyeVec.xy/d*ld;
+	view.xyz = oEyeVec;
+		
+	d = clamp(ld/1536.0-0.5, 0.0, 1.0);	
+	d *= d;
+		
+	oPosition = vec4(position, 1.0);
+	oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
+	vary_position = modelview_matrix * oPosition;
+	oPosition = modelViewProj * oPosition;
+	
+	refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
+	
+	//get wave position parameter (create sweeping horizontal waves)
+	vec3 v = pos.xyz;
+	v.x += (cos(v.x*0.08/*+time*0.01*/)+sin(v.y*0.02))*6.0;
+	    
+	//push position for further horizon effect.
+	pos.xyz = oEyeVec.xyz*(waterHeight/oEyeVec.z);
+	pos.w = 1.0;
+	pos = modelview_matrix*pos;
+	
+	//pass wave parameters to pixel shader
+	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + d1 * time * 0.055;
+	//get two normal map (detail map) texture coordinates
+	littleWave.xy = (v.xy) * vec2(0.45, 0.9)   + d2 * time * 0.13;
+	littleWave.zw = (v.xy) * vec2(0.1, 0.2) + d1 * time * 0.1;
+	view.w = bigWave.y;
+	refCoord.w = bigWave.x;
+	
+	gl_Position = oPosition;
+}
diff --git a/indra/newview/app_settings/shaders/class3/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class3/lighting/lightV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..30ad493331f5e9b3faba61aecc93554f31b790f2
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/lighting/lightV.glsl
@@ -0,0 +1,43 @@
+/** 
+ * @file class3\lighting\lightV.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$
+ */
+ 
+
+
+// All lights, no specular highlights
+vec3 atmosAmbient();
+vec4 sumLights(vec3 pos, vec3 norm, vec4 color);
+float getAmbientClamp();
+
+vec4 calcLighting(vec3 pos, vec3 norm, vec4 color)
+{
+	vec4 c = sumLights(pos, norm, color);
+
+#if !defined(AMBIENT_KILL)
+    c.rgb += atmosAmbient() * color.rgb * getAmbientClamp();
+#endif
+ 
+    return c;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
index e043ac873ebbbcf0fd1bb81ab33b310ec3cee997..c1aee69c30e68bcb1fda1ddb3a9294456bb782f0 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsV.glsl
+ * @file class3\lighting\sumLightsSpecularV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -26,16 +26,16 @@
 float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da);
 vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol);
 
-vec3 atmosAmbient(vec3 light);
+vec3 atmosAmbient();
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 atmosGetDiffuseSunlightColor();
 vec3 scaleDownLight(vec3 light);
 
 uniform vec4 light_position[8];
-uniform vec3 light_attenuation[8]; 
+uniform vec4 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol)
+vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor)
 {
 	vec4 col = vec4(0.0, 0.0, 0.0, color.a);
 	
@@ -55,8 +55,8 @@ vec4 sumLightsSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor
 	col.rgb = scaleDownLight(col.rgb);
 						
 	// Add windlight lights
-	col.rgb += atmosAmbient(baseCol.rgb);
-	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz,atmosGetDiffuseSunlightColor()*baseCol.a, 1.0));
+	col.rgb += atmosAmbient();
+	col.rgb += atmosAffectDirectionalLight(calcDirectionalLightSpecular(specularSum, view, norm, light_position[0].xyz,atmosGetDiffuseSunlightColor(), 1.0));
 
 	col.rgb = min(col.rgb*color.rgb, 1.0);
 	specularColor.rgb = min(specularColor.rgb*specularSum.rgb, 1.0);
diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
index dadff40933a1dc067f024741e0c41ceed4d3a24d..4b663dd5b2ee751d20278bb7f87ba4214184d5d4 100644
--- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
+++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl
@@ -1,5 +1,5 @@
 /**
- * @file sumLightsV.glsl
+ * @file class3\lighting\sumLightsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
@@ -25,37 +25,40 @@
  
 
 float calcDirectionalLight(vec3 n, vec3 l);
-float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight);
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight);
 
-vec3 atmosAmbient(vec3 light);
 vec3 atmosAffectDirectionalLight(float lightIntensity);
 vec3 scaleDownLight(vec3 light);
-vec3 scaleUpLight(vec3 light);
 
 uniform vec4 light_position[8];
 uniform vec3 light_direction[8];
-uniform vec3 light_attenuation[8]; 
+uniform vec4 light_attenuation[8]; 
 uniform vec3 light_diffuse[8];
 
-vec4 sumLights(vec3 pos, vec3 norm, vec4 color, vec4 baseLight)
+vec4 sumLights(vec3 pos, vec3 norm, vec4 color)
 {
 	vec4 col = vec4(0.0, 0.0, 0.0, color.a);
 	
 	// Collect normal lights (need to be divided by two, as we later multiply by 2)
 	
 	// Collect normal lights
-	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z);
-	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z);
-	col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].z);
-	col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].z);
-	col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].z);
-	col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].z);
+	col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].y, light_attenuation[2].z);
+	col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].y, light_attenuation[3].z);
+	col.rgb += light_diffuse[4].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[4], light_direction[4], light_attenuation[4].x, light_attenuation[4].y, light_attenuation[4].z);
+	col.rgb += light_diffuse[5].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[5], light_direction[5], light_attenuation[5].x, light_attenuation[5].y, light_attenuation[5].z);
+	col.rgb += light_diffuse[6].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[6], light_direction[6], light_attenuation[6].x, light_attenuation[6].y, light_attenuation[6].z);
+	col.rgb += light_diffuse[7].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[7], light_direction[7], light_attenuation[7].x, light_attenuation[7].y, light_attenuation[7].z);
 	col.rgb += light_diffuse[1].rgb*calcDirectionalLight(norm, light_position[1].xyz);
-	col.rgb = scaleDownLight(col.rgb);
+    col.rgb = scaleDownLight(col.rgb);
+
+#if defined(LOCAL_LIGHT_KILL)
+    col.rgb = vec3(0);
+#endif
 
 	// Add windlight lights
+#if !defined(SUNLIGHT_KILL)
 	col.rgb += atmosAffectDirectionalLight(calcDirectionalLight(norm, light_position[0].xyz));
-	col.rgb += atmosAmbient(baseLight.rgb);
+#endif
 
 	col.rgb = min(col.rgb*color.rgb, 1.0);
 	
diff --git a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl b/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..c6ea3ec9d43a60a469cc0acf47c84ef5857539b9
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoF.glsl
@@ -0,0 +1,73 @@
+/** 
+ * @file class3\wl\advancedAtmoF.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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+in vec3 view_dir;
+
+uniform vec3 cameraPosLocal;
+uniform vec3 sun_dir;
+uniform float sun_size;
+
+uniform sampler2D transmittance_texture;
+uniform sampler3D scattering_texture;
+uniform sampler3D mie_scattering_texture;
+uniform sampler2D irradiance_texture;
+
+vec3 GetSolarLuminance();
+vec3 GetSkyLuminance(vec3 camPos, vec3 view_dir, float shadow_length, vec3 sun_dir, out vec3 transmittance);
+vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 sun_dir, out vec3 transmittance);
+vec3 GetSunAndSkyIlluminance(vec3 pos, vec3 norm, vec3 sun_dir, out vec3 sky_irradiance);
+
+void main()
+{
+    vec3 view_direction = normalize(view_dir);
+
+    vec3 camPos = cameraPosLocal;
+    vec3 transmittance;
+    vec3 sky_illum;
+    vec3 radiance = GetSkyLuminance(camPos, view_direction, 0.0f, sun_dir, transmittance);
+    vec3 radiance2 = GetSunAndSkyIlluminance(camPos, view_direction, sun_dir, sky_illum);
+
+    //radiance *= transmittance;
+
+    // If the view ray intersects the Sun, add the Sun radiance.
+    if (dot(view_direction, sun_dir) >= sun_size)
+    {
+        radiance = radiance + transmittance * GetSolarLuminance();
+    }
+
+    //vec3 color = vec3(1.0) - exp(-radiance);
+    //color = pow(color, vec3(1.0 / 2.2));
+
+    frag_color.rgb = radiance;
+ 
+    frag_color.a = 1.0;
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl b/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..65bb00b1f6ea8166ffb524adaaa16ccf309b2b99
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/windlight/advancedAtmoV.glsl
@@ -0,0 +1,43 @@
+/** 
+ * @file class3\wl\advancedAtmoV.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;
+
+// Inputs
+uniform vec3 camPosLocal;
+
+out vec3 view_dir;
+
+void main()
+{
+	// World / view / projection
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+
+	// this will be normalized in the frag shader...
+	view_dir = position.xyz - camPosLocal.xyz; 
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..2b70ba76dcf26dda524c5d50f16e791bd94114ec
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/windlight/atmosphericsF.glsl
@@ -0,0 +1,46 @@
+/** 
+ * @file class3\wl\atmosphericsF.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$
+ */
+
+vec3 getAdditiveColor();
+vec3 getAtmosAttenuation();
+vec3 scaleSoftClipFrag(vec3 light);
+
+uniform int no_atmo;
+
+vec3 atmosFragLighting(vec3 light, vec3 additive, vec3 atten)
+{
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+    light *= atten.r;
+    light += additive;
+    return light * 2.0;
+}
+
+vec3 atmosLighting(vec3 light)
+{
+    return atmosFragLighting(light, getAdditiveColor(), getAtmosAttenuation());
+}
diff --git a/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..b76192d73f63964b664ca847dc7b3e8f2d25fac0
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/windlight/atmosphericsV.glsl
@@ -0,0 +1,51 @@
+/**
+ * @file class3\wl\atmosphericsV.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$
+ */
+
+// VARYING param funcs
+void setSunlitColor(vec3 v);
+void setAmblitColor(vec3 v);
+void setAdditiveColor(vec3 v);
+void setAtmosAttenuation(vec3 v);
+void setPositionEye(vec3 v);
+
+vec3 getAdditiveColor();
+
+void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, out vec3 sunlit, out vec3 amblit, out vec3 additive, out vec3 atten, bool use_ao);
+
+void calcAtmospherics(vec3 inPositionEye) {
+
+    vec3 P = inPositionEye;
+    setPositionEye(P);
+    vec3 tmpsunlit = vec3(1);
+    vec3 tmpamblit = vec3(1);
+    vec3 tmpaddlit = vec3(1);
+    vec3 tmpattenlit = vec3(1);
+    calcAtmosphericVars(inPositionEye, vec3(0), 1, tmpsunlit, tmpamblit, tmpaddlit, tmpattenlit, true);
+    setSunlitColor(tmpsunlit);
+    setAmblitColor(tmpamblit);
+    setAdditiveColor(tmpaddlit);
+    setAtmosAttenuation(tmpattenlit);
+}
+
diff --git a/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..545a32a227453028da553139c9d1f17a348a997b
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/windlight/transportF.glsl
@@ -0,0 +1,68 @@
+/** 
+ * @file class3\wl\transportF.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$
+ */
+ 
+//////////////////////////////////////////////////////////
+// The fragment shader for the terrain atmospherics
+//////////////////////////////////////////////////////////
+
+vec3 getAdditiveColor();
+vec3 getAtmosAttenuation();
+
+uniform int no_atmo;
+
+vec3 atmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    if (no_atmo == 1)
+    {
+        return light;
+    }
+    // fullbright responds minimally to atmos scatter effects 
+    light *= min(15.0 * atten.r, 1.0);
+    light += (0.1 * additive);
+    return light * 2.0;
+}
+
+vec3 atmosTransport(vec3 light)
+{
+     return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
+}
+
+vec3 fullbrightAtmosTransportFrag(vec3 light, vec3 additive, vec3 atten)
+{
+    float brightness = dot(light.rgb, vec3(0.33333));
+    return vec3(1,0,1);
+    //return atmosTransportFrag(light * 0.5, additive * (brightness * 0.5 + 0.5), atten);
+}
+
+vec3 fullbrightAtmosTransport(vec3 light)
+{
+    return atmosTransportFrag(light, getAdditiveColor(), getAtmosAttenuation());
+}
+
+vec3 fullbrightShinyAtmosTransport(vec3 light)
+{
+    float brightness = dot(light.rgb, vec3(0.33333));
+    return atmosTransportFrag(light * 0.5, getAdditiveColor() * (brightness * brightness), getAtmosAttenuation());
+}
diff --git a/indra/newview/app_settings/shaders/shader_hierarchy.txt b/indra/newview/app_settings/shaders/shader_hierarchy.txt
index d8bbf69b389e84495dbf3a780ddee593e4338c06..8ef04d8e1fff9ca0f20e9e78624743d52dd03025 100644
--- a/indra/newview/app_settings/shaders/shader_hierarchy.txt
+++ b/indra/newview/app_settings/shaders/shader_hierarchy.txt
@@ -1,3 +1,9 @@
+Class 3 is highest quality / lowest  performance
+Class 2 is medium  quality / medium  performance
+Class 1 is lowest  quality / highest performance
+
+Shaders WILL fall back to "lower" classes for functionality.
+
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 avatar/avatarV.glsl - gAvatarProgram, gAvatarWaterProgram
 	main() - avatar/avatarV.glsl
@@ -7,7 +13,6 @@ avatar/avatarV.glsl - gAvatarProgram, gAvatarWaterProgram
 			sumLights() - lighting/sumLightsV.glsl
 				calcDirectionalLight() - lighting/lightFuncV.glsl
 				calcPointLight() - lighting/lightFuncV.glsl
-				scaleDownLight() - windlight/atmosphericsHelpersV.glsl
 				atmosAmbient() - windlight/atmosphericsHelpersV.glsl
 				atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -28,7 +33,6 @@ avatar/eyeballV.glsl - gAvatarEyeballProgram
 				atmosAmbient() - windlight/atmosphericsHelpersV.glsl
 				atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
 				atmosGetDiffuseSunlightColor() - windlight/atmosphericsHelpersV.glsl
-				scaleDownLight() - windlight/atmosphericsHelpersV.glsl
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 avatar/eyeballF.glsl - gAvatarEyeballProgram
 	main() - avatar/eyeballF.glsl
@@ -53,7 +57,6 @@ environment/terrainV.glsl - gTerrainProgram, gTerrainWaterProgram
 			sumLights() - lighting/sumLightsV.glsl
 				calcDirectionalLight() - lighting/lightFuncV.glsl
 				calcPointLight() - lighting/lightFuncV.glsl
-				scaleDownLight() - windlight/atmosphericsHelpersV.glsl
 				atmosAmbient() - windlight/atmosphericsHelpersV.glsl
 				atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -120,7 +123,6 @@ objects/shinyV.glsl - gObjectShinyProgram, gObjectShinyWaterProgram
 				sumLights() - lighting/sumLightsV.glsl
 					calcDirectionalLight() - lighting/lightFuncV.glsl
 					calcPointLight() - lighting/lightFuncV.glsl
-					scaleDownLight() - windlight/atmosphericsHelpersV.glsl
 					atmosAmbient() - windlight/atmosphericsHelpersV.glsl
 					atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -143,7 +145,6 @@ objects/simpleV.glsl - gObjectSimpleProgram, gObjectSimpleWaterProgram
 			sumLights() - lighting/sumLightsV.glsl
 				calcDirectionalLight() - lighting/lightFuncV.glsl
 				calcPointLight() - lighting/lightFuncV.glsl
-				scaleDownLight() - windlight/atmosphericsHelpersV.glsl
 				atmosAmbient() - windlight/atmosphericsHelpersV.glsl
 				atmosAffectDirectionalLight() - windlight/atmosphericsHelpersV.glsl
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/indra/newview/app_settings/ultra_graphics.xml b/indra/newview/app_settings/ultra_graphics.xml
index 3e7fccbd5f1e2b917ba83f72d536cb17d51f2447..eb2cd356d94e8fcff1c394b4e1ad25dc6136a99a 100644
--- a/indra/newview/app_settings/ultra_graphics.xml
+++ b/indra/newview/app_settings/ultra_graphics.xml
@@ -34,8 +34,6 @@
 	<!--Default for now-->
 	<RenderVolumeLODFactor value="2.0"/>
 	<!--NO SHADERS-->
-	<VertexShaderEnable value="TRUE"/>
-	<!--NO SHADERS-->
 	<WindLightUseAtmosShaders value="TRUE"/>
 	<!--Deferred Shading-->
 	<RenderDeferred value="TRUE"/>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index e99b94f150231d5dac83dbd1a468decffeeb7a37..e6ee45871988c587cd7fe965109a14173d6d61ee 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -66,6 +66,7 @@ RenderCompressTextures		1	1
 RenderShaderLightingMaxLevel	1	3
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderUseStreamVBO			1	1
 RenderFSAASamples			1	16
@@ -98,6 +99,7 @@ VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -129,6 +131,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -159,6 +162,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -189,6 +193,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -219,6 +224,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -249,6 +255,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -279,6 +286,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -309,6 +317,7 @@ WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderFSAASamples			1	2
 
@@ -320,6 +329,7 @@ RenderVBOEnable				1	0
 RenderShadowDetail			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 
 //
 // Class 0 Hardware (just old)
@@ -375,6 +385,7 @@ WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
+RenderUseAdvancedAtmospherics 0 0
 
 //
 // No Vertex Shaders available
@@ -388,6 +399,7 @@ WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
 RenderShadowDetail			0	0
+RenderUseAdvancedAtmospherics 0 0
 
 //
 // GL_ARB_map_buffer_range exists
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 801a622e934751a7c080826e555c7b65861539db..bc836a99ca7b6b02fea9b213fa23d62c59c40d48 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -66,6 +66,7 @@ RenderCompressTextures		1	1
 RenderShaderLightingMaxLevel	1	3
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderFSAASamples			1	16
 RenderMaxTextureIndex		1	16
@@ -97,6 +98,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -128,6 +130,7 @@ VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -158,6 +161,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -188,6 +192,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -217,6 +222,7 @@ RenderVolumeLODFactor		1	1.125
 VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderDeferredSSAO			1	0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
@@ -248,6 +254,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -278,6 +285,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -308,6 +316,7 @@ WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderFSAASamples			1	2
 
@@ -319,6 +328,7 @@ RenderVBOEnable				1	0
 RenderShadowDetail			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 
 //
 // Class 0 Hardware (just old)
@@ -373,6 +383,7 @@ VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
@@ -386,6 +397,7 @@ VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
@@ -413,6 +425,7 @@ RenderReflectionDetail		0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 1f891ee4d7b0cb6a0054a8b891dc9f14ffcdb974..68202a571fbf57801bf228fdba694d689702e2b5 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -66,6 +66,7 @@ RenderCompressTextures		1	1
 RenderShaderLightingMaxLevel	1	3
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderUseStreamVBO			1	1
 RenderFSAASamples			1	16
@@ -98,6 +99,7 @@ VertexShaderEnable			1	0
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -129,6 +131,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -159,6 +162,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	0
@@ -189,6 +193,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -219,6 +224,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -249,6 +255,7 @@ VertexShaderEnable			1	1
 WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
@@ -280,6 +287,7 @@ WindLightUseAtmosShaders	1	1
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
 RenderShadowDetail			1	2
+RenderUseAdvancedAtmospherics 1 0
 WLSkyDetail					1	48
 RenderFSAASamples			1	2
 
@@ -309,6 +317,7 @@ WindLightUseAtmosShaders	1	1
 WLSkyDetail					1	128
 RenderDeferred				1	1
 RenderDeferredSSAO			1	1
+RenderUseAdvancedAtmospherics 1 0
 RenderShadowDetail			1	2
 RenderFSAASamples			1	2
 
@@ -320,6 +329,7 @@ RenderVBOEnable				1	0
 RenderShadowDetail			1	0
 RenderDeferred				1	0
 RenderDeferredSSAO			1	0
+RenderUseAdvancedAtmospherics 1 0
 
 //
 // Class 0 Hardware (just old)
@@ -368,6 +378,7 @@ VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
@@ -381,6 +392,7 @@ VertexShaderEnable			0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
@@ -407,6 +419,7 @@ RenderReflectionDetail		0	0
 WindLightUseAtmosShaders	0	0
 RenderDeferred				0	0
 RenderDeferredSSAO			0	0
+RenderUseAdvancedAtmospherics 0 0
 RenderShadowDetail			0	0
 
 //
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 1545be345772b94d6a7d07fbba00f777a7e1eaf6..c8d2524e0e4414beb48ae79667af990786018d1a 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -44,7 +44,6 @@
 #include "llchicletbar.h"
 #include "llconsole.h"
 #include "lldonotdisturbnotificationstorage.h"
-#include "llenvmanager.h"
 #include "llfirstuse.h"
 #include "llfloatercamera.h"
 #include "llfloaterimcontainer.h"
@@ -384,6 +383,7 @@ LLAgent::LLAgent() :
 
 	mAgentOriginGlobal(),
 	mPositionGlobal(),
+    mLastTestGlobal(),
 
 	mDistanceTraveled(0.F),
 	mLastPositionGlobal(LLVector3d::zero),
@@ -775,7 +775,7 @@ void LLAgent::setFlying(BOOL fly, BOOL fail_sound)
 			// and it's OK if you're already flying
 			if (fail_sound)
 			{
-				make_ui_sound("UISndBadKeystroke");
+			make_ui_sound("UISndBadKeystroke");
 			}
 			return;
 		}
@@ -1086,6 +1086,13 @@ void LLAgent::setPositionAgent(const LLVector3 &pos_agent)
 		pos_agent_d.setVec(pos_agent);
 		mPositionGlobal = pos_agent_d + mAgentOriginGlobal;
 	}
+
+    if (((mLastTestGlobal - mPositionGlobal).lengthSquared() > 1.0) && !mOnPositionChanged.empty())
+    {   // If the position has changed my more than 1 meter since the last time we triggered.
+        // filters out some noise. 
+        mLastTestGlobal = mPositionGlobal;
+        mOnPositionChanged(mFrameAgent.getOrigin(), mPositionGlobal);
+    }
 }
 
 //-----------------------------------------------------------------------------
@@ -1126,6 +1133,12 @@ const LLVector3 &LLAgent::getPositionAgent()
 	return mFrameAgent.getOrigin();
 }
 
+boost::signals2::connection LLAgent::whenPositionChanged(position_signal_t::slot_type fn)
+{
+    return mOnPositionChanged.connect(fn);
+}
+
+
 //-----------------------------------------------------------------------------
 // getRegionsVisited()
 //-----------------------------------------------------------------------------
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 5ba1083d8efc345b2b7f48b138972da50758a7df..1a352d339719aa4c2ae0c06dc977e6484395acf5 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -189,6 +189,8 @@ class LLAgent : public LLOldEvents::LLObservable
  	// Position
 	//--------------------------------------------------------------------
 public:
+    typedef boost::signals2::signal<void(const LLVector3 &position_local, const LLVector3d &position_global)> position_signal_t;
+
 	LLVector3		getPosAgentFromGlobal(const LLVector3d &pos_global) const;
 	LLVector3d		getPosGlobalFromAgent(const LLVector3 &pos_agent) const;	
 	const LLVector3d &getPositionGlobal() const;
@@ -196,11 +198,17 @@ class LLAgent : public LLOldEvents::LLObservable
 	// Call once per frame to update position, angles (radians).
 	void			updateAgentPosition(const F32 dt, const F32 yaw, const S32 mouse_x, const S32 mouse_y);	
 	void			setPositionAgent(const LLVector3 &center);
+
+    boost::signals2::connection whenPositionChanged(position_signal_t::slot_type fn);
+
 protected:
 	void			propagate(const F32 dt); // ! BUG ! Should roll into updateAgentPosition
 private:
 	mutable LLVector3d mPositionGlobal;
 
+    position_signal_t   mOnPositionChanged;
+    LLVector3d          mLastTestGlobal;
+
   	//--------------------------------------------------------------------
  	// Velocity
 	//--------------------------------------------------------------------
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 013c40f557d8fd2a71e03102a917e44c6f4a414a..2411f0f86d5d61c5652c064c30b2cc4d9045d84d 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -799,14 +799,13 @@ void LLAgentWearables::createStandardWearables()
 			((OnWearableItemCreatedCB*)(&(*cb)))->addPendingWearable(wearable);
 			// no need to update here...
 			LLUUID category_id = LLUUID::null;
-			create_inventory_item(gAgent.getID(),
+            create_inventory_wearable(gAgent.getID(),
 								  gAgent.getSessionID(),
 								  category_id,
 								  wearable->getTransactionID(),
 								  wearable->getName(),
 								  wearable->getDescription(),
 								  wearable->getAssetType(),
-								  LLInventoryType::IT_WEARABLE,
 								  wearable->getType(),
 								  wearable->getPermissions().getMaskNextOwner(),
 								  cb);
@@ -868,14 +867,13 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback
 												   const LLUUID& category_id,
 												   BOOL notify)
 {
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  category_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
 						  wearable->getAssetType(),
-						  LLInventoryType::IT_WEARABLE,
 						  wearable->getType(),
 						  wearable->getPermissions().getMaskNextOwner(),
 						  cb);
@@ -1546,7 +1544,6 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
 
 	LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
 	LLAssetType::EType asset_type = wearable->getAssetType();
-	LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
 	LLPointer<LLInventoryCallback> cb;
 	if(wear)
 	{
@@ -1569,13 +1566,13 @@ void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, con
 		folder_id = gInventory.findCategoryUUIDForType(folder_type);
 	}
 
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  folder_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
-						  asset_type, inv_type,
+						  asset_type,
 						  wearable->getType(),
 						  LLFloaterPerms::getNextOwnerPerms("Wearables"),
 						  cb);
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 3c3dda1765633a801b8425d9d6fd43ea051e67fb..1a330591882d1fc730049e5152831ab1c486d1f3 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1029,14 +1029,13 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
 	const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
 	LLPointer<LLInventoryCallback> cb = new LLBoostFuncInventoryCallback(boost::bind(recovered_item_cb,_1,type,wearable,this));
 
-	create_inventory_item(gAgent.getID(),
+    create_inventory_wearable(gAgent.getID(),
 						  gAgent.getSessionID(),
 						  lost_and_found_id,
 						  wearable->getTransactionID(),
 						  wearable->getName(),
 						  wearable->getDescription(),
 						  wearable->getAssetType(),
-						  LLInventoryType::IT_WEARABLE,
 						  wearable->getType(),
 						  wearable->getPermissions().getMaskNextOwner(),
 						  cb);
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b232a8c3bbfeb3bc6002aa8da53ef1f422c61065..cbb47d71f7c2de41b9ac811de7cb6564d57acf42 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -33,6 +33,7 @@
 #include "llfeaturemanager.h"
 #include "lluictrlfactory.h"
 #include "lltexteditor.h"
+#include "llenvironment.h"
 #include "llerrorcontrol.h"
 #include "lleventtimer.h"
 #include "llviewertexturelist.h"
@@ -172,8 +173,6 @@
 #include "llviewerparcelmgr.h"
 #include "llworldmapview.h"
 #include "llpostprocess.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
 
 #include "lldebugview.h"
 #include "llconsole.h"
@@ -209,6 +208,7 @@
 #include "llfloateroutfitsnapshot.h"
 #include "llfloatersnapshot.h"
 #include "llsidepanelinventory.h"
+#include "llatmosphere.h"
 
 // includes for idle() idleShutdown()
 #include "llviewercontrol.h"
@@ -777,6 +777,10 @@ bool LLAppViewer::init()
 	// Memory will be cleaned up in ::cleanupClass()
 	LLWearableType::initParamSingleton(new LLUITranslationBridge());
 
+    // initialize the LLSettingsType translation bridge.
+    LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>();
+    LLSettingsType::initClass(trans);
+
 	// initialize SSE options
 	LLVector4a::initClass();
 
@@ -1137,6 +1141,9 @@ bool LLAppViewer::init()
 
 	gGLActive = FALSE;
 
+#if LL_RELEASE_FOR_DOWNLOAD 
+    if (!gSavedSettings.getBOOL("CmdLineSkipUpdater"))
+    {
 	LLProcess::Params updater;
 	updater.desc = "updater process";
 	// Because it's the updater, it MUST persist beyond the lifespan of the
@@ -1162,18 +1169,13 @@ bool LLAppViewer::init()
 	// ForceAddressSize
 	updater.args.add(stringize(gSavedSettings.getU32("ForceAddressSize")));
 
-#if LL_WINDOWS && !LL_RELEASE_FOR_DOWNLOAD && !LL_SEND_CRASH_REPORTS
-	// This is neither a release package, nor crash-reporting enabled test build
-	// try to run version updater, but don't bother if it fails (file might be missing)
-	LLLeap *leap_p = LLLeap::create(updater, false);
-	if (!leap_p)
+		// Run the updater. An exception from launching the updater should bother us.
+		LLLeap::create(updater, true);
+	}
+	else
 	{
-		LL_WARNS("LLLeap") << "Failed to run LLLeap" << LL_ENDL;
+		LL_WARNS("InitInfo") << "Skipping updater check." << LL_ENDL;
 	}
-#else
- 	// Run the updater. An exception from launching the updater should bother us.
-	LLLeap::create(updater, true);
-#endif
 
 	// Iterate over --leap command-line options. But this is a bit tricky: if
 	// there's only one, it won't be an array at all.
@@ -1205,6 +1207,7 @@ bool LLAppViewer::init()
 							 << "lleventhost no longer supported as a dynamic library"
 							 << LL_ENDL;
 	}
+#endif
 
 	LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match;
 
@@ -1316,6 +1319,8 @@ static LLTrace::BlockTimerStatHandle FTM_YIELD("Yield");
 
 static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
 static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
+static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch");
+
 static LLTrace::BlockTimerStatHandle FTM_VFS("VFS Thread");
 static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
 static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
@@ -1467,8 +1472,10 @@ bool LLAppViewer::doFrame()
 				pingMainloopTimeout("Main:Display");
 				gGLActive = TRUE;
 
+				display();
+
 				static U64 last_call = 0;
-				if (!gTeleportDisplay)
+				if (!gTeleportDisplay || gGLManager.mIsIntel) // SL-10625...throttle early, throttle often with Intel
 				{
 					// Frame/draw throttling
 					U64 elapsed_time = LLTimer::getTotalTime() - last_call;
@@ -1482,8 +1489,6 @@ bool LLAppViewer::doFrame()
 				}
 				last_call = LLTimer::getTotalTime();
 
-				display();
-
 				pingMainloopTimeout("Main:Snapshot");
 				LLFloaterSnapshot::update(); // take snapshots
 					LLFloaterOutfitSnapshot::update();
@@ -1630,7 +1635,7 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
 	 	work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread
 	}
 	{
-		LL_RECORD_BLOCK_TIME(FTM_DECODE);
+		LL_RECORD_BLOCK_TIME(FTM_FETCH);
 	 	work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread
 	}
 	return work_pending;
@@ -1653,6 +1658,8 @@ void LLAppViewer::flushVFSIO()
 
 bool LLAppViewer::cleanup()
 {
+    LLAtmosphere::cleanupClass();
+
 	//ditch LLVOAvatarSelf instance
 	gAgentAvatarp = NULL;
 
@@ -1902,6 +1909,12 @@ bool LLAppViewer::cleanup()
 	// Store the time of our current logoff
 	gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
 
+    if (LLEnvironment::instanceExists())
+    {
+        //Store environment settings if nessesary
+        LLEnvironment::getInstance()->saveToSettings();
+    }
+
 	// Must do this after all panels have been deleted because panels that have persistent rects
 	// save their rects on delete.
 	gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
@@ -2206,7 +2219,9 @@ void errorCallback(const std::string &error_string)
 	// static info file.
 	LLAppViewer::instance()->writeDebugInfo();
 
+#ifndef SHADER_CRASH_NONFATAL
 	LLError::crashAndLoop(error_string);
+#endif
 }
 
 void LLAppViewer::initLoggingAndGetLastDuration()
@@ -4933,7 +4948,6 @@ void LLAppViewer::idle()
 	//
 	// Update weather effects
 	//
-	gSky.propagateHeavenlyBodies(gFrameDTClamped);				// moves sun, moon, and planets
 
 	// Update wind vector
 	LLVector3 wind_position_region;
@@ -5417,7 +5431,7 @@ bool LLAppViewer::onChangeFrameLimit(LLSD const & evt)
 {
 	if (evt.asInteger() > 0)
 	{
-		mMinMicroSecPerFrame = 1000000 / evt.asInteger();
+		mMinMicroSecPerFrame = (U64)(1000000.0f / F32(evt.asInteger()));
 	}
 	else
 	{
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 1298ba51e24e5b22f7933c6101969f5331f8931f..e8b3464c6e7815cc1b419a3e6fd64d096e938073 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -393,8 +393,6 @@ extern LLVector3 gRelativeWindVec;
 extern U32	gPacketsIn;
 extern BOOL gPrintMessagesThisFrame;
 
-extern LLUUID gSunTextureID;
-extern LLUUID gMoonTextureID;
 extern LLUUID gBlackSquareID;
 
 extern BOOL gRandomizeFramerate;
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index f0b74e743957c012d71bde75dcf5a81199b8ee93..1797d2dd6e525015f2bd40c9af31d8e8e2d1532d 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -626,10 +626,10 @@ namespace action_give_inventory
 	 * Checks My Inventory visibility.
 	 */
 
-	static bool is_give_inventory_acceptable()
+	static bool is_give_inventory_acceptable(LLInventoryPanel* panel = NULL)
 	{
 		// check selection in the panel
-		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
+		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);
 		if (inventory_selected_uuids.empty()) return false; // nothing selected
 
 		bool acceptable = false;
@@ -694,7 +694,7 @@ namespace action_give_inventory
 		uuid_vec_t mAvatarUuids;
 	};
 
-	static void give_inventory_cb(const LLSD& notification, const LLSD& response)
+	static void give_inventory_cb(const LLSD& notification, const LLSD& response, std::set<LLUUID> inventory_selected_uuids)
 	{
 		S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 		// if Cancel pressed
@@ -703,7 +703,6 @@ namespace action_give_inventory
 			return;
 		}
 
-		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
 		if (inventory_selected_uuids.empty())
 		{
 			return;
@@ -786,11 +785,11 @@ namespace action_give_inventory
 	 * @param avatar_names - avatar names request to be sent.
 	 * @param avatar_uuids - avatar names request to be sent.
 	 */
-	static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
+	static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names, LLInventoryPanel* panel = NULL)
 	{
 		llassert(avatar_names.size() == avatar_uuids.size());
 
-		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
+		const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs(panel);
 		if (inventory_selected_uuids.empty())
 		{
 			return;
@@ -824,7 +823,7 @@ namespace action_give_inventory
 		substitutions["ITEMS"] = items;
 		LLShareInfo::instance().mAvatarNames = avatar_names;
 		LLShareInfo::instance().mAvatarUuids = avatar_uuids;
-		LLNotificationsUtil::add(notification, substitutions, LLSD(), &give_inventory_cb);
+		LLNotificationsUtil::add(notification, substitutions, LLSD(), boost::bind(&give_inventory_cb, _1, _2, inventory_selected_uuids));
 	}
 }
 
@@ -877,11 +876,14 @@ void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std::
 }
 
 //static
-std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
+std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs(LLInventoryPanel* active_panel)
 {
 	std::set<LLFolderViewItem*> inventory_selected;
 
-	LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
+	if (!active_panel)
+	{
+		active_panel = action_give_inventory::get_active_inventory_panel();
+	}
 	if (active_panel)
 	{
 		inventory_selected= active_panel->getRootFolder()->getSelectionList();
@@ -911,15 +913,16 @@ void LLAvatarActions::shareWithAvatars(LLView * panel)
 {
 	using namespace action_give_inventory;
 
-    LLFloater* root_floater = gFloaterView->getParentFloater(panel);
+	LLFloater* root_floater = gFloaterView->getParentFloater(panel);
+	LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(panel);
 	LLFloaterAvatarPicker* picker =
-		LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE, FALSE, root_floater->getName());
+		LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2, inv_panel), TRUE, FALSE, FALSE, root_floater->getName());
 	if (!picker)
 	{
 		return;
 	}
 
-	picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
+	picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable, inv_panel));
 	picker->openFriendsTab();
     
     if (root_floater)
diff --git a/indra/newview/llavataractions.h b/indra/newview/llavataractions.h
index b56d5b0fb9ee2b7fa0d4dc655450941895e6146e..7c721076c8810777ad4276ec8d567b32b6c5d66e 100644
--- a/indra/newview/llavataractions.h
+++ b/indra/newview/llavataractions.h
@@ -244,7 +244,7 @@ class LLAvatarActions
 	 */
 	static void viewChatHistory(const LLUUID& id);
 
-	static std::set<LLUUID> getInventorySelectedUUIDs();
+	static std::set<LLUUID> getInventorySelectedUUIDs(LLInventoryPanel* active_panel = NULL);
 
 private:
 	static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index f0682dc1ba77a72fd346e60f68bb01d8bf559de3..5a6b66df52b0213e17a35829d88ec919e3f8b4ff 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -35,8 +35,6 @@
 #include "llviewerregion.h"
 #include "llskinningutil.h"
 
-//#pragma optimize("", off)
-
 const F32 LLControlAvatar::MAX_LEGAL_OFFSET = 3.0f;
 const F32 LLControlAvatar::MAX_LEGAL_SIZE = 64.0f;
 
@@ -263,7 +261,7 @@ void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor)
 {
     joint->setScale(factor * joint->getScale());
     
-	for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin();
+	for (LLJoint::joints_t::iterator iter = joint->mChildren.begin();
 		 iter != joint->mChildren.end(); ++iter)
 	{
 		LLJoint* child = *iter;
@@ -580,12 +578,12 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
         return NULL;
     }
 
-    LLViewerObject* hit = NULL;
+	LLViewerObject* hit = NULL;
 
-    if (lineSegmentBoundingBox(start, end))
-    {
-        LLVector4a local_end = end;
-        LLVector4a local_intersection;
+	if (lineSegmentBoundingBox(start, end))
+	{
+		LLVector4a local_end = end;
+		LLVector4a local_intersection;
         if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
         {
             local_end = local_intersection;
@@ -604,20 +602,20 @@ LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLV
             {
                 LLVOVolume *volp = *vol_it;
                 if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, face_hit, &local_intersection, tex_coord, normal, tangent))
-                {
-                    local_end = local_intersection;
-                    if (intersection)
-                    {
-                        *intersection = local_intersection;
-                    }
+        {
+            local_end = local_intersection;
+            if (intersection)
+            {
+                *intersection = local_intersection;
+            }
                     hit = volp;
                     break;
                 }
             }
         }
-    }
-
-    return hit;
+	}
+		
+	return hit;
 }
 
 // virtual
diff --git a/indra/newview/lldaycyclemanager.cpp b/indra/newview/lldaycyclemanager.cpp
deleted file mode 100644
index 803e2b2fb22e9544df263b883be8b6c326b1d5b3..0000000000000000000000000000000000000000
--- a/indra/newview/lldaycyclemanager.cpp
+++ /dev/null
@@ -1,230 +0,0 @@
-/**
- * @file lldaycyclemanager.cpp
- * @brief Implementation for the LLDayCycleManager class.
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "lldaycyclemanager.h"
-
-#include "lldiriterator.h"
-
-void LLDayCycleManager::getPresetNames(preset_name_list_t& names) const
-{
-	names.clear();
-
-	for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
-	{
-		names.push_back(it->first);
-	}
-}
-
-void LLDayCycleManager::getPresetNames(preset_name_list_t& user, preset_name_list_t& sys) const
-{
-	user.clear();
-	sys.clear();
-
-	for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
-	{
-		const std::string& name = it->first;
-
-		if (isSystemPreset(name))
-		{
-			sys.push_back(name);
-		}
-		else
-		{
-			user.push_back(name);
-		}
-	}
-}
-
-void LLDayCycleManager::getUserPresetNames(preset_name_list_t& user) const
-{
-	preset_name_list_t sys; // unused
-	getPresetNames(user, sys);
-}
-
-bool LLDayCycleManager::getPreset(const std::string name, LLWLDayCycle& day_cycle) const
-{
-	dc_map_t::const_iterator it = mDayCycleMap.find(name);
-	if (it == mDayCycleMap.end())
-	{
-		return false;
-	}
-
-	day_cycle = it->second;
-	return true;
-}
-
-bool LLDayCycleManager::getPreset(const std::string name, LLSD& day_cycle) const
-{
-	LLWLDayCycle dc;
-	if (!getPreset(name, dc))
-	{
-		return false;
-	}
-
-	day_cycle = dc.asLLSD();
-	return true;
-}
-
-bool LLDayCycleManager::presetExists(const std::string name) const
-{
-	LLWLDayCycle dummy;
-	return getPreset(name, dummy);
-}
-
-bool LLDayCycleManager::isSystemPreset(const std::string& name) const
-{
-	return gDirUtilp->fileExists(getSysDir() + LLURI::escape(name) + ".xml");
-}
-
-bool LLDayCycleManager::savePreset(const std::string& name, const LLSD& data)
-{
-	// Save given preset.
-	LLWLDayCycle day;
-	day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
-	day.save(getUserDir() + LLURI::escape(name) + ".xml");
-
-	// Add it to our map.
-	addPreset(name, data);
-	mModifySignal();
-	return true;
-}
-
-bool LLDayCycleManager::deletePreset(const std::string& name)
-{
-	// Remove it from the map.
-	dc_map_t::iterator it = mDayCycleMap.find(name);
-	if (it == mDayCycleMap.end())
-	{
-		LL_WARNS("Windlight") << "No day cycle named " << name << LL_ENDL;
-		return false;
-	}
-	mDayCycleMap.erase(it);
-
-	// Remove from the filesystem.
-	std::string filename = LLURI::escape(name) + ".xml";
-	if (gDirUtilp->fileExists(getUserDir() + filename))
-	{
-		gDirUtilp->deleteFilesInDir(getUserDir(), filename);
-	}
-
-	// Signal interested parties.
-	mModifySignal();
-	return true;
-}
-
-bool LLDayCycleManager::isSkyPresetReferenced(const std::string& preset_name) const
-{
-	// We're traversing local day cycles, they can only reference local skies.
-	LLWLParamKey key(preset_name, LLEnvKey::SCOPE_LOCAL);
-
-	for (dc_map_t::const_iterator it = mDayCycleMap.begin(); it != mDayCycleMap.end(); ++it)
-	{
-		if (it->second.hasReferencesTo(key))
-		{
-			return true;
-		}
-	}
-
-	return false;
-}
-
-boost::signals2::connection LLDayCycleManager::setModifyCallback(const modify_signal_t::slot_type& cb)
-{
-	return mModifySignal.connect(cb);
-}
-
-// virtual
-void LLDayCycleManager::initSingleton()
-{
-	LL_DEBUGS("Windlight") << "Loading all day cycles" << LL_ENDL;
-	loadAllPresets();
-}
-
-void LLDayCycleManager::loadAllPresets()
-{
-	mDayCycleMap.clear();
-
-	// First, load system (coming out of the box) day cycles.
-	loadPresets(getSysDir());
-
-	// Then load user presets. Note that user day cycles will modify any system ones already loaded.
-	loadPresets(getUserDir());
-}
-
-void LLDayCycleManager::loadPresets(const std::string& dir)
-{
-	LLDirIterator dir_iter(dir, "*.xml");
-
-	while (1)
-	{
-		std::string file;
-		if (!dir_iter.next(file)) break; // no more files
-		loadPreset(gDirUtilp->add(dir, file));
-	}
-}
-
-bool LLDayCycleManager::loadPreset(const std::string& path)
-{
-	LLSD data = LLWLDayCycle::loadDayCycleFromPath(path);
-	if (data.isUndefined())
-	{
-		LL_WARNS() << "Error loading day cycle from " << path << LL_ENDL;
-		return false;
-	}
-
-	std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
-	addPreset(name, data);
-
-	return true;
-}
-
-bool LLDayCycleManager::addPreset(const std::string& name, const LLSD& data)
-{
-	if (name.empty())
-	{
-		//llassert(name.empty());
-		return false;
-	}
-
-	LLWLDayCycle day;
-	day.loadDayCycle(data, LLEnvKey::SCOPE_LOCAL);
-	mDayCycleMap[name] = day;
-	return true;
-}
-
-// static
-std::string LLDayCycleManager::getSysDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/days", "");
-}
-
-// static
-std::string LLDayCycleManager::getUserDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/days", "");
-}
diff --git a/indra/newview/lldaycyclemanager.h b/indra/newview/lldaycyclemanager.h
deleted file mode 100644
index 04db9d5dacedeaa6675f69fafbb19a590dc1ae02..0000000000000000000000000000000000000000
--- a/indra/newview/lldaycyclemanager.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * @file lldaycyclemanager.h
- * @brief Implementation for the LLDayCycleManager class.
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLDAYCYCLEMANAGER_H
-#define LL_LLDAYCYCLEMANAGER_H
-
-#include <map>
-#include <string>
-
-#include "llwldaycycle.h"
-#include "llwlparammanager.h"
-
-/**
- * WindLight day cycles manager class
- *
- * Provides interface for accessing, loading and saving day cycles.
- */
-class LLDayCycleManager : public LLSingleton<LLDayCycleManager>
-{
-	LLSINGLETON_EMPTY_CTOR(LLDayCycleManager);
-	LOG_CLASS(LLDayCycleManager);
-
-public:
-	typedef std::list<std::string> preset_name_list_t;
-
-	typedef std::map<std::string, LLWLDayCycle> dc_map_t;
-	typedef boost::signals2::signal<void()> modify_signal_t;
-
-	void getPresetNames(preset_name_list_t& names) const;
-	void getPresetNames(preset_name_list_t& user, preset_name_list_t& sys) const;
-	void getUserPresetNames(preset_name_list_t& user) const;
-
-	bool getPreset(const std::string name, LLWLDayCycle& day_cycle) const;
-	bool getPreset(const std::string name, LLSD& day_cycle) const;
-	bool presetExists(const std::string name) const;
-	bool isSystemPreset(const std::string& name) const;
-	bool savePreset(const std::string& name, const LLSD& data);
-	bool deletePreset(const std::string& name);
-
-	/// @return true if there is a day cycle that refers to the sky preset.
-	bool isSkyPresetReferenced(const std::string& preset_name) const;
-
-	/// Emitted when a preset gets added or deleted.
-	boost::signals2::connection setModifyCallback(const modify_signal_t::slot_type& cb);
-
-private:
-	/*virtual*/ void initSingleton();
-
-	void loadAllPresets();
-	void loadPresets(const std::string& dir);
-	bool loadPreset(const std::string& path);
-	bool addPreset(const std::string& name, const LLSD& data);
-
-	static std::string getSysDir();
-	static std::string getUserDir();
-
-	dc_map_t mDayCycleMap;
-	modify_signal_t mModifySignal;
-};
-
-#endif // LL_LLDAYCYCLEMANAGER_H
diff --git a/indra/newview/lldensityctrl.cpp b/indra/newview/lldensityctrl.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..298a309e7cad9881e423efcb97437ce56fc69685
--- /dev/null
+++ b/indra/newview/lldensityctrl.cpp
@@ -0,0 +1,225 @@
+/**
+* @file lldensityctrl.cpp
+* @brief Control for specifying density over a height range for sky settings.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lldensityctrl.h"
+
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "llsettingssky.h"
+
+static LLDefaultChildRegistry::Register<LLDensityCtrl> register_density_control("densityctrl");
+
+const std::string LLDensityCtrl::DENSITY_RAYLEIGH("density_rayleigh");
+const std::string LLDensityCtrl::DENSITY_MIE("density_mie");
+const std::string LLDensityCtrl::DENSITY_ABSORPTION("density_absorption");
+
+namespace
+{   
+    const std::string   FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL("level_exponential");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE("exponential_scale");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_LINEAR("level_linear");
+    const std::string   FIELD_SKY_DENSITY_PROFILE_CONSTANT("level_constant");
+    const std::string   FIELD_SKY_DENSITY_MAX_ALTITUDE("max_altitude");
+    const std::string   FIELD_SKY_DENSITY_ANISO_FACTOR("aniso_factor");
+    const std::string   FIELD_SKY_DENSITY_ANISO_FACTOR_LABEL("aniso_factor_label");
+}
+
+const std::string& LLDensityCtrl::NameForDensityProfileType(DensityProfileType t)
+{
+    switch (t)
+    {
+        case Rayleigh:   return DENSITY_RAYLEIGH;
+        case Mie:        return DENSITY_MIE;
+        case Absorption: return DENSITY_ABSORPTION;
+        default:
+            break;
+    }
+
+    llassert(false);
+    return DENSITY_RAYLEIGH;
+}
+
+LLDensityCtrl::Params::Params()
+: image_density_feedback("image_density_feedback")
+, lbl_exponential("label_exponential")
+, lbl_exponential_scale("label_exponential_scale")
+, lbl_linear("label_linear")
+, lbl_constant("label_constant")
+, lbl_max_altitude("label_max_altitude")
+, lbl_aniso_factor("label_aniso_factor")
+, profile_type(LLDensityCtrl::Rayleigh)
+{
+}
+
+LLDensityCtrl::LLDensityCtrl(const Params& params)
+: mProfileType(params.profile_type)
+, mImgDensityFeedback(params.image_density_feedback)
+{
+
+}
+
+LLSD LLDensityCtrl::getProfileConfig()
+{
+    LLSD config;
+    switch (mProfileType)
+    {
+        case Rayleigh:   return mSkySettings->getRayleighConfigs();
+        case Mie:        return mSkySettings->getMieConfigs();
+        case Absorption: return mSkySettings->getAbsorptionConfigs();
+        default:
+            break;
+    }
+    llassert(false);
+    return config;
+}
+
+BOOL LLDensityCtrl::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onExponentialChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onExponentialScaleFactorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onLinearChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onConstantChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMaxAltitudeChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAnisoFactorChanged(); });
+
+    if (mProfileType != Mie)
+    {
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR_LABEL)->setValue(false);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setVisible(false);
+    }
+
+    return TRUE;
+}
+
+void LLDensityCtrl::setEnabled(BOOL enabled)
+{
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setEnabled(enabled);
+
+    if (mProfileType == Mie)
+    {
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setEnabled(enabled);
+    }
+}
+
+void LLDensityCtrl::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(TRUE);
+    setAllChildrenEnabled(TRUE);
+
+    LLSD config = getProfileConfig();
+
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM]);
+    getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->setValue(config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH]);
+
+    if (mProfileType == Mie)
+    {        
+        getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->setValue(config[LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR]);
+    }
+}
+
+void LLDensityCtrl::updateProfile()
+{
+    F32 exponential_term  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL)->getValueF32();
+    F32 exponential_scale = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_EXPONENTIAL_SCALE)->getValueF32();
+    F32 linear_term       = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_LINEAR)->getValueF32();
+    F32 constant_term     = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_PROFILE_CONSTANT)->getValueF32();
+    F32 max_alt           = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MAX_ALTITUDE)->getValueF32();
+    F32 aniso_factor      = 0.0f;
+
+    if (mProfileType == Mie)
+    {
+        aniso_factor = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ANISO_FACTOR)->getValueF32();
+    }
+
+    LLSD profile = LLSettingsSky::createSingleLayerDensityProfile(max_alt, exponential_term, exponential_scale, linear_term, constant_term, aniso_factor);
+
+    switch (mProfileType)
+    {
+        case Rayleigh: mSkySettings->setRayleighConfigs(profile); break;
+        case Mie: mSkySettings->setMieConfigs(profile); break;
+        case Absorption: mSkySettings->setAbsorptionConfigs(profile); break;
+        default:
+            break;
+    }
+}
+
+void LLDensityCtrl::onExponentialChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onExponentialScaleFactorChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onLinearChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onConstantChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onMaxAltitudeChanged()
+{
+    updateProfile();
+    updatePreview();
+}
+
+void LLDensityCtrl::onAnisoFactorChanged()
+{
+    updateProfile();
+}
+
+void LLDensityCtrl::updatePreview()
+{
+    // AdvancedAtmospherics TODO
+    // Generate image according to current density profile
+}
+
diff --git a/indra/newview/lldensityctrl.h b/indra/newview/lldensityctrl.h
new file mode 100644
index 0000000000000000000000000000000000000000..789022803c37ddde588e1502f0b27ba13255b727
--- /dev/null
+++ b/indra/newview/lldensityctrl.h
@@ -0,0 +1,104 @@
+/**
+* @file lldensityctrl.h
+* @brief Control for specifying density over a height range for sky settings.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#ifndef LLDENSITY_CTRL_H
+#define LLDENSITY_CTRL_H
+
+#include "lluictrl.h"
+#include "llsettingssky.h"
+#include "lltextbox.h"
+#include "llsliderctrl.h"
+
+class LLDensityCtrl : public LLUICtrl
+{
+public:
+    static const std::string DENSITY_RAYLEIGH;
+    static const std::string DENSITY_MIE;
+    static const std::string DENSITY_ABSORPTION;
+
+    // Type of density profile this tab is updating
+    enum DensityProfileType
+    {
+        Rayleigh,
+        Mie,
+        Absorption
+    };
+
+    static const std::string& NameForDensityProfileType(DensityProfileType t);
+
+    struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
+    {
+        Optional<LLTextBox::Params>         lbl_exponential,
+            lbl_exponential_scale,
+            lbl_linear,
+            lbl_constant,
+            lbl_max_altitude,
+            lbl_aniso_factor;
+
+        Optional<LLSliderCtrl::Params> exponential_slider,
+        exponential_scale_slider,
+        linear_slider,
+        constant_slider,
+        aniso_factor_slider;
+
+        Optional<LLUIImage*> image_density_feedback;
+
+        DensityProfileType profile_type;
+        Params();
+    };
+
+    virtual BOOL	        postBuild() override;
+    virtual void	        setEnabled(BOOL enabled) override;
+
+    void setProfileType(DensityProfileType t) { mProfileType = t; }
+
+    void refresh();
+    void updateProfile();
+
+    LLSettingsSky::ptr_t    getSky() const                                          { return mSkySettings; }
+    void                    setSky(const LLSettingsSky::ptr_t &sky)                 { mSkySettings = sky; refresh(); }
+
+protected:
+    friend class LLUICtrlFactory;
+    LLDensityCtrl(const Params&);
+
+    LLSD getProfileConfig();
+    void updatePreview();
+
+private:
+    void onExponentialChanged();
+    void onExponentialScaleFactorChanged();
+    void onLinearChanged();
+    void onConstantChanged();
+    void onMaxAltitudeChanged();
+    void onAnisoFactorChanged();
+
+    DensityProfileType    mProfileType = Rayleigh;
+    LLUIImage*            mImgDensityFeedback = nullptr;
+    LLSettingsSky::ptr_t  mSkySettings;
+};
+
+#endif LLDENSITY_CTRL_H
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 82888b2df6d83325ed52230d50fadf6fa99a3d17..2aee7b450acc116ecc355a6480cff6cedcde43ff 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -127,7 +127,7 @@ LLDrawPool::LLDrawPool(const U32 type)
 	mType = type;
 	sNumDrawPools++;
 	mId = sNumDrawPools;
-	mVertexShaderLevel = 0;
+	mShaderLevel = 0;
 	mSkipRender = false;
 }
 
@@ -141,7 +141,7 @@ LLViewerTexture *LLDrawPool::getDebugTexture()
 	return NULL;
 }
 
-//virtuals
+//virtual
 void LLDrawPool::beginRenderPass( S32 pass )
 {
 }
@@ -406,9 +406,9 @@ void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL t
 	}
 }
 
-void LLRenderPass::renderTexture(U32 type, U32 mask)
+void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures)
 {
-	pushBatches(type, mask, TRUE);
+	pushBatches(type, mask, true, batch_textures);
 }
 
 void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
@@ -449,10 +449,10 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
 	if (params.mModelMatrix != gGLLastMatrix)
 	{
 		gGLLastMatrix = params.mModelMatrix;
+        gGL.matrixMode(LLRender::MM_MODELVIEW);
 		gGL.loadMatrix(gGLModelView);
 		if (params.mModelMatrix)
 		{
-			llassert(gGL.getMatrixMode() == LLRender::MM_MODELVIEW);
 			gGL.multMatrix((GLfloat*) params.mModelMatrix->mMatrix);
 		}
 		gPipeline.mMatrixOpCount++;
@@ -461,6 +461,11 @@ void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
 
 void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures)
 {
+    if (!params.mCount)
+    {
+        return;
+    }
+
 	applyModelMatrix(params);
 
 	bool tex_setup = false;
@@ -515,6 +520,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
 
 	if (tex_setup)
 	{
+        gGL.matrixMode(LLRender::MM_TEXTURE0);
 		gGL.loadIdentity();
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 	}
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index bc299cc89fa24e7ff59926f5b196f604432e02dc..4eb9a4151d59daeb6912d10a1005197119774cd3 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -107,7 +107,7 @@ class LLDrawPool
 	virtual void prerender() = 0;
 	virtual U32 getVertexDataMask() = 0;
 	virtual BOOL verify() const { return TRUE; }		// Verify that all data in the draw pool is correct!
-	virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
+	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.
@@ -116,7 +116,7 @@ class LLDrawPool
 	virtual void resetDrawOrders() = 0;
 
 protected:
-	S32 mVertexShaderLevel;
+	S32 mShaderLevel;
 	S32	mId;
 	U32 mType;				// Type of draw pool
 	BOOL mSkipRender;
@@ -174,7 +174,7 @@ class LLRenderPass : public LLDrawPool
 	virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
 	virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
 	virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE);
-	virtual void renderTexture(U32 type, U32 mask);
+	virtual void renderTexture(U32 type, U32 mask, BOOL batch_textures = TRUE);
 
 };
 
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 0873300cd257bffec2f0408c4e267fb01cde120f..da0467315f3f5e61308b4e5d1890febf790ec6bd 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -53,6 +53,22 @@ BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
 
 static BOOL deferred_render = FALSE;
 
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETUP("Alpha Setup");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED("Alpha Deferred");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SETBUFFER("Alpha SetBuffer");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DRAW("Alpha Draw");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_TEX_BINDS("Alpha Tex Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MATS("Alpha Mat Tex Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GLOW("Alpha Glow Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_SHADER_BINDS("Alpha Shader Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS("Alpha Def Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS("Alpha Def Tex Binds");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MESH_REBUILD("Alpha Mesh Rebuild");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_EMISSIVE("Alpha Emissive");
+static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_LIGHT_SETUP("Alpha Light Setup");
+
 LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
 		LLRenderPass(type), current_shader(NULL), target_shader(NULL),
 		simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL),
@@ -69,7 +85,7 @@ LLDrawPoolAlpha::~LLDrawPoolAlpha()
 
 void LLDrawPoolAlpha::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 S32 LLDrawPoolAlpha::getNumPostDeferredPasses() 
@@ -90,37 +106,37 @@ S32 LLDrawPoolAlpha::getNumPostDeferredPasses()
 
 void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) 
 { 
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA);
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED);
+
+    F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+
+    emissive_shader = (LLPipeline::sRenderDeferred)   ? &gDeferredEmissiveProgram    :
+                      (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+
+    emissive_shader->bind();
+    emissive_shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
+    emissive_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); 
+	emissive_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
 
 	if (pass == 0)
 	{
-		if (LLPipeline::sImpostorRender)
-		{
-			simple_shader = &gDeferredAlphaImpostorProgram;
-			fullbright_shader = &gDeferredFullbrightProgram;
-		}
-		else if (LLPipeline::sUnderWaterRender)
-		{
-			simple_shader = &gDeferredAlphaWaterProgram;
-			fullbright_shader = &gDeferredFullbrightWaterProgram;
-		}
-		else
-		{
-		simple_shader = &gDeferredAlphaProgram;
-			fullbright_shader = &gDeferredFullbrightProgram;
-		}
-		
-		F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+        fullbright_shader = (LLPipeline::sImpostorRender)   ? &gDeferredFullbrightProgram      :
+                            (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
 
 		fullbright_shader->bind();
 		fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f); 
 		fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
+        fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
 		fullbright_shader->unbind();
 
+        simple_shader = (LLPipeline::sImpostorRender)   ? &gDeferredAlphaImpostorProgram :
+                        (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram    : &gDeferredAlphaProgram;
+
 		//prime simple shader (loads shadow relevant uniforms)
 		gPipeline.bindDeferredShader(*simple_shader);
 
 		simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
+        simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
 	}
 	else if (!LLPipeline::sImpostorRender)
 	{
@@ -134,25 +150,8 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
 		gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f);
 	}
 
-
-    if (LLPipeline::sRenderDeferred)
-    {
-		emissive_shader = &gDeferredEmissiveProgram;
-    }
-    else
-    {
-		if (LLPipeline::sUnderWaterRender)
-		{
-			emissive_shader = &gObjectEmissiveWaterProgram;
-		}
-		else
-		{
-			emissive_shader = &gObjectEmissiveProgram;
-		}
-    }
-
 	deferred_render = TRUE;
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		// Start out with no shaders.
 		current_shader = target_shader = NULL;
@@ -162,6 +161,8 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
 
 void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) 
 { 
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED);
+
 	if (pass == 1 && !LLPipeline::sImpostorRender)
 	{
 		gPipeline.mDeferredDepth.flush();
@@ -175,44 +176,64 @@ void LLDrawPoolAlpha::endPostDeferredPass(S32 pass)
 
 void LLDrawPoolAlpha::renderPostDeferred(S32 pass) 
 { 
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED);
 	render(pass); 
 }
 
 void LLDrawPoolAlpha::beginRenderPass(S32 pass)
 {
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA);
+	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP);
 	
-	if (LLPipeline::sImpostorRender)
-	{
-		simple_shader = &gObjectSimpleImpostorProgram;
-		fullbright_shader = &gObjectFullbrightProgram;
-		emissive_shader = &gObjectEmissiveProgram;
-	}
-	else if (LLPipeline::sUnderWaterRender)
-	{
-		simple_shader = &gObjectSimpleWaterProgram;
-		fullbright_shader = &gObjectFullbrightWaterProgram;
-		emissive_shader = &gObjectEmissiveWaterProgram;
-	}
-	else
-	{
-		simple_shader = &gObjectSimpleProgram;
-		fullbright_shader = &gObjectFullbrightProgram;
-		emissive_shader = &gObjectEmissiveProgram;
-	}
+    simple_shader     = (LLPipeline::sImpostorRender)   ? &gObjectSimpleImpostorProgram  :
+                        (LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram     : &gObjectSimpleProgram;
+
+    fullbright_shader = (LLPipeline::sImpostorRender)   ? &gObjectFullbrightProgram      :
+                        (LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
+
+    emissive_shader   = (LLPipeline::sImpostorRender)   ? &gObjectEmissiveProgram        :
+                        (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram   : &gObjectEmissiveProgram;
 
-	if (mVertexShaderLevel > 0)
+    if (LLPipeline::sImpostorRender)
 	{
-		// Start out with no shaders.
-		current_shader = target_shader = NULL;
-		LLGLSLShader::bindNoShader();
+        if (mShaderLevel > 0)
+		{
+            fullbright_shader->bind();
+			fullbright_shader->setMinimumAlpha(0.5f);
+            fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+			simple_shader->bind();
+			simple_shader->setMinimumAlpha(0.5f);
+            simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+        }
+        else
+        {
+            gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK
+        }
 	}
+    else
+	{
+        if (mShaderLevel > 0)
+	    {
+			fullbright_shader->bind();
+			fullbright_shader->setMinimumAlpha(0.f);
+            fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+			simple_shader->bind();
+			simple_shader->setMinimumAlpha(0.f);
+            simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+		}
+        else
+        {
+            gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
+        }
+    }
 	gPipeline.enableLightsDynamic();
+
+    LLGLSLShader::bindNoShader();
+	current_shader = NULL;
 }
 
 void LLDrawPoolAlpha::endRenderPass( S32 pass )
 {
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA);
+	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SETUP);
 	LLRenderPass::endRenderPass(pass);
 
 	if(gPipeline.canUseWindLightShaders()) 
@@ -255,38 +276,9 @@ void LLDrawPoolAlpha::render(S32 pass)
 		mAlphaSFactor = LLRender::BF_ZERO;                         // } glow suppression
 		mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;       // }
 		gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
-
-		if (mVertexShaderLevel > 0)
-		{
-			if (LLPipeline::sImpostorRender)
-			{
-				fullbright_shader->bind();
-				fullbright_shader->setMinimumAlpha(0.5f);
-				simple_shader->bind();
-				simple_shader->setMinimumAlpha(0.5f);
-			}				
-			else
-			{
-				fullbright_shader->bind();
-				fullbright_shader->setMinimumAlpha(0.f);
-				simple_shader->bind();
-				simple_shader->setMinimumAlpha(0.f);
-			}
-		}
-		else
-		{
-			if (LLPipeline::sImpostorRender)
-			{
-				gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK
-			}
-			else
-			{
-				gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
-			}
-		}
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass);
 	}
@@ -311,7 +303,7 @@ void LLDrawPoolAlpha::render(S32 pass)
 		}
 		else
 		{
-			gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+			gPipeline.enableLightsFullbright();
 		}
 
 		gGL.diffuseColor4f(1,0,0,1);
@@ -370,11 +362,257 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask)
 	}
 }
 
-static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group");
-static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_PUSH("Alpha Push Verts");
+inline bool IsFullbright(LLDrawInfo& params)
+{
+    return params.mFullbright;
+}
+
+inline bool IsMaterial(LLDrawInfo& params)
+{
+    return params.mMaterial != nullptr;
+}
+
+inline bool IsEmissive(LLDrawInfo& params)
+{
+    return params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE);
+}
+
+inline void Draw(LLDrawInfo* draw, U32 mask)
+{
+    draw->mVertexBuffer->setBuffer(mask);
+    LLRenderPass::applyModelMatrix(*draw);
+	draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);                    
+    gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
+}
+
+bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader)
+{
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_TEX_BINDS);    
+
+    bool tex_setup = false;
+
+    if (deferred_render && use_material && current_shader)
+    {
+        LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
+        if (draw->mNormalMap)
+		{            
+			draw->mNormalMap->addTextureStats(draw->mVSize);
+			current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
+		} 
+						
+		if (draw->mSpecularMap)
+		{
+			draw->mSpecularMap->addTextureStats(draw->mVSize);
+			current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
+		} 
+    }
+    else if (current_shader == simple_shader)
+    {
+        LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(draw->mVSize);	    
+	    LLViewerFetchedTexture::sWhiteImagep->addTextureStats(draw->mVSize);
+        current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);						
+	    current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+    }
+	if (use_shaders && draw->mTextureList.size() > 1)
+	{
+		for (U32 i = 0; i < draw->mTextureList.size(); ++i)
+		{
+			if (draw->mTextureList[i].notNull())
+			{
+				gGL.getTexUnit(i)->bind(draw->mTextureList[i], TRUE);
+			}
+		}
+	}
+	else
+	{ //not batching textures or batch has only 1 texture -- might need a texture matrix
+		if (draw->mTexture.notNull())
+		{
+			draw->mTexture->addTextureStats(draw->mVSize);
+			if (use_shaders && use_material)
+			{
+				current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, draw->mTexture);
+			}
+			else
+			{
+			    gGL.getTexUnit(0)->bind(draw->mTexture, TRUE) ;
+			}
+						
+			if (draw->mTextureMatrix)
+			{
+				tex_setup = true;
+				gGL.getTexUnit(0)->activate();
+				gGL.matrixMode(LLRender::MM_TEXTURE);
+				gGL.loadMatrix((GLfloat*) draw->mTextureMatrix->mMatrix);
+				gPipeline.mTextureMatrixOps++;
+			}
+		}
+		else
+		{
+			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+		}
+	}
+    
+    return tex_setup;
+}
+
+void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
+{
+    if (tex_setup)
+	{
+		gGL.getTexUnit(0)->activate();
+        gGL.matrixMode(LLRender::MM_TEXTURE);
+		gGL.loadIdentity();
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
+	}
+}
+
+void LLDrawPoolAlpha::renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples)
+{
+    gPipeline.enableLightsDynamic();
+    simple_shader->bind();
+	simple_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
+	simple_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
+    simple_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);
+	simple_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f);
+    simple_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 0.0f);
+    bool use_shaders = gPipeline.canUseVertexShaders();
+    for (LLDrawInfo* draw : simples)
+    {
+        bool tex_setup = TexSetup(draw, use_shaders, false, simple_shader);
+        LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
+		gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
+
+	    Draw(draw, mask);
+        RestoreTexSetup(tex_setup);
+    }
+    simple_shader->unbind();
+}
+
+void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights)
+{
+    gPipeline.enableLightsFullbright();
+    fullbright_shader->bind();
+    fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f);
+    bool use_shaders = gPipeline.canUseVertexShaders();
+    for (LLDrawInfo* draw : fullbrights)
+    {
+        bool tex_setup = TexSetup(draw, use_shaders, false, fullbright_shader);
+
+        LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
+		gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
+
+        Draw(draw, mask & ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2));
+        RestoreTexSetup(tex_setup);
+    }
+    fullbright_shader->unbind();
+}
+
+void LLDrawPoolAlpha::renderMaterials(U32 mask, std::vector<LLDrawInfo*>& materials)
+{
+    LLGLSLShader::bindNoShader();
+    current_shader = NULL;
+
+    gPipeline.enableLightsDynamic();
+    bool use_shaders = gPipeline.canUseVertexShaders();
+    for (LLDrawInfo* draw : materials)
+    {
+        U32 mask = draw->mShaderMask;
+
+		llassert(mask < LLMaterial::SHADER_COUNT);
+		target_shader = (LLPipeline::sUnderWaterRender) ? &(gDeferredMaterialWaterProgram[mask]) : &(gDeferredMaterialProgram[mask]);
+
+		if (current_shader != target_shader)
+		{
+            LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
+            if (current_shader)
+            {
+                gPipeline.unbindDeferredShader(*current_shader);
+            }
+			gPipeline.bindDeferredShader(*target_shader);
+            current_shader = target_shader;
+		}
+        
+        bool tex_setup = TexSetup(draw, use_shaders, true, current_shader);
+
+        current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, draw->mSpecColor.mV[0], draw->mSpecColor.mV[1], draw->mSpecColor.mV[2], draw->mSpecColor.mV[3]);						
+		current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, draw->mEnvIntensity);
+		current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, draw->mFullbright ? 1.f : 0.f);
+
+        {
+            LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_TEX_BINDS);
+			if (draw->mNormalMap)
+			{
+				draw->mNormalMap->addTextureStats(draw->mVSize);
+				current_shader->bindTexture(LLShaderMgr::BUMP_MAP, draw->mNormalMap);
+			} 
+						
+			if (draw->mSpecularMap)
+			{
+				draw->mSpecularMap->addTextureStats(draw->mVSize);
+				current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
+			}
+        }
+
+        LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
+		gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
+
+        Draw(draw, mask);
+        RestoreTexSetup(tex_setup);
+    }
+}
+
+void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
+{
+    draw->mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
+	draw->mVertexBuffer->drawRange(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
+	gPipeline.addTrianglesDrawn(draw->mCount, draw->mDrawMode);
+}
+
+void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw)
+{
+    // install glow-accumulating blend mode
+    gGL.blendFunc(
+            LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
+			LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
+
+	emissive_shader->bind();
+					
+	drawEmissive(mask, draw);
+
+	// restore our alpha blend mode
+	gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
+
+    current_shader->bind();
+}
+
+void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
+{
+    emissive_shader->bind();
+    emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
+
+    gPipeline.enableLightsDynamic();
+
+    // install glow-accumulating blend mode
+    // don't touch color, add to alpha (glow)
+	gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE); 
+    bool use_shaders = gPipeline.canUseVertexShaders();
+    for (LLDrawInfo* draw : emissives)
+    {
+        bool tex_setup = TexSetup(draw, use_shaders, false, emissive_shader);
+        drawEmissive(mask, draw);
+        RestoreTexSetup(tex_setup);
+    }
+
+    // restore our alpha blend mode
+	gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
+
+    emissive_shader->unbind();
+}
 
 void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 {
+    BOOL batch_fullbrights = gSavedSettings.getBOOL("RenderAlphaBatchFullbrights");
+    BOOL batch_emissives   = gSavedSettings.getBOOL("RenderAlphaBatchEmissives");
 	BOOL initialized_lighting = FALSE;
 	BOOL light_enabled = TRUE;
 	
@@ -389,10 +627,13 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 		if (group->getSpatialPartition()->mRenderByGroup &&
 		    !group->isDead())
 		{
+            std::vector<LLDrawInfo*> emissives;
+            std::vector<LLDrawInfo*> fullbrights;
+
 			bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE
 													  || group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
 
-			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow.
+			bool draw_glow_for_this_partition = mShaderLevel > 0; // no shaders = no glow.
 
 			
 			LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_GROUP_LOOP);
@@ -405,11 +646,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 			for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)	
 			{
 				LLDrawInfo& params = **k;
-
-				if ((params.mVertexBuffer->getTypeMask() & mask) != mask)
+                U32 have_mask = params.mVertexBuffer->getTypeMask() & mask;
+				if (have_mask != mask)
 				{ //FIXME!
 					LL_WARNS_ONCE() << "Missing required components, expected mask: " << mask
-									<< " present: " << (params.mVertexBuffer->getTypeMask() & mask)
+									<< " present: " << have_mask
 									<< ". Skipping render batch." << LL_ENDL;
 					continue;
 				}
@@ -431,6 +672,12 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 					}
 				}
 
+                if (params.mFullbright && batch_fullbrights)
+				{
+                    fullbrights.push_back(&params);
+                    continue;
+				}
+
 				LLRenderPass::applyModelMatrix(params);
 
 				LLMaterial* mat = NULL;
@@ -445,6 +692,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 					// Turn off lighting if it hasn't already been so.
 					if (light_enabled || !initialized_lighting)
 					{
+                        LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
+
 						initialized_lighting = TRUE;
 						if (use_shaders) 
 						{
@@ -452,7 +701,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 						}
 						else
 						{
-							gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+							gPipeline.enableLightsFullbright();
 						}
 						light_enabled = FALSE;
 					}
@@ -460,6 +709,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 				// Turn on lighting if it isn't already.
 				else if (!light_enabled || !initialized_lighting)
 				{
+                    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_LIGHT_SETUP);
+
 					initialized_lighting = TRUE;
 					if (use_shaders) 
 					{
@@ -486,7 +737,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 
 					if (current_shader != target_shader)
 					{
+                        LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DEFERRED_SHADER_BINDS);
 						gPipeline.bindDeferredShader(*target_shader);
+                        current_shader = target_shader;
 					}
 				}
 				else if (!params.mFullbright)
@@ -501,6 +754,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 				if(use_shaders && (current_shader != target_shader))
 				{// If we need shaders, and we're not ALREADY using the proper shader, then bind it
 				// (this way we won't rebind shaders unnecessarily).
+                    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_SHADER_BINDS);
 					current_shader = target_shader;
 					current_shader->bind();
 				}
@@ -510,83 +764,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 					current_shader = NULL;
 				}
 
-				if (use_shaders && mat)
-				{
-					// We have a material.  Supply the appropriate data here.
-					if (LLPipeline::sRenderDeferred)
-					{
-						current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, params.mSpecColor.mV[0], params.mSpecColor.mV[1], params.mSpecColor.mV[2], params.mSpecColor.mV[3]);						
-						current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, params.mEnvIntensity);
-						current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, params.mFullbright ? 1.f : 0.f);
+                LLVector4 spec_color(1, 1, 1, 1);
+                F32 env_intensity = 0.0f;
+                F32 brightness = 1.0f;
 
-						if (params.mNormalMap)
-						{
-							params.mNormalMap->addTextureStats(params.mVSize);
-							current_shader->bindTexture(LLShaderMgr::BUMP_MAP, params.mNormalMap);
-						} 
-						
-						if (params.mSpecularMap)
-						{
-							params.mSpecularMap->addTextureStats(params.mVSize);
-							current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, params.mSpecularMap);
-						} 
-					}
-
-				} else if (LLPipeline::sRenderDeferred && current_shader && (current_shader == simple_shader))
+                // We have a material.  Supply the appropriate data here.
+				if (use_shaders && mat && deferred_render)
 				{
-					current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, 1.0f, 1.0f, 1.0f, 1.0f);						
-					current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, 0.0f);			
-					LLViewerFetchedTexture::sFlatNormalImagep->addTextureStats(params.mVSize);
-					current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);						
-					LLViewerFetchedTexture::sWhiteImagep->addTextureStats(params.mVSize);
-					current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
-				}
+					spec_color    = params.mSpecColor;
+                    env_intensity = params.mEnvIntensity;
+                    brightness    = params.mFullbright ? 1.f : 0.f;
+                }
+
+                if (current_shader)
+                {
+                    current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]);						
+				    current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity);
+					current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness);
+                }
 
 				if (params.mGroup)
 				{
 					params.mGroup->rebuildMesh();
 				}
 
-				bool tex_setup = false;
-
-				if (use_shaders && params.mTextureList.size() > 1)
-				{
-					for (U32 i = 0; i < params.mTextureList.size(); ++i)
-					{
-						if (params.mTextureList[i].notNull())
-						{
-							gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE);
-						}
-					}
-				}
-				else
-				{ //not batching textures or batch has only 1 texture -- might need a texture matrix
-					if (params.mTexture.notNull())
-					{
-						params.mTexture->addTextureStats(params.mVSize);
-						if (use_shaders && mat)
-						{
-							current_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, params.mTexture);
-						}
-						else
-						{
-						gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ;
-						}
-						
-						if (params.mTextureMatrix)
-						{
-							tex_setup = true;
-							gGL.getTexUnit(0)->activate();
-							gGL.matrixMode(LLRender::MM_TEXTURE);
-							gGL.loadMatrix((GLfloat*) params.mTextureMatrix->mMatrix);
-							gPipeline.mTextureMatrixOps++;
-						}
-					}
-					else
-					{
-						gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-					}
-				}
+                bool tex_setup = TexSetup(&params, use_shaders, use_shaders && (mat != nullptr), current_shader);
 
 				{
 					LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_PUSH);
@@ -596,41 +798,56 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
 					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
 					params.mVertexBuffer->setBuffer(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
 
-					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
-					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
+                    {
+                        LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_DRAW);
+					    params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+					    gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
+                    }
 				}
-				
-				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.
+
+				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha.
 				if (current_shader && 
 					draw_glow_for_this_partition &&
 					params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
 				{
-					// install glow-accumulating blend mode
-					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
-					LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
-
-					emissive_shader->bind();
-					
-					params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
-					
-					// do the actual drawing, again
-					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
-					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode);
-
-					// restore our alpha blend mode
-					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
-
-					current_shader->bind();
+                    LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_EMISSIVE);
+
+                    if (batch_emissives)
+                    {
+                        emissives.push_back(&params);
+                    }
+                    else
+                    {
+                        drawEmissiveInline(mask, &params);
+                    } 
 				}
 			
 				if (tex_setup)
 				{
 					gGL.getTexUnit(0)->activate();
+                    gGL.matrixMode(LLRender::MM_TEXTURE);
 					gGL.loadIdentity();
 					gGL.matrixMode(LLRender::MM_MODELVIEW);
 				}
 			}
-		}
+
+            if (batch_fullbrights)
+            {
+                light_enabled = false;
+                renderFullbrights(mask, fullbrights);
+            }
+
+            if (batch_emissives)
+            {
+                light_enabled = true;
+                renderEmissives(mask, emissives);
+            }
+
+            if (current_shader)
+            {
+                current_shader->bind();
+            }
+		}        
 	}
 
 	gGL.setSceneBlendType(LLRender::BT_ALPHA);
diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h
index d064a3a324b7522c97b395d86c4e48b125292ec4..a069f805e827c4d5b175a8a2224b8fa821da6c9d 100644
--- a/indra/newview/lldrawpoolalpha.h
+++ b/indra/newview/lldrawpoolalpha.h
@@ -75,6 +75,17 @@ class LLDrawPoolAlpha: public LLRenderPass
 	LLGLSLShader* fullbright_shader;	
 	LLGLSLShader* emissive_shader;
 
+    void renderSimples(U32 mask, std::vector<LLDrawInfo*>& simples);
+    void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
+    void renderMaterials(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
+    void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
+
+    void drawEmissive(U32 mask, LLDrawInfo* draw);
+    void drawEmissiveInline(U32 mask, LLDrawInfo* draw);
+
+    bool TexSetup(LLDrawInfo* draw, bool use_shaders, bool use_material, LLGLSLShader* current_shader);
+    void RestoreTexSetup(bool tex_setup);
+
 	// our 'normal' alpha blend function for this pass
 	LLRender::eBlendFactor mColorSFactor;
 	LLRender::eBlendFactor mColorDFactor;	
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 63abadbcf4299e786fddc24bc3aa4b05e959cc59..789a254389b8e34ed46ed82b9f293ede3567a848 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -38,6 +38,7 @@
 #include "lldrawable.h"
 #include "lldrawpoolbump.h"
 #include "llface.h"
+#include "llvolume.h"
 #include "llmeshrepository.h"
 #include "llsky.h"
 #include "llviewercamera.h"
@@ -145,16 +146,16 @@ LLDrawPool *LLDrawPoolAvatar::instancePool()
 }
 
 
-S32 LLDrawPoolAvatar::getVertexShaderLevel() const
+S32 LLDrawPoolAvatar::getShaderLevel() const
 {
-	return (S32) LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
+	return (S32) LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
 }
 
 void LLDrawPoolAvatar::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR);
 	
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	
 	if (sShaderLevel > 0)
 	{
@@ -305,7 +306,7 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
 void LLDrawPoolAvatar::beginPostDeferredAlpha()
 {
 	sSkipOpaque = TRUE;
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram = &gDeferredAvatarAlphaProgram;
 	sRenderingSkinned = TRUE;
 
@@ -396,7 +397,7 @@ void LLDrawPoolAvatar::endPostDeferredAlpha()
 		
 	gPipeline.unbindDeferredShader(*sVertexProgram);
 	sDiffuseChannel = 0;
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 }
 
 void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
@@ -455,8 +456,13 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 		sVertexProgram = &gDeferredAvatarAlphaShadowProgram;
 
         // bind diffuse tex so we can reference the alpha channel...
-        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-		
+        S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
+        sDiffuseChannel = 0;
+        if (loc != -1)
+        {
+            sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		}
+
 		if ((sShaderLevel > 0))  // for hardware blending
 		{
 			sRenderingSkinned = TRUE;
@@ -470,8 +476,13 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 		sVertexProgram = &gDeferredAvatarAlphaMaskShadowProgram;
 
         // bind diffuse tex so we can reference the alpha channel...
-        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-		
+        S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
+        sDiffuseChannel = 0;
+        if (loc != -1)
+        {
+            sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		}
+
 		if ((sShaderLevel > 0))  // for hardware blending
 		{
 			sRenderingSkinned = TRUE;
@@ -485,7 +496,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 		sVertexProgram = &gDeferredAttachmentAlphaShadowProgram;
 
         // bind diffuse tex so we can reference the alpha channel...
-        sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+        S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
+        sDiffuseChannel = 0;
+        if (loc != -1)
+        {
+            sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		}
 		
 		if ((sShaderLevel > 0))  // for hardware blending
 		{
@@ -500,7 +516,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 		sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram;
 
         // bind diffuse tex so we can reference the alpha channel...
-		sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
+        sDiffuseChannel = 0;
+        if (loc != -1)
+        {
+            sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		}
 
 		if ((sShaderLevel > 0))  // for hardware blending
 		{
@@ -513,7 +534,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
 	else // SHADOW_PASS_ATTACHMENT_OPAQUE
 	{
 		sVertexProgram = &gDeferredAttachmentShadowProgram;
-		sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
+        sDiffuseChannel = 0;
+        if (loc != -1)
+        {
+            sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+		}
 		sVertexProgram->bind();
 	}
 }
@@ -776,7 +802,7 @@ void LLDrawPoolAvatar::beginImpostor()
 		gImpostorProgram.setMinimumAlpha(0.01f);
 	}
 
-	gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+	gPipeline.enableLightsFullbright();
 	sDiffuseChannel = 0;
 }
 
@@ -806,6 +832,14 @@ void LLDrawPoolAvatar::beginRigid()
 		{	//eyeballs render with the specular shader
 			sVertexProgram->bind();
 			sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
+            if (LLPipeline::sRenderingHUDs)
+	        {
+		        sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	        }
+	        else
+	        {
+		        sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	        }
 		}
 	}
 	else
@@ -816,7 +850,7 @@ void LLDrawPoolAvatar::beginRigid()
 
 void LLDrawPoolAvatar::endRigid()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	if (sVertexProgram != NULL)
 	{
 		sVertexProgram->unbind();
@@ -841,7 +875,7 @@ void LLDrawPoolAvatar::beginDeferredImpostor()
 
 void LLDrawPoolAvatar::endDeferredImpostor()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL);
 	sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -856,11 +890,19 @@ void LLDrawPoolAvatar::beginDeferredRigid()
 	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	sVertexProgram->bind();
 	sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
+    if (LLPipeline::sRenderingHUDs)
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 }
 
 void LLDrawPoolAvatar::endDeferredRigid()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	sVertexProgram->unbind();
 	gGL.getTexUnit(0)->activate();
@@ -899,6 +941,14 @@ void LLDrawPoolAvatar::beginSkinned()
 
 		sVertexProgram->bind();
 		sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 		gGL.getTexUnit(0)->activate();
 	}
 	else
@@ -908,6 +958,14 @@ void LLDrawPoolAvatar::beginSkinned()
 			// software skinning, use a basic shader for windlight.
 			// TODO: find a better fallback method for software skinning.
 			sVertexProgram->bind();
+            if (LLPipeline::sRenderingHUDs)
+	        {
+		        sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	        }
+	        else
+	        {
+		        sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	        }
 		}
 	}
 
@@ -926,7 +984,7 @@ void LLDrawPoolAvatar::endSkinned()
 		sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
 		gGL.getTexUnit(0)->activate();
 		sVertexProgram->unbind();
-		sShaderLevel = mVertexShaderLevel;
+		sShaderLevel = mShaderLevel;
 	}
 	else
 	{
@@ -970,6 +1028,14 @@ void LLDrawPoolAvatar::beginRiggedSimple()
 	{
 		sDiffuseChannel = 0;
 		sVertexProgram->bind();
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 }
 
@@ -1035,6 +1101,16 @@ void LLDrawPoolAvatar::beginRiggedGlow()
 		sVertexProgram->bind();
 
 		sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f);
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
+
 		F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
 		sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
 	}
@@ -1082,16 +1158,22 @@ void LLDrawPoolAvatar::beginRiggedFullbright()
 		sDiffuseChannel = 0;
 		sVertexProgram->bind();
 
-		if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred)
+        if (LLPipeline::sRenderingHUDs)
+        {            
+            sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+        }
+		else if (LLPipeline::sRenderDeferred)
 		{
-			sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+            sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+			F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+			sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
 		} 
 		else 
 		{
-			sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
-
-			F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
-			sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
+            sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
 		}
 	}
 }
@@ -1134,6 +1216,14 @@ void LLDrawPoolAvatar::beginRiggedShinySimple()
 	if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
 	{
 		sVertexProgram->bind();
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 		LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
 	}
 }
@@ -1184,17 +1274,32 @@ void LLDrawPoolAvatar::beginRiggedFullbrightShiny()
 	if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
 	{
 		sVertexProgram->bind();
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 		LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
 
-		if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred)
+        if (LLPipeline::sRenderingHUDs)
 		{
 			sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
-		} 
-		else 
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+        }
+		else if (LLPipeline::sRenderDeferred)
 		{
-			sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+            sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
 			F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
 			sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+        }
+        else
+        {
+			sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+            sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
 		}
 	}
 }
@@ -1216,6 +1321,14 @@ void LLDrawPoolAvatar::beginDeferredRiggedSimple()
 	sVertexProgram = &gDeferredSkinnedDiffuseProgram;
 	sDiffuseChannel = 0;
 	sVertexProgram->bind();
+    if (LLPipeline::sRenderingHUDs)
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 }
 
 void LLDrawPoolAvatar::endDeferredRiggedSimple()
@@ -1229,6 +1342,14 @@ void LLDrawPoolAvatar::beginDeferredRiggedBump()
 {
 	sVertexProgram = &gDeferredSkinnedBumpProgram;
 	sVertexProgram->bind();
+    if (LLPipeline::sRenderingHUDs)
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 	normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
 	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 }
@@ -1261,6 +1382,14 @@ void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass)
 	}
 
 	sVertexProgram->bind();
+    if (LLPipeline::sRenderingHUDs)
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 	normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
 	specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
 	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
@@ -1288,13 +1417,21 @@ void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass)
 
 void LLDrawPoolAvatar::beginDeferredSkinned()
 {
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 	sVertexProgram = &gDeferredAvatarProgram;
 	sRenderingSkinned = TRUE;
 
 	sVertexProgram->bind();
 	sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
-	
+	if (LLPipeline::sRenderingHUDs)
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
+
 	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 	gGL.getTexUnit(0)->activate();
 }
@@ -1307,7 +1444,7 @@ void LLDrawPoolAvatar::endDeferredSkinned()
 
 	sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
 
-	sShaderLevel = mVertexShaderLevel;
+	sShaderLevel = mShaderLevel;
 
 	gGL.getTexUnit(0)->activate();
 }
@@ -1697,15 +1834,13 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
     LLFace* face,
     const LLMeshSkinInfo* skin,
     LLVolume* volume,
-    const LLVolumeFace& vol_face)
+    LLVolumeFace& vol_face)
 {
 	LLVector4a* weights = vol_face.mWeights;
 	if (!weights)
 	{
 		return;
 	}
-    // FIXME ugly const cast
-    LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
 
 	LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
 	LLDrawable* drawable = face->getDrawable();
@@ -1715,6 +1850,48 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
 		return;
 	}
 
+    const U32 max_joints = LLSkinningUtil::getMaxJointCount();
+
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+    #define CONDITION_WEIGHT(f) ((U8)llclamp((S32)f, (S32)0, (S32)max_joints-1))
+    LLVector4a* just_weights = vol_face.mJustWeights;
+    // we need to calculate the separated indices and store just the matrix weights for this vol...
+    if (!vol_face.mJointIndices)
+    {
+        // not very consty after all...
+        vol_face.allocateJointIndices(vol_face.mNumVertices);
+        just_weights = vol_face.mJustWeights;
+
+        U8* joint_indices_cursor = vol_face.mJointIndices;
+        for (int i = 0; i < vol_face.mNumVertices; i++)
+        {
+            F32* w = weights[i].getF32ptr();
+            F32* w_ = just_weights[i].getF32ptr();
+
+            F32 w0 = floorf(w[0]);
+            F32 w1 = floorf(w[1]);
+            F32 w2 = floorf(w[2]);
+            F32 w3 = floorf(w[3]);
+
+            joint_indices_cursor[0] = CONDITION_WEIGHT(w0);
+            joint_indices_cursor[1] = CONDITION_WEIGHT(w1);
+            joint_indices_cursor[2] = CONDITION_WEIGHT(w2);
+            joint_indices_cursor[3] = CONDITION_WEIGHT(w3);
+
+            // remove joint portion of combined weight
+            w_[0] = w[0] - w0;
+            w_[1] = w[1] - w1;
+            w_[2] = w[2] - w2;
+            w_[3] = w[3] - w3;
+
+            joint_indices_cursor += 4;
+        }
+    }
+#endif
+
+    // FIXME ugly const cast
+    LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
+
 	U32 data_mask = face->getRiggedVertexBufferDataMask();
 
     if (!vol_face.mWeightsScrubbed)
@@ -1791,29 +1968,67 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
 		LLMatrix4a bind_shape_matrix;
 		bind_shape_matrix.loadu(skin->mBindShapeMatrix);
 
-        const U32 max_joints = LLSkinningUtil::getMaxJointCount();
-		for (U32 j = 0; j < buffer->getNumVerts(); ++j)
-		{
-			LLMatrix4a final_mat;
-            LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints);
-			
-			LLVector4a& v = vol_face.mPositions[j];
-
-			LLVector4a t;
-			LLVector4a dst;
-			bind_shape_matrix.affineTransform(v, t);
-			final_mat.affineTransform(t, dst);
-			pos[j] = dst;
-
-			if (norm)
-			{
-				LLVector4a& n = vol_face.mNormals[j];
-				bind_shape_matrix.rotate(n, t);
-				final_mat.rotate(t, dst);
-				dst.normalize3fast();
-				norm[j] = dst;
-			}
-		}
+#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+        U8* joint_indices_cursor = vol_face.mJointIndices;
+        // fast path with joint indices separate from weights
+        if (joint_indices_cursor)
+        {
+            LLMatrix4a src[4];
+		    for (U32 j = 0; j < buffer->getNumVerts(); ++j)
+		    {
+			    LLMatrix4a final_mat;
+                //LLMatrix4a final_mat_correct;
+
+                F32* jw = just_weights[j].getF32ptr();
+
+                LLSkinningUtil::getPerVertexSkinMatrixWithIndices(jw, joint_indices_cursor, mat, final_mat, src);                
+
+                joint_indices_cursor += 4;
+
+			    LLVector4a& v = vol_face.mPositions[j];
+
+			    LLVector4a t;
+			    LLVector4a dst;
+			    bind_shape_matrix.affineTransform(v, t);
+			    final_mat.affineTransform(t, dst);
+			    pos[j] = dst;
+
+			    if (norm)
+			    {
+				    LLVector4a& n = vol_face.mNormals[j];
+				    bind_shape_matrix.rotate(n, t);
+				    final_mat.rotate(t, dst);
+				    dst.normalize3fast();
+				    norm[j] = dst;
+			    }
+		    }
+        }
+        // slow path with joint indices calculated from weights
+        else
+#endif
+        {
+            for (U32 j = 0; j < buffer->getNumVerts(); ++j)
+		    {
+			    LLMatrix4a final_mat;
+                LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints);
+
+			    LLVector4a& v = vol_face.mPositions[j];
+			    LLVector4a t;
+			    LLVector4a dst;
+			    bind_shape_matrix.affineTransform(v, t);
+			    final_mat.affineTransform(t, dst);
+			    pos[j] = dst;
+
+			    if (norm)
+			    {
+				    LLVector4a& n = vol_face.mNormals[j];
+				    bind_shape_matrix.rotate(n, t);
+				    final_mat.rotate(t, dst);
+				    //dst.normalize3fast();
+				    norm[j] = dst;
+			    }
+		    }
+        }
 	}
 }
 
@@ -2079,12 +2294,24 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 
 			if (face->mTextureMatrix && vobj->mTexAnimMode)
 			{
-				gGL.matrixMode(LLRender::MM_TEXTURE);
-				gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix);
+                U32 tex_index = gGL.getCurrentTexUnitIndex();
+
+                if (tex_index <= 1)
+                {
+                    gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index));
+                    gGL.pushMatrix();
+				    gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix);
+                }
+
 				buff->setBuffer(data_mask);
 				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
+
+                if (tex_index <= 1)
+                {
+                    gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index));
+				    gGL.popMatrix();
+                    gGL.matrixMode(LLRender::MM_MODELVIEW);
+                }
 			}
 			else
 			{
@@ -2153,7 +2380,7 @@ void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
 
 			stop_glerror();
 
-			const LLVolumeFace& vol_face = volume->getVolumeFace(te);
+			LLVolumeFace& vol_face = volume->getVolumeFace(te);
 			updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face);
 		}
 	}
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 8c1bc70c8e4630a45e5a71707c2efe1a6d72ec33..cb09eb18e2152bc3ef35b8aee6aa55d1dd21be68 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -57,6 +57,7 @@ class LLDrawPoolAvatar : public LLFacePool
 
     ~LLDrawPoolAvatar();
     /*virtual*/ BOOL isDead();
+
     typedef enum
 	{
 		RIGGED_MATERIAL=0,
@@ -175,7 +176,7 @@ typedef enum
 
 	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
 
-	virtual S32 getVertexShaderLevel() const;
+	virtual S32 getShaderLevel() const;
 
 	LLDrawPoolAvatar();
 
@@ -256,7 +257,7 @@ typedef enum
 									  LLFace* facep, 
 									  const LLMeshSkinInfo* skin, 
 									  LLVolume* volume,
-									  const LLVolumeFace& vol_face);
+									  LLVolumeFace& vol_face);
 	void updateRiggedVertexBuffers(LLVOAvatar* avatar);
 
 	void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false);
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 7b9fd5c6c634fe007923e59377f1246bfc4927ef..14069fa6c2bbef8b940093d12efada767f464049 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -193,7 +193,7 @@ LLDrawPoolBump::LLDrawPoolBump()
 
 void LLDrawPoolBump::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 // static
@@ -201,7 +201,7 @@ S32 LLDrawPoolBump::numBumpPasses()
 {
 	if (gSavedSettings.getBOOL("RenderObjectBump"))
 	{
-		if (mVertexShaderLevel > 1)
+		if (mShaderLevel > 1)
 		{
 			if (LLPipeline::sImpostorRender)
 			{
@@ -241,7 +241,7 @@ void LLDrawPoolBump::beginRenderPass(S32 pass)
 			beginShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				beginFullbrightShiny();
 			}
@@ -274,7 +274,7 @@ void LLDrawPoolBump::render(S32 pass)
 			renderShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				renderFullbrightShiny();
 			}
@@ -301,7 +301,7 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
 			endShiny();
 			break;
 		case 1:
-			if (mVertexShaderLevel > 1)
+			if (mShaderLevel > 1)
 			{
 				endFullbrightShiny();
 			}
@@ -335,12 +335,12 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 	mShiny = TRUE;
 	sVertexMask = VERTEX_MASK_SHINY;
 	// Second pass: environment map
-	if (!invisible && mVertexShaderLevel > 1)
+	if (!invisible && mShaderLevel > 1)
 	{
 		sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
 	}
 	
-	if (getVertexShaderLevel() > 0)
+	if (getShaderLevel() > 0)
 	{
 		if (LLPipeline::sUnderWaterRender)
 		{
@@ -351,15 +351,23 @@ void LLDrawPoolBump::beginShiny(bool invisible)
 			shader = &gObjectShinyProgram;
 		}
 		shader->bind();
+        if (LLPipeline::sRenderingHUDs)
+        {
+            shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+        }
+        else
+        {
+            shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+        }
 	}
 	else
 	{
 		shader = NULL;
 	}
 
-	bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+	bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
 
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //indexed texture rendering, channel 0 is always diffuse
 		diffuse_channel = 0;
 	}
@@ -428,7 +436,7 @@ void LLDrawPoolBump::renderShiny(bool invisible)
 	if( gSky.mVOSkyp->getCubeMap() )
 	{
 		LLGLEnable blend_enable(GL_BLEND);
-		if (!invisible && mVertexShaderLevel > 1)
+		if (!invisible && mShaderLevel > 1)
 		{
 			LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		}
@@ -453,7 +461,7 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
 		{
 			shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
 					
-			if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
+			if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
 			{
 				if (diffuse_channel != 0)
 				{
@@ -486,7 +494,7 @@ void LLDrawPoolBump::endShiny(bool invisible)
 		return;
 	}
 
-	unbindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible);
+	unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
 	if (shader)
 	{
 		shader->unbind();
@@ -534,6 +542,15 @@ void LLDrawPoolBump::beginFullbrightShiny()
 					 LLVector4(gGLModelView+8),
 					 LLVector4(gGLModelView+12));
 		shader->bind();
+        if (LLPipeline::sRenderingHUDs)
+        {
+            shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+        }
+        else
+        {
+            shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+        }
+
 		LLVector3 vec = LLVector3(gShinyOrigin) * mat;
 		LLVector4 vec4(vec, gShinyOrigin.mV[3]);
 		shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);			
@@ -551,7 +568,7 @@ void LLDrawPoolBump::beginFullbrightShiny()
 		gGL.getTexUnit(0)->activate();
 	}
 
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //indexed texture rendering, channel 0 is always diffuse
 		diffuse_channel = 0;
 	}
@@ -571,7 +588,7 @@ void LLDrawPoolBump::renderFullbrightShiny()
 	{
 		LLGLEnable blend_enable(GL_BLEND);
 
-		if (mVertexShaderLevel > 1)
+		if (mShaderLevel > 1)
 		{
 			LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		}
@@ -1524,7 +1541,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL
 			tex_setup = true;
 		}
 
-		if (mShiny && mVertexShaderLevel > 1 && texture)
+		if (mShiny && mShaderLevel > 1 && texture)
 		{
 			if (params.mTexture.notNull())
 			{
diff --git a/indra/newview/lldrawpoolground.cpp b/indra/newview/lldrawpoolground.cpp
index 59c3fbf7a125bf6ab727770e59ffc606d4bfeedc..6bd2631d3b2badc315e0a494b3eebe432e20e5ab 100644
--- a/indra/newview/lldrawpoolground.cpp
+++ b/indra/newview/lldrawpoolground.cpp
@@ -53,7 +53,7 @@ LLDrawPool *LLDrawPoolGround::instancePool()
 
 void LLDrawPoolGround::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
 }
 
 void LLDrawPoolGround::render(S32 pass)
@@ -63,13 +63,9 @@ void LLDrawPoolGround::render(S32 pass)
 		return;
 	}	
 	
-	LLGLSPipelineSkyBox gls_skybox;
+	LLGLSPipelineDepthTestSkyBox gls_skybox(true, false);
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
-	LLGLSquashToFarClip far_clip(glh_get_current_projection());
-
 	F32 water_height = gAgent.getRegion()->getWaterHeight();
 	gGL.pushMatrix();
 	LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
@@ -77,8 +73,6 @@ void LLDrawPoolGround::render(S32 pass)
 
 	LLFace *facep = mDrawFace[0];
 
-	gPipeline.disableLights();
-
 	LLOverrideFaceColor col(this, gSky.mVOSkyp->getGLFogColor());
 	facep->renderIndexed();
 	
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index 63e96a93b53e530d5a5fec93b6a767a2b3938d2f..05b0c1f1a93c6c666bee6916611e082206dccdd9 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -42,7 +42,7 @@ LLDrawPoolMaterials::LLDrawPoolMaterials()
 
 void LLDrawPoolMaterials::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); 
 }
 
 S32 LLDrawPoolMaterials::getNumDeferredPasses()
@@ -81,6 +81,15 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
 
 	mShader->bind();
 
+    if (LLPipeline::sRenderingHUDs)
+    {
+        mShader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+    }
+    else
+    {
+        mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+    }
+
 	diffuse_channel = mShader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
 		
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_MATERIALS);
@@ -194,7 +203,7 @@ void LLDrawPoolMaterials::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture,
 			tex_setup = true;
 		}
 		
-		if (mVertexShaderLevel > 1 && texture)
+		if (mShaderLevel > 1 && texture)
 		{
 			if (params.mTexture.notNull())
 			{
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index bd180de6c608ef9a6cf5c3c3ca110bea43a0151e..f211cf6e27b6c24b981d9366d1b6f2e290f00795 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -47,6 +47,14 @@ void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
 {
 	gDeferredEmissiveProgram.bind();
 	gDeferredEmissiveProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+    if (LLPipeline::sRenderingHUDs)
+	{
+		gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 }
 
 static LLTrace::BlockTimerStatHandle FTM_RENDER_GLOW_PUSH("Glow Push");
@@ -82,7 +90,7 @@ void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
 
 S32 LLDrawPoolGlow::getNumPasses()
 {
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
 	{
 		return 1;
 	}
@@ -103,7 +111,7 @@ void LLDrawPoolGlow::render(S32 pass)
 	glPolygonOffset(-1.0f, -1.0f);
 	gGL.setSceneBlendType(LLRender::BT_ADD);
 	
-	U32 shader_level = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	U32 shader_level = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 
 	//should never get here without basic shaders enabled
 	llassert(shader_level > 0);
@@ -119,6 +127,15 @@ void LLDrawPoolGlow::render(S32 pass)
 		shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
 	}	
 
+    if (LLPipeline::sRenderingHUDs)
+	{
+		shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
+
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 	gGL.setColorMask(false, true);
 
@@ -147,7 +164,7 @@ LLDrawPoolSimple::LLDrawPoolSimple() :
 
 void LLDrawPoolSimple::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolSimple::beginRenderPass(S32 pass)
@@ -167,9 +184,18 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass)
 		simple_shader = &gObjectSimpleProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 	else 
 	{
@@ -187,7 +213,7 @@ void LLDrawPoolSimple::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -201,7 +227,7 @@ void LLDrawPoolSimple::render(S32 pass)
 		LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
 		gPipeline.enableLightsDynamic();
 
-		if (mVertexShaderLevel > 0)
+		if (mShaderLevel > 0)
 		{
 			U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
 
@@ -244,7 +270,7 @@ LLDrawPoolAlphaMask::LLDrawPoolAlphaMask() :
 
 void LLDrawPoolAlphaMask::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
@@ -260,9 +286,18 @@ void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
 		simple_shader = &gObjectSimpleAlphaMaskProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 	else 
 	{
@@ -280,7 +315,7 @@ void LLDrawPoolAlphaMask::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -291,11 +326,20 @@ void LLDrawPoolAlphaMask::render(S32 pass)
 	LLGLDisable blend(GL_BLEND);
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
 	
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 		simple_shader->setMinimumAlpha(0.33f);
 
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
+
 		pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
@@ -317,7 +361,7 @@ LLDrawPoolFullbrightAlphaMask::LLDrawPoolFullbrightAlphaMask() :
 
 void LLDrawPoolFullbrightAlphaMask::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
@@ -333,9 +377,18 @@ void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
 		simple_shader = &gObjectFullbrightAlphaMaskProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 	else 
 	{
@@ -353,7 +406,7 @@ void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass)
 	stop_glerror();
 	LLRenderPass::endRenderPass(pass);
 	stop_glerror();
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -363,18 +416,30 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		if (simple_shader)
 		{
 			simple_shader->bind();
 			simple_shader->setMinimumAlpha(0.33f);
-			if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred)
-			{
-				simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
-			} else {
-				simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
-			}
+
+            if (LLPipeline::sRenderingHUDs)
+	        {
+		        simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+                simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+	        }
+	        else
+	        {
+		        simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+                if (LLPipeline::sRenderDeferred)
+			    {
+                    simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);				    
+			    }
+                else
+                {
+				    simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+			    }
+	        }
 		}
 		pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 		//LLGLSLShader::bindNoShader();
@@ -382,7 +447,7 @@ void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
 	else
 	{
 		LLGLEnable test(GL_ALPHA_TEST);
-		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		gPipeline.enableLightsFullbright();
 		pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE);
 		gPipeline.enableLightsDynamic();
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
@@ -397,6 +462,15 @@ void LLDrawPoolSimple::beginDeferredPass(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
 	gDeferredDiffuseProgram.bind();
+
+    if (LLPipeline::sRenderingHUDs)
+	{
+		gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
 }
 
 void LLDrawPoolSimple::endDeferredPass(S32 pass)
@@ -435,6 +509,16 @@ void LLDrawPoolAlphaMask::renderDeferred(S32 pass)
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_DEFERRED);
 	gDeferredDiffuseAlphaMaskProgram.bind();
 	gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f);
+
+    if (LLPipeline::sRenderingHUDs)
+	{
+		gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+	}
+	else
+	{
+		gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+	}
+
 	pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
 	gDeferredDiffuseAlphaMaskProgram.unbind();			
 }
@@ -449,7 +533,7 @@ LLDrawPoolGrass::LLDrawPoolGrass() :
 
 void LLDrawPoolGrass::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 
@@ -467,10 +551,18 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass)
 		simple_shader = &gObjectAlphaMaskNonIndexedProgram;
 	}
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->bind();
 		simple_shader->setMinimumAlpha(0.5f);
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 	else 
 	{
@@ -488,7 +580,7 @@ void LLDrawPoolGrass::endRenderPass(S32 pass)
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS);
 	LLRenderPass::endRenderPass(pass);
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		simple_shader->unbind();
 	}
@@ -527,6 +619,16 @@ void LLDrawPoolGrass::renderDeferred(S32 pass)
 		LL_RECORD_BLOCK_TIME(FTM_RENDER_GRASS_DEFERRED);
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.bind();
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.setMinimumAlpha(0.5f);
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    gDeferredNonIndexedDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    gDeferredNonIndexedDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
+
 		//render grass
 		LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask());
 	}			
@@ -541,7 +643,7 @@ LLDrawPoolFullbright::LLDrawPoolFullbright() :
 
 void LLDrawPoolFullbright::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
@@ -553,6 +655,15 @@ void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
 	else
 	{
 		gDeferredFullbrightProgram.bind();
+
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
 	}
 	
 }
@@ -600,7 +711,7 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass)
 
 	stop_glerror();
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		fullbright_shader->unbind();
 	}
@@ -615,12 +726,21 @@ void LLDrawPoolFullbright::render(S32 pass)
 
 	stop_glerror();
 
-	if (mVertexShaderLevel > 0)
+	if (mShaderLevel > 0)
 	{
 		fullbright_shader->bind();
 		fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f);
 		fullbright_shader->uniform1f(LLViewerShaderMgr::TEXTURE_GAMMA, 1.f);
 
+        if (LLPipeline::sRenderingHUDs)
+	    {
+		    fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+	    }
+	    else
+	    {
+		    fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+	    }
+
 		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
 		pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
 		pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE);
@@ -630,7 +750,7 @@ void LLDrawPoolFullbright::render(S32 pass)
 	}
 	else
 	{
-		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		gPipeline.enableLightsFullbright();
 		U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
 		renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
 		pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask);
@@ -651,23 +771,32 @@ S32 LLDrawPoolFullbright::getNumPasses()
 void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass)
 {
 	
-	if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred)
-	{
-		gObjectFullbrightAlphaMaskProgram.bind();
+    if (LLPipeline::sRenderingHUDs)
+    {
+        gObjectFullbrightAlphaMaskProgram.bind();
 		gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
-	} 
-	else 
-	{	
-		if (LLPipeline::sUnderWaterRender)
+        gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+    }
+	else if (LLPipeline::sRenderDeferred)
+	{
+        if (LLPipeline::sUnderWaterRender)
 		{
 			gDeferredFullbrightAlphaMaskWaterProgram.bind();
 			gDeferredFullbrightAlphaMaskWaterProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+            gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
 		}
 		else
 		{
 			gDeferredFullbrightAlphaMaskProgram.bind();
 			gDeferredFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+            gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
 		}
+    }
+    else
+    {
+		gObjectFullbrightAlphaMaskProgram.bind();
+		gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+        gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
 	}
 }
 
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index bdb16abc78c23ffac3e67aefb0a8d0b7d4adec97..dbe8724088716f844bd60a368dba81c721891239 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -55,7 +55,7 @@ LLDrawPool *LLDrawPoolSky::instancePool()
 
 void LLDrawPoolSky::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); 
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT); 
 	gSky.mVOSkyp->updateGeometry(gSky.mVOSkyp->mDrawable);
 }
 
@@ -75,7 +75,7 @@ void LLDrawPoolSky::render(S32 pass)
 	}
 	
 	// don't render sky under water (background just gets cleared to fog color)
-	if(mVertexShaderLevel > 0 && LLPipeline::sUnderWaterRender)
+	if(mShaderLevel > 0 && LLPipeline::sUnderWaterRender)
 	{
 		return;
 	}
@@ -98,18 +98,10 @@ void LLDrawPoolSky::render(S32 pass)
 	}
 	
 
-	LLGLSPipelineSkyBox gls_skybox;
+	LLGLSPipelineDepthTestSkyBox gls_skybox(true, false);
 
-	LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE);
-
-	LLGLSquashToFarClip far_clip(glh_get_current_projection());
-
-	LLGLEnable fog_enable( (mVertexShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
-
-	gPipeline.disableLights();
+	LLGLEnable fog_enable( (mShaderLevel < 1 && LLViewerCamera::getInstance()->cameraUnderWater()) ? GL_FOG : 0);
 	
-	LLGLDisable clip(GL_CLIP_PLANE0);
-
 	gGL.pushMatrix();
 	LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
 	gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
@@ -119,35 +111,52 @@ void LLDrawPoolSky::render(S32 pass)
 	LLVertexBuffer::unbind();
 	gGL.diffuseColor4f(1,1,1,1);
 
-	for (S32 i = 0; i < llmin(6, face_count); ++i)
+	for (S32 i = 0; i < face_count; ++i)
 	{
-		renderSkyCubeFace(i);
+		renderSkyFace(i);
 	}
 
 	gGL.popMatrix();
 }
 
-void LLDrawPoolSky::renderSkyCubeFace(U8 side)
+void LLDrawPoolSky::renderSkyFace(U8 index)
 {
-	LLFace &face = *mDrawFace[LLVOSky::FACE_SIDE0 + side];
-	if (!face.getGeomCount())
+	LLFace* face = mDrawFace[index];
+
+	if (!face || !face->getGeomCount())
 	{
 		return;
 	}
 
-	llassert(mSkyTex);
-	mSkyTex[side].bindTexture(TRUE);
-	
-	face.renderIndexed();
-
-	if (LLSkyTex::doInterpolate())
-	{
-		
-		LLGLEnable blend(GL_BLEND);
-		mSkyTex[side].bindTexture(FALSE);
-		gGL.diffuseColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled
-		face.renderIndexed();
-	}
+    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...
+    {
+        LLGLEnable blend(GL_BLEND);
+
+        LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
+        if (tex)
+        {
+            gGL.getTexUnit(0)->bind(tex, true);
+            face->renderIndexed();
+        }
+    }
 }
 
 void LLDrawPoolSky::endRenderPass( S32 pass )
diff --git a/indra/newview/lldrawpoolsky.h b/indra/newview/lldrawpoolsky.h
index 098bd2134ae28b60f3085bf34439f4a649d0e54b..916d8c1cbe7243892900a4db5dcf6b59cf058537 100644
--- a/indra/newview/lldrawpoolsky.h
+++ b/indra/newview/lldrawpoolsky.h
@@ -61,7 +61,7 @@ class LLDrawPoolSky : public LLFacePool
 	/*virtual*/ void endRenderPass(S32 pass);
 	void setSkyTex(LLSkyTex* const st) { mSkyTex = st; }
 
-	void renderSkyCubeFace(U8 side);
+	void renderSkyFace(U8 index);
 	void renderHeavenlyBody(U8 hb, LLFace* face);
 	void renderSunHalo(LLFace* face);
 
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 3eefcef7aac66263687d915f02da932539c5b579..33a11631fef9662b2487697c977ad8483f870ba0 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -48,6 +48,8 @@
 #include "pipeline.h"
 #include "llviewershadermgr.h"
 #include "llrender.h"
+#include "llenvironment.h"
+#include "llsettingsvo.h"
 
 const F32 DETAIL_SCALE = 1.f/16.f;
 int DebugDetailMap = 0;
@@ -110,7 +112,7 @@ U32 LLDrawPoolTerrain::getVertexDataMask()
 
 void LLDrawPoolTerrain::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT);
 	sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
 }
 
@@ -123,7 +125,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass )
 					&gTerrainWaterProgram :
 					&gTerrainProgram;	
 
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0)
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
 	{
 		sShader->bind();
 	}
@@ -134,7 +136,7 @@ void LLDrawPoolTerrain::endRenderPass( S32 pass )
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN);
 	//LLFacePool::endRenderPass(pass);
 
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) {
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0) {
 		sShader->unbind();
 	}
 }
@@ -145,6 +147,18 @@ S32 LLDrawPoolTerrain::getDetailMode()
 	return sDetailMode;
 }
 
+void LLDrawPoolTerrain::boostTerrainDetailTextures()
+{
+    // Hack! Get the region that this draw pool is rendering from!
+	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
+	LLVLComposition *compp = regionp->getComposition();
+	for (S32 i = 0; i < 4; i++)
+	{
+		compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
+		compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
+	}
+}
+
 void LLDrawPoolTerrain::render(S32 pass)
 {
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN);
@@ -154,14 +168,7 @@ void LLDrawPoolTerrain::render(S32 pass)
 		return;
 	}
 
-	// Hack! Get the region that this draw pool is rendering from!
-	LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
-	LLVLComposition *compp = regionp->getComposition();
-	for (S32 i = 0; i < 4; i++)
-	{
-		compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
-		compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area
-	}
+	boostTerrainDetailTextures();
 
 	LLOverrideFaceColor override(this, 1.f, 1.f, 1.f, 1.f);
 
@@ -180,7 +187,7 @@ void LLDrawPoolTerrain::render(S32 pass)
 
 	LLGLSPipeline gls;
 	
-	if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0)
+	if (mShaderLevel > 1 && sShader->mShaderLevel > 0)
 	{
 		gPipeline.enableLightsDynamic();
 
@@ -216,7 +223,7 @@ void LLDrawPoolTerrain::beginDeferredPass(S32 pass)
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_TERRAIN);
 	LLFacePool::beginRenderPass(pass);
 
-	sShader = &gDeferredTerrainProgram;
+	sShader = LLPipeline::sUnderWaterRender ? &gDeferredTerrainWaterProgram : &gDeferredTerrainProgram;
 
 	sShader->bind();
 }
@@ -236,6 +243,8 @@ void LLDrawPoolTerrain::renderDeferred(S32 pass)
 		return;
 	}
 
+    boostTerrainDetailTextures();
+
 	renderFullShader();
 
 	// Special-case for land ownership feedback
@@ -252,6 +261,9 @@ void LLDrawPoolTerrain::beginShadowPass(S32 pass)
 	LLFacePool::beginRenderPass(pass);
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 	gDeferredShadowProgram.bind();
+
+    LLEnvironment& environment = LLEnvironment::instance();
+    gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 }
 
 void LLDrawPoolTerrain::endShadowPass(S32 pass)
@@ -327,7 +339,8 @@ void LLDrawPoolTerrain::renderFullShader()
 	//
 	S32 detail0 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL0);
 	gGL.getTexUnit(detail0)->bind(detail_texture0p);
-	gGL.getTexUnit(0)->activate();
+    gGL.getTexUnit(detail0)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+	gGL.getTexUnit(detail0)->activate();
 
 	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
 	llassert(shader);
@@ -335,54 +348,40 @@ void LLDrawPoolTerrain::renderFullShader()
 	shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV);
 	shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV);
 
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+
+    ((LLSettingsVOWater*)pwater.get())->updateShader(shader);
 
 	//
 	// detail texture 1
 	//
 	S32 detail1 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL1); 
 	gGL.getTexUnit(detail1)->bind(detail_texture1p);
-	
-	/// ALPHA TEXTURE COORDS 0:
-	gGL.getTexUnit(1)->activate();
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail1)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+	gGL.getTexUnit(detail1)->activate();
 	
 	// detail texture 2
 	//
 	S32 detail2 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL2);
 	gGL.getTexUnit(detail2)->bind(detail_texture2p);
-
-	gGL.getTexUnit(2)->activate();
+    gGL.getTexUnit(detail2)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+	gGL.getTexUnit(detail2)->activate();
 	
-	/// ALPHA TEXTURE COORDS 1:
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.translatef(-2.f, 0.f, 0.f);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
 
-	//
 	// detail texture 3
 	//
 	S32 detail3 = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);
 	gGL.getTexUnit(detail3)->bind(detail_texture3p);
-	
-	/// ALPHA TEXTURE COORDS 2:
-	gGL.getTexUnit(3)->activate();
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.translatef(-1.f, 0.f, 0.f);
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail3)->setTextureAddressMode(LLTexUnit::TAM_WRAP);
+	gGL.getTexUnit(detail3)->activate();
 
 	//
 	// Alpha Ramp 
 	//
 	S32 alpha_ramp = sShader->enableTexture(LLViewerShaderMgr::TERRAIN_ALPHARAMP);
 	gGL.getTexUnit(alpha_ramp)->bind(m2DAlphaRampImagep);
-		
+    gGL.getTexUnit(alpha_ramp)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+
 	// GL_BLEND disabled by default
 	drawLoop();
 
@@ -394,47 +393,32 @@ void LLDrawPoolTerrain::renderFullShader()
 	sShader->disableTexture(LLViewerShaderMgr::TERRAIN_DETAIL3);
 
 	gGL.getTexUnit(alpha_ramp)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(4)->disable();
-	gGL.getTexUnit(4)->activate();
+	gGL.getTexUnit(alpha_ramp)->disable();
+	gGL.getTexUnit(alpha_ramp)->activate();
 	
 	gGL.getTexUnit(detail3)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(3)->disable();
-	gGL.getTexUnit(3)->activate();
-	
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail3)->disable();
+	gGL.getTexUnit(detail3)->activate();
 
 	gGL.getTexUnit(detail2)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(2)->disable();
-	gGL.getTexUnit(2)->activate();
-	
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail2)->disable();
+	gGL.getTexUnit(detail2)->activate();
 
 	gGL.getTexUnit(detail1)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(1)->disable();
-	gGL.getTexUnit(1)->activate();
-	
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail1)->disable();
+	gGL.getTexUnit(detail1)->activate();
 	
 	//----------------------------------------------------------------------------
 	// Restore Texture Unit 0 defaults
 	
 	gGL.getTexUnit(detail0)->unbind(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(0)->activate();
-	gGL.matrixMode(LLRender::MM_TEXTURE);
-	gGL.loadIdentity();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
+	gGL.getTexUnit(detail0)->enable(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(detail0)->activate();
 }
 
 void LLDrawPoolTerrain::hilightParcelOwners(bool deferred)
 {
-	if (mVertexShaderLevel > 1)
+	if (mShaderLevel > 1)
 	{ //use fullbright shader for highlighting
 		LLGLSLShader* old_shader = sShader;
 		sShader->unbind();
diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h
index 484820491a07728a8ed8b8716efa39e8d395c23b..04e27d9370ed4dd05309450a0e8a5eceebb441f0 100644
--- a/indra/newview/lldrawpoolterrain.h
+++ b/indra/newview/lldrawpoolterrain.h
@@ -78,6 +78,8 @@ class LLDrawPoolTerrain : public LLFacePool
 	static F32 sDetailScale; // meters per texture
 
 protected:
+    void boostTerrainDetailTextures();
+
 	void renderSimple();
 	void renderOwnership();
 
diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp
index b1f40781f73e5bcdccd50ac111e41d928b8492cc..b885008caeade02b3eca3ab7f8e664971c8890e3 100644
--- a/indra/newview/lldrawpooltree.cpp
+++ b/indra/newview/lldrawpooltree.cpp
@@ -38,6 +38,7 @@
 #include "llrender.h"
 #include "llviewercontrol.h"
 #include "llviewerregion.h"
+#include "llenvironment.h"
 
 S32 LLDrawPoolTree::sDiffTex = 0;
 static LLGLSLShader* shader = NULL;
@@ -57,7 +58,7 @@ LLDrawPool *LLDrawPoolTree::instancePool()
 
 void LLDrawPoolTree::prerender()
 {
-	mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
+	mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
 }
 
 void LLDrawPoolTree::beginRenderPass(S32 pass)
@@ -96,7 +97,6 @@ void LLDrawPoolTree::render(S32 pass)
 	}
 
 	LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1);
-	LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f);
 
 	gGL.getTexUnit(sDiffTex)->bind(mTexturep);
 				
@@ -138,7 +138,7 @@ void LLDrawPoolTree::endRenderPass(S32 pass)
 		shader->unbind();
 	}
 	
-	if (mVertexShaderLevel <= 0)
+	if (mShaderLevel <= 0)
 	{
 		gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
 	}
@@ -178,7 +178,10 @@ void LLDrawPoolTree::beginShadowPass(S32 pass)
 	glPolygonOffset(gSavedSettings.getF32("RenderDeferredTreeShadowOffset"),
 					gSavedSettings.getF32("RenderDeferredTreeShadowBias"));
 
+    LLEnvironment& environment = LLEnvironment::instance();
+
 	gDeferredTreeShadowProgram.bind();
+    gDeferredTreeShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 	gDeferredTreeShadowProgram.setMinimumAlpha(0.5f);
 }
 
diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h
index e7e25453cffffaa7d7adcd0c3d408b40eff6c9d7..9c1e60f5ebb990a8fc8310cf0569e1230c6a997d 100644
--- a/indra/newview/lldrawpooltree.h
+++ b/indra/newview/lldrawpooltree.h
@@ -37,7 +37,8 @@ class LLDrawPoolTree : public LLFacePool
 	{
 		VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX |
 							LLVertexBuffer::MAP_NORMAL |
-							LLVertexBuffer::MAP_TEXCOORD0							
+                            LLVertexBuffer::MAP_COLOR  |
+							LLVertexBuffer::MAP_TEXCOORD0
 	};
 
 	virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index df06ad31e6d1919cdc3c1495541cce801bd9dff8..073adfb627ae16cc3e7d73f60d8f33fce330a29c 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -46,10 +46,9 @@
 #include "llworld.h"
 #include "pipeline.h"
 #include "llviewershadermgr.h"
-#include "llwaterparammanager.h"
-
-const LLUUID TRANSPARENT_WATER_TEXTURE("2bfd3884-7e27-69b9-ba3a-3e673f680004");
-const LLUUID OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf86315de055");
+#include "llenvironment.h"
+#include "llsettingssky.h"
+#include "llsettingswater.h"
 
 static float sTime;
 
@@ -58,42 +57,51 @@ BOOL deferred_render = FALSE;
 BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
 BOOL LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
 BOOL LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
-LLColor4 LLDrawPoolWater::sWaterFogColor = LLColor4(0.2f, 0.5f, 0.5f, 0.f);
 F32 LLDrawPoolWater::sWaterFogEnd = 0.f;
 
-LLVector3 LLDrawPoolWater::sLightDir;
-
-LLDrawPoolWater::LLDrawPoolWater() :
-	LLFacePool(POOL_WATER)
+LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER)
 {
-	mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	gGL.getTexUnit(0)->bind(mHBTex[0]) ;
-	mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-	mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	gGL.getTexUnit(0)->bind(mHBTex[1]);
-	mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
 
+LLDrawPoolWater::~LLDrawPoolWater()
+{
+}
 
-	mWaterImagep = LLViewerTextureManager::getFetchedTexture(TRANSPARENT_WATER_TEXTURE);
-	llassert(mWaterImagep);
-	mWaterImagep->setNoDelete();
-	mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(OPAQUE_WATER_TEXTURE);
-	llassert(mOpaqueWaterImagep);
-	mWaterNormp = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL);
-	mWaterNormp->setNoDelete();
+void LLDrawPoolWater::setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId)
+{
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+    mWaterImagep[0] = LLViewerTextureManager::getFetchedTexture(!transparentTextureId.isNull() ? transparentTextureId : pwater->GetDefaultTransparentTextureAssetId());
+    mWaterImagep[1] = LLViewerTextureManager::getFetchedTexture(!nextTransparentTextureId.isNull() ? nextTransparentTextureId : (!transparentTextureId.isNull() ? transparentTextureId : pwater->GetDefaultTransparentTextureAssetId()));
+    mWaterImagep[0]->addTextureStats(1024.f*1024.f);
+    mWaterImagep[1]->addTextureStats(1024.f*1024.f);
+}
 
-	restoreGL();
+void LLDrawPoolWater::setOpaqueTexture(const LLUUID& opaqueTextureId)
+{
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+    mOpaqueWaterImagep = LLViewerTextureManager::getFetchedTexture(opaqueTextureId);
+    mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);
 }
 
-LLDrawPoolWater::~LLDrawPoolWater()
+void LLDrawPoolWater::setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId)
 {
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+    mWaterNormp[0] = LLViewerTextureManager::getFetchedTexture(!normalMapId.isNull() ? normalMapId : pwater->GetDefaultWaterNormalAssetId());
+    mWaterNormp[1] = LLViewerTextureManager::getFetchedTexture(!nextNormalMapId.isNull() ? nextNormalMapId : (!normalMapId.isNull() ? normalMapId : pwater->GetDefaultWaterNormalAssetId()));
+    mWaterNormp[0]->addTextureStats(1024.f*1024.f);
+    mWaterNormp[1]->addTextureStats(1024.f*1024.f);
 }
 
 //static
 void LLDrawPoolWater::restoreGL()
 {
-	
+	/*LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+    if (pwater)
+    {
+        setTransparentTextures(pwater->getTransparentTextureID(), pwater->getNextTransparentTextureID());
+        setOpaqueTexture(pwater->GetDefaultOpaqueTextureAssetId());
+        setNormalMaps(pwater->getNormalMapID(), pwater->getNextNormalMapID());
+    }*/
 }
 
 LLDrawPool *LLDrawPoolWater::instancePool()
@@ -105,14 +113,7 @@ LLDrawPool *LLDrawPoolWater::instancePool()
 
 void LLDrawPoolWater::prerender()
 {
-	mVertexShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ?
-		LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
-
-	// got rid of modulation by light color since it got a little too
-	// green at sunset and sl-57047 (underwater turns black at 8:00)
-	sWaterFogColor = LLWaterParamManager::instance().getFogColor();
-	sWaterFogColor.mV[3] = 0;
-
+	mShaderLevel = (gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps) ? LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WATER) : 0;
 }
 
 S32 LLDrawPoolWater::getNumPasses()
@@ -178,7 +179,7 @@ void LLDrawPoolWater::render(S32 pass)
 
 	LLGLEnable blend(GL_BLEND);
 
-	if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
+	if ((mShaderLevel > 0) && !sSkipScreenCopy)
 	{
 		shade();
 		return;
@@ -203,10 +204,13 @@ void LLDrawPoolWater::render(S32 pass)
 	LLGLDisable cullFace(GL_CULL_FACE);
 	
 	// Set up second pass first
-	mWaterImagep->addTextureStats(1024.f*1024.f);
 	gGL.getTexUnit(1)->activate();
 	gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE);
-	gGL.getTexUnit(1)->bind(mWaterImagep) ;
+	gGL.getTexUnit(1)->bind(mWaterImagep[0]) ;
+
+    gGL.getTexUnit(2)->activate();
+	gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(2)->bind(mWaterImagep[1]) ;
 
 	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
 	F32 up_dot = camera_up * LLVector3::z_axis;
@@ -263,6 +267,14 @@ void LLDrawPoolWater::render(S32 pass)
 	gGL.getTexUnit(1)->activate();
 	gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
 	gGL.getTexUnit(1)->disable();
+
+    glDisable(GL_TEXTURE_GEN_S); //texture unit 1
+	glDisable(GL_TEXTURE_GEN_T); //texture unit 1
+
+    gGL.getTexUnit(2)->activate();
+	gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE);
+	gGL.getTexUnit(2)->disable();
+
 	glDisable(GL_TEXTURE_GEN_S); //texture unit 1
 	glDisable(GL_TEXTURE_GEN_T); //texture unit 1
 
@@ -362,8 +374,6 @@ void LLDrawPoolWater::renderOpaqueLegacyWater()
 
 	gPipeline.disableLights();
 
-	mOpaqueWaterImagep->addTextureStats(1024.f*1024.f);
-
 	// Activate the texture binding and bind one
 	// texture since all images will have the same texture
 	gGL.getTexUnit(0)->activate();
@@ -461,97 +471,39 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
 
 	LLGLSNoFog noFog;
 
-	gGL.getTexUnit(0)->bind(mHBTex[dr]);
+	gGL.getTexUnit(0)->bind((dr == 0) ? voskyp->getSunTex() : voskyp->getMoonTex());
 
 	LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV));
 	face->renderIndexed();
 }
 
-void LLDrawPoolWater::shade()
+void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp)
 {
-	if (!deferred_render)
-	{
-		gGL.setColorMask(true, true);
-	}
-
-	LLVOSky *voskyp = gSky.mVOSkyp;
-
-	if(voskyp == NULL) 
-	{
-		return;
-	}
+    F32  water_height  = LLEnvironment::instance().getWaterHeight(); 
+    F32  camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
+    F32  eyedepth      = camera_height - water_height;
+    bool underwater    = eyedepth <= 0.0f;
 
-	LLGLDisable blend(GL_BLEND);
-
-	LLColor3 light_diffuse(0,0,0);
-	F32 light_exp = 0.0f;
-	LLVector3 light_dir;
-	LLColor3 light_color;
-
-	if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) 	 
-    { 	 
-        light_dir  = gSky.getSunDirection(); 	 
-        light_dir.normVec(); 	
-		light_color = gSky.getSunDiffuseColor();
-		if(gSky.mVOSkyp) {
-	        light_diffuse = gSky.mVOSkyp->getSun().getColorCached(); 	 
-			light_diffuse.normVec(); 	 
-		}
-        light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); 	 
-        light_diffuse *= light_exp + 0.25f; 	 
-    } 	 
-    else  	 
-    { 	 
-        light_dir       = gSky.getMoonDirection(); 	 
-        light_dir.normVec(); 	 
-		light_color = gSky.getMoonDiffuseColor();
-        light_diffuse   = gSky.mVOSkyp->getMoon().getColorCached(); 	 
-        light_diffuse.normVec(); 	 
-        light_diffuse *= 0.5f; 	 
-        light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0); 	 
-    }
-
-	light_exp *= light_exp;
-	light_exp *= light_exp;
-	light_exp *= light_exp;
-	light_exp *= light_exp;
-	light_exp *= 256.f;
-	light_exp = light_exp > 32.f ? light_exp : 32.f;
+    LLEnvironment& environment = LLEnvironment::instance();
+    LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
+    LLSettingsSky::ptr_t   psky   = environment.getCurrentSky();
 
-	LLGLSLShader* shader;
+    shader->bind();
 
-	F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight();
-	
-	if (eyedepth < 0.f && LLPipeline::sWaterReflections)
-	{
+// bind textures for water rendering
 	if (deferred_render)
 	{
-			shader = &gDeferredUnderWaterProgram;
-	}
-		else
-	{
-		shader = &gUnderWaterProgram;
-	}
-	}
-	else if (deferred_render)
-	{
-		shader = &gDeferredWaterProgram;
-	}
-	else
-	{
-		shader = &gWaterProgram;
+        if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
+	    {
+		    glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
+		    shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
+	    }
 	}
 
-	if (deferred_render)
-	{
-		gPipeline.bindDeferredShader(*shader);
-	}
-	else
-	{
-		shader->bind();
-	}
+    LLColor4 specular(psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor());
+    shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV);
 
-	sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
+	sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f;
 	
 	S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
 		
@@ -563,62 +515,65 @@ void LLDrawPoolWater::shade()
 	}	
 
 	//bind normal map
-	S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+	S32 bumpTex  = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+    S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
 
-	LLWaterParamManager * param_mgr = &LLWaterParamManager::instance();
+    LLViewerTexture* tex_a = mWaterNormp[0];
+    LLViewerTexture* tex_b = mWaterNormp[1];
 
-	// change mWaterNormp if needed
-	if (mWaterNormp->getID() != param_mgr->getNormalMapID())
-	{
-		mWaterNormp = LLViewerTextureManager::getFetchedTexture(param_mgr->getNormalMapID());
-	}
-
-	mWaterNormp->addTextureStats(1024.f*1024.f);
-	gGL.getTexUnit(bumpTex)->bind(mWaterNormp) ;
-	if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
-	{
-		mWaterNormp->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
-	}
-	else 
-	{
-		mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT);
-	}
-	
-	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);	
-		
-	if (screentex > -1)
-	{
-		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
-		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, 
-			param_mgr->getFogDensity());
-		gPipeline.mWaterDis.bindTexture(0, screentex);
-	}
-	
-	stop_glerror();
+    F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor();
 	
-	gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);	
-
-	if (mVertexShaderLevel == 1)
-	{
-		sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue;
-		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
-	}
+    gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+    gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
 
+    if (tex_a && (!tex_b || (tex_a == tex_b)))
+    {
+		gGL.getTexUnit(bumpTex)->bind(tex_a);
+        blend_factor = 0; // only one tex provided, no blending
+    }
+    else if (tex_b && !tex_a)
+    {
+        gGL.getTexUnit(bumpTex)->bind(tex_b);
+        blend_factor = 0; // only one tex provided, no blending
+    }
+    else if (tex_b != tex_a)
+    {
+        gGL.getTexUnit(bumpTex)->bind(tex_a);
+        gGL.getTexUnit(bumpTex2)->bind(tex_b);
+    }
+	
+    // bind reflection texture from RenderTarget
+	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
 	F32 screenRes[] = 
 	{
 		1.f/gGLViewport[2],
 		1.f/gGLViewport[3]
 	};
-	shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
-	stop_glerror();
-	
+		
 	S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
 	stop_glerror();
-	
-	light_dir.normVec();
-	sLightDir = light_dir;
-	
-	light_diffuse *= 6.f;
+
+// set uniforms for water rendering
+    shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
+    shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+    LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f);
+    F32      fog_density = pwater->getModifiedWaterFogDensity(underwater);
+
+    if (screentex > -1)
+	{
+		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
+		gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
+	}
+    
+    if (mShaderLevel == 1)
+    {
+        //F32 fog_density_slider_value = param_mgr->mDensitySliderValue;
+		//sWaterFogColor.mV[3] = fog_density_slider_value;
+        fog_color.mV[VW] = log(fog_density) / log(2);
+	}
+
+    shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
 
 	//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
 	shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
@@ -626,76 +581,100 @@ void LLDrawPoolWater::shade()
 	shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
 	shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
 	shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
-	shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV);
-	shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV);
+    if (LLEnvironment::instance().isCloudScrollPaused())
+    {
+        static const std::array<F32, 2> zerowave{ {0.0f, 0.0f} };
+        
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data());
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data());
+    }
+    else
+    {
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
+        shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
+    }
 	shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
 
-	shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, param_mgr->getNormalScale().mV);
-	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, param_mgr->getFresnelScale());
-	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, param_mgr->getFresnelOffset());
-	shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, param_mgr->getBlurMultiplier());
+	shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
+	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
+	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
+    shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier());
 
-	F32 sunAngle = llmax(0.f, light_dir.mV[2]);
+	F32 sunAngle = llmax(0.f, light_dir.mV[1]);
 	F32 scaledAngle = 1.f - sunAngle;
 
+    shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
 	shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
 	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle);
+    shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
+
+    LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
+    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
+    shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
 
-	LLColor4 water_color;
-	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
-	F32 up_dot = camera_up * LLVector3::z_axis;
 	if (LLViewerCamera::getInstance()->cameraUnderWater())
 	{
-		water_color.setVec(1.f, 1.f, 1.f, 0.4f);
-		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());
+		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
 	}
 	else
 	{
-		water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
-		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());
+		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
 	}
 
-	if (water_color.mV[3] > 0.9f)
-	{
-		water_color.mV[3] = 0.9f;
-	}
-
-	{
-		LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
+	{		
 		LLGLDisable cullface(GL_CULL_FACE);
-		for (std::vector<LLFace*>::iterator iter = mDrawFace.begin();
-			iter != mDrawFace.end(); iter++)
-		{
-			LLFace *face = *iter;
 
-			if (voskyp->isReflFace(face))
-			{
-				continue;
-			}
+        if (edge)
+        {
+            for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++)
+		    {
+			    LLFace *face = *iter;
+                if (face)
+                {
+                    LLVOWater* water = (LLVOWater*) face->getViewerObject();
+			        gGL.getTexUnit(diffTex)->bind(face->getTexture());
+
+                    if (water)
+                    {
+                        bool edge_patch = water->getIsEdgePatch();
+                        if (edge_patch)
+                        {
+                            //sNeedsReflectionUpdate = TRUE;
+                            face->renderIndexed();
+                        }
+                    }
+                }
+		    }
+        }
+        else
+        {
+            for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++)
+		    {
+			    LLFace *face = *iter;
+                if (face)
+                {
+                    LLVOWater* water = (LLVOWater*) face->getViewerObject();
+			        gGL.getTexUnit(diffTex)->bind(face->getTexture());
+
+                    if (water)
+                    {
+                        bool edge_patch = water->getIsEdgePatch();
+                        if (!edge_patch)
+                        {
+                            sNeedsReflectionUpdate = TRUE;
+                            sNeedsDistortionUpdate = TRUE;
+                            face->renderIndexed();
+                        }
+                    }
+                }
+		    }
+        }
+    }
 
-			LLVOWater* water = (LLVOWater*) face->getViewerObject();
-			gGL.getTexUnit(diffTex)->bind(face->getTexture());
+    gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+    gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
 
-			sNeedsReflectionUpdate = TRUE;
-			
-			if (water->getUseTexture() || !water->getIsEdgePatch())
-			{
-				sNeedsDistortionUpdate = TRUE;
-				face->renderIndexed();
-			}
-			else if (gGLManager.mHasDepthClamp || deferred_render)
-			{
-				face->renderIndexed();
-			}
-			else
-			{
-				LLGLSquashToFarClip far_clip(glh_get_current_projection());
-				face->renderIndexed();
-			}
-		}
-	}
-	
 	shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
 	shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);	
 	shader->disableTexture(LLShaderMgr::BUMP_MAP);
@@ -703,15 +682,118 @@ void LLDrawPoolWater::shade()
 	shader->disableTexture(LLShaderMgr::WATER_REFTEX);
 	shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
 
-	if (deferred_render)
+	shader->unbind();
+}
+
+void LLDrawPoolWater::shade()
+{
+	if (!deferred_render)
 	{
-		gPipeline.unbindDeferredShader(*shader);
+		gGL.setColorMask(true, true);
 	}
-	else
+
+	LLVOSky *voskyp = gSky.mVOSkyp;
+
+	if(voskyp == NULL) 
 	{
-		shader->unbind();
+		return;
 	}
 
+	LLGLDisable blend(GL_BLEND);
+
+	LLColor3 light_diffuse(0,0,0);
+	F32 light_exp = 0.0f;
+	LLVector3 light_dir;
+
+    LLEnvironment& environment = LLEnvironment::instance();
+    LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
+    LLSettingsSky::ptr_t   psky   = environment.getCurrentSky();
+
+    light_dir = environment.getLightDirection();
+    light_dir.normalize();
+
+    bool sun_up  = environment.getIsSunUp();
+    bool moon_up = environment.getIsMoonUp();
+
+    if (sun_up)
+    {
+        light_diffuse += voskyp->getSun().getColorCached();
+    }
+    // moonlight is several orders of magnitude less bright than sunlight,
+    // so only use this color when the moon alone is showing
+    else if (moon_up)
+    {        
+        light_diffuse += psky->getMoonDiffuse(); 
+    }
+
+    light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f);
+
+    light_diffuse.normalize();
+    light_diffuse *= (light_exp + 0.25f);
+
+	light_exp *= light_exp;
+	light_exp *= light_exp;
+	light_exp *= light_exp;
+	light_exp *= light_exp;
+	light_exp *= 256.f;
+	light_exp = light_exp > 32.f ? light_exp : 32.f;
+
+    light_diffuse *= 6.f;
+
+	LLGLSLShader* shader = nullptr;
+    LLGLSLShader* edge_shader = nullptr;
+
+	F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight();
+	
+	if (eyedepth < 0.f && LLPipeline::sWaterReflections)
+	{
+	    if (deferred_render)
+	    {
+            shader = &gDeferredUnderWaterProgram;
+	    }
+		else
+        {
+	        shader = &gUnderWaterProgram;
+        }
+	}
+	else if (deferred_render)
+	{
+		shader = &gDeferredWaterProgram;
+        edge_shader = nullptr;
+	}
+	else
+	{
+		shader = &gWaterProgram;
+        edge_shader = &gWaterEdgeProgram;
+	}
+
+    if (mWaterNormp[0])
+    {
+	    if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
+	    {
+		    mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+	    }
+	    else 
+	    {
+		    mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT);
+	    }
+	}
+
+    if (mWaterNormp[1])
+    {
+	    if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
+	    {
+            mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+	    }
+	    else 
+	    {
+            mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT);
+	    }
+	}
+
+    shade2(false, shader, light_diffuse, light_dir, light_exp);
+    shade2(true, edge_shader ? edge_shader : shader, light_diffuse, light_dir, light_exp);
+
 	gGL.getTexUnit(0)->activate();
 	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
 	if (!deferred_render)
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index aeeba179d6ca134c240ea7cf70ec4768a95cea20..d436557e1cb070f43ceb23598c23b874864a7add 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -33,22 +33,20 @@
 class LLFace;
 class LLHeavenBody;
 class LLWaterSurface;
+class LLGLSLShader;
 
 class LLDrawPoolWater: public LLFacePool
 {
 protected:
-	LLPointer<LLViewerTexture> mHBTex[2];
-	LLPointer<LLViewerTexture> mWaterImagep;
-	LLPointer<LLViewerTexture> mOpaqueWaterImagep;
-	LLPointer<LLViewerTexture> mWaterNormp;
+	LLPointer<LLViewerTexture> mWaterImagep[2];	
+	LLPointer<LLViewerTexture> mWaterNormp[2];
+
+    LLPointer<LLViewerTexture> mOpaqueWaterImagep;
 
 public:
 	static BOOL sSkipScreenCopy;
 	static BOOL sNeedsReflectionUpdate;
 	static BOOL sNeedsDistortionUpdate;
-	static LLVector3 sLightDir;
-
-	static LLColor4 sWaterFogColor;
 	static F32 sWaterFogEnd;
 
 	enum
@@ -82,6 +80,11 @@ class LLDrawPoolWater: public LLFacePool
 
 	void renderReflection(LLFace* face);
 	void shade();
+    void shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp);
+
+    void setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId);
+    void setOpaqueTexture(const LLUUID& opaqueTextureId);
+    void setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId);
 
 protected:
 	void renderOpaqueLegacyWater();
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index 309f535c39174e0bce708b29e87921b0dbfce6d8..961d72c62eb7bc18b3680ba43fb4a75b84726654 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -29,66 +29,39 @@
 #include "lldrawpoolwlsky.h"
 
 #include "llerror.h"
-#include "llgl.h"
-#include "pipeline.h"
-#include "llviewercamera.h"
+#include "llface.h"
 #include "llimage.h"
-#include "llwlparammanager.h"
-#include "llviewershadermgr.h"
+#include "llrender.h"
+#include "llatmosphere.h"
+#include "llenvironment.h" 
 #include "llglslshader.h"
+#include "llgl.h"
+
+#include "llviewerregion.h"
+#include "llviewershadermgr.h"
+#include "llviewercamera.h"
+#include "pipeline.h"
 #include "llsky.h"
 #include "llvowlsky.h"
-#include "llviewerregion.h"
-#include "llface.h"
-#include "llrender.h"
-
-LLPointer<LLViewerTexture> LLDrawPoolWLSky::sCloudNoiseTexture = NULL;
+#include "llsettingsvo.h"
 
-LLPointer<LLImageRaw> LLDrawPoolWLSky::sCloudNoiseRawImage = NULL;
+static LLStaticHashedString sCamPosLocal("camPosLocal");
+static LLStaticHashedString sCustomAlpha("custom_alpha");
 
 static LLGLSLShader* cloud_shader = NULL;
-static LLGLSLShader* sky_shader = NULL;
+static LLGLSLShader* sky_shader   = NULL;
+static LLGLSLShader* sun_shader   = NULL;
+static LLGLSLShader* moon_shader  = NULL;
 
+static float sStarTime;
 
 LLDrawPoolWLSky::LLDrawPoolWLSky(void) :
 	LLDrawPool(POOL_WL_SKY)
 {
-	const std::string cloudNoiseFilename(gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight", "clouds2.tga"));
-	LL_INFOS() << "loading WindLight cloud noise from " << cloudNoiseFilename << LL_ENDL;
-
-	LLPointer<LLImageFormatted> cloudNoiseFile(LLImageFormatted::createFromExtension(cloudNoiseFilename));
-
-	if(cloudNoiseFile.isNull()) {
-		LL_ERRS() << "Error: Failed to load cloud noise image " << cloudNoiseFilename << LL_ENDL;
-	}
-
-	if(cloudNoiseFile->load(cloudNoiseFilename))
-	{
-		sCloudNoiseRawImage = new LLImageRaw();
-
-		if(cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f))
-		{
-			//debug use			
-			LL_DEBUGS() << "cloud noise raw image width: " << sCloudNoiseRawImage->getWidth() << " : height: " << sCloudNoiseRawImage->getHeight() << " : components: " << 
-				(S32)sCloudNoiseRawImage->getComponents() << " : data size: " << sCloudNoiseRawImage->getDataSize() << LL_ENDL ;
-			llassert_always(sCloudNoiseRawImage->getData()) ;
-
-			sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
-		}
-		else
-		{
-			sCloudNoiseRawImage = NULL ;
-		}
-	}
-
-	LLWLParamManager::getInstance()->propagateParameters();
 }
 
 LLDrawPoolWLSky::~LLDrawPoolWLSky()
 {
-	//LL_INFOS() << "destructing wlsky draw pool." << LL_ENDL;
-	sCloudNoiseTexture = NULL;
-	sCloudNoiseRawImage = NULL;
 }
 
 LLViewerTexture *LLDrawPoolWLSky::getDebugTexture()
@@ -107,39 +80,70 @@ void LLDrawPoolWLSky::beginRenderPass( S32 pass )
 			LLPipeline::sUnderWaterRender ?
 				&gObjectFullbrightNoColorWaterProgram :
 				&gWLCloudProgram;
+
+    sun_shader =
+			LLPipeline::sUnderWaterRender ?
+				&gObjectFullbrightNoColorWaterProgram :
+				&gWLSunProgram;
+
+    moon_shader =
+			LLPipeline::sUnderWaterRender ?
+				&gObjectFullbrightNoColorWaterProgram :
+				&gWLMoonProgram;
 }
 
 void LLDrawPoolWLSky::endRenderPass( S32 pass )
 {
+    sky_shader   = nullptr;
+    cloud_shader = nullptr;
+    sun_shader   = nullptr;
+    moon_shader  = nullptr;
 }
 
 void LLDrawPoolWLSky::beginDeferredPass(S32 pass)
 {
 	sky_shader = &gDeferredWLSkyProgram;
 	cloud_shader = &gDeferredWLCloudProgram;
+
+    sun_shader =
+			LLPipeline::sUnderWaterRender ?
+				&gObjectFullbrightNoColorWaterProgram :
+				&gDeferredWLSunProgram;
+
+    moon_shader =
+			LLPipeline::sUnderWaterRender ?
+				&gObjectFullbrightNoColorWaterProgram :
+				&gDeferredWLMoonProgram;
 }
 
 void LLDrawPoolWLSky::endDeferredPass(S32 pass)
 {
-
+    sky_shader   = nullptr;
+    cloud_shader = nullptr;
+    sun_shader   = nullptr;
+    moon_shader  = nullptr;
 }
 
-void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) const
+void LLDrawPoolWLSky::renderFsSky(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader * shader) const
 {
-	LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+    gSky.mVOWLSkyp->drawFsSky();
+}
 
-	llassert_always(NULL != shader);
+void LLDrawPoolWLSky::renderDome(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader * shader) const
+{
+    llassert_always(NULL != shader);
 
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.pushMatrix();
 
 	//chop off translation
-	if (LLPipeline::sReflectionRender && origin.mV[2] > 256.f)
+	if (LLPipeline::sReflectionRender && camPosLocal.mV[2] > 256.f)
 	{
-		gGL.translatef(origin.mV[0], origin.mV[1], 256.f-origin.mV[2]*0.5f);
+		gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], 256.f-camPosLocal.mV[2]*0.5f);
 	}
 	else
 	{
-		gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+		gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]);
 	}
 		
 
@@ -151,64 +155,120 @@ void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) cons
 
 	gGL.translatef(0.f,-camHeightLocal, 0.f);
 	
-	// Draw WL Sky	
-	static LLStaticHashedString sCamPosLocal("camPosLocal");
+	// Draw WL Sky
 	shader->uniform3f(sCamPosLocal, 0.f, camHeightLocal, 0.f);
 
-	gSky.mVOWLSkyp->drawDome();
+    gSky.mVOWLSkyp->drawDome();
 
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.popMatrix();
 }
 
-void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const
+void LLDrawPoolWLSky::renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const
 {
+    LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+
 	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
 	{
-		LLGLDisable blend(GL_BLEND);
+        LLGLSPipelineDepthTestSkyBox sky(true, true);
 
-		sky_shader->bind();
+        sky_shader->bind();
 
-		/// Render the skydome
-		renderDome(camHeightLocal, sky_shader);	
+        LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+        LLViewerTexture* rainbow_tex = gSky.mVOSkyp->getRainbowTex();
+        LLViewerTexture* halo_tex  = gSky.mVOSkyp->getHaloTex();
+
+        sky_shader->bindTexture(LLShaderMgr::RAINBOW_MAP, rainbow_tex);
+        sky_shader->bindTexture(LLShaderMgr::HALO_MAP,  halo_tex);
+
+        ((LLSettingsVOSky*)psky.get())->updateShader(sky_shader);
+
+        F32 moisture_level  = (float)psky->getSkyMoistureLevel();
+        F32 droplet_radius  = (float)psky->getSkyDropletRadius();
+        F32 ice_level       = (float)psky->getSkyIceLevel();
+
+        // hobble halos and rainbows when there's no light source to generate them
+        if (!psky->getIsSunUp() && !psky->getIsMoonUp())
+        {
+            moisture_level = 0.0f;
+            ice_level      = 0.0f;
+        }
+
+        sky_shader->uniform1f(LLShaderMgr::MOISTURE_LEVEL, moisture_level);
+        sky_shader->uniform1f(LLShaderMgr::DROPLET_RADIUS, droplet_radius);
+        sky_shader->uniform1f(LLShaderMgr::ICE_LEVEL, ice_level);
+
+        sky_shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor());
+
+        sky_shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, psky->getIsSunUp() ? 1 : 0);
+
+        /// Render the skydome
+        renderDome(origin, camHeightLocal, sky_shader);	
 
 		sky_shader->unbind();
-	}
+    }
+}
+
+void LLDrawPoolWLSky::renderSkyHaze(const LLVector3& camPosLocal, F32 camHeightLocal) const
+{
+    LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+
+	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+	{
+        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);
+        renderDome(origin, camHeightLocal, sky_shader);	
+		sky_shader->unbind();
+    }
 }
 
 void LLDrawPoolWLSky::renderStars(void) const
 {
-	LLGLSPipelineSkyBox gls_sky;
-	LLGLEnable blend(GL_BLEND);
-	gGL.setSceneBlendType(LLRender::BT_ALPHA);
+    LLGLSPipelineBlendSkyBox gls_skybox(true, false);
 	
 	// *NOTE: have to have bound the cloud noise texture already since register
 	// combiners blending below requires something to be bound
 	// and we might as well only bind once.
 	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
 	
-	gPipeline.disableLights();
-	
 	// *NOTE: we divide by two here and GL_ALPHA_SCALE by two below to avoid
 	// clamping and allow the star_alpha param to brighten the stars.
-	bool error;
 	LLColor4 star_alpha(LLColor4::black);
-	star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f;
 
-	// If start_brightness is not set, exit
-	if( error )
+    star_alpha.mV[3] = LLEnvironment::instance().getCurrentSky()->getStarBrightness() / 512.f;
+    
+	// If star brightness is not set, exit
+	if( star_alpha.mV[3] < 0.001 )
 	{
-		LL_WARNS() << "star_brightness missing in mCurParams" << LL_ENDL;
+		LL_DEBUGS("SKY") << "star_brightness below threshold." << LL_ENDL;
 		return;
 	}
 
-	gGL.getTexUnit(0)->bind(gSky.mVOSkyp->getBloomTex());
+    LLViewerTexture* tex_a = gSky.mVOSkyp->getBloomTex();
+    LLViewerTexture* tex_b = gSky.mVOSkyp->getBloomTexNext();
+	
+    if (tex_a && (!tex_b || (tex_a == tex_b)))
+    {
+        // Bind current and next sun textures
+		gGL.getTexUnit(0)->bind(tex_a);
+    }
+    else if (tex_b && !tex_a)
+    {
+        gGL.getTexUnit(0)->bind(tex_b);
+    }
+    else if (tex_b != tex_a)
+    {
+        gGL.getTexUnit(0)->bind(tex_a);
+    }
 
 	gGL.pushMatrix();
 	gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
 	if (LLGLSLShader::sNoFixedFunction)
 	{
 		gCustomAlphaProgram.bind();
-		static LLStaticHashedString sCustomAlpha("custom_alpha");
 		gCustomAlphaProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]);
 	}
 	else
@@ -220,6 +280,8 @@ void LLDrawPoolWLSky::renderStars(void) const
 
 	gSky.mVOWLSkyp->drawStars();
 
+    gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
 	gGL.popMatrix();
 
 	if (LLGLSLShader::sNoFixedFunction)
@@ -233,123 +295,296 @@ void LLDrawPoolWLSky::renderStars(void) const
 	}
 }
 
-void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const
+void LLDrawPoolWLSky::renderStarsDeferred(void) const
 {
-	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && sCloudNoiseTexture.notNull())
-	{
-		LLGLEnable blend(GL_BLEND);
-		gGL.setSceneBlendType(LLRender::BT_ALPHA);
-		
-		gGL.getTexUnit(0)->bind(sCloudNoiseTexture);
+	LLGLSPipelineBlendSkyBox gls_sky(true, false);
 
-		cloud_shader->bind();
+	gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
 
-		/// Render the skydome
-		renderDome(camHeightLocal, cloud_shader);
+    F32 star_alpha = LLEnvironment::instance().getCurrentSky()->getStarBrightness() / 500.0f;
 
-		cloud_shader->unbind();
+	// If start_brightness is not set, exit
+	if(star_alpha < 0.001f)
+	{
+		LL_DEBUGS("SKY") << "star_brightness below threshold." << LL_ENDL;
+		return;
 	}
-}
 
-void LLDrawPoolWLSky::renderHeavenlyBodies()
-{
-	LLGLSPipelineSkyBox gls_skybox;
-	LLGLEnable blend_on(GL_BLEND);
-	gPipeline.disableLights();
+	gDeferredStarProgram.bind();	
 
-#if 0 // when we want to re-add a texture sun disc, here's where to do it.
-	LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN];
-	if (gSky.mVOSkyp->getSun().getDraw() && face->getGeomCount())
-	{
-		LLViewerTexture * tex  = face->getTexture();
-		gGL.getTexUnit(0)->bind(tex);
-		LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor());
-		LLFacePool::LLOverrideFaceColor color_override(this, color);
-		face->renderIndexed();
-	}
-#endif
+    LLViewerTexture* tex_a = gSky.mVOSkyp->getBloomTex();
+    LLViewerTexture* tex_b = gSky.mVOSkyp->getBloomTexNext();
+
+    F32 blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor();
+	
+    if (tex_a && (!tex_b || (tex_a == tex_b)))
+    {
+        // Bind current and next sun textures
+		gGL.getTexUnit(0)->bind(tex_a);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+        blend_factor = 0;
+    }
+    else if (tex_b && !tex_a)
+    {
+        gGL.getTexUnit(0)->bind(tex_b);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+        blend_factor = 0;
+    }
+    else if (tex_b != tex_a)
+    {
+        gGL.getTexUnit(0)->bind(tex_a);
+        gGL.getTexUnit(1)->bind(tex_b);
+    }
+
+    gDeferredStarProgram.uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+    if (LLPipeline::sReflectionRender)
+    {
+        star_alpha = 1.0f;
+    }
+	gDeferredStarProgram.uniform1f(sCustomAlpha, star_alpha);
+
+    sStarTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f;
+
+    gDeferredStarProgram.uniform1f(LLShaderMgr::WATER_TIME, sStarTime);
+
+	gSky.mVOWLSkyp->drawStars();
+
+    gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+    gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
 
-	LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON];
+    gDeferredStarProgram.unbind();
+}
 
-	if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount())
+void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const
+{
+	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp->getCloudNoiseTex())
 	{
-		// *NOTE: even though we already bound this texture above for the
-		// stars register combiners, we bind again here for defensive reasons,
-		// since LLImageGL::bind detects that it's a noop, and optimizes it out.
-		gGL.getTexUnit(0)->bind(face->getTexture());
-		LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor());
-		F32 a = gSky.mVOSkyp->getMoon().getDirection().mV[2];
-		if (a > 0.f)
-		{
-			a = a*a*4.f;
-		}
-			
-		color.mV[3] = llclamp(a, 0.f, 1.f);
-		
-		if (gPipeline.canUseVertexShaders())
-		{
-			gHighlightProgram.bind();
-		}
+        LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-		LLFacePool::LLOverrideFaceColor color_override(this, color);
+		LLGLSPipelineBlendSkyBox pipeline(true, true);
 		
-		face->renderIndexed();
+		cloudshader->bind();
+
+        LLPointer<LLViewerTexture> cloud_noise      = gSky.mVOSkyp->getCloudNoiseTex();
+        LLPointer<LLViewerTexture> cloud_noise_next = gSky.mVOSkyp->getCloudNoiseTexNext();
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+
+        F32 cloud_variance = psky ? psky->getCloudVariance() : 0.0f;
+        F32 blend_factor   = psky ? psky->getBlendFactor() : 0.0f;
+
+        // if we even have sun disc textures to work with...
+        if (cloud_noise || cloud_noise_next)
+        {
+            if (cloud_noise && (!cloud_noise_next || (cloud_noise == cloud_noise_next)))
+            {
+                // Bind current and next sun textures
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise, LLTexUnit::TT_TEXTURE);
+                blend_factor = 0;
+            }
+            else if (cloud_noise_next && !cloud_noise)
+            {
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise_next, LLTexUnit::TT_TEXTURE);
+                blend_factor = 0;
+            }
+            else if (cloud_noise_next != cloud_noise)
+            {
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise, LLTexUnit::TT_TEXTURE);
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP_NEXT, cloud_noise_next, LLTexUnit::TT_TEXTURE);
+            }
+        }
+
+        cloudshader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+        cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance);
+        cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor());
+
+        ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader);
+
+		/// Render the skydome
+        renderDome(camPosLocal, camHeightLocal, cloudshader);
 
-		if (gPipeline.canUseVertexShaders())
-		{
-			gHighlightProgram.unbind();
-		}
+		cloudshader->unbind();
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
 	}
 }
 
-void LLDrawPoolWLSky::renderDeferred(S32 pass)
+void LLDrawPoolWLSky::renderSkyClouds(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const
 {
-	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+	if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS) && gSky.mVOSkyp->getCloudNoiseTex())
 	{
-		return;
-	}
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY);
+        LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-	const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius();
+        LLGLSPipelineBlendSkyBox pipeline(true, true);
+		
+		cloudshader->bind();
+
+        LLPointer<LLViewerTexture> cloud_noise      = gSky.mVOSkyp->getCloudNoiseTex();
+        LLPointer<LLViewerTexture> cloud_noise_next = gSky.mVOSkyp->getCloudNoiseTexNext();
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+
+        F32 cloud_variance = psky ? psky->getCloudVariance() : 0.0f;
+        F32 blend_factor   = psky ? psky->getBlendFactor() : 0.0f;
+
+        // if we even have sun disc textures to work with...
+        if (cloud_noise || cloud_noise_next)
+        {
+            if (cloud_noise && (!cloud_noise_next || (cloud_noise == cloud_noise_next)))
+            {
+                // Bind current and next sun textures
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise, LLTexUnit::TT_TEXTURE);
+                blend_factor = 0;
+            }
+            else if (cloud_noise_next && !cloud_noise)
+            {
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise_next, LLTexUnit::TT_TEXTURE);
+                blend_factor = 0;
+            }
+            else if (cloud_noise_next != cloud_noise)
+            {
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP, cloud_noise, LLTexUnit::TT_TEXTURE);
+                cloudshader->bindTexture(LLShaderMgr::CLOUD_NOISE_MAP_NEXT, cloud_noise_next, LLTexUnit::TT_TEXTURE);
+            }
+        }
+
+        cloudshader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+        cloudshader->uniform1f(LLShaderMgr::CLOUD_VARIANCE, cloud_variance);
+        cloudshader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, psky->getSunMoonGlowFactor());
+
+        ((LLSettingsVOSky*)psky.get())->updateShader(cloudshader);
 
-	LLGLSNoFog disableFog;
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-	LLGLDisable clip(GL_CLIP_PLANE0);
+		/// Render the skydome
+        renderDome(camPosLocal, camHeightLocal, cloudshader);
 
-	gGL.setColorMask(true, false);
+		cloudshader->unbind();
 
-	LLGLSquashToFarClip far_clip(glh_get_current_projection());
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+	}
+}
 
-	renderSkyHaze(camHeightLocal);
+void LLDrawPoolWLSky::renderHeavenlyBodies()
+{
+	LLGLSPipelineBlendSkyBox gls_skybox(true, false);
 
-	LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+    LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
 	gGL.pushMatrix();
+	gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);	        
 
-		
-		gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
+	LLFace * face = gSky.mVOSkyp->mFace[LLVOSky::FACE_SUN];
 
-		gDeferredStarProgram.bind();
-		// *NOTE: have to bind a texture here since register combiners blending in
-		// renderStars() requires something to be bound and we might as well only
-		// bind the moon's texture once.		
-		gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture());
+    F32 blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor();
+    bool can_use_vertex_shaders = gPipeline.canUseVertexShaders();
+    bool can_use_windlight_shaders = gPipeline.canUseWindLightShaders();
 
-		renderHeavenlyBodies();
 
-		renderStars();
-		
-		gDeferredStarProgram.unbind();
+	if (gSky.mVOSkyp->getSun().getDraw() && face && face->getGeomCount())
+	{
+		LLPointer<LLViewerTexture> tex_a = face->getTexture(LLRender::DIFFUSE_MAP);
+        LLPointer<LLViewerTexture> tex_b = face->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP);
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+        gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+
+        // if we even have sun disc textures to work with...
+        if (tex_a || tex_b)
+        {
+            // if and only if we have a texture defined, render the sun disc
+            if (can_use_vertex_shaders && can_use_windlight_shaders)
+            {
+                sun_shader->bind();
+
+                if (tex_a && (!tex_b || (tex_a == tex_b)))
+                {
+                    // Bind current and next sun textures
+                    sun_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
+                    blend_factor = 0;
+                }
+                else if (tex_b && !tex_a)
+                {
+                    sun_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
+                    blend_factor = 0;
+                }
+                else if (tex_b != tex_a)
+                {
+                    sun_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
+                    sun_shader->bindTexture(LLShaderMgr::ALTERNATE_DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
+                }
+
+                LLColor4 color(gSky.mVOSkyp->getSun().getInterpColor());
+
+                sun_shader->uniform4fv(LLShaderMgr::DIFFUSE_COLOR, 1, color.mV);
+                sun_shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+                face->renderIndexed();
+
+                gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+                gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+
+                sun_shader->unbind();
+            }
+        }
+	}
 
-	gGL.popMatrix();
+    blend_factor = LLEnvironment::instance().getCurrentSky()->getBlendFactor();
 
-	renderSkyClouds(camHeightLocal);
+	face = gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON];
 
-	gGL.setColorMask(true, true);
-	//gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+	if (gSky.mVOSkyp->getMoon().getDraw() && face && face->getTexture(LLRender::DIFFUSE_MAP) && face->getGeomCount() && moon_shader)
+	{        
+        LLViewerTexture* tex_a = face->getTexture(LLRender::DIFFUSE_MAP);
+        LLViewerTexture* tex_b = face->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP);
 
+		LLColor4 color(gSky.mVOSkyp->getMoon().getInterpColor());
+		
+        if (can_use_vertex_shaders && can_use_windlight_shaders && (tex_a || tex_b))
+        {
+            moon_shader->bind();
+
+            if (tex_a && (!tex_b || (tex_a == tex_b)))
+            {
+                // Bind current and next sun textures
+                moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_a, LLTexUnit::TT_TEXTURE);
+                blend_factor = 0;
+            }
+            else if (tex_b && !tex_a)
+            {
+                moon_shader->bindTexture(LLShaderMgr::DIFFUSE_MAP, tex_b, LLTexUnit::TT_TEXTURE);
+                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);
+            }
+
+            LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+            F32 moon_brightness = (float)psky->getMoonBrightness();
+
+            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);
+
+            face->renderIndexed();
+
+            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+            gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
+
+            moon_shader->unbind();
+        }
+    }
+
+    gGL.popMatrix();
 }
 
-void LLDrawPoolWLSky::render(S32 pass)
+void LLDrawPoolWLSky::renderDeferred(S32 pass)
 {
 	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
 	{
@@ -357,34 +592,37 @@ void LLDrawPoolWLSky::render(S32 pass)
 	}
 	LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY);
 
-	const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius();
-
-	LLGLSNoFog disableFog;
-	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-	LLGLDisable clip(GL_CLIP_PLANE0);
-
-	LLGLSquashToFarClip far_clip(glh_get_current_projection());
-
-	renderSkyHaze(camHeightLocal);
-
-	LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
-	gGL.pushMatrix();
+    const F32 camHeightLocal = LLEnvironment::instance().getCamHeight();
 
-		gGL.translatef(origin.mV[0], origin.mV[1], origin.mV[2]);
-
-		// *NOTE: have to bind a texture here since register combiners blending in
-		// renderStars() requires something to be bound and we might as well only
-		// bind the moon's texture once.		
-		gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture());
+	gGL.setColorMask(true, false);
 
-		renderHeavenlyBodies();
+    LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
 
-		renderStars();
-		
+    if (gPipeline.canUseWindLightShaders())
+    {
+        renderSkyHazeDeferred(origin, camHeightLocal);
+        renderStarsDeferred();
+        renderHeavenlyBodies();
+        renderSkyCloudsDeferred(origin, camHeightLocal, cloud_shader);
+    }
+    gGL.setColorMask(true, true);
+}
 
-	gGL.popMatrix();
+void LLDrawPoolWLSky::render(S32 pass)
+{
+	if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY))
+	{
+		return;
+	}
+	LL_RECORD_BLOCK_TIME(FTM_RENDER_WL_SKY);
 
-	renderSkyClouds(camHeightLocal);
+    const F32 camHeightLocal = LLEnvironment::instance().getCamHeight();
+    LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
+    
+	renderSkyHaze(origin, camHeightLocal);    
+    renderStars();
+    renderHeavenlyBodies();	
+	renderSkyClouds(origin, camHeightLocal, cloud_shader);
 
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 }
@@ -411,15 +649,9 @@ void LLDrawPoolWLSky::resetDrawOrders()
 //static
 void LLDrawPoolWLSky::cleanupGL()
 {
-	sCloudNoiseTexture = NULL;
 }
 
 //static
 void LLDrawPoolWLSky::restoreGL()
 {
-	if(sCloudNoiseRawImage.notNull())
-	{
-		sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE);
-	}
 }
-
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index cd15c991ee091fefb8e4f3f6a7ab452fa77364bb..3acfda4eee55508f3779a5aa65e96a6300ffd3bf 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -38,7 +38,8 @@ class LLDrawPoolWLSky : public LLDrawPool {
 							LLVertexBuffer::MAP_TEXCOORD0;
 	static const U32 STAR_VERTEX_DATA_MASK =	LLVertexBuffer::MAP_VERTEX |
 		LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0;
-
+    static const U32 ADV_ATMO_SKY_VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX
+                                                   | LLVertexBuffer::MAP_TEXCOORD0;
 	LLDrawPoolWLSky(void);
 	/*virtual*/ ~LLDrawPoolWLSky();
 
@@ -57,7 +58,7 @@ class LLDrawPoolWLSky : public LLDrawPool {
 	/*virtual*/ void prerender();
 	/*virtual*/ U32 getVertexDataMask() { return SKY_VERTEX_DATA_MASK; }
 	/*virtual*/ BOOL verify() const { return TRUE; }		// Verify that all data in the draw pool is correct!
-	/*virtual*/ S32 getVertexShaderLevel() const { return mVertexShaderLevel; }
+	/*virtual*/ S32 getShaderLevel() const { return mShaderLevel; }
 	
 	//static LLDrawPool* createPool(const U32 type, LLViewerTexture *tex0 = NULL);
 
@@ -70,15 +71,18 @@ class LLDrawPoolWLSky : public LLDrawPool {
 	static void cleanupGL();
 	static void restoreGL();
 private:
-	void renderDome(F32 camHeightLocal, LLGLSLShader * shader) const;
-	void renderSkyHaze(F32 camHeightLocal) const;
-	void renderStars(void) const;
-	void renderSkyClouds(F32 camHeightLocal) const;
-	void renderHeavenlyBodies();
+    void renderFsSky(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader * shader) const;
+	void renderDome(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader * shader) const;
 
-private:
-	static LLPointer<LLViewerTexture> sCloudNoiseTexture;
-	static LLPointer<LLImageRaw> sCloudNoiseRawImage;
+    void renderSkyHaze(const LLVector3& camPosLocal, F32 camHeightLocal) const;
+    void renderSkyClouds(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const;
+
+	void renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const;
+    void renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const;
+
+    void renderStarsDeferred(void) const;
+	void renderStars(void) const;
+	void renderHeavenlyBodies();    
 };
 
 #endif // LL_DRAWPOOLWLSKY_H
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 8ef0dd28650329cc0431d32a8a8ab9babc5bd956..1e8c57ac6ad422746216af8d38b2a121b529eb6a 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -129,7 +129,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth)
 	llassert(mFullHeight <= 512);
 	llassert(mFullWidth <= 512);
 
-	if (gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI)
+	if (gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete())
 	{ //using offscreen render target, just use the bottom left corner
 		mOrigin.set(0, 0);
 	}
@@ -216,11 +216,12 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 		return TRUE;
 	}
 
-	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mWaterDis.isComplete() && !gGLManager.mIsATI;
+	bool use_fbo = gGLManager.mHasFramebufferObject && gPipeline.mBake.isComplete();
 
 	if (use_fbo)
 	{
-		gPipeline.mWaterDis.bindTarget();
+		gPipeline.mBake.bindTarget();
+        gPipeline.mBake.clear();
 	}
 
 	LLGLSLShader::bindNoShader();
@@ -240,6 +241,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 				gDepthDirty = TRUE;
 								
 				gGL.color4f(1,1,1,1);
+                dynamicTexture->setBoundTarget(use_fbo ? &gPipeline.mBake : nullptr);
 				dynamicTexture->preRender();	// Must be called outside of startRender()
 				result = FALSE;
 				if (dynamicTexture->render())
@@ -250,7 +252,7 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 				}
 				gGL.flush();
 				LLVertexBuffer::unbind();
-				
+				dynamicTexture->setBoundTarget(nullptr);
 				dynamicTexture->postRender(result);
 			}
 		}
@@ -258,9 +260,11 @@ BOOL LLViewerDynamicTexture::updateAllInstances()
 
 	if (use_fbo)
 	{
-		gPipeline.mWaterDis.flush();
+		gPipeline.mBake.flush();
 	}
 
+    gGL.flush();
+
 	return ret;
 }
 
diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h
index f3f57c9a6b2752e110021c3733afbb33bfdd4aca..4bd74a84252ece10ee9e4ae884a83fcb9264be8b 100644
--- a/indra/newview/lldynamictexture.h
+++ b/indra/newview/lldynamictexture.h
@@ -88,6 +88,9 @@ class LLViewerDynamicTexture : public LLViewerTexture
 	static BOOL	updateAllInstances();
 	static void destroyGL() ;
 	static void restoreGL() ;
+
+    void setBoundTarget(LLRenderTarget* target) { mBoundTarget = target; }
+
 protected:
 	void generateGLTexture();
 	void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE);
@@ -97,6 +100,8 @@ class LLViewerDynamicTexture : public LLViewerTexture
 	LLCoordGL mOrigin;
 	LL_ALIGN_16(LLCamera mCamera);
 	
+    LLRenderTarget* mBoundTarget;
+
 	typedef std::set<LLViewerDynamicTexture*> instance_list_t;
 	static instance_list_t sInstances[ LLViewerDynamicTexture::ORDER_COUNT ];
 	static S32 sNumRenders;
diff --git a/indra/newview/llenvadapters.cpp b/indra/newview/llenvadapters.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fdbcf68fa44e0f9a36efc402d8d7212a841bd9a2
--- /dev/null
+++ b/indra/newview/llenvadapters.cpp
@@ -0,0 +1,67 @@
+/**
+ * @file llenvadapters.cpp
+ * @brief Declaration of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llenvadapters.h"
+
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+//=========================================================================
+
+LLSkySettingsAdapter::LLSkySettingsAdapter():
+    mWLGamma(1.0f, LLSettingsSky::SETTING_GAMMA),
+    
+    // Lighting
+    mLightnorm(LLColor4(0.f, 0.707f, -0.707f, 1.f), LLSettingsSky::SETTING_LIGHT_NORMAL),
+    mSunlight(LLColor4(0.5f, 0.5f, 0.5f, 1.0f), LLSettingsSky::SETTING_SUNLIGHT_COLOR, "WLSunlight"),
+    
+    mGlow(LLColor4(18.0f, 0.0f, -0.01f, 1.0f), LLSettingsSky::SETTING_GLOW),
+    // Clouds
+    mCloudColor(LLColor4(0.5f, 0.5f, 0.5f, 1.0f), LLSettingsSky::SETTING_CLOUD_COLOR, "WLCloudColor"),
+    mCloudMain(LLColor4(0.5f, 0.5f, 0.125f, 1.0f), LLSettingsSky::SETTING_CLOUD_POS_DENSITY1),
+    mCloudCoverage(0.0f, LLSettingsSky::SETTING_CLOUD_SHADOW),
+    mCloudDetail(LLColor4(0.0f, 0.0f, 0.0f, 1.0f), LLSettingsSky::SETTING_CLOUD_POS_DENSITY2),    
+    mCloudScale(0.42f, LLSettingsSky::SETTING_CLOUD_SCALE)
+{
+
+}
+
+LLWatterSettingsAdapter::LLWatterSettingsAdapter():
+    mFogColor(LLColor4((22.f / 255.f), (43.f / 255.f), (54.f / 255.f), (0.0f)), LLSettingsWater::SETTING_FOG_COLOR, "WaterFogColor"),
+    mFogDensity(4, LLSettingsWater::SETTING_FOG_DENSITY, 2),
+    mUnderWaterFogMod(0.25, LLSettingsWater::SETTING_FOG_MOD),
+    mNormalScale(LLVector3(2.f, 2.f, 2.f), LLSettingsWater::SETTING_NORMAL_SCALE),
+    mFresnelScale(0.5f, LLSettingsWater::SETTING_FRESNEL_SCALE),
+    mFresnelOffset(0.4f, LLSettingsWater::SETTING_FRESNEL_OFFSET),
+    mScaleAbove(0.025f, LLSettingsWater::SETTING_SCALE_ABOVE),
+    mScaleBelow(0.2f, LLSettingsWater::SETTING_SCALE_BELOW),
+    mBlurMultiplier(0.1f, LLSettingsWater::SETTING_BLUR_MULTIPILER),
+    mWave1Dir(LLVector2(0.5f, 0.5f), LLSettingsWater::SETTING_WAVE1_DIR),
+    mWave2Dir(LLVector2(0.5f, 0.5f), LLSettingsWater::SETTING_WAVE2_DIR)
+
+{
+
+}
diff --git a/indra/newview/llenvadapters.h b/indra/newview/llenvadapters.h
new file mode 100644
index 0000000000000000000000000000000000000000..bd58db0589eee60b2f6057f4828464587876daaf
--- /dev/null
+++ b/indra/newview/llenvadapters.h
@@ -0,0 +1,459 @@
+/**
+ * @file llenvadapters.h
+ * @brief Declaration of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifndef LL_ENVADAPTERS_H
+#define LL_ENVADAPTERS_H
+
+#include "v3math.h"
+#include "v3color.h"
+#include "v4math.h"
+#include "llsettingsbase.h"
+#include "llsettingssky.h"
+
+class WLColorControl 
+{
+public:
+    inline WLColorControl(LLColor4 color, const std::string& n, const std::string& slider_name = std::string()):
+        mColor(color), 
+        mName(n), 
+        mSliderName(slider_name),
+        mHasSliderName(false),
+        mIsSunOrAmbientColor(false),
+        mIsBlueHorizonOrDensity(false)
+    {
+        // if there's a slider name, say we have one
+        mHasSliderName = !mSliderName.empty();
+
+        // if it's the sun controller
+        mIsSunOrAmbientColor = (mSliderName == "WLSunlight" || mSliderName == "WLAmbient");
+        mIsBlueHorizonOrDensity = (mSliderName == "WLBlueHorizon" || mSliderName == "WLBlueDensity");
+    }
+
+    inline void setColor4(const LLColor4 & val)
+    {
+        mColor = val;
+    }
+
+    inline void setColor3(const LLColor3 & val)
+    {
+        mColor = val;
+    }
+
+    inline LLColor4 getColor4() const
+    {
+        return mColor;
+    }
+
+    inline LLColor3 getColor3(void) const 
+    {
+        return vec4to3(mColor);
+    }
+
+    inline void update(const LLSettingsBase::ptr_t &psetting) const 
+    {
+        psetting->setValue(mName, mColor);
+    }
+
+    inline bool getHasSliderName() const
+    {
+        return mHasSliderName;
+    }
+
+    inline std::string getSliderName() const
+    {
+        return mSliderName;
+    }
+
+    inline bool getIsSunOrAmbientColor() const
+    {
+        return mIsSunOrAmbientColor;
+    }
+
+    inline bool getIsBlueHorizonOrDensity() const
+    {
+        return mIsBlueHorizonOrDensity;
+    }
+
+    inline F32 getRed() const
+    {
+        return mColor[0];
+    }
+
+    inline F32 getGreen() const
+    {
+        return mColor[1];
+    }
+
+    inline F32 getBlue() const
+    {
+        return mColor[2];
+    }
+
+    inline F32 getIntensity() const
+    {
+        return mColor[3];
+    }
+
+    inline void setRed(F32 red)
+    {
+        mColor[0] = red;
+    }
+
+    inline void setGreen(F32 green)
+    {
+        mColor[1] = green;
+    }
+
+    inline void setBlue(F32 blue)
+    {
+        mColor[2] = blue;
+    }
+
+    inline void setIntensity(F32 intensity)
+    {
+        mColor[3] = intensity;
+    }
+
+private:
+    LLColor4    mColor;         /// [3] is intensity, not alpha
+    std::string mName;			/// name to use to dereference params
+    std::string mSliderName;	/// name of the slider in menu
+    bool        mHasSliderName;			/// only set slider name for true color types
+    bool        mIsSunOrAmbientColor;			/// flag for if it's the sun or ambient color controller
+    bool        mIsBlueHorizonOrDensity;		/// flag for if it's the Blue Horizon or Density color controller
+
+};
+
+// float slider control
+class WLFloatControl 
+{
+public:
+    inline WLFloatControl(F32 val, const std::string& n, F32 m = 1.0f):
+        x(val), 
+        mName(n), 
+        mult(m)
+    {
+    }
+
+    inline WLFloatControl &operator = (F32 val) 
+    {
+        x = val;
+        return *this;
+    }
+
+    inline operator F32 (void) const 
+    {
+        return x;
+    }
+
+    inline void update(const LLSettingsBase::ptr_t &psetting) const 
+    {
+        psetting->setValue(mName, x);
+    }
+
+    inline F32 getMult() const
+    {
+        return mult;
+    }
+
+    inline void setValue(F32 val)
+    {
+        x = val;
+    }
+
+private:
+    F32 x;
+    std::string mName;
+    F32 mult;
+};
+
+class WLXFloatControl
+{
+public:
+    inline WLXFloatControl(F32 val, const std::string& n, F32 b): 
+        mExp(val),
+        mBase(b),
+        mName(n)
+    {
+    }
+
+    inline WLXFloatControl & operator = (F32 val)
+    {
+        mExp = log(val) / log(mBase);
+
+        return *this;
+    }
+
+    inline operator F32 (void) const
+    {
+        return pow(mBase, mExp);
+    }
+
+    inline void update(const LLSettingsBase::ptr_t &psetting) const
+    {
+        psetting->setValue(mName, pow(mBase, mExp));
+    }
+
+    inline F32 getExp() const
+    {
+        return mExp;
+    }
+
+    inline void setExp(F32 val)
+    {
+        mExp = val;
+    }
+
+    inline F32 getBase() const
+    {
+        return mBase;
+    }
+
+    inline void setBase(F32 val)
+    {
+        mBase = val;
+    }
+
+private:
+    F32 mExp;
+    F32 mBase;
+    std::string mName;
+};
+
+class WLVect2Control
+{
+public:
+    inline WLVect2Control(LLVector2 val, const std::string& n): 
+        mU(val.mV[0]), 
+        mV(val.mV[1]), 
+        mName(n)
+    {
+    }
+
+    inline WLVect2Control & operator = (const LLVector2 & val)
+    {
+        mU = val.mV[0];
+        mV = val.mV[1];
+
+        return *this;
+    }
+
+    inline void update(const LLSettingsBase::ptr_t &psetting) const
+    {
+        psetting->setValue(mName, LLVector2(mU, mV));
+    }
+
+    inline F32 getU() const
+    {
+        return mU;
+    }
+
+    inline void setU(F32 val)
+    {
+        mU = val;
+    }
+
+    inline F32 getV() const
+    {
+        return mV;
+    }
+
+    inline void setV(F32 val)
+    {
+        mV = val;
+    }
+
+private:
+    F32 mU;
+    F32 mV;
+    std::string mName;
+};
+
+class WLVect3Control
+{
+public:
+    inline WLVect3Control(LLVector3 val, const std::string& n):
+        mX(val.mV[0]),
+        mY(val.mV[1]),
+        mZ(val.mV[2]),
+        mName(n)
+    {
+    }
+
+    inline WLVect3Control & operator = (const LLVector3 & val)
+    {
+        mX = val.mV[0];
+        mY = val.mV[1];
+        mZ = val.mV[2];
+
+        return *this;
+    }
+
+    inline void update(const LLSettingsBase::ptr_t &psetting) const
+    {
+        psetting->setValue(mName, LLVector3(mX, mY, mZ));
+    }
+
+    inline F32 getX() const
+    {
+        return mX;
+    }
+
+    inline void setX(F32 val)
+    {
+        mX = val;
+    }
+
+    inline F32 getY() const
+    {
+        return mY;
+    }
+
+    inline void setY(F32 val)
+    {
+        mY = val;
+    }
+
+    inline F32 getZ() const
+    {
+        return mZ;
+    }
+
+    inline void setZ(F32 val)
+    {
+        mZ = val;
+    }
+
+private:
+    F32 mX;
+    F32 mY;
+    F32 mZ;
+    std::string mName;
+};
+
+class LLDensityProfileSettingsAdapter
+{
+public:
+    LLDensityProfileSettingsAdapter(const std::string& config, int layerIndex = 0)
+    : mConfig(config)
+    , mLayerIndex(layerIndex)
+    , mLayerWidth(1.0f, LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH)
+    , mExpTerm(1.0f, LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM)
+    , mExpScale(1.0f, LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR)
+    , mLinTerm(1.0f, LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM)
+    , mConstantTerm(1.0f, LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM)
+    {}
+
+protected:
+    std::string     mConfig;
+    int             mLayerIndex;
+    WLFloatControl  mLayerWidth; // 0.0 -> to top of atmosphere, however big that may be.
+    WLFloatControl  mExpTerm;
+    WLFloatControl  mExpScale;
+    WLFloatControl  mLinTerm;
+    WLFloatControl  mConstantTerm;
+};
+
+class LLRayleighDensityProfileSettingsAdapter : public LLDensityProfileSettingsAdapter
+{
+public:
+    LLRayleighDensityProfileSettingsAdapter(int layerIndex = 0)
+    : LLDensityProfileSettingsAdapter(LLSettingsSky::SETTING_RAYLEIGH_CONFIG, layerIndex)
+    {
+    }
+};
+
+class LLMieDensityProfileSettingsAdapter : public LLDensityProfileSettingsAdapter
+{
+public:
+    LLMieDensityProfileSettingsAdapter(int layerIndex = 0)
+    : LLDensityProfileSettingsAdapter(LLSettingsSky::SETTING_MIE_CONFIG, layerIndex)
+    , mAnisotropy(0.8f, LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR)
+    {
+    }
+
+protected:
+    WLFloatControl  mAnisotropy;
+};
+
+class LLAbsorptionDensityProfileSettingsAdapter : public LLDensityProfileSettingsAdapter
+{
+public:
+    LLAbsorptionDensityProfileSettingsAdapter(int layerIndex = 0)
+    : LLDensityProfileSettingsAdapter(LLSettingsSky::SETTING_ABSORPTION_CONFIG, layerIndex)
+    {
+    }
+};
+
+//-------------------------------------------------------------------------
+class LLSkySettingsAdapter
+{
+public:
+    typedef std::shared_ptr<LLSkySettingsAdapter> ptr_t;
+    
+    LLSkySettingsAdapter();
+
+    WLFloatControl  mWLGamma;
+
+    /// Lighting
+    WLColorControl  mLightnorm;
+    WLColorControl  mSunlight;    
+    WLColorControl  mGlow;
+
+    /// Clouds
+    WLColorControl  mCloudColor;
+    WLColorControl  mCloudMain;
+    WLFloatControl  mCloudCoverage;
+    WLColorControl  mCloudDetail;    
+    WLFloatControl  mCloudScale;
+};
+
+class LLWatterSettingsAdapter
+{
+public:
+    typedef std::shared_ptr<LLWatterSettingsAdapter> ptr_t;
+
+    LLWatterSettingsAdapter();
+
+    WLColorControl  mFogColor;
+    WLXFloatControl mFogDensity;
+    WLFloatControl  mUnderWaterFogMod;
+
+    /// wavelet scales and directions
+    WLVect3Control  mNormalScale;
+    WLVect2Control  mWave1Dir;
+    WLVect2Control  mWave2Dir;
+
+    // controls how water is reflected and refracted
+    WLFloatControl  mFresnelScale;
+    WLFloatControl  mFresnelOffset;
+    WLFloatControl  mScaleAbove;
+    WLFloatControl  mScaleBelow;
+    WLFloatControl  mBlurMultiplier;
+
+};
+
+#endif // LL_ENVIRONMENT_H
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e1c4f943468441151193def0616499d121d1831
--- /dev/null
+++ b/indra/newview/llenvironment.cpp
@@ -0,0 +1,3419 @@
+/**
+ * @file llenvmanager.cpp
+ * @brief Implementation of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llenvironment.h"
+
+#include <algorithm>
+
+#include "llagent.h"
+#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewerregion.h"
+#include "llwlhandlers.h"
+#include "lltrans.h"
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "llviewercamera.h"
+#include "pipeline.h"
+#include "llsky.h"
+
+#include "llviewershadermgr.h"
+
+#include "llparcel.h"
+#include "llviewerparcelmgr.h"
+
+#include "llsdserialize.h"
+#include "lldiriterator.h"
+
+#include "llsettingsvo.h"
+#include "llnotificationsutil.h"
+
+#include "llregioninfomodel.h"
+
+#include <boost/make_shared.hpp>
+
+#include "llatmosphere.h"
+#include "llagent.h"
+#include "roles_constants.h"
+#include "llestateinfomodel.h"
+
+#include "lldispatcher.h"
+#include "llviewergenericmessage.h"
+#include "llexperiencelog.h"
+
+//=========================================================================
+namespace
+{
+    const std::string KEY_ENVIRONMENT("environment");
+    const std::string KEY_DAYASSET("day_asset");
+    const std::string KEY_DAYCYCLE("day_cycle");
+    const std::string KEY_DAYHASH("day_hash");
+    const std::string KEY_DAYLENGTH("day_length");
+    const std::string KEY_DAYNAME("day_name");
+    const std::string KEY_DAYNAMES("day_names");
+    const std::string KEY_DAYOFFSET("day_offset");
+    const std::string KEY_ENVVERSION("env_version");
+    const std::string KEY_ISDEFAULT("is_default");
+    const std::string KEY_PARCELID("parcel_id");
+    const std::string KEY_REGIONID("region_id");
+    const std::string KEY_TRACKALTS("track_altitudes");
+    const std::string KEY_FLAGS("flags");
+
+    const std::string MESSAGE_PUSHENVIRONMENT("PushExpEnvironment");
+
+    const std::string ACTION_CLEARENVIRONMENT("ClearEnvironment");
+    const std::string ACTION_PUSHFULLENVIRONMENT("PushFullEnvironment");
+    const std::string ACTION_PUSHPARTIALENVIRONMENT("PushPartialEnvironment");
+
+    const std::string KEY_ASSETID("asset_id");
+    const std::string KEY_TRANSITIONTIME("transition_time");
+    const std::string KEY_ACTION("action");
+    const std::string KEY_ACTIONDATA("action_data");
+    const std::string KEY_EXPERIENCEID("public_id");
+    const std::string KEY_OBJECTNAME("ObjectName");     // some of these do not conform to the '_' format.  
+    const std::string KEY_PARCELNAME("ParcelName");     // But changing these would also alter the Experience Log requirements.
+    const std::string KEY_COUNT("Count");
+
+    const std::string LISTENER_NAME("LLEnvironmentSingleton");
+    const std::string PUMP_EXPERIENCE("experience_permission");
+
+    const std::string LOCAL_ENV_STORAGE_FILE("local_environment_data.bin");
+
+    //---------------------------------------------------------------------
+    LLTrace::BlockTimerStatHandle   FTM_ENVIRONMENT_UPDATE("Update Environment Tick");
+    LLTrace::BlockTimerStatHandle   FTM_SHADER_PARAM_UPDATE("Update Shader Parameters");
+
+    LLSettingsBase::Seconds         DEFAULT_UPDATE_THRESHOLD(10.0);
+    const LLSettingsBase::Seconds   MINIMUM_SPANLENGTH(0.01f);
+
+    //---------------------------------------------------------------------
+    inline LLSettingsBase::TrackPosition get_wrapping_distance(LLSettingsBase::TrackPosition begin, LLSettingsBase::TrackPosition end)
+    {
+        if (begin < end)
+        {
+            return end - begin;
+        }
+        else if (begin > end)
+        {
+            return LLSettingsBase::TrackPosition(1.0) - (begin - end);
+        }
+
+        return 1.0f;
+    }
+
+    LLSettingsDay::CycleTrack_t::iterator get_wrapping_atafter(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
+    {
+        if (collection.empty())
+            return collection.end();
+
+        LLSettingsDay::CycleTrack_t::iterator it = collection.upper_bound(key);
+
+        if (it == collection.end())
+        {   // wrap around
+            it = collection.begin();
+        }
+
+        return it;
+    }
+
+    LLSettingsDay::CycleTrack_t::iterator get_wrapping_atbefore(LLSettingsDay::CycleTrack_t &collection, const LLSettingsBase::TrackPosition& key)
+    {
+        if (collection.empty())
+            return collection.end();
+
+        LLSettingsDay::CycleTrack_t::iterator it = collection.lower_bound(key);
+
+        if (it == collection.end())
+        {   // all keyframes are lower, take the last one.
+            --it; // we know the range is not empty
+        }
+        else if ((*it).first > key)
+        {   // the keyframe we are interested in is smaller than the found.
+            if (it == collection.begin())
+                it = collection.end();
+            --it;
+        }
+
+        return it;
+    }
+
+    LLSettingsDay::TrackBound_t get_bounding_entries(LLSettingsDay::CycleTrack_t &track, const LLSettingsBase::TrackPosition& keyframe)
+    {
+        return LLSettingsDay::TrackBound_t(get_wrapping_atbefore(track, keyframe), get_wrapping_atafter(track, keyframe));
+    }
+
+    // Find normalized track position of given time along full length of cycle
+    inline LLSettingsBase::TrackPosition convert_time_to_position(const LLSettingsBase::Seconds& time, const LLSettingsBase::Seconds& len)
+    {
+        LLSettingsBase::TrackPosition position = LLSettingsBase::TrackPosition(fmod((F64)time, (F64)len) / (F64)len);
+        return llclamp(position, 0.0f, 1.0f);
+    }
+
+    inline LLSettingsBase::BlendFactor convert_time_to_blend_factor(const LLSettingsBase::Seconds& time, const LLSettingsBase::Seconds& len, LLSettingsDay::CycleTrack_t &track)
+    {
+        LLSettingsBase::TrackPosition position = convert_time_to_position(time, len);
+        LLSettingsDay::TrackBound_t bounds(get_bounding_entries(track, position));
+
+        LLSettingsBase::TrackPosition spanlength(get_wrapping_distance((*bounds.first).first, (*bounds.second).first));
+        if (position < (*bounds.first).first)
+            position += 1.0;
+
+        LLSettingsBase::TrackPosition start = position - (*bounds.first).first;
+
+        return static_cast<LLSettingsBase::BlendFactor>(start / spanlength);
+    }
+
+    //---------------------------------------------------------------------
+    class LLTrackBlenderLoopingTime : public LLSettingsBlenderTimeDelta
+    {
+    public:
+        LLTrackBlenderLoopingTime(const LLSettingsBase::ptr_t &target, const LLSettingsDay::ptr_t &day, S32 trackno,
+            LLSettingsBase::Seconds cyclelength, LLSettingsBase::Seconds cycleoffset, LLSettingsBase::Seconds updateThreshold) :
+            LLSettingsBlenderTimeDelta(target, LLSettingsBase::ptr_t(), LLSettingsBase::ptr_t(), LLSettingsBase::Seconds(1.0)),
+            mDay(day),
+            mTrackNo(0),
+            mCycleLength(cyclelength),
+            mCycleOffset(cycleoffset)
+        {
+            // must happen prior to getBoundingEntries call...
+            mTrackNo = selectTrackNumber(trackno);
+
+            LLSettingsBase::Seconds now(getAdjustedNow());
+            LLSettingsDay::TrackBound_t initial = getBoundingEntries(now);
+
+            mInitial = (*initial.first).second;
+            mFinal = (*initial.second).second;
+            mBlendSpan = getSpanTime(initial);
+
+            initializeTarget(now);
+            setOnFinished([this](const LLSettingsBlender::ptr_t &){ onFinishedSpan(); });
+        }
+
+        void switchTrack(S32 trackno, const LLSettingsBase::TrackPosition&) override
+        {
+            S32 use_trackno = selectTrackNumber(trackno);
+
+            if (use_trackno == mTrackNo)
+            {   // results in no change
+                return;
+            }
+
+            LLSettingsBase::ptr_t pstartsetting = mTarget->buildDerivedClone();
+            mTrackNo = use_trackno;
+
+            LLSettingsBase::Seconds now = getAdjustedNow() + LLEnvironment::TRANSITION_ALTITUDE;
+            LLSettingsDay::TrackBound_t bounds = getBoundingEntries(now);
+
+            LLSettingsBase::ptr_t pendsetting = (*bounds.first).second->buildDerivedClone();
+            LLSettingsBase::TrackPosition targetpos = convert_time_to_position(now, mCycleLength) - (*bounds.first).first;
+            LLSettingsBase::TrackPosition targetspan = get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
+
+            LLSettingsBase::BlendFactor blendf = calculateBlend(targetpos, targetspan);
+            pendsetting->blend((*bounds.second).second, blendf);
+
+            reset(pstartsetting, pendsetting, LLEnvironment::TRANSITION_ALTITUDE);
+        }
+
+    protected:
+        S32 selectTrackNumber(S32 trackno)
+        {
+            if (trackno == 0)
+            {   // We are dealing with the water track.  There is only ever one.
+                return trackno;
+            }
+
+            for (S32 test = trackno; test != 0; --test)
+            {   // Find the track below the requested one with data.
+                LLSettingsDay::CycleTrack_t &track = mDay->getCycleTrack(test);
+
+                if (!track.empty())
+                    return test;
+            }
+
+            return 1;
+        }
+
+        LLSettingsDay::TrackBound_t getBoundingEntries(LLSettingsBase::Seconds time)
+        {
+            LLSettingsDay::CycleTrack_t &wtrack = mDay->getCycleTrack(mTrackNo);
+            LLSettingsBase::TrackPosition position = convert_time_to_position(time, mCycleLength);
+            LLSettingsDay::TrackBound_t bounds = get_bounding_entries(wtrack, position);
+            return bounds;
+        }
+
+        void initializeTarget(LLSettingsBase::Seconds time)
+        {
+            LLSettingsBase::BlendFactor blendf(convert_time_to_blend_factor(time, mCycleLength, mDay->getCycleTrack(mTrackNo)));
+
+            blendf = llclamp(blendf, 0.0, 0.999);
+            setTimeSpent(LLSettingsBase::Seconds(blendf * mBlendSpan));
+
+            setBlendFactor(blendf);
+        }
+
+        LLSettingsBase::Seconds getAdjustedNow() const
+        {
+            LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch());
+
+            return (now + mCycleOffset);
+        }
+
+        LLSettingsBase::Seconds getSpanTime(const LLSettingsDay::TrackBound_t &bounds) const
+        {
+            LLSettingsBase::Seconds span = mCycleLength * get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
+            if (span < MINIMUM_SPANLENGTH) // for very short spans set a minimum length.
+                span = MINIMUM_SPANLENGTH;
+            return span;
+        }
+
+    private:
+        LLSettingsDay::ptr_t        mDay;
+        S32                         mTrackNo;
+        LLSettingsBase::Seconds     mCycleLength;
+        LLSettingsBase::Seconds     mCycleOffset;
+
+        void onFinishedSpan()
+        {
+            LLSettingsBase::Seconds adjusted_now = getAdjustedNow();
+            LLSettingsDay::TrackBound_t next = getBoundingEntries(adjusted_now);
+            LLSettingsBase::Seconds nextspan = getSpanTime(next);
+
+            reset((*next.first).second, (*next.second).second, nextspan);
+
+            // Recalculate (reinitialize) position. Because:
+            // - 'delta' from applyTimeDelta accumulates errors (probably should be fixed/changed to absolute time)
+            // - freezes and lag can result in reset being called too late, so we need to add missed time
+            // - occasional time corrections can happen
+            // - some transition switches can happen outside applyTimeDelta thus causing 'desync' from 'delta' (can be fixed by getting rid of delta)
+            initializeTarget(adjusted_now);
+        }
+    };
+
+    class LLEnvironmentPushDispatchHandler : public LLDispatchHandler
+    {
+    public:
+        virtual bool operator()(const LLDispatcher *, const std::string& key, const LLUUID& invoice, const sparam_t& strings) override
+        {
+            LLSD message;
+            sparam_t::const_iterator it = strings.begin();
+
+            if (it != strings.end())
+            {
+                const std::string& llsdRaw = *it++;
+                std::istringstream llsdData(llsdRaw);
+                if (!LLSDSerialize::deserialize(message, llsdData, llsdRaw.length()))
+                {
+                    LL_WARNS() << "LLExperienceLogDispatchHandler: Attempted to read parameter data into LLSD but failed:" << llsdRaw << LL_ENDL;
+                }
+            }
+
+            message[KEY_EXPERIENCEID] = invoice;
+            // Object Name
+            if (it != strings.end())
+            {
+                message[KEY_OBJECTNAME] = *it++;
+            }
+
+            // parcel Name
+            if (it != strings.end())
+            {
+                message[KEY_PARCELNAME] = *it++;
+            }
+            message[KEY_COUNT] = 1;
+
+            LLEnvironment::instance().handleEnvironmentPush(message);
+            return true;
+        }
+    };
+
+    LLEnvironmentPushDispatchHandler environment_push_dispatch_handler;
+
+    template<class SETTINGT>
+    class LLSettingsInjected : public SETTINGT
+    {
+    public:
+        typedef std::shared_ptr<LLSettingsInjected<SETTINGT> >  ptr_t;
+
+        LLSettingsInjected(typename SETTINGT::ptr_t source) :
+            SETTINGT(),
+            mSource(source),
+            mLastSourceHash(0),
+            mLastHash(0)
+        {}
+
+        virtual ~LLSettingsInjected() {};
+
+        typename SETTINGT::ptr_t getSource() const                    { return this->mSource; }
+        void setSource(const typename SETTINGT::ptr_t &source)        
+        {
+            if (source.get() == this) // do not set a source to itself.
+                return;
+            this->mSource = source; 
+            this->setDirtyFlag(true); 
+            this->mLastSourceHash = 0; 
+        }
+
+        virtual bool isDirty() const override { return SETTINGT::isDirty() || (this->mSource->isDirty()); }
+        virtual bool isVeryDirty() const override { return SETTINGT::isVeryDirty() || (this->mSource->isVeryDirty()); }
+
+        void injectSetting(const std::string keyname, LLSD value, LLUUID experience_id, F32Seconds transition)
+        {
+            if (transition > 0.1)
+            {
+                typename Injection::ptr_t injection = std::make_shared<Injection>(transition, keyname, value, true, experience_id);
+
+                mInjections.push_back(injection);
+                std::stable_sort(mInjections.begin(), mInjections.end(), [](const typename Injection::ptr_t &a, const typename Injection::ptr_t &b) { return a->mTimeRemaining < b->mTimeRemaining; });
+            }
+            else
+            {
+                mOverrideValues[keyname] = value;
+                mOverrideExps[keyname] = experience_id;
+                this->setDirtyFlag(true);
+            }
+        }
+
+        void removeInjection(const std::string keyname, LLUUID experience, LLSettingsBase::Seconds transition)
+        {
+            injections_t injections_buf;
+            for (auto it = mInjections.begin(); it != mInjections.end(); it++)
+            {
+                if ((keyname.empty() || ((*it)->mKeyName == keyname)) &&
+                    (experience.isNull() || (experience == (*it)->mExperience)))
+                {
+                    if (transition != LLEnvironment::TRANSITION_INSTANT)
+                    {
+                        typename Injection::ptr_t injection = std::make_shared<Injection>(transition, keyname, (*it)->mLastValue, false, LLUUID::null);
+                        injections_buf.push_front(injection);
+                    }
+                }
+                else
+                {
+                    injections_buf.push_front(*it);
+                }
+            }
+            mInjections.clear();
+            mInjections = injections_buf;
+
+            for (auto itexp = mOverrideExps.begin(); itexp != mOverrideExps.end();)
+            {
+                if (experience.isNull() || ((*itexp).second == experience))
+                {
+                    if (transition != LLEnvironment::TRANSITION_INSTANT)
+                    {
+                        typename Injection::ptr_t injection = std::make_shared<Injection>(transition, (*itexp).first, mOverrideValues[(*itexp).first], false, LLUUID::null);
+                        mInjections.push_front(injection);
+                    }
+                    mOverrideValues.erase((*itexp).first);
+                    mOverrideExps.erase(itexp++);
+                }
+                else
+                    ++itexp;
+            }
+            std::stable_sort(mInjections.begin(), mInjections.end(), [](const typename Injection::ptr_t &a, const typename Injection::ptr_t &b) { return a->mTimeRemaining < b->mTimeRemaining; });
+        }
+
+        void removeInjections(LLUUID experience_id, LLSettingsBase::Seconds transition)
+        {
+            removeInjection(std::string(), experience_id, transition);
+        }
+
+        void injectExperienceValues(LLSD values, LLUUID experience_id, typename LLSettingsBase::Seconds transition)
+        {
+            for (auto it = values.beginMap(); it != values.endMap(); ++it)
+            {
+                injectSetting((*it).first, (*it).second, experience_id, transition);
+            }
+            this->setDirtyFlag(true);
+        }
+
+        void applyInjections(LLSettingsBase::Seconds delta)
+        {
+            this->mSettings = this->mSource->getSettings();
+
+            for (auto ito = mOverrideValues.beginMap(); ito != mOverrideValues.endMap(); ++ito)
+            {
+                this->mSettings[(*ito).first] = (*ito).second;
+            }
+
+            const LLSettingsBase::stringset_t &slerps = this->getSlerpKeys();
+            const LLSettingsBase::stringset_t &skips = this->getSkipInterpolateKeys();
+            const LLSettingsBase::stringset_t &specials = this->getSpecialKeys();
+
+            typename injections_t::iterator it;
+            for (it = mInjections.begin(); it != mInjections.end(); ++it)
+            {
+                std::string key_name = (*it)->mKeyName;
+
+                LLSD value = this->mSettings[key_name];
+                LLSD target = (*it)->mValue;
+
+                if ((*it)->mFirstTime)
+                    (*it)->mFirstTime = false;
+                else
+                    (*it)->mTimeRemaining -= delta;
+
+                typename LLSettingsBase::BlendFactor mix = 1.0f - ((*it)->mTimeRemaining.value() / (*it)->mTransition.value());
+
+                if (mix >= 1.0)
+                {
+                    if ((*it)->mBlendIn)
+                    {
+                        mOverrideValues[key_name] = target;
+                        mOverrideExps[key_name] = (*it)->mExperience;
+                        this->mSettings[key_name] = target;
+                    }
+                    else
+                    {
+                        this->mSettings.erase(key_name);
+                    }
+                }
+                else if (specials.find(key_name) != specials.end())
+                {
+                    updateSpecial(*it, mix);
+                }
+                else if (skips.find(key_name) == skips.end())
+                {
+                    if (!(*it)->mBlendIn)
+                        mix = 1.0 - mix;
+                    (*it)->mLastValue = this->interpolateSDValue(key_name, value, target, this->getParameterMap(), mix, slerps);
+                    this->mSettings[key_name] = (*it)->mLastValue;
+                }
+            }
+
+            size_t hash = this->getHash();
+
+            if (hash != mLastHash)
+            {
+                this->setDirtyFlag(true);
+                mLastHash = hash;
+            }
+
+            it = mInjections.begin();
+            it = std::find_if(mInjections.begin(), mInjections.end(), [](const typename Injection::ptr_t &a) { return a->mTimeRemaining > 0.0f; });
+
+            if (it != mInjections.begin())
+            {
+                mInjections.erase(mInjections.begin(), mInjections.end());
+            }
+
+        }
+
+        bool hasInjections() const
+        {
+            return (!mInjections.empty() || (mOverrideValues.size() > 0));
+        }
+
+    protected:
+        struct Injection
+        {
+            Injection(typename LLSettingsBase::Seconds transition, const std::string &keyname, LLSD value, bool blendin, LLUUID experince, S32 index = -1) :
+                mTransition(transition),
+                mTimeRemaining(transition),
+                mKeyName(keyname),
+                mValue(value),
+                mExperience(experince),
+                mIndex(index),
+                mBlendIn(blendin),
+                mFirstTime(true)
+            {}
+
+            typename LLSettingsBase::Seconds    mTransition;
+            typename LLSettingsBase::Seconds    mTimeRemaining;
+            std::string                         mKeyName;
+            LLSD                                mValue;
+            LLSD                                mLastValue;
+            LLUUID                              mExperience;
+            S32                                 mIndex;
+            bool                                mBlendIn;
+            bool                                mFirstTime;
+
+            typedef std::shared_ptr<Injection>  ptr_t;
+        };
+
+
+        virtual void updateSettings() override
+        {
+            static LLFrameTimer timer;
+
+            if (!this->mSource)
+                return;
+
+            // clears the dirty flag on this object.  Need to prevent triggering 
+            // more calls into this updateSettings
+            LLSettingsBase::updateSettings();
+
+            resetSpecial();
+
+            if (this->mSource->isDirty())
+            {
+                this->mSource->updateSettings();
+            }
+
+            typename LLSettingsBase::Seconds delta(timer.getElapsedTimeAndResetF32());
+
+
+            SETTINGT::updateSettings();
+
+            if (!mInjections.empty())
+                this->setDirtyFlag(true);
+        }
+
+        LLSettingsBase::stringset_t getSpecialKeys() const;
+        void                        resetSpecial();
+        void                        updateSpecial(const typename Injection::ptr_t &injection, typename LLSettingsBase::BlendFactor mix);
+
+    private:
+        typedef std::map<std::string, LLUUID>   key_to_expid_t;
+        typedef std::deque<typename Injection::ptr_t>    injections_t;
+
+        size_t                      mLastSourceHash;
+        size_t                      mLastHash;
+        typename SETTINGT::ptr_t    mSource;
+        injections_t                mInjections;
+        LLSD                        mOverrideValues;
+        key_to_expid_t              mOverrideExps;
+    };
+
+    template<>
+    LLSettingsBase::stringset_t LLSettingsInjected<LLSettingsVOSky>::getSpecialKeys() const
+    {
+        static LLSettingsBase::stringset_t specialSet;
+
+        if (specialSet.empty())
+        {
+            specialSet.insert(SETTING_BLOOM_TEXTUREID);
+            specialSet.insert(SETTING_RAINBOW_TEXTUREID);
+            specialSet.insert(SETTING_HALO_TEXTUREID);
+            specialSet.insert(SETTING_CLOUD_TEXTUREID);
+            specialSet.insert(SETTING_MOON_TEXTUREID);
+            specialSet.insert(SETTING_SUN_TEXTUREID);
+        }
+        return specialSet;
+    }
+
+    template<>
+    LLSettingsBase::stringset_t LLSettingsInjected<LLSettingsVOWater>::getSpecialKeys() const
+    {
+        static stringset_t specialSet;
+
+        if (specialSet.empty())
+        {
+            specialSet.insert(SETTING_TRANSPARENT_TEXTURE);
+            specialSet.insert(SETTING_NORMAL_MAP);
+        }
+        return specialSet;
+    }
+
+    template<>
+    void LLSettingsInjected<LLSettingsVOSky>::resetSpecial()
+    {
+        mNextSunTextureId.setNull();
+        mNextMoonTextureId.setNull();
+        mNextCloudTextureId.setNull();
+        mNextBloomTextureId.setNull();
+        mNextRainbowTextureId.setNull();
+        mNextHaloTextureId.setNull();
+        setBlendFactor(0.0f);
+    }
+
+    template<>
+    void LLSettingsInjected<LLSettingsVOWater>::resetSpecial()
+    {
+        mNextNormalMapID.setNull();
+        mNextTransparentTextureID.setNull();
+        setBlendFactor(0.0f);
+    }
+
+    template<>
+    void LLSettingsInjected<LLSettingsVOSky>::updateSpecial(const typename LLSettingsInjected<LLSettingsVOSky>::Injection::ptr_t &injection, typename LLSettingsBase::BlendFactor mix)
+    {
+        if (injection->mKeyName == SETTING_SUN_TEXTUREID)
+        {
+            mNextSunTextureId = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_MOON_TEXTUREID)
+        {
+            mNextMoonTextureId = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_CLOUD_TEXTUREID)
+        {
+            mNextCloudTextureId = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_BLOOM_TEXTUREID)
+        {
+            mNextBloomTextureId = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_RAINBOW_TEXTUREID)
+        {
+            mNextRainbowTextureId = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_HALO_TEXTUREID)
+        {
+            mNextHaloTextureId = injection->mValue.asUUID();
+        }
+
+        // Unfortunately I don't have a per texture blend factor.  We'll just pick the one that is furthest along.
+        if (getBlendFactor() < mix)
+        {
+            setBlendFactor(mix);
+        }
+    }
+
+    template<>
+    void LLSettingsInjected<LLSettingsVOWater>::updateSpecial(const typename LLSettingsInjected<LLSettingsVOWater>::Injection::ptr_t &injection, typename LLSettingsBase::BlendFactor mix)
+    {
+        if (injection->mKeyName == SETTING_NORMAL_MAP)
+        {
+            mNextNormalMapID = injection->mValue.asUUID();
+        }
+        else if (injection->mKeyName == SETTING_TRANSPARENT_TEXTURE)
+        {
+            mNextTransparentTextureID = injection->mValue.asUUID();
+        }
+
+        // Unfortunately I don't have a per texture blend factor.  We'll just pick the one that is furthest along.
+        if (getBlendFactor() < mix)
+        {
+            setBlendFactor(mix);
+        }
+    }
+
+    typedef LLSettingsInjected<LLSettingsVOSky>   LLSettingsInjectedSky;
+    typedef LLSettingsInjected<LLSettingsVOWater> LLSettingsInjectedWater;
+
+    //=====================================================================
+    class DayInjection : public LLEnvironment::DayInstance
+    {
+        friend class InjectedTransition;
+
+    public:
+        typedef std::shared_ptr<DayInjection> ptr_t;
+        typedef std::weak_ptr<DayInjection> wptr_t;
+
+                                            DayInjection(LLEnvironment::EnvSelection_t env);
+        virtual                             ~DayInjection();
+
+        virtual bool                        applyTimeDelta(const LLSettingsBase::Seconds& delta) override;
+
+        void                                setInjectedDay(const LLSettingsDay::ptr_t &pday, LLUUID experience_id, LLSettingsBase::Seconds transition);
+        void                                setInjectedSky(const LLSettingsSky::ptr_t &psky, LLUUID experience_id, LLSettingsBase::Seconds transition);
+        void                                setInjectedWater(const LLSettingsWater::ptr_t &pwater, LLUUID experience_id, LLSettingsBase::Seconds transition);
+
+        void                                injectSkySettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition);
+        void                                injectWaterSettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition);
+
+        void                                clearInjections(LLUUID experience_id, LLSettingsBase::Seconds transition_time);
+
+        virtual void                        animate() override;
+
+        LLEnvironment::DayInstance::ptr_t   getBaseDayInstance() const  { return mBaseDayInstance; }
+        void                                setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday);
+
+        S32                                 countExperiencesActive() const { return mActiveExperiences.size(); }
+
+        bool                                isOverriddenSky() const { return !mSkyExperience.isNull(); }
+        bool                                isOverriddenWater() const { return !mWaterExperience.isNull(); }
+
+        bool                                hasInjections() const;
+
+        void                                testExperiencesOnParcel(S32 parcel_id);
+    private:
+        static void                         testExperiencesOnParcelCoro(wptr_t that, S32 parcel_id);
+
+
+        void                                animateSkyChange(LLSettingsSky::ptr_t psky, LLSettingsBase::Seconds transition);
+        void                                animateWaterChange(LLSettingsWater::ptr_t pwater, LLSettingsBase::Seconds transition);
+
+        void                                onEnvironmentChanged(LLEnvironment::EnvSelection_t env);
+        void                                onParcelChange();
+
+        void                                checkExperience();
+
+
+        LLEnvironment::DayInstance::ptr_t   mBaseDayInstance;
+
+        LLSettingsInjectedSky::ptr_t        mInjectedSky;
+        LLSettingsInjectedWater::ptr_t      mInjectedWater;
+        std::set<LLUUID>                    mActiveExperiences;
+        LLUUID                              mDayExperience;
+        LLUUID                              mSkyExperience;
+        LLUUID                              mWaterExperience;
+        LLEnvironment::connection_t         mEnvChangeConnection;
+        boost::signals2::connection         mParcelChangeConnection;
+    };
+
+    class InjectedTransition : public LLEnvironment::DayTransition
+    {
+    public:
+                                    InjectedTransition(const DayInjection::ptr_t &injection, const LLSettingsSky::ptr_t &skystart, const LLSettingsWater::ptr_t &waterstart, DayInstance::ptr_t &end, LLSettingsDay::Seconds time):
+                                        LLEnvironment::DayTransition(skystart, waterstart, end, time),
+                                        mInjection(injection)
+                                    { }
+        virtual                     ~InjectedTransition() { };
+
+        virtual void                animate() override;
+
+    protected:
+        DayInjection::ptr_t         mInjection;
+    };
+
+}
+
+//=========================================================================
+const F32Seconds LLEnvironment::TRANSITION_INSTANT(0.0f);
+const F32Seconds LLEnvironment::TRANSITION_FAST(1.0f);
+const F32Seconds LLEnvironment::TRANSITION_DEFAULT(5.0f);
+const F32Seconds LLEnvironment::TRANSITION_SLOW(10.0f);
+const F32Seconds LLEnvironment::TRANSITION_ALTITUDE(5.0f);
+
+const LLUUID LLEnvironment::KNOWN_SKY_SUNRISE("01e41537-ff51-2f1f-8ef7-17e4df760bfb");
+const LLUUID LLEnvironment::KNOWN_SKY_MIDDAY("6c83e853-e7f8-cad7-8ee6-5f31c453721c");
+const LLUUID LLEnvironment::KNOWN_SKY_SUNSET("084e26cd-a900-28e8-08d0-64a9de5c15e2");
+const LLUUID LLEnvironment::KNOWN_SKY_MIDNIGHT("8a01b97a-cb20-c1ea-ac63-f7ea84ad0090");
+
+const S32 LLEnvironment::NO_TRACK(-1);
+const S32 LLEnvironment::NO_VERSION(-3); // For viewer sided change, like ENV_LOCAL. -3 since -1 and -2 are taken by parcel initial server/viewer version
+const S32 LLEnvironment::VERSION_CLEANUP(-4); // for cleanups
+
+const F32 LLEnvironment::SUN_DELTA_YAW(F_PI);   // 180deg 
+
+
+const U32 LLEnvironment::DayInstance::NO_ANIMATE_SKY(0x01);
+const U32 LLEnvironment::DayInstance::NO_ANIMATE_WATER(0x02);
+
+
+//-------------------------------------------------------------------------
+LLEnvironment::LLEnvironment():
+    mCloudScrollDelta(),
+    mCloudScrollPaused(false),
+    mSelectedSky(),
+    mSelectedWater(),
+    mSelectedDay(),
+    mSelectedEnvironment(LLEnvironment::ENV_LOCAL),
+    mCurrentTrack(1),
+    mEditorCounter(0),
+    mShowSunBeacon(false),
+    mShowMoonBeacon(false)
+{
+}
+
+void LLEnvironment::initSingleton()
+{
+    LLSettingsSky::ptr_t p_default_sky = LLSettingsVOSky::buildDefaultSky();
+    LLSettingsWater::ptr_t p_default_water = LLSettingsVOWater::buildDefaultWater();
+
+    mCurrentEnvironment = std::make_shared<DayInstance>(ENV_DEFAULT);
+    mCurrentEnvironment->setSky(p_default_sky);
+    mCurrentEnvironment->setWater(p_default_water);
+
+    mEnvironments[ENV_DEFAULT] = mCurrentEnvironment;
+
+    requestRegion();
+
+    gAgent.addParcelChangedCallback([this]() { onParcelChange(); });
+
+    //TODO: This frequently results in one more request than we need.  It isn't breaking, but should be nicer.
+    // We need to know new env version to fix this, without it we can only do full re-request
+    // Happens: on updates, on opening LLFloaterRegionInfo, on region crossing if info floater is open
+    LLRegionInfoModel::instance().setUpdateCallback([this]() { requestRegion(); });
+    gAgent.addRegionChangedCallback([this]() { onRegionChange(); });
+
+    gAgent.whenPositionChanged([this](const LLVector3 &localpos, const LLVector3d &) { onAgentPositionHasChanged(localpos); });
+
+    if (!gGenericDispatcher.isHandlerPresent(MESSAGE_PUSHENVIRONMENT))
+    {
+        gGenericDispatcher.addHandler(MESSAGE_PUSHENVIRONMENT, &environment_push_dispatch_handler);
+    }
+
+    LLEventPumps::instance().obtain(PUMP_EXPERIENCE).listen(LISTENER_NAME, [this](LLSD message) { listenExperiencePump(message); return false; });
+}
+
+void LLEnvironment::cleanupSingleton()
+{
+    LLEventPumps::instance().obtain(PUMP_EXPERIENCE).stopListening(LISTENER_NAME);
+}
+
+LLEnvironment::~LLEnvironment()
+{
+}
+
+bool LLEnvironment::canEdit() const
+{
+    return true;
+}
+
+LLSettingsSky::ptr_t LLEnvironment::getCurrentSky() const 
+{ 
+    LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky(); 
+
+    if (!psky && mCurrentEnvironment->getEnvironmentSelection() >= ENV_EDIT)
+    {
+        for (int idx = 0; idx < ENV_END; ++idx)
+        {
+            if (mEnvironments[idx]->getSky())
+            {
+                psky = mEnvironments[idx]->getSky();
+                break;
+            }
+        }
+    }
+    return psky;
+}
+
+LLSettingsWater::ptr_t LLEnvironment::getCurrentWater() const 
+{
+    LLSettingsWater::ptr_t pwater = mCurrentEnvironment->getWater(); 
+
+    if (!pwater && mCurrentEnvironment->getEnvironmentSelection() >= ENV_EDIT)
+    {
+        for (int idx = 0; idx < ENV_END; ++idx)
+        {
+            if (mEnvironments[idx]->getWater())
+            {
+                pwater = mEnvironments[idx]->getWater();
+                break;
+            }
+        }
+    }
+    return pwater;
+}
+
+void LayerConfigToDensityLayer(const LLSD& layerConfig, DensityLayer& layerOut)
+{
+    layerOut.constant_term  = layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM].asReal();
+    layerOut.exp_scale      = layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR].asReal();
+    layerOut.exp_term       = layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();
+    layerOut.linear_term    = layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM].asReal();
+    layerOut.width          = layerConfig[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal();
+}
+
+void LLEnvironment::getAtmosphericModelSettings(AtmosphericModelSettings& settingsOut, const LLSettingsSky::ptr_t &psky)
+{
+    settingsOut.m_skyBottomRadius   = psky->getSkyBottomRadius();
+    settingsOut.m_skyTopRadius      = psky->getSkyTopRadius();
+    settingsOut.m_sunArcRadians     = psky->getSunArcRadians();
+    settingsOut.m_mieAnisotropy     = psky->getMieAnisotropy();
+
+    LLSD rayleigh = psky->getRayleighConfigs();
+    settingsOut.m_rayleighProfile.clear();
+    for (LLSD::array_iterator itf = rayleigh.beginArray(); itf != rayleigh.endArray(); ++itf)
+    {
+        DensityLayer layer;
+        LLSD& layerConfig = (*itf);
+        LayerConfigToDensityLayer(layerConfig, layer);
+        settingsOut.m_rayleighProfile.push_back(layer);
+    }
+
+    LLSD mie = psky->getMieConfigs();
+    settingsOut.m_mieProfile.clear();
+    for (LLSD::array_iterator itf = mie.beginArray(); itf != mie.endArray(); ++itf)
+    {
+        DensityLayer layer;
+        LLSD& layerConfig = (*itf);
+        LayerConfigToDensityLayer(layerConfig, layer);
+        settingsOut.m_mieProfile.push_back(layer);
+    }
+    settingsOut.m_mieAnisotropy = psky->getMieAnisotropy();
+
+    LLSD absorption = psky->getAbsorptionConfigs();
+    settingsOut.m_absorptionProfile.clear();
+    for (LLSD::array_iterator itf = absorption.beginArray(); itf != absorption.endArray(); ++itf)
+    {
+        DensityLayer layer;
+        LLSD& layerConfig = (*itf);
+        LayerConfigToDensityLayer(layerConfig, layer);
+        settingsOut.m_absorptionProfile.push_back(layer);
+    }
+}
+
+bool LLEnvironment::canAgentUpdateParcelEnvironment() const
+{
+    LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
+
+    return canAgentUpdateParcelEnvironment(parcel);
+}
+
+
+bool LLEnvironment::canAgentUpdateParcelEnvironment(LLParcel *parcel) const
+{
+    if (!parcel)
+        return false;
+
+    if (!LLEnvironment::instance().isExtendedEnvironmentEnabled())
+        return false;
+
+    if (gAgent.isGodlike())
+        return true;
+
+    if (!parcel->getRegionAllowEnvironmentOverride())
+        return false;
+
+    return LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_ALLOW_ENVIRONMENT);
+}
+
+bool LLEnvironment::canAgentUpdateRegionEnvironment() const
+{
+    if (gAgent.isGodlike())
+        return true;
+
+    return gAgent.getRegion()->canManageEstate();
+}
+
+bool LLEnvironment::isExtendedEnvironmentEnabled() const
+{
+    return !gAgent.getRegionCapability("ExtEnvironment").empty();
+}
+
+bool LLEnvironment::isInventoryEnabled() const
+{
+    return (!gAgent.getRegionCapability("UpdateSettingsAgentInventory").empty() &&
+        !gAgent.getRegionCapability("UpdateSettingsTaskInventory").empty());
+}
+
+void LLEnvironment::onRegionChange()
+{
+//     if (gAgent.getRegionCapability("ExperienceQuery").empty())
+//     {
+//     // for now environmental experiences do not survive region crossings
+    clearExperienceEnvironment(LLUUID::null, TRANSITION_DEFAULT);
+//     }
+
+    LLViewerRegion* cur_region = gAgent.getRegion();
+    if (!cur_region)
+    {
+        return;
+    }
+    if (!cur_region->capabilitiesReceived())
+    {
+        cur_region->setCapabilitiesReceivedCallback([](LLUUID region_id) {  LLEnvironment::instance().requestRegion(); });
+        return;
+    }
+    requestRegion();
+}
+
+void LLEnvironment::onParcelChange()
+{
+    S32 parcel_id(INVALID_PARCEL_ID);
+    LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel();
+
+    if (parcel)
+    {
+        parcel_id = parcel->getLocalID();
+    }
+
+    requestParcel(parcel_id);
+}
+
+//-------------------------------------------------------------------------
+F32 LLEnvironment::getCamHeight() const
+{
+    return (mCurrentEnvironment->getSky()->getDomeOffset() * mCurrentEnvironment->getSky()->getDomeRadius());
+}
+
+F32 LLEnvironment::getWaterHeight() const
+{
+    return gAgent.getRegion()->getWaterHeight();
+}
+
+bool LLEnvironment::getIsSunUp() const
+{
+    if (!mCurrentEnvironment || !mCurrentEnvironment->getSky())
+        return false;
+    return mCurrentEnvironment->getSky()->getIsSunUp();
+}
+
+bool LLEnvironment::getIsMoonUp() const
+{
+    if (!mCurrentEnvironment || !mCurrentEnvironment->getSky())
+        return false;
+    return mCurrentEnvironment->getSky()->getIsMoonUp();
+}
+
+//-------------------------------------------------------------------------
+void LLEnvironment::setSelectedEnvironment(LLEnvironment::EnvSelection_t env, LLSettingsBase::Seconds transition, bool forced)
+{
+    mSelectedEnvironment = env;
+    updateEnvironment(transition, forced);
+}
+
+bool LLEnvironment::hasEnvironment(LLEnvironment::EnvSelection_t env)
+{
+    if ((env < ENV_EDIT) || (env >= ENV_DEFAULT) || (!mEnvironments[env]))
+    {
+        return false;
+    }
+
+    return true;
+}
+
+LLEnvironment::DayInstance::ptr_t LLEnvironment::getEnvironmentInstance(LLEnvironment::EnvSelection_t env, bool create /*= false*/)
+{
+    DayInstance::ptr_t environment = mEnvironments[env];
+    if (create)
+    {
+        if (environment)
+            environment = environment->clone();
+        else
+        {
+            if (env == ENV_PUSH)
+                environment = std::make_shared<DayInjection>(env);
+            else
+                environment = std::make_shared<DayInstance>(env);
+        }
+        mEnvironments[env] = environment;
+    }
+
+    return environment;
+}
+
+
+void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version)
+{
+    if ((env < ENV_EDIT) || (env >= ENV_DEFAULT))
+    {   
+        LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL;
+        return;
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env, true);
+
+    environment->clear();
+    environment->setDay(pday, daylength, dayoffset);
+    environment->setSkyTrack(mCurrentTrack);
+    environment->animate();
+
+    if (!mSignalEnvChanged.empty())
+        mSignalEnvChanged(env, env_version);
+}
+
+
+void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, LLEnvironment::fixedEnvironment_t fixed, S32 env_version)
+{
+    if ((env < ENV_EDIT) || (env >= ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL;
+        return;
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env, true);
+
+
+    if (fixed.first)
+    {
+        environment->setSky(fixed.first);
+        environment->setFlags(DayInstance::NO_ANIMATE_SKY);
+    }
+    else if (!environment->getSky())
+    {
+        environment->setSky(mCurrentEnvironment->getSky());
+        environment->setFlags(DayInstance::NO_ANIMATE_SKY);
+    }
+        
+    if (fixed.second)
+    {
+        environment->setWater(fixed.second);
+        environment->setFlags(DayInstance::NO_ANIMATE_WATER);
+    }
+    else if (!environment->getWater())
+    {
+        environment->setWater(mCurrentEnvironment->getWater());
+        environment->setFlags(DayInstance::NO_ANIMATE_WATER);
+    }
+
+    if (!mSignalEnvChanged.empty())
+        mSignalEnvChanged(env, env_version);
+
+    /*TODO: readjust environment*/
+}
+
+void LLEnvironment::setEnvironment(LLEnvironment::EnvSelection_t env, const LLSettingsBase::ptr_t &settings, S32 env_version)
+{
+    DayInstance::ptr_t environment = getEnvironmentInstance(env);
+
+    if (env == ENV_DEFAULT)
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to set default environment. Not allowed." << LL_ENDL;
+        return;
+    }
+
+    if (!settings)
+    {
+        clearEnvironment(env);
+        return;
+    }
+
+    if (settings->getSettingsType() == "daycycle")
+    {
+        LLSettingsDay::Seconds daylength(LLSettingsDay::DEFAULT_DAYLENGTH);
+        LLSettingsDay::Seconds dayoffset(LLSettingsDay::DEFAULT_DAYOFFSET);
+        if (environment)
+        {
+            daylength = environment->getDayLength();
+            dayoffset = environment->getDayOffset();
+        }
+        setEnvironment(env, std::static_pointer_cast<LLSettingsDay>(settings), daylength, dayoffset);
+    }
+    else if (settings->getSettingsType() == "sky")
+    {
+        fixedEnvironment_t fixedenv(std::static_pointer_cast<LLSettingsSky>(settings), LLSettingsWater::ptr_t());
+        setEnvironment(env, fixedenv);
+    }
+    else if (settings->getSettingsType() == "water")
+    {
+        fixedEnvironment_t fixedenv(LLSettingsSky::ptr_t(), std::static_pointer_cast<LLSettingsWater>(settings));
+        setEnvironment(env, fixedenv);
+    }
+}
+
+void LLEnvironment::setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version)
+{
+    setEnvironment(env, assetId, LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET);
+}
+
+
+void LLEnvironment::setEnvironment(EnvSelection_t env,
+                                   const LLUUID &assetId,
+                                   LLSettingsDay::Seconds daylength,
+                                   LLSettingsDay::Seconds dayoffset,
+                                   S32 env_version)
+{
+    LLSettingsVOBase::getSettingsAsset(assetId,
+        [this, env, daylength, dayoffset, env_version](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+        {
+            onSetEnvAssetLoaded(env, asset_id, settings, daylength, dayoffset, TRANSITION_DEFAULT, status, env_version);
+        });
+}
+
+void LLEnvironment::onSetEnvAssetLoaded(EnvSelection_t env,
+                                        LLUUID asset_id,
+                                        LLSettingsBase::ptr_t settings,
+                                        LLSettingsDay::Seconds daylength,
+                                        LLSettingsDay::Seconds dayoffset,
+                                        LLSettingsBase::Seconds transition,
+                                        S32 status,
+                                        S32 env_version)
+{
+    if (!settings || status)
+    {
+        LLSD args;
+        args["DESC"] = asset_id.asString();
+        LLNotificationsUtil::add("FailedToFindSettings", args);
+        return;
+    }
+
+    setEnvironment(env, settings);
+    updateEnvironment(transition);
+}
+
+void LLEnvironment::clearEnvironment(LLEnvironment::EnvSelection_t env)
+{
+    if ((env < ENV_EDIT) || (env >= ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to change invalid environment selection." << LL_ENDL;
+        return;
+    }
+
+    mEnvironments[env].reset();
+
+    if (!mSignalEnvChanged.empty())
+        mSignalEnvChanged(env, VERSION_CLEANUP);
+
+    /*TODO: readjust environment*/
+}
+
+LLSettingsDay::ptr_t LLEnvironment::getEnvironmentDay(LLEnvironment::EnvSelection_t env)
+{
+    if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env);
+
+    if (environment)
+        return environment->getDayCycle();
+
+    return LLSettingsDay::ptr_t();
+}
+
+LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayLength(EnvSelection_t env)
+{
+    if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+        return LLSettingsDay::Seconds(0);
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env);
+
+    if (environment)
+        return environment->getDayLength();
+
+    return LLSettingsDay::Seconds(0);
+}
+
+LLSettingsDay::Seconds LLEnvironment::getEnvironmentDayOffset(EnvSelection_t env)
+{
+    if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+        return LLSettingsDay::Seconds(0);
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env);
+    if (environment)
+        return environment->getDayOffset();
+
+    return LLSettingsDay::Seconds(0);
+}
+
+
+LLEnvironment::fixedEnvironment_t LLEnvironment::getEnvironmentFixed(LLEnvironment::EnvSelection_t env, bool resolve)
+{
+    if ((env == ENV_CURRENT) || resolve)
+    {
+        fixedEnvironment_t fixed;
+        for (S32 idx = ((resolve) ? env : mSelectedEnvironment); idx < ENV_END; ++idx)
+        {
+            if (fixed.first && fixed.second)
+                break;
+
+            if (idx == ENV_EDIT)
+                continue;   // skip the edit environment.
+
+            DayInstance::ptr_t environment = getEnvironmentInstance(static_cast<EnvSelection_t>(idx));
+            if (environment)
+            {
+                if (!fixed.first)
+                    fixed.first = environment->getSky();
+                if (!fixed.second)
+                    fixed.second = environment->getWater();
+            }
+        }
+
+        if (!fixed.first || !fixed.second)
+            LL_WARNS("ENVIRONMENT") << "Can not construct complete fixed environment.  Missing Sky and/or Water." << LL_ENDL;
+
+        return fixed;
+    }
+
+    if ((env < ENV_EDIT) || (env > ENV_DEFAULT))
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to retrieve invalid environment selection." << LL_ENDL;
+        return fixedEnvironment_t();
+    }
+
+    DayInstance::ptr_t environment = getEnvironmentInstance(env);
+
+    if (environment)
+        return fixedEnvironment_t(environment->getSky(), environment->getWater());
+
+    return fixedEnvironment_t();
+}
+
+LLEnvironment::DayInstance::ptr_t LLEnvironment::getSelectedEnvironmentInstance()
+{
+    for (S32 idx = mSelectedEnvironment; idx < ENV_DEFAULT; ++idx)
+    {
+        if (mEnvironments[idx])
+            return mEnvironments[idx];
+    }
+
+    return mEnvironments[ENV_DEFAULT];
+}
+
+LLEnvironment::DayInstance::ptr_t LLEnvironment::getSharedEnvironmentInstance()
+{
+    for (S32 idx = ENV_PARCEL; idx < ENV_DEFAULT; ++idx)
+    {
+        if (mEnvironments[idx])
+            return mEnvironments[idx];
+    }
+
+    return mEnvironments[ENV_DEFAULT];
+}
+
+void LLEnvironment::updateEnvironment(LLSettingsBase::Seconds transition, bool forced)
+{
+    DayInstance::ptr_t pinstance = getSelectedEnvironmentInstance();
+
+    if ((mCurrentEnvironment != pinstance) || forced)
+    {
+        if (transition != TRANSITION_INSTANT)
+        {
+	        DayInstance::ptr_t trans = std::make_shared<DayTransition>(
+	            mCurrentEnvironment->getSky(), mCurrentEnvironment->getWater(), pinstance, transition);
+	
+	        trans->animate();
+	
+	        mCurrentEnvironment = trans;
+        }
+        else
+        {
+            mCurrentEnvironment = pinstance;
+        }
+    }
+}
+
+LLVector4 LLEnvironment::toCFR(const LLVector3 vec) const
+{
+    LLVector4 vec_cfr(vec.mV[1], vec.mV[0], vec.mV[2], 0.0f);
+    return vec_cfr;
+}
+
+LLVector4 LLEnvironment::toLightNorm(const LLVector3 vec) const
+{
+    LLVector4 vec_ogl(vec.mV[1], vec.mV[2], vec.mV[0], 0.0f);
+    return vec_ogl;
+}
+
+LLVector3 LLEnvironment::getLightDirection() const
+{
+    LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky();
+    if (!psky)
+    {
+        return LLVector3(0, 0, 1);
+    }
+    return psky->getLightDirection();
+}
+
+LLVector3 LLEnvironment::getSunDirection() const
+{
+    LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky();
+    if (!psky)
+    {
+        return LLVector3(0, 0, 1);
+    }
+    return psky->getSunDirection();
+}
+
+LLVector3 LLEnvironment::getMoonDirection() const
+{
+    LLSettingsSky::ptr_t psky = mCurrentEnvironment->getSky();
+    if (!psky)
+    {
+        return LLVector3(0, 0, -1);
+    }
+    return psky->getMoonDirection();
+}
+
+LLVector4 LLEnvironment::getLightDirectionCFR() const
+{
+    LLVector3 light_direction = getLightDirection();
+    LLVector4 light_direction_cfr = toCFR(light_direction);
+    return light_direction_cfr;
+}
+
+LLVector4 LLEnvironment::getSunDirectionCFR() const
+{
+    LLVector3 light_direction = getSunDirection();
+    LLVector4 light_direction_cfr = toCFR(light_direction);
+    return light_direction_cfr;
+}
+
+LLVector4 LLEnvironment::getMoonDirectionCFR() const
+{
+    LLVector3 light_direction = getMoonDirection();
+    LLVector4 light_direction_cfr = toCFR(light_direction);
+    return light_direction_cfr;
+}
+
+LLVector4 LLEnvironment::getClampedLightNorm() const
+{
+    LLVector3 light_direction = getLightDirection();
+    if (light_direction.mV[2] < -0.1f)
+    {
+        light_direction.mV[2] = -0.1f;
+    }
+    return toLightNorm(light_direction);
+}
+
+LLVector4 LLEnvironment::getClampedSunNorm() const
+{
+    LLVector3 light_direction = getSunDirection();
+    if (light_direction.mV[2] < -0.1f)
+    {
+        light_direction.mV[2] = -0.1f;
+    }
+    return toLightNorm(light_direction);
+}
+
+LLVector4 LLEnvironment::getClampedMoonNorm() const
+{
+    LLVector3 light_direction = getMoonDirection();
+    if (light_direction.mV[2] < -0.1f)
+    {
+        light_direction.mV[2] = -0.1f;
+    }
+    return toLightNorm(light_direction);
+}
+
+LLVector4 LLEnvironment::getRotatedLightNorm() const
+{
+    LLVector3 light_direction = getLightDirection();
+    light_direction *= LLQuaternion(-mLastCamYaw, LLVector3(0.f, 1.f, 0.f));
+    return toLightNorm(light_direction);
+}
+
+//-------------------------------------------------------------------------
+void LLEnvironment::update(const LLViewerCamera * cam)
+{
+    LL_RECORD_BLOCK_TIME(FTM_ENVIRONMENT_UPDATE);
+    //F32Seconds now(LLDate::now().secondsSinceEpoch());
+    static LLFrameTimer timer;
+
+    F32Seconds delta(timer.getElapsedTimeAndResetF32());
+
+    {
+        DayInstance::ptr_t keeper = mCurrentEnvironment;    
+        // make sure the current environment does not go away until applyTimeDelta is done.
+        mCurrentEnvironment->applyTimeDelta(delta);
+
+    }
+    // update clouds, sun, and general
+    updateCloudScroll();
+
+    // cache this for use in rotating the rotated light vec for shader param updates later...
+    mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW;
+
+    stop_glerror();
+
+    // *TODO: potential optimization - this block may only need to be
+    // executed some of the time.  For example for water shaders only.
+    {
+        LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
+        end_shaders = LLViewerShaderMgr::instance()->endShaders();
+        for (shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
+        {
+            if ((shaders_iter->mProgramObject != 0)
+                && (gPipeline.canUseWindLightShaders()
+                || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
+            {
+                shaders_iter->mUniformsDirty = TRUE;
+            }
+        }
+    }
+}
+
+void LLEnvironment::updateCloudScroll()
+{
+    // This is a function of the environment rather than the sky, since it should 
+    // persist through sky transitions.
+    static LLTimer s_cloud_timer;
+
+    F64 delta_t = s_cloud_timer.getElapsedTimeAndResetF64();
+    
+    if (mCurrentEnvironment->getSky() && !mCloudScrollPaused)
+    {
+        LLVector2 cloud_delta = static_cast<F32>(delta_t)* (mCurrentEnvironment->getSky()->getCloudScrollRate()) / 100.0;
+        mCloudScrollDelta += cloud_delta;
+    }
+
+}
+
+// static
+void LLEnvironment::updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting)
+{
+    LL_RECORD_BLOCK_TIME(FTM_SHADER_PARAM_UPDATE);
+
+    //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL;
+    LLSettingsBase::parammapping_t params = psetting->getParameterMap();
+    for (auto &it: params)
+    {
+        LLSD value;
+        // legacy first since it contains ambient color and we prioritize value from legacy, see getAmbientColor()
+        if (psetting->mSettings.has(LLSettingsSky::SETTING_LEGACY_HAZE) && psetting->mSettings[LLSettingsSky::SETTING_LEGACY_HAZE].has(it.first))
+        {
+            value = psetting->mSettings[LLSettingsSky::SETTING_LEGACY_HAZE][it.first];
+        }
+        else if (psetting->mSettings.has(it.first))
+        {
+            value = psetting->mSettings[it.first];
+        }
+        else
+        {
+            // We need to reset shaders, use defaults
+            value = it.second.getDefaultValue();
+        }
+
+        LLSD::Type setting_type = value.type();
+        stop_glerror();
+        switch (setting_type)
+        {
+        case LLSD::TypeInteger:
+            shader->uniform1i(it.second.getShaderKey(), value.asInteger());
+            //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << value << LL_ENDL;
+            break;
+        case LLSD::TypeReal:
+            shader->uniform1f(it.second.getShaderKey(), value.asReal());
+            //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << value << LL_ENDL;
+            break;
+
+        case LLSD::TypeBoolean:
+            shader->uniform1i(it.second.getShaderKey(), value.asBoolean() ? 1 : 0);
+            //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << value << LL_ENDL;
+            break;
+
+        case LLSD::TypeArray:
+        {
+            LLVector4 vect4(value);
+            //_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << vect4 << LL_ENDL;
+            shader->uniform4fv(it.second.getShaderKey(), 1, vect4.mV);
+            break;
+        }
+
+        //  case LLSD::TypeMap:
+        //  case LLSD::TypeString:
+        //  case LLSD::TypeUUID:
+        //  case LLSD::TypeURI:
+        //  case LLSD::TypeBinary:
+        //  case LLSD::TypeDate:
+        default:
+            break;
+        }
+        stop_glerror();
+    }
+    //_WARNS("RIDER") << "----------------------------------------------------------------" << LL_ENDL;
+
+    psetting->applySpecial(shader);
+}
+
+void LLEnvironment::updateShaderUniforms(LLGLSLShader *shader)
+{
+    updateGLVariablesForSettings(shader, mCurrentEnvironment->getWater());
+    updateGLVariablesForSettings(shader, mCurrentEnvironment->getSky());
+}
+
+void LLEnvironment::recordEnvironment(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envinfo, LLSettingsBase::Seconds transition)
+{
+    if (envinfo->mParcelId == INVALID_PARCEL_ID)
+    {
+        // the returned info applies to an entire region.
+        if (!envinfo->mDayCycle)
+        {
+            clearEnvironment(ENV_PARCEL);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion);
+            updateEnvironment();
+        }
+        else if (envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_WATER)
+                 || envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_GROUND_LEVEL))
+        {
+            LL_WARNS("ENVIRONMENT") << "Invalid day cycle for region" << LL_ENDL;
+            clearEnvironment(ENV_PARCEL);
+            setEnvironment(ENV_REGION, LLSettingsDay::GetDefaultAssetId(), LLSettingsDay::DEFAULT_DAYLENGTH, LLSettingsDay::DEFAULT_DAYOFFSET, envinfo->mEnvVersion);
+            updateEnvironment();
+        }
+        else
+        {
+            setEnvironment(ENV_REGION, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);
+            mTrackAltitudes = envinfo->mAltitudes;
+        }
+
+        LL_DEBUGS("ENVIRONMENT") << "Altitudes set to {" << mTrackAltitudes[0] << ", "<< mTrackAltitudes[1] << ", " << mTrackAltitudes[2] << ", " << mTrackAltitudes[3] << LL_ENDL;
+    }
+    else
+    {
+        LLParcel *parcel = LLViewerParcelMgr::instance().getAgentParcel();
+        LL_DEBUGS("ENVIRONMENT") << "Have parcel environment #" << envinfo->mParcelId << LL_ENDL;
+        if (parcel && (parcel->getLocalID() != parcel_id))
+        {
+            LL_DEBUGS("ENVIRONMENT") << "Requested parcel #" << parcel_id << " agent is on " << parcel->getLocalID() << LL_ENDL;
+            return;
+        }
+
+        if (!envinfo->mDayCycle)
+        {
+            LL_DEBUGS("ENVIRONMENT") << "Clearing environment on parcel #" << parcel_id << LL_ENDL;
+            clearEnvironment(ENV_PARCEL);
+        }
+        else if (envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_WATER)
+                 || envinfo->mDayCycle->isTrackEmpty(LLSettingsDay::TRACK_GROUND_LEVEL))
+        {
+            LL_WARNS("ENVIRONMENT") << "Invalid day cycle for parcel #" << parcel_id << LL_ENDL;
+            clearEnvironment(ENV_PARCEL);
+        }
+        else
+        {
+            setEnvironment(ENV_PARCEL, envinfo->mDayCycle, envinfo->mDayLength, envinfo->mDayOffset, envinfo->mEnvVersion);
+        }
+    }
+
+    updateEnvironment(transition);
+}
+
+void LLEnvironment::adjustRegionOffset(F32 adjust)
+{
+    if (isExtendedEnvironmentEnabled())
+    {
+        LL_WARNS("ENVIRONMENT") << "Attempt to adjust region offset on EEP region.  Legacy regions only." << LL_ENDL;
+    }
+
+    if (mEnvironments[ENV_REGION])
+    {
+        F32 day_length = mEnvironments[ENV_REGION]->getDayLength();
+        F32 day_offset = mEnvironments[ENV_REGION]->getDayOffset();
+
+        F32 day_adjustment = adjust * day_length;
+
+        day_offset += day_adjustment;
+        if (day_offset < 0.0f)
+            day_offset = day_length + day_offset;
+        mEnvironments[ENV_REGION]->setDayOffset(LLSettingsBase::Seconds(day_offset));
+    }
+}
+
+//=========================================================================
+void LLEnvironment::requestRegion(environment_apply_fn cb)
+{
+    requestParcel(INVALID_PARCEL_ID, cb);
+}
+
+void LLEnvironment::updateRegion(const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    updateParcel(INVALID_PARCEL_ID, pday, day_length, day_offset, altitudes, cb);
+}
+
+void LLEnvironment::updateRegion(const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    if (!isExtendedEnvironmentEnabled())
+    {
+        LL_WARNS("ENVIRONMENT") << "attempt to apply asset id to region not supporting it." << LL_ENDL;
+        LLNotificationsUtil::add("NoEnvironmentSettings");
+        return;
+    }
+
+    updateParcel(INVALID_PARCEL_ID, asset_id, display_name, track_num, day_length, day_offset, flags, altitudes, cb);
+}
+
+void LLEnvironment::updateRegion(const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    updateParcel(INVALID_PARCEL_ID, psky, day_length, day_offset, altitudes, cb);
+}
+
+void LLEnvironment::updateRegion(const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    updateParcel(INVALID_PARCEL_ID, pwater, day_length, day_offset, altitudes, cb);
+}
+
+
+void LLEnvironment::resetRegion(environment_apply_fn cb)
+{
+    resetParcel(INVALID_PARCEL_ID, cb);
+}
+
+void LLEnvironment::requestParcel(S32 parcel_id, environment_apply_fn cb)
+{
+    if (!isExtendedEnvironmentEnabled())
+    {   /*TODO: When EEP is live on the entire grid, this can go away. */
+        if (parcel_id == INVALID_PARCEL_ID)
+        {
+            if (!cb)
+            {
+                LLSettingsBase::Seconds transition = LLViewerParcelMgr::getInstance()->getTeleportInProgress() ? TRANSITION_FAST : TRANSITION_DEFAULT;
+                cb = [this, transition](S32 pid, EnvironmentInfo::ptr_t envinfo)
+                {
+                    clearEnvironment(ENV_PARCEL);
+                    recordEnvironment(pid, envinfo, transition);
+                };
+            }
+
+            LLEnvironmentRequest::initiate(cb);
+        }
+        else if (cb)
+            cb(parcel_id, EnvironmentInfo::ptr_t());
+        return;
+    }
+
+    if (!cb)
+    {
+        LLSettingsBase::Seconds transition = LLViewerParcelMgr::getInstance()->getTeleportInProgress() ? TRANSITION_FAST : TRANSITION_DEFAULT;
+        cb = [this, transition](S32 pid, EnvironmentInfo::ptr_t envinfo) { recordEnvironment(pid, envinfo, transition); };
+    }
+
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironment::coroRequestEnvironment",
+        [this, parcel_id, cb]() { coroRequestEnvironment(parcel_id, cb); });
+}
+
+void LLEnvironment::updateParcel(S32 parcel_id, const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(asset_id, display_name, day_length, day_offset, altitudes, flags));
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment",
+        [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); });
+}
+
+void LLEnvironment::onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 parcel_id, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes)
+{
+    if (status)
+    {
+        LL_WARNS("ENVIRONMENT") << "Unable to get settings asset with id " << asset_id << "!" << LL_ENDL;
+        LLNotificationsUtil::add("FailedToLoadSettingsApply");
+        return;
+    }
+
+    LLSettingsDay::ptr_t pday;
+
+    if (settings->getSettingsType() == "daycycle")
+        pday = std::static_pointer_cast<LLSettingsDay>(settings);
+    else
+    {
+        pday = createDayCycleFromEnvironment( (parcel_id == INVALID_PARCEL_ID) ? ENV_REGION : ENV_PARCEL, settings);
+    }
+
+    if (!pday)
+    {
+        LL_WARNS("ENVIRONMENT") << "Unable to construct day around " << asset_id << "!" << LL_ENDL;
+        LLNotificationsUtil::add("FailedToBuildSettingsDay");
+        return;
+    }
+
+    updateParcel(parcel_id, pday, day_length, day_offset, altitudes);
+}
+
+void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    LLSettingsDay::ptr_t pday = createDayCycleFromEnvironment((parcel_id == INVALID_PARCEL_ID) ? ENV_REGION : ENV_PARCEL, psky);
+    pday->setFlag(psky->getFlags());
+    updateParcel(parcel_id, pday, day_length, day_offset, altitudes, cb);
+}
+
+void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    LLSettingsDay::ptr_t pday = createDayCycleFromEnvironment((parcel_id == INVALID_PARCEL_ID) ? ENV_REGION : ENV_PARCEL, pwater);
+    pday->setFlag(pwater->getFlags());
+    updateParcel(parcel_id, pday, day_length, day_offset, altitudes, cb);
+}
+
+void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 track_num, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    UpdateInfo::ptr_t updates(std::make_shared<UpdateInfo>(pday, day_length, day_offset, altitudes));
+
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironment::coroUpdateEnvironment",
+        [this, parcel_id, track_num, updates, cb]() { coroUpdateEnvironment(parcel_id, track_num, updates, cb); });
+}
+
+void LLEnvironment::updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, LLEnvironment::altitudes_vect_t altitudes, environment_apply_fn cb)
+{
+    updateParcel(parcel_id, pday, NO_TRACK, day_length, day_offset, altitudes, cb);
+}
+
+
+
+void LLEnvironment::resetParcel(S32 parcel_id, environment_apply_fn cb)
+{
+    std::string coroname =
+        LLCoros::instance().launch("LLEnvironment::coroResetEnvironment",
+        [this, parcel_id, cb]() { coroResetEnvironment(parcel_id, NO_TRACK, cb); });
+}
+
+void LLEnvironment::coroRequestEnvironment(S32 parcel_id, LLEnvironment::environment_apply_fn apply)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("ResetEnvironment", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    std::string url = gAgent.getRegionCapability("ExtEnvironment");
+    if (url.empty())
+        return;
+
+    LL_DEBUGS("ENVIRONMENT") << "Requesting for parcel_id=" << parcel_id << LL_ENDL;
+
+    if (parcel_id != INVALID_PARCEL_ID)
+    {
+        std::stringstream query;
+
+        query << "?parcelid=" << parcel_id;
+        url += query.str();
+    }
+
+    LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+    // results that come back may contain the new settings
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+    if (!status)
+    {
+        LL_WARNS("ENVIRONMENT") << "Couldn't retrieve environment settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
+    }
+    else
+    {
+        LLSD environment = result[KEY_ENVIRONMENT];
+        if (environment.isDefined() && apply)
+        {
+            EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment);
+            apply(parcel_id, envinfo);
+        }
+    }
+
+}
+
+void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInfo::ptr_t updates, environment_apply_fn apply)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("ResetEnvironment", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    std::string url = gAgent.getRegionCapability("ExtEnvironment");
+    if (url.empty())
+        return;
+
+    LLSD body(LLSD::emptyMap());
+    body[KEY_ENVIRONMENT] = LLSD::emptyMap();
+
+    if (track_no == NO_TRACK)
+    {   // day length and offset are only applicable if we are addressing the entire day cycle.
+        if (updates->mDayLength > 0)
+            body[KEY_ENVIRONMENT][KEY_DAYLENGTH] = updates->mDayLength;
+        if (updates->mDayOffset > 0)
+            body[KEY_ENVIRONMENT][KEY_DAYOFFSET] = updates->mDayOffset;
+
+        if ((parcel_id == INVALID_PARCEL_ID) && (updates->mAltitudes.size() == 3))
+        {   // only test for altitude changes if we are changing the region.
+            body[KEY_ENVIRONMENT][KEY_TRACKALTS] = LLSD::emptyArray();
+            for (S32 i = 0; i < 3; ++i)
+            {
+                body[KEY_ENVIRONMENT][KEY_TRACKALTS][i] = updates->mAltitudes[i];
+            }
+        }
+    }
+
+    if (updates->mDayp)
+        body[KEY_ENVIRONMENT][KEY_DAYCYCLE] = updates->mDayp->getSettings();
+    else if (!updates->mSettingsAsset.isNull())
+    {
+        body[KEY_ENVIRONMENT][KEY_DAYASSET] = updates->mSettingsAsset;
+        if (!updates->mDayName.empty())
+            body[KEY_ENVIRONMENT][KEY_DAYNAME] = updates->mDayName;
+    }
+
+    body[KEY_ENVIRONMENT][KEY_FLAGS] = LLSD::Integer(updates->mFlags);
+    //_WARNS("ENVIRONMENT") << "Body = " << body << LL_ENDL;
+
+    if ((parcel_id != INVALID_PARCEL_ID) || (track_no != NO_TRACK))
+    {
+        std::stringstream query;
+        query << "?";
+
+        if (parcel_id != INVALID_PARCEL_ID)
+        {
+            query << "parcelid=" << parcel_id;
+
+            if (track_no != NO_TRACK)
+                query << "&";
+        }
+        if (track_no != NO_TRACK)
+        { 
+            query << "trackno=" << track_no;
+        }
+        url += query.str();
+    }
+
+    LLSD result = httpAdapter->putAndSuspend(httpRequest, url, body);
+    // results that come back may contain the new settings
+
+    LLSD notify;
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if ((!status) || !result["success"].asBoolean())
+    {
+        LL_WARNS("ENVIRONMENT") << "Couldn't update Windlight settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
+
+        notify = LLSD::emptyMap();
+        notify["FAIL_REASON"] = result["message"].asString();
+    }
+    else
+    {
+        LLSD environment = result[KEY_ENVIRONMENT];
+        if (environment.isDefined() && apply)
+        {
+            EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment);
+            apply(parcel_id, envinfo);
+        }
+    }
+
+    if (!notify.isUndefined())
+    {
+        LLNotificationsUtil::add("WLRegionApplyFail", notify);
+        //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
+    }
+}
+
+void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environment_apply_fn apply)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("ResetEnvironment", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+
+    std::string url = gAgent.getRegionCapability("ExtEnvironment");
+    if (url.empty())
+        return;
+
+    if ((parcel_id != INVALID_PARCEL_ID) || (track_no != NO_TRACK))
+    {
+        std::stringstream query;
+        query << "?";
+
+        if (parcel_id != INVALID_PARCEL_ID)
+        {
+            query << "parcelid=" << parcel_id;
+
+            if (track_no != NO_TRACK)
+                query << "&";
+        }
+        if (track_no != NO_TRACK)
+        {
+            query << "trackno=" << track_no;
+        }
+        url += query.str();
+    }
+
+    LLSD result = httpAdapter->deleteAndSuspend(httpRequest, url);
+    // results that come back may contain the new settings
+
+    LLSD notify; 
+
+    LLSD httpResults = result["http_result"];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if ((!status) || !result["success"].asBoolean())
+    {
+        LL_WARNS("ENVIRONMENT") << "Couldn't reset Windlight settings in " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
+
+        notify = LLSD::emptyMap();
+        notify["FAIL_REASON"] = result["message"].asString();
+    }
+    else
+    {
+       LLSD environment = result[KEY_ENVIRONMENT];
+        if (environment.isDefined() && apply)
+        {
+            EnvironmentInfo::ptr_t envinfo = LLEnvironment::EnvironmentInfo::extract(environment);
+            apply(parcel_id, envinfo);
+        }
+    }
+
+    if (!notify.isUndefined())
+    {
+        LLNotificationsUtil::add("WLRegionApplyFail", notify);
+        //LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
+    }
+
+}
+
+
+//=========================================================================
+
+LLEnvironment::EnvironmentInfo::EnvironmentInfo():
+    mParcelId(INVALID_PARCEL_ID),
+    mRegionId(),
+    mDayLength(0),
+    mDayOffset(0),
+    mDayHash(0),
+    mDayCycle(),
+    mAltitudes({ { 0.0, 0.0, 0.0, 0.0 } }),
+    mIsDefault(false),
+    mIsLegacy(false),
+    mDayCycleName(),
+    mNameList(),
+    mEnvVersion(INVALID_PARCEL_ENVIRONMENT_VERSION)
+{
+}
+
+LLEnvironment::EnvironmentInfo::ptr_t LLEnvironment::EnvironmentInfo::extract(LLSD environment)
+{
+    ptr_t pinfo = std::make_shared<EnvironmentInfo>();
+
+    pinfo->mIsDefault = environment.has(KEY_ISDEFAULT) ? environment[KEY_ISDEFAULT].asBoolean() : true;
+    pinfo->mParcelId = environment.has(KEY_PARCELID) ? environment[KEY_PARCELID].asInteger() : INVALID_PARCEL_ID;
+    pinfo->mRegionId = environment.has(KEY_REGIONID) ? environment[KEY_REGIONID].asUUID() : LLUUID::null;
+    pinfo->mIsLegacy = false;
+
+    if (environment.has(KEY_TRACKALTS))
+    {
+        for (int idx = 0; idx < 3; idx++)
+        {
+            pinfo->mAltitudes[idx+1] = environment[KEY_TRACKALTS][idx].asReal();
+        }
+        pinfo->mAltitudes[0] = 0;
+    }
+
+    if (environment.has(KEY_DAYCYCLE))
+    {
+        pinfo->mDayCycle = LLSettingsVODay::buildFromEnvironmentMessage(environment[KEY_DAYCYCLE]);
+        pinfo->mDayLength = LLSettingsDay::Seconds(environment.has(KEY_DAYLENGTH) ? environment[KEY_DAYLENGTH].asInteger() : -1);
+        pinfo->mDayOffset = LLSettingsDay::Seconds(environment.has(KEY_DAYOFFSET) ? environment[KEY_DAYOFFSET].asInteger() : -1);
+        pinfo->mDayHash = environment.has(KEY_DAYHASH) ? environment[KEY_DAYHASH].asInteger() : 0;
+    }
+    else
+    {
+        pinfo->mDayLength = LLEnvironment::instance().getEnvironmentDayLength(ENV_REGION);
+        pinfo->mDayOffset = LLEnvironment::instance().getEnvironmentDayOffset(ENV_REGION);
+    }
+
+    if (environment.has(KEY_DAYASSET))
+    {
+        pinfo->mAssetId = environment[KEY_DAYASSET].asUUID();
+    }
+
+    if (environment.has(KEY_DAYNAMES))
+    {
+        LLSD daynames = environment[KEY_DAYNAMES];
+        if (daynames.isArray())
+        {
+            pinfo->mDayCycleName.clear();
+            for (S32 index = 0; index < pinfo->mNameList.size(); ++index)
+            {
+                pinfo->mNameList[index] = daynames[index].asString();
+            }
+        }
+        else if (daynames.isString())
+        {
+            for (std::string &name: pinfo->mNameList)
+            {
+                name.clear();
+            }
+
+            pinfo->mDayCycleName = daynames.asString();
+        }
+    }
+    else if (pinfo->mDayCycle)
+    {
+        pinfo->mDayCycleName = pinfo->mDayCycle->getName();
+    }
+
+
+    if (environment.has(KEY_ENVVERSION))
+    {
+        LLSD version = environment[KEY_ENVVERSION];
+        pinfo->mEnvVersion = version.asInteger();
+    }
+    else
+    {
+        // can be used for region, but versions should be same
+        pinfo->mEnvVersion = pinfo->mIsDefault ? UNSET_PARCEL_ENVIRONMENT_VERSION : INVALID_PARCEL_ENVIRONMENT_VERSION;
+    }
+
+    return pinfo;
+}
+
+
+LLEnvironment::EnvironmentInfo::ptr_t LLEnvironment::EnvironmentInfo::extractLegacy(LLSD legacy)
+{
+    if (!legacy.isArray() || !legacy[0].has("regionID"))
+    {
+        LL_WARNS("ENVIRONMENT") << "Invalid legacy settings for environment: " << legacy << LL_ENDL;
+        return ptr_t();
+    }
+
+    ptr_t pinfo = std::make_shared<EnvironmentInfo>();
+
+    pinfo->mIsDefault = false;
+    pinfo->mParcelId = INVALID_PARCEL_ID;
+    pinfo->mRegionId = legacy[0]["regionID"].asUUID();
+    pinfo->mIsLegacy = true;
+
+    pinfo->mDayLength = LLSettingsDay::DEFAULT_DAYLENGTH;
+    pinfo->mDayOffset = LLSettingsDay::DEFAULT_DAYOFFSET;
+    pinfo->mDayCycle = LLSettingsVODay::buildFromLegacyMessage(pinfo->mRegionId, legacy[1], legacy[2], legacy[3]);
+    if (pinfo->mDayCycle)
+        pinfo->mDayHash = pinfo->mDayCycle->getHash();
+
+    pinfo->mAltitudes[0] = 0;
+    pinfo->mAltitudes[2] = 10001;
+    pinfo->mAltitudes[3] = 10002;
+    pinfo->mAltitudes[4] = 10003;
+
+    return pinfo;
+}
+
+//=========================================================================
+LLSettingsWater::ptr_t LLEnvironment::createWaterFromLegacyPreset(const std::string filename, LLSD &messages)
+{
+    std::string name(gDirUtilp->getBaseFileName(filename, true));
+    std::string path(gDirUtilp->getDirName(filename));
+
+    LLSettingsWater::ptr_t water = LLSettingsVOWater::buildFromLegacyPresetFile(name, path, messages);
+
+    if (!water)
+    {
+        messages["NAME"] = name;
+        messages["FILE"] = filename;
+    }
+    return water;
+}
+
+LLSettingsSky::ptr_t LLEnvironment::createSkyFromLegacyPreset(const std::string filename, LLSD &messages)
+{
+    std::string name(gDirUtilp->getBaseFileName(filename, true));
+    std::string path(gDirUtilp->getDirName(filename));
+
+    LLSettingsSky::ptr_t sky = LLSettingsVOSky::buildFromLegacyPresetFile(name, path, messages);
+    if (!sky)
+    {
+        messages["NAME"] = name;
+        messages["FILE"] = filename;
+    }
+    return sky;
+}
+
+LLSettingsDay::ptr_t LLEnvironment::createDayCycleFromLegacyPreset(const std::string filename, LLSD &messages)
+{
+    std::string name(gDirUtilp->getBaseFileName(filename, true));
+    std::string path(gDirUtilp->getDirName(filename));
+
+    LLSettingsDay::ptr_t day = LLSettingsVODay::buildFromLegacyPresetFile(name, path, messages);
+    if (!day)
+    {
+        messages["NAME"] = name;
+        messages["FILE"] = filename;
+    }
+    return day;
+}
+
+LLSettingsDay::ptr_t LLEnvironment::createDayCycleFromEnvironment(EnvSelection_t env, LLSettingsBase::ptr_t settings)
+{
+    std::string type(settings->getSettingsType());
+
+    if (type == "daycycle")
+        return std::static_pointer_cast<LLSettingsDay>(settings);
+
+    if ((env != ENV_PARCEL) && (env != ENV_REGION))
+    {
+        LL_WARNS("ENVIRONMENT") << "May only create from parcel or region environment." << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t day = this->getEnvironmentDay(env);
+    if (!day && (env == ENV_PARCEL))
+    {
+        day = this->getEnvironmentDay(ENV_REGION);
+    }
+
+    if (!day)
+    {
+        LL_WARNS("ENVIRONMENT") << "Could not retrieve existing day settings." << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    day = day->buildClone();
+
+    if (type == "sky")
+    {
+        for (S32 idx = 1; idx < LLSettingsDay::TRACK_MAX; ++idx)
+            day->clearCycleTrack(idx);
+        day->setSettingsAtKeyframe(settings, 0.0f, 1);
+    }
+    else if (type == "water")
+    {
+        day->clearCycleTrack(LLSettingsDay::TRACK_WATER);
+        day->setSettingsAtKeyframe(settings, 0.0f, LLSettingsDay::TRACK_WATER);
+    }
+
+    return day;
+}
+
+void LLEnvironment::onAgentPositionHasChanged(const LLVector3 &localpos)
+{
+    S32 trackno = calculateSkyTrackForAltitude(localpos.mV[VZ]);
+    if (trackno == mCurrentTrack)
+        return;
+
+    mCurrentTrack = trackno;
+    for (S32 env = ENV_LOCAL; env < ENV_DEFAULT; ++env)
+    {
+        if (mEnvironments[env])
+            mEnvironments[env]->setSkyTrack(mCurrentTrack);
+    }
+}
+
+S32 LLEnvironment::calculateSkyTrackForAltitude(F64 altitude)
+{
+    auto it = std::find_if_not(mTrackAltitudes.begin(), mTrackAltitudes.end(), [altitude](F32 test) { return altitude > test; });
+    
+    if (it == mTrackAltitudes.begin())
+        return 1;
+    else if (it == mTrackAltitudes.end())
+        return 4;
+
+    return std::min(static_cast<S32>(std::distance(mTrackAltitudes.begin(), it)), 4);
+}
+
+//-------------------------------------------------------------------------
+void LLEnvironment::handleEnvironmentPush(LLSD &message)
+{
+    // Log the experience message
+    LLExperienceLog::instance().handleExperienceMessage(message);
+
+    std::string action = message[KEY_ACTION].asString();
+    LLUUID experience_id = message[KEY_EXPERIENCEID].asUUID();
+    LLSD action_data = message[KEY_ACTIONDATA];
+    F32 transition_time = action_data[KEY_TRANSITIONTIME].asReal();
+
+    //TODO: Check here that the viewer thinks the experience is still valid.
+
+
+    if (action == ACTION_CLEARENVIRONMENT)
+    { 
+        handleEnvironmentPushClear(experience_id, action_data, transition_time);
+    }
+    else if (action == ACTION_PUSHFULLENVIRONMENT)
+    { 
+        handleEnvironmentPushFull(experience_id, action_data, transition_time);
+    }
+    else if (action == ACTION_PUSHPARTIALENVIRONMENT)
+    { 
+        handleEnvironmentPushPartial(experience_id, action_data, transition_time);
+    }
+    else
+    { 
+        LL_WARNS("ENVIRONMENT", "GENERICMESSAGES") << "Unknown environment push action '" << action << "'" << LL_ENDL;
+    }
+}
+
+void LLEnvironment::handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition)
+{
+    clearExperienceEnvironment(experience_id, LLSettingsBase::Seconds(transition));
+}
+
+void LLEnvironment::handleEnvironmentPushFull(LLUUID experience_id, LLSD &message, F32 transition)
+{
+    LLUUID asset_id(message[KEY_ASSETID].asUUID());
+
+    setExperienceEnvironment(experience_id, asset_id, LLSettingsBase::Seconds(transition));
+}
+
+void LLEnvironment::handleEnvironmentPushPartial(LLUUID experience_id, LLSD &message, F32 transition)
+{
+    LLSD settings(message["settings"]);
+
+    if (settings.isUndefined())
+        return;
+
+    setExperienceEnvironment(experience_id, settings, LLSettingsBase::Seconds(transition));
+}
+
+void LLEnvironment::clearExperienceEnvironment(LLUUID experience_id, LLSettingsBase::Seconds transition_time)
+{
+    DayInjection::ptr_t injection = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+    if (injection)
+    {
+        injection->clearInjections(experience_id, transition_time);
+    }
+
+}
+
+void LLEnvironment::setSharedEnvironment()
+{
+    clearEnvironment(LLEnvironment::ENV_LOCAL);
+    setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+    updateEnvironment();
+}
+
+void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLUUID asset_id, F32 transition_time)
+{
+    LLSettingsVOBase::getSettingsAsset(asset_id,
+        [this, experience_id, transition_time](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+    {
+        onSetExperienceEnvAssetLoaded(experience_id, settings, transition_time, status);
+    });
+
+
+}
+
+void LLEnvironment::onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettingsBase::ptr_t settings, F32 transition_time, S32 status)
+{
+    DayInjection::ptr_t environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+    bool updateenvironment(false);
+
+    if (!settings || status)
+    {
+        LLSD args;
+        args["DESC"] = experience_id.asString();
+        LLNotificationsUtil::add("FailedToFindSettings", args);
+        return;
+    }
+
+    if (!environment)
+    {
+        environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH, true));
+        updateenvironment = true;
+    }
+
+    if (settings->getSettingsType() == "daycycle")
+    {
+        environment->setInjectedDay(std::static_pointer_cast<LLSettingsDay>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+    }
+    else if (settings->getSettingsType() == "sky")
+    {
+        environment->setInjectedSky(std::static_pointer_cast<LLSettingsSky>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+    }
+    else if (settings->getSettingsType() == "water")
+    {
+        environment->setInjectedWater(std::static_pointer_cast<LLSettingsWater>(settings), experience_id, LLSettingsBase::Seconds(transition_time));
+    }
+
+    if (updateenvironment)
+        updateEnvironment(TRANSITION_INSTANT, true);
+}
+
+
+void LLEnvironment::setExperienceEnvironment(LLUUID experience_id, LLSD data, F32 transition_time)
+{
+    LLSD sky(data["sky"]);
+    LLSD water(data["water"]);
+
+    if (sky.isUndefined() && water.isUndefined())
+    {
+        clearExperienceEnvironment(experience_id, LLSettingsBase::Seconds(transition_time));
+        return;
+    }
+
+    DayInjection::ptr_t environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH));
+    bool updateenvironment(false);
+
+    if (!environment)
+    {
+        environment = std::dynamic_pointer_cast<DayInjection>(getEnvironmentInstance(ENV_PUSH, true));
+        updateenvironment = true;
+    }
+
+    if (!sky.isUndefined())
+    {
+        environment->injectSkySettings(sky, experience_id, LLSettingsBase::Seconds(transition_time));
+    }
+
+    if (!water.isUndefined())
+    {
+        environment->injectWaterSettings(sky, experience_id, LLSettingsBase::Seconds(transition_time));
+    }
+
+    if (updateenvironment)
+        updateEnvironment(TRANSITION_INSTANT, true);
+
+}
+
+void LLEnvironment::listenExperiencePump(const LLSD &message)
+{
+    LLUUID experience_id = message["experience"];
+    LLSD data = message[experience_id.asString()];
+    std::string permission(data["permission"].asString());
+
+    if ((permission == "Forget") || (permission == "Block"))
+    {
+        clearExperienceEnvironment(experience_id, (permission == "Block") ? TRANSITION_INSTANT : TRANSITION_FAST);
+    }
+}
+
+//=========================================================================
+LLEnvironment::DayInstance::DayInstance(EnvSelection_t env) :
+    mDayCycle(),
+    mSky(),
+    mWater(),
+    mDayLength(LLSettingsDay::DEFAULT_DAYLENGTH),
+    mDayOffset(LLSettingsDay::DEFAULT_DAYOFFSET),
+    mBlenderSky(),
+    mBlenderWater(),
+    mInitialized(false),
+    mSkyTrack(1),
+    mEnv(env),
+    mAnimateFlags(0)
+{ }
+
+
+LLEnvironment::DayInstance::ptr_t LLEnvironment::DayInstance::clone() const
+{
+    ptr_t environment = std::make_shared<DayInstance>(mEnv);
+
+    environment->mDayCycle = mDayCycle;
+    environment->mSky = mSky;
+    environment->mWater = mWater;
+    environment->mDayLength = mDayLength;
+    environment->mDayOffset = mDayOffset;
+    environment->mBlenderSky = mBlenderSky;
+    environment->mBlenderWater = mBlenderWater;
+    environment->mInitialized = mInitialized;
+    environment->mSkyTrack = mSkyTrack;
+    environment->mAnimateFlags = mAnimateFlags;
+
+    return environment;
+}
+
+bool LLEnvironment::DayInstance::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+{
+    ptr_t keeper(shared_from_this());   // makes sure that this does not go away while it is being worked on.
+
+    bool changed(false);
+    if (!mInitialized)
+        initialize();
+
+    if (mBlenderSky)
+        changed |= mBlenderSky->applyTimeDelta(delta);
+    if (mBlenderWater)
+        changed |= mBlenderWater->applyTimeDelta(delta);
+    return changed;
+}
+
+void LLEnvironment::DayInstance::setDay(const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset)
+{
+    mInitialized = false;
+
+    mAnimateFlags = 0;
+
+    mDayCycle = pday;
+    mDayLength = daylength;
+    mDayOffset = dayoffset;
+
+    mBlenderSky.reset();
+    mBlenderWater.reset();
+
+    mSky = LLSettingsVOSky::buildDefaultSky();
+    mWater = LLSettingsVOWater::buildDefaultWater();
+
+    animate();
+}
+
+
+void LLEnvironment::DayInstance::setSky(const LLSettingsSky::ptr_t &psky)
+{
+    mInitialized = false;
+
+    bool different_sky = mSky != psky;
+    
+    mSky = psky;
+    mSky->mReplaced |= different_sky;
+    mSky->update();
+    mBlenderSky.reset();
+
+    if (gAtmosphere)
+    {
+        AtmosphericModelSettings settings;
+        LLEnvironment::getAtmosphericModelSettings(settings, psky);
+        gAtmosphere->configureAtmosphericModel(settings);
+    }
+}
+
+void LLEnvironment::DayInstance::setWater(const LLSettingsWater::ptr_t &pwater)
+{
+    mInitialized = false;
+
+    bool different_water = mWater != pwater;
+    mWater = pwater;
+    mWater->mReplaced |= different_water;
+    mWater->update();
+    mBlenderWater.reset();
+}
+
+void LLEnvironment::DayInstance::initialize()
+{
+    mInitialized = true;
+
+    if (!mWater)
+        mWater = LLSettingsVOWater::buildDefaultWater();
+    if (!mSky)
+        mSky = LLSettingsVOSky::buildDefaultSky();
+}
+
+void LLEnvironment::DayInstance::clear()
+{
+    mDayCycle.reset();
+    mSky.reset();
+    mWater.reset();
+    mDayLength = LLSettingsDay::DEFAULT_DAYLENGTH;
+    mDayOffset = LLSettingsDay::DEFAULT_DAYOFFSET;
+    mBlenderSky.reset();
+    mBlenderWater.reset();
+    mSkyTrack = 1;
+}
+
+void LLEnvironment::DayInstance::setSkyTrack(S32 trackno)
+{
+    mSkyTrack = trackno;
+    if (mBlenderSky)
+    {
+        mBlenderSky->switchTrack(trackno, 0.0);
+    }
+}
+
+void LLEnvironment::DayInstance::setBlenders(const LLSettingsBlender::ptr_t &skyblend, const LLSettingsBlender::ptr_t &waterblend)
+{
+    mBlenderSky = skyblend;
+    mBlenderWater = waterblend;
+}
+
+LLSettingsBase::TrackPosition LLEnvironment::DayInstance::getProgress() const
+{
+    LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch());
+    now += mDayOffset;
+
+    if ((mDayLength <= 0) || !mDayCycle)
+        return -1.0f;   // no actual day cycle.
+
+    return convert_time_to_position(now, mDayLength);
+}
+
+LLSettingsBase::TrackPosition LLEnvironment::DayInstance::secondsToKeyframe(LLSettingsDay::Seconds seconds)
+{
+    return convert_time_to_position(seconds, mDayLength);
+}
+
+void LLEnvironment::DayInstance::animate()
+{
+    LLSettingsBase::Seconds now(LLDate::now().secondsSinceEpoch());
+
+    now += mDayOffset;
+
+    if (!mDayCycle)
+        return;
+
+    if (!(mAnimateFlags & NO_ANIMATE_WATER))
+    {
+        LLSettingsDay::CycleTrack_t &wtrack = mDayCycle->getCycleTrack(0);
+
+        if (wtrack.empty())
+        {
+            mWater.reset();
+            mBlenderWater.reset();
+        }
+        else
+        {
+            mWater = LLSettingsVOWater::buildDefaultWater();
+            mBlenderWater = std::make_shared<LLTrackBlenderLoopingTime>(mWater, mDayCycle, 0,
+                mDayLength, mDayOffset, DEFAULT_UPDATE_THRESHOLD);
+        }
+    }
+
+    if (!(mAnimateFlags & NO_ANIMATE_SKY))
+    {
+        // sky, initialize to track 1
+        LLSettingsDay::CycleTrack_t &track = mDayCycle->getCycleTrack(1);
+
+        if (track.empty())
+        {
+            mSky.reset();
+            mBlenderSky.reset();
+        }
+        else
+        {
+            mSky = LLSettingsVOSky::buildDefaultSky();
+            mBlenderSky = std::make_shared<LLTrackBlenderLoopingTime>(mSky, mDayCycle, 1,
+                mDayLength, mDayOffset, DEFAULT_UPDATE_THRESHOLD);
+            mBlenderSky->switchTrack(mSkyTrack, 0.0);
+        }
+    }
+}
+
+//-------------------------------------------------------------------------
+LLEnvironment::DayTransition::DayTransition(const LLSettingsSky::ptr_t &skystart,
+    const LLSettingsWater::ptr_t &waterstart, LLEnvironment::DayInstance::ptr_t &end, LLSettingsDay::Seconds time) :
+    DayInstance(ENV_NONE),
+    mStartSky(skystart),
+    mStartWater(waterstart),
+    mNextInstance(end),
+    mTransitionTime(time)
+{
+    
+}
+
+bool LLEnvironment::DayTransition::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+{
+    bool changed(false);
+
+    changed = mNextInstance->applyTimeDelta(delta);
+    changed |= DayInstance::applyTimeDelta(delta);
+    return changed;
+}
+
+void LLEnvironment::DayTransition::animate() 
+{
+    mNextInstance->animate();
+
+    mWater = mStartWater->buildClone();
+    mBlenderWater = std::make_shared<LLSettingsBlenderTimeDelta>(mWater, mStartWater, mNextInstance->getWater(), mTransitionTime);
+    mBlenderWater->setOnFinished(
+        [this](LLSettingsBlender::ptr_t blender) { 
+            mBlenderWater.reset();
+
+            if (!mBlenderSky && !mBlenderWater)
+                LLEnvironment::instance().mCurrentEnvironment = mNextInstance;
+            else
+                setWater(mNextInstance->getWater());
+    });
+
+    mSky = mStartSky->buildClone();
+    mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(mSky, mStartSky, mNextInstance->getSky(), mTransitionTime);
+    mBlenderSky->setOnFinished(
+        [this](LLSettingsBlender::ptr_t blender) {
+        mBlenderSky.reset();
+
+        if (!mBlenderSky && !mBlenderWater)
+            LLEnvironment::instance().mCurrentEnvironment = mNextInstance;
+        else
+            setSky(mNextInstance->getSky());
+    });
+}
+
+void LLEnvironment::saveToSettings()
+{
+    std::string user_dir = gDirUtilp->getLindenUserDir();
+    if (user_dir.empty())
+    {
+        // not logged in
+        return;
+    }
+    bool has_data = false;
+
+    if (gSavedSettings.getBOOL("EnvironmentPersistAcrossLogin"))
+    {
+        DayInstance::ptr_t environment = getEnvironmentInstance(ENV_LOCAL);
+        if (environment)
+        {
+            // Environment is 'layered'. No data in ENV_LOCAL means we are using parcel/region
+            // Store local environment for next session
+            LLSD env_data;
+
+            LLSettingsDay::ptr_t day = environment->getDayCycle();
+            if (day)
+            {
+                const std::string name = day->getName();
+                const LLUUID asset_id = day->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["day_id"] = asset_id;
+                    env_data["day_length"] = LLSD::Integer(environment->getDayLength());
+                    env_data["day_offset"] = LLSD::Integer(environment->getDayOffset());
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["day_llsd"] = day->getSettings();
+                    env_data["day_length"] = LLSD::Integer(environment->getDayLength());
+                    env_data["day_offset"] = LLSD::Integer(environment->getDayOffset());
+                    has_data = true;
+                }
+            }
+
+            LLSettingsSky::ptr_t sky = environment->getSky();
+            if ((environment->getFlags() & DayInstance::NO_ANIMATE_SKY) && sky)
+            {
+                const std::string name = sky->getName();
+                const LLUUID asset_id = sky->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["sky_id"] = asset_id;
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["sky_llsd"] = sky->getSettings();
+                    has_data = true;
+                }
+                has_data = true;
+            }
+
+            LLSettingsWater::ptr_t water = environment->getWater();
+            if ((environment->getFlags() & DayInstance::NO_ANIMATE_WATER) && water)
+            {
+                const std::string name = water->getName();
+                const LLUUID asset_id = water->getAssetId();
+                if (asset_id.notNull())
+                {
+                    // just save the id
+                    env_data["water_id"] = asset_id;
+                    has_data = true;
+                }
+                else if (!name.empty() && name != LLSettingsBase::DEFAULT_SETTINGS_NAME)
+                {
+                    // This setting was created locally and was not saved
+                    // The only option is to save the whole thing
+                    env_data["water_llsd"] = water->getSettings();
+                    has_data = true;
+                }
+            }
+
+            std::string user_filepath = user_dir + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE;
+            llofstream out(user_filepath.c_str(), std::ios_base::out | std::ios_base::binary);
+            if (out.good())
+            {
+                LLSDSerialize::toBinary(env_data, out);
+                out.close();
+            }
+            else
+            {
+                LL_WARNS("ENVIRONMENT") << "Unable to open " << user_filepath << " for output." << LL_ENDL;
+            }
+        }
+    }
+
+    if (!has_data)
+    {
+        LLFile::remove(user_dir + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE, ENOENT);
+    }
+}
+
+void LLEnvironment::loadSkyWaterFromSettings(const LLSD &env_data, bool &valid, bool &assets_present)
+{
+    if (env_data.has("sky_id"))
+    {
+        // causes asset loaded callback and an update
+        setEnvironment(ENV_LOCAL, env_data["sky_id"].asUUID());
+        valid = true;
+        assets_present = true;
+    }
+    else if (env_data.has("sky_llsd"))
+    {
+        LLSettingsSky::ptr_t sky = std::make_shared<LLSettingsVOSky>(env_data["sky_llsd"]);
+        setEnvironment(ENV_LOCAL, sky);
+        valid = true;
+    }
+
+    if (env_data.has("water_id"))
+    {
+        // causes asset loaded callback and an update
+        setEnvironment(ENV_LOCAL, env_data["water_id"].asUUID());
+        valid = true;
+        assets_present = true;
+    }
+    else if (env_data.has("water_llsd"))
+    {
+        LLSettingsWater::ptr_t sky = std::make_shared<LLSettingsVOWater>(env_data["water_llsd"]);
+        setEnvironment(ENV_LOCAL, sky);
+        valid = true;
+    }
+}
+
+bool LLEnvironment::loadFromSettings()
+{
+    if (!gSavedSettings.getBOOL("EnvironmentPersistAcrossLogin"))
+    {
+        return false;
+    }
+
+    std::string user_path = gDirUtilp->getLindenUserDir();
+    if (user_path.empty())
+    {
+        LL_WARNS("ENVIRONMENT") << "Can't load previous environment, Environment was initialized before user logged in" << LL_ENDL;
+        return false;
+    }
+    std::string user_filepath(user_path + gDirUtilp->getDirDelimiter() + LOCAL_ENV_STORAGE_FILE);
+    if (!gDirUtilp->fileExists(user_filepath))
+    {
+        // No previous environment
+        return false;
+    }
+
+    LLSD env_data;
+    llifstream file(user_filepath.c_str(), std::ios_base::in | std::ios_base::binary);
+    if (file.is_open())
+    {
+        LLSDSerialize::fromBinary(env_data, file, LLSDSerialize::SIZE_UNLIMITED);
+        if (env_data.isUndefined())
+        {
+            LL_WARNS("ENVIRONMENT") << "error loading " << user_filepath << LL_ENDL;
+            return false;
+        }
+        else
+        {
+            LL_INFOS("ENVIRONMENT") << "Loaded previous session environment from: " << user_filepath << LL_ENDL;
+        }
+        file.close();
+    }
+    else
+    {
+        LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL;
+    }
+
+    if (!env_data.isMap() || env_data.emptyMap())
+    {
+        LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL;
+        return false;
+    }
+
+    bool valid = false;
+    bool has_assets = false;
+
+    if (env_data.has("day_id"))
+    {
+        LLSettingsDay::Seconds length = LLSettingsDay::Seconds(env_data["day_length"].asInteger());
+        LLSettingsDay::Seconds offset = LLSettingsDay::Seconds(env_data["day_offset"].asInteger());
+        LLUUID assetId = env_data["day_id"].asUUID();
+
+        LLSettingsVOBase::getSettingsAsset(assetId,
+            [this, length, offset, env_data](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat)
+        {
+            // Day should be always applied first,
+            // otherwise it will override sky or water that was set earlier
+            // so wait for asset to load before applying sky/water
+            onSetEnvAssetLoaded(ENV_LOCAL, asset_id, settings, length, offset, TRANSITION_DEFAULT, status, NO_VERSION);
+            bool valid = false, has_assets = false;
+            loadSkyWaterFromSettings(env_data, valid, has_assets);
+            if (!has_assets && valid)
+            {
+                // Settings were loaded from file without having an asset, needs update
+                // otherwise update will be done by asset callback
+                updateEnvironment(TRANSITION_DEFAULT, true);
+            }
+        });
+        // bail early, everything have to be done at callback
+        return true;
+    }
+    else if (env_data.has("day_llsd"))
+    {
+        S32 length = env_data["day_length"].asInteger();
+        S32 offset = env_data["day_offset"].asInteger();
+        LLSettingsDay::ptr_t day = std::make_shared<LLSettingsVODay>(env_data["day_llsd"]);
+        setEnvironment(ENV_LOCAL, day, LLSettingsDay::Seconds(length), LLSettingsDay::Seconds(offset));
+        valid = true;
+    }
+
+    loadSkyWaterFromSettings(env_data, valid, has_assets);
+
+    if (valid && !has_assets)
+    {
+        // Settings were loaded from file without having an asset, needs update
+        // otherwise update will be done by asset callback
+        updateEnvironment(TRANSITION_DEFAULT, true);
+    }
+    return valid;
+}
+
+void LLEnvironment::saveBeaconsState()
+{
+    if (mEditorCounter == 0)
+    {
+        mShowSunBeacon = gSavedSettings.getBOOL("sunbeacon");
+        mShowMoonBeacon = gSavedSettings.getBOOL("moonbeacon");
+    }
+    ++mEditorCounter;
+}
+void LLEnvironment::revertBeaconsState()
+{
+    --mEditorCounter;
+    if (mEditorCounter == 0)
+    {
+        gSavedSettings.setBOOL("sunbeacon", mShowSunBeacon && gSavedSettings.getBOOL("sunbeacon"));
+        gSavedSettings.setBOOL("moonbeacon", mShowMoonBeacon && gSavedSettings.getBOOL("moonbeacon"));
+    }
+}
+
+//=========================================================================
+LLTrackBlenderLoopingManual::LLTrackBlenderLoopingManual(const LLSettingsBase::ptr_t &target, const LLSettingsDay::ptr_t &day, S32 trackno) :
+        LLSettingsBlender(target, LLSettingsBase::ptr_t(), LLSettingsBase::ptr_t()),
+        mDay(day),
+        mTrackNo(trackno),
+        mPosition(0.0)
+{
+    LLSettingsDay::TrackBound_t initial = getBoundingEntries(mPosition);
+
+    if (initial.first != mEndMarker)
+    {   // No frames in track
+        mInitial = (*initial.first).second;
+        mFinal = (*initial.second).second;
+
+        LLSD initSettings = mInitial->getSettings();
+        mTarget->replaceSettings(initSettings);
+    }
+}
+
+LLSettingsBase::BlendFactor LLTrackBlenderLoopingManual::setPosition(const LLSettingsBase::TrackPosition& position)
+{
+    mPosition = llclamp(position, 0.0f, 1.0f);
+
+    LLSettingsDay::TrackBound_t bounds = getBoundingEntries(mPosition);
+
+    if (bounds.first == mEndMarker)
+    {   // No frames in track.
+        return 0.0;
+    }
+
+    mInitial = (*bounds.first).second;
+    mFinal = (*bounds.second).second;
+
+    F64 spanLength = getSpanLength(bounds);
+
+    F64 spanPos = ((mPosition < (*bounds.first).first) ? (mPosition + 1.0) : mPosition) - (*bounds.first).first;
+
+    if (spanPos > spanLength)
+    {
+        // we are clamping position to 0-1 and spanLength is 1
+        // so don't account for case of spanPos == spanLength
+        spanPos = fmod(spanPos, spanLength);
+    }
+
+    F64 blendf = spanPos / spanLength;
+    return LLSettingsBlender::setBlendFactor(blendf);
+}
+
+void LLTrackBlenderLoopingManual::switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position)
+{
+    mTrackNo = trackno;
+
+    LLSettingsBase::TrackPosition useposition = (position < 0.0) ? mPosition : position;
+
+    setPosition(useposition);
+}
+
+LLSettingsDay::TrackBound_t LLTrackBlenderLoopingManual::getBoundingEntries(F64 position)
+{
+    LLSettingsDay::CycleTrack_t &wtrack = mDay->getCycleTrack(mTrackNo);
+
+    mEndMarker = wtrack.end();
+
+    LLSettingsDay::TrackBound_t bounds = get_bounding_entries(wtrack, position);
+    return bounds;
+}
+
+F64 LLTrackBlenderLoopingManual::getSpanLength(const LLSettingsDay::TrackBound_t &bounds) const
+{
+    return get_wrapping_distance((*bounds.first).first, (*bounds.second).first);
+}
+
+//=========================================================================
+namespace
+{
+    DayInjection::DayInjection(LLEnvironment::EnvSelection_t env):
+        LLEnvironment::DayInstance(env),
+        mBaseDayInstance(),
+        mInjectedSky(),
+        mInjectedWater(),
+        mActiveExperiences(),
+        mDayExperience(),
+        mSkyExperience(),
+        mWaterExperience(),
+        mEnvChangeConnection(),
+        mParcelChangeConnection()
+    {
+        mInjectedSky = std::make_shared<LLSettingsInjectedSky>(LLEnvironment::instance().getCurrentSky());
+        mInjectedWater = std::make_shared<LLSettingsInjectedWater>(LLEnvironment::instance().getCurrentWater());
+        mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+        mSky = mInjectedSky;
+        mWater = mInjectedWater;
+
+        mEnvChangeConnection = LLEnvironment::instance().setEnvironmentChanged([this](LLEnvironment::EnvSelection_t env, S32) { onEnvironmentChanged(env); });
+        mParcelChangeConnection = gAgent.addParcelChangedCallback([this]() { onParcelChange(); });
+    }
+
+    DayInjection::~DayInjection()
+    {
+        if (mEnvChangeConnection.connected())
+            mEnvChangeConnection.disconnect();
+        if (mParcelChangeConnection.connected())
+            mParcelChangeConnection.disconnect();
+    }
+
+
+    bool DayInjection::applyTimeDelta(const LLSettingsBase::Seconds& delta)
+    {
+        bool changed(false);
+
+        if (mBaseDayInstance)
+            changed |= mBaseDayInstance->applyTimeDelta(delta);
+        mInjectedSky->applyInjections(delta);
+        mInjectedWater->applyInjections(delta);
+        changed |= LLEnvironment::DayInstance::applyTimeDelta(delta);
+        if (changed)
+        {
+            mInjectedSky->setDirtyFlag(true);
+            mInjectedWater->setDirtyFlag(true);
+        }
+        mInjectedSky->update();
+        mInjectedWater->update();
+
+        if (!hasInjections())
+        {   // There are no injections being managed.  This should really go away.
+            LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+            LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+        }
+
+        return changed;
+    }
+
+    void DayInjection::setBaseDayInstance(const LLEnvironment::DayInstance::ptr_t &baseday) 
+    { 
+        mBaseDayInstance = baseday;
+
+        if (mSkyExperience.isNull())
+            mInjectedSky->setSource(mBaseDayInstance->getSky());
+        if (mWaterExperience.isNull())
+            mInjectedWater->setSource(mBaseDayInstance->getWater());
+    }
+
+
+    bool DayInjection::hasInjections() const
+    {
+        return (!mSkyExperience.isNull() || !mWaterExperience.isNull() || !mDayExperience.isNull() ||
+            mBlenderSky || mBlenderWater || mInjectedSky->hasInjections() || mInjectedWater->hasInjections());
+    }
+
+
+    void DayInjection::testExperiencesOnParcel(S32 parcel_id)
+    {
+        LLCoros::instance().launch("DayInjection::testExperiencesOnParcel",
+            [this, parcel_id]() { DayInjection::testExperiencesOnParcelCoro(std::static_pointer_cast<DayInjection>(this->shared_from_this()), parcel_id); });
+
+    }
+
+    void DayInjection::setInjectedDay(const LLSettingsDay::ptr_t &pday, LLUUID experience_id, LLSettingsBase::Seconds transition)
+    {
+        mSkyExperience = experience_id;
+        mWaterExperience = experience_id;
+        mDayExperience = experience_id;
+
+        mBaseDayInstance = mBaseDayInstance->clone();
+        mBaseDayInstance->setEnvironmentSelection(LLEnvironment::ENV_NONE);
+        mBaseDayInstance->setDay(pday, mBaseDayInstance->getDayLength(), mBaseDayInstance->getDayOffset());
+        animateSkyChange(mBaseDayInstance->getSky(), transition);
+        animateWaterChange(mBaseDayInstance->getWater(), transition);
+
+        mActiveExperiences.insert(experience_id);
+    }
+
+    void DayInjection::setInjectedSky(const LLSettingsSky::ptr_t &psky, LLUUID experience_id, LLSettingsBase::Seconds transition)
+    {
+        mSkyExperience = experience_id;
+        mActiveExperiences.insert(experience_id);
+        checkExperience();
+        animateSkyChange(psky, transition);
+    }
+
+    void DayInjection::setInjectedWater(const LLSettingsWater::ptr_t &pwater, LLUUID experience_id, LLSettingsBase::Seconds transition)
+    {
+        mWaterExperience = experience_id;
+        mActiveExperiences.insert(experience_id);
+        checkExperience();
+        animateWaterChange(pwater, transition);
+    }
+
+    void DayInjection::injectSkySettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition)
+    {
+        mInjectedSky->injectExperienceValues(settings, experience_id, transition);
+        mActiveExperiences.insert(experience_id);
+    }
+
+    void DayInjection::injectWaterSettings(LLSD settings, LLUUID experience_id, LLSettingsBase::Seconds transition)
+    {
+        mInjectedWater->injectExperienceValues(settings, experience_id, transition);
+        mActiveExperiences.insert(experience_id);
+    }
+
+    void DayInjection::clearInjections(LLUUID experience_id, LLSettingsBase::Seconds transition_time)
+    {
+        if ((experience_id.isNull() && !mDayExperience.isNull()) || (experience_id == mDayExperience))
+        {
+            mDayExperience.setNull();
+            if (mSkyExperience == experience_id)
+                mSkyExperience.setNull();
+            if (mWaterExperience == experience_id)
+                mWaterExperience.setNull();
+
+            mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+
+            if (mSkyExperience.isNull())
+                animateSkyChange(mBaseDayInstance->getSky(), transition_time);
+            if (mWaterExperience.isNull())
+                animateWaterChange(mBaseDayInstance->getWater(), transition_time);
+        }
+
+        if ((experience_id.isNull() && !mSkyExperience.isNull()) || (experience_id == mSkyExperience))
+        {
+            mSkyExperience.setNull();
+            animateSkyChange(mBaseDayInstance->getSky(), transition_time);
+        }
+        if ((experience_id.isNull() && !mWaterExperience.isNull()) || (experience_id == mWaterExperience))
+        {
+            mWaterExperience.setNull();
+            animateWaterChange(mBaseDayInstance->getWater(), transition_time);
+        }
+
+        mInjectedSky->removeInjections(experience_id, transition_time);
+        mInjectedWater->removeInjections(experience_id, transition_time);
+
+        if (experience_id.isNull())
+            mActiveExperiences.clear();
+        else
+            mActiveExperiences.erase(experience_id);
+
+        if ((transition_time == LLEnvironment::TRANSITION_INSTANT) && (countExperiencesActive() == 0))
+        {   // Only do this if instant and there are no other experiences injecting values.
+            // (otherwise will be handled after transition)
+            LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+            LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+        }
+    }
+
+
+    void DayInjection::testExperiencesOnParcelCoro(wptr_t that, S32 parcel_id)
+    {
+        LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+        LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+            httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("testExperiencesOnParcelCoro", httpPolicy));
+        LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+        std::string url = gAgent.getRegionCapability("ExperienceQuery");
+
+        if (url.empty())
+        {
+            LL_WARNS("ENVIRONMENT") << "No experience query cap." << LL_ENDL;
+            return; // no checking in this region.
+        }
+
+        {
+            ptr_t thatlock(that);
+            std::stringstream fullurl;
+
+            if (!thatlock)
+                return;
+
+            fullurl << url << "?";
+            fullurl << "parcelid=" << parcel_id;
+
+            for (auto it = thatlock->mActiveExperiences.begin(); it != thatlock->mActiveExperiences.end(); ++it)
+            {
+                if (it != thatlock->mActiveExperiences.begin())
+                    fullurl << ",";
+                else
+                    fullurl << "&experiences=";
+                fullurl << (*it).asString();
+            }
+            url = fullurl.str();
+        }
+
+        LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
+        LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+        LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+        if (!status)
+        {
+            LL_WARNS() << "Unable to retrieve experience status for parcel." << LL_ENDL;
+            return;
+        }
+
+        {
+            LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel();
+            if (!parcel)
+                return;
+
+            if (parcel_id != parcel->getLocalID())
+            {
+                // Agent no longer on queried parcel.
+                return;
+            }
+        }
+
+
+        LLSD experiences = result["experiences"];
+        {
+            ptr_t thatlock(that);
+            if (!thatlock)
+                return;
+
+            for (LLSD::map_iterator itr = experiences.beginMap(); itr != experiences.endMap(); ++itr)
+            {
+                if (!((*itr).second.asBoolean()))
+                    thatlock->clearInjections(LLUUID((*itr).first), LLEnvironment::TRANSITION_FAST);
+
+            }
+        }
+    }
+
+    void DayInjection::animateSkyChange(LLSettingsSky::ptr_t psky, LLSettingsBase::Seconds transition)
+    {
+        if (mInjectedSky.get() == psky.get())
+        {   // An attempt to animate to itself... don't do it.
+            return;
+        }
+        if (transition == LLEnvironment::TRANSITION_INSTANT)
+        {
+            mBlenderSky.reset();
+            mInjectedSky->setSource(psky);
+        }
+        else
+        {
+            LLSettingsSky::ptr_t start_sky(mInjectedSky->getSource()->buildClone());
+            LLSettingsSky::ptr_t target_sky(start_sky->buildClone());
+            mInjectedSky->setSource(target_sky);
+
+            mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(target_sky, start_sky, psky, transition);
+            mBlenderSky->setOnFinished(
+                [this, psky](LLSettingsBlender::ptr_t blender) 
+                {
+                    mBlenderSky.reset();
+                    mInjectedSky->setSource(psky);
+                    setSky(mInjectedSky);
+                    if (!mBlenderWater && (countExperiencesActive() == 0))
+                    {
+                        LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+                        LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+                    }
+                });
+        }
+    }
+
+    void DayInjection::animateWaterChange(LLSettingsWater::ptr_t pwater, LLSettingsBase::Seconds transition)
+    {
+        if (mInjectedWater.get() == pwater.get())
+        {   // An attempt to animate to itself. Bad idea.
+            return;
+        }
+        if (transition == LLEnvironment::TRANSITION_INSTANT)
+        { 
+            mBlenderWater.reset();
+            mInjectedWater->setSource(pwater);
+        }
+        else
+        {
+            LLSettingsWater::ptr_t start_Water(mInjectedWater->getSource()->buildClone());
+            LLSettingsWater::ptr_t scratch_Water(start_Water->buildClone());
+            mInjectedWater->setSource(scratch_Water);
+
+            mBlenderWater = std::make_shared<LLSettingsBlenderTimeDelta>(scratch_Water, start_Water, pwater, transition);
+            mBlenderWater->setOnFinished(
+                [this, pwater](LLSettingsBlender::ptr_t blender) 
+                {
+                    mBlenderWater.reset();
+                    mInjectedWater->setSource(pwater);
+                    setWater(mInjectedWater);
+                    if (!mBlenderSky && (countExperiencesActive() == 0))
+                    {
+                        LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_PUSH);
+                        LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+                    }
+                });
+        }
+    }
+
+    void DayInjection::onEnvironmentChanged(LLEnvironment::EnvSelection_t env)
+    {
+        if (env >= LLEnvironment::ENV_PARCEL)
+        {
+            LLEnvironment::EnvSelection_t base_env(mBaseDayInstance->getEnvironmentSelection());
+            LLEnvironment::DayInstance::ptr_t nextbase = LLEnvironment::instance().getSharedEnvironmentInstance();
+
+            if ((base_env == LLEnvironment::ENV_NONE) || (nextbase == mBaseDayInstance) || 
+                    (!mSkyExperience.isNull() && !mWaterExperience.isNull()))
+            {   // base instance completely overridden, or not changed no transition will happen
+                return;
+            }
+
+            LL_WARNS("PUSHENV") << "Underlying environment has changed (" << env << ")! Base env is type " << base_env << LL_ENDL;
+
+            LLEnvironment::DayInstance::ptr_t trans = std::make_shared<InjectedTransition>(std::static_pointer_cast<DayInjection>(shared_from_this()),
+                mBaseDayInstance->getSky(), mBaseDayInstance->getWater(), nextbase, LLEnvironment::TRANSITION_DEFAULT);
+
+            trans->animate();
+            setBaseDayInstance(trans);
+        }
+    }
+
+    void DayInjection::onParcelChange()
+    {
+        S32 parcel_id(INVALID_PARCEL_ID);
+        LLParcel* parcel = LLViewerParcelMgr::instance().getAgentParcel();
+
+        if (!parcel)
+            return;
+
+        parcel_id = parcel->getLocalID();
+
+        testExperiencesOnParcel(parcel_id);
+    }
+
+    void DayInjection::checkExperience()
+    {
+        if ((!mDayExperience.isNull()) && (mSkyExperience != mDayExperience) && (mWaterExperience != mDayExperience))
+        {   // There was a day experience but we've replaced it with a water and a sky experience. 
+            mDayExperience.setNull();
+            mBaseDayInstance = LLEnvironment::instance().getSharedEnvironmentInstance();
+        }
+    }
+
+    void DayInjection::animate()
+    {
+
+    }
+
+    void InjectedTransition::animate()
+    {
+        mNextInstance->animate();
+
+        if (!mInjection->isOverriddenSky())
+        {
+            mSky = mStartSky->buildClone();
+            mBlenderSky = std::make_shared<LLSettingsBlenderTimeDelta>(mSky, mStartSky, mNextInstance->getSky(), mTransitionTime);
+            mBlenderSky->setOnFinished(
+                [this](LLSettingsBlender::ptr_t blender) {
+                mBlenderSky.reset();
+
+                if (!mBlenderSky && !mBlenderSky)
+                    mInjection->setBaseDayInstance(mNextInstance);
+                else
+                    mInjection->mInjectedSky->setSource(mNextInstance->getSky());
+            });
+        }
+        else
+        {
+            mSky = mInjection->getSky();
+            mBlenderSky.reset();
+        }
+
+        if (!mInjection->isOverriddenWater())
+        {
+            mWater = mStartWater->buildClone();
+            mBlenderWater = std::make_shared<LLSettingsBlenderTimeDelta>(mWater, mStartWater, mNextInstance->getWater(), mTransitionTime);
+            mBlenderWater->setOnFinished(
+                [this](LLSettingsBlender::ptr_t blender) {
+                mBlenderWater.reset();
+
+                if (!mBlenderSky && !mBlenderWater)
+                    mInjection->setBaseDayInstance(mNextInstance);
+                else
+                    mInjection->mInjectedWater->setSource(mNextInstance->getWater());
+            });
+        }
+        else
+        {
+            mWater = mInjection->getWater();
+            mBlenderWater.reset();
+        }
+
+    }
+
+}
+
diff --git a/indra/newview/llenvironment.h b/indra/newview/llenvironment.h
new file mode 100644
index 0000000000000000000000000000000000000000..91c4b851352d9928c5a1d9e899f137e8307af967
--- /dev/null
+++ b/indra/newview/llenvironment.h
@@ -0,0 +1,474 @@
+/**
+ * @file llenvmanager.h
+ * @brief Declaration of classes managing WindLight and water settings.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifndef LL_ENVIRONMENT_H
+#define LL_ENVIRONMENT_H
+
+#include "llsingleton.h"
+#include "llmemory.h"
+#include "llsd.h"
+
+#include "llsettingsbase.h"
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+#include "llsettingsdaycycle.h"
+
+#include "llatmosphere.h"
+
+#include <boost/signals2.hpp>
+
+//-------------------------------------------------------------------------
+class LLViewerCamera;
+class LLGLSLShader;
+class LLParcel;
+
+//-------------------------------------------------------------------------
+class LLEnvironment : public LLSingleton<LLEnvironment>
+{
+    LLSINGLETON_C11(LLEnvironment);
+    LOG_CLASS(LLEnvironment);
+
+public:
+    static const F32Seconds     TRANSITION_INSTANT;
+    static const F32Seconds     TRANSITION_FAST;
+    static const F32Seconds     TRANSITION_DEFAULT;
+    static const F32Seconds     TRANSITION_SLOW;
+    static const F32Seconds     TRANSITION_ALTITUDE;
+
+    static const LLUUID         KNOWN_SKY_SUNRISE;
+    static const LLUUID         KNOWN_SKY_MIDDAY;
+    static const LLUUID         KNOWN_SKY_SUNSET;
+    static const LLUUID         KNOWN_SKY_MIDNIGHT;
+
+    static const S32            NO_TRACK;
+    static const S32            NO_VERSION;
+    static const S32            VERSION_CLEANUP;
+
+    struct EnvironmentInfo
+    {
+        EnvironmentInfo();
+
+        typedef std::shared_ptr<EnvironmentInfo>    ptr_t;
+        typedef std::array<std::string, 5>          namelist_t;
+
+        S32                     mParcelId;
+        LLUUID                  mRegionId;
+        S64Seconds              mDayLength;
+        S64Seconds              mDayOffset;
+        size_t                  mDayHash;
+        LLSettingsDay::ptr_t    mDayCycle;
+        std::array<F32, 4>      mAltitudes;
+        bool                    mIsDefault;
+        LLUUID                  mAssetId;
+        bool                    mIsLegacy;
+        std::string             mDayCycleName;
+        namelist_t              mNameList;
+        S32                     mEnvVersion;
+
+        static ptr_t            extract(LLSD);
+        static ptr_t            extractLegacy(LLSD);
+    };
+
+    enum EnvSelection_t
+    {
+        ENV_EDIT = 0,
+        ENV_LOCAL,
+        ENV_PUSH,
+        ENV_PARCEL,
+        ENV_REGION,
+        ENV_DEFAULT,
+        ENV_END,
+        ENV_CURRENT = -1,
+        ENV_NONE = -2
+    };
+
+    typedef boost::signals2::connection     connection_t;
+
+    typedef std::pair<LLSettingsSky::ptr_t, LLSettingsWater::ptr_t> fixedEnvironment_t;
+    typedef std::function<void(S32, EnvironmentInfo::ptr_t)>        environment_apply_fn;
+    typedef boost::signals2::signal<void(EnvSelection_t, S32)>      env_changed_signal_t;
+    typedef env_changed_signal_t::slot_type                         env_changed_fn;
+    typedef std::array<F32, 4>                                      altitude_list_t;
+    typedef std::vector<F32>                                        altitudes_vect_t;
+
+    virtual                     ~LLEnvironment();
+
+    bool                        canEdit() const;
+    bool                        isExtendedEnvironmentEnabled() const;
+    bool                        isInventoryEnabled() const;
+    bool                        canAgentUpdateParcelEnvironment() const;
+    bool                        canAgentUpdateParcelEnvironment(LLParcel *parcel) const;
+    bool                        canAgentUpdateRegionEnvironment() const;
+
+    LLSettingsDay::ptr_t        getCurrentDay() const { return mCurrentEnvironment->getDayCycle(); }
+    LLSettingsSky::ptr_t        getCurrentSky() const;
+    LLSettingsWater::ptr_t      getCurrentWater() const;
+
+    static void                 getAtmosphericModelSettings(AtmosphericModelSettings& settingsOut, const LLSettingsSky::ptr_t &psky);
+
+    void                        update(const LLViewerCamera * cam);
+
+    static void                 updateGLVariablesForSettings(LLGLSLShader *shader, const LLSettingsBase::ptr_t &psetting);
+    void                        updateShaderUniforms(LLGLSLShader *shader);
+
+    void                        setSelectedEnvironment(EnvSelection_t env, LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false);
+    EnvSelection_t              getSelectedEnvironment() const                  { return mSelectedEnvironment; }
+
+    bool                        hasEnvironment(EnvSelection_t env);
+    void                        setEnvironment(EnvSelection_t env, const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version = NO_VERSION);
+    void                        setEnvironment(EnvSelection_t env, fixedEnvironment_t fixed, S32 env_version = NO_VERSION);
+    void                        setEnvironment(EnvSelection_t env, const LLSettingsBase::ptr_t &fixed, S32 env_version = NO_VERSION);
+    void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixed, LLSettingsWater::ptr_t()), env_version); }
+    void                        setEnvironment(EnvSelection_t env, const LLSettingsWater::ptr_t & fixed, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(LLSettingsSky::ptr_t(), fixed), env_version); }
+    void                        setEnvironment(EnvSelection_t env, const LLSettingsSky::ptr_t & fixeds, const LLSettingsWater::ptr_t & fixedw, S32 env_version = NO_VERSION) { setEnvironment(env, fixedEnvironment_t(fixeds, fixedw), env_version); }
+    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, S32 env_version = NO_VERSION);
+    void                        setEnvironment(EnvSelection_t env, const LLUUID &assetId, S32 env_version = NO_VERSION);
+
+    void                        setSharedEnvironment();
+
+    void                        clearEnvironment(EnvSelection_t env);
+    LLSettingsDay::ptr_t        getEnvironmentDay(EnvSelection_t env);
+    LLSettingsDay::Seconds      getEnvironmentDayLength(EnvSelection_t env);
+    LLSettingsDay::Seconds      getEnvironmentDayOffset(EnvSelection_t env);
+    fixedEnvironment_t          getEnvironmentFixed(EnvSelection_t env, bool resolve = false);
+    LLSettingsSky::ptr_t        getEnvironmentFixedSky(EnvSelection_t env, bool resolve = false)      { return getEnvironmentFixed(env, resolve).first; };
+    LLSettingsWater::ptr_t      getEnvironmentFixedWater(EnvSelection_t env, bool resolve = false)    { return getEnvironmentFixed(env, resolve).second; };
+
+    void                        updateEnvironment(LLSettingsBase::Seconds transition = TRANSITION_DEFAULT, bool forced = false);
+
+    inline LLVector2            getCloudScrollDelta() const { return mCloudScrollDelta; }
+    void                        pauseCloudScroll()          { mCloudScrollPaused = true; }
+    void                        resumeCloudScroll()         { mCloudScrollPaused = false; }
+    bool                        isCloudScrollPaused() const { return mCloudScrollPaused; }
+
+    F32                         getCamHeight() const;
+    F32                         getWaterHeight() const;
+    bool                        getIsSunUp() const;
+    bool                        getIsMoonUp() const;
+
+    void                        saveToSettings();
+    bool                        loadFromSettings();
+    void                        saveBeaconsState();
+    void                        revertBeaconsState();
+
+    // Returns either sun or moon direction (depending on which is up and stronger)
+    // Light direction in +x right, +z up, +y at internal coord sys
+    LLVector3                   getLightDirection() const; // returns sun or moon depending on which is up
+    LLVector3                   getSunDirection() const;
+    LLVector3                   getMoonDirection() const;
+
+    // Returns light direction converted to CFR coord system
+    LLVector4                   getLightDirectionCFR() const; // returns sun or moon depending on which is up
+    LLVector4                   getSunDirectionCFR() const;
+    LLVector4                   getMoonDirectionCFR() const;
+
+    // Returns light direction converted to OGL coord system
+    // and clamped above -0.1f in Y to avoid render artifacts in sky shaders
+    LLVector4                   getClampedLightNorm() const; // returns sun or moon depending on which is up
+    LLVector4                   getClampedSunNorm() const;
+    LLVector4                   getClampedMoonNorm() const;
+
+    // Returns light direction converted to OGL coord system
+    // and rotated by last cam yaw needed by water rendering shaders
+    LLVector4                   getRotatedLightNorm() const;
+
+    static LLSettingsWater::ptr_t createWaterFromLegacyPreset(const std::string filename, LLSD &messages);
+    static LLSettingsSky::ptr_t createSkyFromLegacyPreset(const std::string filename, LLSD &messages);
+    static LLSettingsDay::ptr_t createDayCycleFromLegacyPreset(const std::string filename, LLSD &messages);
+
+    // Construct a new day cycle based on the environment.  Replacing either the water or the sky tracks.
+    LLSettingsDay::ptr_t        createDayCycleFromEnvironment(EnvSelection_t env, LLSettingsBase::ptr_t settings);
+
+    F32                         getProgress() const                         { return (mCurrentEnvironment) ? mCurrentEnvironment->getProgress() : -1.0f; }
+    F32                         getRegionProgress() const                   { return (mEnvironments[ENV_REGION]) ? mEnvironments[ENV_REGION]->getProgress() : -1.0f; }
+    void                        adjustRegionOffset(F32 adjust);     // only used on legacy regions, to better sync the viewer with other agents
+
+    //-------------------------------------------
+    connection_t                setEnvironmentChanged(env_changed_fn cb)    { return mSignalEnvChanged.connect(cb); }
+
+    void                        requestRegion(environment_apply_fn cb = environment_apply_fn());
+    void                        updateRegion(const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateRegion(const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateRegion(const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateRegion(const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        resetRegion(environment_apply_fn cb = environment_apply_fn());
+    void                        requestParcel(S32 parcel_id, environment_apply_fn cb = environment_apply_fn());
+    void                        updateParcel(S32 parcel_id, const LLUUID &asset_id, std::string display_name, S32 track_num, S32 day_length, S32 day_offset, U32 flags, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 track_num, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateParcel(S32 parcel_id, const LLSettingsDay::ptr_t &pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateParcel(S32 parcel_id, const LLSettingsSky::ptr_t &psky, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        updateParcel(S32 parcel_id, const LLSettingsWater::ptr_t &pwater, S32 day_length, S32 day_offset, altitudes_vect_t altitudes = altitudes_vect_t(), environment_apply_fn cb = environment_apply_fn());
+    void                        resetParcel(S32 parcel_id, environment_apply_fn cb = environment_apply_fn());
+
+    void                        selectAgentEnvironment();
+
+    S32                         calculateSkyTrackForAltitude(F64 altitude);
+
+    const altitude_list_t &     getRegionAltitudes() const { return mTrackAltitudes; }
+
+    void                        handleEnvironmentPush(LLSD &message);
+
+    class DayInstance: public std::enable_shared_from_this<DayInstance>
+    {
+    public:
+        typedef std::shared_ptr<DayInstance> ptr_t;
+
+        static const U32                NO_ANIMATE_SKY;
+        static const U32                NO_ANIMATE_WATER;
+
+                                        DayInstance(EnvSelection_t env);
+        virtual                         ~DayInstance() { };
+
+        virtual ptr_t                   clone() const;
+
+        virtual bool                    applyTimeDelta(const LLSettingsBase::Seconds& delta);
+
+        virtual void                    setDay(const LLSettingsDay::ptr_t &pday, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset);
+        virtual void                    setSky(const LLSettingsSky::ptr_t &psky);
+        virtual void                    setWater(const LLSettingsWater::ptr_t &pwater);
+
+        void                            initialize();
+        bool                            isInitialized();
+
+        void                            clear();
+
+        void                            setSkyTrack(S32 trackno);
+
+        LLSettingsDay::ptr_t            getDayCycle() const     { return mDayCycle; }
+        LLSettingsSky::ptr_t            getSky() const          { return mSky; }
+        LLSettingsWater::ptr_t          getWater() const        { return mWater; }
+        LLSettingsDay::Seconds          getDayLength() const    { return mDayLength; }
+        LLSettingsDay::Seconds          getDayOffset() const    { return mDayOffset; }
+        S32                             getSkyTrack() const     { return mSkyTrack; }
+
+        void                            setDayOffset(LLSettingsBase::Seconds offset) { mDayOffset = offset; animate(); }
+
+        virtual void                    animate();
+
+        void                            setBlenders(const LLSettingsBlender::ptr_t &skyblend, const LLSettingsBlender::ptr_t &waterblend);
+
+        EnvSelection_t                  getEnvironmentSelection() const { return mEnv; }
+        void                            setEnvironmentSelection(EnvSelection_t env) { mEnv = env; }
+
+        LLSettingsBase::TrackPosition   getProgress() const;
+
+        void                            setFlags(U32 flag) { mAnimateFlags |= flag; }
+        void                            clearFlags(U32 flag) { mAnimateFlags &= ~flag; }
+        U32                             getFlags() { return mAnimateFlags; }
+
+    protected:
+
+
+        LLSettingsDay::ptr_t        mDayCycle;
+        LLSettingsSky::ptr_t        mSky;
+        LLSettingsWater::ptr_t      mWater;
+        S32                         mSkyTrack;
+
+        bool                        mInitialized;
+
+        LLSettingsDay::Seconds      mDayLength;
+        LLSettingsDay::Seconds      mDayOffset;
+        S32                         mLastTrackAltitude;
+
+        LLSettingsBlender::ptr_t    mBlenderSky;
+        LLSettingsBlender::ptr_t    mBlenderWater;
+
+        EnvSelection_t              mEnv;
+
+        U32                         mAnimateFlags;
+
+        LLSettingsBase::TrackPosition secondsToKeyframe(LLSettingsDay::Seconds seconds);
+    };
+
+    class DayTransition : public DayInstance
+    {
+    public:
+                                    DayTransition(const LLSettingsSky::ptr_t &skystart, const LLSettingsWater::ptr_t &waterstart, DayInstance::ptr_t &end, LLSettingsDay::Seconds time);
+        virtual                     ~DayTransition() { };
+
+        virtual bool                applyTimeDelta(const LLSettingsBase::Seconds& delta) override;
+        virtual void                animate() override;
+
+    protected:
+        LLSettingsSky::ptr_t        mStartSky;
+        LLSettingsWater::ptr_t      mStartWater;
+        DayInstance::ptr_t          mNextInstance;
+        LLSettingsDay::Seconds      mTransitionTime;
+    };
+
+    DayInstance::ptr_t          getSelectedEnvironmentInstance();
+    DayInstance::ptr_t          getSharedEnvironmentInstance();
+
+protected:
+    virtual void                initSingleton() override;
+    virtual void                cleanupSingleton() override;
+
+
+private:
+    LLVector4 toCFR(const LLVector3 vec) const;
+    LLVector4 toLightNorm(const LLVector3 vec) const;
+
+    typedef std::array<DayInstance::ptr_t, ENV_END> InstanceArray_t;
+
+    struct ExpEnvironmentEntry
+    {
+        typedef std::shared_ptr<ExpEnvironmentEntry> ptr_t;
+
+        S32Seconds  mTime;
+        LLUUID      mExperienceId;
+        LLSD        mEnvironmentOverrides;
+    };
+    typedef std::deque<ExpEnvironmentEntry::ptr_t>  mPushOverrides;
+
+    LLUUID                      mPushEnvironmentExpId;
+
+    static const F32            SUN_DELTA_YAW;
+    F32                         mLastCamYaw = 0.0f;
+
+    LLVector2                   mCloudScrollDelta;  // cumulative cloud delta
+    bool                        mCloudScrollPaused;
+
+    InstanceArray_t             mEnvironments;
+
+    EnvSelection_t              mSelectedEnvironment;
+    DayInstance::ptr_t          mCurrentEnvironment;
+
+    LLSettingsSky::ptr_t        mSelectedSky;
+    LLSettingsWater::ptr_t      mSelectedWater;
+    LLSettingsDay::ptr_t        mSelectedDay;
+
+    LLSettingsBlender::ptr_t    mBlenderSky;
+    LLSettingsBlender::ptr_t    mBlenderWater;
+
+    env_changed_signal_t        mSignalEnvChanged;
+
+    S32                         mCurrentTrack;
+    altitude_list_t             mTrackAltitudes;
+
+    LLSD                        mSkyOverrides;
+    LLSD                        mWaterOverrides;
+    typedef std::map<std::string, LLUUID> experience_overrides_t;
+    experience_overrides_t      mExperienceOverrides;
+
+    DayInstance::ptr_t          getEnvironmentInstance(EnvSelection_t env, bool create = false);
+
+    void                        updateCloudScroll();
+
+    void                        onRegionChange();
+    void                        onParcelChange();
+
+    bool                        mShowSunBeacon;
+    bool                        mShowMoonBeacon;
+    S32                         mEditorCounter;
+
+    struct UpdateInfo
+    {
+        typedef std::shared_ptr<UpdateInfo> ptr_t;
+
+        UpdateInfo(LLSettingsDay::ptr_t pday, S32 day_length, S32 day_offset, altitudes_vect_t altitudes):
+            mDayp(pday),
+            mSettingsAsset(),
+            mDayLength(day_length),
+            mDayOffset(day_offset),
+            mAltitudes(altitudes),
+            mDayName(),
+            mFlags(0)
+        {
+            if (mDayp)
+            {
+                mDayName = mDayp->getName();
+                mFlags = mDayp->getFlags();
+            }
+        }
+
+        UpdateInfo(LLUUID settings_asset, std::string name, S32 day_length, S32 day_offset, altitudes_vect_t altitudes, U32 flags) :
+            mDayp(),
+            mSettingsAsset(settings_asset),
+            mDayLength(day_length),
+            mDayOffset(day_offset),
+            mAltitudes(altitudes),
+            mDayName(name),
+            mFlags(flags)
+        {}
+
+        LLSettingsDay::ptr_t    mDayp; 
+        LLUUID                  mSettingsAsset; 
+        S32                     mDayLength; 
+        S32                     mDayOffset; 
+        altitudes_vect_t        mAltitudes;
+        std::string             mDayName;
+        U32                     mFlags;
+    };
+
+    void                        coroRequestEnvironment(S32 parcel_id, environment_apply_fn apply);
+    void                        coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInfo::ptr_t updates, environment_apply_fn apply);
+    void                        coroResetEnvironment(S32 parcel_id, S32 track_no, environment_apply_fn apply);
+
+    void                        recordEnvironment(S32 parcel_id, EnvironmentInfo::ptr_t environment, LLSettingsBase::Seconds transition);
+
+    void                        onAgentPositionHasChanged(const LLVector3 &localpos);
+
+    void                        onSetEnvAssetLoaded(EnvSelection_t env, LLUUID asset_id, LLSettingsBase::ptr_t settings, LLSettingsDay::Seconds daylength, LLSettingsDay::Seconds dayoffset, LLSettingsBase::Seconds transition, S32 status, S32 env_version);
+    void                        onUpdateParcelAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 parcel_id, S32 day_length, S32 day_offset, altitudes_vect_t altitudes);
+
+    void                        handleEnvironmentPushClear(LLUUID experience_id, LLSD &message, F32 transition);
+    void                        handleEnvironmentPushFull(LLUUID experience_id, LLSD &message, F32 transition);
+    void                        handleEnvironmentPushPartial(LLUUID experience_id, LLSD &message, F32 transition);
+
+    void clearExperienceEnvironment(LLUUID experience_id, LLSettingsBase::Seconds transition_time);
+    void                        setExperienceEnvironment(LLUUID experience_id, LLUUID asset_id, F32 transition_time);
+    void                        setExperienceEnvironment(LLUUID experience_id, LLSD environment, F32 transition_time);
+    void                        onSetExperienceEnvAssetLoaded(LLUUID experience_id, LLSettingsBase::ptr_t setting, F32 transition_time, S32 status);
+
+    void                        listenExperiencePump(const LLSD &message);
+    void                        loadSkyWaterFromSettings(const LLSD &env_data, bool &valid, bool &assets_present); // for use in loadFromSettings()
+
+};
+
+class LLTrackBlenderLoopingManual : public LLSettingsBlender
+{
+public:
+    LLTrackBlenderLoopingManual(const LLSettingsBase::ptr_t &target, const LLSettingsDay::ptr_t &day, S32 trackno);
+
+    F64                         setPosition(const LLSettingsBase::TrackPosition& position);
+    virtual void                switchTrack(S32 trackno, const LLSettingsBase::TrackPosition& position) override;
+    S32                         getTrack() const { return mTrackNo; }
+
+    typedef std::shared_ptr<LLTrackBlenderLoopingManual> ptr_t;
+protected:
+    LLSettingsDay::TrackBound_t getBoundingEntries(F64 position);
+    F64                         getSpanLength(const LLSettingsDay::TrackBound_t &bounds) const;
+
+private:
+    LLSettingsDay::ptr_t        mDay;
+    S32                         mTrackNo;
+    F64                         mPosition;
+
+    LLSettingsDay::CycleTrack_t::iterator mEndMarker;
+};
+
+#endif // LL_ENVIRONMENT_H
+
diff --git a/indra/newview/llenvmanager.cpp b/indra/newview/llenvmanager.cpp
deleted file mode 100644
index fa1c3b983ec2222f75a5025b0d63e16c4d151842..0000000000000000000000000000000000000000
--- a/indra/newview/llenvmanager.cpp
+++ /dev/null
@@ -1,721 +0,0 @@
-/**
- * @file llenvmanager.cpp
- * @brief Implementation of classes managing WindLight and water settings.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llenvmanager.h"
-
-#include "llagent.h"
-#include "lldaycyclemanager.h"
-#include "llviewercontrol.h" // for gSavedSettings
-#include "llviewerregion.h"
-#include "llwaterparammanager.h"
-#include "llwlhandlers.h"
-#include "llwlparammanager.h"
-#include "lltrans.h"
-
-std::string LLWLParamKey::toString() const
-{
-	switch (scope)
-	{
-	case SCOPE_LOCAL:
-		return name + std::string(" (") + LLTrans::getString("Local") + std::string(")");
-		break;
-	case SCOPE_REGION:
-		return name + std::string(" (") + LLTrans::getString("Region") + std::string(")");
-		break;
-	default:
-		return name + " (?)";
-	}
-}
-
-std::string LLEnvPrefs::getWaterPresetName() const
-{
-	if (mWaterPresetName.empty())
-	{
-		LL_WARNS() << "Water preset name is empty" << LL_ENDL;
-	}
-
-	return mWaterPresetName;
-}
-
-std::string LLEnvPrefs::getSkyPresetName() const
-{
-	if (mSkyPresetName.empty())
-	{
-		LL_WARNS() << "Sky preset name is empty" << LL_ENDL;
-	}
-
-	return mSkyPresetName;
-}
-
-std::string LLEnvPrefs::getDayCycleName() const
-{
-	if (mDayCycleName.empty())
-	{
-		LL_WARNS() << "Day cycle name is empty" << LL_ENDL;
-	}
-
-	return mDayCycleName;
-}
-
-void LLEnvPrefs::setUseRegionSettings(bool val)
-{
-	mUseRegionSettings = val;
-}
-
-void LLEnvPrefs::setUseWaterPreset(const std::string& name)
-{
-	mUseRegionSettings = false;
-	mWaterPresetName = name;
-}
-
-void LLEnvPrefs::setUseSkyPreset(const std::string& name)
-{
-	mUseRegionSettings = false;
-	mUseDayCycle = false;
-	mSkyPresetName = name;
-}
-
-void LLEnvPrefs::setUseDayCycle(const std::string& name)
-{
-	mUseRegionSettings = false;
-	mUseDayCycle = true;
-	mDayCycleName = name;
-}
-
-//=============================================================================
-LLEnvManagerNew::LLEnvManagerNew():
-	mInterpNextChangeMessage(true),
-	mCurRegionUUID(LLUUID::null),
-	mLastReceivedID(LLUUID::null)
-{
-
-	// Set default environment settings.
-	mUserPrefs.mUseRegionSettings = true;
-	mUserPrefs.mUseDayCycle = true;
-	mUserPrefs.mWaterPresetName = "Default";
-	mUserPrefs.mSkyPresetName = "Default";
-	mUserPrefs.mDayCycleName = "Default";
-
-	LL_DEBUGS("Windlight")<<LL_ENDL;
-	gAgent.addRegionChangedCallback(boost::bind(&LLEnvManagerNew::onRegionChange, this));
-}
-
-bool LLEnvManagerNew::getUseRegionSettings() const
-{
-	return mUserPrefs.getUseRegionSettings();
-}
-
-bool LLEnvManagerNew::getUseDayCycle() const
-{
-	return mUserPrefs.getUseDayCycle();
-}
-
-bool LLEnvManagerNew::getUseFixedSky() const
-{
-	return mUserPrefs.getUseFixedSky();
-}
-
-std::string LLEnvManagerNew::getWaterPresetName() const
-{
-	return mUserPrefs.getWaterPresetName();
-}
-
-std::string LLEnvManagerNew::getSkyPresetName() const
-{
-	return mUserPrefs.getSkyPresetName();
-}
-
-std::string LLEnvManagerNew::getDayCycleName() const
-{
-	return mUserPrefs.getDayCycleName();
-}
-
-const LLEnvironmentSettings& LLEnvManagerNew::getRegionSettings() const
-{
-	return !mNewRegionPrefs.isEmpty() ? mNewRegionPrefs : mCachedRegionPrefs;
-}
-
-void LLEnvManagerNew::setRegionSettings(const LLEnvironmentSettings& new_settings)
-{
-	// Set region settings override that will be used locally
-	// until user either uploads the changes or goes to another region.
-	mNewRegionPrefs = new_settings;
-}
-
-bool LLEnvManagerNew::usePrefs()
-{
-	LL_DEBUGS("Windlight") << "Displaying preferred environment" << LL_ENDL;
-	updateManagersFromPrefs(false);
-	return true;
-}
-
-bool LLEnvManagerNew::useDefaults()
-{
-	bool rslt;
-
-	rslt  = useDefaultWater();
-	rslt &= useDefaultSky();
-
-	return rslt;
-}
-
-bool LLEnvManagerNew::useRegionSettings()
-{
-	bool rslt;
-
-	rslt  = useRegionSky();
-	rslt &= useRegionWater();
-
-	return rslt;
-}
-
-bool LLEnvManagerNew::useWaterPreset(const std::string& name)
-{
-	LL_DEBUGS("Windlight") << "Displaying water preset " << name << LL_ENDL;
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-	bool rslt = water_mgr.getParamSet(name, water_mgr.mCurParams);
-	llassert(rslt == true);
-	return rslt;
-}
-
-bool LLEnvManagerNew::useWaterParams(const LLSD& params)
-{
-	LL_DEBUGS("Windlight") << "Displaying water params" << LL_ENDL;
-	LLWaterParamManager::instance().mCurParams.setAll(params);
-	return true;
-}
-
-bool LLEnvManagerNew::useSkyPreset(const std::string& name)
-{
-	LLWLParamManager& sky_mgr = LLWLParamManager::instance();
-	LLWLParamSet param_set;
-
-	if (!sky_mgr.getParamSet(LLWLParamKey(name, LLEnvKey::SCOPE_LOCAL), param_set))
-	{
-		LL_WARNS() << "No sky preset named " << name << LL_ENDL;
-		return false;
-	}
-
-	LL_DEBUGS("Windlight") << "Displaying sky preset " << name << LL_ENDL;
-	sky_mgr.applySkyParams(param_set.getAll());
-	return true;
-}
-
-bool LLEnvManagerNew::useSkyParams(const LLSD& params)
-{
-	LL_DEBUGS("Windlight") << "Displaying sky params" << LL_ENDL;
-	LLWLParamManager::instance().applySkyParams(params);
-	return true;
-}
-
-bool LLEnvManagerNew::useDayCycle(const std::string& name, LLEnvKey::EScope scope)
-{
-	LLSD params;
-
-	if (scope == LLEnvKey::SCOPE_REGION)
-	{
-		LL_DEBUGS("Windlight") << "Displaying region day cycle " << name << LL_ENDL;
-		params = getRegionSettings().getWLDayCycle();
-	}
-	else
-	{
-		LL_DEBUGS("Windlight") << "Displaying local day cycle " << name << LL_ENDL;
-
-		if (!LLDayCycleManager::instance().getPreset(name, params))
-		{
-			LL_WARNS() << "No day cycle named " << name << LL_ENDL;
-			return false;
-		}
-	}
-
-	bool rslt = LLWLParamManager::instance().applyDayCycleParams(params, scope);
-	llassert(rslt == true);
-	return rslt;
-}
-
-bool LLEnvManagerNew::useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time /* = 0.5*/)
-{
-	LL_DEBUGS("Windlight") << "Displaying day cycle params" << LL_ENDL;
-	return LLWLParamManager::instance().applyDayCycleParams(params, scope);
-}
-
-void LLEnvManagerNew::setUseRegionSettings(bool val)
-{
-	mUserPrefs.setUseRegionSettings(val);
-	saveUserPrefs();
-	updateManagersFromPrefs(false);
-}
-
-void LLEnvManagerNew::setUseWaterPreset(const std::string& name)
-{
-	// *TODO: make sure the preset exists.
-	if (name.empty())
-	{
-		LL_WARNS() << "Empty water preset name passed" << LL_ENDL;
-		return;
-	}
-
-	mUserPrefs.setUseWaterPreset(name);
-	saveUserPrefs();
-	updateManagersFromPrefs(false);
-}
-
-void LLEnvManagerNew::setUseSkyPreset(const std::string& name)
-{
-	// *TODO: make sure the preset exists.
-	if (name.empty())
-	{
-		LL_WARNS() << "Empty sky preset name passed" << LL_ENDL;
-		return;
-	}
-
-	mUserPrefs.setUseSkyPreset(name);
-	saveUserPrefs();
-	updateManagersFromPrefs(false);
-}
-
-void LLEnvManagerNew::setUseDayCycle(const std::string& name)
-{
-	if (!LLDayCycleManager::instance().presetExists(name))
-	{
-		LL_WARNS() << "Invalid day cycle name passed" << LL_ENDL;
-		return;
-	}
-
-	mUserPrefs.setUseDayCycle(name);
-	saveUserPrefs();
-	updateManagersFromPrefs(false);
-}
-
-void LLEnvManagerNew::loadUserPrefs()
-{
-	// operate on members directly to avoid side effects
-	mUserPrefs.mWaterPresetName	= gSavedSettings.getString("WaterPresetName");
-	mUserPrefs.mSkyPresetName	= gSavedSettings.getString("SkyPresetName");
-	mUserPrefs.mDayCycleName	= gSavedSettings.getString("DayCycleName");
-
-	bool use_region_settings = gSavedSettings.getBOOL("EnvironmentPersistAcrossLogin") ? gSavedSettings.getBOOL("UseEnvironmentFromRegion") : true;
-	mUserPrefs.mUseRegionSettings	= use_region_settings;
-	mUserPrefs.mUseDayCycle			= gSavedSettings.getBOOL("UseDayCycle");
-
-	if (mUserPrefs.mUseRegionSettings)
-	{
-		requestRegionSettings();
-	}
-}
-
-void LLEnvManagerNew::saveUserPrefs()
-{
-	gSavedSettings.setString("WaterPresetName",			getWaterPresetName());
-	gSavedSettings.setString("SkyPresetName",			getSkyPresetName());
-	gSavedSettings.setString("DayCycleName",			getDayCycleName());
-
-	gSavedSettings.setBOOL("UseEnvironmentFromRegion",	getUseRegionSettings());
-	gSavedSettings.setBOOL("UseDayCycle",				getUseDayCycle());
-
-	mUsePrefsChangeSignal();
-}
-
-void LLEnvManagerNew::setUserPrefs(
-	const std::string& water_preset,
-	const std::string& sky_preset,
-	const std::string& day_cycle_preset,
-	bool use_fixed_sky,
-	bool use_region_settings)
-{
-	// operate on members directly to avoid side effects
-	mUserPrefs.mWaterPresetName	= water_preset;
-	mUserPrefs.mSkyPresetName	= sky_preset;
-	mUserPrefs.mDayCycleName	= day_cycle_preset;
-
-	mUserPrefs.mUseRegionSettings	= use_region_settings;
-	mUserPrefs.mUseDayCycle			= !use_fixed_sky;
-
-	saveUserPrefs();
-	updateManagersFromPrefs(false);
-}
-
-void LLEnvManagerNew::dumpUserPrefs()
-{
-	LL_DEBUGS("Windlight") << "WaterPresetName: "	<< gSavedSettings.getString("WaterPresetName") << LL_ENDL;
-	LL_DEBUGS("Windlight") << "SkyPresetName: "		<< gSavedSettings.getString("SkyPresetName") << LL_ENDL;
-	LL_DEBUGS("Windlight") << "DayCycleName: "		<< gSavedSettings.getString("DayCycleName") << LL_ENDL;
-
-	LL_DEBUGS("Windlight") << "UseEnvironmentFromRegion: "	<< gSavedSettings.getBOOL("UseEnvironmentFromRegion") << LL_ENDL;
-	LL_DEBUGS("Windlight") << "UseDayCycle: "				<< gSavedSettings.getBOOL("UseDayCycle") << LL_ENDL;
-}
-
-void LLEnvManagerNew::dumpPresets()
-{
-	const LLEnvironmentSettings& region_settings = getRegionSettings();
-	std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : "Unknown region";
-
-	// Dump water presets.
-	LL_DEBUGS("Windlight") << "Waters:" << LL_ENDL;
-	if (region_settings.getWaterParams().size() != 0)
-	{
-		LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
-	}
-	LLWaterParamManager::preset_name_list_t water_presets;
-	LLWaterParamManager::instance().getPresetNames(water_presets);
-	for (LLWaterParamManager::preset_name_list_t::const_iterator it = water_presets.begin(); it != water_presets.end(); ++it)
-	{
-		LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
-	}
-
-	// Dump sky presets.
-	LL_DEBUGS("Windlight") << "Skies:" << LL_ENDL;
-	LLWLParamManager::preset_key_list_t sky_preset_keys;
-	LLWLParamManager::instance().getPresetKeys(sky_preset_keys);
-	for (LLWLParamManager::preset_key_list_t::const_iterator it = sky_preset_keys.begin(); it != sky_preset_keys.end(); ++it)
-	{
-		std::string preset_name = it->name;
-		std::string item_title;
-
-		if (it->scope == LLEnvKey::SCOPE_LOCAL) // local preset
-		{
-			item_title = preset_name;
-		}
-		else // region preset
-		{
-			item_title = preset_name + " (" + region_name + ")";
-		}
-		LL_DEBUGS("Windlight") << " - " << item_title << LL_ENDL;
-	}
-
-	// Dump day cycles.
-	LL_DEBUGS("Windlight") << "Days:" << LL_ENDL;
-	const LLSD& cur_region_dc = region_settings.getWLDayCycle();
-	if (cur_region_dc.size() != 0)
-	{
-		LL_DEBUGS("Windlight") << " - " << region_name << LL_ENDL;
-	}
-	LLDayCycleManager::preset_name_list_t days;
-	LLDayCycleManager::instance().getPresetNames(days);
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = days.begin(); it != days.end(); ++it)
-	{
-		LL_DEBUGS("Windlight") << " - " << *it << LL_ENDL;
-	}
-}
-
-void LLEnvManagerNew::requestRegionSettings()
-{
-	LL_DEBUGS("Windlight") << LL_ENDL;
-	LLEnvironmentRequest::initiate();
-}
-
-bool LLEnvManagerNew::sendRegionSettings(const LLEnvironmentSettings& new_settings)
-{
-	LLSD metadata;
-
-	metadata["regionID"] = gAgent.getRegion()->getRegionID();
-	// add last received update ID to outbound message so simulator can handle concurrent updates
-	metadata["messageID"] = mLastReceivedID;
-
-	return LLEnvironmentApply::initiateRequest(new_settings.makePacket(metadata));
-}
-
-boost::signals2::connection LLEnvManagerNew::setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb)
-{
-	return mUsePrefsChangeSignal.connect(cb);
-}
-
-boost::signals2::connection LLEnvManagerNew::setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb)
-{
-	return mRegionSettingsChangeSignal.connect(cb);
-}
-
-boost::signals2::connection LLEnvManagerNew::setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb)
-{
-	return mRegionSettingsAppliedSignal.connect(cb);
-}
-
-// static
-bool LLEnvManagerNew::canEditRegionSettings()
-{
-	LLViewerRegion* region = gAgent.getRegion();
-	BOOL owner_or_god = gAgent.isGodlike() || (region && region->getOwner() == gAgent.getID());
-	BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
-
-	LL_DEBUGS("Windlight") << "Can edit region settings: " << (bool) owner_or_god_or_manager << LL_ENDL;
-	return owner_or_god_or_manager;
-}
-
-// static
-const std::string LLEnvManagerNew::getScopeString(LLEnvKey::EScope scope)
-{
-	switch(scope)
-	{
-		case LLEnvKey::SCOPE_LOCAL:
-			return LLTrans::getString("LocalSettings");
-		case LLEnvKey::SCOPE_REGION:
-			return LLTrans::getString("RegionSettings");
-		default:
-			return " (?)";
-	}
-}
-
-void LLEnvManagerNew::onRegionSettingsResponse(const LLSD& content)
-{
-	// If the message was valid, grab the UUID from it and save it for next outbound update message.
-	mLastReceivedID = content[0]["messageID"].asUUID();
-
-	// Refresh cached region settings.
-	LL_DEBUGS("Windlight") << "Received region environment settings: " << content << LL_ENDL;
-	F32 sun_hour = 0; // *TODO
-	LLEnvironmentSettings new_settings(content[1], content[2], content[3], sun_hour);
-	mCachedRegionPrefs = new_settings;
-
-	// Load region sky presets.
-	LLWLParamManager::instance().refreshRegionPresets(getRegionSettings().getSkyMap());
-
-	// If using server settings, update managers.
-	if (getUseRegionSettings())
-	{
-		updateManagersFromPrefs(mInterpNextChangeMessage);
-	}
-
-	// Let interested parties know about the region settings update.
-	mRegionSettingsChangeSignal();
-
-	// reset
-	mInterpNextChangeMessage = false;
-}
-
-void LLEnvManagerNew::onRegionSettingsApplyResponse(bool ok)
-{
-	LL_DEBUGS("Windlight") << "Applying region settings " << (ok ? "succeeded" : "failed") << LL_ENDL;
-
-	// Clear locally modified region settings because they have just been uploaded.
-	mNewRegionPrefs.clear();
-
-	mRegionSettingsAppliedSignal(ok);
-}
-
-//-- private methods ----------------------------------------------------------
-
-// virtual
-void LLEnvManagerNew::initSingleton()
-{
-	LL_DEBUGS("Windlight") << "Initializing LLEnvManagerNew" << LL_ENDL;
-
-	loadUserPrefs();
-
-	// preferences loaded, can set params
-	std::string preferred_day = getDayCycleName();
-	if (!useDayCycle(preferred_day, LLEnvKey::SCOPE_LOCAL))
-	{
-		LL_WARNS() << "No day cycle named " << preferred_day << ", reverting LLWLParamManager to defaults" << LL_ENDL;
-		LLWLParamManager::instance().setDefaultDay();
-	}
-
-	std::string sky = getSkyPresetName();
-	if (!useSkyPreset(sky))
-	{
-		LL_WARNS() << "No sky preset named " << sky << ", falling back to defaults" << LL_ENDL;
-		LLWLParamManager::instance().setDefaultSky();
-
-		// *TODO: Fix user preferences accordingly.
-	}
-
-	LLWLParamManager::instance().resetAnimator(0.5 /*noon*/, getUseDayCycle());
-}
-
-void LLEnvManagerNew::updateSkyFromPrefs()
-{
-	bool success = true;
-
-	// Sync sky with user prefs.
-	if (getUseRegionSettings()) // apply region-wide settings
-	{
-		success = useRegionSky();
-	}
-	else // apply user-specified settings
-	{
-		if (getUseDayCycle())
-		{
-			success = useDayCycle(getDayCycleName(), LLEnvKey::SCOPE_LOCAL);
-		}
-		else
-		{
-			success = useSkyPreset(getSkyPresetName());
-		}
-	}
-
-	// If something went wrong, fall back to defaults.
-	if (!success)
-	{
-		// *TODO: fix user prefs
-		useDefaultSky();
-	}
-}
-
-void LLEnvManagerNew::updateWaterFromPrefs(bool interpolate)
-{
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-	LLSD target_water_params;
-
-	// Determine new water settings based on user prefs.
-
-	{
-		// Fall back to default water.
-		LLWaterParamSet default_water;
-		water_mgr.getParamSet("Default", default_water);
-		target_water_params = default_water.getAll();
-	}
-
-	if (getUseRegionSettings())
-	{
-		// *TODO: make sure whether region settings belong to the current region?
-		const LLSD& region_water_params = getRegionSettings().getWaterParams();
-		if (region_water_params.size() != 0) // region has no water settings
-		{
-			LL_DEBUGS("Windlight") << "Applying region water" << LL_ENDL;
-			target_water_params = region_water_params;
-		}
-		else
-		{
-			LL_DEBUGS("Windlight") << "Applying default water" << LL_ENDL;
-		}
-	}
-	else
-	{
-		std::string water = getWaterPresetName();
-		LL_DEBUGS("Windlight") << "Applying water preset [" << water << "]" << LL_ENDL;
-		LLWaterParamSet params;
-		if (!water_mgr.getParamSet(water, params))
-		{
-			LL_WARNS() << "No water preset named " << water << ", falling back to defaults" << LL_ENDL;
-			water_mgr.getParamSet("Default", params);
-
-			// *TODO: Fix user preferences accordingly.
-		}
-		target_water_params = params.getAll();
-	}
-
-	// Sync water with user prefs.
-	water_mgr.applyParams(target_water_params, interpolate);
-}
-
-void LLEnvManagerNew::updateManagersFromPrefs(bool interpolate)
-{
-	LL_DEBUGS("Windlight")<<LL_ENDL;
-	// Apply water settings.
-	updateWaterFromPrefs(interpolate);
-
-	// Apply sky settings.
-	updateSkyFromPrefs();
-}
-
-bool LLEnvManagerNew::useRegionSky()
-{
-	const LLEnvironmentSettings& region_settings = getRegionSettings();
-
-	// If region is set to defaults,
-	if (region_settings.getSkyMap().size() == 0)
-	{
-		// well... apply the default sky settings.
-		useDefaultSky();
-		return true;
-	}
-
-	// Otherwise apply region day cycle/skies.
-	LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
-
-	// *TODO: Support fixed sky from region. Just do sky reset for now.
-	if (region_settings.getSkyMap().size() == 1)
-	{
-		// Region is set to fixed sky. Reset.
-		useSkyParams(region_settings.getSkyMap().beginMap()->second);
-	}
-	return useDayCycleParams(
-		region_settings.getWLDayCycle(),
-		LLEnvKey::SCOPE_REGION,
-		region_settings.getDayTime());
-}
-
-bool LLEnvManagerNew::useRegionWater()
-{
-	const LLEnvironmentSettings& region_settings = getRegionSettings();
-	const LLSD& region_water = region_settings.getWaterParams();
-
-	// If region is set to defaults,
-	if (region_water.size() == 0)
-	{
-		// well... apply the default water settings.
-		return useDefaultWater();
-	}
-
-	// Otherwise apply region water.
-	LL_DEBUGS("Windlight") << "Applying region sky" << LL_ENDL;
-	return useWaterParams(region_water);
-}
-
-bool LLEnvManagerNew::useDefaultSky()
-{
-	return useDayCycle("Default", LLEnvKey::SCOPE_LOCAL);
-}
-
-bool LLEnvManagerNew::useDefaultWater()
-{
-	return useWaterPreset("Default");
-}
-
-
-void LLEnvManagerNew::onRegionChange()
-{
-	// Avoid duplicating region setting requests
-	// by checking whether the region is actually changing.
-	LLViewerRegion* regionp = gAgent.getRegion();
-	LLUUID region_uuid = regionp ? regionp->getRegionID() : LLUUID::null;
-	if (region_uuid != mCurRegionUUID)
-	{
-	// Clear locally modified region settings.
-	mNewRegionPrefs.clear();
-
-	// *TODO: clear environment settings of the previous region?
-
-	// Request environment settings of the new region.
-	mCurRegionUUID = region_uuid;
-		// for region crossings, interpolate the change; for teleports, don't
-		mInterpNextChangeMessage = (gAgent.getTeleportState() == LLAgent::TELEPORT_NONE);
-		LL_DEBUGS("Windlight") << (mInterpNextChangeMessage ? "Crossed" : "Teleported")
-							   << " to new region: " << region_uuid
-							   << LL_ENDL;
-	requestRegionSettings();
-	}
-	else
-	{
-		LL_DEBUGS("Windlight") << "disregarding region change; interp: "
-							   << (mInterpNextChangeMessage ? "true" : "false")
-							   << " regionp: " << regionp
-							   << " old: " << mCurRegionUUID
-							   << " new: " << region_uuid
-							   << LL_ENDL;
-	}
-}
diff --git a/indra/newview/llenvmanager.h b/indra/newview/llenvmanager.h
deleted file mode 100644
index 54bbf85e867bcffdf1e7bf06e49c70cd68c4bd4d..0000000000000000000000000000000000000000
--- a/indra/newview/llenvmanager.h
+++ /dev/null
@@ -1,349 +0,0 @@
-/**
- * @file llenvmanager.h
- * @brief Declaration of classes managing WindLight and water settings.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLENVMANAGER_H
-#define LL_LLENVMANAGER_H
-
-#include "llmemory.h"
-#include "llsd.h"
-
-class LLWLParamManager;
-class LLWaterParamManager;
-class LLWLAnimator;
-
-// generic key
-struct LLEnvKey
-{
-public:
-	// Note: enum ordering is important; for example, a region-level floater (1) will see local and region (all values that are <=)
-	typedef enum e_scope
-	{
-		SCOPE_LOCAL,				// 0
-		SCOPE_REGION//,				// 1
-		// SCOPE_ESTATE,			// 2
-		// etc.
-	} EScope;
-};
-
-struct LLWLParamKey : LLEnvKey
-{
-public:
-	// scope and source of a param set (WL sky preset)
-	std::string name;
-	EScope scope;
-
-	// for conversion from LLSD
-	static const int NAME_IDX = 0;
-	static const int SCOPE_IDX = 1;
-
-	inline LLWLParamKey(const std::string& n, EScope s)
-		: name(n), scope(s)
-	{
-	}
-
-	inline LLWLParamKey(LLSD llsd)
-		: name(llsd[NAME_IDX].asString()), scope(EScope(llsd[SCOPE_IDX].asInteger()))
-	{
-	}
-
-	inline LLWLParamKey() // NOT really valid, just so std::maps can return a default of some sort
-		: name(""), scope(SCOPE_LOCAL)
-	{
-	}
-
-	inline LLWLParamKey(std::string& stringVal)
-	{
-		size_t len = stringVal.length();
-		if (len > 0)
-		{
-			name = stringVal.substr(0, len - 1);
-			scope = (EScope) atoi(stringVal.substr(len - 1, len).c_str());
-		}
-	}
-
-	inline std::string toStringVal() const
-	{
-		std::stringstream str;
-		str << name << scope;
-		return str.str();
-	}
-
-	inline LLSD toLLSD() const
-	{
-		LLSD llsd = LLSD::emptyArray();
-		llsd.append(LLSD(name));
-		llsd.append(LLSD(scope));
-		return llsd;
-	}
-
-	inline void fromLLSD(const LLSD& llsd)
-	{
-		name = llsd[NAME_IDX].asString();
-		scope = EScope(llsd[SCOPE_IDX].asInteger());
-	}
-
-	inline bool operator <(const LLWLParamKey other) const
-	{
-		if (name < other.name)
-		{	
-			return true;
-		}
-		else if (name > other.name)
-		{
-			return false;
-		}
-		else
-		{
-			return scope < other.scope;
-		}
-	}
-
-	inline bool operator ==(const LLWLParamKey other) const
-	{
-		return (name == other.name) && (scope == other.scope);
-	}
-
-	std::string toString() const;
-};
-
-class LLEnvironmentSettings
-{
-public:
-	LLEnvironmentSettings() :
-		mWLDayCycle(LLSD::emptyMap()),
-		mSkyMap(LLSD::emptyMap()),
-		mWaterParams(LLSD::emptyMap()),
-		mDayTime(0.f)
-	{}
-	LLEnvironmentSettings(const LLSD& dayCycle, const LLSD& skyMap, const LLSD& waterParams, F64 dayTime) :
-		mWLDayCycle(dayCycle),
-		mSkyMap(skyMap),
-		mWaterParams(waterParams),
-		mDayTime(dayTime)
-	{}
-	~LLEnvironmentSettings() {}
-
-	void saveParams(const LLSD& dayCycle, const LLSD& skyMap, const LLSD& waterParams, F64 dayTime)
-	{
-		mWLDayCycle = dayCycle;
-		mSkyMap = skyMap;
-		mWaterParams = waterParams;
-		mDayTime = dayTime;
-	}
-
-	const LLSD& getWLDayCycle() const
-	{
-		return mWLDayCycle;
-	}
-
-	const LLSD& getWaterParams() const
-	{
-		return mWaterParams;
-	}
-
-	const LLSD& getSkyMap() const
-	{
-		return mSkyMap;
-	}
-
-	F64 getDayTime() const
-	{
-		return mDayTime;
-	}
-
-	bool isEmpty() const
-	{
-		return mWLDayCycle.size() == 0;
-	}
-
-	void clear()
-	{
-		*this = LLEnvironmentSettings();
-	}
-
-	LLSD makePacket(const LLSD& metadata) const
-	{
-		LLSD full_packet = LLSD::emptyArray();
-
-		// 0: metadata
-		full_packet.append(metadata);
-
-		// 1: day cycle
-		full_packet.append(mWLDayCycle);
-
-		// 2: map of sky setting names to sky settings (as LLSD)
-		full_packet.append(mSkyMap);
-
-		// 3: water params
-		full_packet.append(mWaterParams);
-
-		return full_packet;
-	}
-
-private:
-	LLSD mWLDayCycle, mWaterParams, mSkyMap;
-	F64 mDayTime;
-};
-
-/**
- * User environment preferences.
- */
-class LLEnvPrefs
-{
-public:
-	LLEnvPrefs() : mUseRegionSettings(true), mUseDayCycle(true) {}
-
-	bool getUseRegionSettings() const { return mUseRegionSettings; }
-	bool getUseDayCycle() const { return mUseDayCycle; }
-	bool getUseFixedSky() const { return !getUseDayCycle(); }
-
-	std::string getWaterPresetName() const;
-	std::string getSkyPresetName() const;
-	std::string getDayCycleName() const;
-
-	void setUseRegionSettings(bool val);
-	void setUseWaterPreset(const std::string& name);
-	void setUseSkyPreset(const std::string& name);
-	void setUseDayCycle(const std::string& name);
-
-	bool			mUseRegionSettings;
-	bool			mUseDayCycle;
-	std::string		mWaterPresetName;
-	std::string		mSkyPresetName;
-	std::string		mDayCycleName;
-};
-
-/**
- * Setting:
- * 1. Use region settings.
- * 2. Use my setting: <water preset> + <fixed_sky>|<day_cycle>
- */
-class LLEnvManagerNew : public LLSingleton<LLEnvManagerNew>
-{
-	LLSINGLETON(LLEnvManagerNew);
-	LOG_CLASS(LLEnvManagerNew);
-public:
-	typedef boost::signals2::signal<void()> prefs_change_signal_t;
-	typedef boost::signals2::signal<void()> region_settings_change_signal_t;
-	typedef boost::signals2::signal<void(bool)> region_settings_applied_signal_t;
-
-	// getters to access user env. preferences
-	bool getUseRegionSettings() const;
-	bool getUseDayCycle() const;
-	bool getUseFixedSky() const;
-	std::string getWaterPresetName() const;
-	std::string getSkyPresetName() const;
-	std::string getDayCycleName() const;
-
-	/// @return cached env. settings of the current region.
-	const LLEnvironmentSettings& getRegionSettings() const;
-
-	/**
-	 * Set new region settings without uploading them to the region.
-	 *
-	 * The override will be reset when the changes are applied to the region (=uploaded)
-	 * or user teleports to another region.
-	 */
-	void setRegionSettings(const LLEnvironmentSettings& new_settings);
-
-	// Change environment w/o changing user preferences.
-	bool usePrefs();
-	bool useDefaults();
-	bool useRegionSettings();
-	bool useWaterPreset(const std::string& name);
-	bool useWaterParams(const LLSD& params);
-	bool useSkyPreset(const std::string& name);
-	bool useSkyParams(const LLSD& params);
-	bool useDayCycle(const std::string& name, LLEnvKey::EScope scope);
-	bool useDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time = 0.5);
-
-	// setters for user env. preferences
-	void setUseRegionSettings(bool val);
-	void setUseWaterPreset(const std::string& name);
-	void setUseSkyPreset(const std::string& name);
-	void setUseDayCycle(const std::string& name);
-	void setUserPrefs(
-		const std::string& water_preset,
-		const std::string& sky_preset,
-		const std::string& day_cycle_preset,
-		bool use_fixed_sky,
-		bool use_region_settings);
-
-	// debugging methods
-	void dumpUserPrefs();
-	void dumpPresets();
-
-	// Misc.
-	void requestRegionSettings();
-	bool sendRegionSettings(const LLEnvironmentSettings& new_settings);
-	boost::signals2::connection setPreferencesChangeCallback(const prefs_change_signal_t::slot_type& cb);
-	boost::signals2::connection setRegionSettingsChangeCallback(const region_settings_change_signal_t::slot_type& cb);
-	boost::signals2::connection setRegionSettingsAppliedCallback(const region_settings_applied_signal_t::slot_type& cb);
-
-	static bool canEditRegionSettings(); /// @return true if we have access to editing region environment
-	static const std::string getScopeString(LLEnvKey::EScope scope);
-
-	// Public callbacks.
-	void onRegionSettingsResponse(const LLSD& content);
-	void onRegionSettingsApplyResponse(bool ok);
-
-private:
-	/*virtual*/ void initSingleton();
-
-	void loadUserPrefs();
-	void saveUserPrefs();
-
-	void updateSkyFromPrefs();
-	void updateWaterFromPrefs(bool interpolate);
-	void updateManagersFromPrefs(bool interpolate);
-
-	bool useRegionSky();
-	bool useRegionWater();
-
-	bool useDefaultSky();
-	bool useDefaultWater();
-
-	void onRegionChange();
-
-	/// Emitted when user environment preferences change.
-	prefs_change_signal_t mUsePrefsChangeSignal;
-
-	/// Emitted when region environment settings update comes.
-	region_settings_change_signal_t	mRegionSettingsChangeSignal;
-
-	/// Emitted when agent region changes. Move to LLAgent?
-	region_settings_applied_signal_t mRegionSettingsAppliedSignal;
-
-	LLEnvPrefs				mUserPrefs;					/// User environment preferences.
-	LLEnvironmentSettings	mCachedRegionPrefs;			/// Cached region environment settings.
-	LLEnvironmentSettings	mNewRegionPrefs;			/// Not-yet-uploaded modified region env. settings.
-	bool					mInterpNextChangeMessage;	/// Interpolate env. settings on next region change.
-	LLUUID					mCurRegionUUID;				/// To avoid duplicated region env. settings requests.
-	LLUUID					mLastReceivedID;			/// Id of last received region env. settings.
-};
-
-#endif // LL_LLENVMANAGER_H
-
diff --git a/indra/newview/llestateinfomodel.cpp b/indra/newview/llestateinfomodel.cpp
index 95d40be9133220ab88db82757e14e014dfb0d60d..4fdb86059286b13d4b12ec5fc665182b40b0dd4d 100644
--- a/indra/newview/llestateinfomodel.cpp
+++ b/indra/newview/llestateinfomodel.cpp
@@ -73,6 +73,7 @@ bool LLEstateInfoModel::getDenyAnonymous()			const {	return getFlag(REGION_FLAGS
 bool LLEstateInfoModel::getDenyAgeUnverified()		const {	return getFlag(REGION_FLAGS_DENY_AGEUNVERIFIED);	}
 bool LLEstateInfoModel::getAllowVoiceChat()			const { return getFlag(REGION_FLAGS_ALLOW_VOICE); }
 bool LLEstateInfoModel::getAllowAccessOverride()	const { return getFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE); }
+bool LLEstateInfoModel::getAllowEnvironmentOverride() const { return getFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE); }
 
 void LLEstateInfoModel::setUseFixedSun(bool val)			{ setFlag(REGION_FLAGS_SUN_FIXED, 				val);	}
 void LLEstateInfoModel::setIsExternallyVisible(bool val)	{ setFlag(REGION_FLAGS_EXTERNALLY_VISIBLE,		val);	}
@@ -81,6 +82,7 @@ void LLEstateInfoModel::setDenyAnonymous(bool val)			{ setFlag(REGION_FLAGS_DENY
 void LLEstateInfoModel::setDenyAgeUnverified(bool val)		{ setFlag(REGION_FLAGS_DENY_AGEUNVERIFIED,		val);	}
 void LLEstateInfoModel::setAllowVoiceChat(bool val)		    { setFlag(REGION_FLAGS_ALLOW_VOICE,				val);	}
 void LLEstateInfoModel::setAllowAccessOverride(bool val)    { setFlag(REGION_FLAGS_ALLOW_ACCESS_OVERRIDE,   val);   }
+void LLEstateInfoModel::setAllowEnvironmentOverride(bool val) { setFlag(REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE, val); }
 
 void LLEstateInfoModel::update(const strings_t& strings)
 {
@@ -222,6 +224,7 @@ std::string LLEstateInfoModel::getInfoDump()
 	dump["deny_age_unverified"  ] = getDenyAgeUnverified();
 	dump["allow_voice_chat"     ] = getAllowVoiceChat();
     dump["override_public_access"] = getAllowAccessOverride();
+    dump["override_environment"] = getAllowEnvironmentOverride();
 
 	std::stringstream dump_str;
 	dump_str << dump;
diff --git a/indra/newview/llestateinfomodel.h b/indra/newview/llestateinfomodel.h
index 0082b5b1f4682c83401c7857f7c7def8b92e532f..d6f00c573cf11c619d9ee62917c6bde60d31938e 100644
--- a/indra/newview/llestateinfomodel.h
+++ b/indra/newview/llestateinfomodel.h
@@ -56,6 +56,7 @@ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
 	bool				getDenyAgeUnverified()		const;
 	bool				getAllowVoiceChat()			const;
     bool                getAllowAccessOverride()    const;
+    bool                getAllowEnvironmentOverride() const;
 
 	const std::string&	getName()					const { return mName; }
 	const LLUUID&		getOwnerID()				const { return mOwnerID; }
@@ -70,6 +71,7 @@ class LLEstateInfoModel : public LLSingleton<LLEstateInfoModel>
 	void setDenyAgeUnverified(bool val);
 	void setAllowVoiceChat(bool val);
     void setAllowAccessOverride(bool val);
+    void setAllowEnvironmentOverride(bool val);
 
 	void setSunHour(F32 sun_hour) { mSunHour = sun_hour; }
 
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 5e0f3ab7f948f1b2659f623216f2b2419fd96410..299fffd9ab942a90085441c952f5ba896d92d96e 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -106,6 +106,7 @@ namespace Details
         LLSD message;
         message["sender"] = mSenderIp;
         message["body"] = content["body"];
+
         LLMessageSystem::dispatch(msg_name, message);
     }
 
@@ -241,7 +242,7 @@ namespace Details
                 !result.get("events") ||
                 !result.get("id"))
             {
-                LL_WARNS("LLEventPollImpl") << " <" << counter << "> received event poll with no events or id key: " << LLSDXMLStreamer(result) << LL_ENDL;
+                LL_WARNS("LLEventPollImpl") << " <" << counter << "> received event poll with no events or id key: " << result << LL_ENDL;
                 continue;
             }
 
@@ -254,7 +255,7 @@ namespace Details
             }
 
             // was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
-            LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL;
+            LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << acknowledge << ")" << LL_ENDL;
 
             LLSD::array_const_iterator i = events.beginArray();
             LLSD::array_const_iterator end = events.endArray();
diff --git a/indra/newview/llexperiencelog.h b/indra/newview/llexperiencelog.h
index 09e0cd8821bd6fd3ae96a52f17f052c16b726300..5cc5bf685fd0445b122a349ad6055c2cf464ebf8 100644
--- a/indra/newview/llexperiencelog.h
+++ b/indra/newview/llexperiencelog.h
@@ -62,10 +62,9 @@ class LLExperienceLog : public LLSingleton<LLExperienceLog>
 	static std::string getPermissionString(const LLSD& message, const std::string& base);
 	void setEventsToSave(LLSD new_events){mEventsToSave = new_events; }
 	bool isNotExpired(std::string& date);
-protected:
 	void handleExperienceMessage(LLSD& message);
 
-
+protected:
 	void loadEvents();
 	void saveEvents();
 	void eraseExpired();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 85ee33edb19234b99736aba2c106c52b4cd3a71e..18ea184da6a128617cca14cd851349a6521a8637 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -168,7 +168,8 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
 	mImportanceToCamera = 0.f ;
 	mBoundingSphereRadius = 0.0f ;
 
-	mHasMedia = FALSE ;
+	mHasMedia = false ;
+	mIsMediaAllowed = true;
 }
 
 void LLFace::destroy()
@@ -302,6 +303,11 @@ void LLFace::setDiffuseMap(LLViewerTexture* tex)
 	setTexture(LLRender::DIFFUSE_MAP, tex);
 }
 
+void LLFace::setAlternateDiffuseMap(LLViewerTexture* tex)
+{
+    setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, tex);
+}
+
 void LLFace::setNormalMap(LLViewerTexture* tex)
 {
 	setTexture(LLRender::NORMAL_MAP, tex);
@@ -1414,17 +1420,16 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 
 			if (shiny_in_alpha)
 			{
-
-				static const GLfloat alpha[4] =
+				static const GLfloat SHININESS_TO_ALPHA[4] =
 				{
-					0.00f,
+					0.0000f,
 					0.25f,
 					0.5f,
 					0.75f
 				};
 			
 				llassert(tep->getShiny() <= 3);
-				color.mV[3] = U8 (alpha[tep->getShiny()] * 255);
+				color.mV[3] = U8 (SHININESS_TO_ALPHA[tep->getShiny()] * 255);
 			}
 		}
 	}
@@ -1710,7 +1715,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 				// that emboss mapping always shows up on the upward faces of cubes when 
 				// it's noon (since a lot of builders build with the sun forced to noon).
 				LLVector3   sun_ray  = gSky.mVOSkyp->mBumpSunDir;
-				LLVector3   moon_ray = gSky.getMoonDirection();
+				LLVector3   moon_ray = gSky.mVOSkyp->getMoon().getDirection();
 				LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray;
 
 				bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV);
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 77861f7d2f9016b21e1f2e5e53b9236d6f5e836f..c74d4e3fa843a1f114f5d1df272cad1a1a7b8b46 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -104,6 +104,7 @@ class LLFace : public LLTrace::MemTrackableNonVirtual<LLFace, 16>
 	void			setDiffuseMap(LLViewerTexture* tex);
 	void			setNormalMap(LLViewerTexture* tex);
 	void			setSpecularMap(LLViewerTexture* tex);
+    void			setAlternateDiffuseMap(LLViewerTexture* tex);
 	void            switchTexture(U32 ch, LLViewerTexture* new_texture);
 	void            dirtyTexture();
 	LLXformMatrix*	getXform()			const	{ return mXform; }
@@ -217,6 +218,9 @@ class LLFace : public LLTrace::MemTrackableNonVirtual<LLFace, 16>
 	void        setHasMedia(bool has_media)  { mHasMedia = has_media ;}
 	BOOL        hasMedia() const ;
 
+    void        setMediaAllowed(bool is_media_allowed)  { mIsMediaAllowed = is_media_allowed; }
+    BOOL        isMediaAllowed() const { return mIsMediaAllowed; }
+
 	BOOL		switchTexture() ;
 
 	//vertex buffer tracking
@@ -292,6 +296,7 @@ class LLFace : public LLTrace::MemTrackableNonVirtual<LLFace, 16>
 	F32         mImportanceToCamera ; 
 	F32         mBoundingSphereRadius ;
 	bool        mHasMedia ;
+	bool        mIsMediaAllowed;
 
 	
 protected:
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index d90f03b403ccb36dd4d3d4f7c8cef26a42402d92..239d1621010154363f144ac01ba00ba0d7bf82fe 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -130,7 +130,7 @@ BOOL LLFastTimerView::postBuild()
 {
 	LLButton& pause_btn = getChildRef<LLButton>("pause_btn");
 	mScrollBar = getChild<LLScrollbar>("scroll_vert");
-
+	
 	pause_btn.setCommitCallback(boost::bind(&LLFastTimerView::onPause, this));
 	return TRUE;
 }
@@ -361,12 +361,12 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
     }
     else
     {
-        setPauseState(true);
-        mScrollIndex = llclamp(mScrollIndex + clicks,
-            0,
-            llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY));
+	setPauseState(true);
+	mScrollIndex = llclamp(	mScrollIndex + clicks,
+							0,
+							llmin((S32)mRecording.getNumRecordedPeriods(), (S32)mRecording.getNumRecordedPeriods() - MAX_VISIBLE_HISTORY));
     }
-    return TRUE;
+	return TRUE;
 }
 
 static BlockTimerStatHandle FTM_RENDER_TIMER("Timers");
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index aa9cba0c188b650e1527e53e7f5d61cfd91d4815..d915a9fd2695a7aeeff74afb75ba8a5612382c53 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -617,36 +617,36 @@ void LLFeatureManager::applyFeatures(bool skipFeatures)
 
 void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures)
 {
-	LLViewerShaderMgr::sSkipReload = true;
+    LLViewerShaderMgr::sSkipReload = true;
 
-	applyBaseMasks();
+    applyBaseMasks();
 
-	// if we're passed an invalid level, default to "Low"
-	std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low");
-	if (features == "Low")
-	{
+    // if we're passed an invalid level, default to "Low"
+    std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low");
+    if (features == "Low")
+    {
 #if LL_DARWIN
-		// This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac
-		// systems which support them instead of falling back to fixed-function unnecessarily
-		// MAINT-2157
-		if (gGLManager.mGLVersion < 2.1f)
+        // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac
+        // systems which support them instead of falling back to fixed-function unnecessarily
+        // MAINT-2157
+        if (gGLManager.mGLVersion < 2.1f)
 #else
-		// only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
-		if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
+        // only use fixed function by default if GL version < 3.0 or this is an intel graphics chip
+        if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel)
 #endif
-		{
+        {
             // same as Low, but with "Basic Shaders" disabled
-			features = "LowFixedFunction";
-		}
-	}
+            features = "LowFixedFunction";
+        }
+    }
 
-	maskFeatures(features);
+    maskFeatures(features);
 
-	applyFeatures(skipFeatures);
+    applyFeatures(skipFeatures);
 
-	LLViewerShaderMgr::sSkipReload = false;
-	LLViewerShaderMgr::instance()->setShaders();
-	gPipeline.refreshCachedSettings();
+    LLViewerShaderMgr::sSkipReload = false;
+    LLViewerShaderMgr::instance()->setShaders();
+    gPipeline.refreshCachedSettings();
 }
 
 void LLFeatureManager::applyBaseMasks()
diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index f2040bc76080050e0108a14cfe4158ab553bc4dc..a1a06706bc6da7a57dcfb851e049c9ae1f36eea2 100644
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -75,6 +75,7 @@ BOOL LLFloaterBulkPermission::postBuild()
 	mBulkChangeIncludeScripts = gSavedSettings.getBOOL("BulkChangeIncludeScripts");
 	mBulkChangeIncludeSounds = gSavedSettings.getBOOL("BulkChangeIncludeSounds");
 	mBulkChangeIncludeTextures = gSavedSettings.getBOOL("BulkChangeIncludeTextures");
+	mBulkChangeIncludeSettings = gSavedSettings.getBOOL("BulkChangeIncludeSettings");
 	mBulkChangeShareWithGroup = gSavedSettings.getBOOL("BulkChangeShareWithGroup");
 	mBulkChangeEveryoneCopy = gSavedSettings.getBOOL("BulkChangeEveryoneCopy");
 	mBulkChangeNextOwnerModify = gSavedSettings.getBOOL("BulkChangeNextOwnerModify");
@@ -186,6 +187,7 @@ void LLFloaterBulkPermission::onCloseBtn()
 	gSavedSettings.setBOOL("BulkChangeIncludeScripts", mBulkChangeIncludeScripts);
 	gSavedSettings.setBOOL("BulkChangeIncludeSounds", mBulkChangeIncludeSounds);
 	gSavedSettings.setBOOL("BulkChangeIncludeTextures", mBulkChangeIncludeTextures);
+	gSavedSettings.setBOOL("BulkChangeIncludeSettings", mBulkChangeIncludeSettings);
 	gSavedSettings.setBOOL("BulkChangeShareWithGroup", mBulkChangeShareWithGroup);
 	gSavedSettings.setBOOL("BulkChangeEveryoneCopy", mBulkChangeEveryoneCopy);
 	gSavedSettings.setBOOL("BulkChangeNextOwnerModify", mBulkChangeNextOwnerModify);
@@ -281,6 +283,7 @@ void LLFloaterBulkPermission::doCheckUncheckAll(BOOL check)
 	gSavedSettings.setBOOL("BulkChangeIncludeScripts"   , check);
 	gSavedSettings.setBOOL("BulkChangeIncludeSounds"    , check);
 	gSavedSettings.setBOOL("BulkChangeIncludeTextures"  , check);
+	gSavedSettings.setBOOL("BulkChangeIncludeSettings"  , check);
 }
 
 
@@ -302,6 +305,7 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve
 			( asstype == LLAssetType::AT_OBJECT    && gSavedSettings.getBOOL("BulkChangeIncludeObjects"   )) ||
 			( asstype == LLAssetType::AT_LSL_TEXT  && gSavedSettings.getBOOL("BulkChangeIncludeScripts"   )) ||
 			( asstype == LLAssetType::AT_SOUND     && gSavedSettings.getBOOL("BulkChangeIncludeSounds"    )) ||
+			( asstype == LLAssetType::AT_SETTINGS  && gSavedSettings.getBOOL("BulkChangeIncludeSettings"  )) ||
 			( asstype == LLAssetType::AT_TEXTURE   && gSavedSettings.getBOOL("BulkChangeIncludeTextures"  )))
 		{
 			LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
@@ -333,7 +337,12 @@ void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInve
 					//|| something else // for next owner perms
 					)
 				{
-					perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("BulkChange"));
+					U32 mask_next = LLFloaterPerms::getNextOwnerPerms("BulkChange");
+					if (asstype == LLAssetType::AT_SETTINGS)
+					{
+						mask_next |= PERM_COPY;
+					}
+					perm.setMaskNext(mask_next);
 					perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("BulkChange"));
 					perm.setMaskGroup(LLFloaterPerms::getGroupPerms("BulkChange"));
 					new_item->setPermissions(perm); // here's the beef
diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
index 0c042c3ee373b82dd0473810106da30331c22b79..1afc876bba981406d3dde48443505d6add8d7e87 100644
--- a/indra/newview/llfloaterbulkpermission.h
+++ b/indra/newview/llfloaterbulkpermission.h
@@ -102,6 +102,7 @@ class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener
 	bool mBulkChangeIncludeScripts;
 	bool mBulkChangeIncludeSounds;
 	bool mBulkChangeIncludeTextures;
+	bool mBulkChangeIncludeSettings;
 	bool mBulkChangeShareWithGroup;
 	bool mBulkChangeEveryoneCopy;
 	bool mBulkChangeNextOwnerModify;
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index 5a9cdbba44d6bfe3aee80e43f079528bf4e32147..4d3ebcda1e5182558f5d80b363ce4f7eab52c0f8 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -241,7 +241,7 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
 		BOOL item_is_multi = FALSE;
 		if (( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED
 			|| inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
-			&& !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK))
+            && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK))
 		{
 			item_is_multi = TRUE;
 		}
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index 4607b4ac411d5fb04ec7c4c92a29a9e8077d43a6..440ec06c4ea70744e37d12739221e490a4ace04a 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -216,7 +216,7 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
 		BOOL item_is_multi = FALSE;
 		if ((inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED
 			|| inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
-			&& !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK))
+            && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_SUBTYPE_MASK))
 		{
 			item_is_multi = TRUE;
 		}
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index ec2c9740afe9846836ce5632a7b0e5f2b8f01689..1a784223c2eb0084645ccef108fb203e3f09fcff 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -485,56 +485,8 @@ BOOL LLFloaterColorPicker::isColorChanged()
 //
 void LLFloaterColorPicker::draw()
 {
-	LLRect swatch_rect;
-	mSwatch->localRectToOtherView(mSwatch->getLocalRect(), &swatch_rect, this);
-	// draw context cone connecting color picker with color swatch in parent floater
-	LLRect local_rect = getLocalRect();
-	if (hasFocus() && mSwatch->isInVisibleChain() && mContextConeOpacity > 0.001f)
-	{
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-		LLGLEnable(GL_CULL_FACE);
-		gGL.begin(LLRender::QUADS);
-		{
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mTop);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mTop);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-			gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-			gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-			gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-			gGL.vertex2i(swatch_rect.mRight, swatch_rect.mBottom);
-			gGL.vertex2i(swatch_rect.mLeft, swatch_rect.mBottom);
-		}
-		gGL.end();
-	}
-
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), 
-                                        LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime));
-	}
+	static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+	drawConeToOwner(mContextConeOpacity, max_opacity, mSwatch, mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
 
 	mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance());
 	mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately);
diff --git a/indra/newview/llfloaterdeleteenvpreset.cpp b/indra/newview/llfloaterdeleteenvpreset.cpp
deleted file mode 100644
index bb11c813b4e393675589319e89d44f36296bfe5f..0000000000000000000000000000000000000000
--- a/indra/newview/llfloaterdeleteenvpreset.cpp
+++ /dev/null
@@ -1,285 +0,0 @@
-/** 
- * @file llfloaterdeleteenvpreset.cpp
- * @brief Floater to delete a water / sky / day cycle preset.
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterdeleteenvpreset.h"
-
-// libs
-#include "llbutton.h"
-#include "llcombobox.h"
-#include "llnotificationsutil.h"
-
-// newview
-#include "lldaycyclemanager.h"
-#include "llwaterparammanager.h"
-
-static bool confirmation_callback(const LLSD& notification, const LLSD& response, boost::function<void()> cb)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-	if (option == 0)
-	{
-		cb();
-	}
-	return false;
-
-}
-
-LLFloaterDeleteEnvPreset::LLFloaterDeleteEnvPreset(const LLSD &key)
-:	LLFloater(key)
-,	mPresetCombo(NULL)
-{
-}
-
-// virtual
-BOOL LLFloaterDeleteEnvPreset::postBuild()
-{
-	mPresetCombo = getChild<LLComboBox>("preset_combo");
-	mPresetCombo->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::postPopulate, this));
-
-	getChild<LLButton>("delete")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnDelete, this));
-	getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterDeleteEnvPreset::onBtnCancel, this));
-
-	// Listen to user preferences change, in which case we need to rebuild the presets list
-	// to disable the [new] current preset.
-	LLEnvManagerNew::instance().setPreferencesChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populatePresetsList, this));
-
-	// Listen to presets addition/removal.
-	LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateDayCyclesList, this));
-	LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateSkyPresetsList, this));
-	LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterDeleteEnvPreset::populateWaterPresetsList, this));
-
-	return TRUE;
-}
-
-// virtual
-void LLFloaterDeleteEnvPreset::onOpen(const LLSD& key)
-{
-	std::string param = key.asString();
-	std::string floater_title = getString(std::string("title_") + param);
-	std::string combo_label = getString(std::string("label_" + param));
-
-	// Update floater title.
-	setTitle(floater_title);
-
-	// Update the combobox label.
-	getChild<LLUICtrl>("label")->setValue(combo_label);
-
-	// Populate the combobox.
-	populatePresetsList();
-}
-
-void LLFloaterDeleteEnvPreset::onBtnDelete()
-{
-	std::string param = mKey.asString();
-	std::string preset_name = mPresetCombo->getValue().asString();
-	boost::function<void()> confirm_cb;
-
-	if (param == "water")
-	{
-		// Don't allow deleting system presets.
-		if (LLWaterParamManager::instance().isSystemPreset(preset_name))
-		{
-			LLNotificationsUtil::add("WLNoEditDefault");
-			return;
-		}
-
-		confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteWaterPresetConfirmation, this);
-	}
-	else if (param == "sky")
-	{
-		// Don't allow deleting presets referenced by local day cycles.
-		if (LLDayCycleManager::instance().isSkyPresetReferenced(preset_name))
-		{
-			LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", getString("msg_sky_is_referenced")));
-			return;
-		}
-
-		LLWLParamManager& wl_mgr = LLWLParamManager::instance();
-
-		// Don't allow deleting system presets.
-		if (wl_mgr.isSystemPreset(preset_name))
-		{
-			LLNotificationsUtil::add("WLNoEditDefault");
-			return;
-		}
-
-		confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteSkyPresetConfirmation, this);
-	}
-	else if (param == "day_cycle")
-	{
-		LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
-
-		// Don't allow deleting system presets.
-		if (day_mgr.isSystemPreset(preset_name))
-		{
-			LLNotificationsUtil::add("WLNoEditDefault");
-			return;
-		}
-
-		confirm_cb = boost::bind(&LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation, this);
-	}
-	else
-	{
-		LL_WARNS() << "Unrecognized key" << LL_ENDL;
-	}
-
-	LLSD args;
-	args["MESSAGE"] = getString("msg_confirm_deletion");
-	LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(),
-		boost::bind(&confirmation_callback, _1, _2, confirm_cb));
-}
-
-void LLFloaterDeleteEnvPreset::onBtnCancel()
-{
-	closeFloater();
-}
-
-void LLFloaterDeleteEnvPreset::populatePresetsList()
-{
-	std::string param = mKey.asString();
-
-	if (param == "water")
-	{
-		populateWaterPresetsList();
-	}
-	else if (param == "sky")
-	{
-		populateSkyPresetsList();
-	}
-	else if (param == "day_cycle")
-	{
-		populateDayCyclesList();
-	}
-	else
-	{
-		LL_WARNS() << "Unrecognized key" << LL_ENDL;
-	}
-}
-
-void LLFloaterDeleteEnvPreset::populateWaterPresetsList()
-{
-	if (mKey.asString() != "water") return;
-
-	mPresetCombo->removeall();
-
-	std::string cur_preset;
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	if (!env_mgr.getUseRegionSettings())
-	{
-		cur_preset = env_mgr.getWaterPresetName();
-	}
-
-	LLWaterParamManager::preset_name_list_t presets;
-	LLWaterParamManager::instance().getUserPresetNames(presets); // list only user presets
-	for (LLWaterParamManager::preset_name_list_t::const_iterator it = presets.begin(); it != presets.end(); ++it)
-	{
-		std::string name = *it;
-
-		bool enabled = (name != cur_preset); // don't allow deleting current preset
-		mPresetCombo->add(name, ADD_BOTTOM, enabled);
-	}
-
-	postPopulate();
-}
-
-void LLFloaterDeleteEnvPreset::populateSkyPresetsList()
-{
-	if (mKey.asString() != "sky") return;
-
-	mPresetCombo->removeall();
-
-	std::string cur_preset;
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	if (!env_mgr.getUseRegionSettings() && env_mgr.getUseFixedSky())
-	{
-		cur_preset = env_mgr.getSkyPresetName();
-	}
-
-	LLWLParamManager::preset_name_list_t user_presets;
-	LLWLParamManager::instance().getUserPresetNames(user_presets);
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		const std::string& name = *it;
-		mPresetCombo->add(name, ADD_BOTTOM, /*enabled = */ name != cur_preset);
-	}
-
-	postPopulate();
-}
-
-void LLFloaterDeleteEnvPreset::populateDayCyclesList()
-{
-	if (mKey.asString() != "day_cycle") return;
-
-	mPresetCombo->removeall();
-
-	std::string cur_day;
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	if (!env_mgr.getUseRegionSettings() && env_mgr.getUseDayCycle())
-	{
-		cur_day = env_mgr.getDayCycleName();
-	}
-
-	LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
-	LLDayCycleManager::preset_name_list_t user_days;
-	day_mgr.getUserPresetNames(user_days); // list only user presets
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
-	{
-		const std::string& name = *it;
-		mPresetCombo->add(name, ADD_BOTTOM, name != cur_day);
-	}
-
-	postPopulate();
-}
-
-void LLFloaterDeleteEnvPreset::postPopulate()
-{
-	// Handle empty list and empty selection.
-	bool has_selection = mPresetCombo->getItemCount() > 0 && mPresetCombo->getSelectedValue().isDefined();
-
-	if (!has_selection)
-	{
-		mPresetCombo->setLabel(getString("combo_label"));
-	}
-
-	getChild<LLButton>("delete")->setEnabled(has_selection);
-}
-
-void LLFloaterDeleteEnvPreset::onDeleteDayCycleConfirmation()
-{
-	LLDayCycleManager::instance().deletePreset(mPresetCombo->getValue().asString());
-}
-
-void LLFloaterDeleteEnvPreset::onDeleteSkyPresetConfirmation()
-{
-	LLWLParamKey key(mPresetCombo->getValue().asString(), LLEnvKey::SCOPE_LOCAL);
-	LLWLParamManager::instance().removeParamSet(key, true);
-}
-
-void LLFloaterDeleteEnvPreset::onDeleteWaterPresetConfirmation()
-{
-	LLWaterParamManager::instance().removeParamSet(mPresetCombo->getValue().asString(), true);
-}
diff --git a/indra/newview/llfloatereditdaycycle.cpp b/indra/newview/llfloatereditdaycycle.cpp
deleted file mode 100644
index 5c0991b0b311dd6d1915dfac72c3c479c1f0413a..0000000000000000000000000000000000000000
--- a/indra/newview/llfloatereditdaycycle.cpp
+++ /dev/null
@@ -1,825 +0,0 @@
-/** 
- * @file llfloatereditdaycycle.cpp
- * @brief Floater to create or edit a day cycle
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloatereditdaycycle.h"
-
-// libs
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-#include "llcombobox.h"
-#include "llloadingindicator.h"
-#include "llmultisliderctrl.h"
-#include "llnotifications.h"
-#include "llnotificationsutil.h"
-#include "llspinctrl.h"
-#include "lltimectrl.h"
-
-// newview
-#include "llagent.h"
-#include "lldaycyclemanager.h"
-#include "llenvmanager.h"
-#include "llregioninfomodel.h"
-#include "llviewerregion.h"
-#include "llwlparammanager.h"
-
-const F32 LLFloaterEditDayCycle::sHoursPerDay = 24.0f;
-
-LLFloaterEditDayCycle::LLFloaterEditDayCycle(const LLSD &key)
-:	LLFloater(key)
-,	mDayCycleNameEditor(NULL)
-,	mDayCyclesCombo(NULL)
-,	mTimeSlider(NULL)
-,	mKeysSlider(NULL)
-,	mSkyPresetsCombo(NULL)
-,	mTimeCtrl(NULL)
-,	mMakeDefaultCheckBox(NULL)
-,	mSaveButton(NULL)
-{
-}
-
-// virtual
-BOOL LLFloaterEditDayCycle::postBuild()
-{
-	mDayCycleNameEditor = getChild<LLLineEditor>("day_cycle_name");
-	mDayCyclesCombo = getChild<LLComboBox>("day_cycle_combo");
-
-	mTimeSlider = getChild<LLMultiSliderCtrl>("WLTimeSlider");
-	mKeysSlider = getChild<LLMultiSliderCtrl>("WLDayCycleKeys");
-	mSkyPresetsCombo = getChild<LLComboBox>("WLSkyPresets");
-	mTimeCtrl = getChild<LLTimeCtrl>("time");
-	mSaveButton = getChild<LLButton>("save");
-	mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
-
-	initCallbacks();
-
-	// add the time slider
-	mTimeSlider->addSlider();
-
-	return TRUE;
-}
-
-// virtual
-void LLFloaterEditDayCycle::onOpen(const LLSD& key)
-{
-	bool new_day = isNewDay();
-	std::string param = key.asString();
-	std::string floater_title = getString(std::string("title_") + param);
-	std::string hint = getString(std::string("hint_" + param));
-
-	// Update floater title.
-	setTitle(floater_title);
-
-	// Update the hint at the top.
-	getChild<LLUICtrl>("hint")->setValue(hint);
-
-	// Hide the hint to the right of the combo if we're invoked to create a new preset.
-	getChildView("note")->setVisible(!new_day);
-
-	// Switch between the day cycle presets combobox and day cycle name input field.
-	mDayCyclesCombo->setVisible(!new_day);
-	mDayCycleNameEditor->setVisible(new_day);
-
-	// TODO: Make sure only one instance of the floater exists?
-
-	reset();
-}
-
-// virtual
-void LLFloaterEditDayCycle::onClose(bool app_quitting)
-{
-	if (!app_quitting) // there's no point to change environment if we're quitting
-	{
-		LLEnvManagerNew::instance().usePrefs(); // revert changes made to current day cycle
-	}
-}
-
-// virtual
-void LLFloaterEditDayCycle::draw()
-{
-	syncTimeSlider();
-	LLFloater::draw();
-}
-
-void LLFloaterEditDayCycle::initCallbacks(void)
-{
-	mDayCycleNameEditor->setKeystrokeCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleNameEdited, this), NULL);
-	mDayCyclesCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleSelected, this));
-	mDayCyclesCombo->setTextEntryCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleNameEdited, this));
-	mTimeSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onTimeSliderMoved, this));
-	mKeysSlider->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeMoved, this));
-	mTimeCtrl->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyTimeChanged, this));
-	mSkyPresetsCombo->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onKeyPresetChanged, this));
-
-	getChild<LLButton>("WLAddKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onAddKey, this));
-	getChild<LLButton>("WLDeleteKey")->setClickedCallback(boost::bind(&LLFloaterEditDayCycle::onDeleteKey, this));
-
-	mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnSave, this));
-	mSaveButton->setRightMouseDownCallback(boost::bind(&LLFloaterEditDayCycle::dumpTrack, this));
-	getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditDayCycle::onBtnCancel, this));
-
-	// Connect to env manager events.
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	env_mgr.setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditDayCycle::onRegionSettingsChange, this));
-	gAgent.addRegionChangedCallback(boost::bind(&LLFloaterEditDayCycle::onRegionChange, this));
-	env_mgr.setRegionSettingsAppliedCallback(boost::bind(&LLFloaterEditDayCycle::onRegionSettingsApplied, this, _1));
-
-	// Connect to day cycle manager events.
-	LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterEditDayCycle::onDayCycleListChange, this));
-
-	// Connect to sky preset list changes.
-	LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditDayCycle::onSkyPresetListChange, this));
-
-	// Connect to region info updates.
-	LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditDayCycle::onRegionInfoUpdate, this));
-}
-
-void LLFloaterEditDayCycle::syncTimeSlider()
-{
-	// set time
-	mTimeSlider->setCurSliderValue((F32)LLWLParamManager::getInstance()->mAnimator.getDayTime() * sHoursPerDay);
-}
-
-void LLFloaterEditDayCycle::loadTrack()
-{
-	// clear the slider
-	mKeysSlider->clear();
-	mSliderToKey.clear();
-
-	// add sliders
-
-	LL_DEBUGS() << "Adding " << LLWLParamManager::getInstance()->mDay.mTimeMap.size() << " keys to slider" << LL_ENDL;
-
-	LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
-	for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
-	{
-		addSliderKey(it->first * sHoursPerDay, it->second);
-	}
-
-	// set drop-down menu to match preset of currently-selected keyframe (one is automatically selected initially)
-	const std::string& cur_sldr = mKeysSlider->getCurSlider();
-	if (strlen(cur_sldr.c_str()) > 0)	// only do this if there is a curSldr, otherwise we put an invalid entry into the map
-	{
-		mSkyPresetsCombo->selectByValue(mSliderToKey[cur_sldr].keyframe.toStringVal());
-	}
-
-	syncTimeSlider();
-}
-
-void LLFloaterEditDayCycle::applyTrack()
-{
-	LL_DEBUGS() << "Applying track (" << mSliderToKey.size() << ")" << LL_ENDL;
-
-	// if no keys, do nothing
-	if (mSliderToKey.size() == 0)
-	{
-		LL_DEBUGS() << "No keys, not syncing" << LL_ENDL;
-		return;
-	}
-
-	llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
-
-	// create a new animation track
-	LLWLParamManager::getInstance()->mDay.clearKeyframes();
-
-	// add the keys one by one
-	for (std::map<std::string, SliderKey>::iterator it = mSliderToKey.begin();
-		it != mSliderToKey.end(); ++it)
-	{
-		LLWLParamManager::getInstance()->mDay.addKeyframe(it->second.time / sHoursPerDay,
-			it->second.keyframe);
-	}
-
-	// set the param manager's track to the new one
-	LLWLParamManager::getInstance()->resetAnimator(
-		mTimeSlider->getCurSliderValue() / sHoursPerDay, false);
-
-	LLWLParamManager::getInstance()->mAnimator.update(
-		LLWLParamManager::getInstance()->mCurParams);
-}
-
-void LLFloaterEditDayCycle::refreshSkyPresetsList()
-{
-	// Don't allow selecting region skies for a local day cycle,
-	// because thus we may end up with invalid day cycle.
-	bool include_region_skies = getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION;
-
-	mSkyPresetsCombo->removeall();
-
-	LLWLParamManager::preset_name_list_t region_presets;
-	LLWLParamManager::preset_name_list_t user_presets, sys_presets;
-	LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
-
-	if (include_region_skies)
-	{
-		// Add region presets.
-		for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
-		{
-			std::string preset_name = *it;
-			std::string item_title = preset_name + " (" + getRegionName() + ")";
-			mSkyPresetsCombo->add(preset_name, LLWLParamKey(*it, LLEnvKey::SCOPE_REGION).toStringVal());
-		}
-
-		if (!region_presets.empty())
-		{
-			mSkyPresetsCombo->addSeparator();
-		}
-	}
-
-	// Add user presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mSkyPresetsCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	if (!user_presets.empty())
-	{
-		mSkyPresetsCombo->addSeparator();
-	}
-
-	// Add system presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
-	{
-		mSkyPresetsCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	// set defaults on combo boxes
-	mSkyPresetsCombo->selectFirstItem();
-}
-
-void LLFloaterEditDayCycle::refreshDayCyclesList()
-{
-	llassert(isNewDay() == false);
-
-	mDayCyclesCombo->removeall();
-
-#if 0 // Disable editing existing day cycle until the workflow is clear enough.
-	const LLSD& region_day = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
-	if (region_day.size() > 0)
-	{
-		LLWLParamKey key(getRegionName(), LLEnvKey::SCOPE_REGION);
-		mDayCyclesCombo->add(key.name, key.toLLSD());
-		mDayCyclesCombo->addSeparator();
-	}
-#endif
-
-	LLDayCycleManager::preset_name_list_t user_days, sys_days;
-	LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
-
-	// Add user days.
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
-	{
-		mDayCyclesCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
-
-	if (user_days.size() > 0)
-	{
-		mDayCyclesCombo->addSeparator();
-	}
-
-	// Add system days.
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
-	{
-		mDayCyclesCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
-
-	mDayCyclesCombo->setLabel(getString("combo_label"));
-}
-
-void LLFloaterEditDayCycle::onTimeSliderMoved()
-{
-	/// get the slider value
-	F32 val = mTimeSlider->getCurSliderValue() / sHoursPerDay;
-
-	// set the value, turn off animation
-	LLWLParamManager::getInstance()->mAnimator.setDayTime((F64)val);
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
-	// then call update once
-	LLWLParamManager::getInstance()->mAnimator.update(
-		LLWLParamManager::getInstance()->mCurParams);
-}
-
-void LLFloaterEditDayCycle::onKeyTimeMoved()
-{
-	if (mKeysSlider->getValue().size() == 0)
-	{
-		return;
-	}
-
-	// make sure we have a slider
-	const std::string& cur_sldr = mKeysSlider->getCurSlider();
-	if (cur_sldr == "")
-	{
-		return;
-	}
-
-	F32 time24 = mKeysSlider->getCurSliderValue();
-
-	// check to see if a key exists
-	LLWLParamKey key = mSliderToKey[cur_sldr].keyframe;
-	LL_DEBUGS() << "Setting key time: " << time24 << LL_ENDL;
-	mSliderToKey[cur_sldr].time = time24;
-
-	// if it exists, turn on check box
-	mSkyPresetsCombo->selectByValue(key.toStringVal());
-
-	mTimeCtrl->setTime24(time24);
-
-	applyTrack();
-}
-
-void LLFloaterEditDayCycle::onKeyTimeChanged()
-{
-	// if no keys, skipped
-	if (mSliderToKey.size() == 0)
-	{
-		return;
-	}
-
-	F32 time24 = mTimeCtrl->getTime24();
-
-	const std::string& cur_sldr = mKeysSlider->getCurSlider();
-	mKeysSlider->setCurSliderValue(time24, TRUE);
-	F32 time = mKeysSlider->getCurSliderValue() / sHoursPerDay;
-
-	// now set the key's time in the sliderToKey map
-	LL_DEBUGS() << "Setting key time: " << time << LL_ENDL;
-	mSliderToKey[cur_sldr].time = time;
-
-	applyTrack();
-}
-
-void LLFloaterEditDayCycle::onKeyPresetChanged()
-{
-	// do nothing if no sliders
-	if (mKeysSlider->getValue().size() == 0)
-	{
-		return;
-	}
-
-	// change the map
-
-	std::string stringVal = mSkyPresetsCombo->getSelectedValue().asString();
-	LLWLParamKey new_key(stringVal);
-	llassert(!new_key.name.empty());
-	const std::string& cur_sldr = mKeysSlider->getCurSlider();
-
-	// if null, don't use
-	if (cur_sldr == "")
-	{
-		return;
-	}
-
-	mSliderToKey[cur_sldr].keyframe = new_key;
-
-	// Apply changes to current day cycle.
-	applyTrack();
-}
-
-void LLFloaterEditDayCycle::onAddKey()
-{
-	llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
-
-	S32 max_sliders;
-	LLEnvKey::EScope scope = LLEnvKey::SCOPE_LOCAL; // *TODO: editing region day cycle
-	switch (scope)
-	{
-		case LLEnvKey::SCOPE_LOCAL:
-			max_sliders = 20; // *HACK this should be LLWLPacketScrubber::MAX_LOCAL_KEY_FRAMES;
-			break;
-		case LLEnvKey::SCOPE_REGION:
-			max_sliders = 12; // *HACK this should be LLWLPacketScrubber::MAX_REGION_KEY_FRAMES;
-			break;
-		default:
-			max_sliders = (S32) mKeysSlider->getMaxValue();
-			break;
-	}
-
-	if ((S32)mSliderToKey.size() >= max_sliders)
-	{
-		LLSD args;
-		args["SCOPE"] = LLEnvManagerNew::getScopeString(scope);
-		args["MAX"] = max_sliders;
-		LLNotificationsUtil::add("DayCycleTooManyKeyframes", args, LLSD(), LLNotificationFunctorRegistry::instance().DONOTHING);
-		return;
-	}
-
-	// add the slider key
-	std::string key_val = mSkyPresetsCombo->getSelectedValue().asString();
-	LLWLParamKey sky_params(key_val);
-	llassert(!sky_params.name.empty());
-
-	F32 time = mTimeSlider->getCurSliderValue();
-	addSliderKey(time, sky_params);
-
-	// apply the change to current day cycles
-	applyTrack();
-}
-
-void LLFloaterEditDayCycle::addSliderKey(F32 time, LLWLParamKey keyframe)
-{
-	// make a slider
-	const std::string& sldr_name = mKeysSlider->addSlider(time);
-	if (sldr_name.empty())
-	{
-		return;
-	}
-
-	// set the key
-	SliderKey newKey(keyframe, mKeysSlider->getCurSliderValue());
-
-	llassert_always(sldr_name != LLStringUtil::null);
-
-	// add to map
-	mSliderToKey.insert(std::pair<std::string, SliderKey>(sldr_name, newKey));
-
-	llassert_always(mSliderToKey.size() == mKeysSlider->getValue().size());
-}
-
-LLWLParamKey LLFloaterEditDayCycle::getSelectedDayCycle()
-{
-	LLWLParamKey dc_key;
-
-	if (mDayCycleNameEditor->getVisible())
-	{
-		dc_key.name = mDayCycleNameEditor->getText();
-		dc_key.scope = LLEnvKey::SCOPE_LOCAL;
-	}
-	else
-	{
-		LLSD combo_val = mDayCyclesCombo->getValue();
-
-		if (!combo_val.isArray()) // manually typed text
-		{
-			dc_key.name = combo_val.asString();
-			dc_key.scope = LLEnvKey::SCOPE_LOCAL;
-		}
-		else
-		{
-			dc_key.fromLLSD(combo_val);
-		}
-	}
-
-	return dc_key;
-}
-
-bool LLFloaterEditDayCycle::isNewDay() const
-{
-	return mKey.asString() == "new";
-}
-
-void LLFloaterEditDayCycle::dumpTrack()
-{
-	LL_DEBUGS("Windlight") << "Dumping day cycle" << LL_ENDL;
-
-	LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay;
-	for (std::map<F32, LLWLParamKey>::iterator it = cur_dayp.mTimeMap.begin(); it != cur_dayp.mTimeMap.end(); ++it)
-	{
-		F32 time = it->first * 24.0f;
-		S32 h = (S32) time;
-		S32 m = (S32) ((time - h) * 60.0f);
-		LL_DEBUGS("Windlight") << llformat("(%.3f) %02d:%02d", time, h, m) << " => " << it->second.name << LL_ENDL;
-	}
-}
-
-void LLFloaterEditDayCycle::enableEditing(bool enable)
-{
-	mSkyPresetsCombo->setEnabled(enable);
-	mTimeCtrl->setEnabled(enable);
-	getChild<LLPanel>("day_cycle_slider_panel")->setCtrlsEnabled(enable);
-	mSaveButton->setEnabled(enable);
-	mMakeDefaultCheckBox->setEnabled(enable);
-}
-
-void LLFloaterEditDayCycle::reset()
-{
-	// clear the slider
-	mKeysSlider->clear();
-	mSliderToKey.clear();
-
-	refreshSkyPresetsList();
-
-	if (isNewDay())
-	{
-		mDayCycleNameEditor->setValue(LLSD());
-		F32 time = 0.5f * sHoursPerDay;
-		mSaveButton->setEnabled(FALSE); // will be enabled as soon as users enters a name
-		mTimeSlider->setCurSliderValue(time);
-
-		addSliderKey(time, LLWLParamKey("Default", LLEnvKey::SCOPE_LOCAL));
-		onKeyTimeMoved(); // update the time control and sky sky combo
-
-		applyTrack();
-	}
-	else
-	{
-		refreshDayCyclesList();
-
-		// Disable controls until a day cycle  to edit is selected.
-		enableEditing(false);
-	}
-}
-
-void LLFloaterEditDayCycle::saveRegionDayCycle()
-{
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	LLWLDayCycle& cur_dayp = LLWLParamManager::instance().mDay; // the day cycle being edited
-
-	// Get current day cycle and the sky preset it references.
-	LLSD day_cycle = cur_dayp.asLLSD();
-	LLSD sky_map;
-	cur_dayp.getSkyMap(sky_map);
-
-	// Apply it to the region.
-	LLEnvironmentSettings new_region_settings;
-	new_region_settings.saveParams(day_cycle, sky_map, env_mgr.getRegionSettings().getWaterParams(), 0.0f);
-
-#if 1
-	LLEnvManagerNew::instance().setRegionSettings(new_region_settings);
-#else // Temporary disabled ability to upload new region settings from the Day Cycle Editor.
-	if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings))
-	{
-		LL_WARNS() << "Error applying region environment settings" << LL_ENDL;
-		return;
-	}
-
-	setApplyProgress(true);
-#endif
-}
-
-void LLFloaterEditDayCycle::setApplyProgress(bool started)
-{
-	LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("progress_indicator");
-
-	indicator->setVisible(started);
-
-	if (started)
-	{
-		indicator->start();
-	}
-	else
-	{
-		indicator->stop();
-	}
-}
-
-bool LLFloaterEditDayCycle::getApplyProgress() const
-{
-	return getChild<LLLoadingIndicator>("progress_indicator")->getVisible();
-}
-
-void LLFloaterEditDayCycle::onDeleteKey()
-{
-	if (mSliderToKey.size() == 0)
-	{
-		return;
-	}
-	else if (mSliderToKey.size() == 1)
-	{
-		LLNotifications::instance().add("EnvCannotDeleteLastDayCycleKey", LLSD(), LLSD());
-		return;
-	}
-
-	// delete from map
-	const std::string& sldr_name = mKeysSlider->getCurSlider();
-	std::map<std::string, SliderKey>::iterator mIt = mSliderToKey.find(sldr_name);
-	mSliderToKey.erase(mIt);
-
-	mKeysSlider->deleteCurSlider();
-
-	if (mSliderToKey.size() == 0)
-	{
-		return;
-	}
-
-	const std::string& name = mKeysSlider->getCurSlider();
-	mSkyPresetsCombo->selectByValue(mSliderToKey[name].keyframe.toStringVal());
-	F32 time24 = mSliderToKey[name].time;
-
-	mTimeCtrl->setTime24(time24);
-
-	applyTrack();
-}
-
-void LLFloaterEditDayCycle::onRegionSettingsChange()
-{
-	LL_DEBUGS("Windlight") << "Region settings changed" << LL_ENDL;
-
-	if (getApplyProgress()) // our region settings have being applied
-	{
-		setApplyProgress(false);
-
-		// Change preference if requested.
-		if (mMakeDefaultCheckBox->getValue())
-		{
-			LL_DEBUGS("Windlight") << "Changed environment preference to region settings" << LL_ENDL;
-			LLEnvManagerNew::instance().setUseRegionSettings(true);
-		}
-
-		closeFloater();
-	}
-}
-
-void LLFloaterEditDayCycle::onRegionChange()
-{
-	LL_DEBUGS("Windlight") << "Region changed" << LL_ENDL;
-
-	// If we're editing the region day cycle
-	if (getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION)
-	{
-		reset(); // undoes all unsaved changes
-	}
-}
-
-void LLFloaterEditDayCycle::onRegionSettingsApplied(bool success)
-{
-	LL_DEBUGS("Windlight") << "Region settings applied: " << success << LL_ENDL;
-
-	if (!success)
-	{
-		// stop progress indicator
-		setApplyProgress(false);
-	}
-}
-
-void LLFloaterEditDayCycle::onRegionInfoUpdate()
-{
-	LL_DEBUGS("Windlight") << "Region info updated" << LL_ENDL;
-	bool can_edit = true;
-
-	// If we've selected the region day cycle for editing.
-	if (getSelectedDayCycle().scope == LLEnvKey::SCOPE_REGION)
-	{
-		// check whether we have the access
-		can_edit = LLEnvManagerNew::canEditRegionSettings();
-	}
-
-	enableEditing(can_edit);
-}
-
-void LLFloaterEditDayCycle::onDayCycleNameEdited()
-{
-	// Disable saving a day cycle having empty name.
-	LLWLParamKey key = getSelectedDayCycle();
-	mSaveButton->setEnabled(!key.name.empty());
-}
-
-void LLFloaterEditDayCycle::onDayCycleSelected()
-{
-	LLSD day_data;
-	LLWLParamKey dc_key = getSelectedDayCycle();
-	bool can_edit = true;
-
-	if (dc_key.scope == LLEnvKey::SCOPE_LOCAL)
-	{
-		if (!LLDayCycleManager::instance().getPreset(dc_key.name, day_data))
-		{
-			LL_WARNS() << "No day cycle named " << dc_key.name << LL_ENDL;
-			return;
-		}
-	}
-	else
-	{
-		day_data = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
-		if (day_data.size() == 0)
-		{
-			LL_WARNS() << "Empty region day cycle" << LL_ENDL;
-			llassert(day_data.size() > 0);
-			return;
-		}
-
-		can_edit = LLEnvManagerNew::canEditRegionSettings();
-	}
-
-	// We may need to add or remove region skies from the list.
-	refreshSkyPresetsList();
-
-	F32 slider_time = mTimeSlider->getCurSliderValue() / sHoursPerDay;
-	LLWLParamManager::instance().applyDayCycleParams(day_data, dc_key.scope, slider_time);
-	loadTrack();
-
-	enableEditing(can_edit);
-}
-
-void LLFloaterEditDayCycle::onBtnSave()
-{
-	LLDayCycleManager& day_mgr = LLDayCycleManager::instance();
-	LLWLParamKey selected_day = getSelectedDayCycle();
-
-	if (selected_day.scope == LLEnvKey::SCOPE_REGION)
-	{
-		saveRegionDayCycle();
-		closeFloater();
-		return;
-	}
-
-	std::string name = selected_day.name;
-	if (name.empty())
-	{
-		// *TODO: show an alert
-		LL_WARNS() << "Empty day cycle name" << LL_ENDL;
-		return;
-	}
-
-	// Don't allow overwriting system presets.
-	if (day_mgr.isSystemPreset(name))
-	{
-		LLNotificationsUtil::add("WLNoEditDefault");
-		return;
-	}
-
-	// Save, ask for confirmation for overwriting an existing preset.
-	if (day_mgr.presetExists(name))
-	{
-		LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditDayCycle::onSaveAnswer, this, _1, _2));
-	}
-	else
-	{
-		// new preset, hence no confirmation needed
-		onSaveConfirmed();
-	}
-}
-
-void LLFloaterEditDayCycle::onBtnCancel()
-{
-	closeFloater();
-}
-
-bool LLFloaterEditDayCycle::onSaveAnswer(const LLSD& notification, const LLSD& response)
-{
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
-
-	// If they choose save, do it.  Otherwise, don't do anything
-	if (option == 0)
-	{
-		onSaveConfirmed();
-	}
-
-	return false;
-}
-
-void LLFloaterEditDayCycle::onSaveConfirmed()
-{
-	std::string name = getSelectedDayCycle().name;
-
-	// Save preset.
-	LLSD data = LLWLParamManager::instance().mDay.asLLSD();
-	LL_DEBUGS("Windlight") << "Saving day cycle " << name << ": " << data << LL_ENDL;
-	LLDayCycleManager::instance().savePreset(name, data);
-
-	// Change preference if requested.
-	if (mMakeDefaultCheckBox->getValue())
-	{
-		LL_DEBUGS("Windlight") << name << " is now the new preferred day cycle" << LL_ENDL;
-		LLEnvManagerNew::instance().setUseDayCycle(name);
-	}
-
-	closeFloater();
-}
-
-void LLFloaterEditDayCycle::onDayCycleListChange()
-{
-	if (!isNewDay())
-	{
-		refreshDayCyclesList();
-	}
-}
-
-void LLFloaterEditDayCycle::onSkyPresetListChange()
-{
-	refreshSkyPresetsList();
-
-	// Refresh sliders from the currently visible day cycle.
-	loadTrack();
-}
-
-// static
-std::string LLFloaterEditDayCycle::getRegionName()
-{
-	return gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
-}
diff --git a/indra/newview/llfloatereditdaycycle.h b/indra/newview/llfloatereditdaycycle.h
deleted file mode 100644
index e6e4fe39c1e80ca6de114c840d977492521609b5..0000000000000000000000000000000000000000
--- a/indra/newview/llfloatereditdaycycle.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/** 
- * @file llfloatereditdaycycle.h
- * @brief Floater to create or edit a day cycle
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLFLOATEREDITDAYCYCLE_H
-#define LL_LLFLOATEREDITDAYCYCLE_H
-
-#include "llfloater.h"
-
-#include "llwlparammanager.h" // for LLWLParamKey
-
-class LLCheckBoxCtrl;
-class LLComboBox;
-class LLLineEditor;
-class LLMultiSliderCtrl;
-class LLTimeCtrl;
-
-/**
- * Floater for creating or editing a day cycle.
- */
-class LLFloaterEditDayCycle : public LLFloater
-{
-	LOG_CLASS(LLFloaterEditDayCycle);
-
-public:
-	LLFloaterEditDayCycle(const LLSD &key);
-
-	/*virtual*/	BOOL	postBuild();
-	/*virtual*/ void	onOpen(const LLSD& key);
-	/*virtual*/ void	onClose(bool app_quitting);
-	/*virtual*/ void	draw();
-
-private:
-
-	/// sync the time slider with day cycle structure
-	void syncTimeSlider();
-
-	// 	makes sure key slider has what's in day cycle
-	void loadTrack();
-
-	/// makes sure day cycle data structure has what's in menu
-	void applyTrack();
-
-	/// refresh the sky presets combobox
-	void refreshSkyPresetsList();
-
-	/// refresh the day cycle combobox
-	void refreshDayCyclesList();
-
-	/// add a slider to the track
-	void addSliderKey(F32 time, LLWLParamKey keyframe);
-
-	void initCallbacks();
-	LLWLParamKey getSelectedDayCycle();
-	bool isNewDay() const;
-	void dumpTrack();
-	void enableEditing(bool enable);
-	void reset();
-	void saveRegionDayCycle();
-
-	void setApplyProgress(bool started);
-	bool getApplyProgress() const;
-
-	void onTimeSliderMoved();	/// time slider moved
-	void onKeyTimeMoved();		/// a key frame moved
-	void onKeyTimeChanged();	/// a key frame's time changed
-	void onKeyPresetChanged();	/// sky preset selected
-	void onAddKey();			/// new key added on slider
-	void onDeleteKey();			/// a key frame deleted
-
-	void onRegionSettingsChange();
-	void onRegionChange();
-	void onRegionSettingsApplied(bool success);
-	void onRegionInfoUpdate();
-
-	void onDayCycleNameEdited();
-	void onDayCycleSelected();
-	void onBtnSave();
-	void onBtnCancel();
-
-	bool onSaveAnswer(const LLSD& notification, const LLSD& response);
-	void onSaveConfirmed();
-
-	void onDayCycleListChange();
-	void onSkyPresetListChange();
-
-	static std::string getRegionName();
-
-	/// convenience class for holding keyframes mapped to sliders
-	struct SliderKey
-	{
-	public:
-		SliderKey(LLWLParamKey kf, F32 t) : keyframe(kf), time(t) {}
-		SliderKey() : keyframe(), time(0.f) {} // Don't use this default constructor
-
-		LLWLParamKey keyframe;
-		F32 time;
-	};
-
-	static const F32 sHoursPerDay;
-
-	LLLineEditor*		mDayCycleNameEditor;
-	LLComboBox*			mDayCyclesCombo;
-	LLMultiSliderCtrl*	mTimeSlider;
-	LLMultiSliderCtrl*	mKeysSlider;
-	LLComboBox*			mSkyPresetsCombo;
-	LLTimeCtrl*			mTimeCtrl;
-	LLCheckBoxCtrl*		mMakeDefaultCheckBox;
-	LLButton*			mSaveButton;
-
-	// map of sliders to parameters
-	std::map<std::string, SliderKey> mSliderToKey;
-};
-
-#endif // LL_LLFLOATEREDITDAYCYCLE_H
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ea22043de88a567dccdc38c440a595f7b041eff2
--- /dev/null
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -0,0 +1,2155 @@
+/** 
+ * @file llfloatereditextdaycycle.cpp
+ * @brief Floater to create or edit a day cycle
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatereditextdaycycle.h"
+
+// libs
+#include "llbutton.h"
+#include "llcallbacklist.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llloadingindicator.h"
+#include "lllocalbitmaps.h"
+#include "llmultisliderctrl.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llspinctrl.h"
+#include "lltimectrl.h"
+#include "lltabcontainer.h"
+#include "llfilepicker.h"
+
+#include "llsettingsvo.h"
+#include "llinventorymodel.h"
+#include "llviewerparcelmgr.h"
+
+#include "llsettingspicker.h"
+#include "lltrackpicker.h"
+
+// newview
+#include "llagent.h"
+#include "llappviewer.h" //gDisconected
+#include "llparcel.h"
+#include "llflyoutcombobtn.h" //Todo: make a proper UI element/button/panel instead
+#include "llregioninfomodel.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
+#include "llviewerregion.h"
+#include "llpaneleditwater.h"
+#include "llpaneleditsky.h"
+
+#include "llui.h"
+
+#include "llenvironment.h"
+#include "lltrans.h"
+
+extern LLControlGroup gSavedSettings;
+
+//=========================================================================
+namespace {
+    const std::string track_tabs[] = {
+        "water_track",
+        "sky1_track",
+        "sky2_track",
+        "sky3_track",
+        "sky4_track",
+    };
+
+    const std::string ICN_LOCK_EDIT("icn_lock_edit");
+    const std::string BTN_SAVE("save_btn");
+    const std::string BTN_FLYOUT("btn_flyout");
+    const std::string BTN_CANCEL("cancel_btn");
+    const std::string BTN_ADDFRAME("add_frame");
+    const std::string BTN_DELFRAME("delete_frame");
+    const std::string BTN_IMPORT("btn_import");
+    const std::string BTN_LOADFRAME("btn_load_frame");
+    const std::string BTN_CLONETRACK("copy_track");
+    const std::string BTN_LOADTRACK("load_track");
+    const std::string BTN_CLEARTRACK("clear_track");
+    const std::string SLDR_TIME("WLTimeSlider");
+    const std::string SLDR_KEYFRAMES("WLDayCycleFrames");
+    const std::string VIEW_SKY_SETTINGS("frame_settings_sky");
+    const std::string VIEW_WATER_SETTINGS("frame_settings_water");
+    const std::string LBL_CURRENT_TIME("current_time");
+    const std::string TXT_DAY_NAME("day_cycle_name");
+    const std::string TABS_SKYS("sky_tabs");
+    const std::string TABS_WATER("water_tabs");
+
+    const std::string EVNT_DAYTRACK("DayCycle.Track");
+    const std::string EVNT_PLAY("DayCycle.PlayActions");
+
+    const std::string ACTION_PLAY("play");
+    const std::string ACTION_PAUSE("pause");
+    const std::string ACTION_FORWARD("forward");
+    const std::string ACTION_BACK("back");
+
+    // For flyout
+    const std::string XML_FLYOUTMENU_FILE("menu_save_settings.xml");
+    // From menu_save_settings.xml, consider moving into flyout since it should be supported by flyout either way
+    const std::string ACTION_SAVE("save_settings");
+    const std::string ACTION_SAVEAS("save_as_new_settings");
+    const std::string ACTION_COMMIT("commit_changes");
+    const std::string ACTION_APPLY_LOCAL("apply_local");
+    const std::string ACTION_APPLY_PARCEL("apply_parcel");
+    const std::string ACTION_APPLY_REGION("apply_region");
+
+    const F32 DAY_CYCLE_PLAY_TIME_SECONDS = 60;
+
+    const std::string STR_COMMIT_PARCEL("commit_parcel");
+    const std::string STR_COMMIT_REGION("commit_region");
+    //---------------------------------------------------------------------
+
+}
+
+//=========================================================================
+const std::string LLFloaterEditExtDayCycle::KEY_INVENTORY_ID("inventory_id");
+const std::string LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT("edit_context");
+const std::string LLFloaterEditExtDayCycle::KEY_DAY_LENGTH("day_length");
+const std::string LLFloaterEditExtDayCycle::KEY_CANMOD("canmod");
+
+const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_INVENTORY("inventory");
+const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_PARCEL("parcel");
+const std::string LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION("region");
+
+//=========================================================================
+
+class LLDaySettingCopiedCallback : public LLInventoryCallback
+{
+public:
+    LLDaySettingCopiedCallback(LLHandle<LLFloater> handle) : mHandle(handle) {}
+
+    virtual void fire(const LLUUID& inv_item_id)
+    {
+        if (!mHandle.isDead())
+        {
+            LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+            if (item)
+            {
+                LLFloaterEditExtDayCycle* floater = (LLFloaterEditExtDayCycle*)mHandle.get();
+                floater->onInventoryCreated(item->getAssetUUID(), inv_item_id);
+            }
+        }
+    }
+
+private:
+    LLHandle<LLFloater> mHandle;
+};
+
+//=========================================================================
+
+LLFloaterEditExtDayCycle::LLFloaterEditExtDayCycle(const LLSD &key) :
+    LLFloater(key),
+    mFlyoutControl(nullptr),
+    mDayLength(0),
+    mCurrentTrack(1),
+    mShiftCopyEnabled(false),
+    mTimeSlider(nullptr),
+    mFramesSlider(nullptr),
+    mCurrentTimeLabel(nullptr),
+    mImportButton(nullptr),
+    mInventoryId(),
+    mInventoryItem(nullptr),
+    mLoadFrame(nullptr),
+    mSkyBlender(),
+    mWaterBlender(),
+    mScratchSky(),
+    mScratchWater(),
+    mIsPlaying(false),
+    mIsDirty(false),
+    mCanSave(false),
+    mCanCopy(false),
+    mCanMod(false),
+    mCanTrans(false),
+    mCloneTrack(nullptr),
+    mLoadTrack(nullptr),
+    mClearTrack(nullptr)
+{
+
+    mCommitCallbackRegistrar.add(EVNT_DAYTRACK, [this](LLUICtrl *ctrl, const LLSD &data) { onTrackSelectionCallback(data); });
+    mCommitCallbackRegistrar.add(EVNT_PLAY, [this](LLUICtrl *ctrl, const LLSD &data) { onPlayActionCallback(data); });
+
+    mScratchSky = LLSettingsVOSky::buildDefaultSky();
+    mScratchWater = LLSettingsVOWater::buildDefaultWater();
+
+    mEditSky = mScratchSky;
+    mEditWater = mScratchWater;
+}
+
+LLFloaterEditExtDayCycle::~LLFloaterEditExtDayCycle()
+{
+    // Todo: consider remaking mFlyoutControl into full view class that initializes intself with floater,
+    // complete with postbuild, e t c...
+    delete mFlyoutControl;
+}
+
+// virtual
+BOOL LLFloaterEditExtDayCycle::postBuild()
+{
+    getChild<LLLineEditor>(TXT_DAY_NAME)->setKeystrokeCallback(boost::bind(&LLFloaterEditExtDayCycle::onCommitName, this, _1, _2), NULL);
+
+    mAddFrameButton = getChild<LLButton>(BTN_ADDFRAME, true);
+    mDeleteFrameButton = getChild<LLButton>(BTN_DELFRAME, true);
+    mTimeSlider = getChild<LLMultiSliderCtrl>(SLDR_TIME);
+    mFramesSlider = getChild<LLMultiSliderCtrl>(SLDR_KEYFRAMES);
+    mSkyTabLayoutContainer = getChild<LLView>(VIEW_SKY_SETTINGS, true);
+    mWaterTabLayoutContainer = getChild<LLView>(VIEW_WATER_SETTINGS, true);
+    mCurrentTimeLabel = getChild<LLTextBox>(LBL_CURRENT_TIME, true);
+    mImportButton = getChild<LLButton>(BTN_IMPORT, true);
+    mLoadFrame = getChild<LLButton>(BTN_LOADFRAME, true);
+    mCloneTrack = getChild<LLButton>(BTN_CLONETRACK, true);
+    mLoadTrack = getChild<LLButton>(BTN_LOADTRACK, true);
+    mClearTrack = getChild<LLButton>(BTN_CLEARTRACK, true);
+
+    mFlyoutControl = new LLFlyoutComboBtnCtrl(this, BTN_SAVE, BTN_FLYOUT, XML_FLYOUTMENU_FILE, false);
+    mFlyoutControl->setAction([this](LLUICtrl *ctrl, const LLSD &data) { onButtonApply(ctrl, data); });
+
+    getChild<LLButton>(BTN_CANCEL, true)->setCommitCallback([this](LLUICtrl *ctrl, const LLSD &data) { onClickCloseBtn(); });
+    mTimeSlider->setCommitCallback([this](LLUICtrl *ctrl, const LLSD &data) { onTimeSliderCallback(); });
+    mAddFrameButton->setCommitCallback([this](LLUICtrl *ctrl, const LLSD &data) { onAddFrame(); });
+    mDeleteFrameButton->setCommitCallback([this](LLUICtrl *ctrl, const LLSD &data) { onRemoveFrame(); });
+    mImportButton->setCommitCallback([this](LLUICtrl *, const LLSD &){ onButtonImport(); });
+    mLoadFrame->setCommitCallback([this](LLUICtrl *, const LLSD &){ onButtonLoadFrame(); });
+
+    mCloneTrack->setCommitCallback([this](LLUICtrl *, const LLSD&){ onCloneTrack(); });
+    mLoadTrack->setCommitCallback([this](LLUICtrl *, const LLSD&){  onLoadTrack();});
+    mClearTrack->setCommitCallback([this](LLUICtrl *, const LLSD&){ onClearTrack(); });
+
+
+    mFramesSlider->setCommitCallback([this](LLUICtrl *, const LLSD &data) { onFrameSliderCallback(data); });
+    mFramesSlider->setDoubleClickCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask){ onFrameSliderDoubleClick(x, y, mask); });
+    mFramesSlider->setMouseDownCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask){ onFrameSliderMouseDown(x, y, mask); });
+    mFramesSlider->setMouseUpCallback([this](LLUICtrl*, S32 x, S32 y, MASK mask){ onFrameSliderMouseUp(x, y, mask); });
+
+    mTimeSlider->addSlider(0);
+
+    LLTabContainer* tab_container = mSkyTabLayoutContainer->getChild<LLTabContainer>("sky_tabs"); 
+    S32 tab_count = tab_container->getTabCount();
+
+    LLSettingsEditPanel *panel = nullptr;
+    
+    for (S32 idx = 0; idx < tab_count; ++idx)
+    {
+        panel = static_cast<LLSettingsEditPanel *>(tab_container->getPanelByIndex(idx));
+        if (panel)
+            panel->setOnDirtyFlagChanged([this](LLPanel *, bool val) { onPanelDirtyFlagChanged(val); });
+    }
+
+    tab_container = mWaterTabLayoutContainer->getChild<LLTabContainer>("water_tabs");
+    tab_count = tab_container->getTabCount();
+
+    for (S32 idx = 0; idx < tab_count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(tab_container->getPanelByIndex(idx));
+        if (panel)
+            panel->setOnDirtyFlagChanged([this](LLPanel *, bool val) { onPanelDirtyFlagChanged(val); });
+    }
+
+	return TRUE;
+}
+
+void LLFloaterEditExtDayCycle::onOpen(const LLSD& key)
+{
+    if (!mEditDay)
+    {
+        LLEnvironment::instance().saveBeaconsState();
+    }
+    mEditDay.reset();
+    mEditContext = CONTEXT_UNKNOWN;
+    if (key.has(KEY_EDIT_CONTEXT))
+    {
+        std::string context = key[KEY_EDIT_CONTEXT].asString();
+
+        if (context == VALUE_CONTEXT_INVENTORY)
+            mEditContext = CONTEXT_INVENTORY;
+        else if (context == VALUE_CONTEXT_PARCEL)
+            mEditContext = CONTEXT_PARCEL;
+        else if (context == VALUE_CONTEXT_REGION)
+            mEditContext = CONTEXT_REGION;
+    }
+
+    if (key.has(KEY_CANMOD))
+    {
+        mCanMod = key[KEY_CANMOD].asBoolean();
+    }
+
+    if (mEditContext == CONTEXT_UNKNOWN)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Unknown editing context!" << LL_ENDL;
+    }
+
+    if (key.has(KEY_INVENTORY_ID))
+    {
+        loadInventoryItem(key[KEY_INVENTORY_ID].asUUID());
+    }
+    else
+    {
+        mCanSave = true;
+        mCanCopy = true;
+        mCanMod = true;
+        mCanTrans = true;
+        setEditDefaultDayCycle();
+    }
+
+    mDayLength.value(0);
+    if (key.has(KEY_DAY_LENGTH))
+    {
+        mDayLength.value(key[KEY_DAY_LENGTH].asReal());
+    }
+
+    // Time&Percentage labels
+    mCurrentTimeLabel->setTextArg("[PRCNT]", std::string("0"));
+    const S32 max_elm = 5;
+    if (mDayLength.value() != 0)
+    {
+        S32Hours hrs;
+        S32Minutes minutes;
+        LLSettingsDay::Seconds total;
+        LLUIString formatted_label = getString("time_label");
+        for (int i = 0; i < max_elm; i++)
+        {
+            total = ((mDayLength / (max_elm - 1)) * i); 
+            hrs = total;
+            minutes = total - hrs;
+
+            formatted_label.setArg("[HH]", llformat("%d", hrs.value()));
+            formatted_label.setArg("[MM]", llformat("%d", abs(minutes.value())));
+            getChild<LLTextBox>("p" + llformat("%d", i), true)->setTextArg("[DSC]", formatted_label.getString());
+        }
+        hrs = mDayLength;
+        minutes = mDayLength - hrs;
+        formatted_label.setArg("[HH]", llformat("%d", hrs.value()));
+        formatted_label.setArg("[MM]", llformat("%d", abs(minutes.value())));
+        mCurrentTimeLabel->setTextArg("[DSC]", formatted_label.getString());
+    }
+    else
+    {
+        for (int i = 0; i < max_elm; i++)
+        {
+            getChild<LLTextBox>("p" + llformat("%d", i), true)->setTextArg("[DSC]", std::string());
+        }
+        mCurrentTimeLabel->setTextArg("[DSC]", std::string());
+    }
+
+    // Adjust Time&Percentage labels' location according to length
+    LLRect label_rect = getChild<LLTextBox>("p0", true)->getRect();
+    F32 slider_width = mFramesSlider->getRect().getWidth();
+    for (int i = 1; i < max_elm; i++)
+    {
+        LLTextBox *pcnt_label = getChild<LLTextBox>("p" + llformat("%d", i), true);
+        LLRect new_rect = pcnt_label->getRect();
+        new_rect.mLeft = label_rect.mLeft + (S32)(slider_width * (F32)i / (F32)(max_elm - 1)) - (S32)(pcnt_label->getTextPixelWidth() / 2);
+        pcnt_label->setRect(new_rect);
+    }
+
+    // Altitudes&Track labels
+    LLUIString formatted_label = getString("sky_track_label");
+    const LLEnvironment::altitude_list_t &altitudes = LLEnvironment::instance().getRegionAltitudes();
+    bool extended_env = LLEnvironment::instance().isExtendedEnvironmentEnabled();
+    bool use_altitudes = extended_env
+                         && altitudes.size() > 0
+                         && ((mEditContext == CONTEXT_PARCEL) || (mEditContext == CONTEXT_REGION));
+    for (S32 idx = 1; idx < 4; ++idx)
+    {
+        std::ostringstream convert;
+        if (use_altitudes)
+        {
+            convert << altitudes[idx] << "m";
+        }
+        else
+        {
+            convert << (idx + 1);
+        }
+        formatted_label.setArg("[ALT]", convert.str());
+        getChild<LLButton>(track_tabs[idx + 1], true)->setLabel(formatted_label.getString());
+    }
+
+    for (U32 i = 2; i < LLSettingsDay::TRACK_MAX; i++) //skies #2 through #4
+    {
+        getChild<LLButton>(track_tabs[i])->setEnabled(extended_env);
+    }
+
+    if (mEditContext == CONTEXT_INVENTORY)
+    {
+        mFlyoutControl->setShownBtnEnabled(true);
+        mFlyoutControl->setSelectedItem(ACTION_SAVE);
+    }
+    else if ((mEditContext == CONTEXT_REGION) || (mEditContext == CONTEXT_PARCEL))
+    {
+        std::string commit_str = (mEditContext == CONTEXT_PARCEL) ? STR_COMMIT_PARCEL : STR_COMMIT_REGION;
+        mFlyoutControl->setMenuItemLabel(ACTION_COMMIT, getString(commit_str));
+        mFlyoutControl->setShownBtnEnabled(true);
+        mFlyoutControl->setSelectedItem(ACTION_COMMIT);
+    }
+    else
+    {
+        mFlyoutControl->setShownBtnEnabled(false);
+    }
+}
+
+void LLFloaterEditExtDayCycle::onClose(bool app_quitting)
+{
+    doCloseInventoryFloater(app_quitting);
+    doCloseTrackFloater(app_quitting);
+    // there's no point to change environment if we're quitting
+    // or if we already restored environment
+    stopPlay();
+    LLEnvironment::instance().revertBeaconsState();
+    if (!app_quitting)
+    {
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::TRANSITION_FAST);
+        LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
+        mEditDay.reset();
+    }
+}
+
+void LLFloaterEditExtDayCycle::onFocusReceived()
+{
+    if (isInVisibleChain())
+    {
+        updateEditEnvironment();
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+    }
+}
+
+void LLFloaterEditExtDayCycle::onFocusLost()
+{
+}
+
+
+void LLFloaterEditExtDayCycle::onVisibilityChange(BOOL new_visibility)
+{
+}
+
+void LLFloaterEditExtDayCycle::refresh()
+{
+    if (mEditDay)
+    {
+        LLLineEditor* name_field = getChild<LLLineEditor>(TXT_DAY_NAME);
+        name_field->setText(mEditDay->getName());
+        name_field->setEnabled(mCanMod);
+    }
+
+
+    bool is_inventory_avail = canUseInventory();
+
+    bool show_commit = ((mEditContext == CONTEXT_PARCEL) || (mEditContext == CONTEXT_REGION));
+    bool show_apply = (mEditContext == CONTEXT_INVENTORY);
+
+    if (show_commit)
+    {
+        std::string commit_text;
+        if (mEditContext == CONTEXT_PARCEL)
+            commit_text = getString(STR_COMMIT_PARCEL);
+        else
+            commit_text = getString(STR_COMMIT_REGION);
+
+        mFlyoutControl->setMenuItemLabel(ACTION_COMMIT, commit_text);
+    }
+
+    mFlyoutControl->setMenuItemVisible(ACTION_COMMIT, show_commit);
+    mFlyoutControl->setMenuItemVisible(ACTION_SAVE, is_inventory_avail);
+    mFlyoutControl->setMenuItemVisible(ACTION_SAVEAS, is_inventory_avail);
+    mFlyoutControl->setMenuItemVisible(ACTION_APPLY_LOCAL, true);
+    mFlyoutControl->setMenuItemVisible(ACTION_APPLY_PARCEL, show_apply);
+    mFlyoutControl->setMenuItemVisible(ACTION_APPLY_REGION, show_apply);
+
+    mFlyoutControl->setMenuItemEnabled(ACTION_COMMIT, show_commit && !mCommitSignal.empty());
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVE, is_inventory_avail && mCanMod && !mInventoryId.isNull() && mCanSave);
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVEAS, is_inventory_avail && mCanCopy && mCanSave);
+    mFlyoutControl->setMenuItemEnabled(ACTION_APPLY_LOCAL, true);
+    mFlyoutControl->setMenuItemEnabled(ACTION_APPLY_PARCEL, canApplyParcel() && show_apply);
+    mFlyoutControl->setMenuItemEnabled(ACTION_APPLY_REGION, canApplyRegion() && show_apply);
+
+    mImportButton->setEnabled(mCanMod);
+
+    LLFloater::refresh();
+}
+
+
+void LLFloaterEditExtDayCycle::setEditDayCycle(const LLSettingsDay::ptr_t &pday)
+{
+    mExpectingAssetId.setNull();
+    mEditDay = pday->buildDeepCloneAndUncompress();
+
+    if (mEditDay->isTrackEmpty(LLSettingsDay::TRACK_WATER))
+    {
+        LL_WARNS("ENVDAYEDIT") << "No water frames found, generating replacement" << LL_ENDL;
+        mEditDay->setWaterAtKeyframe(LLSettingsVOWater::buildDefaultWater(), .5f);
+    }
+
+    if (mEditDay->isTrackEmpty(LLSettingsDay::TRACK_GROUND_LEVEL))
+    {
+        LL_WARNS("ENVDAYEDIT") << "No sky frames found, generating replacement" << LL_ENDL;
+        mEditDay->setSkyAtKeyframe(LLSettingsVOSky::buildDefaultSky(), .5f, LLSettingsDay::TRACK_GROUND_LEVEL);
+    }
+
+    mCanSave = !pday->getFlag(LLSettingsBase::FLAG_NOSAVE);
+    mCanCopy = !pday->getFlag(LLSettingsBase::FLAG_NOCOPY) && mCanSave;
+    mCanMod = !pday->getFlag(LLSettingsBase::FLAG_NOMOD) && mCanSave;
+    mCanTrans = !pday->getFlag(LLSettingsBase::FLAG_NOTRANS) && mCanSave;
+
+    updateEditEnvironment();
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+    synchronizeTabs();
+    updateTabs();
+    refresh();
+}
+
+
+void LLFloaterEditExtDayCycle::setEditDefaultDayCycle()
+{
+    mInventoryItem = nullptr;
+    mInventoryId.setNull();
+    mExpectingAssetId = LLSettingsDay::GetDefaultAssetId();
+    LLSettingsVOBase::getSettingsAsset(LLSettingsDay::GetDefaultAssetId(),
+        [this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
+}
+
+std::string LLFloaterEditExtDayCycle::getEditName() const
+{
+    if (mEditDay)
+        return mEditDay->getName();
+    return "new";
+}
+
+void LLFloaterEditExtDayCycle::setEditName(const std::string &name)
+{
+    if (mEditDay)
+        mEditDay->setName(name);
+    getChild<LLLineEditor>(TXT_DAY_NAME)->setText(name);
+}
+
+/* virtual */
+BOOL LLFloaterEditExtDayCycle::handleKeyUp(KEY key, MASK mask, BOOL called_from_parent)
+{
+    if (!mEditDay)
+    {
+        mShiftCopyEnabled = false;
+    }
+    else if (mask == MASK_SHIFT && mShiftCopyEnabled)
+    {
+        mShiftCopyEnabled = false;
+        std::string curslider = mFramesSlider->getCurSlider();
+        if (!curslider.empty())
+        {
+            F32 sliderpos = mFramesSlider->getCurSliderValue();
+
+            keymap_t::iterator it = mSliderKeyMap.find(curslider);
+            if (it != mSliderKeyMap.end())
+            {
+                if (mEditDay->moveTrackKeyframe(mCurrentTrack, (*it).second.mFrame, sliderpos))
+                {
+                    (*it).second.mFrame = sliderpos;
+                }
+                else
+                {
+                    mFramesSlider->setCurSliderValue((*it).second.mFrame);
+                }
+            }
+            else
+            {
+                LL_WARNS("ENVDAYEDIT") << "Failed to find frame " << sliderpos << " for slider " << curslider << LL_ENDL;
+            }
+        }
+    }
+    return LLFloater::handleKeyUp(key, mask, called_from_parent);
+}
+
+void LLFloaterEditExtDayCycle::onButtonApply(LLUICtrl *ctrl, const LLSD &data)
+{
+    std::string ctrl_action = ctrl->getName();
+
+    if (!mEditDay)
+    {
+        LL_WARNS("ENVDAYEDIT") << "mEditDay is null! This should never happen! Something is very very wrong" << LL_ENDL;
+        LLNotificationsUtil::add("EnvironmentApplyFailed");
+        closeFloater();
+        return;
+    }
+
+    LLSettingsDay::ptr_t dayclone = mEditDay->buildClone(); // create a compressed copy
+
+    if (!dayclone)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Unable to clone daycylce from editor." << LL_ENDL;
+        return;
+    }
+
+    // brute-force local texture scan
+    for (U32 i = 0; i <= LLSettingsDay::TRACK_MAX; i++)
+    {
+        LLSettingsDay::CycleTrack_t &day_track = dayclone->getCycleTrack(i);
+
+        LLSettingsDay::CycleTrack_t::iterator iter = day_track.begin();
+        LLSettingsDay::CycleTrack_t::iterator end = day_track.end();
+        S32 frame_num = 0;
+
+        while (iter != end)
+        {
+            frame_num++;
+            std::string desc;
+            bool is_local = false; // because getString can be empty
+            if (i == LLSettingsDay::TRACK_WATER)
+            {
+                LLSettingsWater::ptr_t water = std::static_pointer_cast<LLSettingsWater>(iter->second);
+                if (water)
+                {
+                    // LLViewerFetchedTexture and check for FTT_LOCAL_FILE or check LLLocalBitmapMgr
+                    if (LLLocalBitmapMgr::getInstance()->isLocal(water->getNormalMapID()))
+                    {
+                        desc = LLTrans::getString("EnvironmentNormalMap");
+                        is_local = true;
+                    }
+                    else if (LLLocalBitmapMgr::getInstance()->isLocal(water->getTransparentTextureID()))
+                    {
+                        desc = LLTrans::getString("EnvironmentTransparent");
+                        is_local = true;
+                    }
+                }
+            }
+            else
+            {
+                LLSettingsSky::ptr_t sky = std::static_pointer_cast<LLSettingsSky>(iter->second);
+                if (sky)
+                {
+                    if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getSunTextureId()))
+                    {
+                        desc = LLTrans::getString("EnvironmentSun");
+                        is_local = true;
+                    }
+                    else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getMoonTextureId()))
+                    {
+                        desc = LLTrans::getString("EnvironmentMoon");
+                        is_local = true;
+                    }
+                    else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getCloudNoiseTextureId()))
+                    {
+                        desc = LLTrans::getString("EnvironmentCloudNoise");
+                        is_local = true;
+                    }
+                    else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getBloomTextureId()))
+                    {
+                        desc = LLTrans::getString("EnvironmentBloom");
+                        is_local = true;
+                    }
+                }
+            }
+
+            if (is_local)
+            {
+                LLSD args;
+                LLButton* button = getChild<LLButton>(track_tabs[i], true);
+                args["TRACK"] = button->getCurrentLabel();
+                args["FRAME"] = iter->first * 100; // %
+                args["FIELD"] = desc;
+                args["FRAMENO"] = frame_num;
+                LLNotificationsUtil::add("WLLocalTextureDayBlock", args);
+                return;
+            }
+            iter++;
+        }
+    }
+
+    if (ctrl_action == ACTION_SAVE)
+    {
+        doApplyUpdateInventory(dayclone);
+    }
+    else if (ctrl_action == ACTION_SAVEAS)
+    {
+        LLSD args;
+        args["DESC"] = dayclone->getName();
+        LLNotificationsUtil::add("SaveSettingAs", args, LLSD(), boost::bind(&LLFloaterEditExtDayCycle::onSaveAsCommit, this, _1, _2, dayclone));
+    }
+    else if ((ctrl_action == ACTION_APPLY_LOCAL) ||
+        (ctrl_action == ACTION_APPLY_PARCEL) ||
+        (ctrl_action == ACTION_APPLY_REGION))
+    {
+        doApplyEnvironment(ctrl_action, dayclone);
+    }
+    else if (ctrl_action == ACTION_COMMIT)
+    {
+        doApplyCommit(dayclone);
+    }
+    else
+    {
+        LL_WARNS("ENVDAYEDIT") << "Unknown settings action '" << ctrl_action << "'" << LL_ENDL;
+    }
+}
+
+void LLFloaterEditExtDayCycle::onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsDay::ptr_t &day)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+    if (0 == option)
+    {
+        std::string settings_name = response["message"].asString();
+
+        LLInventoryObject::correctInventoryName(settings_name);
+        if (settings_name.empty())
+        {
+            // Ideally notification should disable 'OK' button if name won't fit our requirements,
+            // for now either display notification, or use some default name
+            settings_name = "Unnamed";
+        }
+
+        if (mCanMod)
+        {
+            doApplyCreateNewInventory(day, settings_name);
+        }
+        else if (mInventoryItem)
+        {
+            const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+            LLUUID parent_id = mInventoryItem->getParentUUID();
+            if (marketplacelistings_id == parent_id)
+            {
+                parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
+            }
+
+            LLPointer<LLInventoryCallback> cb = new LLDaySettingCopiedCallback(getHandle());
+            copy_inventory_item(
+                gAgent.getID(),
+                mInventoryItem->getPermissions().getOwner(),
+                mInventoryItem->getUUID(),
+                parent_id,
+                settings_name,
+                cb);
+        }
+        else
+        {
+            LL_WARNS() << "Failed to copy day setting" << LL_ENDL;
+        }
+    }
+}
+
+void LLFloaterEditExtDayCycle::onClickCloseBtn(bool app_quitting /*= false*/)
+{
+    if (!app_quitting)
+        checkAndConfirmSettingsLoss([this](){ closeFloater(); clearDirtyFlag(); });
+    else
+        closeFloater();
+}
+
+void LLFloaterEditExtDayCycle::onButtonImport()
+{
+    checkAndConfirmSettingsLoss([this]() { doImportFromDisk(); });
+}
+
+void LLFloaterEditExtDayCycle::onButtonLoadFrame()
+{
+    doOpenInventoryFloater((mCurrentTrack == LLSettingsDay::TRACK_WATER) ? LLSettingsType::ST_WATER : LLSettingsType::ST_SKY, LLUUID::null);
+}
+
+void LLFloaterEditExtDayCycle::onAddFrame()
+{
+    LLSettingsBase::Seconds frame(mTimeSlider->getCurSliderValue());
+    LLSettingsBase::ptr_t setting;
+    if (!mEditDay)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame while waiting for day(asset) to load." << LL_ENDL;
+        return;
+    }
+    if ((mEditDay->getSettingsNearKeyframe(frame, mCurrentTrack, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR)).second)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame too close to existing frame." << LL_ENDL;
+        return;
+    }
+    if (!mFramesSlider->canAddSliders())
+    {
+        // Shouldn't happen, button should be disabled
+        LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame when slider is full." << LL_ENDL;
+        return;
+    }
+
+    if (mCurrentTrack == LLSettingsDay::TRACK_WATER)
+    {
+        // scratch water should always have the current water settings.
+        LLSettingsWater::ptr_t water(mScratchWater->buildClone());
+        setting = water;
+        mEditDay->setWaterAtKeyframe( std::static_pointer_cast<LLSettingsWater>(setting), frame);
+    }
+    else
+    {
+        // scratch sky should always have the current sky settings.
+        LLSettingsSky::ptr_t sky(mScratchSky->buildClone());
+        setting = sky;
+        mEditDay->setSkyAtKeyframe(sky, frame, mCurrentTrack);
+    }
+    setDirtyFlag();
+    addSliderFrame(frame, setting);
+    updateTabs();
+}
+
+void LLFloaterEditExtDayCycle::onRemoveFrame()
+{
+    std::string sldr_key = mFramesSlider->getCurSlider();
+    if (sldr_key.empty())
+    {
+        return;
+    }
+    setDirtyFlag();
+    removeCurrentSliderFrame();
+    updateTabs();
+}
+
+
+void LLFloaterEditExtDayCycle::onCloneTrack()
+{
+    if (!mEditDay)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Attempt to copy track while waiting for day(asset) to load." << LL_ENDL;
+        return;
+    }
+    const LLEnvironment::altitude_list_t &altitudes = LLEnvironment::instance().getRegionAltitudes();
+    bool use_altitudes = altitudes.size() > 0 && ((mEditContext == CONTEXT_PARCEL) || (mEditContext == CONTEXT_REGION));
+
+    LLSD args = LLSD::emptyArray();
+
+    S32 populated_counter = 0;
+    for (U32 i = 1; i < LLSettingsDay::TRACK_MAX; i++)
+    {
+        LLSD track;
+        track["id"] = LLSD::Integer(i);
+        bool populated = (!mEditDay->isTrackEmpty(i)) && (i != mCurrentTrack);
+        track["enabled"] = populated;
+        if (populated)
+        {
+            populated_counter++;
+        }
+        if (use_altitudes)
+        {
+            track["altitude"] = altitudes[i - 1];
+        }
+        args.append(track);
+    }
+
+    if (populated_counter > 0)
+    {
+        doOpenTrackFloater(args);
+    }
+    else
+    {
+        // Should not happen
+        LL_WARNS("ENVDAYEDIT") << "Tried to copy tracks, but there are no available sources" << LL_ENDL;
+    }
+}
+
+
+void LLFloaterEditExtDayCycle::onLoadTrack()
+{
+    LLUUID curitemId = mInventoryId;
+
+    if (mCurrentEdit && curitemId.notNull())
+    {
+        curitemId = LLFloaterSettingsPicker::findItemID(mCurrentEdit->getAssetId(), false, false);
+    }
+
+    doOpenInventoryFloater(LLSettingsType::ST_DAYCYCLE, curitemId);
+}
+
+
+void LLFloaterEditExtDayCycle::onClearTrack()
+{
+    if (!mEditDay)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Attempt to clear track while waiting for day(asset) to load." << LL_ENDL;
+        return;
+    }
+
+    if (mCurrentTrack > 1)
+        mEditDay->getCycleTrack(mCurrentTrack).clear();
+    else
+    {
+        LLSettingsDay::CycleTrack_t &track(mEditDay->getCycleTrack(mCurrentTrack));
+
+        auto first = track.begin();
+        auto last = track.end();
+        ++first;
+        track.erase(first, last);
+    }
+
+    updateEditEnvironment();
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_INSTANT);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+    synchronizeTabs();
+    updateTabs();
+    refresh();
+}
+
+void LLFloaterEditExtDayCycle::onCommitName(class LLLineEditor* caller, void* user_data)
+{
+    if (!mEditDay)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Attempt to rename day while waiting for day(asset) to load." << LL_ENDL;
+        return;
+    }
+
+    mEditDay->setName(caller->getText());
+}
+
+void LLFloaterEditExtDayCycle::onTrackSelectionCallback(const LLSD& user_data)
+{
+    U32 track_index = user_data.asInteger(); // 1-5
+    selectTrack(track_index);
+}
+
+void LLFloaterEditExtDayCycle::onPlayActionCallback(const LLSD& user_data)
+{
+    std::string action = user_data.asString();
+
+    F32 frame = mTimeSlider->getCurSliderValue();
+
+    if (action == ACTION_PLAY)
+    {
+        startPlay();
+    }
+    else if (action == ACTION_PAUSE)
+    {
+        stopPlay();
+    }
+    else if (mSliderKeyMap.size() != 0)
+    {
+        F32 new_frame = 0;
+        if (action == ACTION_FORWARD)
+        {
+            new_frame = mEditDay->getUpperBoundFrame(mCurrentTrack, frame + (mTimeSlider->getIncrement() / 2));
+        }
+        else if (action == ACTION_BACK)
+        {
+            new_frame = mEditDay->getLowerBoundFrame(mCurrentTrack, frame - (mTimeSlider->getIncrement() / 2));
+        }
+        selectFrame(new_frame, 0.0f);
+        stopPlay();
+    }
+}
+
+void LLFloaterEditExtDayCycle::onFrameSliderCallback(const LLSD &data)
+{
+    std::string curslider = mFramesSlider->getCurSlider();
+
+    if (!curslider.empty() && mEditDay)
+    {
+        F32 sliderpos = mFramesSlider->getCurSliderValue();
+
+        keymap_t::iterator it = mSliderKeyMap.find(curslider);
+        if (it != mSliderKeyMap.end())
+        {
+            if (gKeyboard->currentMask(TRUE) == MASK_SHIFT && mShiftCopyEnabled && mCanMod)
+            {
+                // don't move the point/frame as long as shift is pressed and user is attempting to copy
+                // handleKeyUp will do the move if user releases key too early.
+                if (!(mEditDay->getSettingsNearKeyframe(sliderpos, mCurrentTrack, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR)).second)
+                {
+                    LL_DEBUGS("ENVDAYEDIT") << "Copying frame from " << it->second.mFrame << " to " << sliderpos << LL_ENDL;
+                    LLSettingsBase::ptr_t new_settings;
+
+                    // mEditDay still remembers old position, add copy at new position
+                    if (mCurrentTrack == LLSettingsDay::TRACK_WATER)
+                    {
+                        LLSettingsWaterPtr_t water_ptr = std::dynamic_pointer_cast<LLSettingsWater>(it->second.pSettings)->buildClone();
+                        mEditDay->setWaterAtKeyframe(water_ptr, sliderpos);
+                        new_settings = water_ptr;
+                    }
+                    else
+                    {
+                        LLSettingsSkyPtr_t sky_ptr = std::dynamic_pointer_cast<LLSettingsSky>(it->second.pSettings)->buildClone();
+                        mEditDay->setSkyAtKeyframe(sky_ptr, sliderpos, mCurrentTrack);
+                        new_settings = sky_ptr;
+                    }
+                    // mSliderKeyMap still remembers old position, for simplicity, just move it to be identical to slider
+                    F32 old_frame = it->second.mFrame;
+                    it->second.mFrame = sliderpos;
+                    // slider already moved old frame, create new one in old place
+                    addSliderFrame(old_frame, new_settings, false /*because we are going to reselect new one*/);
+                    // reselect new frame
+                    mFramesSlider->setCurSlider(it->first);
+                    mShiftCopyEnabled = false;
+                    setDirtyFlag();
+                }
+            }
+            else
+            {
+                // slider rounds values to nearest increments, changes can be substanntial (half increment)
+                if (abs(mFramesSlider->getNearestIncrement((*it).second.mFrame) - sliderpos) < F_APPROXIMATELY_ZERO)
+                {
+                    // same value
+                    mFramesSlider->setCurSliderValue((*it).second.mFrame);
+                }
+                else if (mEditDay->moveTrackKeyframe(mCurrentTrack, (*it).second.mFrame, sliderpos) && mCanMod)
+                {
+                    (*it).second.mFrame = sliderpos;
+                    setDirtyFlag();
+                }
+                else
+                {
+                    // same value, wrong track, no such value, no mod
+                    mFramesSlider->setCurSliderValue((*it).second.mFrame);
+                }
+
+                mShiftCopyEnabled = false;
+            }
+        }
+    }
+}
+
+void LLFloaterEditExtDayCycle::onFrameSliderDoubleClick(S32 x, S32 y, MASK mask)
+{
+    stopPlay();
+    onAddFrame();
+}
+
+void LLFloaterEditExtDayCycle::onFrameSliderMouseDown(S32 x, S32 y, MASK mask)
+{
+    stopPlay();
+    F32 sliderpos = mFramesSlider->getSliderValueFromPos(x, y);
+
+    std::string slidername = mFramesSlider->getCurSlider();
+
+    mShiftCopyEnabled = !slidername.empty() && gKeyboard->currentMask(TRUE) == MASK_SHIFT;
+
+    if (!slidername.empty())
+    {
+        LLRect thumb_rect = mFramesSlider->getSliderThumbRect(slidername);
+        if ((x >= thumb_rect.mRight) || (x <= thumb_rect.mLeft))
+        {
+            mFramesSlider->resetCurSlider();
+        }
+    }
+
+    mTimeSlider->setCurSliderValue(sliderpos);
+
+    updateTabs();
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+}
+
+void LLFloaterEditExtDayCycle::onFrameSliderMouseUp(S32 x, S32 y, MASK mask)
+{
+    // Only happens when clicking on empty space of frameslider, not on specific frame
+    F32 sliderpos = mFramesSlider->getSliderValueFromPos(x, y);
+
+    mTimeSlider->setCurSliderValue(sliderpos);
+    selectFrame(sliderpos, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
+}
+
+
+void LLFloaterEditExtDayCycle::onPanelDirtyFlagChanged(bool value)
+{
+    if (value)
+        setDirtyFlag();
+}
+
+void LLFloaterEditExtDayCycle::checkAndConfirmSettingsLoss(on_confirm_fn cb)
+{
+    if (isDirty())
+    {
+        LLSD args(LLSDMap("TYPE", mEditDay->getSettingsType())
+            ("NAME", mEditDay->getName()));
+
+        // create and show confirmation textbox
+        LLNotificationsUtil::add("SettingsConfirmLoss", args, LLSD(),
+            [cb](const LLSD&notif, const LLSD&resp)
+            {
+                S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+                if (opt == 0)
+                    cb();
+            });
+    }
+    else if (cb)
+    {
+        cb();
+    }
+}
+
+void LLFloaterEditExtDayCycle::onTimeSliderCallback()
+{
+    stopPlay();
+    selectFrame(mTimeSlider->getCurSliderValue(), LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
+}
+
+void LLFloaterEditExtDayCycle::cloneTrack(U32 source_index, U32 dest_index)
+{
+    cloneTrack(mEditDay, source_index, dest_index);
+}
+
+void LLFloaterEditExtDayCycle::cloneTrack(const LLSettingsDay::ptr_t &source_day, U32 source_index, U32 dest_index)
+{
+    if ((source_index == LLSettingsDay::TRACK_WATER || dest_index == LLSettingsDay::TRACK_WATER) && (source_index != dest_index))
+    {   // one of the tracks is a water track, the other is not
+        LLSD args;
+
+        LL_WARNS() << "Can not import water track into sky track or vice versa" << LL_ENDL;
+
+        LLButton* button = getChild<LLButton>(track_tabs[source_index], true);
+        args["TRACK1"] = button->getCurrentLabel();
+        button = getChild<LLButton>(track_tabs[dest_index], true);
+        args["TRACK2"] = button->getCurrentLabel();
+
+        LLNotificationsUtil::add("TrackLoadMismatch", args);
+        return;
+    }
+
+    // don't use replaceCycleTrack because we will end up with references, but we need to clone
+
+    // hold on to a backup of the 
+    LLSettingsDay::CycleTrack_t backup_track = mEditDay->getCycleTrack(dest_index);
+
+    mEditDay->clearCycleTrack(dest_index); // because source can be empty
+    LLSettingsDay::CycleTrack_t source_track = source_day->getCycleTrack(source_index);
+    S32 addcount(0);
+    for (auto &track_frame : source_track)
+    {
+        LLSettingsBase::ptr_t pframe = track_frame.second;
+        LLSettingsBase::ptr_t pframeclone = pframe->buildDerivedClone();
+        if (pframeclone)
+        {
+            ++addcount;
+            mEditDay->setSettingsAtKeyframe(pframeclone, track_frame.first, dest_index);
+        }
+    }
+
+    if (!addcount)
+    {   // nothing was actually added.  Restore the old track and issue a warning.
+        mEditDay->replaceCycleTrack(dest_index, backup_track);
+
+        LLSD args;
+        LLButton* button = getChild<LLButton>(track_tabs[dest_index], true);
+        args["TRACK"] = button->getCurrentLabel();
+
+        LLNotificationsUtil::add("TrackLoadFailed", args);
+    }
+    setDirtyFlag();
+
+    updateSlider();
+    updateTabs();
+    updateButtons();
+}
+
+void LLFloaterEditExtDayCycle::selectTrack(U32 track_index, bool force )
+{
+    if (track_index < LLSettingsDay::TRACK_MAX)
+        mCurrentTrack = track_index;
+
+    LLButton* button = getChild<LLButton>(track_tabs[mCurrentTrack], true);
+    if (button->getToggleState() && !force)
+    {
+        return;
+    }
+
+    for (U32 i = 0; i < LLSettingsDay::TRACK_MAX; i++) // use max value
+    {
+        getChild<LLButton>(track_tabs[i], true)->setToggleState(i == mCurrentTrack);
+    }
+
+    bool show_water = (mCurrentTrack == LLSettingsDay::TRACK_WATER);
+    mSkyTabLayoutContainer->setVisible(!show_water);
+    mWaterTabLayoutContainer->setVisible(show_water);
+
+    updateSlider();
+    updateLabels();
+}
+
+void LLFloaterEditExtDayCycle::selectFrame(F32 frame, F32 slop_factor)
+{
+    mFramesSlider->resetCurSlider();
+
+    keymap_t::iterator iter = mSliderKeyMap.begin();
+    keymap_t::iterator end_iter = mSliderKeyMap.end();
+    while (iter != end_iter)
+    {
+        F32 keyframe = iter->second.mFrame;
+        F32 frame_dif = fabs(keyframe - frame);
+        if (frame_dif <= slop_factor)
+        {
+            keymap_t::iterator next_iter = std::next(iter);
+            if ((frame_dif != 0) && (next_iter != end_iter))
+            {
+                if (fabs(next_iter->second.mFrame - frame) < frame_dif)
+                {
+                    mFramesSlider->setCurSlider(next_iter->first);
+                    frame = next_iter->second.mFrame;
+                    break;
+                }
+            }
+            mFramesSlider->setCurSlider(iter->first);
+            frame = iter->second.mFrame;  
+            break;
+        }
+        iter++;
+    }
+
+    mTimeSlider->setCurSliderValue(frame);
+    // block or update tabs according to new selection
+    updateTabs();
+//  LLEnvironment::instance().updateEnvironment();
+}
+
+void LLFloaterEditExtDayCycle::clearTabs()
+{
+    // Note: If this doesn't look good, init panels with default settings. It might be better looking
+    if (mCurrentTrack == LLSettingsDay::TRACK_WATER)
+    {
+        const LLSettingsWaterPtr_t p_water = LLSettingsWaterPtr_t(NULL);
+        updateWaterTabs(p_water);
+    }
+    else
+    {
+        const LLSettingsSkyPtr_t p_sky = LLSettingsSkyPtr_t(NULL);
+        updateSkyTabs(p_sky);
+    }
+    updateButtons();
+    updateTimeAndLabel();
+}
+
+void LLFloaterEditExtDayCycle::updateTabs()
+{
+    reblendSettings();
+    synchronizeTabs();
+
+    updateButtons();
+    updateTimeAndLabel();
+}
+
+void LLFloaterEditExtDayCycle::updateWaterTabs(const LLSettingsWaterPtr_t &p_water)
+{
+    LLView* tab_container = mWaterTabLayoutContainer->getChild<LLView>(TABS_WATER); //can't extract panels directly, since it is in 'tuple'
+    LLPanelSettingsWaterMainTab* panel = dynamic_cast<LLPanelSettingsWaterMainTab*>(tab_container->findChildView("water_panel"));
+    if (panel)
+    {
+        panel->setWater(p_water);
+    }
+}
+
+void LLFloaterEditExtDayCycle::updateSkyTabs(const LLSettingsSkyPtr_t &p_sky)
+{
+    LLTabContainer* tab_container = mSkyTabLayoutContainer->getChild<LLTabContainer>(TABS_SKYS); //can't extract panels directly, since they are in 'tuple'
+
+    LLPanelSettingsSky* panel;
+    panel = dynamic_cast<LLPanelSettingsSky*>(tab_container->findChildView("atmosphere_panel"));
+    if (panel)
+    {
+        panel->setSky(p_sky);
+    }
+    panel = dynamic_cast<LLPanelSettingsSky*>(tab_container->findChildView("clouds_panel"));
+    if (panel)
+    {
+        panel->setSky(p_sky);
+    }
+    panel = dynamic_cast<LLPanelSettingsSky*>(tab_container->findChildView("moon_panel"));
+    if (panel)
+    {
+        panel->setSky(p_sky);
+    }
+}
+
+void LLFloaterEditExtDayCycle::updateLabels()
+{
+    std::string label_arg = (mCurrentTrack == LLSettingsDay::TRACK_WATER) ? "water_label" : "sky_label";
+
+    mAddFrameButton->setLabelArg("[FRAME]", getString(label_arg));
+    mDeleteFrameButton->setLabelArg("[FRAME]", getString(label_arg));
+    mLoadFrame->setLabelArg("[FRAME]", getString(label_arg));
+}
+
+void LLFloaterEditExtDayCycle::updateButtons()
+{
+    // This logic appears to work in reverse, the add frame button
+    // is only enabled when you're on an existing frame and disabled
+    // in all the interim positions where you'd want to add a frame...
+
+    bool can_manipulate = mEditDay && !mIsPlaying && mCanMod;
+    bool can_clone(false);
+    bool can_clear(false);
+
+    if (can_manipulate)
+    {
+        if (mCurrentTrack == 0)
+        {
+            can_clone = false;
+        }
+        else
+        {
+            for (S32 track = 1; track < LLSettingsDay::TRACK_MAX; ++track)
+            {
+                if (track == mCurrentTrack)
+                    continue;
+                can_clone |= !mEditDay->getCycleTrack(track).empty();
+            }
+        }
+
+        can_clear = (mCurrentTrack > 1) ? (!mEditDay->getCycleTrack(mCurrentTrack).empty()) : (mEditDay->getCycleTrack(mCurrentTrack).size() > 1);
+    }
+
+    mCloneTrack->setEnabled(can_clone);
+    mLoadTrack->setEnabled(can_manipulate);
+    mClearTrack->setEnabled(can_clear);
+    mAddFrameButton->setEnabled(can_manipulate && isAddingFrameAllowed());
+    mDeleteFrameButton->setEnabled(can_manipulate && isRemovingFrameAllowed());
+    mLoadFrame->setEnabled(can_manipulate);
+
+    // update track buttons
+    bool extended_env = LLEnvironment::instance().isExtendedEnvironmentEnabled();
+    for (S32 track = 0; track < LLSettingsDay::TRACK_MAX; ++track)
+    {
+        LLButton* button = getChild<LLButton>(track_tabs[track], true);
+        button->setEnabled(extended_env);
+        button->setToggleState(track == mCurrentTrack);
+    }
+}
+
+void LLFloaterEditExtDayCycle::updateSlider()
+{
+    F32 frame_position = mTimeSlider->getCurSliderValue();
+    mFramesSlider->clear();
+    mSliderKeyMap.clear();
+
+    if (!mEditDay)
+    {
+        // floater is waiting for asset
+        return;
+    }
+
+    LLSettingsDay::CycleTrack_t track = mEditDay->getCycleTrack(mCurrentTrack);
+    for (auto &track_frame : track)
+    {
+        addSliderFrame(track_frame.first, track_frame.second, false);
+    }
+
+    if (mSliderKeyMap.size() > 0)
+    {
+        // update positions
+        mLastFrameSlider = mFramesSlider->getCurSlider();
+    }
+    else
+    {
+        // disable panels
+        clearTabs();
+        mLastFrameSlider.clear();
+    }
+
+    selectFrame(frame_position, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
+}
+
+void LLFloaterEditExtDayCycle::updateTimeAndLabel()
+{
+    F32 time = mTimeSlider->getCurSliderValue();
+    mCurrentTimeLabel->setTextArg("[PRCNT]", llformat("%.0f", time * 100));
+    if (mDayLength.value() != 0)
+    {
+        LLUIString formatted_label = getString("time_label");
+
+        LLSettingsDay::Seconds total = (mDayLength  * time); 
+        S32Hours hrs = total;
+        S32Minutes minutes = total - hrs;
+
+        formatted_label.setArg("[HH]", llformat("%d", hrs.value()));
+        formatted_label.setArg("[MM]", llformat("%d", abs(minutes.value())));
+        mCurrentTimeLabel->setTextArg("[DSC]", formatted_label.getString());
+    }
+    else
+    {
+        mCurrentTimeLabel->setTextArg("[DSC]", std::string());
+    }
+
+    // Update blender here:
+}
+
+void LLFloaterEditExtDayCycle::addSliderFrame(F32 frame, const LLSettingsBase::ptr_t &setting, bool update_ui)
+{
+    // multi slider distinguishes elements by key/name in string format
+    // store names to map to be able to recall dependencies
+    std::string new_slider = mFramesSlider->addSlider(frame);
+    if (!new_slider.empty())
+    {
+        mSliderKeyMap[new_slider] = FrameData(frame, setting);
+
+        if (update_ui)
+        {
+            mLastFrameSlider = new_slider;
+            mTimeSlider->setCurSliderValue(frame);
+            updateTabs();
+        }
+    }
+}
+
+void LLFloaterEditExtDayCycle::removeCurrentSliderFrame()
+{
+    std::string sldr = mFramesSlider->getCurSlider();
+    if (sldr.empty())
+    {
+        return;
+    }
+    mFramesSlider->deleteCurSlider();
+    keymap_t::iterator iter = mSliderKeyMap.find(sldr);
+    if (iter != mSliderKeyMap.end())
+    {
+        LL_DEBUGS("ENVDAYEDIT") << "Removing frame from " << iter->second.mFrame << LL_ENDL;
+        LLSettingsBase::Seconds seconds(iter->second.mFrame);
+        mEditDay->removeTrackKeyframe(mCurrentTrack, seconds);
+        mSliderKeyMap.erase(iter);
+    }
+
+    mLastFrameSlider = mFramesSlider->getCurSlider();
+    mTimeSlider->setCurSliderValue(mFramesSlider->getCurSliderValue());
+    updateTabs();
+}
+
+void LLFloaterEditExtDayCycle::removeSliderFrame(F32 frame)
+{
+    keymap_t::iterator it = std::find_if(mSliderKeyMap.begin(), mSliderKeyMap.end(), 
+        [frame](const keymap_t::value_type &value) { return fabs(value.second.mFrame - frame) < LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR; });
+
+    if (it != mSliderKeyMap.end())
+    {
+        mFramesSlider->deleteSlider((*it).first);
+        mSliderKeyMap.erase(it);
+    }
+
+}
+
+//-------------------------------------------------------------------------
+
+LLFloaterEditExtDayCycle::connection_t LLFloaterEditExtDayCycle::setEditCommitSignal(LLFloaterEditExtDayCycle::edit_commit_signal_t::slot_type cb)
+{
+    return mCommitSignal.connect(cb);
+}
+
+void LLFloaterEditExtDayCycle::loadInventoryItem(const LLUUID  &inventoryId, bool can_trans)
+{
+    if (inventoryId.isNull())
+    {
+        mInventoryItem = nullptr;
+        mInventoryId.setNull();
+        mCanSave = true;
+        mCanCopy = true;
+        mCanMod = true;
+        mCanTrans = true;
+        return;
+    }
+
+    mInventoryId = inventoryId;
+    LL_INFOS("ENVDAYEDIT") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
+    mInventoryItem = gInventory.getItem(mInventoryId);
+
+    if (!mInventoryItem)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
+
+        LLNotificationsUtil::add("CantFindInvItem");
+        closeFloater();
+        mInventoryId.setNull();
+        mInventoryItem = nullptr;
+        return;
+    }
+
+    if (mInventoryItem->getAssetUUID().isNull())
+    {
+        LL_WARNS("ENVDAYEDIT") << "Asset ID in inventory item is NULL (" << mInventoryId << ")" <<  LL_ENDL;
+
+        LLNotificationsUtil::add("UnableEditItem");
+        closeFloater();
+
+        mInventoryId.setNull();
+        mInventoryItem = nullptr;
+        return;
+    }
+
+    mCanSave = true;
+    mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
+    mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
+    mCanTrans = can_trans && mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+
+    mExpectingAssetId = mInventoryItem->getAssetUUID();
+    LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
+        [this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
+}
+
+void LLFloaterEditExtDayCycle::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
+{
+    if (asset_id != mExpectingAssetId)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Expecting {" << mExpectingAssetId << "} got {" << asset_id << "} - throwing away." << LL_ENDL;
+        return;
+    }
+    mExpectingAssetId.setNull();
+    clearDirtyFlag();
+
+    if (!settings || status)
+    {
+        LLSD args;
+        args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown";
+        LLNotificationsUtil::add("FailedToFindSettings", args);
+        closeFloater();
+        return;
+    }
+
+    if (settings->getFlag(LLSettingsBase::FLAG_NOSAVE))
+    {
+        mCanSave = false;
+        mCanCopy = false;
+        mCanMod = false;
+        mCanTrans = false;
+    }
+    else
+    {
+        if (mCanCopy)
+            settings->clearFlag(LLSettingsBase::FLAG_NOCOPY);
+        else
+            settings->setFlag(LLSettingsBase::FLAG_NOCOPY);
+
+        if (mCanMod)
+            settings->clearFlag(LLSettingsBase::FLAG_NOMOD);
+        else
+            settings->setFlag(LLSettingsBase::FLAG_NOMOD);
+
+        if (mCanTrans)
+            settings->clearFlag(LLSettingsBase::FLAG_NOTRANS);
+        else
+            settings->setFlag(LLSettingsBase::FLAG_NOTRANS);
+
+        if (mInventoryItem)
+            settings->setName(mInventoryItem->getName());
+    }
+
+    setEditDayCycle(std::dynamic_pointer_cast<LLSettingsDay>(settings));
+}
+
+void LLFloaterEditExtDayCycle::updateEditEnvironment(void)
+{
+    if (!mEditDay)
+        return;
+    S32 skytrack = (mCurrentTrack) ? mCurrentTrack : 1;
+    mSkyBlender = std::make_shared<LLTrackBlenderLoopingManual>(mScratchSky, mEditDay, skytrack);
+    mWaterBlender = std::make_shared<LLTrackBlenderLoopingManual>(mScratchWater, mEditDay, LLSettingsDay::TRACK_WATER);
+
+    if (LLEnvironment::instance().isExtendedEnvironmentEnabled())
+    {
+        selectTrack(LLSettingsDay::TRACK_MAX, true);
+    }
+    else
+    {
+        selectTrack(1, true);
+    }
+
+    reblendSettings();
+
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, mEditSky, mEditWater);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+}
+
+void LLFloaterEditExtDayCycle::synchronizeTabs()
+{
+    // This should probably get moved into "updateTabs"
+    std::string curslider = mFramesSlider->getCurSlider();
+    bool canedit(false);
+
+    LLSettingsWater::ptr_t psettingW;
+    LLTabContainer * tabs = mWaterTabLayoutContainer->getChild<LLTabContainer>(TABS_WATER);
+    if (mCurrentTrack == LLSettingsDay::TRACK_WATER)
+    {
+        if (!mEditDay)
+        {
+            canedit = false;
+        }
+        else if (!curslider.empty())
+        {
+            canedit = !mIsPlaying;
+            // either search mEditDay or retrieve from mSliderKeyMap
+            keymap_t::iterator slider_it = mSliderKeyMap.find(curslider);
+            if (slider_it != mSliderKeyMap.end())
+            {
+                psettingW = std::static_pointer_cast<LLSettingsWater>(slider_it->second.pSettings);
+            }
+        }
+        mCurrentEdit = psettingW;
+        if (!psettingW)
+        {
+            canedit = false;
+            psettingW = mScratchWater;
+        }
+
+        getChild<LLUICtrl>(ICN_LOCK_EDIT)->setVisible(!canedit);
+    }
+    else 
+    {
+        psettingW = mScratchWater;
+    }
+    mEditWater = psettingW;
+
+    setTabsData(tabs, psettingW, canedit);
+
+    LLSettingsSky::ptr_t psettingS;
+    canedit = false;
+    tabs = mSkyTabLayoutContainer->getChild<LLTabContainer>(TABS_SKYS);
+    if (mCurrentTrack != LLSettingsDay::TRACK_WATER)
+    {
+        if (!mEditDay)
+        {
+            canedit = false;
+        }
+        else if (!curslider.empty())
+        {
+            canedit = !mIsPlaying;
+            // either search mEditDay or retrieve from mSliderKeyMap
+            keymap_t::iterator slider_it = mSliderKeyMap.find(curslider);
+            if (slider_it != mSliderKeyMap.end())
+            {
+                psettingS = std::static_pointer_cast<LLSettingsSky>(slider_it->second.pSettings);
+            }
+        }
+        mCurrentEdit = psettingS;
+        if (!psettingS)
+        {
+            canedit = false;
+            psettingS = mScratchSky;
+        }
+
+        getChild<LLUICtrl>(ICN_LOCK_EDIT)->setVisible(!canedit);
+    }
+    else
+    {
+        psettingS = mScratchSky;
+    }
+    mEditSky = psettingS;
+
+    doCloseInventoryFloater();
+    doCloseTrackFloater();
+
+    setTabsData(tabs, psettingS, canedit);
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, mEditSky, mEditWater);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+}
+
+void LLFloaterEditExtDayCycle::setTabsData(LLTabContainer * tabcontainer, const LLSettingsBase::ptr_t &settings, bool editable)
+{
+    S32 count = tabcontainer->getTabCount();
+    for (S32 idx = 0; idx < count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(tabcontainer->getPanelByIndex(idx));
+        if (panel)
+        {
+            panel->setCanChangeSettings(editable & mCanMod);
+            panel->setSettings(settings);
+        }
+    }
+}
+
+
+void LLFloaterEditExtDayCycle::reblendSettings()
+{
+    F64 position = mTimeSlider->getCurSliderValue();
+
+    if ((mSkyBlender->getTrack() != mCurrentTrack) && (mCurrentTrack != LLSettingsDay::TRACK_WATER))
+    {
+        mSkyBlender->switchTrack(mCurrentTrack, position);
+    }
+    else
+        mSkyBlender->setPosition(position);
+
+    mWaterBlender->setPosition(position);    
+}
+
+void LLFloaterEditExtDayCycle::doApplyCreateNewInventory(const LLSettingsDay::ptr_t &day, std::string settings_name)
+{
+    if (mInventoryItem)
+    {
+        LLUUID parent_id = mInventoryItem->getParentUUID();
+        U32 next_owner_perm = mInventoryItem->getPermissions().getMaskNextOwner();
+        LLSettingsVOBase::createInventoryItem(day, next_owner_perm, parent_id, settings_name,
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    }
+    else
+    {
+        LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
+        // This method knows what sort of settings object to create.
+        LLSettingsVOBase::createInventoryItem(day, parent_id, settings_name,
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    }
+}
+
+void LLFloaterEditExtDayCycle::doApplyUpdateInventory(const LLSettingsDay::ptr_t &day)
+{
+    if (mInventoryId.isNull())
+        LLSettingsVOBase::createInventoryItem(day, gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS), std::string(),
+                [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    else
+        LLSettingsVOBase::updateInventoryItem(day, mInventoryId,
+                [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
+}
+
+void LLFloaterEditExtDayCycle::doApplyEnvironment(const std::string &where, const LLSettingsDay::ptr_t &day)
+{
+    U32 flags(0);
+
+    if (mInventoryItem)
+    {
+        if (!mInventoryItem->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOMOD;
+        if (!mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOTRANS;
+    }
+
+    flags |= day->getFlags();
+    day->setFlag(flags);
+
+    if (where == ACTION_APPLY_LOCAL)
+    {
+        day->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, day);
+    }
+    else if (where == ACTION_APPLY_PARCEL)
+    {
+        LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
+
+        if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
+        {
+            LL_WARNS("ENVDAYEDIT") << "Can not identify parcel. Not applying." << LL_ENDL;
+            LLNotificationsUtil::add("WLParcelApplyFail");
+            return;
+        }
+
+        if (mInventoryItem && !isDirty())
+        {
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
+        }
+        else
+        {
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), day, -1, -1);
+        }
+    }
+    else if (where == ACTION_APPLY_REGION)
+    {
+        if (mInventoryItem && !isDirty())
+        {
+            LLEnvironment::instance().updateRegion(mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
+        }
+        else
+        {
+            LLEnvironment::instance().updateRegion(day, -1, -1);
+        }
+    }
+    else
+    {
+        LL_WARNS("ENVDAYEDIT") << "Unknown apply '" << where << "'" << LL_ENDL;
+        return;
+    }
+
+}
+
+void LLFloaterEditExtDayCycle::doApplyCommit(LLSettingsDay::ptr_t day)
+{
+    if (!mCommitSignal.empty())
+    {
+        mCommitSignal(day);
+
+        closeFloater();
+    }
+}
+
+bool LLFloaterEditExtDayCycle::isRemovingFrameAllowed()
+{
+    if (mFramesSlider->getCurSlider().empty()) return false;
+
+    if (mCurrentTrack <= LLSettingsDay::TRACK_GROUND_LEVEL)
+    {
+        return (mSliderKeyMap.size() > 1);
+    }
+    else
+    {
+        return (mSliderKeyMap.size() > 0);
+    }
+}
+
+bool LLFloaterEditExtDayCycle::isAddingFrameAllowed()
+{
+    if (!mFramesSlider->getCurSlider().empty() || !mEditDay) return false;
+
+    LLSettingsBase::Seconds frame(mTimeSlider->getCurSliderValue());
+    if ((mEditDay->getSettingsNearKeyframe(frame, mCurrentTrack, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR)).second)
+    {
+        return false;
+    }
+    return mFramesSlider->canAddSliders();
+}
+
+void LLFloaterEditExtDayCycle::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_INFOS("ENVDAYEDIT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
+
+    if (inventory_id.isNull() || !results["success"].asBoolean())
+    {
+        LLNotificationsUtil::add("CantCreateInventory");
+        return;
+    }
+    onInventoryCreated(asset_id, inventory_id);
+}
+
+void LLFloaterEditExtDayCycle::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id)
+{
+    bool can_trans = true;
+    if (mInventoryItem)
+    {
+        LLPermissions perms = mInventoryItem->getPermissions();
+
+        LLInventoryItem *created_item = gInventory.getItem(mInventoryId);
+        
+        if (created_item)
+        {
+            can_trans = perms.allowOperationBy(PERM_TRANSFER, gAgent.getID());
+            created_item->setPermissions(perms);
+            created_item->updateServer(false);
+        }
+    }
+
+    clearDirtyFlag();
+    setFocus(TRUE);                 // Call back the focus...
+    loadInventoryItem(inventory_id, can_trans);
+}
+
+void LLFloaterEditExtDayCycle::onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_WARNS("ENVDAYEDIT") << "Inventory item " << inventory_id << " has been updated with asset " << asset_id << " results are:" << results << LL_ENDL;
+
+    clearDirtyFlag();
+    if (inventory_id != mInventoryId)
+    {
+        loadInventoryItem(inventory_id);
+    }
+}
+
+void LLFloaterEditExtDayCycle::doImportFromDisk()
+{   // Load a a legacy Windlight XML from disk.
+    (new LLFilePickerReplyThread(boost::bind(&LLFloaterEditExtDayCycle::loadSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+}
+
+void LLFloaterEditExtDayCycle::loadSettingFromFile(const std::vector<std::string>& filenames)
+{
+    LLSD messages;
+    if (filenames.size() < 1) return;
+    std::string filename = filenames[0];
+    LL_DEBUGS("ENVDAYEDIT") << "Selected file: " << filename << LL_ENDL;
+    LLSettingsDay::ptr_t legacyday = LLEnvironment::createDayCycleFromLegacyPreset(filename, messages);
+
+    if (!legacyday)
+    {   
+        LLNotificationsUtil::add("WLImportFail", messages);
+        return;
+    }
+
+    loadInventoryItem(LLUUID::null);
+
+    mCurrentTrack = 1;
+    setDirtyFlag();
+    setEditDayCycle(legacyday);
+}
+
+bool LLFloaterEditExtDayCycle::canUseInventory() const
+{
+    return LLEnvironment::instance().isInventoryEnabled();
+}
+
+bool LLFloaterEditExtDayCycle::canApplyRegion() const
+{
+    return gAgent.canManageEstate();
+}
+
+bool LLFloaterEditExtDayCycle::canApplyParcel() const
+{
+    return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
+}
+
+void LLFloaterEditExtDayCycle::startPlay()
+{
+    doCloseInventoryFloater();
+    doCloseTrackFloater();
+
+    mIsPlaying = true;
+    mFramesSlider->resetCurSlider();
+    mPlayTimer.reset();
+    mPlayTimer.start();
+    gIdleCallbacks.addFunction(onIdlePlay, this);
+    mPlayStartFrame = mTimeSlider->getCurSliderValue();
+
+    getChild<LLView>("play_layout", true)->setVisible(FALSE);
+    getChild<LLView>("pause_layout", true)->setVisible(TRUE);
+}
+
+void LLFloaterEditExtDayCycle::stopPlay()
+{
+    if (!mIsPlaying)
+        return;
+
+    mIsPlaying = false;
+    gIdleCallbacks.deleteFunction(onIdlePlay, this);
+    mPlayTimer.stop();
+    F32 frame = mTimeSlider->getCurSliderValue();
+    selectFrame(frame, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
+
+    getChild<LLView>("play_layout", true)->setVisible(TRUE);
+    getChild<LLView>("pause_layout", true)->setVisible(FALSE);
+}
+
+//static
+void LLFloaterEditExtDayCycle::onIdlePlay(void* user_data)
+{
+    if (!gDisconnected)
+    {
+        LLFloaterEditExtDayCycle* self = (LLFloaterEditExtDayCycle*)user_data;
+
+        F32 prcnt_played = self->mPlayTimer.getElapsedTimeF32() / DAY_CYCLE_PLAY_TIME_SECONDS;
+        F32 new_frame = fmod(self->mPlayStartFrame + prcnt_played, 1.f);
+
+        self->mTimeSlider->setCurSliderValue(new_frame); // will do the rounding
+        self->mSkyBlender->setPosition(new_frame);
+        self->mWaterBlender->setPosition(new_frame);
+        self->synchronizeTabs();
+        self->updateTimeAndLabel();
+        self->updateButtons();
+    }
+}
+
+
+void LLFloaterEditExtDayCycle::clearDirtyFlag()
+{
+    mIsDirty = false;
+
+    LLTabContainer* tab_container = mSkyTabLayoutContainer->getChild<LLTabContainer>("sky_tabs");
+    S32 tab_count = tab_container->getTabCount();
+
+    for (S32 idx = 0; idx < tab_count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(tab_container->getPanelByIndex(idx));
+        if (panel)
+            panel->clearIsDirty();
+    }
+
+    tab_container = mWaterTabLayoutContainer->getChild<LLTabContainer>("water_tabs");
+    tab_count = tab_container->getTabCount();
+
+    for (S32 idx = 0; idx < tab_count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(tab_container->getPanelByIndex(idx));
+        if (panel)
+            panel->clearIsDirty();
+    }
+
+}
+
+void LLFloaterEditExtDayCycle::doOpenTrackFloater(const LLSD &args)
+{
+    LLFloaterTrackPicker *picker = static_cast<LLFloaterTrackPicker *>(mTrackFloater.get());
+
+    // Show the dialog
+    if (!picker)
+    {
+        picker = new LLFloaterTrackPicker(this);
+
+        mTrackFloater = picker->getHandle();
+
+        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitTrackId(data.asInteger()); });
+    }
+
+    picker->showPicker(args);
+}
+
+void LLFloaterEditExtDayCycle::doCloseTrackFloater(bool quitting)
+{
+    LLFloater* floaterp = mTrackFloater.get();
+
+    if (floaterp)
+    {
+        floaterp->closeFloater(quitting);
+    }
+}
+
+void LLFloaterEditExtDayCycle::onPickerCommitTrackId(U32 track_id)
+{
+    cloneTrack(track_id, mCurrentTrack);
+}
+
+void LLFloaterEditExtDayCycle::doOpenInventoryFloater(LLSettingsType::type_e type, LLUUID curritem)
+{
+//  LLUI::sWindow->setCursor(UI_CURSOR_WAIT);
+    LLFloaterSettingsPicker *picker = static_cast<LLFloaterSettingsPicker *>(mInventoryFloater.get());
+
+    // Show the dialog
+    if (!picker)
+    {
+        picker = new LLFloaterSettingsPicker(this,
+            LLUUID::null);
+
+        mInventoryFloater = picker->getHandle();
+
+        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitSetting(data["ItemId"].asUUID(), data["Track"].asInteger()); });
+    }
+
+    picker->setSettingsFilter(type);
+    picker->setSettingsItemId(curritem);
+    if (type == LLSettingsType::ST_DAYCYCLE)
+    {
+        picker->setTrackMode((mCurrentTrack == LLSettingsDay::TRACK_WATER) ? LLFloaterSettingsPicker::TRACK_WATER : LLFloaterSettingsPicker::TRACK_SKY);
+    }
+    else
+    {
+        picker->setTrackMode(LLFloaterSettingsPicker::TRACK_NONE);
+    }
+    picker->openFloater();
+    picker->setFocus(TRUE);
+}
+
+void LLFloaterEditExtDayCycle::doCloseInventoryFloater(bool quitting)
+{
+    LLFloater* floaterp = mInventoryFloater.get();
+
+    if (floaterp)
+    {
+        floaterp->closeFloater(quitting);
+    }
+}
+
+void LLFloaterEditExtDayCycle::onPickerCommitSetting(LLUUID item_id, S32 track)
+{
+    LLSettingsBase::TrackPosition frame(mTimeSlider->getCurSliderValue());
+    LLViewerInventoryItem *itemp = gInventory.getItem(item_id);
+    if (itemp)
+    {
+        LLSettingsVOBase::getSettingsAsset(itemp->getAssetUUID(),
+            [this, track, frame, item_id](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoadedForInsertion(item_id, asset_id, settings, status, track, mCurrentTrack, frame); });
+    }
+}
+
+void LLFloaterEditExtDayCycle::onAssetLoadedForInsertion(LLUUID item_id, LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, S32 source_track, S32 dest_track, LLSettingsBase::TrackPosition frame)
+{
+    std::function<void()> cb = [this, settings, frame, source_track, dest_track]()
+    {
+        if (settings->getSettingsType() == "daycycle")
+        {
+            // Load full track
+            LLSettingsDay::ptr_t pday = std::dynamic_pointer_cast<LLSettingsDay>(settings);
+            if (dest_track == LLSettingsDay::TRACK_WATER)
+            {
+                cloneTrack(pday, LLSettingsDay::TRACK_WATER, LLSettingsDay::TRACK_WATER);
+            }
+            else
+            {
+                cloneTrack(pday, source_track, dest_track);
+            }
+        }
+        else
+        {
+            if (!mFramesSlider->canAddSliders())
+            {
+                LL_WARNS("ENVDAYEDIT") << "Attempt to add new frame when slider is full." << LL_ENDL;
+                return;
+            }
+
+            // load or replace single frame
+            LLSettingsDay::CycleTrack_t::value_type nearest = mEditDay->getSettingsNearKeyframe(frame, dest_track, LLSettingsDay::DEFAULT_FRAME_SLOP_FACTOR);
+            if (nearest.first != LLSettingsDay::INVALID_TRACKPOS)
+            {   // There is already a frame near the target location. Remove it so we can put the new one in its place.
+                mEditDay->removeTrackKeyframe(dest_track, nearest.first);
+                removeSliderFrame(nearest.first);
+            }
+
+            // Don't forget to clone (we might reuse/load it couple times)
+            if (settings->getSettingsType() == "sky")
+            {
+                // Load sky to frame
+                if (dest_track != LLSettingsDay::TRACK_WATER)
+                {
+                    mEditDay->setSettingsAtKeyframe(settings->buildDerivedClone(), frame, dest_track);
+                    addSliderFrame(frame, settings, false);
+                }
+                else
+                {
+                    LL_WARNS("ENVDAYEDIT") << "Trying to load day settings as sky" << LL_ENDL;
+                }
+            }
+            else if (settings->getSettingsType() == "water")
+            {
+                // Load water to frame
+                if (dest_track == LLSettingsDay::TRACK_WATER)
+                {
+                    mEditDay->setSettingsAtKeyframe(settings->buildDerivedClone(), frame, dest_track);
+                    addSliderFrame(frame, settings, false);
+                }
+                else
+                {
+                    LL_WARNS("ENVDAYEDIT") << "Trying to load water settings as sky" << LL_ENDL;
+                }
+            }
+        }
+        reblendSettings();
+        synchronizeTabs();
+    };
+
+    if (!settings || status)
+    {
+        LL_WARNS("ENVDAYEDIT") << "Could not load asset " << asset_id << " into frame. status=" << status << LL_ENDL;
+        return;
+    }
+
+    if (!mEditDay)
+    {
+        // day got reset while we were waiting for response
+        return;
+    }
+
+    LLInventoryItem *inv_item = gInventory.getItem(item_id);
+
+    if (inv_item && !inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+    {
+        // Need to check if item is already no-transfer, otherwise make it no-transfer
+        bool no_transfer = false;
+        if (mInventoryItem)
+        {
+            no_transfer = !mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+        }
+        else
+        {
+            no_transfer = mEditDay->getFlag(LLSettingsBase::FLAG_NOTRANS);
+        }
+
+        if (!no_transfer)
+        {
+            LLSD args;
+
+            // create and show confirmation textbox
+            LLNotificationsUtil::add("SettingsMakeNoTrans", args, LLSD(),
+                [this, cb](const LLSD&notif, const LLSD&resp)
+            {
+                S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+                if (opt == 0)
+                {
+                    mCanTrans = false;
+                    mEditDay->setFlag(LLSettingsBase::FLAG_NOTRANS);
+                    cb();
+                }
+            });
+            return;
+        }
+    }
+    
+    cb();
+}
diff --git a/indra/newview/llfloatereditextdaycycle.h b/indra/newview/llfloatereditextdaycycle.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6e9fdb14f8a635757c954ed20b7da7d34fa2acd
--- /dev/null
+++ b/indra/newview/llfloatereditextdaycycle.h
@@ -0,0 +1,262 @@
+/** 
+ * @file llfloatereditextdaycycle.h
+ * @brief Floater to create or edit a day cycle
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifndef LL_LLFLOATEREDITEXTDAYCYCLE_H
+#define LL_LLFLOATEREDITEXTDAYCYCLE_H
+
+#include "llfloater.h"
+#include "llsettingsdaycycle.h"
+#include <boost/signals2.hpp>
+
+#include "llenvironment.h"
+
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLFlyoutComboBtnCtrl;
+class LLLineEditor;
+class LLMultiSliderCtrl;
+class LLTextBox;
+class LLTimeCtrl;
+class LLTabContainer;
+
+class LLInventoryItem;
+class LLDaySettingCopiedCallback;
+
+typedef std::shared_ptr<LLSettingsBase> LLSettingsBasePtr_t;
+
+/**
+ * Floater for creating or editing a day cycle.
+ */
+class LLFloaterEditExtDayCycle : public LLFloater
+{
+	LOG_CLASS(LLFloaterEditExtDayCycle);
+
+    friend class LLDaySettingCopiedCallback;
+
+public:
+    static const std::string    KEY_INVENTORY_ID;
+    static const std::string    KEY_EDIT_CONTEXT;
+    static const std::string    KEY_DAY_LENGTH;
+    static const std::string    KEY_CANMOD;
+
+    static const std::string    VALUE_CONTEXT_INVENTORY;
+    static const std::string    VALUE_CONTEXT_PARCEL;
+    static const std::string    VALUE_CONTEXT_REGION;
+
+    enum edit_context_t {
+        CONTEXT_UNKNOWN,
+        CONTEXT_INVENTORY,
+        CONTEXT_PARCEL,
+        CONTEXT_REGION
+    };
+
+    typedef boost::signals2::signal<void(LLSettingsDay::ptr_t)> edit_commit_signal_t;
+    typedef boost::signals2::connection connection_t;
+
+                                LLFloaterEditExtDayCycle(const LLSD &key);
+    virtual                     ~LLFloaterEditExtDayCycle();
+
+    virtual BOOL                postBuild() override;
+    virtual void                onOpen(const LLSD& key) override;
+    virtual void                onClose(bool app_quitting) override;
+    virtual void                onFocusReceived() override;
+    virtual void                onFocusLost() override;
+    virtual void                onVisibilityChange(BOOL new_visibility) override;
+
+    connection_t                setEditCommitSignal(edit_commit_signal_t::slot_type cb);
+
+    virtual void                refresh() override;
+
+    void                        setEditDayCycle(const LLSettingsDay::ptr_t &pday);
+    void                        setEditDefaultDayCycle();
+    std::string                 getEditName() const;
+    void                        setEditName(const std::string &name);
+    LLUUID                      getEditingAssetId() { return mEditDay ? mEditDay->getAssetId() : LLUUID::null; }
+    LLUUID                      getEditingInventoryId() { return mInventoryId; }
+
+
+    BOOL			            handleKeyUp(KEY key, MASK mask, BOOL called_from_parent) override;
+
+    BOOL                        isDirty() const override { return getIsDirty(); } 
+
+private:
+    typedef std::function<void()> on_confirm_fn;
+    F32 getCurrentFrame() const;
+
+	// flyout response/click
+	void                        onButtonApply(LLUICtrl *ctrl, const LLSD &data);
+    virtual void                onClickCloseBtn(bool app_quitting = false) override;
+    void                        onButtonImport();
+    void                        onButtonLoadFrame();
+    void                        onAddFrame();
+	void                        onRemoveFrame();
+    void                        onCloneTrack();
+    void                        onLoadTrack();
+    void                        onClearTrack();
+	void                        onCommitName(class LLLineEditor* caller, void* user_data);
+	void                        onTrackSelectionCallback(const LLSD& user_data);
+	void                        onPlayActionCallback(const LLSD& user_data);
+	void                        onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsDay::ptr_t &day);
+	// time slider clicked
+	void                        onTimeSliderCallback();
+	// a frame moved or frame selection changed
+	void                        onFrameSliderCallback(const LLSD &);
+    void                        onFrameSliderDoubleClick(S32 x, S32 y, MASK mask);
+    void                        onFrameSliderMouseDown(S32 x, S32 y, MASK mask);
+    void                        onFrameSliderMouseUp(S32 x, S32 y, MASK mask);
+
+    void                        onPanelDirtyFlagChanged(bool);
+
+    void                        checkAndConfirmSettingsLoss(on_confirm_fn cb);
+
+    void                        cloneTrack(U32 source_index, U32 dest_index);
+    void                        cloneTrack(const LLSettingsDay::ptr_t &source_day, U32 source_index, U32 dest_index);
+	void                        selectTrack(U32 track_index, bool force = false);
+	void                        selectFrame(F32 frame, F32 slop_factor);
+	void                        clearTabs();
+	void                        updateTabs();
+	void                        updateWaterTabs(const LLSettingsWaterPtr_t &p_water);
+	void                        updateSkyTabs(const LLSettingsSkyPtr_t &p_sky);
+	void                        updateButtons();
+	void                        updateLabels();
+	void                        updateSlider(); //generate sliders from current track
+	void                        updateTimeAndLabel();
+	void                        addSliderFrame(F32 frame, const LLSettingsBase::ptr_t &setting, bool update_ui = true);
+    void                        removeCurrentSliderFrame();
+    void                        removeSliderFrame(F32 frame);
+
+    void                        loadInventoryItem(const LLUUID  &inventoryId, bool can_trans = true);
+    void                        onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status);
+
+    void                        doImportFromDisk();
+    void                        loadSettingFromFile(const std::vector<std::string>& filenames);
+    void                        doApplyCreateNewInventory(const LLSettingsDay::ptr_t &day, std::string settings_name);
+    void                        doApplyUpdateInventory(const LLSettingsDay::ptr_t &day);
+    void                        doApplyEnvironment(const std::string &where, const LLSettingsDay::ptr_t &day);
+    void                        doApplyCommit(LLSettingsDay::ptr_t day);
+    void                        onInventoryCreated(LLUUID asset_id, LLUUID inventory_id);
+    void                        onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+    void                        onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+
+    void                        doOpenTrackFloater(const LLSD &args);
+    void                        doCloseTrackFloater(bool quitting = false);
+    void                        onPickerCommitTrackId(U32 track_id);
+
+    void                        doOpenInventoryFloater(LLSettingsType::type_e type, LLUUID curritem);
+    void                        doCloseInventoryFloater(bool quitting = false);
+    void                        onPickerCommitSetting(LLUUID item_id, S32 track);
+    void                        onAssetLoadedForInsertion(LLUUID item_id,
+                                                          LLUUID asset_id,
+                                                          LLSettingsBase::ptr_t settings,
+                                                          S32 status,
+                                                          S32 source_track,
+                                                          S32 dest_track,
+                                                          LLSettingsBase::TrackPosition dest_frame);
+
+    bool                        canUseInventory() const;
+    bool                        canApplyRegion() const;
+    bool                        canApplyParcel() const;
+
+    void                        updateEditEnvironment();
+    void                        synchronizeTabs();
+    void                        reblendSettings();
+
+    void                        setTabsData(LLTabContainer * tabcontainer, const LLSettingsBase::ptr_t &settings, bool editable);
+
+    // play functions
+    void                        startPlay();
+    void                        stopPlay();
+    static void                 onIdlePlay(void *);
+
+    bool                        getIsDirty() const  { return mIsDirty; }
+    void                        setDirtyFlag()      { mIsDirty = true; }
+    virtual void                clearDirtyFlag();
+
+    bool                        isRemovingFrameAllowed();
+    bool                        isAddingFrameAllowed();
+
+    LLSettingsDay::ptr_t        mEditDay; // edited copy
+    LLSettingsDay::Seconds      mDayLength;
+    U32                         mCurrentTrack;
+    std::string                 mLastFrameSlider;
+    bool                        mShiftCopyEnabled;
+
+    LLUUID                      mExpectingAssetId;
+
+    LLButton*                   mAddFrameButton;
+    LLButton*                   mDeleteFrameButton;
+    LLButton*                   mImportButton;
+    LLButton*                   mLoadFrame;
+    LLButton *                  mCloneTrack;
+    LLButton *                  mLoadTrack;
+    LLButton *                  mClearTrack;
+    LLMultiSliderCtrl*	        mTimeSlider;
+    LLMultiSliderCtrl*          mFramesSlider;
+    LLView*                     mSkyTabLayoutContainer;
+    LLView*                     mWaterTabLayoutContainer;
+    LLTextBox*                  mCurrentTimeLabel;
+    LLUUID                      mInventoryId;
+    LLInventoryItem *           mInventoryItem;
+    LLFlyoutComboBtnCtrl *      mFlyoutControl;
+
+    LLHandle<LLFloater>         mInventoryFloater;
+    LLHandle<LLFloater>         mTrackFloater;
+
+    LLTrackBlenderLoopingManual::ptr_t  mSkyBlender;
+    LLTrackBlenderLoopingManual::ptr_t  mWaterBlender;
+    LLSettingsSky::ptr_t        mScratchSky;
+    LLSettingsWater::ptr_t      mScratchWater;
+    LLSettingsBase::ptr_t       mCurrentEdit;
+    LLSettingsSky::ptr_t        mEditSky;
+    LLSettingsWater::ptr_t      mEditWater;
+
+    LLFrameTimer                mPlayTimer;
+    F32                         mPlayStartFrame; // an env frame
+    bool                        mIsPlaying;
+    bool                        mIsDirty;
+    bool                        mCanCopy;
+    bool                        mCanMod;
+    bool                        mCanTrans;
+    bool                        mCanSave;
+
+    edit_commit_signal_t        mCommitSignal;
+
+    edit_context_t              mEditContext;
+
+    // For map of sliders to parameters
+    class FrameData
+    {
+    public:
+        FrameData() : mFrame(0) {};
+        FrameData(F32 frame, LLSettingsBase::ptr_t settings) : mFrame(frame), pSettings(settings) {};
+        F32 mFrame;
+        LLSettingsBase::ptr_t pSettings;
+    };
+    typedef std::map<std::string, FrameData> keymap_t;
+    keymap_t mSliderKeyMap; //slider's keys vs old_frames&settings, shadows mFramesSlider
+};
+
+#endif // LL_LLFloaterEditExtDayCycle_H
diff --git a/indra/newview/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp
index d809211ea74120b39410fcec73bd9501ea447886..6bdc5ee8233496ecdd25192bdf67d44a104132d9 100644
--- a/indra/newview/llfloatereditsky.cpp
+++ b/indra/newview/llfloatereditsky.cpp
@@ -28,6 +28,8 @@
 
 #include "llfloatereditsky.h"
 
+#include <boost/make_shared.hpp>
+
 // libs
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
@@ -38,6 +40,7 @@
 #include "llsliderctrl.h"
 #include "lltabcontainer.h"
 #include "lltimectrl.h"
+#include "lljoystickbutton.h"
 
 // newview
 #include "llagent.h"
@@ -45,15 +48,18 @@
 #include "llregioninfomodel.h"
 #include "llviewerregion.h"
 
-static const F32 WL_SUN_AMBIENT_SLIDER_SCALE = 3.0f;
-static const F32 WL_BLUE_HORIZON_DENSITY_SCALE = 2.0f;
-static const F32 WL_CLOUD_SLIDER_SCALE = 1.0f;
+#include "v3colorutil.h"
+#include "llenvironment.h"
+#include "llenvadapters.h"
 
-static F32 sun_pos_to_time24(F32 sun_pos)
+namespace
 {
-	return fmodf(sun_pos * 24.0f + 6, 24.0f);
+    const F32 WL_SUN_AMBIENT_SLIDER_SCALE(3.0f);
+    const F32 WL_BLUE_HORIZON_DENSITY_SCALE(2.0f);
+    const F32 WL_CLOUD_SLIDER_SCALE(1.0f);
 }
 
+
 static F32 time24_to_sun_pos(F32 time24)
 {
 	F32 sun_pos = fmodf((time24 - 6) / 24.0f, 1.0f);
@@ -61,12 +67,13 @@ static F32 time24_to_sun_pos(F32 time24)
 	return sun_pos;
 }
 
-LLFloaterEditSky::LLFloaterEditSky(const LLSD &key)
-:	LLFloater(key)
-,	mSkyPresetNameEditor(NULL)
-,	mSkyPresetCombo(NULL)
-,	mMakeDefaultCheckBox(NULL)
-,	mSaveButton(NULL)
+LLFloaterEditSky::LLFloaterEditSky(const LLSD &key):	
+    LLFloater(key),	
+    mSkyPresetNameEditor(NULL),	
+    mSkyPresetCombo(NULL),	
+    mMakeDefaultCheckBox(NULL),	
+    mSaveButton(NULL),
+    mSkyAdapter()
 {
 }
 
@@ -77,11 +84,14 @@ BOOL LLFloaterEditSky::postBuild()
 	mSkyPresetCombo = getChild<LLComboBox>("sky_preset_combo");
 	mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
 	mSaveButton = getChild<LLButton>("save");
+    mSkyAdapter = boost::make_shared<LLSkySettingsAdapter>();
+
+    LLEnvironment::instance().setSkyListChange(boost::bind(&LLFloaterEditSky::onSkyPresetListChange, this));
 
 	initCallbacks();
 
-	// Create the sun position scrubber on the slider.
-	getChild<LLMultiSliderCtrl>("WLSunPos")->addSlider(12.f);
+// 	// Create the sun position scrubber on the slider.
+// 	getChild<LLMultiSliderCtrl>("WLSunPos")->addSlider(12.f);
 
 	return TRUE;
 }
@@ -115,7 +125,8 @@ void LLFloaterEditSky::onClose(bool app_quitting)
 {
 	if (!app_quitting) // there's no point to change environment if we're quitting
 	{
-		LLEnvManagerNew::instance().usePrefs(); // revert changes made to current environment
+        LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
 	}
 }
 
@@ -137,71 +148,47 @@ void LLFloaterEditSky::initCallbacks(void)
 	mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditSky::onBtnSave, this));
 	getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditSky::onBtnCancel, this));
 
-	LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditSky::onRegionSettingsChange, this));
-	LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditSky::onSkyPresetListChange, this));
-
 	// Connect to region info updates.
 	LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditSky::onRegionInfoUpdate, this));
 
-	//-------------------------------------------------------------------------
-
-	LLWLParamManager& param_mgr = LLWLParamManager::instance();
-
-	// blue horizon
-	getChild<LLUICtrl>("WLBlueHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mBlueHorizon));
-
-	// haze density, horizon, mult, and altitude
-	getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mHazeDensity));
-	getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mHazeHorizon));
-	getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mDensityMult));
-	getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mMaxAlt));
-
-	// blue density
-	getChild<LLUICtrl>("WLBlueDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mBlueDensity));
-
-	// Lighting
-
 	// sunlight
-	getChild<LLUICtrl>("WLSunlight")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mSunlight));
+    getChild<LLUICtrl>("WLSunlight")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &mSkyAdapter->mSunlight));
 
 	// glow
-	getChild<LLUICtrl>("WLGlowR")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowRMoved, this, _1, &param_mgr.mGlow));
-	getChild<LLUICtrl>("WLGlowB")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowBMoved, this, _1, &param_mgr.mGlow));
-
-	// ambient
-	getChild<LLUICtrl>("WLAmbient")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mAmbient));
+    getChild<LLUICtrl>("WLGlowR")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowRMoved, this, _1, &mSkyAdapter->mGlow));
+    getChild<LLUICtrl>("WLGlowB")->setCommitCallback(boost::bind(&LLFloaterEditSky::onGlowBMoved, this, _1, &mSkyAdapter->mGlow));
 
 	// time of day
-	getChild<LLUICtrl>("WLSunPos")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &param_mgr.mLightnorm));     // multi-slider
-	getChild<LLTimeCtrl>("WLDayTime")->setCommitCallback(boost::bind(&LLFloaterEditSky::onTimeChanged, this));                          // time ctrl
-	getChild<LLUICtrl>("WLEastAngle")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &param_mgr.mLightnorm));
+//     getChild<LLUICtrl>("WLSunPos")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &mSkyAdapter->mLightnorm));     // multi-slider
+// 	getChild<LLTimeCtrl>("WLDayTime")->setCommitCallback(boost::bind(&LLFloaterEditSky::onTimeChanged, this));                          // time ctrl
+//     getChild<LLUICtrl>("WLEastAngle")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunMoved, this, _1, &mSkyAdapter->mLightnorm));
+    getChild<LLJoystickQuaternion>("WLSunRotation")->setCommitCallback(boost::bind(&LLFloaterEditSky::onSunRotationChanged, this));
+    getChild<LLJoystickQuaternion>("WLMoonRotation")->setCommitCallback(boost::bind(&LLFloaterEditSky::onMoonRotationChanged, this));
 
 	// Clouds
 
 	// Cloud Color
-	getChild<LLUICtrl>("WLCloudColor")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &param_mgr.mCloudColor));
+    getChild<LLUICtrl>("WLCloudColor")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, &mSkyAdapter->mCloudColor));
 
 	// Cloud
-	getChild<LLUICtrl>("WLCloudX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mCloudMain));
-	getChild<LLUICtrl>("WLCloudY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &param_mgr.mCloudMain));
-	getChild<LLUICtrl>("WLCloudDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &param_mgr.mCloudMain));
+    getChild<LLUICtrl>("WLCloudX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &mSkyAdapter->mCloudMain));
+    getChild<LLUICtrl>("WLCloudY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &mSkyAdapter->mCloudMain));
+    getChild<LLUICtrl>("WLCloudDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &mSkyAdapter->mCloudMain));
 
 	// Cloud Detail
-	getChild<LLUICtrl>("WLCloudDetailX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &param_mgr.mCloudDetail));
-	getChild<LLUICtrl>("WLCloudDetailY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &param_mgr.mCloudDetail));
-	getChild<LLUICtrl>("WLCloudDetailDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &param_mgr.mCloudDetail));
+    getChild<LLUICtrl>("WLCloudDetailX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, &mSkyAdapter->mCloudDetail));
+    getChild<LLUICtrl>("WLCloudDetailY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlGMoved, this, _1, &mSkyAdapter->mCloudDetail));
+    getChild<LLUICtrl>("WLCloudDetailDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlBMoved, this, _1, &mSkyAdapter->mCloudDetail));
 
 	// Cloud extras
-	getChild<LLUICtrl>("WLCloudCoverage")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mCloudCoverage));
-	getChild<LLUICtrl>("WLCloudScale")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mCloudScale));
-	getChild<LLUICtrl>("WLCloudLockX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollXToggled, this, _1));
-	getChild<LLUICtrl>("WLCloudLockY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollYToggled, this, _1));
+    getChild<LLUICtrl>("WLCloudCoverage")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &mSkyAdapter->mCloudCoverage));
+    getChild<LLUICtrl>("WLCloudScale")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &mSkyAdapter->mCloudScale));
 	getChild<LLUICtrl>("WLCloudScrollX")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollXMoved, this, _1));
 	getChild<LLUICtrl>("WLCloudScrollY")->setCommitCallback(boost::bind(&LLFloaterEditSky::onCloudScrollYMoved, this, _1));
-	getChild<LLUICtrl>("WLDistanceMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mDistanceMult));
+    
 
 	// Dome
-	getChild<LLUICtrl>("WLGamma")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &param_mgr.mWLGamma));
+    getChild<LLUICtrl>("WLGamma")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, &mSkyAdapter->mWLGamma));
 	getChild<LLUICtrl>("WLStarAlpha")->setCommitCallback(boost::bind(&LLFloaterEditSky::onStarAlphaMoved, this, _1));
 }
 
@@ -209,320 +196,229 @@ void LLFloaterEditSky::initCallbacks(void)
 
 void LLFloaterEditSky::syncControls()
 {
-	bool err;
-
-	LLWLParamManager * param_mgr = LLWLParamManager::getInstance();
-
-	LLWLParamSet& cur_params = param_mgr->mCurParams;
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+    mEditSettings = psky;
 
-	// blue horizon
-	param_mgr->mBlueHorizon = cur_params.getVector(param_mgr->mBlueHorizon.mName, err);
-	setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE);
+    std::string name = psky->getName();
 
-	// haze density, horizon, mult, and altitude
-	param_mgr->mHazeDensity = cur_params.getFloat(param_mgr->mHazeDensity.mName, err);
-	childSetValue("WLHazeDensity", (F32) param_mgr->mHazeDensity);
-	param_mgr->mHazeHorizon = cur_params.getFloat(param_mgr->mHazeHorizon.mName, err);
-	childSetValue("WLHazeHorizon", (F32) param_mgr->mHazeHorizon);
-	param_mgr->mDensityMult = cur_params.getFloat(param_mgr->mDensityMult.mName, err);
-	childSetValue("WLDensityMult", ((F32) param_mgr->mDensityMult) * param_mgr->mDensityMult.mult);
-	param_mgr->mMaxAlt = cur_params.getFloat(param_mgr->mMaxAlt.mName, err);
-	childSetValue("WLMaxAltitude", (F32) param_mgr->mMaxAlt);
-
-	// blue density
-	param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err);
-	setColorSwatch("WLBlueDensity", param_mgr->mBlueDensity, WL_BLUE_HORIZON_DENSITY_SCALE);
+    mSkyPresetNameEditor->setText(name);
+    mSkyPresetCombo->setValue(name);
 
 	// Lighting
 
 	// sunlight
-	param_mgr->mSunlight = cur_params.getVector(param_mgr->mSunlight.mName, err);
-	setColorSwatch("WLSunlight", param_mgr->mSunlight, WL_SUN_AMBIENT_SLIDER_SCALE);
+    mSkyAdapter->mSunlight.setColor3( psky->getSunlightColor() );
+	setColorSwatch("WLSunlight", mSkyAdapter->mSunlight, WL_SUN_AMBIENT_SLIDER_SCALE);
 
 	// glow
-	param_mgr->mGlow = cur_params.getVector(param_mgr->mGlow.mName, err);
-	childSetValue("WLGlowR", 2 - param_mgr->mGlow.r / 20.0f);
-	childSetValue("WLGlowB", -param_mgr->mGlow.b / 5.0f);
-
-	// ambient
-	param_mgr->mAmbient = cur_params.getVector(param_mgr->mAmbient.mName, err);
-	setColorSwatch("WLAmbient", param_mgr->mAmbient, WL_SUN_AMBIENT_SLIDER_SCALE);
-
-	F32 time24 = sun_pos_to_time24(param_mgr->mCurParams.getFloat("sun_angle",err) / F_TWO_PI);
-	getChild<LLMultiSliderCtrl>("WLSunPos")->setCurSliderValue(time24, TRUE);
-	getChild<LLTimeCtrl>("WLDayTime")->setTime24(time24);
-	childSetValue("WLEastAngle", param_mgr->mCurParams.getFloat("east_angle",err) / F_TWO_PI);
+    mSkyAdapter->mGlow.setColor3( psky->getGlow() );
+	childSetValue("WLGlowR", 2 - mSkyAdapter->mGlow.getRed() / 20.0f);
+	childSetValue("WLGlowB", -mSkyAdapter->mGlow.getBlue() / 5.0f);
+
+// LLSettingsSky::azimalt_t azal = psky->getSunRotationAzAl();
+// 
+// 	F32 time24 = sun_pos_to_time24(azal.second / F_TWO_PI);
+// 	getChild<LLMultiSliderCtrl>("WLSunPos")->setCurSliderValue(time24, TRUE);
+// 	getChild<LLTimeCtrl>("WLDayTime")->setTime24(time24);
+// 	childSetValue("WLEastAngle", azal.first / F_TWO_PI);
+    getChild<LLJoystickQuaternion>("WLSunRotation")->setRotation(psky->getSunRotation());
+    getChild<LLJoystickQuaternion>("WLMoonRotation")->setRotation(psky->getMoonRotation());
 
 	// Clouds
 
 	// Cloud Color
-	param_mgr->mCloudColor = cur_params.getVector(param_mgr->mCloudColor.mName, err);
-	setColorSwatch("WLCloudColor", param_mgr->mCloudColor, WL_CLOUD_SLIDER_SCALE);
+    mSkyAdapter->mCloudColor.setColor3( psky->getCloudColor() );
+	setColorSwatch("WLCloudColor", mSkyAdapter->mCloudColor, WL_CLOUD_SLIDER_SCALE);
 
 	// Cloud
-	param_mgr->mCloudMain = cur_params.getVector(param_mgr->mCloudMain.mName, err);
-	childSetValue("WLCloudX", param_mgr->mCloudMain.r);
-	childSetValue("WLCloudY", param_mgr->mCloudMain.g);
-	childSetValue("WLCloudDensity", param_mgr->mCloudMain.b);
+    mSkyAdapter->mCloudMain.setColor3( psky->getCloudPosDensity1() );
+	childSetValue("WLCloudX", mSkyAdapter->mCloudMain.getRed());
+	childSetValue("WLCloudY", mSkyAdapter->mCloudMain.getGreen());
+	childSetValue("WLCloudDensity", mSkyAdapter->mCloudMain.getBlue());
 
 	// Cloud Detail
-	param_mgr->mCloudDetail = cur_params.getVector(param_mgr->mCloudDetail.mName, err);
-	childSetValue("WLCloudDetailX", param_mgr->mCloudDetail.r);
-	childSetValue("WLCloudDetailY", param_mgr->mCloudDetail.g);
-	childSetValue("WLCloudDetailDensity", param_mgr->mCloudDetail.b);
+	mSkyAdapter->mCloudDetail.setColor3( psky->getCloudPosDensity2() );
+	childSetValue("WLCloudDetailX", mSkyAdapter->mCloudDetail.getRed());
+	childSetValue("WLCloudDetailY", mSkyAdapter->mCloudDetail.getGreen());
+	childSetValue("WLCloudDetailDensity", mSkyAdapter->mCloudDetail.getBlue());
 
 	// Cloud extras
-	param_mgr->mCloudCoverage = cur_params.getFloat(param_mgr->mCloudCoverage.mName, err);
-	param_mgr->mCloudScale = cur_params.getFloat(param_mgr->mCloudScale.mName, err);
-	childSetValue("WLCloudCoverage", (F32) param_mgr->mCloudCoverage);
-	childSetValue("WLCloudScale", (F32) param_mgr->mCloudScale);
+    mSkyAdapter->mCloudCoverage = psky->getCloudShadow();
+    mSkyAdapter->mCloudScale = psky->getCloudScale();
+	childSetValue("WLCloudCoverage", (F32) mSkyAdapter->mCloudCoverage);
+	childSetValue("WLCloudScale", (F32) mSkyAdapter->mCloudScale);
 
 	// cloud scrolling
-	bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX();
-	bool lockY = !param_mgr->mCurParams.getEnableCloudScrollY();
-	childSetValue("WLCloudLockX", lockX);
-	childSetValue("WLCloudLockY", lockY);
+    LLVector2 scroll_rate = psky->getCloudScrollRate();
+
+    // LAPRAS: These should go away...
+    childDisable("WLCloudLockX");
+ 	childDisable("WLCloudLockY");
 
 	// disable if locked, enable if not
-	if (lockX)
-	{
-		childDisable("WLCloudScrollX");
-	}
-	else
-	{
-		childEnable("WLCloudScrollX");
-	}
-	if (lockY)
-	{
-		childDisable("WLCloudScrollY");
-	}
-	else
-	{
-		childEnable("WLCloudScrollY");
-	}
+	childEnable("WLCloudScrollX");
+	childEnable("WLCloudScrollY");
 
 	// *HACK cloud scrolling is off my an additive of 10
-	childSetValue("WLCloudScrollX", param_mgr->mCurParams.getCloudScrollX() - 10.0f);
-	childSetValue("WLCloudScrollY", param_mgr->mCurParams.getCloudScrollY() - 10.0f);
-
-	param_mgr->mDistanceMult = cur_params.getFloat(param_mgr->mDistanceMult.mName, err);
-	childSetValue("WLDistanceMult", (F32) param_mgr->mDistanceMult);
+	childSetValue("WLCloudScrollX", scroll_rate[0] - 10.0f);
+	childSetValue("WLCloudScrollY", scroll_rate[1] - 10.0f);
 
 	// Tweak extras
 
-	param_mgr->mWLGamma = cur_params.getFloat(param_mgr->mWLGamma.mName, err);
-	childSetValue("WLGamma", (F32) param_mgr->mWLGamma);
+    mSkyAdapter->mWLGamma = psky->getGamma();
+	childSetValue("WLGamma", (F32) mSkyAdapter->mWLGamma);
 
-	childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());
+	childSetValue("WLStarAlpha", psky->getStarBrightness());
 }
 
 void LLFloaterEditSky::setColorSwatch(const std::string& name, const WLColorControl& from_ctrl, F32 k)
 {
 	// Set the value, dividing it by <k> first.
-	LLVector4 color_vec = from_ctrl;
-	getChild<LLColorSwatchCtrl>(name)->set(LLColor4(color_vec / k));
+	LLColor4 color = from_ctrl.getColor4();
+	getChild<LLColorSwatchCtrl>(name)->set(color / k);
 }
 
 // color control callbacks
 void LLFloaterEditSky::onColorControlMoved(LLUICtrl* ctrl, WLColorControl* color_ctrl)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
-	LLVector4 color_vec(swatch->get().mV);
-
-	// Set intensity to maximum of the RGB values.
-	color_vec.mV[3] = llmax(color_vec.mV[0], llmax(color_vec.mV[1], color_vec.mV[2]));
+	LLColor4 color_vec(swatch->get().mV);
 
 	// Multiply RGB values by the appropriate factor.
 	F32 k = WL_CLOUD_SLIDER_SCALE;
-	if (color_ctrl->isSunOrAmbientColor)
+	if (color_ctrl->getIsSunOrAmbientColor())
 	{
 		k = WL_SUN_AMBIENT_SLIDER_SCALE;
 	}
-	if (color_ctrl->isBlueHorizonOrDensity)
+	else if (color_ctrl->getIsBlueHorizonOrDensity())
 	{
 		k = WL_BLUE_HORIZON_DENSITY_SCALE;
 	}
 
 	color_vec *= k; // intensity isn't affected by the multiplication
 
+    // Set intensity to maximum of the RGB values.
+    color_vec.mV[3] = color_max(color_vec);
+
 	// Apply the new RGBI value.
-	*color_ctrl = color_vec;
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
-	LLWLParamManager::getInstance()->propagateParameters();
+	color_ctrl->setColor4(color_vec);
+	color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditSky::onColorControlRMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 	WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
 
-	color_ctrl->r = sldr_ctrl->getValueF32();
-	if (color_ctrl->isSunOrAmbientColor)
-	{
-		color_ctrl->r *= WL_SUN_AMBIENT_SLIDER_SCALE;
-	}
-	if (color_ctrl->isBlueHorizonOrDensity)
+    F32 red_value = sldr_ctrl->getValueF32();
+    F32 k = 1.0f;
+
+	if (color_ctrl->getIsSunOrAmbientColor())
 	{
-		color_ctrl->r *= WL_BLUE_HORIZON_DENSITY_SCALE;
+		k = WL_SUN_AMBIENT_SLIDER_SCALE;
 	}
-
-	// move i if it's the max
-	if (color_ctrl->r >= color_ctrl->g && color_ctrl->r >= color_ctrl->b && color_ctrl->hasSliderName)
+	if (color_ctrl->getIsBlueHorizonOrDensity())
 	{
-		color_ctrl->i = color_ctrl->r;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		if (color_ctrl->isSunOrAmbientColor)
-		{
-			childSetValue(name, color_ctrl->r / WL_SUN_AMBIENT_SLIDER_SCALE);
-		}
-		else if	(color_ctrl->isBlueHorizonOrDensity)
-		{
-			childSetValue(name, color_ctrl->r / WL_BLUE_HORIZON_DENSITY_SCALE);
-		}
-		else
-		{
-			childSetValue(name, color_ctrl->r);
-		}
+		k = WL_BLUE_HORIZON_DENSITY_SCALE;
 	}
+    color_ctrl->setRed(red_value * k);
 
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
-
-	LLWLParamManager::getInstance()->propagateParameters();
+    adjustIntensity(color_ctrl, red_value, k);
+    color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditSky::onColorControlGMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+    WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
 
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-	WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+    F32 green_value = sldr_ctrl->getValueF32();
+    F32 k = 1.0f;
 
-	color_ctrl->g = sldr_ctrl->getValueF32();
-	if (color_ctrl->isSunOrAmbientColor)
-	{
-		color_ctrl->g *= WL_SUN_AMBIENT_SLIDER_SCALE;
-	}
-	if (color_ctrl->isBlueHorizonOrDensity)
-	{
-		color_ctrl->g *= WL_BLUE_HORIZON_DENSITY_SCALE;
-	}
+    if (color_ctrl->getIsSunOrAmbientColor())
+    {
+        k = WL_SUN_AMBIENT_SLIDER_SCALE;
+    }
+    if (color_ctrl->getIsBlueHorizonOrDensity())
+    {
+        k = WL_BLUE_HORIZON_DENSITY_SCALE;
+    }
+    color_ctrl->setGreen(green_value * k);
 
-	// move i if it's the max
-	if (color_ctrl->g >= color_ctrl->r && color_ctrl->g >= color_ctrl->b && color_ctrl->hasSliderName)
-	{
-		color_ctrl->i = color_ctrl->g;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		if (color_ctrl->isSunOrAmbientColor)
-		{
-			childSetValue(name, color_ctrl->g / WL_SUN_AMBIENT_SLIDER_SCALE);
-		}
-		else if (color_ctrl->isBlueHorizonOrDensity)
-		{
-			childSetValue(name, color_ctrl->g / WL_BLUE_HORIZON_DENSITY_SCALE);
-		}
-		else
-		{
-			childSetValue(name, color_ctrl->g);
-		}
-	}
-
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
-
-	LLWLParamManager::getInstance()->propagateParameters();
+    adjustIntensity(color_ctrl, green_value, k);
+    color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditSky::onColorControlBMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+    WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
 
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-	WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
+    F32 blue_value = sldr_ctrl->getValueF32();
+    F32 k = 1.0f;
 
-	color_ctrl->b = sldr_ctrl->getValueF32();
-	if (color_ctrl->isSunOrAmbientColor)
-	{
-		color_ctrl->b *= WL_SUN_AMBIENT_SLIDER_SCALE;
-	}
-	if (color_ctrl->isBlueHorizonOrDensity)
-	{
-		color_ctrl->b *= WL_BLUE_HORIZON_DENSITY_SCALE;
-	}
+    if (color_ctrl->getIsSunOrAmbientColor())
+    {
+        k = WL_SUN_AMBIENT_SLIDER_SCALE;
+    }
+    if (color_ctrl->getIsBlueHorizonOrDensity())
+    {
+        k = WL_BLUE_HORIZON_DENSITY_SCALE;
+    }
+    color_ctrl->setBlue(blue_value * k);
 
-	// move i if it's the max
-	if (color_ctrl->b >= color_ctrl->r && color_ctrl->b >= color_ctrl->g && color_ctrl->hasSliderName)
-	{
-		color_ctrl->i = color_ctrl->b;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		if (color_ctrl->isSunOrAmbientColor)
-		{
-			childSetValue(name, color_ctrl->b / WL_SUN_AMBIENT_SLIDER_SCALE);
-		}
-		else if (color_ctrl->isBlueHorizonOrDensity)
-		{
-			childSetValue(name, color_ctrl->b / WL_BLUE_HORIZON_DENSITY_SCALE);
-		}
-		else
-		{
-			childSetValue(name, color_ctrl->b);
-		}
-	}
+    adjustIntensity(color_ctrl, blue_value, k);
+    color_ctrl->update(mEditSettings);
+}
 
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
+void LLFloaterEditSky::adjustIntensity(WLColorControl *ctrl, F32 val, F32 scale)
+{
+    if (ctrl->getHasSliderName())
+    {
+        LLColor4 color = ctrl->getColor4();
+        F32 i = color_max(color) / scale;
+        ctrl->setIntensity(i);
+        std::string name = ctrl->getSliderName();
+        name.append("I");
 
-	LLWLParamManager::getInstance()->propagateParameters();
+        childSetValue(name, i);
+    }
 }
 
+
 /// GLOW SPECIFIC CODE
 void LLFloaterEditSky::onGlowRMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
 
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 	WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
 
 	// scaled by 20
-	color_ctrl->r = (2 - sldr_ctrl->getValueF32()) * 20;
+	color_ctrl->setRed((2 - sldr_ctrl->getValueF32()) * 20);
 
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
-	LLWLParamManager::getInstance()->propagateParameters();
+	color_ctrl->update(mEditSettings);
 }
 
 /// \NOTE that we want NEGATIVE (-) B
 void LLFloaterEditSky::onGlowBMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 	WLColorControl* color_ctrl = static_cast<WLColorControl *>(userdata);
 
 	/// \NOTE that we want NEGATIVE (-) B and NOT by 20 as 20 is too big
-	color_ctrl->b = -sldr_ctrl->getValueF32() * 5;
+	color_ctrl->setBlue(-sldr_ctrl->getValueF32() * 5);
 
-	color_ctrl->update(LLWLParamManager::getInstance()->mCurParams);
-	LLWLParamManager::getInstance()->propagateParameters();
+	color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditSky::onFloatControlMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 	WLFloatControl * floatControl = static_cast<WLFloatControl *>(userdata);
 
-	floatControl->x = sldr_ctrl->getValueF32() / floatControl->mult;
+	floatControl->setValue(sldr_ctrl->getValueF32() / floatControl->getMult());
 
-	floatControl->update(LLWLParamManager::getInstance()->mCurParams);
-	LLWLParamManager::getInstance()->propagateParameters();
+	floatControl->update(mEditSettings);
 }
 
 
@@ -531,8 +427,6 @@ void LLFloaterEditSky::onFloatControlMoved(LLUICtrl* ctrl, void* userdata)
 // time of day
 void LLFloaterEditSky::onSunMoved(LLUICtrl* ctrl, void* userdata)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLMultiSliderCtrl* sun_msldr = getChild<LLMultiSliderCtrl>("WLSunPos");
 	LLSliderCtrl* east_sldr = getChild<LLSliderCtrl>("WLEastAngle");
 	LLTimeCtrl* time_ctrl = getChild<LLTimeCtrl>("WLDayTime");
@@ -542,99 +436,60 @@ void LLFloaterEditSky::onSunMoved(LLUICtrl* ctrl, void* userdata)
 	time_ctrl->setTime24(time24); // sync the time ctrl with the new sun position
 
 	// get the two angles
-	LLWLParamManager * param_mgr = LLWLParamManager::getInstance();
-
-	param_mgr->mCurParams.setSunAngle(F_TWO_PI * time24_to_sun_pos(time24));
-	param_mgr->mCurParams.setEastAngle(F_TWO_PI * east_sldr->getValueF32());
+    F32 azimuth = F_TWO_PI * east_sldr->getValueF32();
+    F32 altitude = F_TWO_PI * time24_to_sun_pos(time24);
+    mEditSettings->setSunRotation(azimuth, altitude);
+    mEditSettings->setMoonRotation(azimuth + F_PI, -altitude);
 
-	// set the sun vector
-	color_ctrl->r = -sin(param_mgr->mCurParams.getEastAngle()) *
-		cos(param_mgr->mCurParams.getSunAngle());
-	color_ctrl->g = sin(param_mgr->mCurParams.getSunAngle());
-	color_ctrl->b = cos(param_mgr->mCurParams.getEastAngle()) *
-		cos(param_mgr->mCurParams.getSunAngle());
-	color_ctrl->i = 1.f;
+    LLVector4 sunnorm( mEditSettings->getSunDirection(), 1.f );
 
-	color_ctrl->update(param_mgr->mCurParams);
-	param_mgr->propagateParameters();
+	color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditSky::onTimeChanged()
 {
 	F32 time24 = getChild<LLTimeCtrl>("WLDayTime")->getTime24();
 	getChild<LLMultiSliderCtrl>("WLSunPos")->setCurSliderValue(time24, TRUE);
-	onSunMoved(getChild<LLUICtrl>("WLSunPos"), &LLWLParamManager::instance().mLightnorm);
+    onSunMoved(getChild<LLUICtrl>("WLSunPos"), &(mSkyAdapter->mLightnorm));
 }
 
-void LLFloaterEditSky::onStarAlphaMoved(LLUICtrl* ctrl)
+void LLFloaterEditSky::onSunRotationChanged()
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+    LLJoystickQuaternion* sun_spinner = getChild<LLJoystickQuaternion>("WLSunRotation");
+    LLQuaternion sunrot(sun_spinner->getRotation());
 
-	LLWLParamManager::getInstance()->mCurParams.setStarBrightness(sldr_ctrl->getValueF32());
+    mEditSettings->setSunRotation(sunrot);
 }
 
-// Clouds
-void LLFloaterEditSky::onCloudScrollXMoved(LLUICtrl* ctrl)
+void LLFloaterEditSky::onMoonRotationChanged()
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
+    LLJoystickQuaternion* moon_spinner = getChild<LLJoystickQuaternion>("WLMoonRotation");
+    LLQuaternion moonrot(moon_spinner->getRotation());
 
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-	// *HACK  all cloud scrolling is off by an additive of 10.
-	LLWLParamManager::getInstance()->mCurParams.setCloudScrollX(sldr_ctrl->getValueF32() + 10.0f);
+    mEditSettings->setMoonRotation(moonrot);
 }
 
-void LLFloaterEditSky::onCloudScrollYMoved(LLUICtrl* ctrl)
+void LLFloaterEditSky::onStarAlphaMoved(LLUICtrl* ctrl)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	// *HACK  all cloud scrolling is off by an additive of 10.
-	LLWLParamManager::getInstance()->mCurParams.setCloudScrollY(sldr_ctrl->getValueF32() + 10.0f);
+    mEditSettings->setStarBrightness(sldr_ctrl->getValueF32());
 }
 
-void LLFloaterEditSky::onCloudScrollXToggled(LLUICtrl* ctrl)
+// Clouds
+void LLFloaterEditSky::onCloudScrollXMoved(LLUICtrl* ctrl)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
-	LLCheckBoxCtrl* cb_ctrl = static_cast<LLCheckBoxCtrl*>(ctrl);
-
-	bool lock = cb_ctrl->get();
-	LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollX(!lock);
-
-	LLSliderCtrl* sldr = getChild<LLSliderCtrl>("WLCloudScrollX");
-
-	if (cb_ctrl->get())
-	{
-		sldr->setEnabled(false);
-	}
-	else
-	{
-		sldr->setEnabled(true);
-	}
-
+	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+	// *HACK  all cloud scrolling is off by an additive of 10.
+    mEditSettings->setCloudScrollRateX(sldr_ctrl->getValueF32() + 10.0f);
 }
 
-void LLFloaterEditSky::onCloudScrollYToggled(LLUICtrl* ctrl)
+void LLFloaterEditSky::onCloudScrollYMoved(LLUICtrl* ctrl)
 {
-	LLWLParamManager::getInstance()->mAnimator.deactivate();
-
-	LLCheckBoxCtrl* cb_ctrl = static_cast<LLCheckBoxCtrl*>(ctrl);
-	bool lock = cb_ctrl->get();
-	LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollY(!lock);
-
-	LLSliderCtrl* sldr = getChild<LLSliderCtrl>("WLCloudScrollY");
+	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	if (cb_ctrl->get())
-	{
-		sldr->setEnabled(false);
-	}
-	else
-	{
-		sldr->setEnabled(true);
-	}
+	// *HACK  all cloud scrolling is off by an additive of 10.
+    mEditSettings->setCloudScrollRateY(sldr_ctrl->getValueF32() + 10.0f);
 }
 
 //=================================================================================================
@@ -664,38 +519,12 @@ void LLFloaterEditSky::refreshSkyPresetsList()
 {
 	mSkyPresetCombo->removeall();
 
-	LLWLParamManager::preset_name_list_t region_presets, user_presets, sys_presets;
-	LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
+    LLEnvironment::list_name_id_t list = LLEnvironment::instance().getSkyList();
 
-#if 0 // Disable editing region skies until the workflow is clear enough.
-	// Add region presets.
-	std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
-	{
-		std::string item_title = *it + " (" + region_name + ")";
-		mSkyPresetCombo->add(item_title, LLWLParamKey(*it, LLEnvKey::SCOPE_REGION).toLLSD());
-	}
-	if (region_presets.size() > 0)
-	{
-		mSkyPresetCombo->addSeparator();
-	}
-#endif
-
-	// Add user presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
-	if (user_presets.size() > 0)
-	{
-		mSkyPresetCombo->addSeparator();
-	}
-
-	// Add system presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
+    for (LLEnvironment::list_name_id_t::iterator it = list.begin(); it != list.end(); ++it)
+    {
+        mSkyPresetCombo->add((*it).first, LLSDArray((*it).first)((*it).second));
+    }
 
 	mSkyPresetCombo->setLabel(getString("combo_label"));
 }
@@ -718,6 +547,7 @@ void LLFloaterEditSky::enableEditing(bool enable)
 
 void LLFloaterEditSky::saveRegionSky()
 {
+#if 0
 	LLWLParamKey key(getSelectedSkyPreset());
 	llassert(key.scope == LLEnvKey::SCOPE_REGION);
 
@@ -728,61 +558,55 @@ void LLFloaterEditSky::saveRegionSky()
 
 	// *TODO: save to cached region settings.
 	LL_WARNS("Windlight") << "Saving region sky is not fully implemented yet" << LL_ENDL;
+#endif
 }
 
-LLWLParamKey LLFloaterEditSky::getSelectedSkyPreset()
+std::string LLFloaterEditSky::getSelectedPresetName() const
 {
-	LLWLParamKey key;
-
-	if (mSkyPresetNameEditor->getVisible())
-	{
-		key.name = mSkyPresetNameEditor->getText();
-		key.scope = LLEnvKey::SCOPE_LOCAL;
-	}
-	else
-	{
-		LLSD combo_val = mSkyPresetCombo->getValue();
-
-		if (!combo_val.isArray()) // manually typed text
-		{
-			key.name = combo_val.asString();
-			key.scope = LLEnvKey::SCOPE_LOCAL;
-		}
-		else
-		{
-			key.fromLLSD(combo_val);
-		}
-	}
+    std::string name;
+    if (mSkyPresetNameEditor->getVisible())
+    {
+        name = mSkyPresetNameEditor->getText();
+    }
+    else
+    {
+        LLSD combo_val = mSkyPresetCombo->getValue();
+        name = combo_val[0].asString();
+    }
 
-	return key;
+    return name;
 }
 
 void LLFloaterEditSky::onSkyPresetNameEdited()
 {
-	// Disable saving a sky preset having empty name.
-	LLWLParamKey key = getSelectedSkyPreset();
-	mSaveButton->setEnabled(!key.name.empty());
+    std::string name = mSkyPresetNameEditor->getText();
+    LLSettingsWater::ptr_t psky = LLEnvironment::instance().getCurrentWater();
+
+    psky->setName(name);
 }
 
 void LLFloaterEditSky::onSkyPresetSelected()
 {
-	LLWLParamKey key = getSelectedSkyPreset();
-	LLWLParamSet sky_params;
+    std::string name;
 
-	if (!LLWLParamManager::instance().getParamSet(key, sky_params))
-	{
-		// Manually entered string?
-		LL_WARNS("Windlight") << "No sky preset named " << key.toString() << LL_ENDL;
-		return;
-	}
+    name = getSelectedPresetName();
 
-	LLEnvManagerNew::instance().useSkyParams(sky_params.getAll());
-	//syncControls();
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().findSkyByName(name);
 
-	bool can_edit = (key.scope == LLEnvKey::SCOPE_LOCAL || LLEnvManagerNew::canEditRegionSettings());
-	enableEditing(can_edit);
+    if (!psky)
+    {
+        LL_WARNS("WATEREDIT") << "Could not find water preset" << LL_ENDL;
+        enableEditing(false);
+        return;
+    }
+
+    psky = psky->buildClone();
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, psky);
+    mEditSettings = psky;
+
+    syncControls();
+    enableEditing(true);
 
-	mMakeDefaultCheckBox->setEnabled(key.scope == LLEnvKey::SCOPE_LOCAL);
 }
 
 bool LLFloaterEditSky::onSaveAnswer(const LLSD& notification, const LLSD& response)
@@ -800,69 +624,29 @@ bool LLFloaterEditSky::onSaveAnswer(const LLSD& notification, const LLSD& respon
 
 void LLFloaterEditSky::onSaveConfirmed()
 {
-	// Save current params to the selected preset.
-	LLWLParamKey key(getSelectedSkyPreset());
+    // Save currently displayed water params to the selected preset.
+    std::string name = mEditSettings->getName();
 
-	LL_DEBUGS("Windlight") << "Saving sky preset " << key.name << LL_ENDL;
-	LLWLParamManager& wl_mgr = LLWLParamManager::instance();
-	if (wl_mgr.hasParamSet(key))
-	{
-		wl_mgr.setParamSet(key, wl_mgr.mCurParams);
-	}
-	else
-	{
-		wl_mgr.addParamSet(key, wl_mgr.mCurParams);
-	}
+    LL_DEBUGS("Windlight") << "Saving sky preset " << name << LL_ENDL;
 
-	wl_mgr.savePreset(key);
+    LLEnvironment::instance().addSky(mEditSettings);
 
-	// Change preference if requested.
-	if (mMakeDefaultCheckBox->getValue())
-	{
-		LL_DEBUGS("Windlight") << key.name << " is now the new preferred sky preset" << LL_ENDL;
-		LLEnvManagerNew::instance().setUseSkyPreset(key.name);
-	}
+    // Change preference if requested.
+    if (mMakeDefaultCheckBox->getEnabled() && mMakeDefaultCheckBox->getValue())
+    {
+        LL_DEBUGS("Windlight") << name << " is now the new preferred sky preset" << LL_ENDL;
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, mEditSettings);
+    }
 
-	closeFloater();
+    closeFloater();
 }
 
 void LLFloaterEditSky::onBtnSave()
 {
-	LLWLParamKey selected_sky = getSelectedSkyPreset();
-	LLWLParamManager& wl_mgr = LLWLParamManager::instance();
-
-	if (selected_sky.scope == LLEnvKey::SCOPE_REGION)
-	{
-		saveRegionSky();
-		closeFloater();
-		return;
-	}
+    LLEnvironment::instance().addSky(mEditSettings);
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, mEditSettings);
 
-	std::string name = selected_sky.name;
-	if (name.empty())
-	{
-		// *TODO: show an alert
-		LL_WARNS() << "Empty sky preset name" << LL_ENDL;
-		return;
-	}
-
-	// Don't allow overwriting system presets.
-	if (wl_mgr.isSystemPreset(name))
-	{
-		LLNotificationsUtil::add("WLNoEditDefault");
-		return;
-	}
-
-	// Save, ask for confirmation for overwriting an existing preset.
-	if (wl_mgr.hasParamSet(selected_sky))
-	{
-		LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditSky::onSaveAnswer, this, _1, _2));
-	}
-	else
-	{
-		// new preset, hence no confirmation needed
-		onSaveConfirmed();
-	}
+    closeFloater();
 }
 
 void LLFloaterEditSky::onBtnCancel()
@@ -872,22 +656,12 @@ void LLFloaterEditSky::onBtnCancel()
 
 void LLFloaterEditSky::onSkyPresetListChange()
 {
-	LLWLParamKey key = getSelectedSkyPreset(); // preset being edited
-	if (!LLWLParamManager::instance().hasParamSet(key))
-	{
-		// Preset we've been editing doesn't exist anymore. Close the floater.
-		closeFloater(false);
-	}
-	else
-	{
-		// A new preset has been added.
-		// Refresh the presets list, though it may not make sense as the floater is about to be closed.
-		refreshSkyPresetsList();
-	}
+    refreshSkyPresetsList();
 }
 
 void LLFloaterEditSky::onRegionSettingsChange()
 {
+#if 0
 	// If creating a new sky, don't bother.
 	if (isNewPreset())
 	{
@@ -905,10 +679,12 @@ void LLFloaterEditSky::onRegionSettingsChange()
 	{
 		refreshSkyPresetsList();
 	}
+#endif
 }
 
 void LLFloaterEditSky::onRegionInfoUpdate()
 {
+#if 0
 	bool can_edit = true;
 
 	// If we've selected a region sky preset for editing.
@@ -919,4 +695,5 @@ void LLFloaterEditSky::onRegionInfoUpdate()
 	}
 
 	enableEditing(can_edit);
+#endif
 }
diff --git a/indra/newview/llfloatereditsky.h b/indra/newview/llfloatereditsky.h
deleted file mode 100644
index a06c4fc5fab8e21a52b88897be6fb8576fabe5a7..0000000000000000000000000000000000000000
--- a/indra/newview/llfloatereditsky.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/** 
- * @file llfloatereditsky.h
- * @brief Floater to create or edit a sky preset
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLFLOATEREDITSKY_H
-#define LL_LLFLOATEREDITSKY_H
-
-#include "llfloater.h"
-#include "llwlparammanager.h"
-
-class LLButton;
-class LLCheckBoxCtrl;
-class LLComboBox;
-class LLLineEditor;
-
-/**
- * Floater for creating or editing a sky preset.
- */
-class LLFloaterEditSky : public LLFloater
-{
-	LOG_CLASS(LLFloaterEditSky);
-
-public:
-	LLFloaterEditSky(const LLSD &key);
-
-	/*virtual*/	BOOL	postBuild();
-	/*virtual*/ void	onOpen(const LLSD& key);
-	/*virtual*/ void	onClose(bool app_quitting);
-	/*virtual*/ void	draw();
-
-private:
-	void initCallbacks(void);
-
-	//-- WL stuff begins ------------------------------------------------------
-
-	void syncControls(); /// sync up sliders with parameters
-
-	void setColorSwatch(const std::string& name, const WLColorControl& from_ctrl, F32 k);
-
-	// general purpose callbacks for dealing with color controllers
-	void onColorControlMoved(LLUICtrl* ctrl, WLColorControl* color_ctrl);
-	void onColorControlRMoved(LLUICtrl* ctrl, void* userdata);
-	void onColorControlGMoved(LLUICtrl* ctrl, void* userdata);
-	void onColorControlBMoved(LLUICtrl* ctrl, void* userdata);
-	void onFloatControlMoved(LLUICtrl* ctrl, void* userdata);
-
-	// lighting callbacks for glow
-	void onGlowRMoved(LLUICtrl* ctrl, void* userdata);
-	void onGlowBMoved(LLUICtrl* ctrl, void* userdata);
-
-	// lighting callbacks for sun
-	void onSunMoved(LLUICtrl* ctrl, void* userdata);
-	void onTimeChanged();
-
-	// for handling when the star slider is moved to adjust the alpha
-	void onStarAlphaMoved(LLUICtrl* ctrl);
-
-	// handle cloud scrolling
-	void onCloudScrollXMoved(LLUICtrl* ctrl);
-	void onCloudScrollYMoved(LLUICtrl* ctrl);
-	void onCloudScrollXToggled(LLUICtrl* ctrl);
-	void onCloudScrollYToggled(LLUICtrl* ctrl);
-
-	//-- WL stuff ends --------------------------------------------------------
-
-	void reset(); /// reset the floater to its initial state
-	bool isNewPreset() const;
-	void refreshSkyPresetsList();
-	void enableEditing(bool enable);
-	void saveRegionSky();
-	LLWLParamKey getSelectedSkyPreset();
-
-	void onSkyPresetNameEdited();
-	void onSkyPresetSelected();
-	bool onSaveAnswer(const LLSD& notification, const LLSD& response);
-	void onSaveConfirmed();
-
-	void onBtnSave();
-	void onBtnCancel();
-
-	void onSkyPresetListChange();
-	void onRegionSettingsChange();
-	void onRegionInfoUpdate();
-
-	LLLineEditor*	mSkyPresetNameEditor;
-	LLComboBox*		mSkyPresetCombo;
-	LLCheckBoxCtrl*	mMakeDefaultCheckBox;
-	LLButton*		mSaveButton;
-};
-
-#endif // LL_LLFLOATEREDITSKY_H
diff --git a/indra/newview/llfloatereditwater.cpp b/indra/newview/llfloatereditwater.cpp
index 43b44eae3750dcc31e2372adbb6f2dee69b618bd..6e7b777e70a31b4654737290fafb3f88981645e3 100644
--- a/indra/newview/llfloatereditwater.cpp
+++ b/indra/newview/llfloatereditwater.cpp
@@ -28,6 +28,8 @@
 
 #include "llfloatereditwater.h"
 
+#include <boost/make_shared.hpp>
+
 // libs
 #include "llbutton.h"
 #include "llcheckboxctrl.h"
@@ -42,16 +44,22 @@
 #include "llagent.h"
 #include "llregioninfomodel.h"
 #include "llviewerregion.h"
-#include "llwaterparammanager.h"
+
+#include "llenvironment.h"
+#include "llsettingswater.h"
+#include "llenvadapters.h"
+
+#include "v3colorutil.h"
 
 #undef max // Fixes a Windows compiler error
 
-LLFloaterEditWater::LLFloaterEditWater(const LLSD &key)
-:	LLFloater(key)
-,	mWaterPresetNameEditor(NULL)
-,	mWaterPresetCombo(NULL)
-,	mMakeDefaultCheckBox(NULL)
-,	mSaveButton(NULL)
+LLFloaterEditWater::LLFloaterEditWater(const LLSD &key):	
+    LLFloater(key),	
+    mWaterPresetNameEditor(NULL),
+    mWaterPresetCombo(NULL),
+    mMakeDefaultCheckBox(NULL),
+    mSaveButton(NULL),
+    mWaterAdapter()
 {
 }
 
@@ -63,6 +71,10 @@ BOOL LLFloaterEditWater::postBuild()
 	mMakeDefaultCheckBox = getChild<LLCheckBoxCtrl>("make_default_cb");
 	mSaveButton = getChild<LLButton>("save");
 
+    mWaterAdapter = boost::make_shared<LLWatterSettingsAdapter>();
+
+    LLEnvironment::instance().setWaterListChange(boost::bind(&LLFloaterEditWater::onWaterPresetListChange, this));
+
 	initCallbacks();
 	refreshWaterPresetsList();
 	syncControls();
@@ -99,7 +111,8 @@ void LLFloaterEditWater::onClose(bool app_quitting)
 {
 	if (!app_quitting) // there's no point to change environment if we're quitting
 	{
-		LLEnvManagerNew::instance().usePrefs(); // revert changes made to current environment
+        LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
 	}
 }
 
@@ -119,44 +132,38 @@ void LLFloaterEditWater::initCallbacks(void)
 	mSaveButton->setCommitCallback(boost::bind(&LLFloaterEditWater::onBtnSave, this));
 	getChild<LLButton>("cancel")->setCommitCallback(boost::bind(&LLFloaterEditWater::onBtnCancel, this));
 
-	LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLFloaterEditWater::onRegionSettingsChange, this));
-	LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEditWater::onWaterPresetListChange, this));
-
 	// Connect to region info updates.
 	LLRegionInfoModel::instance().setUpdateCallback(boost::bind(&LLFloaterEditWater::onRegionInfoUpdate, this));
 
 	//-------------------------------------------------------------------------
 
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-
-	getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterEditWater::onWaterFogColorMoved, this, _1, &water_mgr.mFogColor));
-	//getChild<LLUICtrl>("WaterGlow")->setCommitCallback(boost::bind(&LLFloaterEditWater::onColorControlAMoved, this, _1, &water_mgr.mFogColor));
+    getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterEditWater::onColorControlMoved, this, _1, &mWaterAdapter->mFogColor));
 
 	// fog density
-	getChild<LLUICtrl>("WaterFogDensity")->setCommitCallback(boost::bind(&LLFloaterEditWater::onExpFloatControlMoved, this, _1, &water_mgr.mFogDensity));
-	getChild<LLUICtrl>("WaterUnderWaterFogMod")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mUnderWaterFogMod));
+    getChild<LLUICtrl>("WaterFogDensity")->setCommitCallback(boost::bind(&LLFloaterEditWater::onExpFloatControlMoved, this, _1, &mWaterAdapter->mFogDensity));
+    getChild<LLUICtrl>("WaterUnderWaterFogMod")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mUnderWaterFogMod));
 
 	// blue density
-	getChild<LLUICtrl>("WaterNormalScaleX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlXMoved, this, _1, &water_mgr.mNormalScale));
-	getChild<LLUICtrl>("WaterNormalScaleY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlYMoved, this, _1, &water_mgr.mNormalScale));
-	getChild<LLUICtrl>("WaterNormalScaleZ")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlZMoved, this, _1, &water_mgr.mNormalScale));
+    getChild<LLUICtrl>("WaterNormalScaleX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlXMoved, this, _1, &mWaterAdapter->mNormalScale));
+    getChild<LLUICtrl>("WaterNormalScaleY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlYMoved, this, _1, &mWaterAdapter->mNormalScale));
+    getChild<LLUICtrl>("WaterNormalScaleZ")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector3ControlZMoved, this, _1, &mWaterAdapter->mNormalScale));
 
 	// fresnel
-	getChild<LLUICtrl>("WaterFresnelScale")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mFresnelScale));
-	getChild<LLUICtrl>("WaterFresnelOffset")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mFresnelOffset));
+    getChild<LLUICtrl>("WaterFresnelScale")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mFresnelScale));
+    getChild<LLUICtrl>("WaterFresnelOffset")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mFresnelOffset));
 
 	// scale above/below
-	getChild<LLUICtrl>("WaterScaleAbove")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mScaleAbove));
-	getChild<LLUICtrl>("WaterScaleBelow")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mScaleBelow));
+    getChild<LLUICtrl>("WaterScaleAbove")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mScaleAbove));
+    getChild<LLUICtrl>("WaterScaleBelow")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mScaleBelow));
 
 	// blur mult
-	getChild<LLUICtrl>("WaterBlurMult")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &water_mgr.mBlurMultiplier));
+    getChild<LLUICtrl>("WaterBlurMult")->setCommitCallback(boost::bind(&LLFloaterEditWater::onFloatControlMoved, this, _1, &mWaterAdapter->mBlurMultiplier));
 
 	// wave direction
-	getChild<LLUICtrl>("WaterWave1DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &water_mgr.mWave1Dir));
-	getChild<LLUICtrl>("WaterWave1DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &water_mgr.mWave1Dir));
-	getChild<LLUICtrl>("WaterWave2DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &water_mgr.mWave2Dir));
-	getChild<LLUICtrl>("WaterWave2DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &water_mgr.mWave2Dir));
+    getChild<LLUICtrl>("WaterWave1DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &mWaterAdapter->mWave1Dir));
+    getChild<LLUICtrl>("WaterWave1DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &mWaterAdapter->mWave1Dir));
+    getChild<LLUICtrl>("WaterWave2DirX")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlXMoved, this, _1, &mWaterAdapter->mWave2Dir));
+    getChild<LLUICtrl>("WaterWave2DirY")->setCommitCallback(boost::bind(&LLFloaterEditWater::onVector2ControlYMoved, this, _1, &mWaterAdapter->mWave2Dir));
 
 	LLTextureCtrl* texture_ctrl = getChild<LLTextureCtrl>("WaterNormalMap");
 	texture_ctrl->setDefaultImageAssetID(DEFAULT_WATER_NORMAL);
@@ -169,304 +176,132 @@ void LLFloaterEditWater::syncControls()
 {
 	// *TODO: Eliminate slow getChild() calls.
 
-	bool err;
-
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-
-	LLWaterParamSet& current_params = water_mgr.mCurParams;
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+    mEditSettings = pwater;
 
-	// blue horizon
-	water_mgr.mFogColor = current_params.getVector4(water_mgr.mFogColor.mName, err);
+    std::string name = pwater->getName();
+    mWaterPresetNameEditor->setText(name);
+    mWaterPresetCombo->setValue(name);
 
-	LLColor4 col = water_mgr.getFogColor();
 	//getChild<LLUICtrl>("WaterGlow")->setValue(col.mV[3]);
-	col.mV[3] = 1.0f;
-	getChild<LLColorSwatchCtrl>("WaterFogColor")->set(col);
+    getChild<LLColorSwatchCtrl>("WaterFogColor")->set(LLColor4(pwater->getWaterFogColor()));
 
 	// fog and wavelets
-	water_mgr.mFogDensity.mExp =
-		log(current_params.getFloat(water_mgr.mFogDensity.mName, err)) /
-		log(water_mgr.mFogDensity.mBase);
-	water_mgr.setDensitySliderValue(water_mgr.mFogDensity.mExp);
-	getChild<LLUICtrl>("WaterFogDensity")->setValue(water_mgr.mFogDensity.mExp);
+    mWaterAdapter->mFogDensity = pwater->getWaterFogDensity();
+    getChild<LLUICtrl>("WaterFogDensity")->setValue(mWaterAdapter->mFogDensity.getExp());
 
-	water_mgr.mUnderWaterFogMod.mX =
-		current_params.getFloat(water_mgr.mUnderWaterFogMod.mName, err);
-	getChild<LLUICtrl>("WaterUnderWaterFogMod")->setValue(water_mgr.mUnderWaterFogMod.mX);
+    mWaterAdapter->mUnderWaterFogMod = pwater->getFogMod();
+	getChild<LLUICtrl>("WaterUnderWaterFogMod")->setValue(static_cast<F32>(mWaterAdapter->mUnderWaterFogMod));
 
-	water_mgr.mNormalScale = current_params.getVector3(water_mgr.mNormalScale.mName, err);
-	getChild<LLUICtrl>("WaterNormalScaleX")->setValue(water_mgr.mNormalScale.mX);
-	getChild<LLUICtrl>("WaterNormalScaleY")->setValue(water_mgr.mNormalScale.mY);
-	getChild<LLUICtrl>("WaterNormalScaleZ")->setValue(water_mgr.mNormalScale.mZ);
+    mWaterAdapter->mNormalScale = pwater->getNormalScale();
+    getChild<LLUICtrl>("WaterNormalScaleX")->setValue(mWaterAdapter->mNormalScale.getX());
+	getChild<LLUICtrl>("WaterNormalScaleY")->setValue(mWaterAdapter->mNormalScale.getY());
+	getChild<LLUICtrl>("WaterNormalScaleZ")->setValue(mWaterAdapter->mNormalScale.getZ());
 
 	// Fresnel
-	water_mgr.mFresnelScale.mX = current_params.getFloat(water_mgr.mFresnelScale.mName, err);
-	getChild<LLUICtrl>("WaterFresnelScale")->setValue(water_mgr.mFresnelScale.mX);
-	water_mgr.mFresnelOffset.mX = current_params.getFloat(water_mgr.mFresnelOffset.mName, err);
-	getChild<LLUICtrl>("WaterFresnelOffset")->setValue(water_mgr.mFresnelOffset.mX);
+    mWaterAdapter->mFresnelScale = pwater->getFresnelScale();
+	getChild<LLUICtrl>("WaterFresnelScale")->setValue(static_cast<F32>(mWaterAdapter->mFresnelScale));
+    mWaterAdapter->mFresnelOffset = pwater->getFresnelOffset();
+    getChild<LLUICtrl>("WaterFresnelOffset")->setValue(static_cast<F32>(mWaterAdapter->mFresnelOffset));
 
 	// Scale Above/Below
-	water_mgr.mScaleAbove.mX = current_params.getFloat(water_mgr.mScaleAbove.mName, err);
-	getChild<LLUICtrl>("WaterScaleAbove")->setValue(water_mgr.mScaleAbove.mX);
-	water_mgr.mScaleBelow.mX = current_params.getFloat(water_mgr.mScaleBelow.mName, err);
-	getChild<LLUICtrl>("WaterScaleBelow")->setValue(water_mgr.mScaleBelow.mX);
+    mWaterAdapter->mScaleAbove = pwater->getScaleAbove();
+    getChild<LLUICtrl>("WaterScaleAbove")->setValue(static_cast<F32>(mWaterAdapter->mScaleAbove));
+    mWaterAdapter->mScaleBelow = pwater->getScaleBelow();
+    getChild<LLUICtrl>("WaterScaleBelow")->setValue(static_cast<F32>(mWaterAdapter->mScaleBelow));
 
 	// blur mult
-	water_mgr.mBlurMultiplier.mX = current_params.getFloat(water_mgr.mBlurMultiplier.mName, err);
-	getChild<LLUICtrl>("WaterBlurMult")->setValue(water_mgr.mBlurMultiplier.mX);
+    mWaterAdapter->mBlurMultiplier = pwater->getBlurMultiplier();
+    getChild<LLUICtrl>("WaterBlurMult")->setValue(static_cast<F32>(mWaterAdapter->mBlurMultiplier));
 
 	// wave directions
-	water_mgr.mWave1Dir = current_params.getVector2(water_mgr.mWave1Dir.mName, err);
-	getChild<LLUICtrl>("WaterWave1DirX")->setValue(water_mgr.mWave1Dir.mX);
-	getChild<LLUICtrl>("WaterWave1DirY")->setValue(water_mgr.mWave1Dir.mY);
+    mWaterAdapter->mWave1Dir = pwater->getWave1Dir();
+	getChild<LLUICtrl>("WaterWave1DirX")->setValue(mWaterAdapter->mWave1Dir.getU());
+	getChild<LLUICtrl>("WaterWave1DirY")->setValue(mWaterAdapter->mWave1Dir.getV());
 
-	water_mgr.mWave2Dir = current_params.getVector2(water_mgr.mWave2Dir.mName, err);
-	getChild<LLUICtrl>("WaterWave2DirX")->setValue(water_mgr.mWave2Dir.mX);
-	getChild<LLUICtrl>("WaterWave2DirY")->setValue(water_mgr.mWave2Dir.mY);
+    mWaterAdapter->mWave2Dir = pwater->getWave2Dir();
+	getChild<LLUICtrl>("WaterWave2DirX")->setValue(mWaterAdapter->mWave2Dir.getU());
+    getChild<LLUICtrl>("WaterWave2DirY")->setValue(mWaterAdapter->mWave2Dir.getV());
 
 	LLTextureCtrl* textCtrl = getChild<LLTextureCtrl>("WaterNormalMap");
-	textCtrl->setImageAssetID(water_mgr.getNormalMapID());
-}
-
-// color control callbacks
-void LLFloaterEditWater::onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
-{
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	color_ctrl->mR = sldr_ctrl->getValueF32();
-
-	// move i if it's the max
-	if (color_ctrl->mR >= color_ctrl->mG
-		&& color_ctrl->mR >= color_ctrl->mB
-		&& color_ctrl->mHasSliderName)
-	{
-		color_ctrl->mI = color_ctrl->mR;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		getChild<LLUICtrl>(name)->setValue(color_ctrl->mR);
-	}
-
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
-}
-
-void LLFloaterEditWater::onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
-{
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	color_ctrl->mG = sldr_ctrl->getValueF32();
-
-	// move i if it's the max
-	if (color_ctrl->mG >= color_ctrl->mR
-		&& color_ctrl->mG >= color_ctrl->mB
-		&& color_ctrl->mHasSliderName)
-	{
-		color_ctrl->mI = color_ctrl->mG;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		getChild<LLUICtrl>(name)->setValue(color_ctrl->mG);
-
-	}
-
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
-}
-
-void LLFloaterEditWater::onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
-{
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	color_ctrl->mB = sldr_ctrl->getValueF32();
-
-	// move i if it's the max
-	if (color_ctrl->mB >= color_ctrl->mR
-		&& color_ctrl->mB >= color_ctrl->mG
-		&& color_ctrl->mHasSliderName)
-	{
-		color_ctrl->mI = color_ctrl->mB;
-		std::string name = color_ctrl->mSliderName;
-		name.append("I");
-
-		getChild<LLUICtrl>(name)->setValue(color_ctrl->mB);
-	}
-
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
-}
-
-void LLFloaterEditWater::onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
-{
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	color_ctrl->mA = sldr_ctrl->getValueF32();
-
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
+	textCtrl->setImageAssetID(pwater->getNormalMapID());
 }
 
 
-void LLFloaterEditWater::onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
-{
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	color_ctrl->mI = sldr_ctrl->getValueF32();
-
-	// only for sliders where we pass a name
-	if (color_ctrl->mHasSliderName)
-	{
-		// set it to the top
-		F32 maxVal = std::max(std::max(color_ctrl->mR, color_ctrl->mG), color_ctrl->mB);
-		F32 iVal;
-
-		iVal = color_ctrl->mI;
-
-		// get the names of the other sliders
-		std::string rName = color_ctrl->mSliderName;
-		rName.append("R");
-		std::string gName = color_ctrl->mSliderName;
-		gName.append("G");
-		std::string bName = color_ctrl->mSliderName;
-		bName.append("B");
-
-		// handle if at 0
-		if (iVal == 0)
-		{
-			color_ctrl->mR = 0;
-			color_ctrl->mG = 0;
-			color_ctrl->mB = 0;
-
-		// if all at the start
-		// set them all to the intensity
-		}
-		else if (maxVal == 0)
-		{
-			color_ctrl->mR = iVal;
-			color_ctrl->mG = iVal;
-			color_ctrl->mB = iVal;
-		}
-		else
-		{
-			// add delta amounts to each
-			F32 delta = (iVal - maxVal) / maxVal;
-			color_ctrl->mR *= (1.0f + delta);
-			color_ctrl->mG *= (1.0f + delta);
-			color_ctrl->mB *= (1.0f + delta);
-		}
-
-		// set the sliders to the new vals
-		getChild<LLUICtrl>(rName)->setValue(color_ctrl->mR);
-		getChild<LLUICtrl>(gName)->setValue(color_ctrl->mG);
-		getChild<LLUICtrl>(bName)->setValue(color_ctrl->mB);
-	}
-
-	// now update the current parameters and send them to shaders
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-	LLWaterParamManager::getInstance()->propagateParameters();
-}
-
 // vector control callbacks
-void LLFloaterEditWater::onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+void LLFloaterEditWater::onVector3ControlXMoved(LLUICtrl* ctrl, WLVect3Control* vector_ctrl)
 {
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	vector_ctrl->mX = sldr_ctrl->getValueF32();
-
-	vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
+	vector_ctrl->setX( sldr_ctrl->getValueF32() );
+	vector_ctrl->update(mEditSettings);
 }
 
 // vector control callbacks
-void LLFloaterEditWater::onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+void LLFloaterEditWater::onVector3ControlYMoved(LLUICtrl* ctrl, WLVect3Control* vector_ctrl)
 {
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	vector_ctrl->mY = sldr_ctrl->getValueF32();
-
-	vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
+    vector_ctrl->setY(sldr_ctrl->getValueF32());
+    vector_ctrl->update(mEditSettings);
 }
 
 // vector control callbacks
-void LLFloaterEditWater::onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl)
+void LLFloaterEditWater::onVector3ControlZMoved(LLUICtrl* ctrl, WLVect3Control* vector_ctrl)
 {
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	vector_ctrl->mZ = sldr_ctrl->getValueF32();
-
-	vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	LLWaterParamManager::getInstance()->propagateParameters();
+    vector_ctrl->setZ(sldr_ctrl->getValueF32());
+    vector_ctrl->update(mEditSettings);
 }
 
 
 // vector control callbacks
-void LLFloaterEditWater::onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl)
+void LLFloaterEditWater::onVector2ControlXMoved(LLUICtrl* ctrl, WLVect2Control* vector_ctrl)
 {
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
-
-	vector_ctrl->mX = sldr_ctrl->getValueF32();
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
+    vector_ctrl->setU(sldr_ctrl->getValueF32());
+    vector_ctrl->update(mEditSettings);
 }
 
 // vector control callbacks
-void LLFloaterEditWater::onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl)
+void LLFloaterEditWater::onVector2ControlYMoved(LLUICtrl* ctrl, WLVect2Control* vector_ctrl)
 {
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	vector_ctrl->mY = sldr_ctrl->getValueF32();
-
-	vector_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-
-	LLWaterParamManager::getInstance()->propagateParameters();
+    vector_ctrl->setV(sldr_ctrl->getValueF32());
+    vector_ctrl->update(mEditSettings);
 }
 
-void LLFloaterEditWater::onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl)
+void LLFloaterEditWater::onFloatControlMoved(LLUICtrl* ctrl, WLFloatControl* floatControl)
 {
-	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
+    LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	floatControl->mX = sldr_ctrl->getValueF32() / floatControl->mMult;
-
-	floatControl->update(LLWaterParamManager::getInstance()->mCurParams);
-	LLWaterParamManager::getInstance()->propagateParameters();
+    floatControl->setValue(sldr_ctrl->getValueF32());
+    floatControl->update(mEditSettings);
 }
 
-void LLFloaterEditWater::onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl)
+void LLFloaterEditWater::onExpFloatControlMoved(LLUICtrl* ctrl, WLXFloatControl* expFloatControl)
 {
 	LLSliderCtrl* sldr_ctrl = static_cast<LLSliderCtrl*>(ctrl);
 
-	F32 val = sldr_ctrl->getValueF32();
-	expFloatControl->mExp = val;
-	LLWaterParamManager::getInstance()->setDensitySliderValue(val);
-
-	expFloatControl->update(LLWaterParamManager::getInstance()->mCurParams);
-	LLWaterParamManager::getInstance()->propagateParameters();
+    expFloatControl->setExp(sldr_ctrl->getValueF32());
+    expFloatControl->update(mEditSettings);
 }
 
-void LLFloaterEditWater::onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl)
+void LLFloaterEditWater::onColorControlMoved(LLUICtrl* ctrl, WLColorControl* color_ctrl)
 {
 	LLColorSwatchCtrl* swatch = static_cast<LLColorSwatchCtrl*>(ctrl);
-	*color_ctrl = swatch->get();
-
-	color_ctrl->update(LLWaterParamManager::getInstance()->mCurParams);
-	LLWaterParamManager::getInstance()->propagateParameters();
+	color_ctrl->setColor4( swatch->get() );
+	color_ctrl->update(mEditSettings);
 }
 
 void LLFloaterEditWater::onNormalMapPicked(LLUICtrl* ctrl)
 {
 	LLTextureCtrl* textCtrl = static_cast<LLTextureCtrl*>(ctrl);
 	LLUUID textID = textCtrl->getImageAssetID();
-	LLWaterParamManager::getInstance()->setNormalMapID(textID);
+    mEditSettings->setNormalMapID(textID);
 }
 
 //=============================================================================
@@ -496,38 +331,12 @@ void LLFloaterEditWater::refreshWaterPresetsList()
 {
 	mWaterPresetCombo->removeall();
 
-#if 0 // *TODO: enable when we have a clear workflow to edit existing region environment
-	// If the region already has water params, add them to the list.
-	const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings();
-	if (region_settings.getWaterParams().size() != 0)
-	{
-		const std::string& region_name = gAgent.getRegion()->getName();
-		mWaterPresetCombo->add(region_name, LLSD().with(0, region_name).with(1, LLEnvKey::SCOPE_REGION));
-		mWaterPresetCombo->addSeparator();
-	}
-#endif
-
-	std::list<std::string> user_presets, system_presets;
-	LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
+    LLEnvironment::list_name_id_t list = LLEnvironment::instance().getWaterList();
 
-	// Add local user presets first.
-	for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		const std::string& name = *it;
-		mWaterPresetCombo->add(name, LLSD().with(0, name).with(1, LLEnvKey::SCOPE_LOCAL)); // [<name>, <scope>]
-	}
-
-	if (user_presets.size() > 0)
-	{
-		mWaterPresetCombo->addSeparator();
-	}
-
-	// Add local system presets.
-	for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
-	{
-		const std::string& name = *it;
-		mWaterPresetCombo->add(name, LLSD().with(0, name).with(1, LLEnvKey::SCOPE_LOCAL)); // [<name>, <scope>]
-	}
+    for (LLEnvironment::list_name_id_t::iterator it = list.begin(); it != list.end(); ++it)
+    {
+        mWaterPresetCombo->add((*it).first, LLSDArray((*it).first)((*it).second));
+    }
 
 	mWaterPresetCombo->setLabel(getString("combo_label"));
 }
@@ -544,6 +353,7 @@ void LLFloaterEditWater::enableEditing(bool enable)
 
 void LLFloaterEditWater::saveRegionWater()
 {
+#if 0
 	llassert(getCurrentScope() == LLEnvKey::SCOPE_REGION); // make sure we're editing region water
 
 	LL_DEBUGS("Windlight") << "Saving region water preset" << LL_ENDL;
@@ -552,8 +362,10 @@ void LLFloaterEditWater::saveRegionWater()
 
 	// *TODO: save to cached region settings.
 	LL_WARNS("Windlight") << "Saving region water is not fully implemented yet" << LL_ENDL;
+#endif
 }
 
+#if 0
 std::string LLFloaterEditWater::getCurrentPresetName() const
 {
 	std::string name;
@@ -561,7 +373,9 @@ std::string LLFloaterEditWater::getCurrentPresetName() const
 	getSelectedPreset(name, scope);
 	return name;
 }
+#endif
 
+#if 0
 LLEnvKey::EScope LLFloaterEditWater::getCurrentScope() const
 {
 	std::string name;
@@ -569,71 +383,62 @@ LLEnvKey::EScope LLFloaterEditWater::getCurrentScope() const
 	getSelectedPreset(name, scope);
 	return scope;
 }
+#endif
 
-void LLFloaterEditWater::getSelectedPreset(std::string& name, LLEnvKey::EScope& scope) const
+std::string LLFloaterEditWater::getSelectedPresetName() const
 {
+    std::string name;
 	if (mWaterPresetNameEditor->getVisible())
 	{
 		name = mWaterPresetNameEditor->getText();
-		scope = LLEnvKey::SCOPE_LOCAL;
 	}
 	else
 	{
 		LLSD combo_val = mWaterPresetCombo->getValue();
-
-		if (!combo_val.isArray()) // manually typed text
-		{
-			name = combo_val.asString();
-			scope = LLEnvKey::SCOPE_LOCAL;
-		}
-		else
-		{
-			name = combo_val[0].asString();
-			scope = (LLEnvKey::EScope) combo_val[1].asInteger();
-		}
+		name = combo_val[0].asString();
 	}
+
+    return name;
 }
 
 void LLFloaterEditWater::onWaterPresetNameEdited()
 {
+    std::string name = mWaterPresetNameEditor->getText();
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+
+    pwater->setName(name);
+#if 0
 	// Disable saving a water preset having empty name.
 	mSaveButton->setEnabled(!getCurrentPresetName().empty());
+#endif
 }
 
 void LLFloaterEditWater::onWaterPresetSelected()
 {
-	LLWaterParamSet water_params;
 	std::string name;
-	LLEnvKey::EScope scope;
 
-	getSelectedPreset(name, scope);
+	name = getSelectedPresetName();
 
-	// Display selected preset.
-	if (scope == LLEnvKey::SCOPE_REGION)
-	{
-		water_params.setAll(LLEnvManagerNew::instance().getRegionSettings().getWaterParams());
-	}
-	else // local preset selected
-	{
-		if (!LLWaterParamManager::instance().getParamSet(name, water_params))
-		{
-			// Manually entered string?
-			LL_WARNS("Windlight") << "No water preset named " << name << LL_ENDL;
-			return;
-		}
-	}
+    LLSettingsWater::ptr_t pwater = LLEnvironment::instance().findWaterByName(name);
 
-	LLEnvManagerNew::instance().useWaterParams(water_params.getAll());
+    if (!pwater)
+    {
+        LL_WARNS("WATEREDIT") << "Could not find water preset" << LL_ENDL;
+        enableEditing(false);
+        return;
+    }
 
-	bool can_edit = (scope == LLEnvKey::SCOPE_LOCAL || LLEnvManagerNew::canEditRegionSettings());
-	enableEditing(can_edit);
+    pwater = pwater->buildClone();
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, pwater);
+    mEditSettings = pwater;
 
-	mMakeDefaultCheckBox->setEnabled(scope == LLEnvKey::SCOPE_LOCAL);
+    syncControls();
+    enableEditing(true);
 }
 
 bool LLFloaterEditWater::onSaveAnswer(const LLSD& notification, const LLSD& response)
 {
-	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+  	S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
 
 	// If they choose save, do it.  Otherwise, don't do anything
 	if (option == 0)
@@ -641,32 +446,23 @@ bool LLFloaterEditWater::onSaveAnswer(const LLSD& notification, const LLSD& resp
 		onSaveConfirmed();
 	}
 
-	return false;
+    return false;
 }
 
 void LLFloaterEditWater::onSaveConfirmed()
 {
 	// Save currently displayed water params to the selected preset.
-	std::string name = getCurrentPresetName();
+    std::string name = mEditSettings->getName();
 
 	LL_DEBUGS("Windlight") << "Saving sky preset " << name << LL_ENDL;
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-	if (water_mgr.hasParamSet(name))
-	{
-		water_mgr.setParamSet(name, water_mgr.mCurParams);
-	}
-	else
-	{
-		water_mgr.addParamSet(name, water_mgr.mCurParams);
-	}
 
-	water_mgr.savePreset(name);
+    LLEnvironment::instance().addWater(mEditSettings);
 
 	// Change preference if requested.
 	if (mMakeDefaultCheckBox->getEnabled() && mMakeDefaultCheckBox->getValue())
 	{
 		LL_DEBUGS("Windlight") << name << " is now the new preferred water preset" << LL_ENDL;
-		LLEnvManagerNew::instance().setUseWaterPreset(name);
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, mEditSettings);
 	}
 
 	closeFloater();
@@ -674,42 +470,10 @@ void LLFloaterEditWater::onSaveConfirmed()
 
 void LLFloaterEditWater::onBtnSave()
 {
-	LLEnvKey::EScope scope;
-	std::string name;
-	getSelectedPreset(name, scope);
-
-	if (scope == LLEnvKey::SCOPE_REGION)
-	{
-		saveRegionWater();
-		closeFloater();
-		return;
-	}
-
-	if (name.empty())
-	{
-		// *TODO: show an alert
-		LL_WARNS() << "Empty water preset name" << LL_ENDL;
-		return;
-	}
-
-	// Don't allow overwriting system presets.
-	LLWaterParamManager& water_mgr = LLWaterParamManager::instance();
-	if (water_mgr.isSystemPreset(name))
-	{
-		LLNotificationsUtil::add("WLNoEditDefault");
-		return;
-	}
+    LLEnvironment::instance().addWater(mEditSettings);
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, mEditSettings);
 
-	// Save, ask for confirmation for overwriting an existing preset.
-	if (water_mgr.hasParamSet(name))
-	{
-		LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), boost::bind(&LLFloaterEditWater::onSaveAnswer, this, _1, _2));
-	}
-	else
-	{
-		// new preset, hence no confirmation needed
-		onSaveConfirmed();
-	}
+    closeFloater();
 }
 
 void LLFloaterEditWater::onBtnCancel()
@@ -719,25 +483,12 @@ void LLFloaterEditWater::onBtnCancel()
 
 void LLFloaterEditWater::onWaterPresetListChange()
 {
-	std::string name;
-	LLEnvKey::EScope scope;
-	getSelectedPreset(name, scope); // preset being edited
-
-	if (scope == LLEnvKey::SCOPE_LOCAL && !LLWaterParamManager::instance().hasParamSet(name))
-	{
-		// Preset we've been editing doesn't exist anymore. Close the floater.
-		closeFloater(false);
-	}
-	else
-	{
-		// A new preset has been added.
-		// Refresh the presets list, though it may not make sense as the floater is about to be closed.
-		refreshWaterPresetsList();
-	}
+    refreshWaterPresetsList();
 }
 
 void LLFloaterEditWater::onRegionSettingsChange()
 {
+#if 0
 	// If creating a new preset, don't bother.
 	if (isNewPreset())
 	{
@@ -755,10 +506,12 @@ void LLFloaterEditWater::onRegionSettingsChange()
 	{
 		refreshWaterPresetsList();
 	}
+#endif
 }
 
 void LLFloaterEditWater::onRegionInfoUpdate()
 {
+#if 0
 	bool can_edit = true;
 
 	// If we've selected the region water for editing.
@@ -769,4 +522,5 @@ void LLFloaterEditWater::onRegionInfoUpdate()
 	}
 
 	enableEditing(can_edit);
+#endif
 }
diff --git a/indra/newview/llfloatereditwater.h b/indra/newview/llfloatereditwater.h
deleted file mode 100644
index 2211bca59f182dba1343b991ef00a83f303ade21..0000000000000000000000000000000000000000
--- a/indra/newview/llfloatereditwater.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/** 
- * @file llfloatereditwater.h
- * @brief Floater to create or edit a water preset
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLFLOATEREDITWATER_H
-#define LL_LLFLOATEREDITWATER_H
-
-#include "llfloater.h"
-#include "llenvmanager.h" // for LLEnvKey
-
-class LLButton;
-class LLCheckBoxCtrl;
-class LLComboBox;
-class LLLineEditor;
-
-struct WaterVector2Control;
-struct WaterVector3Control;
-struct WaterColorControl;
-struct WaterFloatControl;
-struct WaterExpFloatControl;
-
-class LLFloaterEditWater : public LLFloater
-{
-	LOG_CLASS(LLFloaterEditWater);
-
-public:
-	LLFloaterEditWater(const LLSD &key);
-
-	/*virtual*/	BOOL	postBuild();
-	/*virtual*/ void	onOpen(const LLSD& key);
-	/*virtual*/ void	onClose(bool app_quitting);
-	/*virtual*/ void	draw();
-
-private:
-	void initCallbacks(void);
-
-	//-- WL stuff begins ------------------------------------------------------
-
-	void syncControls(); /// sync up sliders with parameters
-
-	// general purpose callbacks for dealing with color controllers
-	void onColorControlRMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-	void onColorControlGMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-	void onColorControlBMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-	void onColorControlAMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-	void onColorControlIMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-
-	void onVector3ControlXMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
-	void onVector3ControlYMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
-	void onVector3ControlZMoved(LLUICtrl* ctrl, WaterVector3Control* vector_ctrl);
-
-	void onVector2ControlXMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl);
-	void onVector2ControlYMoved(LLUICtrl* ctrl, WaterVector2Control* vector_ctrl);
-
-	void onFloatControlMoved(LLUICtrl* ctrl, WaterFloatControl* floatControl);
-
-	void onExpFloatControlMoved(LLUICtrl* ctrl, WaterExpFloatControl* expFloatControl);
-
-	void onWaterFogColorMoved(LLUICtrl* ctrl, WaterColorControl* color_ctrl);
-
-	void onNormalMapPicked(LLUICtrl* ctrl); /// handle if they choose a new normal map
-
-	//-- WL stuff ends --------------------------------------------------------
-
-	void reset();
-	bool isNewPreset() const;
-	void refreshWaterPresetsList();
-	void enableEditing(bool enable);
-	void saveRegionWater();
-
-	std::string			getCurrentPresetName() const;
-	LLEnvKey::EScope	getCurrentScope() const;
-	void				getSelectedPreset(std::string& name, LLEnvKey::EScope& scope) const;
-
-	void onWaterPresetNameEdited();
-	void onWaterPresetSelected();
-	bool onSaveAnswer(const LLSD& notification, const LLSD& response);
-	void onSaveConfirmed();
-
-	void onBtnSave();
-	void onBtnCancel();
-
-	void onWaterPresetListChange();
-	void onRegionSettingsChange();
-	void onRegionInfoUpdate();
-
-	LLLineEditor*	mWaterPresetNameEditor;
-	LLComboBox*		mWaterPresetCombo;
-	LLCheckBoxCtrl*	mMakeDefaultCheckBox;
-	LLButton*		mSaveButton;
-};
-
-#endif // LL_LLFLOATEREDITWATER_H
diff --git a/indra/newview/llfloaterenvironmentadjust.cpp b/indra/newview/llfloaterenvironmentadjust.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4eb5e03603513202e1005a318ee29188329c66eb
--- /dev/null
+++ b/indra/newview/llfloaterenvironmentadjust.cpp
@@ -0,0 +1,389 @@
+/** 
+ * @file llfloaterfixedenvironment.cpp
+ * @brief Floaters to create and edit fixed settings for sky and water.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterenvironmentadjust.h"
+
+#include "llnotificationsutil.h"
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "llcolorswatch.h"
+#include "lltexturectrl.h"
+#include "llvirtualtrackball.h"
+#include "llenvironment.h"
+#include "llviewercontrol.h"
+
+//=========================================================================
+namespace
+{
+    const std::string FIELD_SKY_AMBIENT_LIGHT("ambient_light");
+    const std::string FIELD_SKY_BLUE_HORIZON("blue_horizon");
+    const std::string FIELD_SKY_BLUE_DENSITY("blue_density");
+    const std::string FIELD_SKY_SUN_COLOR("sun_color");
+    const std::string FIELD_SKY_CLOUD_COLOR("cloud_color");
+    const std::string FIELD_SKY_HAZE_HORIZON("haze_horizon");
+    const std::string FIELD_SKY_HAZE_DENSITY("haze_density");
+    const std::string FIELD_SKY_CLOUD_COVERAGE("cloud_coverage");
+    const std::string FIELD_SKY_CLOUD_MAP("cloud_map");
+    const std::string FIELD_WATER_NORMAL_MAP("water_normal_map");
+    const std::string FIELD_SKY_CLOUD_SCALE("cloud_scale");
+    const std::string FIELD_SKY_SCENE_GAMMA("scene_gamma");
+    const std::string FIELD_SKY_SUN_ROTATION("sun_rotation");
+    const std::string FIELD_SKY_SUN_SCALE("sun_scale");
+    const std::string FIELD_SKY_GLOW_FOCUS("glow_focus");
+    const std::string FIELD_SKY_GLOW_SIZE("glow_size");
+    const std::string FIELD_SKY_STAR_BRIGHTNESS("star_brightness");
+    const std::string FIELD_SKY_MOON_ROTATION("moon_rotation");
+    const std::string BTN_RESET("btn_reset");
+
+    const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
+    const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f);
+    const F32 SLIDER_SCALE_GLOW_R(20.0f);
+    const F32 SLIDER_SCALE_GLOW_B(-5.0f);
+    //const F32 SLIDER_SCALE_DENSITY_MULTIPLIER(0.001f);
+
+    const S32 FLOATER_ENVIRONMENT_UPDATE(-2);
+}
+
+//=========================================================================
+LLFloaterEnvironmentAdjust::LLFloaterEnvironmentAdjust(const LLSD &key):
+    LLFloater(key)
+{}
+
+LLFloaterEnvironmentAdjust::~LLFloaterEnvironmentAdjust()
+{}
+
+//-------------------------------------------------------------------------
+BOOL LLFloaterEnvironmentAdjust::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_AMBIENT_LIGHT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAmbientLightChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_BLUE_HORIZON)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onBlueHorizonChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_BLUE_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onBlueDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onHazeHorizonChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onHazeDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSceneGammaChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COLOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudColorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudCoverageChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_COLOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunColorChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); });
+    getChild<LLUICtrl>(BTN_RESET)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onButtonReset(); });
+
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudMapChanged(); });
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setDefaultImageAssetID(LLSettingsSky::GetDefaultCloudNoiseTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setAllowNoTexture(TRUE);
+
+    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setDefaultImageAssetID(LLSettingsWater::GetDefaultWaterNormalAssetId());
+    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setBlankImageAssetID(LLUUID(gSavedSettings.getString("DefaultBlankNormalTexture")));
+    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onWaterMapChanged(); });
+
+    refresh();
+    return TRUE;
+}
+
+void LLFloaterEnvironmentAdjust::onOpen(const LLSD& key)
+{
+    if (!mLiveSky)
+    {
+        LLEnvironment::instance().saveBeaconsState();
+    }
+    captureCurrentEnvironment();
+
+    mEventConnection = LLEnvironment::instance().setEnvironmentChanged([this](LLEnvironment::EnvSelection_t env, S32 version){ onEnvironmentUpdated(env, version); });
+
+    LLFloater::onOpen(key);
+    refresh();
+}
+
+void LLFloaterEnvironmentAdjust::onClose(bool app_quitting)
+{
+    LLEnvironment::instance().revertBeaconsState();
+    mEventConnection.disconnect();
+    mLiveSky.reset();
+    mLiveWater.reset();
+    LLFloater::onClose(app_quitting);
+}
+
+
+//-------------------------------------------------------------------------
+void LLFloaterEnvironmentAdjust::refresh()
+{
+    if (!mLiveSky || !mLiveWater)
+    {
+        setAllChildrenEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(TRUE);
+    setAllChildrenEnabled(TRUE);
+
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_AMBIENT_LIGHT)->set(mLiveSky->getAmbientColor() / SLIDER_SCALE_SUN_AMBIENT);
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_HORIZON)->set(mLiveSky->getBlueHorizon() / SLIDER_SCALE_BLUE_HORIZON_DENSITY);
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_DENSITY)->set(mLiveSky->getBlueDensity() / SLIDER_SCALE_BLUE_HORIZON_DENSITY);
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->setValue(mLiveSky->getHazeHorizon());
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->setValue(mLiveSky->getHazeDensity());
+    getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setValue(mLiveSky->getGamma());
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_CLOUD_COLOR)->set(mLiveSky->getCloudColor());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->setValue(mLiveSky->getCloudShadow());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->setValue(mLiveSky->getCloudScale());
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_SUN_COLOR)->set(mLiveSky->getSunlightColor() / SLIDER_SCALE_SUN_AMBIENT);
+
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setValue(mLiveSky->getCloudNoiseTextureId());
+    getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->setValue(mLiveWater->getNormalMapID());
+
+    LLColor3 glow(mLiveSky->getGlow());
+
+    // takes 40 - 0.2 range -> 0 - 1.99 UI range
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setValue(2.0 - (glow.mV[0] / SLIDER_SCALE_GLOW_R));
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B);
+    getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mLiveSky->getStarBrightness());
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(mLiveSky->getSunRotation());
+    getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setValue(mLiveSky->getSunScale());
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(mLiveSky->getMoonRotation());
+
+}
+
+
+void LLFloaterEnvironmentAdjust::captureCurrentEnvironment()
+{
+    LLEnvironment &environment(LLEnvironment::instance());
+    bool updatelocal(false);
+
+    if (environment.hasEnvironment(LLEnvironment::ENV_LOCAL))
+    {
+        if (environment.getEnvironmentDay(LLEnvironment::ENV_LOCAL))
+        {   // We have a full day cycle in the local environment.  Freeze the sky
+            mLiveSky = environment.getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL)->buildClone();
+            mLiveWater = environment.getEnvironmentFixedWater(LLEnvironment::ENV_LOCAL)->buildClone();
+            updatelocal = true;
+        }
+        else
+        {   // otherwise we can just use the sky.
+            mLiveSky = environment.getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL);
+            mLiveWater = environment.getEnvironmentFixedWater(LLEnvironment::ENV_LOCAL);
+        }
+    }
+    else
+    {
+        mLiveSky = environment.getEnvironmentFixedSky(LLEnvironment::ENV_PARCEL, true)->buildClone();
+        mLiveWater = environment.getEnvironmentFixedWater(LLEnvironment::ENV_PARCEL, true)->buildClone();
+        updatelocal = true;
+    }
+
+    if (updatelocal)
+    {
+        environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveSky, FLOATER_ENVIRONMENT_UPDATE);
+        environment.setEnvironment(LLEnvironment::ENV_LOCAL, mLiveWater, FLOATER_ENVIRONMENT_UPDATE);
+    }
+    environment.setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+    environment.updateEnvironment(LLEnvironment::TRANSITION_INSTANT);
+
+}
+
+void LLFloaterEnvironmentAdjust::onButtonReset()
+{
+    LLNotificationsUtil::add("PersonalSettingsConfirmReset", LLSD(), LLSD(),
+        [this](const LLSD&notif, const LLSD&resp)
+    {
+        S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+        if (opt == 0)
+        {
+            this->closeFloater();
+            LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+        }
+    }); 
+
+}
+//-------------------------------------------------------------------------
+void LLFloaterEnvironmentAdjust::onAmbientLightChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setAmbientColor(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_AMBIENT_LIGHT)->get() * SLIDER_SCALE_SUN_AMBIENT));
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onBlueHorizonChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setBlueHorizon(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_HORIZON)->get() * SLIDER_SCALE_BLUE_HORIZON_DENSITY));
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onBlueDensityChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setBlueDensity(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_DENSITY)->get() * SLIDER_SCALE_BLUE_HORIZON_DENSITY));
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onHazeHorizonChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setHazeHorizon(getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onHazeDensityChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setHazeDensity(getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onSceneGammaChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setGamma(getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onCloudColorChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setCloudColor(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_CLOUD_COLOR)->get()));
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onCloudCoverageChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setCloudShadow(getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onCloudScaleChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setCloudScale(getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onGlowChanged()
+{
+    if (!mLiveSky)
+        return;
+    LLColor3 glow(getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->getValue().asReal(), 0.0f, getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->getValue().asReal());
+
+    // takes 0 - 1.99 UI range -> 40 -> 0.2 range
+    glow.mV[0] = (2.0f - glow.mV[0]) * SLIDER_SCALE_GLOW_R;
+    glow.mV[2] *= SLIDER_SCALE_GLOW_B;
+
+    mLiveSky->setGlow(glow);
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onStarBrightnessChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setStarBrightness(getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->getValue().asReal());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onSunRotationChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setSunRotation(getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onSunScaleChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setSunScale((getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->getValue().asReal()));
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onMoonRotationChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setMoonRotation(getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onCloudMapChanged()
+{
+    if (!mLiveSky)
+        return;
+    mLiveSky->setCloudNoiseTextureId(getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->getValue().asUUID());
+    mLiveSky->update();
+}
+
+void LLFloaterEnvironmentAdjust::onWaterMapChanged()
+{
+    if (!mLiveWater)
+        return;
+    mLiveWater->setNormalMapID(getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP)->getValue().asUUID());
+    mLiveWater->update();
+}
+
+void LLFloaterEnvironmentAdjust::onSunColorChanged()
+{
+    if (!mLiveSky)
+        return;
+    LLColor3 color(getChild<LLColorSwatchCtrl>(FIELD_SKY_SUN_COLOR)->get());
+
+    color *= SLIDER_SCALE_SUN_AMBIENT;
+
+    mLiveSky->setSunlightColor(color);
+    mLiveSky->update();
+}
+
+
+void LLFloaterEnvironmentAdjust::onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version)
+{
+    if (env == LLEnvironment::ENV_LOCAL)
+    {   // a new local environment has been applied
+        if (version != FLOATER_ENVIRONMENT_UPDATE)
+        {   // not by this floater
+            captureCurrentEnvironment();
+            refresh();
+        }
+    }
+}
diff --git a/indra/newview/llfloaterenvironmentadjust.h b/indra/newview/llfloaterenvironmentadjust.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb38dbcfa80e3362e4b754b38669be734d0e6696
--- /dev/null
+++ b/indra/newview/llfloaterenvironmentadjust.h
@@ -0,0 +1,92 @@
+/** 
+ * @file llfloaterenvironmentadjust.h
+ * @brief Floaters to create and edit fixed settings for sky and water.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifndef LL_FLOATERENVIRONMENTADJUST_H
+#define LL_FLOATERENVIRONMENTADJUST_H
+
+#include "llfloater.h"
+#include "llsettingsbase.h"
+#include "llsettingssky.h"
+#include "llenvironment.h"
+
+#include "boost/signals2.hpp"
+
+class LLButton;
+class LLLineEditor;
+
+/**
+ * Floater container for taking a snapshot of the current environment and making minor adjustments.
+ */
+class LLFloaterEnvironmentAdjust : public LLFloater
+{
+    LOG_CLASS(LLFloaterEnvironmentAdjust);
+
+public:
+                                LLFloaterEnvironmentAdjust(const LLSD &key);
+    virtual                     ~LLFloaterEnvironmentAdjust();
+
+
+    virtual BOOL                postBuild() override;
+    virtual void                onOpen(const LLSD& key) override;
+    virtual void                onClose(bool app_quitting) override;
+
+    virtual void                refresh() override;
+
+private:
+    void                        captureCurrentEnvironment();
+
+    void                        onAmbientLightChanged();
+    void                        onBlueHorizonChanged();
+    void                        onBlueDensityChanged();
+    void                        onHazeHorizonChanged();
+    void                        onHazeDensityChanged();
+    void                        onSceneGammaChanged();
+
+    void                        onCloudColorChanged();
+    void                        onCloudCoverageChanged();
+    void                        onCloudScaleChanged();
+    void                        onSunColorChanged();
+
+    void                        onGlowChanged();
+    void                        onStarBrightnessChanged();
+    void                        onSunRotationChanged();
+    void                        onSunScaleChanged();
+
+    void                        onMoonRotationChanged();
+
+    void                        onCloudMapChanged();
+    void                        onWaterMapChanged();
+
+    void                        onButtonReset();
+
+    void                        onEnvironmentUpdated(LLEnvironment::EnvSelection_t env, S32 version);
+
+    LLSettingsSky::ptr_t        mLiveSky;
+    LLSettingsWater::ptr_t      mLiveWater;
+    LLEnvironment::connection_t mEventConnection;
+};
+
+#endif // LL_FLOATERFIXEDENVIRONMENT_H
diff --git a/indra/newview/llfloaterenvironmentsettings.cpp b/indra/newview/llfloaterenvironmentsettings.cpp
deleted file mode 100644
index 4dbc8cdee0070109dbbd8e65b55cd05cf051a9d1..0000000000000000000000000000000000000000
--- a/indra/newview/llfloaterenvironmentsettings.cpp
+++ /dev/null
@@ -1,282 +0,0 @@
-/** 
- * @file llfloaterenvironmentsettings.cpp
- * @brief LLFloaterEnvironmentSettings class definition
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llfloaterenvironmentsettings.h"
-
-#include "llcombobox.h"
-#include "llradiogroup.h"
-
-#include "lldaycyclemanager.h"
-#include "llenvmanager.h"
-#include "llwaterparammanager.h"
-#include "llwlparamset.h"
-#include "llwlparammanager.h"
-
-LLFloaterEnvironmentSettings::LLFloaterEnvironmentSettings(const LLSD &key)
-: 	 LLFloater(key)
-	,mRegionSettingsRadioGroup(NULL)
-	,mDayCycleSettingsRadioGroup(NULL)
-	,mWaterPresetCombo(NULL)
-	,mSkyPresetCombo(NULL)
-	,mDayCyclePresetCombo(NULL)
-{	
-}
-
-// virtual
-BOOL LLFloaterEnvironmentSettings::postBuild()
-{	
-	mRegionSettingsRadioGroup = getChild<LLRadioGroup>("region_settings_radio_group");
-	mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSwitchRegionSettings, this));
-
-	mDayCycleSettingsRadioGroup = getChild<LLRadioGroup>("sky_dayc_settings_radio_group");
-	mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSwitchDayCycle, this));
-
-	mWaterPresetCombo = getChild<LLComboBox>("water_settings_preset_combo");
-	mWaterPresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectWaterPreset, this));
-
-	mSkyPresetCombo = getChild<LLComboBox>("sky_settings_preset_combo");
-	mSkyPresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectSkyPreset, this));
-
-	mDayCyclePresetCombo = getChild<LLComboBox>("dayc_settings_preset_combo");
-	mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLFloaterEnvironmentSettings::onSelectDayCyclePreset, this));
-
-	childSetCommitCallback("ok_btn", boost::bind(&LLFloaterEnvironmentSettings::onBtnOK, this), NULL);
-	getChild<LLUICtrl>("ok_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance()));
-	childSetCommitCallback("cancel_btn", boost::bind(&LLFloaterEnvironmentSettings::onBtnCancel, this), NULL);
-	getChild<LLUICtrl>("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance()));
-
-	setCloseCallback(boost::bind(&LLFloaterEnvironmentSettings::cancel, this));
-
-	LLEnvManagerNew::instance().setPreferencesChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::refresh, this));
-	LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLFloaterEnvironmentSettings::populateDayCyclePresetsList, this));
-	LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::populateSkyPresetsList, this));
-	LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLFloaterEnvironmentSettings::populateWaterPresetsList, this));
-
-	return TRUE;
-}
-
-// virtual
-void LLFloaterEnvironmentSettings::onOpen(const LLSD& key)
-{
-	refresh();
-}
-
-void LLFloaterEnvironmentSettings::onSwitchRegionSettings()
-{
-	getChild<LLView>("user_environment_settings")->setEnabled(mRegionSettingsRadioGroup->getSelectedIndex() != 0);
-
-	apply();
-}
-
-void LLFloaterEnvironmentSettings::onSwitchDayCycle()
-{
-	bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-
-	mSkyPresetCombo->setEnabled(is_fixed_sky);
-	mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
-
-	apply();
-}
-
-void LLFloaterEnvironmentSettings::onSelectWaterPreset()
-{
-	apply();
-}
-
-void LLFloaterEnvironmentSettings::onSelectSkyPreset()
-{
-	apply();
-}
-
-void LLFloaterEnvironmentSettings::onSelectDayCyclePreset()
-{
-	apply();
-}
-
-void LLFloaterEnvironmentSettings::onBtnOK()
-{
-	// Save and apply new user preferences.
-	bool use_region_settings	= mRegionSettingsRadioGroup->getSelectedIndex() == 0;
-	bool use_fixed_sky			= mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-	std::string water_preset	= mWaterPresetCombo->getValue().asString();
-	std::string sky_preset		= mSkyPresetCombo->getValue().asString();
-	std::string day_cycle		= mDayCyclePresetCombo->getValue().asString();
-
-	LLEnvManagerNew::instance().setUserPrefs(
-		water_preset,
-		sky_preset,
-		day_cycle,
-		use_fixed_sky,
-		use_region_settings);
-
-	// *TODO: This triggers applying user preferences again, which is suboptimal.
-	closeFloater();
-}
-
-void LLFloaterEnvironmentSettings::onBtnCancel()
-{
-	closeFloater();
-}
-
-void LLFloaterEnvironmentSettings::refresh()
-{
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-
-	bool use_region_settings	= env_mgr.getUseRegionSettings();
-	bool use_fixed_sky			= env_mgr.getUseFixedSky();
-
-	// Set up radio buttons according to user preferences.
-	mRegionSettingsRadioGroup->setSelectedIndex(use_region_settings ? 0 : 1);
-	mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1);
-
-	// Populate the combo boxes with appropriate lists of available presets.
-	populateWaterPresetsList();
-	populateSkyPresetsList();
-	populateDayCyclePresetsList();
-
-	// Enable/disable other controls based on user preferences.
-	getChild<LLView>("user_environment_settings")->setEnabled(!use_region_settings);
-	mSkyPresetCombo->setEnabled(use_fixed_sky);
-	mDayCyclePresetCombo->setEnabled(!use_fixed_sky);
-
-	// Select the current presets in combo boxes.
-	mWaterPresetCombo->selectByValue(env_mgr.getWaterPresetName());
-	mSkyPresetCombo->selectByValue(env_mgr.getSkyPresetName());
-	mDayCyclePresetCombo->selectByValue(env_mgr.getDayCycleName());
-}
-
-void LLFloaterEnvironmentSettings::apply()
-{
-	// Update environment with the user choice.
-	bool use_region_settings	= mRegionSettingsRadioGroup->getSelectedIndex() == 0;
-	bool use_fixed_sky			= mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-	std::string water_preset	= mWaterPresetCombo->getValue().asString();
-	std::string sky_preset		= mSkyPresetCombo->getValue().asString();
-	std::string day_cycle		= mDayCyclePresetCombo->getValue().asString();
-
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	if (use_region_settings)
-	{
-		env_mgr.useRegionSettings();
-	}
-	else
-	{
-		if (use_fixed_sky)
-		{
-			env_mgr.useSkyPreset(sky_preset);
-		}
-		else
-		{
-			env_mgr.useDayCycle(day_cycle, LLEnvKey::SCOPE_LOCAL);
-		}
-
-		env_mgr.useWaterPreset(water_preset);
-	}
-}
-
-void LLFloaterEnvironmentSettings::cancel()
-{
-	// Revert environment to user preferences.
-	LLEnvManagerNew::instance().usePrefs();
-}
-
-void LLFloaterEnvironmentSettings::populateWaterPresetsList()
-{
-	mWaterPresetCombo->removeall();
-
-	std::list<std::string> user_presets, system_presets;
-	LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
-
-	// Add user presets first.
-	for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mWaterPresetCombo->add(*it);
-	}
-
-	if (user_presets.size() > 0)
-	{
-		mWaterPresetCombo->addSeparator();
-	}
-
-	// Add system presets.
-	for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
-	{
-		mWaterPresetCombo->add(*it);
-	}
-}
-
-void LLFloaterEnvironmentSettings::populateSkyPresetsList()
-{
-	mSkyPresetCombo->removeall();
-
-	LLWLParamManager::preset_name_list_t region_presets; // unused as we don't list region presets here
-	LLWLParamManager::preset_name_list_t user_presets, sys_presets;
-	LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
-
-	// Add user presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it);
-	}
-
-	if (!user_presets.empty())
-	{
-		mSkyPresetCombo->addSeparator();
-	}
-
-	// Add system presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it);
-	}
-}
-
-void LLFloaterEnvironmentSettings::populateDayCyclePresetsList()
-{
-	mDayCyclePresetCombo->removeall();
-
-	LLDayCycleManager::preset_name_list_t user_days, sys_days;
-	LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
-
-	// Add user days.
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
-	{
-		mDayCyclePresetCombo->add(*it);
-	}
-
-	if (user_days.size() > 0)
-	{
-		mDayCyclePresetCombo->addSeparator();
-	}
-
-	// Add system days.
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
-	{
-		mDayCyclePresetCombo->add(*it);
-	}
-}
diff --git a/indra/newview/llfloaterenvironmentsettings.h b/indra/newview/llfloaterenvironmentsettings.h
deleted file mode 100644
index 0ab458a0f65ddaca3116912a6031075af3969057..0000000000000000000000000000000000000000
--- a/indra/newview/llfloaterenvironmentsettings.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/** 
- * @file llfloaterenvironmentsettings.h
- * @brief LLFloaterEnvironmentSettings class definition
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, 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$
- */
-
-#ifndef LL_LLFLOATERENVIRONMENTSETTINGS_H
-#define LL_LLFLOATERENVIRONMENTSETTINGS_H
-
-#include "llfloater.h"
-
-class LLComboBox;
-class LLRadioGroup;
-
-class LLFloaterEnvironmentSettings : public LLFloater
-{
-	LOG_CLASS(LLFloaterEnvironmentSettings);
-
-public:
-	LLFloaterEnvironmentSettings(const LLSD &key);
-	/*virtual*/	BOOL	postBuild();	
-	/*virtual*/ void	onOpen(const LLSD& key);
-
-private:
-	void onSwitchRegionSettings();
-	void onSwitchDayCycle();
-
-	void onSelectWaterPreset();
-	void onSelectSkyPreset();
-	void onSelectDayCyclePreset();
-
-	void onBtnOK();
-	void onBtnCancel();
-
-	void refresh(); /// update controls with user prefs
-	void apply();
-	void cancel();
-
-	void populateWaterPresetsList();
-	void populateSkyPresetsList();
-	void populateDayCyclePresetsList();
-
-	LLRadioGroup*	mRegionSettingsRadioGroup;
-	LLRadioGroup*	mDayCycleSettingsRadioGroup;
-
-	LLComboBox*		mWaterPresetCombo;
-	LLComboBox*		mSkyPresetCombo;
-	LLComboBox*		mDayCyclePresetCombo;
-};
-
-#endif // LL_LLFLOATERENVIRONMENTSETTINGS_H
diff --git a/indra/newview/llfloaterexperiencepicker.cpp b/indra/newview/llfloaterexperiencepicker.cpp
index bb54c57baf1a23ed33ee0fc4591ea2d9f9bbf50d..c642da7b83b104554023dd2aa4e0eff54f393f12 100644
--- a/indra/newview/llfloaterexperiencepicker.cpp
+++ b/indra/newview/llfloaterexperiencepicker.cpp
@@ -74,59 +74,8 @@ LLFloaterExperiencePicker* LLFloaterExperiencePicker::show( select_callback_t ca
 
 void LLFloaterExperiencePicker::drawFrustum()
 {
-	if(mFrustumOrigin.get())
-	{
-		LLView * frustumOrigin = mFrustumOrigin.get();
-		LLRect origin_rect;
-		frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
-		// draw context cone connecting color picker with color swatch in parent floater
-		LLRect local_rect = getLocalRect();
-		if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
-				gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
-				gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
-			}
-			gGL.end();
-		}
-
-		if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-		else
-		{
-			mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
-		}
-	}
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mFrustumOrigin.get(), mContextConeFadeTime, mContextConeInAlpha, mContextConeOutAlpha);
 }
 
 void LLFloaterExperiencePicker::draw()
diff --git a/indra/newview/llfloaterfixedenvironment.cpp b/indra/newview/llfloaterfixedenvironment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..37e162b2493c60ddad7eb646ab1d70fceda33fed
--- /dev/null
+++ b/indra/newview/llfloaterfixedenvironment.cpp
@@ -0,0 +1,889 @@
+/** 
+ * @file llfloaterfixedenvironment.cpp
+ * @brief Floaters to create and edit fixed settings for sky and water.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterfixedenvironment.h"
+
+#include <boost/make_shared.hpp>
+
+// libs
+#include "llbutton.h"
+#include "llnotifications.h"
+#include "llnotificationsutil.h"
+#include "llsliderctrl.h"
+#include "lltabcontainer.h"
+#include "llfilepicker.h"
+#include "lllocalbitmaps.h"
+#include "llsettingspicker.h"
+#include "llviewermenufile.h" // LLFilePickerReplyThread
+#include "llviewerparcelmgr.h"
+
+// newview
+#include "llpaneleditwater.h"
+#include "llpaneleditsky.h"
+
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+
+#include "llenvironment.h"
+#include "llagent.h"
+#include "llparcel.h"
+#include "lltrans.h"
+
+#include "llsettingsvo.h"
+#include "llinventorymodel.h"
+
+extern LLControlGroup gSavedSettings;
+
+namespace
+{
+    const std::string FIELD_SETTINGS_NAME("settings_name");
+
+    const std::string CONTROL_TAB_AREA("tab_settings");
+
+    const std::string BUTTON_NAME_IMPORT("btn_import");
+    const std::string BUTTON_NAME_COMMIT("btn_commit");
+    const std::string BUTTON_NAME_CANCEL("btn_cancel");
+    const std::string BUTTON_NAME_FLYOUT("btn_flyout");
+    const std::string BUTTON_NAME_LOAD("btn_load");
+
+    const std::string ACTION_SAVE("save_settings");
+    const std::string ACTION_SAVEAS("save_as_new_settings");
+    const std::string ACTION_COMMIT("commit_changes");
+    const std::string ACTION_APPLY_LOCAL("apply_local");
+    const std::string ACTION_APPLY_PARCEL("apply_parcel");
+    const std::string ACTION_APPLY_REGION("apply_region");
+
+    const std::string XML_FLYOUTMENU_FILE("menu_save_settings.xml");
+}
+
+//=========================================================================
+const std::string LLFloaterFixedEnvironment::KEY_INVENTORY_ID("inventory_id");
+
+
+//=========================================================================
+
+class LLFixedSettingCopiedCallback : public LLInventoryCallback
+{
+public:
+    LLFixedSettingCopiedCallback(LLHandle<LLFloater> handle) : mHandle(handle) {}
+
+    virtual void fire(const LLUUID& inv_item_id)
+    {
+        if (!mHandle.isDead())
+        {
+            LLViewerInventoryItem* item = gInventory.getItem(inv_item_id);
+            if (item)
+            {
+                LLFloaterFixedEnvironment* floater = (LLFloaterFixedEnvironment*)mHandle.get();
+                floater->onInventoryCreated(item->getAssetUUID(), inv_item_id);
+            }
+        }
+    }
+
+private:
+    LLHandle<LLFloater> mHandle;
+};
+
+//=========================================================================
+LLFloaterFixedEnvironment::LLFloaterFixedEnvironment(const LLSD &key) :
+    LLFloater(key),
+    mFlyoutControl(nullptr),
+    mInventoryId(),
+    mInventoryItem(nullptr),
+    mIsDirty(false),
+    mCanCopy(false),
+    mCanMod(false),
+    mCanTrans(false)
+{
+}
+
+LLFloaterFixedEnvironment::~LLFloaterFixedEnvironment()
+{
+    delete mFlyoutControl;
+}
+
+BOOL LLFloaterFixedEnvironment::postBuild()
+{
+    mTab = getChild<LLTabContainer>(CONTROL_TAB_AREA);
+    mTxtName = getChild<LLLineEditor>(FIELD_SETTINGS_NAME);
+
+    mTxtName->setCommitOnFocusLost(TRUE);
+    mTxtName->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNameChanged(mTxtName->getValue().asString()); });
+
+    getChild<LLButton>(BUTTON_NAME_IMPORT)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onButtonImport(); });
+    getChild<LLButton>(BUTTON_NAME_CANCEL)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onClickCloseBtn(); });
+    getChild<LLButton>(BUTTON_NAME_LOAD)->setClickedCallback([this](LLUICtrl *, const LLSD &) { onButtonLoad(); });
+
+    mFlyoutControl = new LLFlyoutComboBtnCtrl(this, BUTTON_NAME_COMMIT, BUTTON_NAME_FLYOUT, XML_FLYOUTMENU_FILE, false);
+    mFlyoutControl->setAction([this](LLUICtrl *ctrl, const LLSD &data) { onButtonApply(ctrl, data); });
+    mFlyoutControl->setMenuItemVisible(ACTION_COMMIT, false);
+
+    return TRUE;
+}
+
+void LLFloaterFixedEnvironment::onOpen(const LLSD& key)
+{
+    LLUUID invid;
+
+    if (key.has(KEY_INVENTORY_ID))
+    {
+        invid = key[KEY_INVENTORY_ID].asUUID();
+    }
+
+    loadInventoryItem(invid);
+    LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
+
+    updateEditEnvironment();
+    syncronizeTabs();
+    refresh();
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+
+}
+
+void LLFloaterFixedEnvironment::onClose(bool app_quitting)
+{
+    doCloseInventoryFloater(app_quitting);
+
+    LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+    LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
+
+    mSettings.reset();
+    syncronizeTabs();
+}
+
+void LLFloaterFixedEnvironment::onFocusReceived()
+{
+    if (isInVisibleChain())
+    {
+        updateEditEnvironment();
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_EDIT, LLEnvironment::TRANSITION_FAST);
+    }
+}
+
+void LLFloaterFixedEnvironment::onFocusLost()
+{
+}
+
+void LLFloaterFixedEnvironment::refresh()
+{
+    if (!mSettings)
+    {
+        // disable everything.
+        return;
+    }
+
+    bool is_inventory_avail = canUseInventory();
+
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVE, is_inventory_avail && mCanMod && !mInventoryId.isNull());
+    mFlyoutControl->setMenuItemEnabled(ACTION_SAVEAS, is_inventory_avail && mCanCopy);
+    mFlyoutControl->setMenuItemEnabled(ACTION_APPLY_PARCEL, canApplyParcel());
+    mFlyoutControl->setMenuItemEnabled(ACTION_APPLY_REGION, canApplyRegion());
+
+    mTxtName->setValue(mSettings->getName());
+    mTxtName->setEnabled(mCanMod);
+
+    S32 count = mTab->getTabCount();
+
+    for (S32 idx = 0; idx < count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(mTab->getPanelByIndex(idx));
+        if (panel)
+        {
+            panel->setCanChangeSettings(mCanMod);
+            panel->refresh();
+        }
+    }
+}
+
+void LLFloaterFixedEnvironment::syncronizeTabs()
+{
+    S32 count = mTab->getTabCount();
+
+    for (S32 idx = 0; idx < count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(mTab->getPanelByIndex(idx));
+        if (panel)
+            panel->setSettings(mSettings);
+    }
+}
+
+LLFloaterSettingsPicker * LLFloaterFixedEnvironment::getSettingsPicker()
+{
+    LLFloaterSettingsPicker *picker = static_cast<LLFloaterSettingsPicker *>(mInventoryFloater.get());
+
+    // Show the dialog
+    if (!picker)
+    {
+        picker = new LLFloaterSettingsPicker(this,
+            LLUUID::null);
+
+        mInventoryFloater = picker->getHandle();
+
+        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitSetting(data["ItemId"].asUUID() /*data["Track"]*/); });
+    }
+
+    return picker;
+}
+
+void LLFloaterFixedEnvironment::loadInventoryItem(const LLUUID  &inventoryId, bool can_trans)
+{
+    if (inventoryId.isNull())
+    {
+        mInventoryItem = nullptr;
+        mInventoryId.setNull();
+        mCanMod = true;
+        mCanCopy = true;
+        mCanTrans = true;
+        return;
+    }
+
+    mInventoryId = inventoryId;
+    LL_INFOS("SETTINGS") << "Setting edit inventory item to " << mInventoryId << "." << LL_ENDL;
+    mInventoryItem = gInventory.getItem(mInventoryId);
+
+    if (!mInventoryItem)
+    {
+        LL_WARNS("SETTINGS") << "Could not find inventory item with Id = " << mInventoryId << LL_ENDL;
+        LLNotificationsUtil::add("CantFindInvItem");
+        closeFloater();
+
+        mInventoryId.setNull();
+        mInventoryItem = nullptr;
+        return;
+    }
+
+    if (mInventoryItem->getAssetUUID().isNull())
+    {
+        LL_WARNS("ENVIRONMENT") << "Asset ID in inventory item is NULL (" << mInventoryId << ")" << LL_ENDL;
+        LLNotificationsUtil::add("UnableEditItem");
+        closeFloater();
+
+        mInventoryId.setNull();
+        mInventoryItem = nullptr;
+        return;
+    }
+
+    mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
+    mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
+    mCanTrans = can_trans && mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+
+    LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
+        [this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
+}
+
+
+void LLFloaterFixedEnvironment::checkAndConfirmSettingsLoss(LLFloaterFixedEnvironment::on_confirm_fn cb)
+{
+    if (isDirty())
+    {
+        LLSD args(LLSDMap("TYPE", mSettings->getSettingsType())
+            ("NAME", mSettings->getName()));
+
+        // create and show confirmation textbox
+        LLNotificationsUtil::add("SettingsConfirmLoss", args, LLSD(),
+            [cb](const LLSD&notif, const LLSD&resp)
+            {
+                S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+                if (opt == 0)
+                    cb();
+            });
+    }
+    else if (cb)
+    {
+        cb();
+    }
+}
+
+void LLFloaterFixedEnvironment::onPickerCommitSetting(LLUUID item_id)
+{
+    loadInventoryItem(item_id);
+//     mInventoryId = item_id;
+//     mInventoryItem = gInventory.getItem(mInventoryId);
+// 
+//     mCanCopy = mInventoryItem->getPermissions().allowCopyBy(gAgent.getID());
+//     mCanMod = mInventoryItem->getPermissions().allowModifyBy(gAgent.getID());
+//     mCanTrans = mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID());
+// 
+//     LLSettingsVOBase::getSettingsAsset(mInventoryItem->getAssetUUID(),
+//         [this](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { onAssetLoaded(asset_id, settings, status); });
+}
+
+void LLFloaterFixedEnvironment::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
+{
+    if (mInventoryItem && mInventoryItem->getAssetUUID() != asset_id)
+    {
+        LL_WARNS("ENVIRONMENT") << "Discarding obsolete asset callback" << LL_ENDL;
+        return;
+    }
+
+    clearDirtyFlag();
+
+    if (!settings || status)
+    {
+        LLSD args;
+        args["NAME"] = (mInventoryItem) ? mInventoryItem->getName() : "Unknown";
+        LLNotificationsUtil::add("FailedToFindSettings", args);
+        closeFloater();
+        return;
+    }
+
+    mSettings = settings;
+    if (mInventoryItem)
+        mSettings->setName(mInventoryItem->getName());
+
+    if (mCanCopy)
+        settings->clearFlag(LLSettingsBase::FLAG_NOCOPY);
+    else
+        settings->setFlag(LLSettingsBase::FLAG_NOCOPY);
+
+    if (mCanMod)
+        settings->clearFlag(LLSettingsBase::FLAG_NOMOD);
+    else
+        settings->setFlag(LLSettingsBase::FLAG_NOMOD);
+
+    if (mCanTrans)
+        settings->clearFlag(LLSettingsBase::FLAG_NOTRANS);
+    else
+        settings->setFlag(LLSettingsBase::FLAG_NOTRANS);
+
+    updateEditEnvironment();
+    syncronizeTabs();
+    refresh();
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST);
+}
+
+void LLFloaterFixedEnvironment::onNameChanged(const std::string &name)
+{
+    mSettings->setName(name);
+    setDirtyFlag();
+}
+
+void LLFloaterFixedEnvironment::onButtonImport()
+{
+    checkAndConfirmSettingsLoss([this](){ doImportFromDisk(); });
+}
+
+void LLFloaterFixedEnvironment::onButtonApply(LLUICtrl *ctrl, const LLSD &data)
+{
+    std::string ctrl_action = ctrl->getName();
+
+    std::string local_desc;
+    LLSettingsBase::ptr_t setting_clone;
+    bool is_local = false; // because getString can be empty
+    if (mSettings->getSettingsType() == "water")
+    {
+        LLSettingsWater::ptr_t water = std::static_pointer_cast<LLSettingsWater>(mSettings);
+        if (water)
+        {
+            setting_clone = water->buildClone();
+            // LLViewerFetchedTexture and check for FTT_LOCAL_FILE or check LLLocalBitmapMgr
+            if (LLLocalBitmapMgr::getInstance()->isLocal(water->getNormalMapID()))
+            {
+                local_desc = LLTrans::getString("EnvironmentNormalMap");
+                is_local = true;
+            }
+            else if (LLLocalBitmapMgr::getInstance()->isLocal(water->getTransparentTextureID()))
+            {
+                local_desc = LLTrans::getString("EnvironmentTransparent");
+                is_local = true;
+            }
+        }
+    }
+    else if (mSettings->getSettingsType() == "sky")
+    {
+        LLSettingsSky::ptr_t sky = std::static_pointer_cast<LLSettingsSky>(mSettings);
+        if (sky)
+        {
+            setting_clone = sky->buildClone();
+            if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getSunTextureId()))
+            {
+                local_desc = LLTrans::getString("EnvironmentSun");
+                is_local = true;
+            }
+            else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getMoonTextureId()))
+            {
+                local_desc = LLTrans::getString("EnvironmentMoon");
+                is_local = true;
+            }
+            else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getCloudNoiseTextureId()))
+            {
+                local_desc = LLTrans::getString("EnvironmentCloudNoise");
+                is_local = true;
+            }
+            else if (LLLocalBitmapMgr::getInstance()->isLocal(sky->getBloomTextureId()))
+            {
+                local_desc = LLTrans::getString("EnvironmentBloom");
+                is_local = true;
+            }
+        }
+    }
+
+    if (is_local)
+    {
+        LLSD args;
+        args["FIELD"] = local_desc;
+        LLNotificationsUtil::add("WLLocalTextureFixedBlock", args);
+        return;
+    }
+
+    if (ctrl_action == ACTION_SAVE)
+    {
+        doApplyUpdateInventory(setting_clone);
+    }
+    else if (ctrl_action == ACTION_SAVEAS)
+    {
+        LLSD args;
+        args["DESC"] = mSettings->getName();
+        LLNotificationsUtil::add("SaveSettingAs", args, LLSD(), boost::bind(&LLFloaterFixedEnvironment::onSaveAsCommit, this, _1, _2, setting_clone));
+    }
+    else if ((ctrl_action == ACTION_APPLY_LOCAL) ||
+        (ctrl_action == ACTION_APPLY_PARCEL) ||
+        (ctrl_action == ACTION_APPLY_REGION))
+    {
+        doApplyEnvironment(ctrl_action, setting_clone);
+    }
+    else
+    {
+        LL_WARNS("ENVIRONMENT") << "Unknown settings action '" << ctrl_action << "'" << LL_ENDL;
+    }
+}
+
+void LLFloaterFixedEnvironment::onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+    if (0 == option)
+    {
+        std::string settings_name = response["message"].asString();
+
+        LLInventoryObject::correctInventoryName(settings_name);
+        if (settings_name.empty())
+        {
+            // Ideally notification should disable 'OK' button if name won't fit our requirements,
+            // for now either display notification, or use some default name
+            settings_name = "Unnamed";
+        }
+
+        if (mCanMod)
+        {
+            doApplyCreateNewInventory(settings_name, settings);
+        }
+        else if (mInventoryItem)
+        {
+            const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false);
+            LLUUID parent_id = mInventoryItem->getParentUUID();
+            if (marketplacelistings_id == parent_id)
+            {
+                parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
+            }
+
+            LLPointer<LLInventoryCallback> cb = new LLFixedSettingCopiedCallback(getHandle());
+            copy_inventory_item(
+                gAgent.getID(),
+                mInventoryItem->getPermissions().getOwner(),
+                mInventoryItem->getUUID(),
+                parent_id,
+                settings_name,
+                cb);
+        }
+        else
+        {
+            LL_WARNS() << "Failed to copy fixed env setting" << LL_ENDL;
+        }
+    }
+}
+
+void LLFloaterFixedEnvironment::onClickCloseBtn(bool app_quitting)
+{
+    if (!app_quitting)
+        checkAndConfirmSettingsLoss([this](){ closeFloater(); clearDirtyFlag(); });
+    else
+        closeFloater();
+}
+
+void LLFloaterFixedEnvironment::onButtonLoad()
+{
+    checkAndConfirmSettingsLoss([this](){ doSelectFromInventory(); });
+}
+
+void LLFloaterFixedEnvironment::doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings)
+{
+    if (mInventoryItem)
+    {
+        LLUUID parent_id = mInventoryItem->getParentUUID();
+        U32 next_owner_perm = mInventoryItem->getPermissions().getMaskNextOwner();
+        LLSettingsVOBase::createInventoryItem(settings, next_owner_perm, parent_id, settings_name,
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    }
+    else
+    {
+        LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
+        // This method knows what sort of settings object to create.
+        LLSettingsVOBase::createInventoryItem(settings, parent_id, settings_name,
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    }
+}
+
+void LLFloaterFixedEnvironment::doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings)
+{
+    LL_DEBUGS("ENVEDIT") << "Update inventory for " << mInventoryId << LL_ENDL;
+    if (mInventoryId.isNull())
+    {
+        LLSettingsVOBase::createInventoryItem(settings, gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS), std::string(),
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryCreated(asset_id, inventory_id, results); });
+    }
+    else
+    {
+        LLSettingsVOBase::updateInventoryItem(settings, mInventoryId,
+            [this](LLUUID asset_id, LLUUID inventory_id, LLUUID, LLSD results) { onInventoryUpdated(asset_id, inventory_id, results); });
+    }
+}
+
+void LLFloaterFixedEnvironment::doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings)
+{
+    U32 flags(0);
+
+    if (mInventoryItem)
+    {
+        if (!mInventoryItem->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOMOD;
+        if (!mInventoryItem->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOTRANS;
+    }
+
+    flags |= settings->getFlags();
+    settings->setFlag(flags);
+
+    if (where == ACTION_APPLY_LOCAL)
+    {
+        settings->setName("Local"); // To distinguish and make sure there is a name. Safe, because this is a copy.
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, settings);
+    }
+    else if (where == ACTION_APPLY_PARCEL)
+    {
+        LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
+
+        if ((!parcel) || (parcel->getLocalID() == INVALID_PARCEL_ID))
+        {
+            LL_WARNS("ENVIRONMENT") << "Can not identify parcel. Not applying." << LL_ENDL;
+            LLNotificationsUtil::add("WLParcelApplyFail");
+            return;
+        }
+
+        if (mInventoryItem && !isDirty())
+        {
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
+        }
+        else if (settings->getSettingsType() == "sky")
+        {
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
+        }
+        else if (settings->getSettingsType() == "water")
+        {
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
+        }
+    }
+    else if (where == ACTION_APPLY_REGION)
+    {
+        if (mInventoryItem && !isDirty())
+        {
+            LLEnvironment::instance().updateRegion(mInventoryItem->getAssetUUID(), mInventoryItem->getName(), LLEnvironment::NO_TRACK, -1, -1, flags);
+        }
+        else if (settings->getSettingsType() == "sky")
+        {
+            LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsSky>(settings), -1, -1);
+        }
+        else if (settings->getSettingsType() == "water")
+        {
+            LLEnvironment::instance().updateRegion(std::static_pointer_cast<LLSettingsWater>(settings), -1, -1);
+        }
+    }
+    else
+    {
+        LL_WARNS("ENVIRONMENT") << "Unknown apply '" << where << "'" << LL_ENDL;
+        return;
+    }
+
+}
+
+void LLFloaterFixedEnvironment::doCloseInventoryFloater(bool quitting)
+{
+    LLFloater* floaterp = mInventoryFloater.get();
+
+    if (floaterp)
+    {
+        floaterp->closeFloater(quitting);
+    }
+}
+
+void LLFloaterFixedEnvironment::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been created with asset " << asset_id << " results are:" << results << LL_ENDL;
+
+    if (inventory_id.isNull() || !results["success"].asBoolean())
+    {
+        LLNotificationsUtil::add("CantCreateInventory");
+        return;
+    }
+    onInventoryCreated(asset_id, inventory_id);
+}
+
+void LLFloaterFixedEnvironment::onInventoryCreated(LLUUID asset_id, LLUUID inventory_id)
+{
+    bool can_trans = true;
+    if (mInventoryItem)
+    {
+        LLPermissions perms = mInventoryItem->getPermissions();
+
+        LLInventoryItem *created_item = gInventory.getItem(mInventoryId);
+
+        if (created_item)
+        {
+            can_trans = perms.allowOperationBy(PERM_TRANSFER, gAgent.getID());
+            created_item->setPermissions(perms);
+            created_item->updateServer(false);
+        }
+    }
+    clearDirtyFlag();
+    setFocus(TRUE);                 // Call back the focus...
+    loadInventoryItem(inventory_id, can_trans);
+}
+
+void LLFloaterFixedEnvironment::onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results)
+{
+    LL_WARNS("ENVIRONMENT") << "Inventory item " << inventory_id << " has been updated with asset " << asset_id << " results are:" << results << LL_ENDL;
+
+    clearDirtyFlag();
+    if (inventory_id != mInventoryId)
+    {
+        loadInventoryItem(inventory_id);
+    }
+}
+
+
+void LLFloaterFixedEnvironment::clearDirtyFlag()
+{
+    mIsDirty = false;
+
+    S32 count = mTab->getTabCount();
+
+    for (S32 idx = 0; idx < count; ++idx)
+    {
+        LLSettingsEditPanel *panel = static_cast<LLSettingsEditPanel *>(mTab->getPanelByIndex(idx));
+        if (panel)
+            panel->clearIsDirty();
+    }
+
+}
+
+void LLFloaterFixedEnvironment::doSelectFromInventory()
+{
+    LLFloaterSettingsPicker *picker = getSettingsPicker();
+
+    picker->setSettingsFilter(mSettings->getSettingsTypeValue());
+    picker->openFloater();
+    picker->setFocus(TRUE);
+}
+
+void LLFloaterFixedEnvironment::onPanelDirtyFlagChanged(bool value)
+{
+    if (value)
+        setDirtyFlag();
+}
+
+//-------------------------------------------------------------------------
+bool LLFloaterFixedEnvironment::canUseInventory() const
+{
+    return LLEnvironment::instance().isInventoryEnabled();
+}
+
+bool LLFloaterFixedEnvironment::canApplyRegion() const
+{
+    return gAgent.canManageEstate();
+}
+
+bool LLFloaterFixedEnvironment::canApplyParcel() const
+{
+    return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
+}
+
+//=========================================================================
+LLFloaterFixedEnvironmentWater::LLFloaterFixedEnvironmentWater(const LLSD &key):
+    LLFloaterFixedEnvironment(key)
+{}
+
+BOOL LLFloaterFixedEnvironmentWater::postBuild()
+{
+    if (!LLFloaterFixedEnvironment::postBuild())
+        return FALSE;
+
+    LLPanelSettingsWater * panel;
+    panel = new LLPanelSettingsWaterMainTab;
+    panel->buildFromFile("panel_settings_water.xml");
+    panel->setWater(std::static_pointer_cast<LLSettingsWater>(mSettings));
+    panel->setOnDirtyFlagChanged( [this] (LLPanel *, bool value) { onPanelDirtyFlagChanged(value); });
+    mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true));
+
+    return TRUE;
+}
+
+void LLFloaterFixedEnvironmentWater::updateEditEnvironment(void)
+{
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, 
+        std::static_pointer_cast<LLSettingsWater>(mSettings));
+}
+
+void LLFloaterFixedEnvironmentWater::onOpen(const LLSD& key)
+{
+    if (!mSettings)
+    {
+        // Initialize the settings, take a snapshot of the current water. 
+        mSettings = LLEnvironment::instance().getEnvironmentFixedWater(LLEnvironment::ENV_CURRENT)->buildClone();
+        mSettings->setName("Snapshot water (new)");
+
+        // TODO: Should we grab sky and keep it around for reference?
+    }
+
+    LLFloaterFixedEnvironment::onOpen(key);
+}
+
+void LLFloaterFixedEnvironmentWater::doImportFromDisk()
+{   // Load a a legacy Windlight XML from disk.
+    (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+}
+
+void LLFloaterFixedEnvironmentWater::loadWaterSettingFromFile(const std::vector<std::string>& filenames)
+{
+    LLSD messages;
+    if (filenames.size() < 1) return;
+    std::string filename = filenames[0];
+    LL_DEBUGS("ENVEDIT") << "Selected file: " << filename << LL_ENDL;
+    LLSettingsWater::ptr_t legacywater = LLEnvironment::createWaterFromLegacyPreset(filename, messages);
+
+    if (!legacywater)
+    {   
+        LLNotificationsUtil::add("WLImportFail", messages);
+        return;
+    }
+
+    loadInventoryItem(LLUUID::null);
+
+    setDirtyFlag();
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, legacywater);
+    setEditSettings(legacywater);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST, true);
+}
+
+//=========================================================================
+LLFloaterFixedEnvironmentSky::LLFloaterFixedEnvironmentSky(const LLSD &key) :
+    LLFloaterFixedEnvironment(key)
+{}
+
+BOOL LLFloaterFixedEnvironmentSky::postBuild()
+{
+    if (!LLFloaterFixedEnvironment::postBuild())
+        return FALSE;
+
+    LLPanelSettingsSky * panel;
+    panel = new LLPanelSettingsSkyAtmosTab;
+    panel->buildFromFile("panel_settings_sky_atmos.xml");
+    panel->setSky(std::static_pointer_cast<LLSettingsSky>(mSettings));
+    panel->setOnDirtyFlagChanged([this](LLPanel *, bool value) { onPanelDirtyFlagChanged(value); });
+    mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(true));
+
+    panel = new LLPanelSettingsSkyCloudTab;
+    panel->buildFromFile("panel_settings_sky_clouds.xml");
+    panel->setSky(std::static_pointer_cast<LLSettingsSky>(mSettings));
+    panel->setOnDirtyFlagChanged([this](LLPanel *, bool value) { onPanelDirtyFlagChanged(value); });
+    mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(false));
+
+    panel = new LLPanelSettingsSkySunMoonTab;
+    panel->buildFromFile("panel_settings_sky_sunmoon.xml");
+    panel->setSky(std::static_pointer_cast<LLSettingsSky>(mSettings));
+    panel->setOnDirtyFlagChanged([this](LLPanel *, bool value) { onPanelDirtyFlagChanged(value); });
+    mTab->addTabPanel(LLTabContainer::TabPanelParams().panel(panel).select_tab(false));
+
+    return TRUE;
+}
+
+void LLFloaterFixedEnvironmentSky::updateEditEnvironment(void)
+{
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, 
+        std::static_pointer_cast<LLSettingsSky>(mSettings));
+}
+
+void LLFloaterFixedEnvironmentSky::onOpen(const LLSD& key)
+{
+    if (!mSettings)
+    {
+        // Initialize the settings, take a snapshot of the current water. 
+        mSettings = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_CURRENT)->buildClone();
+        mSettings->setName("Snapshot sky (new)");
+        LLEnvironment::instance().saveBeaconsState();
+        // TODO: Should we grab water and keep it around for reference?
+    }
+
+    LLFloaterFixedEnvironment::onOpen(key);
+}
+
+void LLFloaterFixedEnvironmentSky::onClose(bool app_quitting)
+{
+    LLEnvironment::instance().revertBeaconsState();
+
+    LLFloaterFixedEnvironment::onClose(app_quitting);
+}
+
+void LLFloaterFixedEnvironmentSky::doImportFromDisk()
+{   // Load a a legacy Windlight XML from disk.
+    (new LLFilePickerReplyThread(boost::bind(&LLFloaterFixedEnvironmentSky::loadSkySettingFromFile, this, _1), LLFilePicker::FFLOAD_XML, false))->getFile();
+}
+
+void LLFloaterFixedEnvironmentSky::loadSkySettingFromFile(const std::vector<std::string>& filenames)
+{
+    if (filenames.size() < 1) return;
+    std::string filename = filenames[0];
+    LLSD messages;
+
+    LL_DEBUGS("ENVEDIT") << "Selected file: " << filename << LL_ENDL;
+    LLSettingsSky::ptr_t legacysky = LLEnvironment::createSkyFromLegacyPreset(filename, messages);
+
+    if (!legacysky)
+    {   
+        LLNotificationsUtil::add("WLImportFail", messages);
+
+        return;
+    }
+
+    loadInventoryItem(LLUUID::null);
+
+    setDirtyFlag();
+    LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_EDIT, legacysky);
+    setEditSettings(legacysky);
+    LLEnvironment::instance().updateEnvironment(LLEnvironment::TRANSITION_FAST, true);
+}
+
+//=========================================================================
diff --git a/indra/newview/llfloaterfixedenvironment.h b/indra/newview/llfloaterfixedenvironment.h
new file mode 100644
index 0000000000000000000000000000000000000000..513996c4a393e6f9f6c4c65b8b4fbb4cc7495991
--- /dev/null
+++ b/indra/newview/llfloaterfixedenvironment.h
@@ -0,0 +1,207 @@
+/** 
+ * @file llfloaterfixedenvironment.h
+ * @brief Floaters to create and edit fixed settings for sky and water.
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, 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$
+ */
+
+#ifndef LL_FLOATERFIXEDENVIRONMENT_H
+#define LL_FLOATERFIXEDENVIRONMENT_H
+
+#include "llfloater.h"
+#include "llsettingsbase.h"
+#include "llflyoutcombobtn.h"
+#include "llinventory.h"
+
+#include "boost/signals2.hpp"
+
+class LLTabContainer;
+class LLButton;
+class LLLineEditor;
+class LLFloaterSettingsPicker;
+class LLFixedSettingCopiedCallback;
+
+/**
+ * Floater container for creating and editing fixed environment settings.
+ */
+class LLFloaterFixedEnvironment : public LLFloater
+{
+    LOG_CLASS(LLFloaterFixedEnvironment);
+
+    friend class LLFixedSettingCopiedCallback;
+
+public:
+    static const std::string    KEY_INVENTORY_ID;
+
+                            LLFloaterFixedEnvironment(const LLSD &key);
+                            ~LLFloaterFixedEnvironment();
+
+    virtual BOOL	        postBuild()                 override;
+    virtual void            onOpen(const LLSD& key)     override;
+    virtual void            onClose(bool app_quitting)  override;
+
+    virtual void            onFocusReceived()           override;
+    virtual void            onFocusLost()               override;
+
+    void                    setEditSettings(const LLSettingsBase::ptr_t &settings)  { mSettings = settings; clearDirtyFlag(); syncronizeTabs(); refresh(); }
+    LLSettingsBase::ptr_t   getEditSettings()   const                           { return mSettings; }
+
+    virtual BOOL            isDirty() const override            { return getIsDirty(); }
+
+protected:
+    typedef std::function<void()> on_confirm_fn;
+
+    virtual void            updateEditEnvironment() = 0;
+    virtual void            refresh()                   override;
+    virtual void            syncronizeTabs();
+
+    LLFloaterSettingsPicker *getSettingsPicker();
+
+    void                    loadInventoryItem(const LLUUID  &inventoryId, bool can_trans = true);
+
+    void                    checkAndConfirmSettingsLoss(on_confirm_fn cb);
+
+    LLTabContainer *        mTab;
+    LLLineEditor *          mTxtName;
+
+    LLSettingsBase::ptr_t   mSettings;
+
+    virtual void            doImportFromDisk() = 0;
+    virtual void            doApplyCreateNewInventory(std::string settings_name, const LLSettingsBase::ptr_t &settings);
+    virtual void            doApplyUpdateInventory(const LLSettingsBase::ptr_t &settings);
+    virtual void            doApplyEnvironment(const std::string &where, const LLSettingsBase::ptr_t &settings);
+    void                    doCloseInventoryFloater(bool quitting = false);
+
+    bool                    canUseInventory() const;
+    bool                    canApplyRegion() const;
+    bool                    canApplyParcel() const;
+
+    LLFlyoutComboBtnCtrl *      mFlyoutControl;
+
+    LLUUID                  mInventoryId;
+    LLInventoryItem *       mInventoryItem;
+    LLHandle<LLFloater>     mInventoryFloater;
+    bool                    mCanCopy;
+    bool                    mCanMod;
+    bool                    mCanTrans;
+
+    void                    onInventoryCreated(LLUUID asset_id, LLUUID inventory_id);
+    void                    onInventoryCreated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+    void                    onInventoryUpdated(LLUUID asset_id, LLUUID inventory_id, LLSD results);
+
+    bool                    getIsDirty() const  { return mIsDirty; }
+    void                    setDirtyFlag()      { mIsDirty = true; }
+    virtual void            clearDirtyFlag();
+
+    void                    doSelectFromInventory();
+    void                    onPanelDirtyFlagChanged(bool);
+
+    virtual void            onClickCloseBtn(bool app_quitting = false) override;
+    void                    onSaveAsCommit(const LLSD& notification, const LLSD& response, const LLSettingsBase::ptr_t &settings);
+
+private:
+    void                    onNameChanged(const std::string &name);
+
+    void                    onButtonImport();
+    void                    onButtonApply(LLUICtrl *ctrl, const LLSD &data);
+    void                    onButtonLoad();
+
+    void                    onPickerCommitSetting(LLUUID item_id);
+    void                    onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status);
+
+    bool                    mIsDirty;
+};
+
+class LLFloaterFixedEnvironmentWater : public LLFloaterFixedEnvironment
+{
+    LOG_CLASS(LLFloaterFixedEnvironmentWater);
+
+public:
+    LLFloaterFixedEnvironmentWater(const LLSD &key);
+
+    BOOL	                postBuild()                 override;
+
+    virtual void            onOpen(const LLSD& key)     override;
+
+protected:
+    virtual void            updateEditEnvironment()     override;
+
+    virtual void            doImportFromDisk()          override;
+    void                    loadWaterSettingFromFile(const std::vector<std::string>& filenames);
+
+private:
+};
+
+class LLFloaterFixedEnvironmentSky : public LLFloaterFixedEnvironment
+{
+    LOG_CLASS(LLFloaterFixedEnvironmentSky);
+
+public:
+    LLFloaterFixedEnvironmentSky(const LLSD &key);
+
+    BOOL	                postBuild()                 override;
+
+    virtual void            onOpen(const LLSD& key)     override;
+    virtual void            onClose(bool app_quitting)  override;
+
+protected:
+    virtual void            updateEditEnvironment()     override;
+
+    virtual void            doImportFromDisk()          override;
+    void                    loadSkySettingFromFile(const std::vector<std::string>& filenames);
+
+private:
+};
+
+class LLSettingsEditPanel : public LLPanel
+{
+public:
+    virtual void setSettings(const LLSettingsBase::ptr_t &) = 0;
+
+    typedef boost::signals2::signal<void(LLPanel *, bool)> on_dirty_charged_sg;
+    typedef boost::signals2::connection connection_t;
+
+    inline bool         getIsDirty() const      { return mIsDirty; }
+    inline void         setIsDirty()            { mIsDirty = true; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
+    inline void         clearIsDirty()          { mIsDirty = false; if (!mOnDirtyChanged.empty()) mOnDirtyChanged(this, mIsDirty); }
+
+    inline bool        getCanChangeSettings() const    { return mCanEdit; }
+    inline void        setCanChangeSettings(bool flag) { mCanEdit = flag; }
+
+    inline connection_t setOnDirtyFlagChanged(on_dirty_charged_sg::slot_type cb)    { return mOnDirtyChanged.connect(cb); }
+
+
+protected:
+    LLSettingsEditPanel() :
+        LLPanel(),
+        mIsDirty(false),
+        mOnDirtyChanged()
+    {}
+
+private:
+    bool                mIsDirty;
+    bool                mCanEdit;
+    
+    on_dirty_charged_sg mOnDirtyChanged;
+};
+
+#endif // LL_FLOATERFIXEDENVIRONMENT_H
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index e778e8eb9e14b7e831149165c3b2a526ae25d9ac..c4e0dd483fa04521c72899959804f4f42927517c 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -485,7 +485,7 @@ void LLFloaterGesture::onClickNew()
 						  "",
 						  LLAssetType::AT_GESTURE,
 						  LLInventoryType::IT_GESTURE,
-						  NOT_WEARABLE,
+                          NO_INV_SUBTYPE,
 						  PERM_MOVE | LLFloaterPerms::getNextOwnerPerms("Gestures"),
 						  cb);
 }
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index d8f4360142e5ac4ba8c8f96cf01376f90f76a9ac..af0e56e4480cb4c85aebb877dd5d3cc6a113eba2 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -79,9 +79,11 @@
 #include "lltrans.h"
 #include "llpanelexperiencelisteditor.h"
 #include "llpanelexperiencepicker.h"
+#include "llpanelenvironment.h"
 #include "llexperiencecache.h"
 
 #include "llgroupactions.h"
+#include "llenvironment.h"
 
 const F64 COVENANT_REFRESH_TIME_SEC = 60.0f;
 
@@ -139,6 +141,38 @@ class LLPanelLandExperiences
 	LLPanelExperienceListEditor* mBlocked;
 };
 
+
+class LLPanelLandEnvironment
+    : public LLPanelEnvironmentInfo
+{
+public:
+                        LLPanelLandEnvironment(LLSafeHandle<LLParcelSelection>& parcelp);
+    
+    virtual bool        isRegion() const override { return false; }
+    virtual bool        isLargeEnough() override 
+    { 
+        LLParcel *parcelp = mParcel->getParcel();
+        return ((parcelp) ? (parcelp->getArea() >= MINIMUM_PARCEL_SIZE) : false);
+    }   
+
+    virtual BOOL        postBuild() override;
+    virtual void        refresh() override;
+
+    virtual LLParcel *  getParcel() override;
+
+    virtual bool        canEdit() override;
+    virtual S32         getParcelId() override; 
+
+protected:
+    virtual void        refreshFromSource() override;
+
+    bool                isSameRegion();
+
+    LLSafeHandle<LLParcelSelection> &   mParcel;
+    S32                 mLastParcelId;
+};
+
+
 // inserts maturity info(icon and text) into target textbox 
 // names_floater - pointer to floater which contains strings with maturity icons filenames
 // str_to_parse is string in format "txt1[MATURITY]txt2" where maturity icon and text will be inserted instead of [MATURITY]
@@ -227,7 +261,7 @@ LLPanelLandCovenant* LLFloaterLand::getCurrentPanelLandCovenant()
 // static
 void LLFloaterLand::refreshAll()
 {
-	LLFloaterLand* land_instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+	LLFloaterLand* land_instance = LLFloaterReg::findTypedInstance<LLFloaterLand>("about_land");
 	if(land_instance)
 	{
 		land_instance->refresh();
@@ -278,6 +312,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed)
 	mFactoryMap["land_media_panel"] =	LLCallbackMap(createPanelLandMedia, this);
 	mFactoryMap["land_access_panel"] =	LLCallbackMap(createPanelLandAccess, this);
 	mFactoryMap["land_experiences_panel"] =	LLCallbackMap(createPanelLandExperiences, this);
+    mFactoryMap["land_environment_panel"] = LLCallbackMap(createPanelLandEnvironment, this);
 
 	sObserver = new LLParcelSelectionObserver();
 	LLViewerParcelMgr::getInstance()->addObserver( sObserver );
@@ -319,6 +354,7 @@ void LLFloaterLand::refresh()
 	mPanelAccess->refresh();
 	mPanelCovenant->refresh();
 	mPanelExperiences->refresh();
+    mPanelEnvironment->refresh();
 }
 
 
@@ -387,6 +423,14 @@ void* LLFloaterLand::createPanelLandExperiences(void* data)
 	return self->mPanelExperiences;
 }
 
+//static 
+void* LLFloaterLand::createPanelLandEnvironment(void* data)
+{
+    LLFloaterLand* self = (LLFloaterLand*)data;
+    self->mPanelEnvironment = new LLPanelLandEnvironment(self->mParcel);
+    return self->mPanelEnvironment;
+}
+
 
 //---------------------------------------------------------------------------
 // LLPanelLandGeneral
@@ -3268,3 +3312,144 @@ void LLPanelLandExperiences::refresh()
 	refreshPanel(mAllowed, EXPERIENCE_KEY_TYPE_ALLOWED);
 	refreshPanel(mBlocked, EXPERIENCE_KEY_TYPE_BLOCKED);
 }
+
+//=========================================================================
+
+LLPanelLandEnvironment::LLPanelLandEnvironment(LLParcelSelectionHandle& parcel) :
+    LLPanelEnvironmentInfo(),
+    mParcel(parcel),
+    mLastParcelId(INVALID_PARCEL_ID)
+{
+}
+
+BOOL LLPanelLandEnvironment::postBuild()
+{
+    if (!LLPanelEnvironmentInfo::postBuild())
+        return FALSE;
+
+    getChild<LLUICtrl>(BTN_USEDEFAULT)->setLabelArg("[USEDEFAULT]", getString(STR_LABEL_USEREGION));
+    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setVisible(FALSE);
+    getChild<LLUICtrl>(PNL_REGION_MSG)->setVisible(FALSE);
+    getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(TRUE);
+
+    return TRUE;
+}
+
+void LLPanelLandEnvironment::refresh()
+{
+    if (gDisconnected)
+        return;
+
+    commitDayLenOffsetChanges(false); // commit unsaved changes if any
+
+    if (!isSameRegion())
+    {
+        setCrossRegion(true);
+        mCurrentEnvironment.reset();
+        mLastParcelId = INVALID_PARCEL_ID;
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+        setControlsEnabled(false);
+        return;
+    }
+
+    if (mLastParcelId != getParcelId())
+    {
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+        mCurrentEnvironment.reset();
+    }
+
+    if (!mCurrentEnvironment && mCurEnvVersion <= INVALID_PARCEL_ENVIRONMENT_VERSION)
+    {
+        refreshFromSource();
+        return;
+    }
+
+    LLPanelEnvironmentInfo::refresh();
+}
+
+void LLPanelLandEnvironment::refreshFromSource()
+{
+    LLParcel *parcel = getParcel();
+
+    if (!LLEnvironment::instance().isExtendedEnvironmentEnabled())
+    {
+        setNoEnvironmentSupport(true);
+        setControlsEnabled(false);
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+        return;
+    }
+    setNoEnvironmentSupport(false);
+
+    if (!parcel)
+    {
+        setNoSelection(true);
+        setControlsEnabled(false);
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+        return;
+    }
+
+    setNoSelection(false);
+    if (isSameRegion())
+    {
+        LL_DEBUGS("ENVIRONMENT") << "Requesting environment for parcel " << parcel->getLocalID() << ", known version " << mCurEnvVersion << LL_ENDL;
+        setCrossRegion(false);
+
+        LLHandle<LLPanel> that_h = getHandle();
+
+        if (mCurEnvVersion < UNSET_PARCEL_ENVIRONMENT_VERSION)
+        {
+            // to mark as requesting
+            mCurEnvVersion = parcel->getParcelEnvironmentVersion();
+        }
+        mLastParcelId = parcel->getLocalID();
+
+        LLEnvironment::instance().requestParcel(parcel->getLocalID(),
+            [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) 
+            {  
+                LLPanelLandEnvironment *that = (LLPanelLandEnvironment*)that_h.get();
+                if (!that) return;
+                that->mLastParcelId = parcel_id; 
+                that->onEnvironmentReceived(parcel_id, envifo); 
+            });
+    }
+    else
+    {
+        setCrossRegion(true);
+        mCurrentEnvironment.reset();
+        mLastParcelId = INVALID_PARCEL_ID;
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+    }
+    setControlsEnabled(false);
+}
+
+
+bool LLPanelLandEnvironment::isSameRegion()
+{
+    LLViewerRegion* regionp = LLViewerParcelMgr::instance().getSelectionRegion();
+
+    return (!regionp || (regionp->getRegionID() == gAgent.getRegion()->getRegionID()));
+}
+
+LLParcel *LLPanelLandEnvironment::getParcel()
+{
+    return mParcel->getParcel();
+}
+
+
+bool LLPanelLandEnvironment::canEdit()
+{
+    LLParcel *parcel = getParcel();
+    if (!parcel)
+        return false;
+
+    return LLEnvironment::instance().canAgentUpdateParcelEnvironment(parcel) && mAllowOverride;
+}
+
+S32 LLPanelLandEnvironment::getParcelId() 
+{
+    LLParcel *parcel = getParcel();
+    if (!parcel)
+        return INVALID_PARCEL_ID;
+
+    return parcel->getLocalID();
+}
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 0c49d78a20974f15b48db0a7ed8c61647acee935..5d9b411f0458ddbec843bd01259c722eb862e960 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -67,6 +67,7 @@ class LLPanelLandRenters;
 class LLPanelLandCovenant;
 class LLParcel;
 class LLPanelLandExperiences;
+class LLPanelLandEnvironment;
 
 class LLFloaterLand
 :	public LLFloater
@@ -103,6 +104,7 @@ class LLFloaterLand
 	static void* createPanelLandMedia(void* data);
 	static void* createPanelLandAccess(void* data);
 	static void* createPanelLandExperiences(void* data);
+    static void* createPanelLandEnvironment(void* data);
 	static void* createPanelLandBan(void* data);
 
 
@@ -119,6 +121,7 @@ class LLFloaterLand
 	LLPanelLandAccess*		mPanelAccess;
 	LLPanelLandCovenant*	mPanelCovenant;
 	LLPanelLandExperiences*	mPanelExperiences;
+    LLPanelLandEnvironment *mPanelEnvironment;
 
 	LLSafeHandle<LLParcelSelection>	mParcel;
 
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 35362c0c7c74cc37ba451a8dfdf3ca0b6f2e10a9..bc44e37c5ade5b85a498be9fc1cf78cc6ff8c755 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -107,6 +107,10 @@ const double RETAIN_COEFFICIENT = 100;
 // So this const is used as a size of Smooth combobox list.
 const S32 SMOOTH_VALUES_NUMBER = 10;
 
+// mCameraDistance
+// Also see: mCameraZoom
+const F32 MODEL_PREVIEW_CAMERA_DISTANCE = 16.f;
+
 void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
 
 
@@ -430,7 +434,7 @@ void LLFloaterModelPreview::initModelPreview()
 	}
 
 	mModelPreview = new LLModelPreview(512, 512, this );
-	mModelPreview->setPreviewTarget(16.f);
+	mModelPreview->setPreviewTarget(MODEL_PREVIEW_CAMERA_DISTANCE);
 	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelPreview::setDetails, this, _1, _2, _3, _4, _5));
 	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelPreview::modelUpdated, this, _1));
 }
@@ -3640,10 +3644,9 @@ BOOL LLModelPreview::render()
 	S32 width = getWidth();
 	S32 height = getHeight();
 
-	LLGLSUIDefault def;
+	LLGLSUIDefault def; // GL_BLEND, GL_ALPHA_TEST, GL_CULL_FACE, depth test
 	LLGLDisable no_blend(GL_BLEND);
-	LLGLEnable cull(GL_CULL_FACE);
-	LLGLDepthTest depth(GL_TRUE);
+	LLGLDepthTest depth(GL_FALSE); // SL-12781 disable z-buffer to render background color
 	LLGLDisable fog(GL_FOG);
 
 	{
@@ -3651,7 +3654,7 @@ BOOL LLModelPreview::render()
 		{
 			gUIProgram.bind();
 		}
-		//clear background to blue
+		//clear background to grey
 		gGL.matrixMode(LLRender::MM_PROJECTION);
 		gGL.pushMatrix();
 		gGL.loadIdentity();
@@ -3756,7 +3759,7 @@ BOOL LLModelPreview::render()
 
 	F32 explode = mFMP->childGetValue("physics_explode").asReal();
 
-	glClear(GL_DEPTH_BUFFER_BIT);
+	LLGLDepthTest gls_depth(GL_TRUE); // SL-12781 re-enable z-buffer for 3D model preview
 
 	LLRect preview_rect;
 
@@ -3779,7 +3782,6 @@ BOOL LLModelPreview::render()
 		target_pos = getPreviewAvatar()->getPositionAgent();
 		z_near = 0.01f;
 		z_far = 1024.f;
-		mCameraDistance = 16.f;
 
 		//render avatar previews every frame
 		refresh();
@@ -3919,9 +3921,9 @@ BOOL LLModelPreview::render()
 			{
 				glClear(GL_DEPTH_BUFFER_BIT);
 				
-				for (U32 i = 0; i < 2; i++)
+				for (U32 pass = 0; pass < 2; pass++)
 				{
-					if (i == 0)
+					if (pass == 0)
 					{ //depth only pass
 						gGL.setColorMask(false, false);
 					}
@@ -3931,7 +3933,7 @@ BOOL LLModelPreview::render()
 					}
 
 					//enable alpha blending on second pass but not first pass
-					LLGLState blend(GL_BLEND, i); 
+					LLGLState blend(GL_BLEND, pass);
 					
 					gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA);
 
@@ -4037,7 +4039,7 @@ BOOL LLModelPreview::render()
 
 					glLineWidth(3.f);
 					glPointSize(8.f);
-					gPipeline.enableLightsFullbright(LLColor4::white);
+					gPipeline.enableLightsFullbright();
 					//show degenerate triangles
 					LLGLDepthTest depth(GL_TRUE, GL_TRUE, GL_ALWAYS);
 					LLGLDisable cull(GL_CULL_FACE);
diff --git a/indra/newview/llfloatermyenvironment.cpp b/indra/newview/llfloatermyenvironment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..21d106c8b1ff1a551cb297bcc44fdfac048fdad3
--- /dev/null
+++ b/indra/newview/llfloatermyenvironment.cpp
@@ -0,0 +1,459 @@
+/** 
+ * @file llfloatergesture.cpp
+ * @brief LLFloaterMyEnvironment class implementation
+ *
+ * $LicenseInfo:firstyear=2002&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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloatermyenvironment.h"
+
+#include "llinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+
+#include "llagent.h"
+#include "llclipboard.h"
+#include "llcheckboxctrl.h"
+#include "llviewerinventory.h"
+#include "llenvironment.h"
+#include "llparcel.h"
+#include "llviewerparcelmgr.h"
+
+//=========================================================================
+namespace
+{
+    const std::string CHECK_DAYS("chk_days");
+    const std::string CHECK_SKIES("chk_skies");
+    const std::string CHECK_WATER("chk_water");
+    const std::string FLT_SEARCH("flt_search");
+    const std::string PANEL_SETTINGS("pnl_settings");
+    const std::string CHECK_SHOWFOLDERS("chk_showfolders");
+    const std::string BUTTON_NEWSETTINGS("btn_gear");
+    const std::string BUTTON_GEAR("btn_newsettings");
+    const std::string BUTTON_DELETE("btn_del");
+
+
+    const std::string ACTION_DOCREATE("MyEnvironments.DoCreate");
+    const std::string ACTION_DOEDIT("MyEnvironments.DoEdit");
+    const std::string ACTION_DOAPPLY("MyEnvironments.DoApply");
+    const std::string ACTION_COPYPASTE("MyEnvironments.CopyPaste");
+    const std::string ENABLE_ACTION("MyEnvironments.EnableAction");
+    const std::string ENABLE_CANAPPLY("MyEnvironments.CanApply");
+    const std::string ENABLE_ENVIRONMENT("MyEnvironments.EnvironmentEnabled");
+
+    const std::string PARAMETER_REGION("region");
+    const std::string PARAMETER_PARCEL("parcel");
+    const std::string PARAMETER_LOCAL("local");
+
+    const std::string PARAMETER_EDIT("edit");
+    const std::string PARAMETER_COPY("copy");
+    const std::string PARAMETER_PASTE("paste");
+    const std::string PARAMETER_COPYUUID("copy_uuid");
+}
+
+//=========================================================================
+LLFloaterMyEnvironment::LLFloaterMyEnvironment(const LLSD& key) :
+    LLFloater(key),
+    mInventoryList(nullptr),
+    mShowFolders(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS),
+    mTypeFilter((0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE)) | (0x01 << static_cast<U64>(LLSettingsType::ST_SKY)) | (0x01 << static_cast<U64>(LLSettingsType::ST_WATER))),
+    mSelectedAsset()
+{
+    mCommitCallbackRegistrar.add(ACTION_DOCREATE, [this](LLUICtrl *, const LLSD &userdata) { onDoCreate(userdata); });
+    mCommitCallbackRegistrar.add(ACTION_DOEDIT, [this](LLUICtrl *, const LLSD &userdata) { mInventoryList->openSelected(); });
+    mCommitCallbackRegistrar.add(ACTION_DOAPPLY, [this](LLUICtrl *, const LLSD &userdata) { onDoApply(userdata.asString()); });
+    mCommitCallbackRegistrar.add(ACTION_COPYPASTE, [this](LLUICtrl *, const LLSD &userdata) { mInventoryList->doToSelected(userdata.asString()); });
+
+    mEnableCallbackRegistrar.add(ENABLE_ACTION, [this](LLUICtrl *, const LLSD &userdata) { return canAction(userdata.asString()); });
+    mEnableCallbackRegistrar.add(ENABLE_CANAPPLY, [this](LLUICtrl *, const LLSD &userdata) { return canApply(userdata.asString()); });
+    mEnableCallbackRegistrar.add(ENABLE_ENVIRONMENT, [](LLUICtrl *, const LLSD &) { return LLEnvironment::instance().isInventoryEnabled(); });
+
+}
+
+LLFloaterMyEnvironment::~LLFloaterMyEnvironment()
+{
+}
+
+
+BOOL LLFloaterMyEnvironment::postBuild()
+{
+    mInventoryList = getChild<LLInventoryPanel>(PANEL_SETTINGS);
+
+    if (mInventoryList)
+    {
+        U32 filter_types = 0x0;
+        filter_types |= 0x1 << LLInventoryType::IT_SETTINGS;
+
+        mInventoryList->setFilterTypes(filter_types);
+
+        mInventoryList->setSelectCallback([this](const std::deque<LLFolderViewItem*>&, BOOL) { onSelectionChange(); });
+        mInventoryList->setShowFolderState(mShowFolders);
+        mInventoryList->setFilterSettingsTypes(mTypeFilter);
+    }
+
+    childSetCommitCallback(CHECK_DAYS, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+    childSetCommitCallback(CHECK_SKIES, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+    childSetCommitCallback(CHECK_WATER, [this](LLUICtrl*, void*) { onFilterCheckChange(); }, nullptr);
+    childSetCommitCallback(CHECK_SHOWFOLDERS, [this](LLUICtrl*, void*) { onShowFoldersChange(); }, nullptr);
+
+    mFilterEdit = getChild<LLFilterEditor>(FLT_SEARCH);
+    mFilterEdit->setCommitCallback([this](LLUICtrl*, const LLSD& param){ onFilterEdit(param.asString()); });
+
+    childSetCommitCallback(BUTTON_DELETE, [this](LLUICtrl *, void*) { onDeleteSelected(); }, nullptr);
+    mSavedFolderState.setApply(FALSE);
+    return TRUE;
+}
+
+void LLFloaterMyEnvironment::refresh()
+{
+    getChild<LLCheckBoxCtrl>(CHECK_SHOWFOLDERS)->setValue(LLSD::Boolean(mShowFolders == LLInventoryFilter::SHOW_ALL_FOLDERS));
+
+    getChild<LLCheckBoxCtrl>(CHECK_DAYS)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE))));
+    getChild<LLCheckBoxCtrl>(CHECK_SKIES)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_SKY))));
+    getChild<LLCheckBoxCtrl>(CHECK_WATER)->setValue(LLSD::Boolean(mTypeFilter & (0x01 << static_cast<U64>(LLSettingsType::ST_WATER))));
+
+    refreshButtonStates();
+
+}
+
+void LLFloaterMyEnvironment::onOpen(const LLSD& key)
+{
+    LLFloater::onOpen(key);
+
+    if (key.has("asset_id") && mInventoryList)
+    {
+        mSelectedAsset = key["asset_id"].asUUID();
+
+        if (!mSelectedAsset.isNull())
+        {
+            LLUUID obj_id = findItemByAssetId(mSelectedAsset, false, false);
+            if (!obj_id.isNull())
+                mInventoryList->setSelection(obj_id, false);
+        }
+    }
+    else
+    {
+        mSelectedAsset.setNull();
+    }
+
+    refresh();
+}
+
+//-------------------------------------------------------------------------
+void LLFloaterMyEnvironment::onShowFoldersChange()
+{
+    bool show_check(getChild<LLCheckBoxCtrl>(CHECK_SHOWFOLDERS)->getValue().asBoolean());
+
+    mShowFolders = (show_check) ? LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS;
+
+    if (mInventoryList)
+        mInventoryList->setShowFolderState(mShowFolders);
+}
+
+void LLFloaterMyEnvironment::onFilterCheckChange()
+{
+    mTypeFilter = 0x0;
+
+    if (getChild<LLCheckBoxCtrl>(CHECK_DAYS)->getValue().asBoolean())
+        mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_DAYCYCLE);
+    if (getChild<LLCheckBoxCtrl>(CHECK_SKIES)->getValue().asBoolean())
+        mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_SKY);
+    if (getChild<LLCheckBoxCtrl>(CHECK_WATER)->getValue().asBoolean())
+        mTypeFilter |= 0x01 << static_cast<U64>(LLSettingsType::ST_WATER);
+
+    if (mInventoryList)
+        mInventoryList->setFilterSettingsTypes(mTypeFilter);
+}
+
+void LLFloaterMyEnvironment::onSelectionChange()
+{
+    refreshButtonStates();
+}
+
+void LLFloaterMyEnvironment::onFilterEdit(const std::string& search_string)
+{
+    std::string upper_case_search_string = search_string;
+    LLStringUtil::toUpper(upper_case_search_string);
+
+    if (upper_case_search_string.empty())
+    {
+        if (mInventoryList->getFilterSubString().empty())
+        {
+            // current filter and new filter empty, do nothing
+            return;
+        }
+
+        mSavedFolderState.setApply(TRUE);
+        mInventoryList->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+        // add folder with current item to list of previously opened folders
+        LLOpenFoldersWithSelection opener;
+        mInventoryList->getRootFolder()->applyFunctorRecursively(opener);
+        mInventoryList->getRootFolder()->scrollToShowSelection();
+
+    }
+    else if (mInventoryList->getFilterSubString().empty())
+    {
+        // first letter in search term, save existing folder open state
+        mSavedFolderState.setApply(FALSE);
+        mInventoryList->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+    }
+
+    mInventoryList->setFilterSubString(search_string);
+}
+
+void LLFloaterMyEnvironment::onDeleteSelected()
+{
+    uuid_vec_t selected;
+
+    getSelectedIds(selected);
+    if (selected.empty())
+        return;
+
+    const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+    for (const LLUUID& itemid: selected)
+    {
+        LLInventoryItem* inv_item = gInventory.getItem(itemid);
+
+        if (inv_item && inv_item->getInventoryType() == LLInventoryType::IT_SETTINGS)
+        {
+            LLInventoryModel::update_list_t update;
+            LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
+            update.push_back(old_folder);
+            LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
+            update.push_back(new_folder);
+            gInventory.accountForUpdate(update);
+
+            LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+            new_item->setParent(trash_id);
+            new_item->updateParentOnServer(FALSE);
+            gInventory.updateItem(new_item);
+        }
+    }
+    gInventory.notifyObservers();
+}
+
+
+void LLFloaterMyEnvironment::onDoCreate(const LLSD &data)
+{
+    menu_create_inventory_item(mInventoryList, NULL, data);
+}
+
+void LLFloaterMyEnvironment::onDoApply(const std::string &context)
+{
+    uuid_vec_t selected;
+    getSelectedIds(selected);
+
+    if (selected.size() != 1) // Exactly one item selected.
+        return;
+
+    LLUUID item_id(selected.front());
+
+    LLInventoryItem* itemp = gInventory.getItem(item_id);
+
+    if (itemp && itemp->getInventoryType() == LLInventoryType::IT_SETTINGS)
+    {
+        LLUUID asset_id = itemp->getAssetUUID();
+        std::string name = itemp->getName();
+
+        U32 flags(0);
+        
+        if (!itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOMOD;
+        if (!itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOTRANS;
+
+        if (context == PARAMETER_REGION)
+        {
+            LLEnvironment::instance().updateRegion(asset_id, name, LLEnvironment::NO_TRACK, -1, -1, flags);
+            LLEnvironment::instance().setSharedEnvironment();
+        }
+        else if (context == PARAMETER_PARCEL)
+        {
+            LLParcel *parcel(LLViewerParcelMgr::instance().getAgentOrSelectedParcel());
+            if (!parcel)
+            {
+                LL_WARNS("ENVIRONMENT") << "Unable to determine parcel." << LL_ENDL;
+                return;
+            }
+            LLEnvironment::instance().updateParcel(parcel->getLocalID(), asset_id, name, LLEnvironment::NO_TRACK, -1, -1, flags);
+            LLEnvironment::instance().setSharedEnvironment();
+        }
+        else if (context == PARAMETER_LOCAL)
+        {
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+        }
+    }
+}
+
+bool LLFloaterMyEnvironment::canAction(const std::string &context)
+{
+    uuid_vec_t selected;
+    getSelectedIds(selected);
+
+    if (selected.empty())
+        return false;
+
+    if (context == PARAMETER_EDIT)
+    { 
+        return (selected.size() == 1) && isSettingSelected(selected.front());
+    }
+    else if (context == PARAMETER_COPY)
+    {
+        for (std::vector<LLUUID>::iterator it = selected.begin(); it != selected.end(); it++)
+        {
+            if(!isSettingSelected(*it))
+            {
+                return false;
+            }
+        }
+        return true;
+    }
+    else if (context == PARAMETER_PASTE)
+    {
+        if (!LLClipboard::instance().hasContents())
+            return false;
+
+        std::vector<LLUUID> ids;
+        LLClipboard::instance().pasteFromClipboard(ids);
+        for (std::vector<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
+        {
+            if (!isSettingSelected(*it))
+            {
+                return false;
+            }
+        }
+        return (selected.size() == 1);
+    }
+    else if (context == PARAMETER_COPYUUID)
+    {
+        return (selected.size() == 1) && isSettingSelected(selected.front());
+    }
+
+    return false;
+}
+
+bool LLFloaterMyEnvironment::canApply(const std::string &context)
+{
+    uuid_vec_t selected;
+    getSelectedIds(selected);
+
+    if (selected.size() != 1) // Exactly one item selected.
+        return false;
+
+    if (context == PARAMETER_REGION)
+    { 
+        return LLEnvironment::instance().canAgentUpdateRegionEnvironment();
+    }
+    else if (context == PARAMETER_PARCEL)
+    { 
+        return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
+    }
+    else
+    {
+        return (context == PARAMETER_LOCAL);
+    }
+}
+
+//-------------------------------------------------------------------------
+void LLFloaterMyEnvironment::refreshButtonStates()
+{
+    bool settings_ok = LLEnvironment::instance().isInventoryEnabled();
+
+    uuid_vec_t selected;
+    getSelectedIds(selected);
+
+    getChild<LLUICtrl>(BUTTON_GEAR)->setEnabled(settings_ok);
+    getChild<LLUICtrl>(BUTTON_NEWSETTINGS)->setEnabled(true);
+    getChild<LLUICtrl>(BUTTON_DELETE)->setEnabled(settings_ok && !selected.empty());
+}
+
+//-------------------------------------------------------------------------
+LLUUID LLFloaterMyEnvironment::findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library)
+{
+    /*TODO: Rider: Move this to gInventory? */
+
+    LLViewerInventoryCategory::cat_array_t cats;
+    LLViewerInventoryItem::item_array_t items;
+    LLAssetIDMatches asset_id_matches(asset_id);
+
+    gInventory.collectDescendentsIf(LLUUID::null,
+        cats,
+        items,
+        LLInventoryModel::INCLUDE_TRASH,
+        asset_id_matches);
+
+    if (!items.empty())
+    {
+        // search for copyable version first
+        for (auto & item : items)
+        {
+            const LLPermissions& item_permissions = item->getPermissions();
+            if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+            {
+                if(!ignore_library || !gInventory.isObjectDescendentOf(item->getUUID(),gInventory.getLibraryRootFolderID()))
+                {
+                    return item->getUUID();
+                }
+            }
+        }
+        // otherwise just return first instance, unless copyable requested
+        if (copyable_only)
+        {
+            return LLUUID::null;
+        }
+        else
+        {
+            if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID()))
+            {
+                return items[0]->getUUID();
+            }
+        }
+    }
+
+    return LLUUID::null;
+}
+
+bool LLFloaterMyEnvironment::isSettingSelected(LLUUID item_id)
+{
+    LLInventoryItem* itemp = gInventory.getItem(item_id);
+
+    if (itemp && itemp->getInventoryType() == LLInventoryType::IT_SETTINGS)
+    {
+        return true;
+    }
+    return false;
+}
+
+void LLFloaterMyEnvironment::getSelectedIds(uuid_vec_t& ids) const
+{
+    LLInventoryPanel::selected_items_t items = mInventoryList->getSelectedItems();
+
+    for (auto itemview : items)
+    {
+        LLFolderViewModelItemInventory* itemp = static_cast<LLFolderViewModelItemInventory*>(itemview->getViewModelItem());
+        ids.push_back(itemp->getUUID());
+    }
+}
diff --git a/indra/newview/llfloatermyenvironment.h b/indra/newview/llfloatermyenvironment.h
new file mode 100644
index 0000000000000000000000000000000000000000..fea0981590c9e5f5d045416442dbfa88a8df6bcf
--- /dev/null
+++ b/indra/newview/llfloatermyenvironment.h
@@ -0,0 +1,78 @@
+/** 
+ * @file llfloatermyenvironment.h
+ * @brief LLFloaterMyEnvironment class header file
+ *
+ * $LicenseInfo:firstyear=2002&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$
+ */
+
+#ifndef LL_LLFLOATERMYENVIRONMENT_H
+#define LL_LLFLOATERMYENVIRONMENT_H
+#include <vector> 
+
+#include "llfloater.h"
+#include "llinventoryobserver.h"
+#include "llinventoryfilter.h"
+#include "llfiltereditor.h"
+
+class LLInventoryPanel;
+
+class LLFloaterMyEnvironment
+:	public LLFloater, LLInventoryFetchDescendentsObserver
+{
+    LOG_CLASS(LLFloaterMyEnvironment);
+public:
+                                    LLFloaterMyEnvironment(const LLSD& key);
+    virtual                         ~LLFloaterMyEnvironment();
+
+    virtual BOOL                    postBuild() override;
+    virtual void                    refresh() override;
+
+    virtual void                    onOpen(const LLSD& key) override;
+
+private:
+    LLInventoryPanel *              mInventoryList;
+    LLFilterEditor *                mFilterEdit;
+    U64                             mTypeFilter;
+    LLInventoryFilter::EFolderShow  mShowFolders;
+    LLUUID                          mSelectedAsset;
+    LLSaveFolderState               mSavedFolderState;
+
+    void                            onShowFoldersChange();
+    void                            onFilterCheckChange();
+    void                            onFilterEdit(const std::string& search_string);
+    void                            onSelectionChange();
+    void                            onDeleteSelected();
+    void                            onDoCreate(const LLSD &data);
+    void                            onDoApply(const std::string &context);
+    bool                            canAction(const std::string &context);
+    bool                            canApply(const std::string &context);
+
+    void                            getSelectedIds(uuid_vec_t& ids) const;
+    void                            refreshButtonStates();
+
+    bool                            isSettingSelected(LLUUID item_id);
+
+    static LLUUID                   findItemByAssetId(LLUUID asset_id, bool copyable_only, bool ignore_library);
+};
+
+
+#endif
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index 87a741bb7bc96fb32b90a71f9f71269a4a38fdab..1e9549a04ee299796c80430239a714852009c30a 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -64,7 +64,7 @@ const S32 PREVIEW_HPAD = PREVIEW_RESIZE_HANDLE_SIZE;
 //-----------------------------------------------------------------------------
 LLFloaterNameDesc::LLFloaterNameDesc(const LLSD& filename )
 	: LLFloater(filename),
-	  mIsAudio(FALSE)
+	  mIsAudio(FALSE)	  
 {
 	mFilenameAndPath = filename.asString();
 	mFilename = gDirUtilp->getBaseFileName(mFilenameAndPath, false);
@@ -188,14 +188,14 @@ void LLFloaterNameDesc::onBtnOK( )
 {
 	getChildView("ok_btn")->setEnabled(FALSE); // don't allow inadvertent extra uploads
 	
-	LLAssetStorage::LLStoreAssetCallback callback = NULL;
+	LLAssetStorage::LLStoreAssetCallback callback;
 	S32 expected_upload_cost = getExpectedUploadCost();
     if (can_afford_transaction(expected_upload_cost))
     {
         void *nruserdata = NULL;
         std::string display_name = LLStringUtil::null;
 
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
             mFilenameAndPath,
             getChild<LLUICtrl>("name_form")->getValue().asString(),
             getChild<LLUICtrl>("description_form")->getValue().asString(), 0,
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 2281ea1496b4093646758f914a42aa791e53c702..3968f43485437166733b737c00ecbf3e9af7e3a9 100644
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -121,7 +121,8 @@ const std::string LLFloaterPermsDefault::sCategoryNames[CAT_LAST] =
 	"Scripts",
 	"Notecards",
 	"Gestures",
-	"Wearables"
+	"Wearables",
+	"Settings"
 };
 
 BOOL LLFloaterPermsDefault::postBuild()
diff --git a/indra/newview/llfloaterperms.h b/indra/newview/llfloaterperms.h
index e866b6de7de11314c6ec44d15854d685227645a5..02359a256ec72b4454cd78562e610fbaaa94d85c 100644
--- a/indra/newview/llfloaterperms.h
+++ b/indra/newview/llfloaterperms.h
@@ -74,6 +74,7 @@ enum Categories
 	CAT_NOTECARDS,
 	CAT_GESTURES,
 	CAT_WEARABLES,
+	CAT_SETTINGS,
 	CAT_LAST
 };
 
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 6ff1fb8b9073b94bcd210be4bfd64bc223c81ed4..951d11bbe5461fdeaded6139eedb7566fc37515d 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -407,7 +407,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
 	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",		boost::bind(&LLFloaterPreference::setHardwareDefaults, this));
 	mCommitCallbackRegistrar.add("Pref.AvatarImpostorsEnable",	boost::bind(&LLFloaterPreference::onAvatarImpostorsEnable, this));
 	mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity",	boost::bind(&LLFloaterPreference::updateMaxComplexity, this));
-	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",		boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));
+    mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate",     boost::bind(&LLFloaterPreference::onRenderOptionEnable, this));
 	mCommitCallbackRegistrar.add("Pref.WindowedMod",			boost::bind(&LLFloaterPreference::onCommitWindowedMode, this));
 	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",		boost::bind(&LLFloaterPreference::refreshUI,this));
 	mCommitCallbackRegistrar.add("Pref.QualityPerformance",		boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));
@@ -870,12 +870,23 @@ void LLFloaterPreference::onOpen(const LLSD& key)
 	}
 }
 
-void LLFloaterPreference::onVertexShaderEnable()
+void LLFloaterPreference::onRenderOptionEnable()
 {
 	refreshEnabledGraphics();
 }
 
-void LLFloaterPreferenceGraphicsAdvanced::onVertexShaderEnable()
+void LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable()
+{
+	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+	if (instance)
+	{
+		instance->refresh();
+	}
+
+	refreshEnabledGraphics();
+}
+
+void LLFloaterPreferenceGraphicsAdvanced::onAdvancedAtmosphericsEnable()
 {
 	LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
 	if (instance)
@@ -1298,20 +1309,19 @@ void LLFloaterPreference::refreshEnabledState()
 	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
 
 	// if vertex shaders off, disable all shader related products
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") ||
-		!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
+	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
 	{
 		ctrl_wind_light->setEnabled(FALSE);
 		ctrl_wind_light->setValue(FALSE);
 	}
 	else
 	{
-		ctrl_wind_light->setEnabled(gSavedSettings.getBOOL("VertexShaderEnable"));
+		ctrl_wind_light->setEnabled(TRUE);
 	}
 
 	//Deferred/SSAO/Shadows
 	BOOL bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump") && gSavedSettings.getBOOL("RenderObjectBump");
-	BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders") && gSavedSettings.getBOOL("VertexShaderEnable");
+	BOOL shaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
 	BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
 						bumpshiny &&
 						shaders && 
@@ -1333,9 +1343,7 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
 	LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
 
 	// Reflections
-	BOOL reflections = gSavedSettings.getBOOL("VertexShaderEnable") 
-		&& gGLManager.mHasCubeMap
-		&& LLCubeMap::sUseCubeMaps;
+    BOOL reflections = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps;
 	ctrl_reflections->setEnabled(reflections);
 	reflections_text->setEnabled(reflections);
 	
@@ -1359,59 +1367,41 @@ void LLFloaterPreferenceGraphicsAdvanced::refreshEnabledState()
 
 	ctrl_avatar_vp->setEnabled(avatar_vp_enabled);
 	
-	if (gSavedSettings.getBOOL("VertexShaderEnable") == FALSE || 
-		gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
-	{
-		ctrl_avatar_cloth->setEnabled(FALSE);
-	} 
-	else
-	{
-		ctrl_avatar_cloth->setEnabled(TRUE);
-	}
-	
-	// Vertex Shaders
-	// Global Shader Enable
-	LLCheckBoxCtrl* ctrl_shader_enable   = getChild<LLCheckBoxCtrl>("BasicShaders");
-	LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail");   // can be linked with control var
-	LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
+    if (gSavedSettings.getBOOL("RenderAvatarVP") == FALSE)
+    {
+        ctrl_avatar_cloth->setEnabled(FALSE);
+    } 
+    else
+    {
+        ctrl_avatar_cloth->setEnabled(TRUE);
+    }
 
-	ctrl_shader_enable->setEnabled(LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"));
-	
-	BOOL shaders = ctrl_shader_enable->get();
-	if (shaders)
-	{
-		terrain_detail->setEnabled(FALSE);
-		terrain_text->setEnabled(FALSE);
-	}
-	else
-	{
-		terrain_detail->setEnabled(TRUE);
-		terrain_text->setEnabled(TRUE);
-	}
-	
-	// WindLight
-	LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
-	LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
-	LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
+    // Vertex Shaders, Global Shader Enable
+    // SL-12594 Basic shaders are always enabled. DJH TODO clean up now-orphaned state handling code
+    LLSliderCtrl* terrain_detail = getChild<LLSliderCtrl>("TerrainDetail");   // can be linked with control var
+    LLTextBox* terrain_text = getChild<LLTextBox>("TerrainDetailText");
 
-	// *HACK just checks to see if we can use shaders... 
-	// maybe some cards that use shaders, but don't support windlight
-	ctrl_wind_light->setEnabled(ctrl_shader_enable->getEnabled() && shaders);
+    terrain_detail->setEnabled(FALSE);
+    terrain_text->setEnabled(FALSE);
 
-	sky->setEnabled(ctrl_wind_light->get() && shaders);
-	sky_text->setEnabled(ctrl_wind_light->get() && shaders);
+    // WindLight
+    LLCheckBoxCtrl* ctrl_wind_light = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
+    LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
+    LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
+    ctrl_wind_light->setEnabled(TRUE);
+    sky->setEnabled(TRUE);
+    sky_text->setEnabled(TRUE);
 
-	//Deferred/SSAO/Shadows
-	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
-	
-	BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
-						((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
-						shaders && 
-						gGLManager.mHasFramebufferObject &&
-						gSavedSettings.getBOOL("RenderAvatarVP") &&
-						(ctrl_wind_light->get()) ? TRUE : FALSE;
+    //Deferred/SSAO/Shadows
+    LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
+    
+    BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
+                        ((bumpshiny_ctrl && bumpshiny_ctrl->get()) ? TRUE : FALSE) &&
+                        gGLManager.mHasFramebufferObject &&
+                        gSavedSettings.getBOOL("RenderAvatarVP") &&
+                        (ctrl_wind_light->get()) ? TRUE : FALSE;
 
-	ctrl_deferred->setEnabled(enabled);
+    ctrl_deferred->setEnabled(enabled);
 
 	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");
 	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");
@@ -1509,7 +1499,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
 	LLTextBox* reflections_text = getChild<LLTextBox>("ReflectionsText");
 	LLCheckBoxCtrl* ctrl_avatar_vp     = getChild<LLCheckBoxCtrl>("AvatarVertexProgram");
 	LLCheckBoxCtrl* ctrl_avatar_cloth  = getChild<LLCheckBoxCtrl>("AvatarCloth");
-	LLCheckBoxCtrl* ctrl_shader_enable = getChild<LLCheckBoxCtrl>("BasicShaders");
 	LLCheckBoxCtrl* ctrl_wind_light    = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");
 	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders");
 	LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");
@@ -1519,42 +1508,6 @@ void LLFloaterPreferenceGraphicsAdvanced::disableUnavailableSettings()
 	LLSliderCtrl* sky = getChild<LLSliderCtrl>("SkyMeshDetail");
 	LLTextBox* sky_text = getChild<LLTextBox>("SkyMeshDetailText");
 
-	// if vertex shaders off, disable all shader related products
-	if (!LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable"))
-	{
-		ctrl_shader_enable->setEnabled(FALSE);
-		ctrl_shader_enable->setValue(FALSE);
-		
-		ctrl_wind_light->setEnabled(FALSE);
-		ctrl_wind_light->setValue(FALSE);
-
-		sky->setEnabled(FALSE);
-		sky_text->setEnabled(FALSE);
-
-		ctrl_reflections->setEnabled(FALSE);
-		ctrl_reflections->setValue(0);
-		reflections_text->setEnabled(FALSE);
-		
-		ctrl_avatar_vp->setEnabled(FALSE);
-		ctrl_avatar_vp->setValue(FALSE);
-		
-		ctrl_avatar_cloth->setEnabled(FALSE);
-		ctrl_avatar_cloth->setValue(FALSE);
-
-		ctrl_shadows->setEnabled(FALSE);
-		ctrl_shadows->setValue(0);
-		shadows_text->setEnabled(FALSE);
-		
-		ctrl_ssao->setEnabled(FALSE);
-		ctrl_ssao->setValue(FALSE);
-
-		ctrl_dof->setEnabled(FALSE);
-		ctrl_dof->setValue(FALSE);
-
-		ctrl_deferred->setEnabled(FALSE);
-		ctrl_deferred->setValue(FALSE);
-	}
-	
 	// disabled windlight
 	if (!LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"))
 	{
@@ -2913,7 +2866,7 @@ void LLPanelPreferenceGraphics::setHardwareDefaults()
 LLFloaterPreferenceGraphicsAdvanced::LLFloaterPreferenceGraphicsAdvanced(const LLSD& key)
 	: LLFloater(key)
 {
-	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",		boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onVertexShaderEnable, this));
+    mCommitCallbackRegistrar.add("Pref.RenderOptionUpdate",            boost::bind(&LLFloaterPreferenceGraphicsAdvanced::onRenderOptionEnable, this));
 	mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxNonImpostors", boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxNonImpostors,this));
 	mCommitCallbackRegistrar.add("Pref.UpdateIndirectMaxComplexity",   boost::bind(&LLFloaterPreferenceGraphicsAdvanced::updateMaxComplexity,this));
 }
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 8113121d0165d8f37fb6db784d87f046dff8c234..526214a617b2af0fa67e434c723aa90af28b8ec9 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -122,8 +122,8 @@ class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver,
 	// callback for defaults
 	void setHardwareDefaults();
 	void setRecommended();
-	// callback for when client turns on shaders
-	void onVertexShaderEnable();
+	// callback for when client modifies a render option
+    void onRenderOptionEnable();
 	// callback for when client turns on impostors
 	void onAvatarImpostorsEnable();
 
@@ -314,8 +314,9 @@ class LLFloaterPreferenceGraphicsAdvanced : public LLFloater
 	static void setIndirectMaxNonImpostors();
 	static void setIndirectMaxArc();
 	void refresh();
-	// callback for when client turns on shaders
-	void onVertexShaderEnable();
+	// callback for when client modifies a render option
+	void onRenderOptionEnable();
+    void onAdvancedAtmosphericsEnable();
 	LOG_CLASS(LLFloaterPreferenceGraphicsAdvanced);
 };
 
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index ec934a4732360c9687099e153e3f2fffde2953b0..8bcc5bbe7a59fecbba171c1b9359793cabe60aaa 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -53,8 +53,6 @@
 #include "llcheckboxctrl.h"
 #include "llclipboard.h"
 #include "llcombobox.h"
-#include "lldaycyclemanager.h"
-#include "llenvmanager.h"
 #include "llestateinfomodel.h"
 #include "llfilepicker.h"
 #include "llfloatergodtools.h"	// for send_sim_wide_deletes()
@@ -88,7 +86,6 @@
 #include "llviewertexteditor.h"
 #include "llviewerwindow.h"
 #include "llvlcomposition.h"
-#include "llwaterparammanager.h"
 #include "lltrans.h"
 #include "llagentui.h"
 #include "llmeshrepository.h"
@@ -100,6 +97,7 @@
 #include "llpanelexperiences.h"
 #include "llcorehttputil.h"
 #include "llavatarnamecache.h"
+#include "llenvironment.h"
 
 const S32 TERRAIN_TEXTURE_COUNT = 4;
 const S32 CORNER_COUNT = 4;
@@ -182,6 +180,40 @@ void unpack_request_params(
 }
 */
 
+class LLPanelRegionEnvironment : public LLPanelEnvironmentInfo
+{
+public:
+                        LLPanelRegionEnvironment();
+    virtual             ~LLPanelRegionEnvironment();
+
+    virtual void        refresh() override;
+
+    virtual bool        isRegion() const override { return true; }
+    virtual LLParcel *  getParcel() override { return nullptr; }
+    virtual bool        canEdit() override { return LLEnvironment::instance().canAgentUpdateRegionEnvironment(); }
+    virtual bool        isLargeEnough() override { return true; }   // regions are always large enough.
+
+    bool                refreshFromRegion(LLViewerRegion* region);
+
+    virtual BOOL        postBuild() override;
+    virtual void        onOpen(const LLSD& key) override {};
+
+    virtual S32         getParcelId() override { return INVALID_PARCEL_ID; }
+
+protected:
+    static const U32    DIRTY_FLAG_OVERRIDE;
+
+    virtual void        refreshFromSource() override;
+
+    bool                confirmUpdateEstateEnvironment(const LLSD& notification, const LLSD& response);
+
+    void                onChkAllowOverride(bool value);
+
+private:
+    bool                mAllowOverrideRestore;
+    connection_t        mCommitConnect;
+};
+
 
 
 bool estate_dispatch_initialized = false;
@@ -196,7 +228,9 @@ LLUUID LLFloaterRegionInfo::sRequestInvoice;
 
 
 LLFloaterRegionInfo::LLFloaterRegionInfo(const LLSD& seed)
-	: LLFloater(seed)
+	: LLFloater(seed),
+    mEnvironmentPanel(NULL),
+    mRegionChangedCallback()
 {}
 
 BOOL LLFloaterRegionInfo::postBuild()
@@ -232,10 +266,10 @@ BOOL LLFloaterRegionInfo::postBuild()
 	panel->buildFromFile("panel_region_terrain.xml");
 	mTab->addTabPanel(panel);
 
-	panel = new LLPanelEnvironmentInfo;
-	mInfoPanels.push_back(panel);
-	panel->buildFromFile("panel_region_environment.xml");
-	mTab->addTabPanel(panel);
+    mEnvironmentPanel = new LLPanelRegionEnvironment;
+    mEnvironmentPanel->buildFromFile("panel_region_environment.xml");
+//  mEnvironmentPanel->configureForRegion();
+    mTab->addTabPanel(mEnvironmentPanel);
 
 	panel = new LLPanelRegionDebugInfo;
 	mInfoPanels.push_back(panel);
@@ -260,13 +294,18 @@ BOOL LLFloaterRegionInfo::postBuild()
 		&processEstateOwnerRequest);
 
 	// Request region info when agent region changes.
-	gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::requestRegionInfo, this));
+	mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLFloaterRegionInfo::onRegionChanged, this));
 
 	return TRUE;
 }
 
 LLFloaterRegionInfo::~LLFloaterRegionInfo()
-{}
+{
+    if (mRegionChangedCallback.connected())
+    {
+        mRegionChangedCallback.disconnect();
+    }
+}
 
 void LLFloaterRegionInfo::onOpen(const LLSD& key)
 {
@@ -293,16 +332,26 @@ void LLFloaterRegionInfo::onClose(bool app_quitting)
 	}
 }
 
+void LLFloaterRegionInfo::onRegionChanged()
+{
+    if (getVisible()) //otherwise onOpen will do request
+    {
+        requestRegionInfo();
+    }
+}
+
 // static
 void LLFloaterRegionInfo::requestRegionInfo()
 {
-	LLTabContainer* tab = getChild<LLTabContainer>("region_panels");
-
-	tab->getChild<LLPanel>("General")->setCtrlsEnabled(FALSE);
-	tab->getChild<LLPanel>("Debug")->setCtrlsEnabled(FALSE);
-	tab->getChild<LLPanel>("Terrain")->setCtrlsEnabled(FALSE);
-	tab->getChild<LLPanel>("Estate")->setCtrlsEnabled(FALSE);
-	tab->getChild<LLPanel>("Access")->setCtrlsEnabled(FALSE);
+	LLTabContainer* tab = findChild<LLTabContainer>("region_panels");
+	if (tab)
+	{
+		tab->getChild<LLPanel>("General")->setCtrlsEnabled(FALSE);
+		tab->getChild<LLPanel>("Debug")->setCtrlsEnabled(FALSE);
+		tab->getChild<LLPanel>("Terrain")->setCtrlsEnabled(FALSE);
+		tab->getChild<LLPanel>("Estate")->setCtrlsEnabled(FALSE);
+        tab->getChild<LLPanel>("Access")->setCtrlsEnabled(FALSE);
+	}
 
 	// Must allow anyone to request the RegionInfo data
 	// so non-owners/non-gods can see the values. 
@@ -362,13 +411,13 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 	{
 		return;
 	}
-
+#if 0
 	// We need to re-request environment setting here,
 	// otherwise after we apply (send) updated region settings we won't get them back,
 	// so our environment won't be updated.
 	// This is also the way to know about externally changed region environment.
 	LLEnvManagerNew::instance().requestRegionSettings();
-	
+#endif	
 	LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
 
 	LLViewerRegion* region = gAgent.getRegion();
@@ -475,7 +524,12 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
 
 	panel->setCtrlsEnabled(allow_modify);
 
-	floater->refreshFromRegion( gAgent.getRegion() );
+	if (floater->getVisible())
+	{
+		// Note: region info also causes LLRegionInfoModel::instance().update(msg); -> requestRegion(); -> changed message
+		// we need to know env version here and in update(msg) to know when to request and when not to, when to filter 'changed'
+		floater->refreshFromRegion(gAgent.getRegion());
+	} // else will rerequest on onOpen either way
 }
 
 // static
@@ -518,6 +572,16 @@ LLPanelRegionGeneralInfo* LLFloaterRegionInfo::getPanelGeneral()
 	return panel;
 }
 
+// static
+LLPanelRegionEnvironment* LLFloaterRegionInfo::getPanelEnvironment()
+{
+	LLFloaterRegionInfo* floater = LLFloaterReg::getTypedInstance<LLFloaterRegionInfo>("region_info");
+	if (!floater) return NULL;
+	LLTabContainer* tab = floater->getChild<LLTabContainer>("region_panels");
+	LLPanelRegionEnvironment* panel = (LLPanelRegionEnvironment*)tab->getChild<LLPanel>("panel_env_info");
+	return panel;
+}
+
 // static
 LLPanelRegionTerrainInfo* LLFloaterRegionInfo::getPanelRegionTerrain()
 {
@@ -579,6 +643,7 @@ void LLFloaterRegionInfo::refreshFromRegion(LLViewerRegion* region)
 			std::mem_fun(&LLPanelRegionInfo::refreshFromRegion),
 #endif
 			region));
+    mEnvironmentPanel->refreshFromRegion(region);
 }
 
 // public
@@ -589,6 +654,7 @@ void LLFloaterRegionInfo::refresh()
 	{
 		(*iter)->refresh();
 	}
+    mEnvironmentPanel->refresh();
 }
 
 void LLFloaterRegionInfo::enableTopButtons()
@@ -2416,605 +2482,6 @@ bool LLDispatchSetEstateExperience::operator()(
 	return true;
 }
 
-
-
-LLPanelEnvironmentInfo::LLPanelEnvironmentInfo()
-:	mEnableEditing(false),
-	mRegionSettingsRadioGroup(NULL),
- 	mDayCycleSettingsRadioGroup(NULL),
- 	mWaterPresetCombo(NULL),
- 	mSkyPresetCombo(NULL),
- 	mDayCyclePresetCombo(NULL)
-{
-}
-
-// virtual
-BOOL LLPanelEnvironmentInfo::postBuild()
-{
-	mRegionSettingsRadioGroup = getChild<LLRadioGroup>("region_settings_radio_group");
-	mRegionSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchRegionSettings, this));
-
-	mDayCycleSettingsRadioGroup = getChild<LLRadioGroup>("sky_dayc_settings_radio_group");
-	mDayCycleSettingsRadioGroup->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSwitchDayCycle, this));
-
-	mWaterPresetCombo = getChild<LLComboBox>("water_settings_preset_combo");
-	mWaterPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectWaterPreset, this));
-
-	mSkyPresetCombo = getChild<LLComboBox>("sky_settings_preset_combo");
-	mSkyPresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectSkyPreset, this));
-
-	mDayCyclePresetCombo = getChild<LLComboBox>("dayc_settings_preset_combo");
-	mDayCyclePresetCombo->setCommitCallback(boost::bind(&LLPanelEnvironmentInfo::onSelectDayCycle, this));
-
-	childSetCommitCallback("apply_btn", boost::bind(&LLPanelEnvironmentInfo::onBtnApply, this), NULL);
-	getChild<LLButton>("apply_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpUserPrefs, LLEnvManagerNew::getInstance()));
-	childSetCommitCallback("cancel_btn", boost::bind(&LLPanelEnvironmentInfo::onBtnCancel, this), NULL);
-	getChild<LLButton>("cancel_btn")->setRightMouseDownCallback(boost::bind(&LLEnvManagerNew::dumpPresets, LLEnvManagerNew::getInstance()));
-
-	LLEnvManagerNew::instance().setRegionSettingsChangeCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingschange, this));
-	LLEnvManagerNew::instance().setRegionSettingsAppliedCallback(boost::bind(&LLPanelEnvironmentInfo::onRegionSettingsApplied, this, _1));
-
-	LLDayCycleManager::instance().setModifyCallback(boost::bind(&LLPanelEnvironmentInfo::populateDayCyclesList, this));
-	LLWLParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateSkyPresetsList, this));
-	LLWaterParamManager::instance().setPresetListChangeCallback(boost::bind(&LLPanelEnvironmentInfo::populateWaterPresetsList, this));
-
-	return TRUE;
-}
-
-// virtual
-void LLPanelEnvironmentInfo::onOpen(const LLSD& key)
-{
-	LL_DEBUGS("Windlight") << "Panel opened, refreshing" << LL_ENDL;
-	refresh();
-}
-
-// virtual
-void LLPanelEnvironmentInfo::onVisibilityChange(BOOL new_visibility)
-{
-	// If hiding (user switched to another tab or closed the floater),
-	// display user's preferred environment.
-	if (!new_visibility)
-	{
-		LLEnvManagerNew::instance().usePrefs();
-	}
-}
-
-// virtual
-bool LLPanelEnvironmentInfo::refreshFromRegion(LLViewerRegion* region)
-{
-	LL_DEBUGS("Windlight") << "Region updated, enabling/disabling controls" << LL_ENDL;
-	BOOL owner_or_god = gAgent.isGodlike() || (region && (region->getOwner() == gAgent.getID()));
-	BOOL owner_or_god_or_manager = owner_or_god || (region && region->isEstateManager());
-
-	// Don't refresh from region settings to avoid flicker after applying new region settings.
-	mEnableEditing = owner_or_god_or_manager;
-	setControlsEnabled(mEnableEditing);
-
-	return LLPanelRegionInfo::refreshFromRegion(region);
-}
-
-void LLPanelEnvironmentInfo::refresh()
-{
-	if(gDisconnected)
-	{
-		return;
-	}
-
-	populateWaterPresetsList();
-	populateSkyPresetsList();
-	populateDayCyclesList();
-
-	// Init radio groups.
-	const LLEnvironmentSettings& settings = LLEnvManagerNew::instance().getRegionSettings();
-	const LLSD& dc = settings.getWLDayCycle();
-	LLSD::Real first_frame_time = dc.size() > 0 ? dc[0][0].asReal() : 0.0f;
-	const bool use_fixed_sky = dc.size() == 1 && first_frame_time < 0;
-	mRegionSettingsRadioGroup->setSelectedIndex(settings.getSkyMap().size() == 0 ? 0 : 1);
-	mDayCycleSettingsRadioGroup->setSelectedIndex(use_fixed_sky ? 0 : 1);
-
-	setControlsEnabled(mEnableEditing);
-
-	setDirty(false);
-}
-
-void LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)
-{
-	mRegionSettingsRadioGroup->setEnabled(enabled);
-	mDayCycleSettingsRadioGroup->setEnabled(enabled);
-
-	mWaterPresetCombo->setEnabled(enabled);
-	mSkyPresetCombo->setEnabled(enabled);
-	mDayCyclePresetCombo->setEnabled(enabled);
-
-	getChildView("apply_btn")->setEnabled(enabled);
-	getChildView("cancel_btn")->setEnabled(enabled);
-
-	if (enabled)
-	{
-		// Enable/disable some controls based on currently selected radio buttons.
-		bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
-		getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
-
-		bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-		mSkyPresetCombo->setEnabled(is_fixed_sky);
-		mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
-	}
-}
-
-void LLPanelEnvironmentInfo::setApplyProgress(bool started)
-{
-	LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("progress_indicator");
-
-	indicator->setVisible(started);
-
-	if (started)
-	{
-		indicator->start();
-	}
-	else
-	{
-		indicator->stop();
-	}
-}
-
-void LLPanelEnvironmentInfo::setDirty(bool dirty)
-{
-	getChildView("apply_btn")->setEnabled(dirty);
-	getChildView("cancel_btn")->setEnabled(dirty);
-}
-
-void LLPanelEnvironmentInfo::sendRegionSunUpdate()
-{
-	LLRegionInfoModel& region_info = LLRegionInfoModel::instance();
-
-	// If the region is being switched to fixed sky,
-	// change the region's sun hour according to the (fixed) sun position.
-	// This is needed for llGetSunDirection() LSL function to work properly (STORM-1330).
-	const LLSD& sky_map = mNewRegionSettings.getSkyMap();
-	bool region_use_fixed_sky = sky_map.size() == 1;
-	if (region_use_fixed_sky)
-	{
-		LLWLParamSet param_set;
-		llassert(sky_map.isMap());
-		param_set.setAll(sky_map.beginMap()->second);
-		F32 sun_angle = param_set.getSunAngle();
-
-		LL_DEBUGS("WindlightSync") << "Old sun hour: " << region_info.mSunHour << LL_ENDL;
-		// convert value range from 0..2pi to 6..30
-		region_info.mSunHour = fmodf((sun_angle / F_TWO_PI) * 24.f, 24.f) + 6.f;
-	}
-
-	region_info.setUseFixedSun(region_use_fixed_sky);
-	region_info.mUseEstateSun = !region_use_fixed_sky;
-	LL_DEBUGS("WindlightSync") << "Sun hour: " << region_info.mSunHour << LL_ENDL;
-
-	region_info.sendRegionTerrain(LLFloaterRegionInfo::getLastInvoice());
-}
-
-void LLPanelEnvironmentInfo::fixEstateSun()
-{
-	// We don't support fixed sun estates anymore and need to fix
-	// such estates for region day cycle to take effect.
-	// *NOTE: Assuming that current estate settings have arrived already.
-	LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
-	if (estate_info.getUseFixedSun())
-	{
-		LL_INFOS() << "Switching estate to global sun" << LL_ENDL;
-		estate_info.setUseFixedSun(false);
-		estate_info.sendEstateInfo();
-	}
-}
-
-void LLPanelEnvironmentInfo::populateWaterPresetsList()
-{
-	mWaterPresetCombo->removeall();
-
-	// If the region already has water params, add them to the list.
-	const LLEnvironmentSettings& region_settings = LLEnvManagerNew::instance().getRegionSettings();
-	if (region_settings.getWaterParams().size() != 0)
-	{
-		const std::string& region_name = gAgent.getRegion()->getName();
-		mWaterPresetCombo->add(region_name, LLWLParamKey(region_name, LLEnvKey::SCOPE_REGION).toLLSD());
-		mWaterPresetCombo->addSeparator();
-	}
-
-	std::list<std::string> user_presets, system_presets;
-	LLWaterParamManager::instance().getPresetNames(user_presets, system_presets);
-
-	// Add local user presets first.
-	for (std::list<std::string>::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
-
-	if (user_presets.size() > 0)
-	{
-		mWaterPresetCombo->addSeparator();
-	}
-
-	// Add local system presets.
-	for (std::list<std::string>::const_iterator it = system_presets.begin(); it != system_presets.end(); ++it)
-	{
-		mWaterPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toLLSD());
-	}
-
-	// There's no way to select current preset because its name is not stored on server.
-}
-
-void LLPanelEnvironmentInfo::populateSkyPresetsList()
-{
-	mSkyPresetCombo->removeall();
-
-	LLWLParamManager::preset_name_list_t region_presets;
-	LLWLParamManager::preset_name_list_t user_presets, sys_presets;
-	LLWLParamManager::instance().getPresetNames(region_presets, user_presets, sys_presets);
-
-	// Add region presets.
-	std::string region_name = gAgent.getRegion() ? gAgent.getRegion()->getName() : LLTrans::getString("Unknown");
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = region_presets.begin(); it != region_presets.end(); ++it)
-	{
-		std::string preset_name = *it;
-		std::string item_title = preset_name + " (" + region_name + ")";
-		mSkyPresetCombo->add(item_title, LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
-	}
-
-	if (!region_presets.empty())
-	{
-		mSkyPresetCombo->addSeparator();
-	}
-
-	// Add user presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = user_presets.begin(); it != user_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	if (!user_presets.empty())
-	{
-		mSkyPresetCombo->addSeparator();
-	}
-
-	// Add system presets.
-	for (LLWLParamManager::preset_name_list_t::const_iterator it = sys_presets.begin(); it != sys_presets.end(); ++it)
-	{
-		mSkyPresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	// Select current preset.
-	LLSD sky_map = LLEnvManagerNew::instance().getRegionSettings().getSkyMap();
-	if (sky_map.size() == 1) // if the region is set to fixed sky
-	{
-		std::string preset_name = sky_map.beginMap()->first;
-		mSkyPresetCombo->selectByValue(LLWLParamKey(preset_name, LLEnvKey::SCOPE_REGION).toStringVal());
-	}
-}
-
-void LLPanelEnvironmentInfo::populateDayCyclesList()
-{
-	mDayCyclePresetCombo->removeall();
-
-	// If the region already has env. settings, add its day cycle to the list.
-	const LLSD& cur_region_dc = LLEnvManagerNew::instance().getRegionSettings().getWLDayCycle();
-	if (cur_region_dc.size() != 0)
-	{
-		LLViewerRegion* region = gAgent.getRegion();
-		llassert(region != NULL);
-
-		LLWLParamKey key(region->getName(), LLEnvKey::SCOPE_REGION);
-		mDayCyclePresetCombo->add(region->getName(), key.toStringVal());
-		mDayCyclePresetCombo->addSeparator();
-	}
-
-	// Add local user day cycles.
-	LLDayCycleManager::preset_name_list_t user_days, sys_days;
-	LLDayCycleManager::instance().getPresetNames(user_days, sys_days);
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = user_days.begin(); it != user_days.end(); ++it)
-	{
-		mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	if (user_days.size() > 0)
-	{
-		mDayCyclePresetCombo->addSeparator();
-	}
-
-	// Add local system day cycles.
-	for (LLDayCycleManager::preset_name_list_t::const_iterator it = sys_days.begin(); it != sys_days.end(); ++it)
-	{
-		mDayCyclePresetCombo->add(*it, LLWLParamKey(*it, LLEnvKey::SCOPE_LOCAL).toStringVal());
-	}
-
-	// Current day cycle is already selected.
-}
-
-bool LLPanelEnvironmentInfo::getSelectedWaterParams(LLSD& water_params)
-{
-	LLWLParamKey water_key(mWaterPresetCombo->getSelectedValue());
-
-	if (water_key.scope == LLEnvKey::SCOPE_REGION)
-	{
-		water_params = LLEnvManagerNew::instance().getRegionSettings().getWaterParams();
-	}
-	else
-	{
-		LLWaterParamSet param_set;
-		if (!LLWaterParamManager::instance().getParamSet(water_key.name, param_set))
-		{
-			LL_WARNS() << "Error getting water preset: " << water_key.name << LL_ENDL;
-			return false;
-		}
-
-		water_params = param_set.getAll();
-	}
-
-	return true;
-}
-
-bool LLPanelEnvironmentInfo::getSelectedSkyParams(LLSD& sky_params, std::string& preset_name)
-{
-	std::string preset_key(mSkyPresetCombo->getValue().asString());
-	LLWLParamKey preset(preset_key);
-
-	// Get the preset sky params.
-	LLWLParamSet param_set;
-	if (!LLWLParamManager::instance().getParamSet(preset, param_set))
-	{
-		LL_WARNS() << "Error getting sky params: " << preset.toLLSD() << LL_ENDL;
-		return false;
-	}
-
-	sky_params = param_set.getAll();
-	preset_name = preset.name;
-	return true;
-}
-
-bool LLPanelEnvironmentInfo::getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope)
-{
-	std::string preset_key(mDayCyclePresetCombo->getValue().asString());
-	LLWLParamKey dc(preset_key);
-	LL_DEBUGS("Windlight") << "Use day cycle: " << dc.toLLSD() << LL_ENDL;
-
-	if (dc.scope == LLEnvKey::SCOPE_REGION) // current region day cycle
-	{
-		const LLEnvironmentSettings& cur_region_settings = LLEnvManagerNew::instance().getRegionSettings();
-		day_cycle = cur_region_settings.getWLDayCycle();
-		sky_map = cur_region_settings.getSkyMap();
-	}
-	else // a local day cycle
-	{
-		if (!LLDayCycleManager::instance().getPreset(dc.name, day_cycle))
-		{
-			LL_WARNS() << "Error getting day cycle " << dc.name << LL_ENDL;
-			return false;
-		}
-
-		// Create sky map from the day cycle.
-		{
-			LLWLDayCycle tmp_day;
-			tmp_day.loadDayCycle(day_cycle, dc.scope);
-			tmp_day.getSkyMap(sky_map);
-		}
-	}
-
-	scope = dc.scope;
-
-	return true;
-}
-void LLPanelEnvironmentInfo::onSwitchRegionSettings()
-{
-	bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
-	getChild<LLView>("user_environment_settings")->setEnabled(!use_defaults);
-
-	if (use_defaults)
-	{
-		LLEnvManagerNew::instance().useDefaults();
-	}
-	else
-	{
-		onSelectWaterPreset();
-		onSwitchDayCycle();
-	}
-
-	setDirty(true);
-}
-
-void LLPanelEnvironmentInfo::onSwitchDayCycle()
-{
-	bool is_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-
-	mSkyPresetCombo->setEnabled(is_fixed_sky);
-	mDayCyclePresetCombo->setEnabled(!is_fixed_sky);
-
-	if (is_fixed_sky)
-	{
-		onSelectSkyPreset();
-	}
-	else
-	{
-		onSelectDayCycle();
-	}
-
-	setDirty(true);
-}
-
-void LLPanelEnvironmentInfo::onSelectWaterPreset()
-{
-	LLSD water_params;
-
-	if (getSelectedWaterParams(water_params))
-	{
-		LLEnvManagerNew::instance().useWaterParams(water_params);
-	}
-
-	setDirty(true);
-}
-
-void LLPanelEnvironmentInfo::onSelectSkyPreset()
-{
-	LLSD params;
-	std::string dummy;
-
-	if (getSelectedSkyParams(params, dummy))
-	{
-		LLEnvManagerNew::instance().useSkyParams(params);
-	}
-
-	setDirty(true);
-}
-
-void LLPanelEnvironmentInfo::onSelectDayCycle()
-{
-	LLSD day_cycle;
-	LLSD sky_map; // unused
-	short scope;
-
-	if (getSelectedDayCycleParams(day_cycle, sky_map, scope))
-	{
-		LLEnvManagerNew::instance().useDayCycleParams(day_cycle, (LLEnvKey::EScope) scope);
-	}
-
-	setDirty(true);
-}
-
-void LLPanelEnvironmentInfo::onBtnApply()
-{
-	const bool use_defaults = mRegionSettingsRadioGroup->getSelectedIndex() == 0;
-	const bool use_fixed_sky = mDayCycleSettingsRadioGroup->getSelectedIndex() == 0;
-
-	LLSD day_cycle;
-	LLSD sky_map;
-	LLSD water_params;
-
-	if (use_defaults)
-	{
-		// settings will be empty
-		LL_DEBUGS("Windlight") << "Defaults" << LL_ENDL;
-	}
-	else // use custom region settings
-	{
-		if (use_fixed_sky)
-		{
-			LL_DEBUGS("Windlight") << "Use fixed sky" << LL_ENDL;
-
-			// Get selected sky params.
-			LLSD params;
-			std::string preset_name;
-			if (!getSelectedSkyParams(params, preset_name))
-			{
-				return;
-			}
-
-			// Create a day cycle consisting of a single sky preset.
-			LLSD key(LLSD::emptyArray());
-			key.append(-1.0f); // indicate that user preference is actually fixed sky, not a day cycle
-			key.append(preset_name);
-			day_cycle.append(key);
-
-			// Create a sky map consisting of only the sky preset.
-			std::map<LLWLParamKey, LLWLParamSet> refs;
-			LLWLParamSet param_set;
-			param_set.setAll(params);
-			refs[LLWLParamKey(preset_name, LLEnvKey::SCOPE_LOCAL)] = param_set; // scope doesn't matter here
-			sky_map = LLWLParamManager::createSkyMap(refs);
-		}
-		else // use day cycle
-		{
-			LL_DEBUGS("Windlight") << "Use day cycle" << LL_ENDL;
-
-			short scope; // unused
-			if (!getSelectedDayCycleParams(day_cycle, sky_map, scope))
-			{
-				return;
-			}
-
-			// If it's a special single-preset day cycle meaning using a fixed sky,
-			// reset the frame time to a non-negative value,
-			// so that the region setting is displayed in the floater as
-			// a day cycle, not a preset. (STORM-1289)
-			if (day_cycle.size() == 1 && day_cycle[0][0].asReal() < 0.0f)
-			{
-				LL_DEBUGS("Windlight") << "Fixing negative time" << LL_ENDL;
-				day_cycle[0][0] = 0.0f;
-			}
-		}
-
-		// Get water params.
-		if (!getSelectedWaterParams(water_params))
-		{
-			// *TODO: show a notification?
-			return;
-		}
-	}
-
-	// Send settings apply request.
-	LLEnvironmentSettings new_region_settings;
-	new_region_settings.saveParams(day_cycle, sky_map, water_params, 0.0f);
-	if (!LLEnvManagerNew::instance().sendRegionSettings(new_region_settings))
-	{
-		LL_WARNS() << "Error applying region environment settings" << LL_ENDL;
-		return;
-	}
-
-	// When the settings get applied, we'll also send the region sun position update.
-	// To determine the sun angle we're going to need the new settings.
-	mNewRegionSettings = new_region_settings;
-
-	// Start spinning the progress indicator.
-	setApplyProgress(true);
-}
-
-void LLPanelEnvironmentInfo::onBtnCancel()
-{
-	// Reload last saved region settings.
-	refresh();
-
-	// Apply them.
-	LLEnvManagerNew& env_mgr = LLEnvManagerNew::instance();
-	const LLEnvironmentSettings& cur_settings = env_mgr.getRegionSettings();
-	const LLSD& region_day_cycle = cur_settings.getWLDayCycle();
-	const LLSD& region_water = cur_settings.getWaterParams();
-	env_mgr.useWaterParams(region_water);
-	env_mgr.useDayCycleParams(region_day_cycle, LLEnvKey::SCOPE_REGION);
-}
-
-void LLPanelEnvironmentInfo::onRegionSettingschange()
-{
-	LL_DEBUGS("Windlight") << "Region settings changed, refreshing" << LL_ENDL;
-	refresh();
-
-	// Stop applying progress indicator (it may be running if it's us who initiated settings update).
-	setApplyProgress(false);
-}
-
-void LLPanelEnvironmentInfo::onRegionSettingsApplied(bool ok)
-{
-	// If applying new settings has failed, stop the indicator right away.
-	// Otherwise it will be stopped when we receive the updated settings from server.
-	if (ok)
-	{
-		// Set the region sun phase/flags according to the chosen new preferences.
-		//
-		// If we do this earlier we may get jerky transition from fixed sky to a day cycle (STORM-1481).
-		// That is caused by the simulator re-sending the region info, which in turn makes us
-		// re-request and display old region environment settings while the new ones haven't been applied yet.
-		sendRegionSunUpdate();
-
-		// Switch estate to not using fixed sun for the region day cycle to work properly (STORM-1506).
-		fixEstateSun();
-	}
-	else
-	{
-		setApplyProgress(false);
-
-		// We need to re-request environment setting here,
-		// otherwise our subsequent attempts to change region settings will fail with the following error:
-		// "Unable to update environment settings because the last update your viewer saw was not the same
-		// as the last update sent from the simulator.  Try sending your update again, and if this
-		// does not work, try leaving and returning to the region."
-		LLEnvManagerNew::instance().requestRegionSettings();
-	}
-}
-
 BOOL LLPanelRegionExperiences::postBuild()
 {
 	mAllowed = setupList("panel_allowed", ESTATE_EXPERIENCE_ALLOWED_ADD, ESTATE_EXPERIENCE_ALLOWED_REMOVE);
@@ -4239,3 +3706,152 @@ bool LLPanelEstateAccess::refreshFromRegion(LLViewerRegion* region)
 	return LLPanelRegionInfo::refreshFromRegion(region);
 }
 
+//=========================================================================
+const U32 LLPanelRegionEnvironment::DIRTY_FLAG_OVERRIDE(0x01 << 4);
+
+LLPanelRegionEnvironment::LLPanelRegionEnvironment():
+    LLPanelEnvironmentInfo(),
+    mAllowOverrideRestore(false)
+{
+}
+
+LLPanelRegionEnvironment::~LLPanelRegionEnvironment()
+{
+    if (mCommitConnect.connected())
+        mCommitConnect.disconnect();
+}
+
+BOOL LLPanelRegionEnvironment::postBuild()
+{
+    LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
+    if (!LLPanelEnvironmentInfo::postBuild())
+        return FALSE;
+
+    getChild<LLUICtrl>(BTN_USEDEFAULT)->setLabelArg("[USEDEFAULT]", getString(STR_LABEL_USEDEFAULT));
+    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setVisible(TRUE);
+    getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(TRUE);
+
+    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setCommitCallback([this](LLUICtrl *, const LLSD &value){ onChkAllowOverride(value.asBoolean()); });
+
+    mCommitConnect = estate_info.setCommitCallback(boost::bind(&LLPanelRegionEnvironment::refreshFromEstate, this));
+    return TRUE;
+}
+
+
+void LLPanelRegionEnvironment::refresh()
+{
+    commitDayLenOffsetChanges(false); // commit unsaved changes if any
+
+    if (!mCurrentEnvironment)
+    {
+        if (mCurEnvVersion <= INVALID_PARCEL_ENVIRONMENT_VERSION)
+        {
+            refreshFromSource(); // will immediately set mCurEnvVersion
+        } // else - already requesting
+        return;
+    }
+
+    LLPanelEnvironmentInfo::refresh();
+
+    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setValue(mAllowOverride);
+}
+
+bool LLPanelRegionEnvironment::refreshFromRegion(LLViewerRegion* region)
+{
+    if (!region)
+    {
+        setNoSelection(true);
+        setControlsEnabled(false);
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+        getChild<LLUICtrl>("region_text")->setValue(LLSD(""));
+    }
+    else
+    {
+        getChild<LLUICtrl>("region_text")->setValue(LLSD(region->getName()));
+    }
+    setNoSelection(false);
+
+    if (gAgent.getRegion()->getRegionID() != region->getRegionID())
+    {
+        setCrossRegion(true);
+        mCurEnvVersion = INVALID_PARCEL_ENVIRONMENT_VERSION;
+    }
+    setCrossRegion(false);
+
+    refreshFromSource();
+    return true;
+}
+
+void LLPanelRegionEnvironment::refreshFromSource()
+{
+    LL_DEBUGS("ENVIRONMENT") << "Requesting environment for region, known version " << mCurEnvVersion << LL_ENDL;
+    LLHandle<LLPanel> that_h = getHandle();
+
+    if (mCurEnvVersion < UNSET_PARCEL_ENVIRONMENT_VERSION)
+    {
+        // to mark as requesting
+        mCurEnvVersion = UNSET_PARCEL_ENVIRONMENT_VERSION;
+    }
+
+    LLEnvironment::instance().requestRegion(
+        [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+
+    setControlsEnabled(false);
+}
+
+bool LLPanelRegionEnvironment::confirmUpdateEstateEnvironment(const LLSD& notification, const LLSD& response)
+{
+    S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+
+    switch (option)
+    {
+    case 0:
+    {
+        LLEstateInfoModel& estate_info = LLEstateInfoModel::instance();
+
+        // update model
+        estate_info.setAllowEnvironmentOverride(mAllowOverride);
+        // send the update to sim
+        estate_info.sendEstateInfo();
+        clearDirtyFlag(DIRTY_FLAG_OVERRIDE);
+    }
+    break;
+
+    case 1:
+        mAllowOverride = mAllowOverrideRestore;
+        getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setValue(mAllowOverride);
+        break;
+    default:
+        break;
+    }
+    return false;
+}
+
+void LLPanelRegionEnvironment::onChkAllowOverride(bool value)
+{
+    setDirtyFlag(DIRTY_FLAG_OVERRIDE);
+    mAllowOverrideRestore = mAllowOverride;
+    mAllowOverride = value;
+
+
+    std::string notification("EstateParcelEnvironmentOverride");
+    if (LLPanelEstateInfo::isLindenEstate())
+        notification = "ChangeLindenEstate";
+
+	LLSD args;
+	args["ESTATENAME"] = LLEstateInfoModel::instance().getName();
+	LLNotification::Params params(notification);
+	params.substitutions(args);
+    params.functor.function([this](const LLSD& notification, const LLSD& response) { confirmUpdateEstateEnvironment(notification, response); });
+
+    if (!value || LLPanelEstateInfo::isLindenEstate())
+    {   // warn if turning off or a Linden Estate
+        LLNotifications::instance().add(params);
+    }
+    else
+    {
+        LLNotifications::instance().forceResponse(params, 0);
+    }
+
+}
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 5d0f5fc6fc6aa296b74515aa0ab8606e5dae71d1..75d0c3ea5c38e34a88dbf2367b7f99b6d0898f15 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -35,8 +35,8 @@
 #include "llhost.h"
 #include "llpanel.h"
 #include "llextendedstatus.h"
+#include "llpanelenvironment.h"
 
-#include "llenvmanager.h" // for LLEnvironmentSettings
 #include "lleventcoro.h"
 
 class LLAvatarName;
@@ -66,13 +66,9 @@ class LLPanelExperienceListEditor;
 class LLPanelExperiences;
 class LLPanelRegionExperiences;
 class LLPanelEstateAccess;
+class LLPanelRegionEnvironment;
 
 class LLEventTimer;
-class LLEnvironmentSettings;
-class LLWLParamManager;
-class LLWaterParamManager;
-class LLWLParamSet;
-class LLWaterParamSet;
 
 class LLFloaterRegionInfo : public LLFloater
 {
@@ -100,10 +96,12 @@ class LLFloaterRegionInfo : public LLFloater
 	static LLPanelRegionTerrainInfo* getPanelRegionTerrain();
 	static LLPanelRegionExperiences* getPanelExperiences();
 	static LLPanelRegionGeneralInfo* getPanelGeneral();
+	static LLPanelRegionEnvironment* getPanelEnvironment();
 
 	// from LLPanel
 	virtual void refresh();
 	
+	void onRegionChanged();
 	void requestRegionInfo();
 	void requestMeshRezInfo();
 	void enableTopButtons();
@@ -124,12 +122,13 @@ class LLFloaterRegionInfo : public LLFloater
 	LLTabContainer* mTab;
 	typedef std::vector<LLPanelRegionInfo*> info_panels_t;
 	info_panels_t mInfoPanels;
-	//static S32 sRequestSerial;	// serial # of last EstateOwnerRequest
+    LLPanelRegionEnvironment *mEnvironmentPanel;
+    //static S32 sRequestSerial;	// serial # of last EstateOwnerRequest
 	static LLUUID sRequestInvoice;
 
 private:
-	LLAgent::god_level_change_slot_t   mGodLevelChangeSlot;
-
+    LLAgent::god_level_change_slot_t   mGodLevelChangeSlot;
+    boost::signals2::connection mRegionChangedCallback;
 };
 
 
@@ -398,69 +397,10 @@ class LLPanelEstateCovenant : public LLPanelRegionInfo
 
 /////////////////////////////////////////////////////////////////////////////
 
-class LLPanelEnvironmentInfo : public LLPanelRegionInfo
-{
-	LOG_CLASS(LLPanelEnvironmentInfo);
-
-public:
-	LLPanelEnvironmentInfo();
-
-	// LLPanel
-	/*virtual*/ BOOL postBuild();
-	/*virtual*/ void onOpen(const LLSD& key);
-
-	// LLView
-	/*virtual*/ void onVisibilityChange(BOOL new_visibility);
-
-	// LLPanelRegionInfo
-	/*virtual*/ bool refreshFromRegion(LLViewerRegion* region);
-
-private:
-	void refresh();
-	void setControlsEnabled(bool enabled);
-	void setApplyProgress(bool started);
-	void setDirty(bool dirty);
-
-	void sendRegionSunUpdate();
-	void fixEstateSun();
-
-	void populateWaterPresetsList();
-	void populateSkyPresetsList();
-	void populateDayCyclesList();
-
-	bool getSelectedWaterParams(LLSD& water_params);
-	bool getSelectedSkyParams(LLSD& sky_params, std::string& preset_name);
-	bool getSelectedDayCycleParams(LLSD& day_cycle, LLSD& sky_map, short& scope);
-
-	void onSwitchRegionSettings();
-	void onSwitchDayCycle();
-
-	void onSelectWaterPreset();
-	void onSelectSkyPreset();
-	void onSelectDayCycle();
-
-	void onBtnApply();
-	void onBtnCancel();
-
-	void onRegionSettingschange();
-	void onRegionSettingsApplied(bool ok);
-
-	/// New environment settings that are being applied to the region.
-	LLEnvironmentSettings	mNewRegionSettings;
-
-	bool			mEnableEditing;
-
-	LLRadioGroup*	mRegionSettingsRadioGroup;
-	LLRadioGroup*	mDayCycleSettingsRadioGroup;
-
-	LLComboBox*		mWaterPresetCombo;
-	LLComboBox*		mSkyPresetCombo;
-	LLComboBox*		mDayCyclePresetCombo;
-};
 
 class LLPanelRegionExperiences : public LLPanelRegionInfo
 {
-	LOG_CLASS(LLPanelEnvironmentInfo);
+    LOG_CLASS(LLPanelRegionExperiences);
 
 public:
 	LLPanelRegionExperiences(){}
@@ -493,7 +433,7 @@ class LLPanelRegionExperiences : public LLPanelRegionInfo
 
 class LLPanelEstateAccess : public LLPanelRegionInfo
 {
-	LOG_CLASS(LLPanelEnvironmentInfo);
+	LOG_CLASS(LLPanelEstateAccess);
 
 public:
 	LLPanelEstateAccess();
diff --git a/indra/newview/llflyoutcombobtn.cpp b/indra/newview/llflyoutcombobtn.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e4f1d9fcaa64922991d604df133c221a8d48faf2
--- /dev/null
+++ b/indra/newview/llflyoutcombobtn.cpp
@@ -0,0 +1,162 @@
+/** 
+ * @file llflyoutcombobtn.cpp
+ * @brief Represents outfit save/save as combo button.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llflyoutcombobtn.h"
+#include "llviewermenu.h"
+
+LLFlyoutComboBtnCtrl::LLFlyoutComboBtnCtrl(LLPanel* parent,
+                                           const std::string &action_button,
+                                           const std::string &flyout_button,
+                                           const std::string &menu_file,
+                                           bool apply_immediately) :
+    mParent(parent),
+    mActionButton(action_button),
+    mFlyoutButton(flyout_button),
+    mApplyImmediately(apply_immediately)
+{
+    // register action mapping before creating menu
+    LLUICtrl::CommitCallbackRegistry::ScopedRegistrar save_registar;
+    save_registar.add("FlyoutCombo.Button.Action", [this](LLUICtrl *ctrl, const LLSD &data) { onFlyoutItemSelected(ctrl, data); });
+    LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enabled_rgistar;
+    enabled_rgistar.add("FlyoutCombo.Button.Check", [this](LLUICtrl *ctrl, const LLSD &data) { return onFlyoutItemCheck(ctrl, data); });
+
+    mParent->childSetAction(flyout_button, [this](LLUICtrl *ctrl, const LLSD &data) { onFlyoutButton(ctrl, data); });
+    mParent->childSetAction(action_button, [this](LLUICtrl *ctrl, const LLSD &data) { onFlyoutAction(ctrl, data); });
+
+	mFlyoutMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu> (menu_file, gMenuHolder,
+			LLViewerMenuHolderGL::child_registry_t::instance());
+
+    // select the first item in the list.
+    setSelectedItem(0);
+}
+
+void LLFlyoutComboBtnCtrl::setAction(LLUICtrl::commit_callback_t cb)
+{
+    mActionSignal.connect(cb);
+}
+
+
+U32 LLFlyoutComboBtnCtrl::getItemCount()
+{
+    return mFlyoutMenu->getItemCount();
+}
+
+void LLFlyoutComboBtnCtrl::setSelectedItem(S32 itemno)
+{
+    LLMenuItemGL *pitem = mFlyoutMenu->getItem(itemno);
+    setSelectedItem(pitem);
+}
+
+void LLFlyoutComboBtnCtrl::setSelectedItem(const std::string &item)
+{
+    LLMenuItemGL *pitem = mFlyoutMenu->getChild<LLMenuItemGL>(item, false);
+    setSelectedItem(pitem);
+}
+
+void LLFlyoutComboBtnCtrl::setSelectedItem(LLMenuItemGL *pitem)
+{
+    if (!pitem)
+    {
+        LL_WARNS("INTERFACE") << "NULL item selected" << LL_ENDL;
+        return;
+    }
+
+    mSelectedName = pitem->getName();
+    
+    LLButton *action_button = mParent->getChild<LLButton>(mActionButton);
+    action_button->setEnabled(pitem->getEnabled());
+    action_button->setLabel(pitem->getLabel());
+}
+
+void LLFlyoutComboBtnCtrl::setMenuItemEnabled(const std::string& item, bool enabled)
+{
+    mFlyoutMenu->setItemEnabled(item, enabled);
+    if (item == mSelectedName)
+    {
+        mParent->getChildView(mActionButton)->setEnabled(enabled);
+    }
+}
+
+void LLFlyoutComboBtnCtrl::setShownBtnEnabled(bool enabled)
+{
+    mParent->getChildView(mActionButton)->setEnabled(enabled);
+}
+
+void LLFlyoutComboBtnCtrl::setMenuItemVisible(const std::string &item, bool visible)
+{
+    mFlyoutMenu->setItemVisible(item, visible);
+}
+
+
+void LLFlyoutComboBtnCtrl::setMenuItemLabel(const std::string &item, const std::string &label)
+{
+    mFlyoutMenu->setItemLabel(item, label);
+}
+
+void LLFlyoutComboBtnCtrl::onFlyoutButton(LLUICtrl *ctrl, const LLSD &data)
+{
+	S32 x, y;
+    LLUI::getInstance()->getMousePositionLocal(mParent, &x, &y);
+
+	mFlyoutMenu->updateParent(LLMenuGL::sMenuContainer);
+	LLMenuGL::showPopup(mParent, mFlyoutMenu, x, y);
+}
+
+void LLFlyoutComboBtnCtrl::onFlyoutItemSelected(LLUICtrl *ctrl, const LLSD &data)
+{
+    LLMenuItemGL *pmenuitem = static_cast<LLMenuItemGL*>(ctrl);
+    setSelectedItem(pmenuitem);
+
+    if (mApplyImmediately)
+    {
+        onFlyoutAction(pmenuitem, data);
+    }
+}
+
+bool LLFlyoutComboBtnCtrl::onFlyoutItemCheck(LLUICtrl *ctrl, const LLSD &data)
+{
+    if (mApplyImmediately)
+    {
+        return false;
+    }
+    else
+    {
+        LLMenuItemGL *pmenuitem = static_cast<LLMenuItemGL*>(ctrl);
+
+        return pmenuitem->getName() == mSelectedName;
+    }
+}
+
+void LLFlyoutComboBtnCtrl::onFlyoutAction(LLUICtrl *ctrl, const LLSD &data)
+{
+    LLMenuItemGL *pmenuitem = mFlyoutMenu->getChild<LLMenuItemGL>(mSelectedName);
+
+    if (!mActionSignal.empty())
+        mActionSignal(pmenuitem, data);
+}
+
diff --git a/indra/newview/llflyoutcombobtn.h b/indra/newview/llflyoutcombobtn.h
new file mode 100644
index 0000000000000000000000000000000000000000..e41cd0cecbc136308797974f864d0d313dac3554
--- /dev/null
+++ b/indra/newview/llflyoutcombobtn.h
@@ -0,0 +1,76 @@
+/** 
+ * @file llsaveoutfitcombobtn.h
+ * @brief Represents outfit save/save as combo button.
+ *
+ * $LicenseInfo:firstyear=2010&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#ifndef LL_LLFLYOUTCOMBOBTN_H
+#define LL_LLFLYOUTCOMBOBTN_H
+
+/*TODO: Make this button generic */
+
+class LLButton;
+
+#include "lltoggleablemenu.h"
+
+class LLFlyoutComboBtnCtrl
+{
+    LOG_CLASS(LLFlyoutComboBtnCtrl);
+public:
+    LLFlyoutComboBtnCtrl(LLPanel* parent,
+                         const std::string &action_button,
+                         const std::string &flyout_button,
+                         const std::string &menu_file,
+                         bool apply_immediately = true);
+
+	void setMenuItemEnabled(const std::string &item, bool enabled);
+	void setShownBtnEnabled(bool enabled);
+    void setMenuItemVisible(const std::string &item, bool visible);
+    void setMenuItemLabel(const std::string &item, const std::string &label);
+
+    U32 getItemCount();
+    void setSelectedItem(S32 itemno);
+    void setSelectedItem(const std::string &item);
+
+    void setAction(LLUICtrl::commit_callback_t cb);
+
+protected:
+    void onFlyoutButton(LLUICtrl *, const LLSD &);
+    void onFlyoutItemSelected(LLUICtrl *, const LLSD &);
+    bool onFlyoutItemCheck(LLUICtrl *, const LLSD &);
+    void onFlyoutAction(LLUICtrl *, const LLSD &);
+
+    void setSelectedItem(LLMenuItemGL *pitem);
+
+private:
+	LLPanel *                   mParent;
+	LLToggleableMenu *          mFlyoutMenu;
+    std::string                 mActionButton;
+    std::string                 mFlyoutButton;
+
+    std::string                 mSelectedName;
+    bool                        mApplyImmediately;
+
+    LLUICtrl::commit_signal_t   mActionSignal;
+};
+#endif // LL_LLFLYOUTCOMBOBTN_H
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index dea54cbe57811716e207dc3a60c0cf2dae6ed4c0..06a908cccc82a9b9a4eee074da122d6a7549ecbc 100644
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -49,8 +49,9 @@ class LLFolderViewModelItemInventory
 	virtual bool hasChildren() const = 0;
 	virtual LLInventoryType::EType getInventoryType() const = 0;
 	virtual void performAction(LLInventoryModel* model, std::string action)   = 0;
-	virtual LLWearableType::EType getWearableType() const = 0;
-	virtual EInventorySortGroup getSortGroup() const = 0;
+    virtual LLWearableType::EType getWearableType() const = 0;
+    virtual LLSettingsType::type_e getSettingsType() const = 0;
+    virtual EInventorySortGroup getSortGroup() const = 0;
 	virtual LLInventoryObject* getInventoryObject() const = 0;
 	virtual void requestSort();
 	virtual void setPassedFilter(bool filtered, S32 filter_generation, std::string::size_type string_offset = std::string::npos, std::string::size_type string_size = 0);
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 62cbea64012fa117ec59cee59bba4958d480bd1d..0be748ace9df10e4938a526acfdec8ffaaa96a24 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -504,7 +504,7 @@ void LLFriendCardsManager::syncFriendsFolder()
 							  gAgentID.asString(),
 							  LLAssetType::AT_CALLINGCARD,
 							  LLInventoryType::IT_CALLINGCARD,
-							  NOT_WEARABLE,
+                              NO_INV_SUBTYPE,
 							  PERM_MOVE | PERM_TRANSFER,
 							  NULL);
 	}
diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp
index fea01786f35796454d72091d74678fe6b9646242..698c15bd2d5f64c1703ae60c94608943149bfdb3 100644
--- a/indra/newview/llglsandbox.cpp
+++ b/indra/newview/llglsandbox.cpp
@@ -44,6 +44,7 @@
 #include "llviewercamera.h"
 
 #include "llvoavatarself.h"
+#include "llsky.h"
 #include "llagent.h"
 #include "lltoolmgr.h"
 #include "llselectmgr.h"
@@ -771,6 +772,16 @@ void draw_line_cube(F32 width, const LLVector3& center)
 	gGL.vertex3f(center.mV[VX] + width ,center.mV[VY] - width,center.mV[VZ] - width);
 }
 
+void draw_cross_lines(const LLVector3& center, F32 dx, F32 dy, F32 dz)
+{
+	gGL.vertex3f(center.mV[VX] - dx, center.mV[VY], center.mV[VZ]);
+	gGL.vertex3f(center.mV[VX] + dx, center.mV[VY], center.mV[VZ]);
+	gGL.vertex3f(center.mV[VX], center.mV[VY] - dy, center.mV[VZ]);
+	gGL.vertex3f(center.mV[VX], center.mV[VY] + dy, center.mV[VZ]);
+	gGL.vertex3f(center.mV[VX], center.mV[VY], center.mV[VZ] - dz);
+	gGL.vertex3f(center.mV[VX], center.mV[VY], center.mV[VZ] + dz);
+}
+
 void LLViewerObjectList::renderObjectBeacons()
 {
 	if (mDebugBeacons.empty())
@@ -808,13 +819,7 @@ void LLViewerObjectList::renderObjectBeacons()
 		
 			gGL.begin(LLRender::LINES);
 			gGL.color4fv(color.mV);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] - 50.f);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] + 50.f);
-			gGL.vertex3f(thisline.mV[VX] - 2.f,thisline.mV[VY],thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX] + 2.f,thisline.mV[VY],thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] - 2.f,thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] + 2.f,thisline.mV[VZ]);
-
+			draw_cross_lines(thisline, 2.0f, 2.0f, 50.f);
 			draw_line_cube(0.10f, thisline);
 			
 			gGL.end();
@@ -843,13 +848,7 @@ void LLViewerObjectList::renderObjectBeacons()
 			const LLVector3 &thisline = debug_beacon.mPositionAgent;
 			gGL.begin(LLRender::LINES);
 			gGL.color4fv(debug_beacon.mColor.mV);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] - 0.5f);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY],thisline.mV[VZ] + 0.5f);
-			gGL.vertex3f(thisline.mV[VX] - 0.5f,thisline.mV[VY],thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX] + 0.5f,thisline.mV[VY],thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] - 0.5f,thisline.mV[VZ]);
-			gGL.vertex3f(thisline.mV[VX],thisline.mV[VY] + 0.5f,thisline.mV[VZ]);
-
+			draw_cross_lines(thisline, 0.5f, 0.5f, 0.5f);
 			draw_line_cube(0.10f, thisline);
 
 			gGL.end();
@@ -880,6 +879,34 @@ void LLViewerObjectList::renderObjectBeacons()
 	}
 }
 
+void LLSky::renderSunMoonBeacons(const LLVector3& pos_agent, const LLVector3& direction, LLColor4 color)
+{
+	LLGLSUIDefault gls_ui;
+	if (LLGLSLShader::sNoFixedFunction)
+	{
+		gUIProgram.bind();
+	}
+	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+	LLVector3 pos_end;
+	for (S32 i = 0; i < 3; ++i)
+	{
+		pos_end.mV[i] = pos_agent.mV[i] + (50 * direction.mV[i]);
+	}
+	glLineWidth(LLPipeline::DebugBeaconLineWidth);
+	gGL.begin(LLRender::LINES);
+	color.mV[3] *= 0.5f;
+	gGL.color4fv(color.mV);
+	draw_cross_lines(pos_agent, 0.5f, 0.5f, 0.5f);
+	draw_cross_lines(pos_end, 2.f, 2.f, 2.f);
+	gGL.vertex3fv(pos_agent.mV);
+	gGL.vertex3fv(pos_end.mV);
+	gGL.end();
+
+	gGL.flush();
+	glLineWidth(1.f);
+
+}
 
 //-----------------------------------------------------------------------------
 // gpu_benchmark() helper classes
@@ -1005,7 +1032,7 @@ F32 gpu_benchmark()
 
 	//number of samples to take
 	const S32 samples = 64;
-
+		
 	//time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark.
 	const F32 time_limit = 30;
 
@@ -1133,7 +1160,7 @@ F32 gpu_benchmark()
 	F32 gbps = results[results.size()/2];
 
 	LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers, " << (F32)results.size() << " tests took " << time_passed << " seconds" << LL_ENDL;
-
+  
 #if LL_DARWIN
     if (gbps > 512.f)
     { 
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index ef3b234f5066a16327b49b3380e5c19665b0861f..82824861a9f901e52d870149ff1c9af6882bfd5b 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -589,8 +589,6 @@ void LLHUDText::renderAllHUD()
 	
 	LLVertexBuffer::unbind();
 
-    LLVertexBuffer::unbind();
-
 	LLGLState::checkStates();
 	LLGLState::checkTextureChannels();
 	LLGLState::checkClientArrays();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 36784ce3f9ace5c2f2b37b7feddfbc69178abe81..4b051f3e44e3726a1f891674236ceaf672246a26 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -81,6 +81,10 @@
 #include "llwearableitemslist.h"
 #include "lllandmarkactions.h"
 #include "llpanellandmarks.h"
+#include "llviewerparcelmgr.h"
+#include "llparcel.h"
+
+#include "llenvironment.h"
 
 #include <boost/shared_ptr.hpp>
 
@@ -1408,6 +1412,14 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
 			//LL_WARNS() << LLAssetType::lookup(asset_type) << " asset type is unhandled for uuid " << uuid << LL_ENDL;
 			break;
 
+        case LLAssetType::AT_SETTINGS:
+            if (inv_type != LLInventoryType::IT_SETTINGS)
+            {
+                LL_WARNS() << LLAssetType::lookup(asset_type) << " asset has inventory type " << LLInventoryType::lookupHumanReadable(inv_type) << " on uuid " << uuid << LL_ENDL;
+            }
+            new_listener = new LLSettingsBridge(inventory, root, uuid, LLSettingsType::fromInventoryFlags(flags));
+            break;
+
 		default:
 			LL_INFOS_ONCE() << "Unhandled asset type (llassetstorage.h): "
 					<< (S32)asset_type << " (" << LLAssetType::lookup(asset_type) << ")" << LL_ENDL;
@@ -3993,6 +4005,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
 		disabled_items.push_back(std::string("New Folder"));
 		disabled_items.push_back(std::string("New Script"));
 		disabled_items.push_back(std::string("New Note"));
+		disabled_items.push_back(std::string("New Settings"));
 		disabled_items.push_back(std::string("New Gesture"));
 		disabled_items.push_back(std::string("New Clothes"));
 		disabled_items.push_back(std::string("New Body Parts"));
@@ -4086,7 +4099,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items
                     items.push_back(std::string("New Gesture"));
                     items.push_back(std::string("New Clothes"));
                     items.push_back(std::string("New Body Parts"));
+                    items.push_back(std::string("New Settings"));
                     items.push_back(std::string("upload_def"));
+
+                    if (!LLEnvironment::instance().isInventoryEnabled())
+                    {
+                        disabled_items.push_back("New Settings");
+                    }
+
                 }
 			}
 			getClipboardEntries(false, items, disabled_items, flags);
@@ -4352,6 +4372,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
 		case DAD_ANIMATION:
 		case DAD_GESTURE:
 		case DAD_MESH:
+        case DAD_SETTINGS:
 			accept = dragItemIntoFolder(inv_item, drop, tooltip_msg);
 			break;
 		case DAD_LINK:
@@ -5231,6 +5252,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
 			tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory");
 			accept = FALSE;
 		}
+		else if ((inv_item->getActualType() == LLAssetType::AT_SETTINGS) && !LLEnvironment::instance().isInventoryEnabled())
+		{
+			tooltip_msg = LLTrans::getString("NoEnvironmentSettings");
+			accept = FALSE;
+		}
 		else
 		{
 			// Don't allow placing an original item from a notecard to Current Outfit or an outfit folder
@@ -5947,6 +5973,7 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
 			case DAD_ANIMATION:
 			case DAD_GESTURE:
 			case DAD_MESH:
+            case DAD_SETTINGS:
 			{
 				LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
 				const LLPermissions& perm = inv_item->getPermissions();
@@ -6968,6 +6995,153 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
 	hide_context_entries(menu, items, disabled_items);
 }
 
+// +=================================================+
+// |        LLSettingsBridge                             |
+// +=================================================+
+
+LLSettingsBridge::LLSettingsBridge(LLInventoryPanel* inventory,
+        LLFolderView* root,
+        const LLUUID& uuid,
+        LLSettingsType::type_e settings_type):
+    LLItemBridge(inventory, root, uuid),
+    mSettingsType(settings_type)
+{
+}
+
+LLUIImagePtr LLSettingsBridge::getIcon() const
+{
+    return LLInventoryIcon::getIcon(LLAssetType::AT_SETTINGS, LLInventoryType::IT_SETTINGS, mSettingsType, FALSE);
+}
+
+void LLSettingsBridge::performAction(LLInventoryModel* model, std::string action)
+{
+    if ("apply_settings_local" == action)
+    {
+        // Single item only
+        LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
+        if (!item) 
+            return;
+        LLUUID asset_id = item->getAssetUUID();
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, asset_id);
+        LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+    }
+    else if ("apply_settings_parcel" == action)
+    {
+        // Single item only
+        LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());
+        if (!item)
+            return;
+        LLUUID asset_id = item->getAssetUUID();
+        std::string name = item->getName();
+
+        U32 flags(0);
+
+        if (!item->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOMOD;
+        if (!item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+            flags |= LLSettingsBase::FLAG_NOTRANS;
+
+        LLParcel *parcel = LLViewerParcelMgr::instance().getAgentOrSelectedParcel();
+        if (!parcel)
+        {
+            LL_WARNS("INVENTORY") << "could not identify parcel." << LL_ENDL;
+            return;
+        }
+        S32 parcel_id = parcel->getLocalID();
+
+        LL_DEBUGS("ENVIRONMENT") << "Applying asset ID " << asset_id << " to parcel " << parcel_id << LL_ENDL;
+        LLEnvironment::instance().updateParcel(parcel_id, asset_id, name, LLEnvironment::NO_TRACK, -1, -1, flags);
+        LLEnvironment::instance().setSharedEnvironment();
+    }
+    else
+        LLItemBridge::performAction(model, action);
+}
+
+void LLSettingsBridge::openItem()
+{
+    LLViewerInventoryItem* item = getItem();
+    if (item)
+    {
+        if (item->getPermissions().getOwner() != gAgent.getID())
+            LLNotificationsUtil::add("NoEditFromLibrary");
+        else
+            LLInvFVBridgeAction::doAction(item->getType(), mUUID, getInventoryModel());
+    }
+}
+
+void LLSettingsBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+    LL_DEBUGS() << "LLSettingsBridge::buildContextMenu()" << LL_ENDL;
+    menuentry_vec_t items;
+    menuentry_vec_t disabled_items;
+
+    if (isMarketplaceListingsFolder())
+    {
+        menuentry_vec_t items;
+        menuentry_vec_t disabled_items;
+        addMarketplaceContextMenuOptions(flags, items, disabled_items);
+        items.push_back(std::string("Properties"));
+        getClipboardEntries(false, items, disabled_items, flags);
+        hide_context_entries(menu, items, disabled_items);
+    }
+    else if (isItemInTrash())
+    {
+        addTrashContextMenuOptions(items, disabled_items);
+    }
+    else
+    {
+        items.push_back(std::string("Share"));
+        if (!canShare())
+        {
+            disabled_items.push_back(std::string("Share"));
+        }
+
+        addOpenRightClickMenuOption(items);
+        items.push_back(std::string("Properties"));
+
+        getClipboardEntries(true, items, disabled_items, flags);
+
+        items.push_back("Settings Separator");
+        items.push_back("Settings Apply Local");
+
+        items.push_back("Settings Apply Parcel");
+        if (!canUpdateParcel())
+            disabled_items.push_back("Settings Apply Parcel");
+        
+        items.push_back("Settings Apply Region");
+        if (!canUpdateRegion())
+            disabled_items.push_back("Settings Apply Region");
+    }
+    addLinkReplaceMenuOption(items, disabled_items);
+    hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLSettingsBridge::renameItem(const std::string& new_name)
+{
+    /*TODO: change internal settings name? */
+    return LLItemBridge::renameItem(new_name);
+}
+
+BOOL LLSettingsBridge::isItemRenameable() const
+{
+    LLViewerInventoryItem* item = getItem();
+    if (item)
+    {
+        return (item->getPermissions().allowModifyBy(gAgent.getID()));
+    }
+    return FALSE;
+}
+
+bool LLSettingsBridge::canUpdateParcel() const
+{
+    return LLEnvironment::instance().canAgentUpdateParcelEnvironment();
+}
+
+bool LLSettingsBridge::canUpdateRegion() const
+{
+    return LLEnvironment::instance().canAgentUpdateRegionEnvironment();
+}
+
 
 // +=================================================+
 // |        LLLinkBridge                             |
@@ -7327,6 +7501,40 @@ void LLWearableBridgeAction::wearOnAvatar()
 	}
 }
 
+class LLSettingsBridgeAction
+    : public LLInvFVBridgeAction
+{
+    friend class LLInvFVBridgeAction;
+public:
+    virtual void doIt()
+    {
+        LLViewerInventoryItem* item = getItem();
+        if (item)
+        {
+            LLSettingsType::type_e type = item->getSettingsType();
+            switch (type)
+            {
+            case LLSettingsType::ST_SKY:
+                LLFloaterReg::showInstance("env_fixed_environmentent_sky", LLSDMap("inventory_id", item->getUUID()), TAKE_FOCUS_YES);
+                break;
+            case LLSettingsType::ST_WATER:
+                LLFloaterReg::showInstance("env_fixed_environmentent_water", LLSDMap("inventory_id", item->getUUID()), TAKE_FOCUS_YES);
+                break;
+            case LLSettingsType::ST_DAYCYCLE:
+                LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("inventory_id", item->getUUID())("edit_context", "inventory"), TAKE_FOCUS_YES);
+                break;
+            default:
+                break;
+            }
+        }
+        LLInvFVBridgeAction::doIt();
+    }
+    virtual ~LLSettingsBridgeAction(){}
+protected:
+    LLSettingsBridgeAction(const LLUUID& id, LLInventoryModel* model) : LLInvFVBridgeAction(id, model) {}
+};
+
+
 LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
 													   const LLUUID& uuid,
 													   LLInventoryModel* model)
@@ -7365,6 +7573,9 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
 		case LLAssetType::AT_BODYPART:
 			action = new LLWearableBridgeAction(uuid,model);
 			break;
+        case LLAssetType::AT_SETTINGS:
+            action = new LLSettingsBridgeAction(uuid, model);
+            break;
 		default:
 			break;
 	}
@@ -7444,7 +7655,8 @@ bool LLFolderViewGroupedItemBridge::canWearSelected(uuid_vec_t item_ids)
 	for (uuid_vec_t::const_iterator it = item_ids.begin(); it != item_ids.end(); ++it)
 	{
 		LLViewerInventoryItem* item = gInventory.getItem(*it);
-		if (!item || (item->getType() >= LLAssetType::AT_COUNT) || (item->getType() <= LLAssetType::AT_NONE))
+		LLAssetType::EType asset_type = item->getType();
+		if (!item || (asset_type >= LLAssetType::AT_COUNT) || (asset_type <= LLAssetType::AT_NONE))
 		{
 			return false;
 		}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 0823cf8b52cf35d24cfe56048925d3a66c7aad0d..fce7ade661a8e5776d8c95d4899b5fe05dcd4041 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -38,6 +38,7 @@
 #include "lltooldraganddrop.h"
 #include "lllandmarklist.h"
 #include "llfolderviewitem.h"
+#include "llsettingsbase.h"
 
 class LLInventoryFilter;
 class LLInventoryPanel;
@@ -108,6 +109,7 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 	virtual void closeItem() {}
 	virtual void showProperties();
 	virtual BOOL isItemRenameable() const { return TRUE; }
+	virtual BOOL isMultiPreviewAllowed() { return TRUE; }
 	//virtual BOOL renameItem(const std::string& new_name) {}
 	virtual BOOL isItemRemovable() const;
 	virtual BOOL isItemMovable() const;
@@ -136,6 +138,7 @@ class LLInvFVBridge : public LLFolderViewModelItemInventory
 							std::string& tooltip_msg) { return FALSE; }
 	virtual LLInventoryType::EType getInventoryType() const { return mInvType; }
 	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
+    virtual LLSettingsType::type_e getSettingsType() const { return LLSettingsType::ST_NONE; }
         EInventorySortGroup getSortGroup()  const { return SG_ITEM; }
 	virtual LLInventoryObject* getInventoryObject() const;
 
@@ -605,6 +608,31 @@ class LLLinkFolderBridge : public LLItemBridge
 	static std::string sPrefix;
 };
 
+
+class LLSettingsBridge : public LLItemBridge
+{
+public:
+    LLSettingsBridge(LLInventoryPanel* inventory,
+        LLFolderView* root,
+        const LLUUID& uuid,
+        LLSettingsType::type_e settings_type);
+    virtual LLUIImagePtr getIcon() const;
+    virtual void	performAction(LLInventoryModel* model, std::string action);
+    virtual void	openItem();
+    virtual BOOL	isMultiPreviewAllowed() { return FALSE; }
+    virtual void	buildContextMenu(LLMenuGL& menu, U32 flags);
+    virtual BOOL    renameItem(const std::string& new_name);
+    virtual BOOL    isItemRenameable() const;
+    virtual LLSettingsType::type_e getSettingsType() const { return mSettingsType; }
+
+protected:
+    bool            canUpdateRegion() const;
+    bool            canUpdateParcel() const;
+
+    LLSettingsType::type_e mSettingsType;
+
+};
+
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 // Class LLInvFVBridgeAction
 //
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index e8bc915f22975233b0c49195cd179913ac141695..745b953996ddd658de341d6d013665c8f3a03f65 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -53,6 +53,7 @@ LLInventoryFilter::FilterOps::FilterOps(const Params& p)
 :	mFilterObjectTypes(p.object_types),
 	mFilterCategoryTypes(p.category_types),
 	mFilterWearableTypes(p.wearable_types),
+    mFilterSettingsTypes(p.settings_types),
 	mMinDate(p.date_range.min_date),
 	mMaxDate(p.date_range.max_date),
 	mHoursAgo(p.hours_ago),
@@ -357,7 +358,21 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent
 	if (filterTypes & FILTERTYPE_WEARABLE)
 	{
 		LLWearableType::EType type = listener->getWearableType();
-		if ((0x1LL << type & mFilterOps.mFilterWearableTypes) == 0)
+        if ((object_type == LLInventoryType::IT_WEARABLE) &&
+                (((0x1LL << type) & mFilterOps.mFilterWearableTypes) == 0))
+		{
+			return FALSE;
+		}
+	}
+
+    ////////////////////////////////////////////////////////////////////////////////
+    // FILTERTYPE_SETTINGS
+    // Pass if this item is a setting of the appropriate type
+    if (filterTypes & FILTERTYPE_SETTINGS)
+    {
+        LLSettingsType::type_e type = listener->getSettingsType();
+        if ((object_type == LLInventoryType::IT_SETTINGS) &&
+            (((0x1LL << type) & mFilterOps.mFilterSettingsTypes) == 0))
 		{
 			return FALSE;
 		}
@@ -658,6 +673,12 @@ void LLInventoryFilter::setFilterWearableTypes(U64 types)
 	mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE;
 }
 
+void LLInventoryFilter::setFilterSettingsTypes(U64 types)
+{
+    updateFilterTypes(types, mFilterOps.mFilterSettingsTypes);
+    mFilterOps.mFilterTypes |= FILTERTYPE_SETTINGS;
+}
+
 void LLInventoryFilter::setFilterEmptySystemFolders()
 {
 	mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS;
@@ -1311,6 +1332,11 @@ U64 LLInventoryFilter::getFilterWearableTypes() const
 	return mFilterOps.mFilterWearableTypes;
 }
 
+U64 LLInventoryFilter::getFilterSettingsTypes() const
+{
+    return mFilterOps.mFilterSettingsTypes;
+}
+
 bool LLInventoryFilter::hasFilterString() const
 {
 	return mFilterSubString.size() > 0;
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 3f24211f4127f20e334df9be192be060e853822b..be02ee3623b2e922eec8dbf12a83c2f3d2dd8231 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -59,6 +59,7 @@ class LLInventoryFilter : public LLFolderViewFilter
         FILTERTYPE_MARKETPLACE_LISTING_FOLDER = 0x1 << 9,	// pass iff folder is a listing folder
         FILTERTYPE_NO_MARKETPLACE_ITEMS = 0x1 << 10,         // pass iff folder is not under the marketplace
         FILTERTYPE_WORN = 0x1 << 11,     // pass if item is worn
+        FILTERTYPE_SETTINGS = 0x1 << 12,    // pass if the item is a settings object
 	};
 
 	enum EFilterDateDirection
@@ -80,7 +81,7 @@ class LLInventoryFilter : public LLFolderViewFilter
 		SO_DATE = 0x1,						// Sort inventory by date
 		SO_FOLDERS_BY_NAME = 0x1 << 1,		// Force folder sort by name
 		SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2,// Force system folders to be on top
-		SO_FOLDERS_BY_WEIGHT = 0x1 << 3,    // Force folder sort by weight, usually, amount of some elements in their descendents
+		SO_FOLDERS_BY_WEIGHT = 0x1 << 3,    // Force folder sort by weight, usually, amount of some elements in their descendants
 	};
 
 	enum ESearchType
@@ -118,6 +119,7 @@ class LLInventoryFilter : public LLFolderViewFilter
 			Optional<U32>				types;
 			Optional<U64>				object_types,
 										wearable_types,
+                                        settings_types,
 										category_types;
 			Optional<EFilterLink>		links;
 			Optional<LLUUID>			uuid;
@@ -132,6 +134,7 @@ class LLInventoryFilter : public LLFolderViewFilter
 			:	types("filter_types", FILTERTYPE_OBJECT),
 				object_types("object_types", 0xffffFFFFffffFFFFULL),
 				wearable_types("wearable_types", 0xffffFFFFffffFFFFULL),
+                settings_types("settings_types", 0xffffFFFFffffFFFFULL),
 				category_types("category_types", 0xffffFFFFffffFFFFULL),
 				links("links", FILTERLINK_INCLUDE_LINKS),
 				uuid("uuid"),
@@ -149,6 +152,7 @@ class LLInventoryFilter : public LLFolderViewFilter
 		U32 			mFilterTypes;
 		U64				mFilterObjectTypes,   // For _OBJECT
 						mFilterWearableTypes,
+                        mFilterSettingsTypes, // for _SETTINGS
 						mFilterLinks,
 						mFilterCategoryTypes; // For _CATEGORY
 		LLUUID      	mFilterUUID; 		  // for UUID
@@ -158,8 +162,8 @@ class LLInventoryFilter : public LLFolderViewFilter
 		U32				mHoursAgo;
 		U32				mDateSearchDirection;
 
-		EFolderShow			mShowFolderState;
-		PermissionMask		mPermissions;
+		EFolderShow		mShowFolderState;
+		PermissionMask	mPermissions;
 		EFilterCreatorType	mFilterCreatorType;
 	};
 							
@@ -189,11 +193,14 @@ class LLInventoryFilter : public LLFolderViewFilter
 	U64 				getFilterObjectTypes() const;
 	U64					getFilterCategoryTypes() const;
 	U64					getFilterWearableTypes() const;
+    U64                 getFilterSettingsTypes() const;
+
 	bool 				isFilterObjectTypesWith(LLInventoryType::EType t) const;
 	void 				setFilterObjectTypes(U64 types);
 	void 				setFilterCategoryTypes(U64 types);
 	void 				setFilterUUID(const LLUUID &object_id);
 	void				setFilterWearableTypes(U64 types);
+    void                setFilterSettingsTypes(U64 types);
 	void				setFilterEmptySystemFolders();
 	void				setFilterWorn();
 	void				setFilterMarketplaceActiveFolders();
@@ -245,8 +252,8 @@ class LLInventoryFilter : public LLFolderViewFilter
 	// +-------------------------------------------------------------------+
 	// + Presentation
 	// +-------------------------------------------------------------------+
-	void 					setShowFolderState( EFolderShow state);
-	EFolderShow 			getShowFolderState() const;
+	void 				setShowFolderState( EFolderShow state);
+	EFolderShow 		getShowFolderState() const;
 	EFilterCreatorType		getFilterCreatorType() const;
 
 	void 				setEmptyLookupMessage(const std::string& message);
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 030c9670191193682ac1c458f118b578d2eee27a..646d92b9e15e34241f3abfbb574248bc89644444 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2395,10 +2395,29 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
 
 	if (("task_open" == action  || "open" == action) && selected_items.size() > 1)
 	{
-		multi_previewp = new LLMultiPreview();
-		gFloaterView->addChild(multi_previewp);
+		bool open_multi_preview = true;
 
-		LLFloater::setFloaterHost(multi_previewp);
+		for (std::set<LLFolderViewItem*>::iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+		{
+			LLFolderViewItem* folder_item = *set_iter;
+			if (folder_item)
+			{
+				LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(folder_item->getViewModelItem());
+				if (!bridge || !bridge->isMultiPreviewAllowed())
+				{
+					open_multi_preview = false;
+					break;
+				}
+			}
+		}
+
+		if (open_multi_preview)
+		{
+			multi_previewp = new LLMultiPreview();
+			gFloaterView->addChild(multi_previewp);
+
+			LLFloater::setFloaterHost(multi_previewp);
+		}
 
 	}
 	else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1)
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index ee6e3dd384ada3e6813be5374ac59f25fd965cdf..81c001b8bd65e909a80ee2d1cbdd06259bca7925 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -34,6 +34,7 @@
 #include "llui.h"
 #include "lluiimage.h"
 #include "llwearabletype.h"
+#include "llinventorysettings.h"
 
 struct IconEntry : public LLDictionaryEntry
 {
@@ -93,6 +94,11 @@ LLIconDictionary::LLIconDictionary()
 	addEntry(LLInventoryType::ICONNAME_LINKFOLDER, 				new IconEntry("Inv_LinkFolder"));
 	addEntry(LLInventoryType::ICONNAME_MESH,	 				new IconEntry("Inv_Mesh"));
 
+    addEntry(LLInventoryType::ICONNAME_SETTINGS_SKY,            new IconEntry("Inv_SettingsSky"));
+    addEntry(LLInventoryType::ICONNAME_SETTINGS_WATER,          new IconEntry("Inv_SettingsWater"));
+    addEntry(LLInventoryType::ICONNAME_SETTINGS_DAY,            new IconEntry("Inv_SettingsDay"));
+    addEntry(LLInventoryType::ICONNAME_SETTINGS,                new IconEntry("Inv_Settings"));
+
 	addEntry(LLInventoryType::ICONNAME_INVALID, 				new IconEntry("Inv_Invalid"));
 	addEntry(LLInventoryType::ICONNAME_UNKNOWN, 				new IconEntry("Inv_Unknown"));
 
@@ -168,6 +174,9 @@ const std::string& LLInventoryIcon::getIconName(LLAssetType::EType asset_type,
 			break;
 		case LLAssetType::AT_MESH:
 			idx = LLInventoryType::ICONNAME_MESH;
+		case LLAssetType::AT_SETTINGS:
+			idx = assignSettingsIcon(misc_flag);
+			break;
 		case LLAssetType::AT_UNKNOWN:
 			idx = LLInventoryType::ICONNAME_UNKNOWN;
 		default:
@@ -189,3 +198,9 @@ LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag)
 	const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag);
 	return LLWearableType::getIconName(wearable_type);
 }
+
+LLInventoryType::EIconName LLInventoryIcon::assignSettingsIcon(U32 misc_flag)
+{
+	LLSettingsType::type_e settings_type = LLSettingsType::fromInventoryFlags(misc_flag);
+	return LLSettingsType::getIconName(settings_type);
+}
diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h
index bc09e32087dd0de9fcd9574d04ba3c2939f8f438..b8637c4e33299ae97f52435a8e350cee87862e7d 100644
--- a/indra/newview/llinventoryicon.h
+++ b/indra/newview/llinventoryicon.h
@@ -48,6 +48,7 @@ class LLInventoryIcon
 
 protected:
 	static LLInventoryType::EIconName assignWearableIcon(U32 misc_flag);
+    static LLInventoryType::EIconName assignSettingsIcon(U32 misc_flag);
 };
 #endif // LL_LLINVENTORYICON_H
 
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index c49d61df31128c59ea8bd066868057e6fdc5a560..17e80dca891d3b792126955b858460231225a5ef 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -888,6 +888,11 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item, U32 mask)
 		return mask;
 	}
 
+	if (item->getType() == LLAssetType::AT_MESH)
+	{
+		return mask;
+	}
+
 	LLPointer<LLViewerInventoryItem> old_item = getItem(item->getUUID());
 	LLPointer<LLViewerInventoryItem> new_item;
 	if(old_item)
@@ -1810,7 +1815,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
 			return;
 		}
 
-		if (LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
+		if (LLAssetType::lookup(item->getType()) == LLAssetType::BADLOOKUP)
 		{
 			if (item->getType() >= LLAssetType::AT_COUNT)
 			{
@@ -2599,6 +2604,7 @@ void LLInventoryModel::createCommonSystemCategories()
 	gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
 	gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true);
 	gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true);
+    gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true);
 }
 
 struct LLUUIDAndName
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 6f461673ee0580752b9b88a9b35aae8e057e97f0..c6075b40664d5922eb3960ea630c09ddd5377430 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -46,12 +46,19 @@
 #include "llnotificationsutil.h"
 #include "llpreview.h"
 #include "llsidepanelinventory.h"
+#include "llstartup.h"
 #include "lltrans.h"
+#include "llviewerassettype.h"
 #include "llviewerattachmenu.h"
 #include "llviewerfoldertype.h"
 #include "llvoavatarself.h"
 
+class LLInventoryRecentItemsPanel;
+class LLAssetFilteredInventoryPanel;
+
 static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
+static LLDefaultChildRegistry::Register<LLInventoryRecentItemsPanel> t_recent_inventory_panel("recent_inventory_panel");
+static LLDefaultChildRegistry::Register<LLAssetFilteredInventoryPanel> t_asset_filtered_inv_panel("asset_filtered_inv_panel");
 
 const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
 const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
@@ -142,8 +149,11 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
 	mInventory(p.inventory),
 	mAcceptsDragAndDrop(p.accepts_drag_and_drop),
 	mAllowMultiSelect(p.allow_multi_select),
+	mAllowDrag(p.allow_drag),
 	mShowItemLinkOverlays(p.show_item_link_overlays),
 	mShowEmptyMessage(p.show_empty_message),
+	mSuppressFolderMenu(p.suppress_folder_menu),
+	mSuppressOpenItemAction(false),
 	mViewsInitialized(false),
 	mInvFVBridgeBuilder(NULL),
 	mInventoryViewModel(p.name),
@@ -190,7 +200,9 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
 	p.grouped_item_model = mGroupedItemBridge;
     p.use_label_suffix = mParams.use_label_suffix;
     p.allow_multiselect = mAllowMultiSelect;
+    p.allow_drag = mAllowDrag;
     p.show_empty_message = mShowEmptyMessage;
+    p.suppress_folder_menu = mSuppressFolderMenu;
     p.show_item_link_overlays = mShowItemLinkOverlays;
     p.root = NULL;
     p.allow_drop = mParams.allow_drop_on_root;
@@ -269,9 +281,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
 	mCompletionObserver = new LLInvPanelComplObserver(boost::bind(&LLInventoryPanel::onItemsCompletion, this));
 	mInventory->addObserver(mCompletionObserver);
 
-	// Build view of inventory if we need default full hierarchy and inventory ready,
-	// otherwise wait for idle callback.
-	if (mInventory->isInventoryUsable() && !mViewsInitialized)
+	// Build view of inventory if we need default full hierarchy and inventory ready, otherwise do in onIdle.
+	// Initializing views takes a while so always do it onIdle if viewer already loaded.
+	if (mInventory->isInventoryUsable() && !mViewsInitialized && LLStartUp::getStartupState() <= STATE_WEARABLES_WAIT)
 	{
 		initializeViews();
 	}
@@ -376,6 +388,11 @@ void LLInventoryPanel::setFilterWearableTypes(U64 types)
 	getFilter().setFilterWearableTypes(types);
 }
 
+void LLInventoryPanel::setFilterSettingsTypes(U64 filter)
+{
+    getFilter().setFilterSettingsTypes(filter);
+}
+
 void LLInventoryPanel::setFilterSubString(const std::string& string)
 {
 	getFilter().setFilterSubString(string);
@@ -386,7 +403,6 @@ const std::string LLInventoryPanel::getFilterSubString()
 	return getFilter().getFilterSubString();
 }
 
-
 void LLInventoryPanel::setSortOrder(U32 order)
 {
     LLInventorySort sorter(order);
@@ -444,198 +460,204 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
 	return getFilter().getShowFolderState();
 }
 
-// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)
-static LLTrace::BlockTimerStatHandle FTM_REFRESH("Inventory Refresh");
-void LLInventoryPanel::modelChanged(U32 mask)
+void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item)
 {
-	LL_RECORD_BLOCK_TIME(FTM_REFRESH);
+	LLFolderViewItem* view_item = getItemByID(item_id);
+	LLFolderViewModelItemInventory* viewmodel_item = 
+		static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);
 
-	if (!mViewsInitialized) return;
-	
-	const LLInventoryModel* model = getModel();
-	if (!model) return;
+	// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item
+	// to folder is the fast way to get a folder without searching through folders tree.
+	LLFolderViewFolder* view_folder = NULL;
 
-	const LLInventoryModel::changed_items_t& changed_items = model->getChangedIDs();
-	if (changed_items.empty()) return;
+	// Check requires as this item might have already been deleted
+	// as a child of its deleted parent.
+	if (model_item && view_item)
+	{
+		view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);
+	}
 
-	for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
-		 items_iter != changed_items.end();
-		 ++items_iter)
+	//////////////////////////////
+	// LABEL Operation
+	// Empty out the display name for relabel.
+	if (mask & LLInventoryObserver::LABEL)
 	{
-		const LLUUID& item_id = (*items_iter);
-		const LLInventoryObject* model_item = model->getObject(item_id);
-		LLFolderViewItem* view_item = getItemByID(item_id);
-		LLFolderViewModelItemInventory* viewmodel_item = 
-			static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);
+		if (view_item)
+		{
+			// Request refresh on this item (also flags for filtering)
+			LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem();
+			if(bridge)
+			{
+				// Clear the display name first, so it gets properly re-built during refresh()
+				bridge->clearDisplayName();
 
-		// LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item
-		// to folder is the fast way to get a folder without searching through folders tree.
-		LLFolderViewFolder* view_folder = NULL;
+				view_item->refresh();
+			}
+			LLFolderViewFolder* parent = view_item->getParentFolder();
+			if(parent)
+			{
+				parent->getViewModelItem()->dirtyDescendantsFilter();
+			}
+		}
+	}
 
-		// Check requires as this item might have already been deleted
-		// as a child of its deleted parent.
-		if (model_item && view_item)
+	//////////////////////////////
+	// REBUILD Operation
+	// Destroy and regenerate the UI.
+	if (mask & LLInventoryObserver::REBUILD)
+	{
+		if (model_item && view_item && viewmodel_item)
 		{
-			view_folder = dynamic_cast<LLFolderViewFolder*>(view_item);
+			const LLUUID& idp = viewmodel_item->getUUID();
+			view_item->destroyView();
+			removeItemID(idp);
 		}
+		view_item = buildNewViews(item_id);
+		viewmodel_item = 
+			static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);
+		view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
+	}
 
-		//////////////////////////////
-		// LABEL Operation
-		// Empty out the display name for relabel.
-		if (mask & LLInventoryObserver::LABEL)
+	//////////////////////////////
+	// INTERNAL Operation
+	// This could be anything.  For now, just refresh the item.
+	if (mask & LLInventoryObserver::INTERNAL)
+	{
+		if (view_item)
 		{
-			if (view_item)
-			{
-				// Request refresh on this item (also flags for filtering)
-				LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem();
-				if(bridge)
-				{	// Clear the display name first, so it gets properly re-built during refresh()
-					bridge->clearDisplayName();
-
-					view_item->refresh();
-				}
-				LLFolderViewFolder* parent = view_item->getParentFolder();
-				if(parent)
-				{
-					parent->getViewModelItem()->dirtyDescendantsFilter();
-				}
-			}
+			view_item->refresh();
 		}
+	}
 
-		//////////////////////////////
-		// REBUILD Operation
-		// Destroy and regenerate the UI.
-		if (mask & LLInventoryObserver::REBUILD)
+	//////////////////////////////
+	// SORT Operation
+	// Sort the folder.
+	if (mask & LLInventoryObserver::SORT)
+	{
+		if (view_folder)
 		{
-			if (model_item && view_item && viewmodel_item)
-			{
-				const LLUUID& idp = viewmodel_item->getUUID();
-				view_item->destroyView();
-				removeItemID(idp);
-			}
-			view_item = buildNewViews(item_id);
-			viewmodel_item = 
-				static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL);
-			view_folder = dynamic_cast<LLFolderViewFolder *>(view_item);
+			view_folder->getViewModelItem()->requestSort();
 		}
+	}
 
+	// We don't typically care which of these masks the item is actually flagged with, since the masks
+	// may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
+	// Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks
+	// panel).  What's relevant is that the item and UI are probably out of sync and thus need to be
+	// resynchronized.
+	if (mask & (LLInventoryObserver::STRUCTURE |
+				LLInventoryObserver::ADD |
+				LLInventoryObserver::REMOVE))
+	{
 		//////////////////////////////
-		// INTERNAL Operation
-		// This could be anything.  For now, just refresh the item.
-		if (mask & LLInventoryObserver::INTERNAL)
+		// ADD Operation
+		// Item exists in memory but a UI element hasn't been created for it.
+		if (model_item && !view_item)
 		{
-			if (view_item)
+			// Add the UI element for this item.
+			buildNewViews(item_id);
+			// Select any newly created object that has the auto rename at top of folder root set.
+			if(mFolderRoot.get()->getRoot()->needsAutoRename())
 			{
-				view_item->refresh();
+				setSelection(item_id, FALSE);
 			}
+			updateFolderLabel(model_item->getParentUUID());
 		}
 
 		//////////////////////////////
-		// SORT Operation
-		// Sort the folder.
-		if (mask & LLInventoryObserver::SORT)
-		{
-			if (view_folder)
-			{
-				view_folder->getViewModelItem()->requestSort();
-			}
-		}	
-
-		// We don't typically care which of these masks the item is actually flagged with, since the masks
-		// may not be accurate (e.g. in the main inventory panel, I move an item from My Inventory into
-		// Landmarks; this is a STRUCTURE change for that panel but is an ADD change for the Landmarks
-		// panel).  What's relevant is that the item and UI are probably out of sync and thus need to be
-		// resynchronized.
-		if (mask & (LLInventoryObserver::STRUCTURE |
-					LLInventoryObserver::ADD |
-					LLInventoryObserver::REMOVE))
+		// STRUCTURE Operation
+		// This item already exists in both memory and UI.  It was probably reparented.
+		else if (model_item && view_item)
 		{
-			//////////////////////////////
-			// ADD Operation
-			// Item exists in memory but a UI element hasn't been created for it.
-			if (model_item && !view_item)
+			LLFolderViewFolder* old_parent = view_item->getParentFolder();
+			// Don't process the item if it is the root
+			if (old_parent)
 			{
-				// Add the UI element for this item.
-				buildNewViews(item_id);
-				// Select any newly created object that has the auto rename at top of folder root set.
-				if(mFolderRoot.get()->getRoot()->needsAutoRename())
+				LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(old_parent->getViewModelItem());
+				LLFolderViewFolder* new_parent =   (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());
+				// Item has been moved.
+				if (old_parent != new_parent)
 				{
-					setSelection(item_id, FALSE);
-				}
-				updateFolderLabel(model_item->getParentUUID());
-			}
-
-			//////////////////////////////
-			// STRUCTURE Operation
-			// This item already exists in both memory and UI.  It was probably reparented.
-			else if (model_item && view_item)
-			{
-				LLFolderViewFolder* old_parent = view_item->getParentFolder();
-				// Don't process the item if it is the root
-				if (old_parent)
-				{
-					LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(old_parent->getViewModelItem());
-					LLFolderViewFolder* new_parent =   (LLFolderViewFolder*)getItemByID(model_item->getParentUUID());
-					// Item has been moved.
-					if (old_parent != new_parent)
+					if (new_parent != NULL)
 					{
-						if (new_parent != NULL)
+						// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI.
+						view_item->addToFolder(new_parent);
+						addItemID(viewmodel_item->getUUID(), view_item);
+						if (mInventory)
 						{
-							// Item is to be moved and we found its new parent in the panel's directory, so move the item's UI.
-							view_item->addToFolder(new_parent);
-							addItemID(viewmodel_item->getUUID(), view_item);
-							if (mInventory)
+							const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+							if (trash_id != model_item->getParentUUID() && (mask & LLInventoryObserver::INTERNAL) && new_parent->isOpen())
 							{
-								const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH);
-								if (trash_id != model_item->getParentUUID() && (mask & LLInventoryObserver::INTERNAL) && new_parent->isOpen())
-								{
-									setSelection(item_id, FALSE);
-								}
+								setSelection(item_id, FALSE);
 							}
-							updateFolderLabel(model_item->getParentUUID());
 						}
-						else 
-						{
-							// Remove the item ID before destroying the view because the view-model-item gets
-							// destroyed when the view is destroyed
-                            removeItemID(viewmodel_item->getUUID());
+						updateFolderLabel(model_item->getParentUUID());
+					}
+					else 
+					{
+						// Remove the item ID before destroying the view because the view-model-item gets
+						// destroyed when the view is destroyed
+						removeItemID(viewmodel_item->getUUID());
 
-							// Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that 
-							// doesn't include trash).  Just remove the item's UI.
-							view_item->destroyView();
-						}
-						if(viewmodel_folder)
-						{
-							updateFolderLabel(viewmodel_folder->getUUID());
-						}
-						old_parent->getViewModelItem()->dirtyDescendantsFilter();
+						// Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that 
+						// doesn't include trash).  Just remove the item's UI.
+						view_item->destroyView();
 					}
-				}
-			}
-			
-			//////////////////////////////
-			// REMOVE Operation
-			// This item has been removed from memory, but its associated UI element still exists.
-			else if (!model_item && view_item && viewmodel_item)
-			{
-				// Remove the item's UI.
-				LLFolderViewFolder* parent = view_item->getParentFolder();
-				removeItemID(viewmodel_item->getUUID());
-				view_item->destroyView();
-				if(parent)
-				{
-					parent->getViewModelItem()->dirtyDescendantsFilter();
-					LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(parent->getViewModelItem());
 					if(viewmodel_folder)
 					{
 						updateFolderLabel(viewmodel_folder->getUUID());
 					}
+					old_parent->getViewModelItem()->dirtyDescendantsFilter();
+				}
+			}
+		}
+
+		//////////////////////////////
+		// REMOVE Operation
+		// This item has been removed from memory, but its associated UI element still exists.
+		else if (!model_item && view_item && viewmodel_item)
+		{
+			// Remove the item's UI.
+			LLFolderViewFolder* parent = view_item->getParentFolder();
+			removeItemID(viewmodel_item->getUUID());
+			view_item->destroyView();
+			if(parent)
+			{
+				parent->getViewModelItem()->dirtyDescendantsFilter();
+				LLFolderViewModelItemInventory* viewmodel_folder = static_cast<LLFolderViewModelItemInventory*>(parent->getViewModelItem());
+				if(viewmodel_folder)
+				{
+					updateFolderLabel(viewmodel_folder->getUUID());
 				}
 			}
 		}
 	}
 }
 
+// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)
+static LLTrace::BlockTimerStatHandle FTM_REFRESH("Inventory Refresh");
+void LLInventoryPanel::modelChanged(U32 mask)
+{
+	LL_RECORD_BLOCK_TIME(FTM_REFRESH);
+
+	if (!mViewsInitialized) return;
+	
+	const LLInventoryModel* model = getModel();
+	if (!model) return;
+
+	const LLInventoryModel::changed_items_t& changed_items = model->getChangedIDs();
+	if (changed_items.empty()) return;
+
+	for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin();
+		 items_iter != changed_items.end();
+		 ++items_iter)
+	{
+		const LLUUID& item_id = (*items_iter);
+		const LLInventoryObject* model_item = model->getObject(item_id);
+		itemChanged(item_id, mask, model_item);
+	}
+}
+
 LLUUID LLInventoryPanel::getRootFolderID()
 {
     LLUUID root_id;
@@ -830,14 +852,17 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge
 
 LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id)
 {
- 	LLInventoryObject const* objectp = gInventory.getObject(id);
-	
-	if (!objectp)
+    LLInventoryObject const* objectp = gInventory.getObject(id);
+    return buildNewViews(id, objectp);
+}
+
+LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id, LLInventoryObject const* objectp)
+{
+    if (!objectp)
     {
         return NULL;
     }
-
-	LLFolderViewItem* folder_view_item = getItemByID(id);
+    LLFolderViewItem* folder_view_item = getItemByID(id);
 
     const LLUUID &parent_id = objectp->getParentUUID();
 	LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)getItemByID(parent_id);
@@ -1122,6 +1147,11 @@ void LLInventoryPanel::clearSelection()
 	mSelectThisID.setNull();
 }
 
+LLInventoryPanel::selected_items_t LLInventoryPanel::getSelectedItems() const
+{
+    return mFolderRoot.get()->getSelectionList();
+}
+
 void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
 {
 	// Schedule updating the folder view context menu when all selected items become complete (STORM-373).
@@ -1631,21 +1661,18 @@ BOOL LLInventoryPanel::handleKeyHere( KEY key, MASK mask )
 		// Open selected items if enter key hit on the inventory panel
 		if (mask == MASK_NONE)
 		{
-
-// @TODO$: Rider: This code is dead with Outbox, however should something similar be 
-//  done for VMM?
-//  
-// 			//Don't allow attaching or opening items from Merchant Outbox
-// 			LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
-// 			if(folder_item)
-// 			{
-// 				LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
-// 				if(bridge && bridge->is() && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
-// 				{
-// 					return handled;
-// 				}
-// 			}
-
+			if (mSuppressOpenItemAction)
+			{
+				LLFolderViewItem* folder_item = mFolderRoot.get()->getCurSelectedItem();
+				if(folder_item)
+				{
+					LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem();
+					if(bridge && (bridge->getInventoryType() != LLInventoryType::IT_CATEGORY))
+					{
+						return handled;
+					}
+				}
+			}
 			LLInventoryAction::doToSelected(mInventory, mFolderRoot.get(), "open");
 			handled = TRUE;
 		}
@@ -1698,9 +1725,6 @@ bool LLInventoryPanel::isSelectionRemovable()
 /************************************************************************/
 /* Recent Inventory Panel related class                                 */
 /************************************************************************/
-class LLInventoryRecentItemsPanel;
-static LLDefaultChildRegistry::Register<LLInventoryRecentItemsPanel> t_recent_inventory_panel("recent_inventory_panel");
-
 static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER;
 class LLInventoryRecentItemsPanel : public LLInventoryPanel
 {
@@ -1729,6 +1753,111 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
 	mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
 }
 
+/************************************************************************/
+/* Asset Pre-Filtered Inventory Panel related class                     */
+/* Exchanges filter's flexibility for speed of generation and           */
+/* improved performance                                                 */
+/************************************************************************/
+class LLAssetFilteredInventoryPanel : public LLInventoryPanel
+{
+public:
+    struct Params
+        : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+    {
+        Mandatory<std::string>	filter_asset_type;
+
+        Params() : filter_asset_type("filter_asset_type") {}
+    };
+
+    void initFromParams(const Params& p);
+protected:
+    LLAssetFilteredInventoryPanel(const Params& p) : LLInventoryPanel(p) {}
+    friend class LLUICtrlFactory;
+public:
+    ~LLAssetFilteredInventoryPanel() {}
+
+    /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+                                       EDragAndDropType cargo_type,
+                                       void* cargo_data,
+                                       EAcceptance* accept,
+                                       std::string& tooltip_msg) override;
+
+protected:
+    /*virtual*/ LLFolderViewItem*	buildNewViews(const LLUUID& id) override;
+    /*virtual*/ void				itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item) override;
+
+private:
+    LLAssetType::EType mAssetType;
+};
+
+
+void LLAssetFilteredInventoryPanel::initFromParams(const Params& p)
+{
+    mAssetType = LLAssetType::lookup(p.filter_asset_type.getValue());
+    LLInventoryPanel::initFromParams(p);
+    U64 filter_cats = getFilter().getFilterCategoryTypes();
+    filter_cats &= ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS);
+    getFilter().setFilterCategoryTypes(filter_cats);
+    getFilter().setFilterNoMarketplaceFolder();
+}
+
+BOOL LLAssetFilteredInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+    EDragAndDropType cargo_type,
+    void* cargo_data,
+    EAcceptance* accept,
+    std::string& tooltip_msg)
+{
+    BOOL result = FALSE;
+
+    if (mAcceptsDragAndDrop)
+    {
+        EDragAndDropType allow_type = LLViewerAssetType::lookupDragAndDropType(mAssetType);
+        // Don't allow DAD_CATEGORY here since it can contain other items besides required assets
+        // We should see everything we drop!
+        if (allow_type == cargo_type)
+        {
+            result = LLInventoryPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+        }
+    }
+
+    return result;
+}
+
+LLFolderViewItem* LLAssetFilteredInventoryPanel::buildNewViews(const LLUUID& id)
+{
+    LLInventoryObject const* objectp = gInventory.getObject(id);
+
+    if (!objectp)
+    {
+        return NULL;
+    }
+
+    if (objectp->getType() != mAssetType && objectp->getType() != LLAssetType::AT_CATEGORY)
+    {
+        return NULL;
+    }
+
+    return LLInventoryPanel::buildNewViews(id, objectp);
+}
+
+void LLAssetFilteredInventoryPanel::itemChanged(const LLUUID& id, U32 mask, const LLInventoryObject* model_item)
+{
+    if (!model_item && !getItemByID(id))
+    {
+        // remove operation, but item is not in panel already
+        return;
+    }
+
+    if (model_item
+        && model_item->getType() != mAssetType
+        && model_item->getType() != LLAssetType::AT_CATEGORY)
+    {
+        return;
+    }
+
+    LLInventoryPanel::itemChanged(id, mask, model_item);
+}
+
 namespace LLInitParam
 {
 	void TypeValues<LLFolderType::EType>::declareValues()
@@ -1758,6 +1887,7 @@ namespace LLInitParam
 		declare(LLFolderType::lookup(LLFolderType::FT_INBOX)            , LLFolderType::FT_INBOX);
 		declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX)           , LLFolderType::FT_OUTBOX);
 		declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT)       , LLFolderType::FT_BASIC_ROOT);
+        declare(LLFolderType::lookup(LLFolderType::FT_SETTINGS)         , LLFolderType::FT_SETTINGS);
 		declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_LISTINGS)   , LLFolderType::FT_MARKETPLACE_LISTINGS);
 		declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_STOCK), LLFolderType::FT_MARKETPLACE_STOCK);
 		declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_VERSION), LLFolderType::FT_MARKETPLACE_VERSION);
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 12001f5a2be5c16eece14e57fe6659d92137dc03..b55eb2b82869c28d3b427649f9c40fe6940cf32b 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -92,11 +92,13 @@ class LLInventoryPanel : public LLPanel
 		Optional<std::string>				sort_order_setting;
 		Optional<LLInventoryModel*>			inventory;
 		Optional<bool>						allow_multi_select;
+		Optional<bool>						allow_drag;
 		Optional<bool>						show_item_link_overlays;
 		Optional<Filter>					filter;
 		Optional<StartFolder>               start_folder;
 		Optional<bool>						use_label_suffix;
 		Optional<bool>						show_empty_message;
+		Optional<bool>						suppress_folder_menu;
 		Optional<bool>						show_root_folder;
 		Optional<bool>						allow_drop_on_root;
 		Optional<bool>						use_marketplace_folders;
@@ -110,7 +112,9 @@ class LLInventoryPanel : public LLPanel
 		:	sort_order_setting("sort_order_setting"),
 			inventory("", &gInventory),
 			allow_multi_select("allow_multi_select", true),
+			allow_drag("allow_drag", true),
 			show_item_link_overlays("show_item_link_overlays", false),
+			suppress_folder_menu("suppress_folder_menu", false),
 			filter("filter"),
 			start_folder("start_folder"),
 			use_label_suffix("use_label_suffix", true),
@@ -144,6 +148,8 @@ class LLInventoryPanel : public LLPanel
 	virtual ~LLInventoryPanel();
 
 public:
+    typedef std::set<LLFolderViewItem*> selected_items_t;
+
 	LLInventoryModel* getModel() { return mInventory; }
 	LLFolderViewModelInventory& getRootViewModel() { return mInventoryViewModel; }
 
@@ -151,7 +157,7 @@ class LLInventoryPanel : public LLPanel
 	void draw();
 	/*virtual*/ BOOL handleKeyHere( KEY key, MASK mask );
 	BOOL handleHover(S32 x, S32 y, MASK mask);
-	BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+	/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 								   EDragAndDropType cargo_type,
 								   void* cargo_data,
 								   EAcceptance* accept,
@@ -168,6 +174,8 @@ class LLInventoryPanel : public LLPanel
 	void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
 	void setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
 	void clearSelection();
+    selected_items_t getSelectedItems() const;
+
 	bool isSelectionRemovable();
 	LLInventoryFilter& getFilter();
 	const LLInventoryFilter& getFilter() const;
@@ -176,8 +184,9 @@ class LLInventoryPanel : public LLPanel
 	U32 getFilterObjectTypes() const;
 	void setFilterPermMask(PermissionMask filter_perm_mask);
 	U32 getFilterPermMask() const;
-	void setFilterWearableTypes(U64 filter);
-	void setFilterSubString(const std::string& string);
+    void setFilterWearableTypes(U64 filter);
+    void setFilterSettingsTypes(U64 filter);
+    void setFilterSubString(const std::string& string);
 	const std::string getFilterSubString();
 	void setSinceLogoff(BOOL sl);
 	void setHoursAgo(U32 hours);
@@ -236,6 +245,8 @@ class LLInventoryPanel : public LLPanel
 	void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus);
 	void updateSelection();
 
+	void setSuppressOpenItemAction(bool supress_open_item) { mSuppressOpenItemAction = supress_open_item; }
+
 	LLFolderViewModelInventory* getFolderViewModel() { return &mInventoryViewModel; }
 	const LLFolderViewModelInventory* getFolderViewModel() const { return &mInventoryViewModel; }
     
@@ -254,8 +265,11 @@ class LLInventoryPanel : public LLPanel
 	LLInvPanelComplObserver*	mCompletionObserver;
 	bool						mAcceptsDragAndDrop;
 	bool 						mAllowMultiSelect;
+	bool 						mAllowDrag;
 	bool 						mShowItemLinkOverlays; // Shows link graphic over inventory item icons
 	bool						mShowEmptyMessage;
+	bool						mSuppressFolderMenu;
+	bool						mSuppressOpenItemAction;
 
 	LLHandle<LLFolderView>      mFolderRoot;
 	LLScrollContainer*			mScroller;
@@ -311,7 +325,9 @@ class LLInventoryPanel : public LLPanel
 	static LLUIColor			sLibraryColor;
 	static LLUIColor			sLinkColor;
 	
-	LLFolderViewItem*	buildNewViews(const LLUUID& id);
+	virtual LLFolderViewItem*	buildNewViews(const LLUUID& id);
+	LLFolderViewItem*			buildNewViews(const LLUUID& id, LLInventoryObject const* objectp);
+	virtual void				itemChanged(const LLUUID& item_id, U32 mask, const LLInventoryObject* model_item);
 	BOOL				getIsHiddenFolderType(LLFolderType::EType folder_type) const;
 	
     virtual LLFolderView * createFolderRoot(LLUUID root_id );
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index eb4e4f4100ded3b65f6597d619da66a0fb0b758d..79fafade2d2489cefd87d6ebb70644315824ac11 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -49,7 +49,7 @@ static LLDefaultChildRegistry::Register<LLJoystickAgentSlide> r1("joystick_slide
 static LLDefaultChildRegistry::Register<LLJoystickAgentTurn> r2("joystick_turn");
 static LLDefaultChildRegistry::Register<LLJoystickCameraRotate> r3("joystick_rotate");
 static LLDefaultChildRegistry::Register<LLJoystickCameraTrack> r5("joystick_track");
-
+static LLDefaultChildRegistry::Register<LLJoystickQuaternion> r6("joystick_quat");
 
 
 const F32 NUDGE_TIME = 0.25f;		// in seconds
@@ -707,3 +707,238 @@ void LLJoystickCameraTrack::resetJoystickCamera()
 {
 	gAgentCamera.resetCameraPan();
 }
+
+//-------------------------------------------------------------------------------
+// LLJoystickQuaternion
+//-------------------------------------------------------------------------------
+
+LLJoystickQuaternion::Params::Params()
+{
+}
+
+LLJoystickQuaternion::LLJoystickQuaternion(const LLJoystickQuaternion::Params &p):
+    LLJoystick(p),
+    mInLeft(false),
+    mInTop(false),
+    mInRight(false),
+    mInBottom(false),
+    mVectorZero(0.0f, 0.0f, 1.0f),
+    mRotation(),
+    mUpDnAxis(1.0f, 0.0f, 0.0f),
+    mLfRtAxis(0.0f, 0.0f, 1.0f),
+    mXAxisIndex(2), // left & right across the control
+    mYAxisIndex(0), // up & down across the  control
+    mZAxisIndex(1)  // tested for above and below
+{
+    for (int i = 0; i < 3; ++i)
+    {
+        mLfRtAxis.mV[i] = (mXAxisIndex == i) ? 1.0 : 0.0;
+        mUpDnAxis.mV[i] = (mYAxisIndex == i) ? 1.0 : 0.0;
+    }
+}
+
+void LLJoystickQuaternion::setToggleState(BOOL left, BOOL top, BOOL right, BOOL bottom)
+{
+    mInLeft = left;
+    mInTop = top;
+    mInRight = right;
+    mInBottom = bottom;
+}
+
+BOOL LLJoystickQuaternion::handleMouseDown(S32 x, S32 y, MASK mask)
+{
+    updateSlop();
+
+    // Set initial offset based on initial click location
+    S32 horiz_center = getRect().getWidth() / 2;
+    S32 vert_center = getRect().getHeight() / 2;
+
+    S32 dx = x - horiz_center;
+    S32 dy = y - vert_center;
+
+    if (dy > dx && dy > -dx)
+    {
+        // top
+        mInitialOffset.mX = 0;
+        mInitialOffset.mY = (mVertSlopNear + mVertSlopFar) / 2;
+        mInitialQuadrant = JQ_UP;
+    }
+    else if (dy > dx && dy <= -dx)
+    {
+        // left
+        mInitialOffset.mX = -(mHorizSlopNear + mHorizSlopFar) / 2;
+        mInitialOffset.mY = 0;
+        mInitialQuadrant = JQ_LEFT;
+    }
+    else if (dy <= dx && dy <= -dx)
+    {
+        // bottom
+        mInitialOffset.mX = 0;
+        mInitialOffset.mY = -(mVertSlopNear + mVertSlopFar) / 2;
+        mInitialQuadrant = JQ_DOWN;
+    }
+    else
+    {
+        // right
+        mInitialOffset.mX = (mHorizSlopNear + mHorizSlopFar) / 2;
+        mInitialOffset.mY = 0;
+        mInitialQuadrant = JQ_RIGHT;
+    }
+
+    return LLJoystick::handleMouseDown(x, y, mask);
+}
+
+BOOL LLJoystickQuaternion::handleMouseUp(S32 x, S32 y, MASK mask)
+{
+    return LLJoystick::handleMouseUp(x, y, mask);
+}
+
+void LLJoystickQuaternion::onHeldDown()
+{
+    LLVector3 axis;
+    updateSlop();
+
+    S32 dx = mLastMouse.mX - mFirstMouse.mX + mInitialOffset.mX;
+    S32 dy = mLastMouse.mY - mFirstMouse.mY + mInitialOffset.mY;
+
+    // left-right rotation
+    if (dx > mHorizSlopNear)
+    {
+        axis += mUpDnAxis;
+    }
+    else if (dx < -mHorizSlopNear)
+    {
+        axis -= mUpDnAxis;
+    }
+
+    // over/under rotation
+    if (dy > mVertSlopNear)
+    {
+        axis += mLfRtAxis;
+    }
+    else if (dy < -mVertSlopNear)
+    {
+        axis -= mLfRtAxis;
+    }
+
+    if (axis.isNull())
+        return;
+
+    axis.normalize();
+
+    LLQuaternion delta;
+    delta.setAngleAxis(0.0523599f, axis);   // about 3deg 
+
+    mRotation *= delta;
+    setValue(mRotation.getValue());
+    onCommit();
+}
+
+void LLJoystickQuaternion::draw()
+{
+    LLGLSUIDefault gls_ui;
+
+    getImageUnselected()->draw(0, 0);
+    LLPointer<LLUIImage> image = getImageSelected();
+
+    if (mInTop)
+    {
+        drawRotatedImage(getImageSelected(), 0);
+    }
+
+    if (mInRight)
+    {
+        drawRotatedImage(getImageSelected(), 1);
+    }
+
+    if (mInBottom)
+    {
+        drawRotatedImage(getImageSelected(), 2);
+    }
+
+    if (mInLeft)
+    {
+        drawRotatedImage(getImageSelected(), 3);
+    }
+
+    LLVector3 draw_point = mVectorZero * mRotation;
+    S32 halfwidth = getRect().getWidth() / 2;
+    S32 halfheight = getRect().getHeight() / 2;
+    draw_point.mV[mXAxisIndex] = (draw_point.mV[mXAxisIndex] + 1.0) * halfwidth;
+    draw_point.mV[mYAxisIndex] = (draw_point.mV[mYAxisIndex] + 1.0) * halfheight;
+
+    gl_circle_2d(draw_point.mV[mXAxisIndex], draw_point.mV[mYAxisIndex], 4, 8,
+        draw_point.mV[mZAxisIndex] >= 0.f);
+
+}
+
+F32 LLJoystickQuaternion::getOrbitRate()
+{
+    return 1;
+}
+
+void LLJoystickQuaternion::updateSlop()
+{
+    // small fixed slop region
+    mVertSlopNear = 16;
+    mVertSlopFar = 32;
+
+    mHorizSlopNear = 16;
+    mHorizSlopFar = 32;
+}
+
+void LLJoystickQuaternion::drawRotatedImage(LLPointer<LLUIImage> image, S32 rotations)
+{
+    S32 width = image->getWidth();
+    S32 height = image->getHeight();
+    LLTexture* texture = image->getImage();
+
+    /*
+    * Scale  texture coordinate system
+    * to handle the different between image size and size of texture.
+    */
+    F32 uv[][2] =
+    {
+        { (F32)width / texture->getWidth(), (F32)height / texture->getHeight() },
+        { 0.f, (F32)height / texture->getHeight() },
+        { 0.f, 0.f },
+        { (F32)width / texture->getWidth(), 0.f }
+    };
+
+    gGL.getTexUnit(0)->bind(texture);
+
+    gGL.color4fv(UI_VERTEX_COLOR.mV);
+
+    gGL.begin(LLRender::QUADS);
+    {
+        gGL.texCoord2fv(uv[(rotations + 0) % 4]);
+        gGL.vertex2i(width, height);
+
+        gGL.texCoord2fv(uv[(rotations + 1) % 4]);
+        gGL.vertex2i(0, height);
+
+        gGL.texCoord2fv(uv[(rotations + 2) % 4]);
+        gGL.vertex2i(0, 0);
+
+        gGL.texCoord2fv(uv[(rotations + 3) % 4]);
+        gGL.vertex2i(width, 0);
+    }
+    gGL.end();
+}
+
+void LLJoystickQuaternion::setRotation(const LLQuaternion &value)
+{
+    if (value != mRotation)
+    {
+        mRotation = value;
+        mRotation.normalize();
+        LLJoystick::setValue(mRotation.getValue());
+    }
+}
+
+LLQuaternion LLJoystickQuaternion::getRotation() const
+{
+    return mRotation;
+}
+
+
diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h
index 3e29215f61b8b9de6952578574b5204d64f2cb2f..b7fdf63e583b4f61e525c5e2b79146053bc134d5 100644
--- a/indra/newview/lljoystickbutton.h
+++ b/indra/newview/lljoystickbutton.h
@@ -30,6 +30,7 @@
 #include "llbutton.h"
 #include "llcoord.h"
 #include "llviewertexture.h"
+#include "llquaternion.h"
 
 typedef enum e_joystick_quadrant
 {
@@ -185,4 +186,47 @@ class LLJoystickCameraTrack
 	virtual void	resetJoystickCamera();
 };
 
+// 
+class LLJoystickQuaternion :
+    public LLJoystick
+{
+public:
+    struct Params :
+        public LLInitParam::Block<Params, LLJoystick::Params>
+    {
+        Params();
+    };
+
+    LLJoystickQuaternion(const LLJoystickQuaternion::Params &);
+
+    virtual void	setToggleState(BOOL left, BOOL top, BOOL right, BOOL bottom);
+
+    virtual BOOL	handleMouseDown(S32 x, S32 y, MASK mask);
+    virtual BOOL	handleMouseUp(S32 x, S32 y, MASK mask);
+    virtual void	onHeldDown();
+    virtual void	draw();
+
+    void            setRotation(const LLQuaternion &value);
+    LLQuaternion    getRotation() const;
+
+protected:
+    F32				getOrbitRate();
+    virtual void	updateSlop();
+    void			drawRotatedImage(LLPointer<LLUIImage> image, S32 rotations);
+
+    BOOL			mInLeft;
+    BOOL			mInTop;
+    BOOL			mInRight;
+    BOOL			mInBottom;
+
+    S32             mXAxisIndex;
+    S32             mYAxisIndex;
+    S32             mZAxisIndex;
+
+    LLVector3       mVectorZero;
+    LLQuaternion    mRotation;
+    LLVector3       mUpDnAxis;
+    LLVector3       mLfRtAxis;
+};
+
 #endif  // LL_LLJOYSTICKBUTTON_H
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 9c00243f448ad4d179b74e51bfef9a75d9e89792..c243f8b4f0194c8567fbaa6f51dd9f36b1f601cc 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -272,7 +272,7 @@ void LLLandmarkActions::createLandmarkHere(
 		name, desc,
 		LLAssetType::AT_LANDMARK,
 		LLInventoryType::IT_LANDMARK,
-		NOT_WEARABLE, PERM_ALL, 
+        NO_INV_SUBTYPE, PERM_ALL,
 		NULL);
 }
 
diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a2acb3efe2d9532fa8cefede51ad09f4d1beae04
--- /dev/null
+++ b/indra/newview/lllegacyatmospherics.cpp
@@ -0,0 +1,853 @@
+/** 
+ * @file lllegacyatmospherics.cpp
+ * @brief LLAtmospherics class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lllegacyatmospherics.h"
+
+#include "llfeaturemanager.h"
+#include "llviewercontrol.h"
+#include "llframetimer.h"
+
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "lldrawable.h"
+#include "llface.h"
+#include "llglheaders.h"
+#include "llsky.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "v3colorutil.h"
+
+#include "llsettingssky.h"
+#include "llenvironment.h"
+#include "lldrawpoolwater.h"
+
+class LLFastLn
+{
+public:
+	LLFastLn() 
+	{
+		mTable[0] = 0;
+		for( S32 i = 1; i < 257; i++ )
+		{
+			mTable[i] = log((F32)i);
+		}
+	}
+
+	F32 ln( F32 x )
+	{
+		const F32 OO_255 = 0.003921568627450980392156862745098f;
+		const F32 LN_255 = 5.5412635451584261462455391880218f;
+
+		if( x < OO_255 )
+		{
+			return log(x);
+		}
+		else
+		if( x < 1 )
+		{
+			x *= 255.f;
+			S32 index = llfloor(x);
+			F32 t = x - index;
+			F32 low = mTable[index];
+			F32 high = mTable[index + 1];
+			return low + t * (high - low) - LN_255;
+		}
+		else
+		if( x <= 255 )
+		{
+			S32 index = llfloor(x);
+			F32 t = x - index;
+			F32 low = mTable[index];
+			F32 high = mTable[index + 1];
+			return low + t * (high - low);
+		}
+		else
+		{
+			return log( x );
+		}
+	}
+
+	F32 pow( F32 x, F32 y )
+	{
+		return (F32)LL_FAST_EXP(y * ln(x));
+	}
+
+
+private:
+	F32 mTable[257]; // index 0 is unused
+};
+
+static LLFastLn gFastLn;
+
+
+// Functions used a lot.
+
+inline F32 LLHaze::calcPhase(const F32 cos_theta) const
+{
+	const F32 g2 = mG * mG;
+	const F32 den = 1 + g2 - 2 * mG * cos_theta;
+	return (1 - g2) * gFastLn.pow(den, -1.5);
+}
+
+inline void color_pow(LLColor3 &col, const F32 e)
+{
+	col.mV[0] = gFastLn.pow(col.mV[0], e);
+	col.mV[1] = gFastLn.pow(col.mV[1], e);
+	col.mV[2] = gFastLn.pow(col.mV[2], e);
+}
+
+inline LLColor3 color_norm(const LLColor3 &col)
+{
+	const F32 m = color_max(col);
+	if (m > 1.f)
+	{
+		return 1.f/m * col;
+	}
+	else return col;
+}
+
+inline void color_gamma_correct(LLColor3 &col)
+{
+	const F32 gamma_inv = 1.f/1.2f;
+	if (col.mV[0] != 0.f)
+	{
+		col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
+	}
+	if (col.mV[1] != 0.f)
+	{
+		col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
+	}
+	if (col.mV[2] != 0.f)
+	{
+		col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
+	}
+}
+
+static LLColor3 calc_air_sca_sea_level()
+{
+	static LLColor3 WAVE_LEN(675, 520, 445);
+	static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
+	static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
+	static LLColor3 n4 = n21 * n21;
+	static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
+	static LLColor3 wl4 = wl2 * wl2;
+	static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
+	static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
+	return dens_div_N * mult_const.divide(wl4);
+}
+
+// static constants.
+LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level();
+F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel);	
+F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f;
+
+/***************************************
+		Atmospherics
+***************************************/
+
+LLAtmospherics::LLAtmospherics()
+: 	mCloudDensity(0.2f),
+	mWind(0.f),
+	mWorldScale(1.f)
+{
+	/// WL PARAMS
+	mInitialized = FALSE;
+	mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
+	mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
+	mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
+	mFogColor.mV[VALPHA] = 0.0f;
+	mFogRatio = 1.2f;
+	mHazeConcentration = 0.f;
+	mInterpVal = 0.f;
+}
+
+
+LLAtmospherics::~LLAtmospherics()
+{
+}
+
+void LLAtmospherics::init()
+{
+   	const F32 haze_int = color_intens(mHaze.calcSigSca(0));
+	mHazeConcentration = haze_int / (color_intens(mHaze.calcAirSca(0)) + haze_int);
+	mInitialized = true;
+}
+
+LLColor4 LLAtmospherics::calcSkyColorInDir(AtmosphericsVars& vars, const LLVector3 &dir, bool isShiny)
+{
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+    return calcSkyColorInDir(psky, vars, dir, isShiny);
+}
+
+// This cubemap is used as "environmentMap" in indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+LLColor4 LLAtmospherics::calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3 &dir, bool isShiny)
+{
+	F32 sky_saturation = 0.25f;
+	F32 land_saturation = 0.1f;
+
+	if (isShiny && dir.mV[VZ] < -0.02f)
+	{
+		LLColor4 col;
+		LLColor3 desat_fog = LLColor3(mFogColor);
+		F32 brightness = desat_fog.brightness();// NOTE: Linear brightness!
+		// So that shiny somewhat shows up at night.
+		if (brightness < 0.15f)
+		{
+			brightness = 0.15f;
+			desat_fog = smear(0.15f);
+		}
+		F32 greyscale_sat = brightness * (1.0f - land_saturation);
+		desat_fog = desat_fog * land_saturation + smear(greyscale_sat);
+		if (!gPipeline.canUseWindLightShaders())
+		{
+			col = LLColor4(desat_fog, 0.f);
+		}
+		else 
+		{
+			col = LLColor4(desat_fog * 0.5f, 0.f);
+		}
+		float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
+		x *= x;
+		col.mV[0] *= x*x;
+		col.mV[1] *= powf(x, 2.5f);
+		col.mV[2] *= x*x*x;
+		return col;
+	}
+
+	// undo OGL_TO_CFR_ROTATION and negate vertical direction.
+	LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[0]);
+
+	//calculates hazeColor
+	calcSkyColorWLVert(psky, Pn, vars);
+
+	if (isShiny)
+	{
+		F32 brightness = vars.hazeColor.brightness();
+		F32 greyscale_sat = brightness * (1.0f - sky_saturation);
+		LLColor3 sky_color = vars.hazeColor * sky_saturation + smear(greyscale_sat);
+		//sky_color *= (0.5f + 0.5f * brightness); // SL-12574 EEP sky is being attenuated too much
+		return LLColor4(sky_color, 0.0f);
+	}
+
+	bool low_end = !gPipeline.canUseWindLightShaders();
+	LLColor3 sky_color = low_end ? vars.hazeColor * 2.0f : psky->gammaCorrect(vars.hazeColor * 2.0f);
+
+	return LLColor4(sky_color, 0.0f);
+}
+
+// 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\lllegacyatmospherics.cpp
+void LLAtmospherics::calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVector3 & Pn, AtmosphericsVars& vars)
+{
+    LLColor3    blue_density = vars.blue_density;
+    LLColor3    blue_horizon = vars.blue_horizon;
+    F32         haze_horizon = vars.haze_horizon;
+    F32         haze_density = vars.haze_density;
+    F32         density_multiplier = vars.density_multiplier;
+    F32         max_y = vars.max_y;
+    LLVector4   sun_norm = vars.sun_norm;
+
+	// project the direction ray onto the sky dome.
+	F32 phi = acos(Pn[1]);
+	F32 sinA = sin(F_PI - phi);
+	if (fabsf(sinA) < 0.01f)
+	{ //avoid division by zero
+		sinA = 0.01f;
+	}
+
+	F32 Plen = vars.dome_radius * sin(F_PI + phi + asin(vars.dome_offset * sinA)) / sinA;
+
+	Pn *= Plen;
+
+	// Set altitude
+	if (Pn[1] > 0.f)
+	{
+		Pn *= (max_y / Pn[1]);
+	}
+	else
+	{
+		Pn *= (-32000.f / Pn[1]);
+	}
+
+	Plen = Pn.length();
+	Pn /= Plen;
+
+	// Initialize temp variables
+	LLColor3 sunlight = vars.sunlight;
+    LLColor3 ambient = vars.ambient;
+    
+    LLColor3 glow = vars.glow;
+    F32 cloud_shadow = vars.cloud_shadow;
+
+	// Sunlight attenuation effect (hue and brightness) due to atmosphere
+	// this is used later for sunlight modulation at various altitudes
+	LLColor3 light_atten = vars.light_atten;
+    LLColor3 light_transmittance = psky->getLightTransmittance(Plen);
+    (void)light_transmittance; // silence Clang warn-error
+
+	// Calculate relative weights
+	LLColor3 temp2(0.f, 0.f, 0.f);
+	LLColor3 temp1 = vars.total_density;
+
+	LLColor3 blue_weight = componentDiv(blue_density, temp1);
+	LLColor3 blue_factor = blue_horizon * blue_weight;
+	LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
+	LLColor3 haze_factor = haze_horizon * haze_weight;
+
+
+	// Compute sunlight from P & lightnorm (for long rays like sky)
+    temp2.mV[1] = llmax(F_APPROXIMATELY_ZERO, llmax(0.f, Pn[1]) * 1.0f + sun_norm.mV[1] );
+
+    temp2.mV[1] = 1.f / temp2.mV[1];
+    componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
+    componentMultBy(sunlight, light_transmittance);
+
+    // Distance
+	temp2.mV[2] = Plen * density_multiplier;
+
+    // Transparency (-> temp1)
+	temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
+
+	// Compute haze glow
+	temp2.mV[0] = Pn * LLVector3(sun_norm);
+
+	temp2.mV[0] = 1.f - temp2.mV[0];
+		// temp2.x is 0 at the sun and increases away from sun
+	temp2.mV[0] = llmax(temp2.mV[0], .001f);	
+		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+
+	// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+	temp2.mV[0] *= glow.mV[0];
+
+	temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]);
+		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
+
+	// Add "minimum anti-solar illumination"
+	temp2.mV[0] += .25f;
+
+
+	// Haze color above cloud
+	vars.hazeColor = (blue_factor * (sunlight + ambient) + componentMult(haze_factor, sunlight * temp2.mV[0] + ambient));	
+
+	// Increase ambient when there are more clouds
+	LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f;
+
+	// Dim sunlight by cloud shadow percentage
+	sunlight *= (1.f - cloud_shadow);
+
+	// Haze color below cloud
+	vars.hazeColorBelowCloud = (blue_factor * (sunlight + tmpAmbient) + componentMult(haze_factor, sunlight * temp2.mV[0] + tmpAmbient));	
+
+	// Final atmosphere additive
+	componentMultBy(vars.hazeColor, LLColor3::white - temp1);
+
+/*
+	// SL-12574
+
+    // Attenuate cloud color by atmosphere
+	temp1 = componentSqrt(temp1);	//less atmos opacity (more transparency) below clouds
+
+	// At horizon, blend high altitude sky color towards the darker color below the clouds
+	vars.hazeColor += componentMult(vars.hazeColorBelowCloud - vars.hazeColor, LLColor3::white - componentSqrt(temp1));
+*/
+}
+
+void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in)
+{
+    LLVector3 tosun = tosun_in;
+
+	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG))
+	{
+		if (!LLGLSLShader::sNoFixedFunction)
+		{
+			glFogf(GL_FOG_DENSITY, 0);
+			glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV);
+			glFogf(GL_FOG_END, 1000000.f);
+		}
+		return;
+	}
+
+	const BOOL hide_clip_plane = TRUE;
+	LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f);
+
+	const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f;
+	// LLWorld::getInstance()->getWaterHeight();
+	F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2];
+
+	F32 near_clip_height = LLViewerCamera::getInstance()->getAtAxis().mV[VZ] * LLViewerCamera::getInstance()->getNear();
+	camera_height += near_clip_height;
+
+	F32 fog_distance = 0.f;
+	LLColor3 res_color[3];
+
+	LLColor3 sky_fog_color = LLColor3::white;
+	LLColor3 render_fog_color = LLColor3::white;
+
+	const F32 tosun_z = tosun.mV[VZ];
+	tosun.mV[VZ] = 0.f;
+	tosun.normalize();
+	LLVector3 perp_tosun;
+	perp_tosun.mV[VX] = -tosun.mV[VY];
+	perp_tosun.mV[VY] = tosun.mV[VX];
+	LLVector3 tosun_45 = tosun + perp_tosun;
+	tosun_45.normalize();
+
+	F32 delta = 0.06f;
+	tosun.mV[VZ] = delta;
+	perp_tosun.mV[VZ] = delta;
+	tosun_45.mV[VZ] = delta;
+	tosun.normalize();
+	perp_tosun.normalize();
+	tosun_45.normalize();
+
+	// Sky colors, just slightly above the horizon in the direction of the sun, perpendicular to the sun, and at a 45 degree angle to the sun.
+    AtmosphericsVars vars;
+
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    // invariants across whole sky tex process...
+    vars.blue_density = psky->getBlueDensity();    
+    vars.blue_horizon = psky->getBlueHorizon();
+    vars.haze_density = psky->getHazeDensity();
+    vars.haze_horizon = psky->getHazeHorizon();
+    vars.density_multiplier = psky->getDensityMultiplier();    
+    vars.distance_multiplier = psky->getDistanceMultiplier();
+    vars.max_y = psky->getMaxY();
+    vars.sun_norm = LLEnvironment::instance().getSunDirectionCFR();
+    vars.sunlight = psky->getSunlightColor();
+    vars.ambient = psky->getAmbientColor();
+    vars.glow = psky->getGlow();
+    vars.cloud_shadow = psky->getCloudShadow();
+    vars.dome_radius = psky->getDomeRadius();
+    vars.dome_offset = psky->getDomeOffset();
+    vars.light_atten = psky->getLightAttenuation(vars.max_y);
+    vars.light_transmittance = psky->getLightTransmittance(vars.max_y);
+    vars.total_density = psky->getTotalDensity();
+    vars.gamma = psky->getGamma();
+
+	res_color[0] = calcSkyColorInDir(vars, tosun);
+	res_color[1] = calcSkyColorInDir(vars, perp_tosun);
+	res_color[2] = calcSkyColorInDir(vars, tosun_45);
+
+	sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]);
+
+	F32 full_off = -0.25f;
+	F32 full_on = 0.00f;
+	F32 on = (tosun_z - full_off) / (full_on - full_off);
+	on = llclamp(on, 0.01f, 1.f);
+	sky_fog_color *= 0.5f * on;
+
+
+	// We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ???
+	S32 i;
+	for (i = 0; i < 3; i++)
+	{
+		sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]);
+	}
+
+	color_gamma_correct(sky_fog_color);
+
+	render_fog_color = sky_fog_color;
+
+	F32 fog_density = 0.f;
+	fog_distance = mFogRatio * distance;
+	
+	if (camera_height > water_height)
+	{
+		LLColor4 fog(render_fog_color);
+		if (!LLGLSLShader::sNoFixedFunction)
+		{
+			glFogfv(GL_FOG_COLOR, fog.mV);
+		}
+		mGLFogCol = fog;
+
+		if (hide_clip_plane)
+		{
+			// For now, set the density to extend to the cull distance.
+			const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f)))
+			fog_density = f_log/fog_distance;
+			if (!LLGLSLShader::sNoFixedFunction)
+			{
+				glFogi(GL_FOG_MODE, GL_EXP2);
+			}
+		}
+		else
+		{
+			const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f))
+			fog_density = (f_log)/fog_distance;
+			if (!LLGLSLShader::sNoFixedFunction)
+			{
+				glFogi(GL_FOG_MODE, GL_EXP);
+			}
+		}
+	}
+	else
+	{
+        LLSettingsWater::ptr_t pwater = LLEnvironment::instance().getCurrentWater();
+		F32 depth = water_height - camera_height;
+		
+		// get the water param manager variables
+        float water_fog_density = pwater->getModifiedWaterFogDensity(depth <= 0.0f);
+
+		LLColor4 water_fog_color(pwater->getWaterFogColor());
+
+		// adjust the color based on depth.  We're doing linear approximations
+		float depth_scale = gSavedSettings.getF32("WaterGLFogDepthScale");
+		float depth_modifier = 1.0f - llmin(llmax(depth / depth_scale, 0.01f), 
+			gSavedSettings.getF32("WaterGLFogDepthFloor"));
+
+		LLColor4 fogCol = water_fog_color * depth_modifier;
+		fogCol.setAlpha(1);
+
+		// set the gl fog color
+		mGLFogCol = fogCol;
+
+		// set the density based on what the shaders use
+		fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale");
+
+		if (!LLGLSLShader::sNoFixedFunction)
+		{
+			glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
+			glFogi(GL_FOG_MODE, GL_EXP2);
+		}
+	}
+
+	mFogColor = sky_fog_color;
+	mFogColor.setAlpha(1);
+
+	LLDrawPoolWater::sWaterFogEnd = fog_distance*2.2f;
+
+	if (!LLGLSLShader::sNoFixedFunction)
+	{
+		LLGLSFog gls_fog;
+		glFogf(GL_FOG_END, fog_distance*2.2f);
+		glFogf(GL_FOG_DENSITY, fog_density);
+		glHint(GL_FOG_HINT, GL_NICEST);
+	}
+	stop_glerror();
+}
+
+// Functions used a lot.
+F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
+{
+	F32 mv = color_max(col);
+	if (0 == mv)
+	{
+		return 0;
+	}
+
+	col *= 1.f / mv;
+	color_pow(col, e);
+	if (postmultiply)
+	{
+		col *= mv;
+	}
+	return mv;
+}
+
+// Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis.
+// Range of output is 0.0f to 2pi //359.99999...f
+// Returns 0.0f when "v" = +/- z_axis.
+F32 azimuth(const LLVector3 &v)
+{
+	F32 azimuth = 0.0f;
+	if (v.mV[VX] == 0.0f)
+	{
+		if (v.mV[VY] > 0.0f)
+		{
+			azimuth = F_PI * 0.5f;
+		}
+		else if (v.mV[VY] < 0.0f)
+		{
+			azimuth = F_PI * 1.5f;// 270.f;
+		}
+	}
+	else
+	{
+		azimuth = (F32) atan(v.mV[VY] / v.mV[VX]);
+		if (v.mV[VX] < 0.0f)
+		{
+			azimuth += F_PI;
+		}
+		else if (v.mV[VY] < 0.0f)
+		{
+			azimuth += F_PI * 2;
+		}
+	}	
+	return azimuth;
+}
+
+bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b)
+{
+    if (a.hazeColor != b.hazeColor)
+    {
+        return false;
+    }
+
+    if (a.hazeColorBelowCloud != b.hazeColorBelowCloud)
+    {
+        return false;
+    }
+
+    if (a.cloudColorSun != b.cloudColorSun)
+    {
+        return false;
+    }
+
+    if (a.cloudColorAmbient != b.cloudColorAmbient)
+    {
+        return false;
+    }
+
+    if (a.cloudDensity != b.cloudDensity)
+    {
+        return false;
+    }
+
+    if (a.density_multiplier != b.density_multiplier)
+    {
+        return false;
+    }
+
+    if (a.haze_horizon != b.haze_horizon)
+    {
+        return false;
+    }
+
+    if (a.haze_density != b.haze_density)
+    {
+        return false;
+    }
+
+    if (a.blue_horizon != b.blue_horizon)
+    {
+        return false;
+    }
+
+    if (a.blue_density != b.blue_density)
+    {
+        return false;
+    }
+
+    if (a.dome_offset != b.dome_offset)
+    {
+        return false;
+    }
+
+    if (a.dome_radius != b.dome_radius)
+    {
+        return false;
+    }
+
+    if (a.cloud_shadow != b.cloud_shadow)
+    {
+        return false;
+    }
+
+    if (a.glow != b.glow)
+    {
+        return false;
+    }
+
+    if (a.ambient != b.ambient)
+    {
+        return false;
+    }
+
+    if (a.sunlight != b.sunlight)
+    {
+        return false;
+    }
+
+    if (a.sun_norm != b.sun_norm)
+    {
+        return false;
+    }
+
+    if (a.gamma != b.gamma)
+    {
+        return false;
+    }
+
+    if (a.max_y != b.max_y)
+    {
+        return false;
+    }
+
+    if (a.distance_multiplier != b.distance_multiplier)
+    {
+        return false;
+    }
+
+    // light_atten, light_transmittance, total_density
+    // are ignored as they always change when the values above do
+    // they're just shared calc across the sky map generation to save cycles
+
+    return true;
+}
+
+bool approximatelyEqual(const F32 &a, const  F32 &b, const F32 &fraction_treshold)
+{
+    F32 diff = fabs(a - b);
+    if (diff < F_APPROXIMATELY_ZERO || diff < llmax(fabs(a), fabs(b)) * fraction_treshold)
+    {
+        return true;
+    }
+    return false;
+}
+
+bool approximatelyEqual(const LLColor3 &a, const  LLColor3 &b, const F32 &fraction_treshold)
+{
+    return approximatelyEqual(a.mV[0], b.mV[0], fraction_treshold)
+           && approximatelyEqual(a.mV[1], b.mV[1], fraction_treshold)
+           && approximatelyEqual(a.mV[2], b.mV[2], fraction_treshold);
+}
+
+bool approximatelyEqual(const LLVector4 &a, const  LLVector4 &b, const F32 &fraction_treshold)
+{
+    return approximatelyEqual(a.mV[0], b.mV[0], fraction_treshold)
+        && approximatelyEqual(a.mV[1], b.mV[1], fraction_treshold)
+        && approximatelyEqual(a.mV[2], b.mV[2], fraction_treshold)
+        && approximatelyEqual(a.mV[3], b.mV[3], fraction_treshold);
+}
+
+bool approximatelyEqual(const AtmosphericsVars& a, const AtmosphericsVars& b, const F32 fraction_treshold)
+{
+    if (!approximatelyEqual(a.hazeColor, b.hazeColor, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.hazeColorBelowCloud, b.hazeColorBelowCloud, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.cloudColorSun, b.cloudColorSun, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.cloudColorAmbient, b.cloudColorAmbient, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.cloudDensity, b.cloudDensity, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.density_multiplier, b.density_multiplier, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.haze_horizon, b.haze_horizon, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.haze_density, b.haze_density, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.blue_horizon, b.blue_horizon, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.blue_density, b.blue_density, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.dome_offset, b.dome_offset, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.dome_radius, b.dome_radius, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.cloud_shadow, b.cloud_shadow, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.glow, b.glow, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.ambient, b.ambient, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.sunlight, b.sunlight, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.sun_norm, b.sun_norm, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.gamma, b.gamma, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.max_y, b.max_y, fraction_treshold))
+    {
+        return false;
+    }
+
+    if (!approximatelyEqual(a.distance_multiplier, b.distance_multiplier, fraction_treshold))
+    {
+        return false;
+    }
+
+    // light_atten, light_transmittance, total_density
+    // are ignored as they always change when the values above do
+    // they're just shared calc across the sky map generation to save cycles
+
+    return true;
+}
+
diff --git a/indra/newview/lllegacyatmospherics.h b/indra/newview/lllegacyatmospherics.h
new file mode 100644
index 0000000000000000000000000000000000000000..03c8efb91aed629c3abbb433238fe8aec9557ba1
--- /dev/null
+++ b/indra/newview/lllegacyatmospherics.h
@@ -0,0 +1,284 @@
+/** 
+ * @file lllegacyatmospherics.h
+ * @brief LLVOSky class header file
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, 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$
+ */
+
+#ifndef LL_LLLEGACYATMOSPHERICS_H
+#define LL_LLLEGACYATMOSPHERICS_H
+
+#include "stdtypes.h"
+#include "v3color.h"
+#include "v4coloru.h"
+#include "llviewertexture.h"
+#include "llviewerobject.h"
+#include "llframetimer.h"
+#include "v3colorutil.h"
+#include "llsettingssky.h"
+
+//////////////////////////////////
+//
+// Lots of constants
+//
+// Will clean these up at some point...
+//
+
+const F32 HORIZON_DIST          = 1024.0f;
+const F32 ATM_EXP_FALLOFF       = 0.000126f;
+const F32 ATM_SEA_LEVEL_NDENS   = 2.55e25f;
+const F32 ATM_HEIGHT            = 100000.f;
+
+// constants used in calculation of scattering coeff of clear air
+const F32 sigma     = 0.035f;
+const F32 fsigma    = (6.f + 3.f * sigma) / (6.f-7.f*sigma);
+const F64 Ndens     = 2.55e25;
+const F64 Ndens2    = Ndens*Ndens;
+
+class LLFace;
+class LLHaze;
+
+LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length)
+{
+    LLColor3 refr_ind;
+    for (S32 i = 0; i < 3; ++i)
+    {
+        const F32 wl2 = wave_length.mV[i] * wave_length.mV[i] * 1e-6f;
+        refr_ind.mV[i] = 6.43e3f + ( 2.95e6f / ( 146.0f - 1.f/wl2 ) ) + ( 2.55e4f / ( 41.0f - 1.f/wl2 ) );
+        refr_ind.mV[i] *= 1.0e-8f;
+        refr_ind.mV[i] += 1.f;
+    }
+    return refr_ind;
+}
+
+
+class LLHaze
+{
+public:
+    LLHaze() : mG(0), mFalloff(1), mAbsCoef(0.f) {mSigSca.setToBlack();}
+    LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2.f) : 
+            mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0.f)
+    {
+        mAbsCoef = color_intens(mSigSca) / sAirScaIntense;
+    }
+
+    LLHaze(const F32 g, const F32 sca, const F32 fo = 2.f) : mG(g),
+            mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
+    {
+        mAbsCoef = 0.01f * sca / sAirScaAvg;
+    }
+
+/* Proportion of light that is scattered into 'path' from 'in' over distance dt. */
+/* assumes that vectors 'path' and 'in' are normalized. Scattering coef / 2pi */
+
+    LL_FORCE_INLINE LLColor3 calcAirSca(const F32 h)
+    {
+       return calcFalloff(h) * sAirScaSeaLevel;
+    }
+
+    LL_FORCE_INLINE void calcAirSca(const F32 h, LLColor3 &result)
+    {
+        result = sAirScaSeaLevel;
+        result *= calcFalloff(h);
+    }
+
+    F32 getG() const                { return mG; }
+
+    void setG(const F32 g)
+    {
+        mG = g;
+    }
+
+    const LLColor3& getSigSca() const // sea level
+    {
+        return mSigSca;
+    } 
+
+    void setSigSca(const LLColor3& s)
+    {
+        mSigSca = s;
+        mAbsCoef = 0.01f * color_intens(mSigSca) / sAirScaIntense;
+    }
+
+    void setSigSca(const F32 s0, const F32 s1, const F32 s2)
+    {
+        mSigSca = sAirScaAvg * LLColor3 (s0, s1, s2);
+        mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
+    }
+
+    F32 getFalloff() const
+    {
+        return mFalloff;
+    }
+
+    void setFalloff(const F32 fo)
+    {
+        mFalloff = fo;
+    }
+
+    F32 getAbsCoef() const
+    {
+        return mAbsCoef;
+    }
+
+    inline static F32 calcFalloff(const F32 h)
+    {
+        return (h <= 0) ? 1.0f : (F32)LL_FAST_EXP(-ATM_EXP_FALLOFF * h);
+    }
+
+    inline LLColor3 calcSigSca(const F32 h) const
+    {
+        return calcFalloff(h * mFalloff) * mSigSca;
+    }
+
+    inline void calcSigSca(const F32 h, LLColor3 &result) const
+    {
+        result = mSigSca;
+        result *= calcFalloff(h * mFalloff);
+    }
+
+    LLColor3 calcSigExt(const F32 h) const
+    {
+        return calcFalloff(h * mFalloff) * (1 + mAbsCoef) * mSigSca;
+    }
+
+    F32 calcPhase(const F32 cos_theta) const;
+
+private:
+    static LLColor3 const sAirScaSeaLevel;
+    static F32 const sAirScaIntense;
+    static F32 const sAirScaAvg;
+
+protected:
+    F32         mG;
+    LLColor3    mSigSca;
+    F32         mFalloff;   // 1 - slow, >1 - faster
+    F32         mAbsCoef;
+};
+
+
+class LLCubeMap;
+
+class AtmosphericsVars
+{
+public:
+    AtmosphericsVars()
+    : hazeColor(0,0,0)
+    , hazeColorBelowCloud(0,0,0)
+    , cloudColorSun(0,0,0)
+    , cloudColorAmbient(0,0,0)
+    , cloudDensity(0.0f)
+    , blue_density()
+    , blue_horizon()
+    , haze_density(0.0f)
+    , haze_horizon(0.0f)
+    , density_multiplier(0.0f)
+    , max_y(0.0f)
+    , gamma(1.0f)
+    , sun_norm(0.0f, 1.0f, 0.0f, 1.0f)
+    , sunlight()
+    , ambient()
+    , glow()
+    , cloud_shadow(1.0f)
+    , dome_radius(1.0f)
+    , dome_offset(1.0f)
+    , light_atten()
+    , light_transmittance()
+    {
+    }
+
+    friend bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b);
+    // returns true if values are within treshold of each other.
+    friend bool approximatelyEqual(const AtmosphericsVars& a, const AtmosphericsVars& b, const F32 fraction_treshold);
+
+    LLColor3  hazeColor;
+    LLColor3  hazeColorBelowCloud;
+	LLColor3  cloudColorSun;
+	LLColor3  cloudColorAmbient;
+	F32       cloudDensity;
+    LLColor3  blue_density;
+    LLColor3  blue_horizon;
+    F32       haze_density;
+    F32       haze_horizon;
+    F32       density_multiplier;
+    F32       distance_multiplier;
+    F32       max_y;
+    F32       gamma;
+    LLVector4 sun_norm;
+    LLColor3  sunlight;
+    LLColor3  ambient;
+    LLColor3  glow;
+    F32       cloud_shadow;
+    F32       dome_radius;
+    F32       dome_offset;
+    LLColor3 light_atten;
+    LLColor3 light_transmittance;
+    LLColor3 total_density;
+};
+
+class LLAtmospherics
+{
+public:    
+    LLAtmospherics();
+    ~LLAtmospherics();
+
+    void init();
+    void updateFog(const F32 distance, const LLVector3& tosun);
+
+    const LLHaze& getHaze() const                    { return mHaze; }
+    LLHaze& getHaze()                                { return mHaze; }
+    F32 getHazeConcentration() const                 { return mHazeConcentration; }
+    void setHaze(const LLHaze& h)                    { mHaze = h; }
+    void setFogRatio(const F32 fog_ratio)            { mFogRatio = fog_ratio; }
+
+    F32      getFogRatio() const                     { return mFogRatio; }
+    LLColor4 getFogColor() const                     { return mFogColor; }
+    LLColor4 getGLFogColor() const                   { return mGLFogCol; }
+
+    void setCloudDensity(F32 cloud_density)          { mCloudDensity = cloud_density; }
+    void setWind ( const LLVector3& wind )           { mWind = wind.length(); }
+
+    LLColor4 calcSkyColorInDir(AtmosphericsVars& vars, const LLVector3& dir, bool isShiny = false);
+    LLColor4 calcSkyColorInDir(const LLSettingsSky::ptr_t &psky, AtmosphericsVars& vars, const LLVector3& dir, bool isShiny = false);
+
+protected:    
+
+    void     calcSkyColorWLVert(const LLSettingsSky::ptr_t &psky, LLVector3 & Pn, AtmosphericsVars& vars);
+    LLColor3 getHazeColor(LLSettingsSky::ptr_t psky, AtmosphericsVars& vars, F32 costheta, F32 cloud_shadow);
+
+    LLHaze              mHaze;
+    F32                 mHazeConcentration;
+    F32                 mCloudDensity;
+    F32                 mWind;
+    BOOL                mInitialized;
+    LLVector3           mLastLightingDirection;
+    LLColor3            mLastTotalAmbient;
+    F32                 mAmbientScale;
+    LLColor3            mNightColorShift;
+    F32                 mInterpVal;
+    LLColor4            mFogColor;
+    LLColor4            mGLFogCol;
+    F32                 mFogRatio;
+    F32                 mWorldScale;
+};
+
+#endif
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index b8bde39bd105af0d6cf8991be35e821ba8250c5a..5a17332fde653a868d52712c5bba8e9916fa4c5f 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -1038,6 +1038,19 @@ LLUUID LLLocalBitmapMgr::getWorldID(LLUUID tracking_id)
 	return world_id;
 }
 
+bool LLLocalBitmapMgr::isLocal(const LLUUID world_id)
+{
+    for (local_list_iter iter = mBitmapList.begin(); iter != mBitmapList.end(); iter++)
+    {
+        LLLocalBitmap* unit = *iter;
+        if (unit->getWorldID() == world_id)
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
 std::string LLLocalBitmapMgr::getFilename(LLUUID tracking_id)
 {
 	std::string filename = "";
diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h
index f6cc1e919e00cc8bdc82565de32c254786e3a5fa..d5ee7efdc640cfa5c90028c5e8b8f7fd8d823986 100644
--- a/indra/newview/lllocalbitmaps.h
+++ b/indra/newview/lllocalbitmaps.h
@@ -120,6 +120,7 @@ class LLLocalBitmapMgr : public LLSingleton<LLLocalBitmapMgr>
 	bool 		checkTextureDimensions(std::string filename);
 
 	LLUUID       getWorldID(LLUUID tracking_id);
+    bool         isLocal(LLUUID world_id);
 	std::string  getFilename(LLUUID tracking_id);
 
 	void         feedScrollList(LLScrollListCtrl* ctrl);
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 802e4941e634c6137f7faee131054389ac7b7ce1..fd418afd2c9381d244485c570770bb09713c1be3 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -44,7 +44,6 @@
 
 // newview includes
 #include "llagent.h"
-#include "llenvmanager.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llinventoryobserver.h"
 #include "lllandmarkactions.h"
diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp
index 51127928d1271e9125fb4bb2b829991cb0bc2b5c..57a6ecb604c616f0b1ea1232f3b24343d09d89f1 100644
--- a/indra/newview/llmachineid.cpp
+++ b/indra/newview/llmachineid.cpp
@@ -237,7 +237,7 @@ S32 LLMachineID::init()
                 {
                     if (j >= serial_size || vtProp.bstrVal[j] == 0)
                         break;
-
+                    
                     static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]);
                     j++;
                 }
diff --git a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
index 63d97f6ac2da08e6103d6567b1bfb2158946e0f0..0663dd41ee98a8eeace49ae399a17aae9db608db 100644
--- a/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
+++ b/indra/newview/llmenuoptionpathfindingrebakenavmesh.cpp
@@ -34,7 +34,6 @@
 #include <boost/signals2.hpp>
 
 #include "llagent.h"
-#include "llenvmanager.h"
 #include "llnotificationsutil.h"
 #include "llpathfindingmanager.h"
 #include "llpathfindingnavmesh.h"
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 53416036c95b1efa5dc099336d889e9c40a16e2e..520c9adcd132797110aa977ab5ca6d2ba141a489 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -1216,7 +1216,6 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename
         checkRemovePhoto(outfit_id);
         std::string upload_pending_name = outfit_id.asString();
         std::string upload_pending_desc = "";
-        LLAssetStorage::LLStoreAssetCallback callback = NULL;
         LLUUID photo_id = upload_new_resource(filename, // file
             upload_pending_name,
             upload_pending_desc,
@@ -1224,7 +1223,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector<std::string>& filename
             LLFloaterPerms::getNextOwnerPerms("Uploads"),
             LLFloaterPerms::getGroupPerms("Uploads"),
             LLFloaterPerms::getEveryonePerms("Uploads"),
-            upload_pending_name, callback, expected_upload_cost, nruserdata, false);
+            upload_pending_name, LLAssetStorage::LLStoreAssetCallback(), expected_upload_cost, nruserdata, false);
         mOutfitLinkPending = outfit_id;
     }
     delete unit;
diff --git a/indra/newview/llpaneleditsky.cpp b/indra/newview/llpaneleditsky.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2e26b691441d0fa439cad061b2a9bd2142d4f061
--- /dev/null
+++ b/indra/newview/llpaneleditsky.cpp
@@ -0,0 +1,877 @@
+/**
+* @file llpaneleditsky.cpp
+* @brief Floaters to create and edit fixed settings for sky and water.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneleditsky.h"
+
+#include "llslider.h"
+#include "llsliderctrl.h"
+#include "lltexturectrl.h"
+#include "llcolorswatch.h"
+#include "llvirtualtrackball.h"
+#include "llsettingssky.h"
+#include "llenvironment.h"
+#include "llatmosphere.h"
+
+namespace
+{   
+    // Atmosphere Tab
+    const std::string   FIELD_SKY_AMBIENT_LIGHT("ambient_light");
+    const std::string   FIELD_SKY_BLUE_HORIZON("blue_horizon");
+    const std::string   FIELD_SKY_BLUE_DENSITY("blue_density");
+    const std::string   FIELD_SKY_HAZE_HORIZON("haze_horizon");
+    const std::string   FIELD_SKY_HAZE_DENSITY("haze_density");
+    const std::string   FIELD_SKY_SCENE_GAMMA("scene_gamma");
+    const std::string   FIELD_SKY_DENSITY_MULTIP("density_multip");
+    const std::string   FIELD_SKY_DISTANCE_MULTIP("distance_multip");
+    const std::string   FIELD_SKY_MAX_ALT("max_alt");
+
+    const std::string   FIELD_SKY_CLOUD_COLOR("cloud_color");
+    const std::string   FIELD_SKY_CLOUD_COVERAGE("cloud_coverage");
+    const std::string   FIELD_SKY_CLOUD_SCALE("cloud_scale");
+    const std::string   FIELD_SKY_CLOUD_VARIANCE("cloud_variance");
+
+    const std::string   FIELD_SKY_CLOUD_SCROLL_XY("cloud_scroll_xy");
+    const std::string   FIELD_SKY_CLOUD_MAP("cloud_map");
+    const std::string   FIELD_SKY_CLOUD_DENSITY_X("cloud_density_x");
+    const std::string   FIELD_SKY_CLOUD_DENSITY_Y("cloud_density_y");
+    const std::string   FIELD_SKY_CLOUD_DENSITY_D("cloud_density_d");
+    const std::string   FIELD_SKY_CLOUD_DETAIL_X("cloud_detail_x");
+    const std::string   FIELD_SKY_CLOUD_DETAIL_Y("cloud_detail_y");
+    const std::string   FIELD_SKY_CLOUD_DETAIL_D("cloud_detail_d");
+
+    const std::string   FIELD_SKY_SUN_MOON_COLOR("sun_moon_color");
+    const std::string   FIELD_SKY_GLOW_FOCUS("glow_focus");
+    const std::string   FIELD_SKY_GLOW_SIZE("glow_size");
+    const std::string   FIELD_SKY_STAR_BRIGHTNESS("star_brightness");
+    const std::string   FIELD_SKY_SUN_ROTATION("sun_rotation");
+    const std::string   FIELD_SKY_SUN_IMAGE("sun_image");
+    const std::string   FIELD_SKY_SUN_SCALE("sun_scale");
+    const std::string   FIELD_SKY_SUN_BEACON("sunbeacon");
+    const std::string   FIELD_SKY_MOON_BEACON("moonbeacon");
+    const std::string   FIELD_SKY_MOON_ROTATION("moon_rotation");
+    const std::string   FIELD_SKY_MOON_IMAGE("moon_image");
+    const std::string   FIELD_SKY_MOON_SCALE("moon_scale");
+    const std::string   FIELD_SKY_MOON_BRIGHTNESS("moon_brightness");
+
+    const std::string   PANEL_SKY_SUN_LAYOUT("sun_layout");
+    const std::string   PANEL_SKY_MOON_LAYOUT("moon_layout");
+
+    const std::string   FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL("rayleigh_exponential");
+    const std::string   FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE("rayleigh_exponential_scale");
+    const std::string   FIELD_SKY_DENSITY_RAYLEIGH_LINEAR("rayleigh_linear");
+    const std::string   FIELD_SKY_DENSITY_RAYLEIGH_CONSTANT("rayleigh_constant");
+    const std::string   FIELD_SKY_DENSITY_RAYLEIGH_MAX_ALTITUDE("rayleigh_max_altitude");
+
+    const std::string   FIELD_SKY_DENSITY_MIE_EXPONENTIAL("mie_exponential");
+    const std::string   FIELD_SKY_DENSITY_MIE_EXPONENTIAL_SCALE("mie_exponential_scale");
+    const std::string   FIELD_SKY_DENSITY_MIE_LINEAR("mie_linear");
+    const std::string   FIELD_SKY_DENSITY_MIE_CONSTANT("mie_constant");
+    const std::string   FIELD_SKY_DENSITY_MIE_ANISO("mie_aniso_factor");
+    const std::string   FIELD_SKY_DENSITY_MIE_MAX_ALTITUDE("mie_max_altitude");
+
+    const std::string   FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL("absorption_exponential");
+    const std::string   FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL_SCALE("absorption_exponential_scale");
+    const std::string   FIELD_SKY_DENSITY_ABSORPTION_LINEAR("absorption_linear");
+    const std::string   FIELD_SKY_DENSITY_ABSORPTION_CONSTANT("absorption_constant");
+    const std::string   FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE("absorption_max_altitude");
+
+    const std::string   FIELD_SKY_DENSITY_MOISTURE_LEVEL("moisture_level");
+    const std::string   FIELD_SKY_DENSITY_DROPLET_RADIUS("droplet_radius");
+    const std::string   FIELD_SKY_DENSITY_ICE_LEVEL("ice_level");
+
+    const F32 SLIDER_SCALE_SUN_AMBIENT(3.0f);
+    const F32 SLIDER_SCALE_BLUE_HORIZON_DENSITY(2.0f);
+    const F32 SLIDER_SCALE_GLOW_R(20.0f);
+    const F32 SLIDER_SCALE_GLOW_B(-5.0f);
+    const F32 SLIDER_SCALE_DENSITY_MULTIPLIER(0.001f);
+}
+
+static LLPanelInjector<LLPanelSettingsSkyAtmosTab> t_settings_atmos("panel_settings_atmos");
+static LLPanelInjector<LLPanelSettingsSkyCloudTab> t_settings_cloud("panel_settings_cloud");
+static LLPanelInjector<LLPanelSettingsSkySunMoonTab> t_settings_sunmoon("panel_settings_sunmoon");
+static LLPanelInjector<LLPanelSettingsSkyDensityTab> t_settings_density("panel_settings_density");
+
+//==========================================================================
+LLPanelSettingsSky::LLPanelSettingsSky() :
+    LLSettingsEditPanel(),
+    mSkySettings()
+{
+
+}
+
+
+//==========================================================================
+LLPanelSettingsSkyAtmosTab::LLPanelSettingsSkyAtmosTab() :
+    LLPanelSettingsSky()
+{
+}
+
+
+BOOL LLPanelSettingsSkyAtmosTab::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_AMBIENT_LIGHT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAmbientLightChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_BLUE_HORIZON)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onBlueHorizonChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_BLUE_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onBlueDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onHazeHorizonChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onHazeDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSceneGammaChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDensityMultipChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDistanceMultipChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMaxAltChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoistureLevelChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onDropletRadiusChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onIceLevelChanged(); });
+    refresh();
+
+    return TRUE;
+}
+
+//virtual
+void LLPanelSettingsSkyAtmosTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+
+    // Make sure we have initialized children (initialized)
+    if (getFirstChild())
+    {
+        getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setEnabled(enabled);
+    }
+}
+
+void LLPanelSettingsSkyAtmosTab::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(getCanChangeSettings());
+    setAllChildrenEnabled(getCanChangeSettings());
+
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_AMBIENT_LIGHT)->set(mSkySettings->getAmbientColor() / SLIDER_SCALE_SUN_AMBIENT);
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_HORIZON)->set(mSkySettings->getBlueHorizon() / SLIDER_SCALE_BLUE_HORIZON_DENSITY);
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_DENSITY)->set(mSkySettings->getBlueDensity() / SLIDER_SCALE_BLUE_HORIZON_DENSITY);
+
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->setValue(mSkySettings->getHazeHorizon());
+    getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->setValue(mSkySettings->getHazeDensity());
+    getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->setValue(mSkySettings->getGamma());
+    F32 density_mult = mSkySettings->getDensityMultiplier();
+    density_mult /= SLIDER_SCALE_DENSITY_MULTIPLIER;
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->setValue(density_mult);
+    getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->setValue(mSkySettings->getDistanceMultiplier());
+    getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->setValue(mSkySettings->getMaxY());
+
+    F32 moisture_level  = mSkySettings->getSkyMoistureLevel();
+    F32 droplet_radius  = mSkySettings->getSkyDropletRadius();
+    F32 ice_level       = mSkySettings->getSkyIceLevel();
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->setValue(moisture_level);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->setValue(droplet_radius);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->setValue(ice_level);
+}
+
+//-------------------------------------------------------------------------
+void LLPanelSettingsSkyAtmosTab::onAmbientLightChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setAmbientColor(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_AMBIENT_LIGHT)->get() * SLIDER_SCALE_SUN_AMBIENT));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onBlueHorizonChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setBlueHorizon(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_HORIZON)->get() * SLIDER_SCALE_BLUE_HORIZON_DENSITY));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onBlueDensityChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setBlueDensity(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_BLUE_DENSITY)->get() * SLIDER_SCALE_BLUE_HORIZON_DENSITY));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onHazeHorizonChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setHazeHorizon(getChild<LLUICtrl>(FIELD_SKY_HAZE_HORIZON)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onHazeDensityChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setHazeDensity(getChild<LLUICtrl>(FIELD_SKY_HAZE_DENSITY)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onSceneGammaChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setGamma(getChild<LLUICtrl>(FIELD_SKY_SCENE_GAMMA)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onDensityMultipChanged()
+{
+    if (!mSkySettings) return;
+    F32 density_mult = getChild<LLUICtrl>(FIELD_SKY_DENSITY_MULTIP)->getValue().asReal();
+    density_mult *= SLIDER_SCALE_DENSITY_MULTIPLIER;
+    mSkySettings->setDensityMultiplier(density_mult);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onDistanceMultipChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setDistanceMultiplier(getChild<LLUICtrl>(FIELD_SKY_DISTANCE_MULTIP)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onMaxAltChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setMaxY(getChild<LLUICtrl>(FIELD_SKY_MAX_ALT)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onMoistureLevelChanged()
+{
+    if (!mSkySettings) return;
+    F32 moisture_level  = getChild<LLUICtrl>(FIELD_SKY_DENSITY_MOISTURE_LEVEL)->getValue().asReal();
+    mSkySettings->setSkyMoistureLevel(moisture_level);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onDropletRadiusChanged()
+{
+    if (!mSkySettings) return;
+    F32 droplet_radius = getChild<LLUICtrl>(FIELD_SKY_DENSITY_DROPLET_RADIUS)->getValue().asReal();
+    mSkySettings->setSkyDropletRadius(droplet_radius);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyAtmosTab::onIceLevelChanged()
+{
+    if (!mSkySettings) return;
+    F32 ice_level = getChild<LLUICtrl>(FIELD_SKY_DENSITY_ICE_LEVEL)->getValue().asReal();
+    mSkySettings->setSkyIceLevel(ice_level);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+//==========================================================================
+LLPanelSettingsSkyCloudTab::LLPanelSettingsSkyCloudTab() :
+    LLPanelSettingsSky()
+{
+}
+
+BOOL LLPanelSettingsSkyCloudTab::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COLOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudColorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudCoverageChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_VARIANCE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudVarianceChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCROLL_XY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudScrollChanged(); });
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudMapChanged(); });
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setDefaultImageAssetID(LLSettingsSky::GetDefaultCloudNoiseTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setAllowNoTexture(TRUE);
+
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_X)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_Y)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_D)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDensityChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_X)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDetailChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_Y)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDetailChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_D)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onCloudDetailChanged(); });
+
+    refresh();
+
+    return TRUE;
+}
+
+//virtual
+void LLPanelSettingsSkyCloudTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+
+    // Make sure we have children (initialized)
+    if (getFirstChild())
+    {
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_VARIANCE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_X)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_Y)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_D)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_X)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_Y)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_D)->setEnabled(enabled);
+    }
+}
+
+void LLPanelSettingsSkyCloudTab::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(getCanChangeSettings());
+    setAllChildrenEnabled(getCanChangeSettings());
+
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_CLOUD_COLOR)->set(mSkySettings->getCloudColor());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->setValue(mSkySettings->getCloudShadow());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->setValue(mSkySettings->getCloudScale());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_VARIANCE)->setValue(mSkySettings->getCloudVariance());
+
+    LLVector2 cloudScroll(mSkySettings->getCloudScrollRate());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCROLL_XY)->setValue(cloudScroll.getValue());
+
+    getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP)->setValue(mSkySettings->getCloudNoiseTextureId());
+
+    LLVector3 cloudDensity(mSkySettings->getCloudPosDensity1().getValue());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_X)->setValue(cloudDensity[0]);
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_Y)->setValue(cloudDensity[1]);
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_D)->setValue(cloudDensity[2]);
+
+    LLVector3 cloudDetail(mSkySettings->getCloudPosDensity2().getValue());
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_X)->setValue(cloudDetail[0]);
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_Y)->setValue(cloudDetail[1]);
+    getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_D)->setValue(cloudDetail[2]);
+}
+
+//-------------------------------------------------------------------------
+void LLPanelSettingsSkyCloudTab::onCloudColorChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setCloudColor(LLColor3(getChild<LLColorSwatchCtrl>(FIELD_SKY_CLOUD_COLOR)->get()));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudCoverageChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setCloudShadow(getChild<LLUICtrl>(FIELD_SKY_CLOUD_COVERAGE)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudScaleChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setCloudScale(getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCALE)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudVarianceChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setCloudVariance(getChild<LLUICtrl>(FIELD_SKY_CLOUD_VARIANCE)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudScrollChanged()
+{
+    if (!mSkySettings) return;
+    LLVector2 scroll(getChild<LLUICtrl>(FIELD_SKY_CLOUD_SCROLL_XY)->getValue());
+    mSkySettings->setCloudScrollRate(scroll);
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudMapChanged()
+{
+    if (!mSkySettings) return;
+    LLTextureCtrl* ctrl = getChild<LLTextureCtrl>(FIELD_SKY_CLOUD_MAP);
+    mSkySettings->setCloudNoiseTextureId(ctrl->getValue().asUUID());
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudDensityChanged()
+{
+    if (!mSkySettings) return;
+    LLColor3 density(getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_X)->getValue().asReal(), 
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_Y)->getValue().asReal(), 
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DENSITY_D)->getValue().asReal());
+    
+    mSkySettings->setCloudPosDensity1(density);
+    setIsDirty();
+}
+
+void LLPanelSettingsSkyCloudTab::onCloudDetailChanged()
+{
+    if (!mSkySettings) return;
+    LLColor3 detail(getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_X)->getValue().asReal(),
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_Y)->getValue().asReal(),
+        getChild<LLUICtrl>(FIELD_SKY_CLOUD_DETAIL_D)->getValue().asReal());
+
+    mSkySettings->setCloudPosDensity2(detail);
+    setIsDirty();
+}
+
+//==========================================================================
+LLPanelSettingsSkySunMoonTab::LLPanelSettingsSkySunMoonTab() :
+    LLPanelSettingsSky()
+{
+}
+
+
+BOOL LLPanelSettingsSkySunMoonTab::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_SUN_MOON_COLOR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunMoonColorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onGlowChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onStarBrightnessChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunImageChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSunScaleChanged(); });
+    getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetBlankSunTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetBlankSunTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setAllowNoTexture(TRUE);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_ROTATION)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonRotationChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_IMAGE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonImageChanged(); });
+    getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setDefaultImageAssetID(LLSettingsSky::GetDefaultMoonTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setBlankImageAssetID(LLSettingsSky::GetDefaultMoonTextureId());
+    getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setAllowNoTexture(TRUE);
+    getChild<LLUICtrl>(FIELD_SKY_MOON_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_MOON_BRIGHTNESS)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMoonBrightnessChanged(); });
+
+    refresh();
+
+    return TRUE;
+}
+
+//virtual
+void LLPanelSettingsSkySunMoonTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+
+    // Make sure we have children
+    if (getFirstChild())
+    {
+        getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_MOON_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_MOON_BRIGHTNESS)->setEnabled(enabled);
+        getChildView(PANEL_SKY_SUN_LAYOUT)->setAllChildrenEnabled(TRUE);
+        getChildView(PANEL_SKY_MOON_LAYOUT)->setAllChildrenEnabled(TRUE);
+    }
+}
+
+void LLPanelSettingsSkySunMoonTab::refresh()
+{
+    if (!mSkySettings || !getCanChangeSettings())
+    {
+        getChildView(PANEL_SKY_SUN_LAYOUT)->setAllChildrenEnabled(FALSE);
+        getChildView(PANEL_SKY_MOON_LAYOUT)->setAllChildrenEnabled(FALSE);
+        getChildView(FIELD_SKY_SUN_BEACON)->setEnabled(TRUE);
+        getChildView(FIELD_SKY_MOON_BEACON)->setEnabled(TRUE);
+        
+        if (!mSkySettings)
+            return;
+    }
+    else
+    {
+        setEnabled(TRUE);
+        setAllChildrenEnabled(TRUE);
+    }
+
+    getChild<LLColorSwatchCtrl>(FIELD_SKY_SUN_MOON_COLOR)->set(mSkySettings->getSunlightColor() / SLIDER_SCALE_SUN_AMBIENT);
+
+    LLColor3 glow(mSkySettings->getGlow());
+    
+    // takes 40 - 0.2 range -> 0 - 1.99 UI range
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->setValue(2.0 - (glow.mV[0] / SLIDER_SCALE_GLOW_R));
+    getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->setValue(glow.mV[2] / SLIDER_SCALE_GLOW_B);
+
+    getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->setValue(mSkySettings->getStarBrightness());
+    getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->setRotation(mSkySettings->getSunRotation());
+    getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->setValue(mSkySettings->getSunTextureId());
+    getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->setValue(mSkySettings->getSunScale());
+    getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->setRotation(mSkySettings->getMoonRotation());
+    getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->setValue(mSkySettings->getMoonTextureId());
+    getChild<LLUICtrl>(FIELD_SKY_MOON_SCALE)->setValue(mSkySettings->getMoonScale());
+    getChild<LLUICtrl>(FIELD_SKY_MOON_BRIGHTNESS)->setValue(mSkySettings->getMoonBrightness());
+}
+
+//-------------------------------------------------------------------------
+void LLPanelSettingsSkySunMoonTab::onSunMoonColorChanged()
+{
+    if (!mSkySettings) return;
+    LLColor3 color(getChild<LLColorSwatchCtrl>(FIELD_SKY_SUN_MOON_COLOR)->get());
+
+    color *= SLIDER_SCALE_SUN_AMBIENT;
+
+    mSkySettings->setSunlightColor(color);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onGlowChanged()
+{
+    if (!mSkySettings) return;
+    LLColor3 glow(getChild<LLUICtrl>(FIELD_SKY_GLOW_SIZE)->getValue().asReal(), 0.0f, getChild<LLUICtrl>(FIELD_SKY_GLOW_FOCUS)->getValue().asReal());
+
+    // takes 0 - 1.99 UI range -> 40 -> 0.2 range
+    glow.mV[0] = (2.0f - glow.mV[0]) * SLIDER_SCALE_GLOW_R; 
+    glow.mV[2] *= SLIDER_SCALE_GLOW_B;
+
+    mSkySettings->setGlow(glow);
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onStarBrightnessChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setStarBrightness(getChild<LLUICtrl>(FIELD_SKY_STAR_BRIGHTNESS)->getValue().asReal());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onSunRotationChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setSunRotation(getChild<LLVirtualTrackball>(FIELD_SKY_SUN_ROTATION)->getRotation());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onSunScaleChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setSunScale((getChild<LLUICtrl>(FIELD_SKY_SUN_SCALE)->getValue().asReal()));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onSunImageChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setSunTextureId(getChild<LLTextureCtrl>(FIELD_SKY_SUN_IMAGE)->getValue().asUUID());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onMoonRotationChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setMoonRotation(getChild<LLVirtualTrackball>(FIELD_SKY_MOON_ROTATION)->getRotation());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onMoonImageChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setMoonTextureId(getChild<LLTextureCtrl>(FIELD_SKY_MOON_IMAGE)->getValue().asUUID());
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onMoonScaleChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setMoonScale((getChild<LLUICtrl>(FIELD_SKY_MOON_SCALE)->getValue().asReal()));
+    mSkySettings->update();
+    setIsDirty();
+}
+
+void LLPanelSettingsSkySunMoonTab::onMoonBrightnessChanged()
+{
+    if (!mSkySettings) return;
+    mSkySettings->setMoonBrightness((getChild<LLUICtrl>(FIELD_SKY_MOON_BRIGHTNESS)->getValue().asReal()));
+    mSkySettings->update();
+    setIsDirty();
+}
+ 
+LLPanelSettingsSkyDensityTab::LLPanelSettingsSkyDensityTab()
+{    
+}
+
+BOOL LLPanelSettingsSkyDensityTab::postBuild()
+{
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onRayleighExponentialChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onRayleighExponentialScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_LINEAR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onRayleighLinearChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_CONSTANT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onRayleighConstantChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onRayleighMaxAltitudeChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieExponentialChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieExponentialScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_LINEAR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieLinearChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_CONSTANT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieConstantChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_ANISO)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieAnisoFactorChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onMieMaxAltitudeChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionExponentialChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionExponentialScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionLinearChanged(); });
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionConstantChanged(); });
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onAbsorptionMaxAltitudeChanged(); });
+
+    refresh();
+    return TRUE;
+}
+
+void LLPanelSettingsSkyDensityTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsSky::setEnabled(enabled);
+
+    // Make sure we have children
+    if (getFirstChild())
+    {
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_LINEAR)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_CONSTANT)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_MAX_ALTITUDE)->setEnabled(enabled);
+
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_LINEAR)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_CONSTANT)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_ANISO)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_MAX_ALTITUDE)->setEnabled(enabled);
+
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL_SCALE)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->setEnabled(enabled);
+        getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setEnabled(enabled);
+    }
+}
+
+void LLPanelSettingsSkyDensityTab::refresh()
+{
+    if (!mSkySettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(getCanChangeSettings());
+    setAllChildrenEnabled(getCanChangeSettings());
+
+    // Get first (only) profile layer of each type for editing
+    LLSD rayleigh_config    = mSkySettings->getRayleighConfig();
+    LLSD mie_config         = mSkySettings->getMieConfig();
+    LLSD absorption_config  = mSkySettings->getAbsorptionConfig();
+
+    F32 rayleigh_exponential_term    = rayleigh_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();
+    F32 rayleigh_exponential_scale   = rayleigh_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR].asReal();
+    F32 rayleigh_linear_term         = rayleigh_config[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM].asReal();
+    F32 rayleigh_constant_term       = rayleigh_config[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM].asReal();
+    F32 rayleigh_max_alt             = rayleigh_config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal();
+
+    F32 mie_exponential_term         = mie_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();
+    F32 mie_exponential_scale        = mie_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR].asReal();
+    F32 mie_linear_term              = mie_config[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM].asReal();
+    F32 mie_constant_term            = mie_config[LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM].asReal();
+    F32 mie_aniso_factor             = mie_config[LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR].asReal();
+    F32 mie_max_alt                  = mie_config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal();
+
+    F32 absorption_exponential_term  = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();
+    F32 absorption_exponential_scale = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR].asReal();
+    F32 absorption_linear_term       = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM].asReal();
+    F32 absorption_constant_term     = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM].asReal();
+    F32 absorption_max_alt           = absorption_config[LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH].asReal();
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL)->setValue(rayleigh_exponential_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE)->setValue(rayleigh_exponential_scale);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_LINEAR)->setValue(rayleigh_linear_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_CONSTANT)->setValue(rayleigh_constant_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_RAYLEIGH_MAX_ALTITUDE)->setValue(rayleigh_max_alt);
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL)->setValue(mie_exponential_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL_SCALE)->setValue(mie_exponential_scale);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_LINEAR)->setValue(mie_linear_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_CONSTANT)->setValue(mie_constant_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_ANISO)->setValue(mie_aniso_factor);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_MIE_MAX_ALTITUDE)->setValue(mie_max_alt);
+
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL)->setValue(absorption_exponential_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL_SCALE)->setValue(absorption_exponential_scale);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->setValue(absorption_linear_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->setValue(absorption_constant_term);
+    getChild<LLUICtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->setValue(absorption_max_alt);
+}
+
+void LLPanelSettingsSkyDensityTab::updateProfile()
+{
+    F32 rayleigh_exponential_term    = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL)->getValueF32();
+    F32 rayleigh_exponential_scale   = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_RAYLEIGH_EXPONENTIAL_SCALE)->getValueF32();
+    F32 rayleigh_linear_term         = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_RAYLEIGH_LINEAR)->getValueF32();
+    F32 rayleigh_constant_term       = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_RAYLEIGH_CONSTANT)->getValueF32();
+    F32 rayleigh_max_alt             = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_RAYLEIGH_MAX_ALTITUDE)->getValueF32();
+
+    F32 mie_exponential_term         = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL)->getValueF32();
+    F32 mie_exponential_scale        = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_EXPONENTIAL_SCALE)->getValueF32();
+    F32 mie_linear_term              = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_LINEAR)->getValueF32();
+    F32 mie_constant_term            = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_CONSTANT)->getValueF32();
+    F32 mie_aniso_factor             = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_ANISO)->getValueF32();
+    F32 mie_max_alt                  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_MIE_MAX_ALTITUDE)->getValueF32();
+
+    F32 absorption_exponential_term  = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL)->getValueF32();
+    F32 absorption_exponential_scale = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ABSORPTION_EXPONENTIAL_SCALE)->getValueF32();
+    F32 absorption_linear_term       = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ABSORPTION_LINEAR)->getValueF32();
+    F32 absorption_constant_term     = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ABSORPTION_CONSTANT)->getValueF32();
+    F32 absorption_max_alt           = getChild<LLSliderCtrl>(FIELD_SKY_DENSITY_ABSORPTION_MAX_ALTITUDE)->getValueF32();
+
+    LLSD rayleigh_config    = LLSettingsSky::createSingleLayerDensityProfile(rayleigh_max_alt, rayleigh_exponential_term, rayleigh_exponential_scale, rayleigh_linear_term, rayleigh_constant_term);
+    LLSD mie_config         = LLSettingsSky::createSingleLayerDensityProfile(mie_max_alt, mie_exponential_term, mie_exponential_scale, mie_linear_term, mie_constant_term, mie_aniso_factor);
+    LLSD absorption_layer   = LLSettingsSky::createSingleLayerDensityProfile(absorption_max_alt, absorption_exponential_term, absorption_exponential_scale, absorption_linear_term, absorption_constant_term);
+
+    static LLSD absorption_layer_ozone = LLSettingsSky::createDensityProfileLayer(0.0f, 0.0f, 0.0f, -1.0f / 15000.0f, 8.0f / 3.0f);
+
+    LLSD absorption_config;
+    absorption_config.append(absorption_layer);
+    absorption_config.append(absorption_layer_ozone);
+
+    mSkySettings->setRayleighConfigs(rayleigh_config);
+    mSkySettings->setMieConfigs(mie_config);
+    mSkySettings->setAbsorptionConfigs(absorption_config);
+    mSkySettings->update();
+    setIsDirty();
+
+    if (gAtmosphere)
+    {
+        AtmosphericModelSettings atmospheric_settings;
+        LLEnvironment::getAtmosphericModelSettings(atmospheric_settings, mSkySettings);
+        gAtmosphere->configureAtmosphericModel(atmospheric_settings);
+    }
+}
+
+void LLPanelSettingsSkyDensityTab::onRayleighExponentialChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onRayleighExponentialScaleChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onRayleighLinearChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onRayleighConstantChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onRayleighMaxAltitudeChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieExponentialChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieExponentialScaleChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieLinearChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieConstantChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieAnisoFactorChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onMieMaxAltitudeChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onAbsorptionExponentialChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onAbsorptionExponentialScaleChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onAbsorptionLinearChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onAbsorptionConstantChanged()
+{
+    updateProfile();
+}
+
+void LLPanelSettingsSkyDensityTab::onAbsorptionMaxAltitudeChanged()
+{
+    updateProfile();
+}
diff --git a/indra/newview/llpaneleditsky.h b/indra/newview/llpaneleditsky.h
new file mode 100644
index 0000000000000000000000000000000000000000..c02c9c95a0c2cc8a84c68e7a05a35a67de5cd1c8
--- /dev/null
+++ b/indra/newview/llpaneleditsky.h
@@ -0,0 +1,171 @@
+/**
+* @file llpaneleditsky.h
+* @brief Panels for sky settings
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#ifndef LLPANEL_EDIT_SKY_H
+#define LLPANEL_EDIT_SKY_H
+
+#include "llpanel.h"
+#include "llsettingssky.h"
+#include "llfloaterfixedenvironment.h"
+
+//=========================================================================
+class LLSlider;
+class LLColorSwatchCtrl;
+class LLTextureCtrl;
+
+//=========================================================================
+class LLPanelSettingsSky : public LLSettingsEditPanel
+{
+    LOG_CLASS(LLPanelSettingsSky);
+
+public:
+                            LLPanelSettingsSky();
+
+    virtual void            setSettings(const LLSettingsBase::ptr_t &settings) override   { setSky(std::static_pointer_cast<LLSettingsSky>(settings)); }
+
+    LLSettingsSky::ptr_t    getSky() const                                          { return mSkySettings; }
+    void                    setSky(const LLSettingsSky::ptr_t &sky)                 { mSkySettings = sky; clearIsDirty(); refresh(); }
+
+protected:
+    LLSettingsSky::ptr_t  mSkySettings;
+};
+
+class LLPanelSettingsSkyAtmosTab : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsSkyAtmosTab);
+
+public:
+                            LLPanelSettingsSkyAtmosTab();
+
+    virtual BOOL	        postBuild() override;
+    virtual void	        setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void            refresh() override;
+
+private:
+    void                    onAmbientLightChanged();
+    void                    onBlueHorizonChanged();
+    void                    onBlueDensityChanged();
+    void                    onHazeHorizonChanged();
+    void                    onHazeDensityChanged();
+    void                    onSceneGammaChanged();
+    void                    onDensityMultipChanged();
+    void                    onDistanceMultipChanged();
+    void                    onMaxAltChanged();
+    void                    onMoistureLevelChanged();
+    void                    onDropletRadiusChanged();
+    void                    onIceLevelChanged();
+
+};
+
+class LLPanelSettingsSkyCloudTab : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsSkyCloudTab);
+
+public:
+                            LLPanelSettingsSkyCloudTab();
+
+    virtual BOOL	        postBuild() override;
+    void	                setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void            refresh() override;
+
+private:
+    void                    onCloudColorChanged();
+    void                    onCloudCoverageChanged();
+    void                    onCloudScaleChanged();
+    void                    onCloudVarianceChanged();
+    void                    onCloudScrollChanged();
+    void                    onCloudMapChanged();
+    void                    onCloudDensityChanged();
+    void                    onCloudDetailChanged();
+};
+
+class LLPanelSettingsSkySunMoonTab : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsSkySunMoonTab);
+
+public:
+                            LLPanelSettingsSkySunMoonTab();
+
+    virtual BOOL	        postBuild() override;
+    virtual void	        setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void            refresh() override;
+
+private:
+    void                    onSunMoonColorChanged();
+    void                    onGlowChanged();
+    void                    onStarBrightnessChanged();
+    void                    onSunRotationChanged();
+    void                    onSunScaleChanged();
+    void                    onSunImageChanged();
+    void                    onMoonRotationChanged();
+    void                    onMoonScaleChanged();
+    void                    onMoonBrightnessChanged();
+    void                    onMoonImageChanged();
+};
+
+// single subtab of the density settings tab
+class LLPanelSettingsSkyDensityTab : public LLPanelSettingsSky
+{
+    LOG_CLASS(LLPanelSettingsSkyDensityTab);
+
+public:
+    LLPanelSettingsSkyDensityTab();
+
+    virtual BOOL postBuild() override;
+    virtual void setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void refresh() override;
+
+    void onRayleighExponentialChanged();
+    void onRayleighExponentialScaleChanged();
+    void onRayleighLinearChanged();
+    void onRayleighConstantChanged();
+    void onRayleighMaxAltitudeChanged();
+
+    void onMieExponentialChanged();
+    void onMieExponentialScaleChanged();
+    void onMieLinearChanged();
+    void onMieConstantChanged();
+    void onMieAnisoFactorChanged();
+    void onMieMaxAltitudeChanged();
+
+    void onAbsorptionExponentialChanged();
+    void onAbsorptionExponentialScaleChanged();
+    void onAbsorptionLinearChanged();
+    void onAbsorptionConstantChanged();
+    void onAbsorptionMaxAltitudeChanged();
+
+    // update the settings for our profile type
+    void updateProfile();
+};
+#endif // LLPANEL_EDIT_SKY_H
diff --git a/indra/newview/llpaneleditwater.cpp b/indra/newview/llpaneleditwater.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a09964e17dcb0290f743eb0d4bc9588e783a4a7e
--- /dev/null
+++ b/indra/newview/llpaneleditwater.cpp
@@ -0,0 +1,251 @@
+/**
+* @file llpaneleditwater.cpp
+* @brief Floaters to create and edit fixed settings for sky and water.
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneleditwater.h"
+
+#include "llslider.h"
+#include "lltexturectrl.h"
+#include "llcolorswatch.h"
+#include "llxyvector.h"
+#include "llviewercontrol.h"
+
+namespace
+{
+    const std::string   FIELD_WATER_FOG_COLOR("water_fog_color");
+    const std::string   FIELD_WATER_FOG_DENSITY("water_fog_density");
+    const std::string   FIELD_WATER_UNDERWATER_MOD("water_underwater_mod");
+    const std::string   FIELD_WATER_NORMAL_MAP("water_normal_map");
+
+    const std::string   FIELD_WATER_WAVE1_XY("water_wave1_xy");
+    const std::string   FIELD_WATER_WAVE2_XY("water_wave2_xy");
+
+    const std::string   FIELD_WATER_NORMAL_SCALE_X("water_normal_scale_x");
+    const std::string   FIELD_WATER_NORMAL_SCALE_Y("water_normal_scale_y");
+    const std::string   FIELD_WATER_NORMAL_SCALE_Z("water_normal_scale_z");
+
+    const std::string   FIELD_WATER_FRESNEL_SCALE("water_fresnel_scale");
+    const std::string   FIELD_WATER_FRESNEL_OFFSET("water_fresnel_offset");
+
+    const std::string   FIELD_WATER_SCALE_ABOVE("water_scale_above");
+    const std::string   FIELD_WATER_SCALE_BELOW("water_scale_below");
+    const std::string   FIELD_WATER_BLUR_MULTIP("water_blur_multip");
+}
+
+static LLPanelInjector<LLPanelSettingsWaterMainTab> t_settings_water("panel_settings_water");
+
+//==========================================================================
+LLPanelSettingsWater::LLPanelSettingsWater() :
+    LLSettingsEditPanel(),
+    mWaterSettings()
+{
+
+}
+
+
+//==========================================================================
+LLPanelSettingsWaterMainTab::LLPanelSettingsWaterMainTab():
+    LLPanelSettingsWater(),
+    mClrFogColor(nullptr),
+    mTxtNormalMap(nullptr)
+{
+}
+
+
+BOOL LLPanelSettingsWaterMainTab::postBuild()
+{
+    mClrFogColor = getChild<LLColorSwatchCtrl>(FIELD_WATER_FOG_COLOR);
+    mTxtNormalMap = getChild<LLTextureCtrl>(FIELD_WATER_NORMAL_MAP);
+
+    getChild<LLXYVector>(FIELD_WATER_WAVE1_XY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onLargeWaveChanged(); });
+
+    mClrFogColor->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFogColorChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFogDensityChanged(); });
+//    getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFogDensityChanged(getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->getValue().asReal()); });
+    getChild<LLUICtrl>(FIELD_WATER_UNDERWATER_MOD)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFogUnderWaterChanged(); });
+
+    mTxtNormalMap->setDefaultImageAssetID(LLSettingsWater::GetDefaultWaterNormalAssetId());
+    mTxtNormalMap->setBlankImageAssetID(LLUUID( gSavedSettings.getString( "DefaultBlankNormalTexture" )));
+    mTxtNormalMap->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNormalMapChanged(); });
+
+    getChild<LLUICtrl>(FIELD_WATER_WAVE2_XY)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onSmallWaveChanged(); });
+
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_X)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNormalScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Y)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNormalScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Z)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onNormalScaleChanged(); });
+
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_SCALE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFresnelScaleChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_OFFSET)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onFresnelOffsetChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_ABOVE)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onScaleAboveChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_BELOW)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onScaleBelowChanged(); });
+    getChild<LLUICtrl>(FIELD_WATER_BLUR_MULTIP)->setCommitCallback([this](LLUICtrl *, const LLSD &) { onBlurMultipChanged(); });
+
+    refresh();
+
+    return TRUE;
+}
+
+//virtual
+void LLPanelSettingsWaterMainTab::setEnabled(BOOL enabled)
+{
+    LLPanelSettingsWater::setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_UNDERWATER_MOD)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_SCALE)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_OFFSET)->setEnabled(enabled);
+
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_X)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Y)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Z)->setEnabled(enabled);
+
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_ABOVE)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_BELOW)->setEnabled(enabled);
+    getChild<LLUICtrl>(FIELD_WATER_BLUR_MULTIP)->setEnabled(enabled);
+}
+
+//==========================================================================
+void LLPanelSettingsWaterMainTab::refresh()
+{
+    if (!mWaterSettings)
+    {
+        setAllChildrenEnabled(FALSE);
+        setEnabled(FALSE);
+        return;
+    }
+
+    setEnabled(getCanChangeSettings());
+    setAllChildrenEnabled(getCanChangeSettings());
+    mClrFogColor->set(mWaterSettings->getWaterFogColor());
+    getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->setValue(mWaterSettings->getWaterFogDensity());
+    getChild<LLUICtrl>(FIELD_WATER_UNDERWATER_MOD)->setValue(mWaterSettings->getFogMod());
+    mTxtNormalMap->setValue(mWaterSettings->getNormalMapID());
+    LLVector2 vect2 = mWaterSettings->getWave1Dir() * -1.0; // Flip so that north and east are +
+    getChild<LLUICtrl>(FIELD_WATER_WAVE1_XY)->setValue(vect2.getValue());
+    vect2 = mWaterSettings->getWave2Dir() * -1.0; // Flip so that north and east are +
+    getChild<LLUICtrl>(FIELD_WATER_WAVE2_XY)->setValue(vect2.getValue());
+    LLVector3 vect3 = mWaterSettings->getNormalScale();
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_X)->setValue(vect3[0]);
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Y)->setValue(vect3[1]);
+    getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Z)->setValue(vect3[2]);
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_SCALE)->setValue(mWaterSettings->getFresnelScale());
+    getChild<LLUICtrl>(FIELD_WATER_FRESNEL_OFFSET)->setValue(mWaterSettings->getFresnelOffset());
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_ABOVE)->setValue(mWaterSettings->getScaleAbove());
+    getChild<LLUICtrl>(FIELD_WATER_SCALE_BELOW)->setValue(mWaterSettings->getScaleBelow());
+    getChild<LLUICtrl>(FIELD_WATER_BLUR_MULTIP)->setValue(mWaterSettings->getBlurMultiplier());
+}
+
+//==========================================================================
+
+void LLPanelSettingsWaterMainTab::onFogColorChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setWaterFogColor(LLColor3(mClrFogColor->get()));
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onFogDensityChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setWaterFogDensity(getChild<LLUICtrl>(FIELD_WATER_FOG_DENSITY)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onFogUnderWaterChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setFogMod(getChild<LLUICtrl>(FIELD_WATER_UNDERWATER_MOD)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onNormalMapChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setNormalMapID(mTxtNormalMap->getImageAssetID());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onLargeWaveChanged()
+{
+    if (!mWaterSettings) return;
+    LLVector2 vect(getChild<LLUICtrl>(FIELD_WATER_WAVE1_XY)->getValue());
+    vect *= -1.0; // Flip so that north and east are -
+    mWaterSettings->setWave1Dir(vect);
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onSmallWaveChanged()
+{
+    if (!mWaterSettings) return;
+    LLVector2 vect(getChild<LLUICtrl>(FIELD_WATER_WAVE2_XY)->getValue());
+    vect *= -1.0; // Flip so that north and east are -
+    mWaterSettings->setWave2Dir(vect);
+    setIsDirty();
+}
+
+
+void LLPanelSettingsWaterMainTab::onNormalScaleChanged()
+{
+    if (!mWaterSettings) return;
+    LLVector3 vect(getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_X)->getValue().asReal(), getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Y)->getValue().asReal(), getChild<LLUICtrl>(FIELD_WATER_NORMAL_SCALE_Z)->getValue().asReal());
+    mWaterSettings->setNormalScale(vect);
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onFresnelScaleChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setFresnelScale(getChild<LLUICtrl>(FIELD_WATER_FRESNEL_SCALE)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onFresnelOffsetChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setFresnelOffset(getChild<LLUICtrl>(FIELD_WATER_FRESNEL_OFFSET)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onScaleAboveChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setScaleAbove(getChild<LLUICtrl>(FIELD_WATER_SCALE_ABOVE)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onScaleBelowChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setScaleBelow(getChild<LLUICtrl>(FIELD_WATER_SCALE_BELOW)->getValue().asReal());
+    setIsDirty();
+}
+
+void LLPanelSettingsWaterMainTab::onBlurMultipChanged()
+{
+    if (!mWaterSettings) return;
+    mWaterSettings->setBlurMultiplier(getChild<LLUICtrl>(FIELD_WATER_BLUR_MULTIP)->getValue().asReal());
+    setIsDirty();
+}
diff --git a/indra/newview/llpaneleditwater.h b/indra/newview/llpaneleditwater.h
new file mode 100644
index 0000000000000000000000000000000000000000..ab2dc47bccb96ed528c99cb1af3c3d80f8b66fbc
--- /dev/null
+++ b/indra/newview/llpaneleditwater.h
@@ -0,0 +1,98 @@
+/**
+* @file llpaneleditwater.h
+* @brief Panels for water settings
+*
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2011, 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$
+*/
+
+#ifndef LLPANEL_EDIT_WATER_H
+#define LLPANEL_EDIT_WATER_H
+
+#include "llpanel.h"
+#include "llsettingswater.h"
+
+#include "llfloaterfixedenvironment.h"
+
+//=========================================================================
+class LLSlider;
+class LLColorSwatchCtrl;
+class LLTextureCtrl;
+class LLXYVector;
+
+//=========================================================================
+class LLPanelSettingsWater : public LLSettingsEditPanel
+{
+    LOG_CLASS(LLPanelSettingsWater);
+
+public:
+                            LLPanelSettingsWater();
+
+    virtual void            setSettings(const LLSettingsBase::ptr_t &settings) override   { setWater(std::static_pointer_cast<LLSettingsWater>(settings)); }
+
+    LLSettingsWater::ptr_t  getWater() const                                        { return mWaterSettings; }
+    void                    setWater(const LLSettingsWater::ptr_t &water)           { mWaterSettings = water; clearIsDirty(); refresh(); }
+
+protected:
+    LLSettingsWater::ptr_t  mWaterSettings;
+};
+
+// *RIDER* In this case this split is unecessary since there is only a single 
+// tab page for water settings at this point.  However more may be added in the 
+// future and I want to reinforce the pattern used for sky/atmosphere tabs.
+class LLPanelSettingsWaterMainTab : public LLPanelSettingsWater
+{
+    LOG_CLASS(LLPanelSettingsWaterMainTab);
+
+public:
+                            LLPanelSettingsWaterMainTab();
+
+    virtual BOOL	        postBuild() override;
+    virtual void	        setEnabled(BOOL enabled) override;
+
+protected:
+    virtual void            refresh() override;
+
+private:
+
+    LLColorSwatchCtrl *     mClrFogColor;
+//     LLSlider *              mSldFogDensity;
+//     LLSlider *              mSldUnderWaterMod;
+    LLTextureCtrl *         mTxtNormalMap;
+
+    void                    onFogColorChanged();
+    void                    onFogDensityChanged();
+    void                    onFogUnderWaterChanged();
+    void                    onNormalMapChanged();
+
+    void                    onLargeWaveChanged();
+    void                    onSmallWaveChanged();
+
+    void                    onNormalScaleChanged();
+    void                    onFresnelScaleChanged();
+    void                    onFresnelOffsetChanged();
+    void                    onScaleAboveChanged();
+    void                    onScaleBelowChanged();
+    void                    onBlurMultipChanged();
+};
+
+
+#endif // LLPANEL_EDIT_WATER_H
diff --git a/indra/newview/llpanelenvironment.cpp b/indra/newview/llpanelenvironment.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2ad7a23278d4cf6d4d5fc0c5f38c014bef71654c
--- /dev/null
+++ b/indra/newview/llpanelenvironment.cpp
@@ -0,0 +1,1178 @@
+/** 
+ * @file llpanelenvironment.cpp
+ * @brief LLPanelExperiences class implementation
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+
+#include "llpanelprofile.h"
+#include "lluictrlfactory.h"
+#include "llexperiencecache.h"
+#include "llagent.h"
+#include "llparcel.h"
+
+#include "llviewerregion.h"
+#include "llpanelenvironment.h"
+#include "llslurl.h"
+#include "lllayoutstack.h"
+
+#include "llfloater.h"
+#include "llfloaterreg.h"
+#include "llfloatereditextdaycycle.h"
+#include "llmultisliderctrl.h"
+#include "llnotificationsutil.h"
+#include "llsettingsvo.h"
+
+#include "llappviewer.h"
+#include "llcallbacklist.h"
+#include "llviewerparcelmgr.h"
+
+#include "llinventorymodel.h"
+
+//=========================================================================
+namespace 
+{
+    const std::string FLOATER_DAY_CYCLE_EDIT("env_edit_extdaycycle");
+    const std::string STRING_REGION_ENV("str_region_env");
+    const std::string STRING_EMPTY_NAME("str_empty");
+
+    inline bool ends_with(std::string const & value, std::string const & ending)
+    {
+        if (ending.size() > value.size())
+            return false;
+        return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+    }
+
+}
+
+//=========================================================================
+const std::string LLPanelEnvironmentInfo::BTN_SELECTINV("btn_select_inventory");
+const std::string LLPanelEnvironmentInfo::BTN_EDIT("btn_edit");
+const std::string LLPanelEnvironmentInfo::BTN_USEDEFAULT("btn_usedefault");
+const std::string LLPanelEnvironmentInfo::BTN_RST_ALTITUDES("btn_rst_altitudes");
+const std::string LLPanelEnvironmentInfo::SLD_DAYLENGTH("sld_day_length");
+const std::string LLPanelEnvironmentInfo::SLD_DAYOFFSET("sld_day_offset");
+const std::string LLPanelEnvironmentInfo::SLD_ALTITUDES("sld_altitudes");
+const std::string LLPanelEnvironmentInfo::ICN_GROUND("icon_ground");
+const std::string LLPanelEnvironmentInfo::ICN_WATER("icon_water");
+const std::string LLPanelEnvironmentInfo::CHK_ALLOWOVERRIDE("chk_allow_override");
+const std::string LLPanelEnvironmentInfo::LBL_TIMEOFDAY("lbl_apparent_time");
+const std::string LLPanelEnvironmentInfo::PNL_SETTINGS("pnl_environment_config");
+const std::string LLPanelEnvironmentInfo::PNL_ENVIRONMENT_ALTITUDES("pnl_environment_altitudes");
+const std::string LLPanelEnvironmentInfo::PNL_BUTTONS("pnl_environment_buttons");
+const std::string LLPanelEnvironmentInfo::PNL_DISABLED("pnl_environment_disabled");
+const std::string LLPanelEnvironmentInfo::TXT_DISABLED("txt_environment_disabled");
+const std::string LLPanelEnvironmentInfo::PNL_REGION_MSG("pnl_environment_region_msg");
+const std::string LLPanelEnvironmentInfo::SDT_DROP_TARGET("sdt_drop_target");
+
+const std::string LLPanelEnvironmentInfo::STR_LABEL_USEDEFAULT("str_label_use_default");
+const std::string LLPanelEnvironmentInfo::STR_LABEL_USEREGION("str_label_use_region");
+const std::string LLPanelEnvironmentInfo::STR_ALTITUDE_DESCRIPTION("str_altitude_desription");
+const std::string LLPanelEnvironmentInfo::STR_NO_PARCEL("str_no_parcel");
+const std::string LLPanelEnvironmentInfo::STR_CROSS_REGION("str_cross_region");
+const std::string LLPanelEnvironmentInfo::STR_LEGACY("str_legacy");
+const std::string LLPanelEnvironmentInfo::STR_DISALLOWED("str_disallowed");
+const std::string LLPanelEnvironmentInfo::STR_TOO_SMALL("str_too_small");
+
+const S32 LLPanelEnvironmentInfo::MINIMUM_PARCEL_SIZE(128);
+
+const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_DAYCYCLE(0x01 << 0);
+const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_DAYLENGTH(0x01 << 1);
+const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_DAYOFFSET(0x01 << 2);
+const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_ALTITUDES(0x01 << 3);
+
+const U32 LLPanelEnvironmentInfo::DIRTY_FLAG_MASK(
+        LLPanelEnvironmentInfo::DIRTY_FLAG_DAYCYCLE | 
+        LLPanelEnvironmentInfo::DIRTY_FLAG_DAYLENGTH | 
+        LLPanelEnvironmentInfo::DIRTY_FLAG_DAYOFFSET |
+        LLPanelEnvironmentInfo::DIRTY_FLAG_ALTITUDES);
+
+const U32 ALTITUDE_SLIDER_COUNT = 3;
+const F32 ALTITUDE_DEFAULT_HEIGHT_STEP = 1000;
+const U32 ALTITUDE_MARKERS_COUNT = 3;
+const U32 ALTITUDE_PREFIXERS_COUNT = 5;
+
+const std::string slider_marker_base = "mark";
+
+const std::string alt_sliders[] = {
+    "sld1",
+    "sld2",
+    "sld3",
+};
+
+const std::string alt_prefixes[] = {
+    "alt1",
+    "alt2",
+    "alt3",
+    "ground",
+    "water",
+};
+
+const std::string alt_panels[] = {
+    "pnl_alt1",
+    "pnl_alt2",
+    "pnl_alt3",
+    "pnl_ground",
+    "pnl_water",
+};
+
+static LLDefaultChildRegistry::Register<LLSettingsDropTarget> r("settings_drop_target");
+
+//=========================================================================
+LLPanelEnvironmentInfo::LLPanelEnvironmentInfo(): 
+    mCurrentEnvironment(),
+    mDirtyFlag(0),
+    mEditorLastParcelId(INVALID_PARCEL_ID),
+    mCrossRegion(false),
+    mNoSelection(false),
+    mNoEnvironment(false),
+    mCurEnvVersion(INVALID_PARCEL_ENVIRONMENT_VERSION),
+    mSettingsFloater(),
+    mEditFloater(),
+    mAllowOverride(true)
+{
+}
+
+LLPanelEnvironmentInfo::~LLPanelEnvironmentInfo()
+{
+    if (mChangeMonitor.connected())
+        mChangeMonitor.disconnect();
+    if (mCommitConnection.connected())
+        mCommitConnection.disconnect();
+    if (mUpdateConnection.connected())
+        mUpdateConnection.disconnect();
+}
+
+BOOL LLPanelEnvironmentInfo::postBuild()
+{
+
+    getChild<LLUICtrl>(BTN_USEDEFAULT)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnDefault(); });
+    getChild<LLUICtrl>(BTN_SELECTINV)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnSelect(); });
+    getChild<LLUICtrl>(BTN_EDIT)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnEdit(); });
+    getChild<LLUICtrl>(BTN_RST_ALTITUDES)->setCommitCallback([this](LLUICtrl *, const LLSD &){ onBtnRstAltitudes(); });
+
+    getChild<LLUICtrl>(SLD_DAYLENGTH)->setCommitCallback([this](LLUICtrl *, const LLSD &value) { onSldDayLengthChanged(value.asReal()); });
+    getChild<LLSliderCtrl>(SLD_DAYLENGTH)->setSliderMouseUpCallback([this](LLUICtrl *, const LLSD &) { onDayLenOffsetMouseUp(); });
+    getChild<LLSliderCtrl>(SLD_DAYLENGTH)->setSliderEditorCommitCallback([this](LLUICtrl *, const LLSD &) { onDayLenOffsetMouseUp(); });
+    getChild<LLUICtrl>(SLD_DAYOFFSET)->setCommitCallback([this](LLUICtrl *, const LLSD &value) { onSldDayOffsetChanged(value.asReal()); });
+    getChild<LLSliderCtrl>(SLD_DAYOFFSET)->setSliderMouseUpCallback([this](LLUICtrl *, const LLSD &) { onDayLenOffsetMouseUp(); });
+    getChild<LLSliderCtrl>(SLD_DAYOFFSET)->setSliderEditorCommitCallback([this](LLUICtrl *, const LLSD &) { onDayLenOffsetMouseUp(); });
+
+    getChild<LLMultiSliderCtrl>(SLD_ALTITUDES)->setCommitCallback([this](LLUICtrl *cntrl, const LLSD &value) { onAltSliderCallback(cntrl, value); });
+    getChild<LLMultiSliderCtrl>(SLD_ALTITUDES)->setSliderMouseUpCallback([this](LLUICtrl *, const LLSD &) { onAltSliderMouseUp(); });
+
+    mChangeMonitor = LLEnvironment::instance().setEnvironmentChanged([this](LLEnvironment::EnvSelection_t env, S32 version) { onEnvironmentChanged(env, version); });
+
+    for (U32 idx = 0; idx < ALTITUDE_SLIDER_COUNT; idx++)
+    {
+        LLSettingsDropTarget* drop_target = findChild<LLSettingsDropTarget>("sdt_" + alt_prefixes[idx]);
+        if (drop_target)
+        {
+            drop_target->setPanel(this, alt_sliders[idx]);
+        }
+        // set initial values to prevent [ALTITUDE] from displaying
+        updateAltLabel(alt_prefixes[idx], idx + 2, idx * 1000);
+    }
+    getChild<LLSettingsDropTarget>("sdt_" + alt_prefixes[3])->setPanel(this, alt_prefixes[3]);
+    getChild<LLSettingsDropTarget>("sdt_" + alt_prefixes[4])->setPanel(this, alt_prefixes[4]);
+
+    return TRUE;
+}
+
+// virtual
+void LLPanelEnvironmentInfo::onOpen(const LLSD& key)
+{
+    refreshFromSource();
+}
+
+// virtual
+void LLPanelEnvironmentInfo::onVisibilityChange(BOOL new_visibility)
+{
+    if (new_visibility)
+    {
+        gIdleCallbacks.addFunction(onIdlePlay, this);
+    }
+    else
+    {
+        commitDayLenOffsetChanges(false); // arrow-key changes
+
+        LLFloaterSettingsPicker *picker = getSettingsPicker(false);
+        if (picker)
+        {
+            picker->closeFloater();
+        }
+
+        gIdleCallbacks.deleteFunction(onIdlePlay, this);
+        LLFloaterEditExtDayCycle *dayeditor = getEditFloater(false);
+        if (mCommitConnection.connected())
+            mCommitConnection.disconnect();
+
+        if (dayeditor)
+        {
+            if (dayeditor->isDirty())
+                dayeditor->refresh();
+            else
+            {
+                dayeditor->closeFloater();
+                mEditFloater.markDead();
+            }
+        }
+    }
+
+}
+
+void LLPanelEnvironmentInfo::refresh()
+{
+    if (gDisconnected)
+        return;
+
+    if (!setControlsEnabled(canEdit()))
+        return;
+
+    if (!mCurrentEnvironment)
+    {
+        return;
+    }
+
+    F32Hours daylength(mCurrentEnvironment->mDayLength);
+    F32Hours dayoffset(mCurrentEnvironment->mDayOffset);
+
+    if (dayoffset.value() > 12.0f)
+        dayoffset -= F32Hours(24.0);
+
+    getChild<LLSliderCtrl>(SLD_DAYLENGTH)->setValue(daylength.value());
+    getChild<LLSliderCtrl>(SLD_DAYOFFSET)->setValue(dayoffset.value());
+   
+    udpateApparentTimeOfDay();
+
+    updateEditFloater(mCurrentEnvironment, canEdit());
+
+    LLEnvironment::altitude_list_t altitudes = mCurrentEnvironment->mAltitudes;
+
+    if (altitudes.size() > 0)
+    {
+        LLMultiSliderCtrl *sld = getChild<LLMultiSliderCtrl>(SLD_ALTITUDES);
+        sld->clear();
+
+        for (S32 idx = 0; idx < ALTITUDE_SLIDER_COUNT; ++idx)
+        {
+            // make sure values are in range, server is supposed to validate them,
+            // but issues happen, try to fix values in such case
+            F32 altitude = llclamp(altitudes[idx + 1], sld->getMinValue(), sld->getMaxValue());
+            bool res = sld->addSlider(altitude, alt_sliders[idx]);
+            if (!res)
+            {
+                LL_WARNS_ONCE("ENVPANEL") << "Failed to validate altitude from server for parcel id" << getParcelId() << LL_ENDL;
+                // Find a spot to insert altitude.
+                // Assuming everything alright with slider, we should find new place in 11 steps top (step 25m, no overlap 100m)
+                F32 alt_step = (altitude > (sld->getMaxValue() / 2)) ? -sld->getIncrement() : sld->getIncrement();
+                for (U32 i = 0; i < 30; i++)
+                {
+                    altitude += alt_step;
+                    if (altitude > sld->getMaxValue())
+                    {
+                        altitude = sld->getMinValue();
+                    }
+                    else if (altitude < sld->getMinValue())
+                    {
+                        altitude = sld->getMaxValue();
+                    }
+                    res = sld->addSlider(altitude, alt_sliders[idx]);
+                    if (res) break;
+                }
+            }
+            if (res)
+            {
+                // slider has some auto correction that might have kicked in
+                altitude = sld->getSliderValue(alt_sliders[idx]);
+            }
+            else
+            {
+                // Something is very very wrong
+                LL_WARNS_ONCE("ENVPANEL") << "Failed to set up altitudes for parcel id " << getParcelId() << LL_ENDL;
+            }
+            updateAltLabel(alt_prefixes[idx], idx + 2, altitude);
+            mAltitudes[alt_sliders[idx]] = AltitudeData(idx + 2, idx, altitude);
+        }
+        if (sld->getCurNumSliders() != ALTITUDE_SLIDER_COUNT)
+        {
+            LL_WARNS("ENVPANEL") << "Failed to add altitude sliders!" << LL_ENDL;
+        }
+        readjustAltLabels();
+        sld->resetCurSlider();
+    }
+
+    updateAltLabel(alt_prefixes[3], 1, 0); // ground
+    updateAltLabel(alt_prefixes[4], 0, 0); // water
+
+}
+
+void LLPanelEnvironmentInfo::refreshFromEstate()
+{
+    LLViewerRegion *pRegion = gAgent.getRegion();
+
+    bool oldAO = mAllowOverride;
+    mAllowOverride = (isRegion() && LLEstateInfoModel::instance().getAllowEnvironmentOverride()) || pRegion->getAllowEnvironmentOverride();
+    if (oldAO != mAllowOverride)
+        refresh();
+}
+
+std::string LLPanelEnvironmentInfo::getNameForTrackIndex(S32 index)
+{
+    std::string invname;
+    if (!mCurrentEnvironment || index < LLSettingsDay::TRACK_WATER || index >= LLSettingsDay::TRACK_MAX)
+    {
+        invname = getString(STRING_EMPTY_NAME);
+    }
+    else if (mCurrentEnvironment->mDayCycleName.empty())
+    {
+        invname = mCurrentEnvironment->mNameList[index];
+
+        if (invname.empty())
+        {
+            if (index <= LLSettingsDay::TRACK_GROUND_LEVEL)
+                invname = getString(isRegion() ? STRING_EMPTY_NAME : STRING_REGION_ENV);
+        }
+    }
+    else if (!mCurrentEnvironment->mDayCycle->isTrackEmpty(index))
+    {
+        invname = mCurrentEnvironment->mDayCycleName;
+    }
+
+
+    if (invname.empty())
+    {
+        invname = getNameForTrackIndex(index - 1);
+        if (invname[0] != '(')
+            invname = "(" + invname + ")";
+    }
+
+    return invname;
+}
+
+LLFloaterSettingsPicker * LLPanelEnvironmentInfo::getSettingsPicker(bool create)
+{
+    LLFloaterSettingsPicker *picker = static_cast<LLFloaterSettingsPicker *>(mSettingsFloater.get());
+
+    // Show the dialog
+    if (!picker && create)
+    {
+        picker = new LLFloaterSettingsPicker(this,
+            LLUUID::null);
+
+        mSettingsFloater = picker->getHandle();
+
+        picker->setCommitCallback([this](LLUICtrl *, const LLSD &data){ onPickerCommitted(data["ItemId"].asUUID()); });
+    }
+
+    return picker;
+}
+
+LLFloaterEditExtDayCycle * LLPanelEnvironmentInfo::getEditFloater(bool create)
+{
+    static const S32 FOURHOURS(4 * 60 * 60);
+    LLFloaterEditExtDayCycle *editor = static_cast<LLFloaterEditExtDayCycle *>(mEditFloater.get());
+
+    // Show the dialog
+    if (!editor && create)
+    {
+        LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, isRegion() ? LLFloaterEditExtDayCycle::CONTEXT_REGION : LLFloaterEditExtDayCycle::CONTEXT_PARCEL)
+            (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH, mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS));
+
+        editor = (LLFloaterEditExtDayCycle *)LLFloaterReg::getInstance(FLOATER_DAY_CYCLE_EDIT, params);
+
+        if (!editor)
+            return nullptr;
+        mEditFloater = editor->getHandle();
+    }
+
+    if (editor && !mCommitConnection.connected())
+        mCommitConnection = editor->setEditCommitSignal([this](LLSettingsDay::ptr_t pday) { onEditCommitted(pday); });
+
+    return editor;
+}
+
+
+void LLPanelEnvironmentInfo::updateEditFloater(const LLEnvironment::EnvironmentInfo::ptr_t &nextenv, bool enable)
+{
+    LLFloaterEditExtDayCycle *dayeditor(getEditFloater(false));
+
+    if (!dayeditor || !dayeditor->isInVisibleChain())
+        return;
+
+    if (!nextenv || !nextenv->mDayCycle || !enable)
+    {
+        if (mCommitConnection.connected())
+            mCommitConnection.disconnect();
+
+        if (dayeditor->isDirty())
+            dayeditor->refresh();
+        else
+            dayeditor->closeFloater();
+    }
+    else if (dayeditor->getEditingAssetId() != nextenv->mDayCycle->getAssetId()
+            || mEditorLastParcelId != nextenv->mParcelId
+            || mEditorLastRegionId != nextenv->mRegionId)
+    {
+        // Ignore dirty
+        // If parcel selection changed whatever we do except saving to inventory with
+        // old settings will be invalid.
+        mEditorLastParcelId = nextenv->mParcelId;
+        mEditorLastRegionId = nextenv->mRegionId;
+
+        dayeditor->setEditDayCycle(nextenv->mDayCycle);
+    }
+}
+
+bool LLPanelEnvironmentInfo::setControlsEnabled(bool enabled)
+{
+    bool is_unavailable(false);
+    bool is_legacy = (mCurrentEnvironment) ? mCurrentEnvironment->mIsLegacy : true;
+    bool is_bigenough = isLargeEnough();
+
+    if (mNoEnvironment || (!LLEnvironment::instance().isExtendedEnvironmentEnabled() && !isRegion()))
+    {
+        is_unavailable = true;
+        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_LEGACY));
+    }
+    else if (mNoSelection)
+    {
+        is_unavailable = true;
+        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_NO_PARCEL));
+    }
+    else if (mCrossRegion)
+    {
+        is_unavailable = true;
+        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_CROSS_REGION));
+    }
+    else if (!isRegion() && !mAllowOverride)
+    {
+        is_unavailable = true;
+        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_DISALLOWED));
+    }
+    else if (!is_bigenough)
+    {
+        is_unavailable = true;
+        getChild<LLTextBox>(TXT_DISABLED)->setText(getString(STR_TOO_SMALL));
+    }
+
+    if (is_unavailable)
+    {
+        getChild<LLUICtrl>(PNL_SETTINGS)->setVisible(false);
+        getChild<LLUICtrl>(PNL_BUTTONS)->setVisible(false);
+        getChild<LLUICtrl>(PNL_DISABLED)->setVisible(true);
+        getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(false);
+        getChild<LLUICtrl>(PNL_REGION_MSG)->setVisible(false);
+        updateEditFloater(mCurrentEnvironment, false);
+
+        return false;
+    }
+    getChild<LLUICtrl>(PNL_SETTINGS)->setVisible(true);
+    getChild<LLUICtrl>(PNL_BUTTONS)->setVisible(true);
+    getChild<LLUICtrl>(PNL_DISABLED)->setVisible(false);
+    getChild<LLUICtrl>(PNL_REGION_MSG)->setVisible(isRegion());
+
+    getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setVisible(LLEnvironment::instance().isExtendedEnvironmentEnabled());
+    getChild<LLUICtrl>(BTN_RST_ALTITUDES)->setVisible(isRegion());
+
+    bool can_enable = enabled && !is_legacy && mCurrentEnvironment && (mCurEnvVersion != INVALID_PARCEL_ENVIRONMENT_VERSION);
+    getChild<LLUICtrl>(BTN_SELECTINV)->setEnabled(can_enable);
+    getChild<LLUICtrl>(BTN_USEDEFAULT)->setEnabled(can_enable);
+    getChild<LLUICtrl>(BTN_EDIT)->setEnabled(can_enable);
+    getChild<LLUICtrl>(SLD_DAYLENGTH)->setEnabled(can_enable);
+    getChild<LLUICtrl>(SLD_DAYOFFSET)->setEnabled(can_enable);
+    getChild<LLUICtrl>(SLD_ALTITUDES)->setEnabled(can_enable && isRegion());
+    getChild<LLUICtrl>(ICN_GROUND)->setColor((can_enable && isRegion()) ? LLColor4::white : LLColor4::grey % 0.8f);
+    getChild<LLUICtrl>(ICN_WATER)->setColor((can_enable && isRegion()) ? LLColor4::white : LLColor4::grey % 0.8f);
+    getChild<LLUICtrl>(BTN_RST_ALTITUDES)->setEnabled(can_enable && isRegion());
+    getChild<LLUICtrl>(PNL_ENVIRONMENT_ALTITUDES)->setEnabled(can_enable);
+    getChild<LLUICtrl>(CHK_ALLOWOVERRIDE)->setEnabled(can_enable && isRegion());
+
+    for (U32 idx = 0; idx < ALTITUDE_MARKERS_COUNT; idx++)
+    {
+        LLUICtrl* marker = findChild<LLUICtrl>(slider_marker_base + llformat("%u", idx));
+        if (marker)
+        {
+            static LLColor4 marker_color(0.75f, 0.75f, 0.75f, 1.f);
+            marker->setColor((can_enable && isRegion()) ? marker_color : marker_color % 0.3f);
+        }
+    }
+
+    for (U32 idx = 0; idx < ALTITUDE_PREFIXERS_COUNT; idx++)
+    {
+        LLSettingsDropTarget* drop_target = findChild<LLSettingsDropTarget>("sdt_" + alt_prefixes[idx]);
+        if (drop_target)
+        {
+            drop_target->setDndEnabled(can_enable);
+        }
+    }
+
+    return true;
+}
+
+void LLPanelEnvironmentInfo::setDirtyFlag(U32 flag)
+{
+    mDirtyFlag |= flag;
+}
+
+void LLPanelEnvironmentInfo::clearDirtyFlag(U32 flag)
+{
+    mDirtyFlag &= ~flag;
+}
+
+void LLPanelEnvironmentInfo::updateAltLabel(const std::string &alt_prefix, U32 sky_index, F32 alt_value)
+{
+    LLMultiSliderCtrl *sld = findChild<LLMultiSliderCtrl>(SLD_ALTITUDES);
+    if (!sld)
+    {
+        LL_WARNS() << "Failed to find slider " << SLD_ALTITUDES << LL_ENDL;
+        return;
+    }
+    LLRect sld_rect = sld->getRect();
+    S32 sld_range = sld_rect.getHeight();
+    S32 sld_bottom = sld_rect.mBottom;
+    S32 sld_offset = sld_rect.getWidth(); // Roughly identical to thumb's width in slider.
+    S32 pos = (sld_range - sld_offset) * ((alt_value - 100) / (4000 - 100));
+
+    // get related views
+    LLTextBox* text = findChild<LLTextBox>("txt_" + alt_prefix);
+    LLLineEditor *field = findChild<LLLineEditor>("edt_invname_" + alt_prefix);
+    LLView *alt_panel = findChild<LLView>("pnl_" + alt_prefix);
+
+    if (text && (sky_index > 1))
+    {
+        // update text
+        std::ostringstream convert;
+        convert << alt_value;
+        text->setTextArg("[ALTITUDE]", convert.str());
+        convert.str("");
+        convert.clear();
+        convert << sky_index;
+        text->setTextArg("[INDEX]", convert.str());
+    }
+
+    if (field)
+    {
+        field->setText(getNameForTrackIndex(sky_index));
+    }
+
+    if (alt_panel && (sky_index > 1))
+    {
+        // move containing panel
+        LLRect rect = alt_panel->getRect();
+        S32 height = rect.getHeight();
+        rect.mBottom = sld_bottom + (sld_offset / 2 + 1) + pos - (height / 2);
+        rect.mTop = rect.mBottom + height;
+        alt_panel->setRect(rect);
+    }
+
+}
+
+void LLPanelEnvironmentInfo::readjustAltLabels()
+{
+    // Re-adjust all labels
+    // Very simple "adjust after the fact" method
+    // Note: labels can be in any order
+
+    LLMultiSliderCtrl *sld = findChild<LLMultiSliderCtrl>(SLD_ALTITUDES);
+    if (!sld) return;
+
+    LLView* view_midle = NULL;
+    U32 midle_ind = 0;
+    S32 shift_up = 0;
+    S32 shift_down = 0;
+    LLRect sld_rect = sld->getRect();
+
+    // Find the middle one
+    for (U32 i = 0; i < ALTITUDE_SLIDER_COUNT; i++)
+    {
+        LLView* cmp_view = findChild<LLView>(alt_panels[i], true);
+        if (!cmp_view) return;
+        LLRect cmp_rect = cmp_view->getRect();
+        S32 pos = 0;
+        shift_up = 0;
+        shift_down = 0;
+
+        for (U32 j = 0; j < ALTITUDE_SLIDER_COUNT; j++)
+        {
+            if (i != j)
+            {
+                LLView* intr_view = findChild<LLView>(alt_panels[j], true);
+                if (!intr_view) return;
+                LLRect intr_rect = intr_view->getRect();
+                if (cmp_rect.mBottom >= intr_rect.mBottom)
+                {
+                    pos++;
+                }
+                if (intr_rect.mBottom <= cmp_rect.mTop && intr_rect.mBottom >= cmp_rect.mBottom)
+                {
+                    shift_up = cmp_rect.mTop - intr_rect.mBottom;
+                }
+                else if (intr_rect.mTop >= cmp_rect.mBottom && intr_rect.mBottom <= cmp_rect.mBottom)
+                {
+                    shift_down = cmp_rect.mBottom - intr_rect.mTop;
+                }
+            }
+        }
+        if (pos == 1) //  middle
+        {
+            view_midle = cmp_view;
+            midle_ind = i;
+            break;
+        }
+    }
+
+    // Account for edges
+    LLRect midle_rect = view_midle->getRect();
+    F32 factor = 0.5f;
+    S32 edge_zone_height = midle_rect.getHeight() * 1.5f;
+
+    if (midle_rect.mBottom - sld_rect.mBottom < edge_zone_height)
+    {
+        factor = 1 - ((midle_rect.mBottom - sld_rect.mBottom) / (edge_zone_height * 2));
+    }
+    else if (sld_rect.mTop - midle_rect.mTop < edge_zone_height )
+    {
+        factor = ((sld_rect.mTop - midle_rect.mTop) / (edge_zone_height * 2));
+    }
+
+    S32 shift_middle = (S32)(((F32)shift_down * factor) + ((F32)shift_up * (1.f - factor)));
+    shift_down = shift_down - shift_middle;
+    shift_up = shift_up - shift_middle;
+
+    // fix crossings
+    for (U32 i = 0; i < ALTITUDE_SLIDER_COUNT; i++)
+    {
+        if (i != midle_ind)
+        {
+            LLView* trn_view = findChild<LLView>(alt_panels[i], true);
+            LLRect trn_rect = trn_view->getRect();
+
+            if (trn_rect.mBottom <= midle_rect.mTop && trn_rect.mBottom >= midle_rect.mBottom)
+            {
+                // Approximate shift
+                trn_rect.translate(0, shift_up);
+                trn_view->setRect(trn_rect);
+            }
+            else if (trn_rect.mTop >= midle_rect.mBottom && trn_rect.mBottom <= midle_rect.mBottom)
+            {
+                // Approximate shift
+                trn_rect.translate(0, shift_down);
+                trn_view->setRect(trn_rect);
+            }
+        }
+    }
+
+    if (shift_middle != 0)
+    {
+        midle_rect.translate(0, -shift_middle); //reversed relative to others
+        view_midle->setRect(midle_rect);
+    }
+}
+
+void LLPanelEnvironmentInfo::onSldDayLengthChanged(F32 value)
+{
+    if (mCurrentEnvironment)
+    {
+        F32Hours daylength(value);
+
+        mCurrentEnvironment->mDayLength = daylength;
+        setDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+
+        udpateApparentTimeOfDay();
+    }
+}
+
+void LLPanelEnvironmentInfo::onSldDayOffsetChanged(F32 value)
+{
+    if (mCurrentEnvironment)
+    {
+        F32Hours dayoffset(value);
+
+        if (dayoffset.value() <= 0.0f)
+            dayoffset += F32Hours(24.0);
+
+        mCurrentEnvironment->mDayOffset = dayoffset;
+        setDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+
+        udpateApparentTimeOfDay();
+    }
+}
+
+void LLPanelEnvironmentInfo::onDayLenOffsetMouseUp()
+{
+    commitDayLenOffsetChanges(true);
+}
+
+void LLPanelEnvironmentInfo::commitDayLenOffsetChanges(bool need_callback)
+{
+    if (mCurrentEnvironment && (getDirtyFlag() & (DIRTY_FLAG_DAYLENGTH | DIRTY_FLAG_DAYOFFSET)))
+    {
+        clearDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+        clearDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+
+        LLHandle<LLPanel> that_h = getHandle();
+
+        if (need_callback)
+        {
+            LLEnvironment::instance().updateParcel(getParcelId(),
+                                                   LLSettingsDay::ptr_t(),
+                                                   mCurrentEnvironment->mDayLength.value(),
+                                                   mCurrentEnvironment->mDayOffset.value(),
+                                                   LLEnvironment::altitudes_vect_t(),
+                                                   [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+        }
+        else
+        {
+            LLEnvironment::instance().updateParcel(getParcelId(),
+                                                   LLSettingsDay::ptr_t(),
+                                                   mCurrentEnvironment->mDayLength.value(),
+                                                   mCurrentEnvironment->mDayOffset.value(),
+                                                   LLEnvironment::altitudes_vect_t());
+        }
+
+    }
+}
+
+void LLPanelEnvironmentInfo::onAltSliderCallback(LLUICtrl *cntrl, const LLSD &data)
+{
+    LLMultiSliderCtrl *sld = (LLMultiSliderCtrl *)cntrl;
+    std::string sld_name = sld->getCurSlider();
+
+    if (sld_name.empty()) return;
+
+    F32 sld_value = sld->getCurSliderValue();
+
+    mAltitudes[sld_name].mAltitude = sld_value;
+
+    // update all labels since we could have jumped multiple and we will need to readjust
+    // (or sort by altitude, too little elements, so I didn't bother with efficiency)
+    altitudes_data_t::iterator end = mAltitudes.end();
+    altitudes_data_t::iterator iter = mAltitudes.begin();
+    altitudes_data_t::iterator iter2;
+    U32 new_index;
+    while (iter != end)
+    {
+        iter2 = mAltitudes.begin();
+        new_index = 2;
+        while (iter2 != end)
+        {
+            if (iter->second.mAltitude > iter2->second.mAltitude)
+            {
+                new_index++;
+            }
+            iter2++;
+        }
+        iter->second.mTrackIndex = new_index;
+
+        updateAltLabel(alt_prefixes[iter->second.mLabelIndex], iter->second.mTrackIndex, iter->second.mAltitude);
+        iter++;
+    }
+
+    readjustAltLabels();
+    setDirtyFlag(DIRTY_FLAG_ALTITUDES);
+}
+
+void LLPanelEnvironmentInfo::onAltSliderMouseUp()
+{
+    if (isRegion() && (getDirtyFlag() & DIRTY_FLAG_ALTITUDES))
+    {
+        clearDirtyFlag(DIRTY_FLAG_ALTITUDES);
+        clearDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+        clearDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+
+        LLHandle<LLPanel> that_h = getHandle();
+        LLEnvironment::altitudes_vect_t alts;
+
+        for (auto alt : mAltitudes)
+        {
+            alts.push_back(alt.second.mAltitude);
+        }
+        setControlsEnabled(false);
+        LLEnvironment::instance().updateParcel(getParcelId(),
+                                               LLSettingsDay::ptr_t(),
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayLength.value() : -1,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayOffset.value() : -1,
+                                               alts);
+    }
+}
+
+void LLPanelEnvironmentInfo::onBtnDefault()
+{
+    LLHandle<LLPanel> that_h = getHandle();
+    S32 parcel_id = getParcelId();
+    LLNotificationsUtil::add("SettingsConfirmReset", LLSD(), LLSD(),
+        [that_h, parcel_id](const LLSD&notif, const LLSD&resp)
+    {
+        S32 opt = LLNotificationsUtil::getSelectedOption(notif, resp);
+        if (opt == 0)
+        {
+            LLEnvironment::instance().resetParcel(parcel_id,
+                [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+        }
+    });
+}
+
+void LLPanelEnvironmentInfo::onBtnEdit()
+{
+    static const S32 FOURHOURS(4 * 60 * 60);
+
+    LLFloaterEditExtDayCycle *dayeditor = getEditFloater();
+
+    LLSD params(LLSDMap(LLFloaterEditExtDayCycle::KEY_EDIT_CONTEXT, isRegion() ? LLFloaterEditExtDayCycle::VALUE_CONTEXT_REGION : LLFloaterEditExtDayCycle::VALUE_CONTEXT_PARCEL)
+            (LLFloaterEditExtDayCycle::KEY_DAY_LENGTH,  mCurrentEnvironment ? (S32)(mCurrentEnvironment->mDayLength.value()) : FOURHOURS)
+            (LLFloaterEditExtDayCycle::KEY_CANMOD,      LLSD::Boolean(true)));
+
+    dayeditor->openFloater(params);
+    if (mCurrentEnvironment && mCurrentEnvironment->mDayCycle)
+    {
+        dayeditor->setEditDayCycle(mCurrentEnvironment->mDayCycle);
+        if (!ends_with(mCurrentEnvironment->mDayCycle->getName(), "(customized)"))
+        {
+            dayeditor->setEditName(mCurrentEnvironment->mDayCycle->getName() + "(customized)");
+        }
+    }
+    else
+        dayeditor->setEditDefaultDayCycle();
+}
+
+void LLPanelEnvironmentInfo::onBtnSelect()
+{
+    LLFloaterSettingsPicker *picker = getSettingsPicker();
+    if (picker)
+    {
+        LLUUID item_id;
+        if (mCurrentEnvironment && mCurrentEnvironment->mDayCycle)
+        {
+            item_id = LLFloaterSettingsPicker::findItemID(mCurrentEnvironment->mDayCycle->getAssetId(), false, false);
+        }
+        picker->setSettingsFilter(LLSettingsType::ST_NONE);
+        picker->setSettingsItemId(item_id);
+        picker->openFloater();
+        picker->setFocus(TRUE);
+    }
+}
+
+void LLPanelEnvironmentInfo::onBtnRstAltitudes()
+{
+    if (isRegion())
+    {
+        LLHandle<LLPanel> that_h = getHandle();
+        LLEnvironment::altitudes_vect_t alts;
+
+        clearDirtyFlag(DIRTY_FLAG_ALTITUDES);
+        clearDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+        clearDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+
+        for (S32 idx = 1; idx <= ALTITUDE_SLIDER_COUNT; ++idx)
+        {
+            F32 new_height = idx * ALTITUDE_DEFAULT_HEIGHT_STEP;
+            alts.push_back(new_height);
+        }
+
+        LLEnvironment::instance().updateParcel(getParcelId(),
+                                               LLSettingsDay::ptr_t(),
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayLength.value() : -1,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayOffset.value() : -1,
+                                               alts,
+            [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+    }
+}
+
+void LLPanelEnvironmentInfo::udpateApparentTimeOfDay()
+{
+    static const F32 SECONDSINDAY(24.0 * 60.0 * 60.0);
+
+    if ((!mCurrentEnvironment) || (mCurrentEnvironment->mDayLength.value() < 1.0) || (mCurrentEnvironment->mDayOffset.value() < 1.0))
+    {
+        getChild<LLUICtrl>(LBL_TIMEOFDAY)->setVisible(false);
+        return;
+    }
+    getChild<LLUICtrl>(LBL_TIMEOFDAY)->setVisible(true);
+
+    S32Seconds  now(LLDate::now().secondsSinceEpoch());
+
+    now += mCurrentEnvironment->mDayOffset;
+
+    F32 perc = (F32)(now.value() % mCurrentEnvironment->mDayLength.value()) / (F32)(mCurrentEnvironment->mDayLength.value());
+
+    S32Seconds  secondofday((S32)(perc * SECONDSINDAY));
+    S32Hours    hourofday(secondofday);
+    S32Seconds  secondofhour(secondofday - hourofday);
+    S32Minutes  minutesofhour(secondofhour);
+    bool        am_pm(hourofday.value() >= 12);
+
+    if (hourofday.value() < 1)
+        hourofday = S32Hours(12);
+    if (hourofday.value() > 12)
+        hourofday -= S32Hours(12);
+
+    std::string lblminute(((minutesofhour.value() < 10) ? "0" : "") + LLSD(minutesofhour.value()).asString());
+
+
+    getChild<LLUICtrl>(LBL_TIMEOFDAY)->setTextArg("[HH]", LLSD(hourofday.value()).asString());
+    getChild<LLUICtrl>(LBL_TIMEOFDAY)->setTextArg("[MM]", lblminute);
+    getChild<LLUICtrl>(LBL_TIMEOFDAY)->setTextArg("[AP]", std::string(am_pm ? "PM" : "AM"));
+    getChild<LLUICtrl>(LBL_TIMEOFDAY)->setTextArg("[PRC]", LLSD((S32)(100 * perc)).asString());
+
+}
+
+void LLPanelEnvironmentInfo::onIdlePlay(void *data)
+{
+    ((LLPanelEnvironmentInfo *)data)->udpateApparentTimeOfDay();
+}
+
+
+void LLPanelEnvironmentInfo::onPickerCommitted(LLUUID item_id, std::string source)
+{
+    if (source == alt_prefixes[4])
+    {
+        onPickerCommitted(item_id, 0);
+    }
+    else if (source == alt_prefixes[3])
+    {
+        onPickerCommitted(item_id, 1);
+    }
+    else
+    {
+        onPickerCommitted(item_id, mAltitudes[source].mTrackIndex);
+    }
+}
+
+void LLPanelEnvironmentInfo::onPickerCommitted(LLUUID item_id, S32 track_num)
+{
+    LLInventoryItem *itemp = gInventory.getItem(item_id);
+    if (itemp)
+    {
+        LLHandle<LLPanel> that_h = getHandle();
+        clearDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+        clearDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+
+        U32 flags(0);
+
+        if (itemp)
+        {
+            if (!itemp->getPermissions().allowOperationBy(PERM_MODIFY, gAgent.getID()))
+                flags |= LLSettingsBase::FLAG_NOMOD;
+            if (!itemp->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+                flags |= LLSettingsBase::FLAG_NOTRANS;
+        }
+
+        LLEnvironment::instance().updateParcel(getParcelId(),
+                                               itemp->getAssetUUID(),
+                                               itemp->getName(),
+                                               track_num,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayLength.value() : -1,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayOffset.value() : -1,
+                                               flags,
+                                               LLEnvironment::altitudes_vect_t(),
+            [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+    }
+}
+
+void LLPanelEnvironmentInfo::onEditCommitted(LLSettingsDay::ptr_t newday)
+{
+    LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_EDIT);
+    LLEnvironment::instance().updateEnvironment();
+    if (!newday)
+    {
+        LL_WARNS("ENVPANEL") << "Editor committed an empty day. Do nothing." << LL_ENDL;
+        return;
+    }
+    if (!mCurrentEnvironment)
+    {
+        // Attempting to save mid update?
+        LL_WARNS("ENVPANEL") << "Failed to apply changes from editor! Dirty state: " << mDirtyFlag << " env version: " << mCurEnvVersion << LL_ENDL;
+        return;
+    }
+    size_t newhash(newday->getHash());
+    size_t oldhash((mCurrentEnvironment->mDayCycle) ? mCurrentEnvironment->mDayCycle->getHash() : 0);
+
+    if (newhash != oldhash)
+    {
+        LLHandle<LLPanel> that_h = getHandle();
+        clearDirtyFlag(DIRTY_FLAG_DAYLENGTH);
+        clearDirtyFlag(DIRTY_FLAG_DAYOFFSET);
+
+        LLEnvironment::instance().updateParcel(getParcelId(),
+                                               newday,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayLength.value() : -1,
+                                               mCurrentEnvironment ? mCurrentEnvironment->mDayOffset.value() : -1,
+                                               LLEnvironment::altitudes_vect_t(),
+            [that_h](S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo) { _onEnvironmentReceived(that_h, parcel_id, envifo); });
+    }
+}
+
+void LLPanelEnvironmentInfo::onEnvironmentChanged(LLEnvironment::EnvSelection_t env, S32 new_version)
+{
+    if (new_version < INVALID_PARCEL_ENVIRONMENT_VERSION)
+    {
+        // cleanups and local changes, we are only interested in changes sent by server
+        return;
+    }
+
+    LL_DEBUGS("ENVPANEL") << "Received environment update " << mCurEnvVersion << " " << new_version << LL_ENDL;
+
+    // Environment comes from different sources, from environment update callbacks,
+    // from hovers (causes callbacks on version change) and from personal requests
+    // filter out duplicates and out of order packets by checking parcel environment version.
+
+    if (isRegion())
+    {
+        // Note: region uses same init versions as parcel
+        if (env == LLEnvironment::ENV_REGION
+            // version should be always growing, UNSET_PARCEL_ENVIRONMENT_VERSION is backup case
+            && (mCurEnvVersion < new_version || mCurEnvVersion <= UNSET_PARCEL_ENVIRONMENT_VERSION))
+        {
+            if (new_version >= UNSET_PARCEL_ENVIRONMENT_VERSION)
+            {
+                // 'pending state' to prevent re-request on following onEnvironmentChanged if there will be any
+                mCurEnvVersion = new_version;
+            }
+            mCurrentEnvironment.reset();
+            refreshFromSource();
+        }
+    }
+    else if ((env == LLEnvironment::ENV_PARCEL)
+             && (getParcelId() == LLViewerParcelMgr::instance().getAgentParcelId()))
+    {
+        LLParcel *parcel = getParcel();
+        if (parcel)
+        {
+            // first for parcel own settings, second is for case when parcel uses region settings
+            if (mCurEnvVersion < new_version
+                || (mCurEnvVersion != new_version && new_version == UNSET_PARCEL_ENVIRONMENT_VERSION))
+            {
+                // 'pending state' to prevent re-request on following onEnvironmentChanged if there will be any
+                mCurEnvVersion = new_version;
+                mCurrentEnvironment.reset();
+
+                refreshFromSource();
+            }
+            else if (mCurrentEnvironment)
+            {
+                // update controls
+                refresh();
+            }
+        }
+    }
+}
+
+
+void LLPanelEnvironmentInfo::onPickerAssetDownloaded(LLSettingsBase::ptr_t settings)
+{
+    LLSettingsVODay::buildFromOtherSetting(settings, [this](LLSettingsDay::ptr_t pday)
+        {
+            if (pday)
+            {
+                mCurrentEnvironment->mDayCycle = pday;
+                setDirtyFlag(DIRTY_FLAG_DAYCYCLE);
+            }
+            refresh();
+        });
+}
+
+void LLPanelEnvironmentInfo::onEnvironmentReceived(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo)
+{
+    if (parcel_id != getParcelId())
+    {
+        LL_WARNS("ENVPANEL") << "Have environment for parcel " << parcel_id << " expecting " << getParcelId() << ". Discarding." << LL_ENDL;
+        return;
+    }
+    mCurrentEnvironment = envifo;
+    clearDirtyFlag(DIRTY_FLAG_MASK);
+    if (mCurrentEnvironment->mEnvVersion > INVALID_PARCEL_ENVIRONMENT_VERSION)
+    {
+        // Server provided version, use it
+        mCurEnvVersion = mCurrentEnvironment->mEnvVersion;
+        LL_DEBUGS("ENVPANEL") << " Setting environment version: " << mCurEnvVersion << " for parcel id: " << parcel_id << LL_ENDL;
+    }
+    // Backup: Version was not provided for some reason
+    else
+    {
+        LL_WARNS("ENVPANEL") << " Environment version was not provided for " << parcel_id << ", old env version: " << mCurEnvVersion << LL_ENDL;
+    }
+
+    refreshFromEstate();
+    refresh();
+
+    // todo: we have envifo and parcel env version, should we just setEnvironment() and parcel's property to prevent dupplicate requests?
+}
+
+void LLPanelEnvironmentInfo::_onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo)
+{
+    LLPanelEnvironmentInfo *that = (LLPanelEnvironmentInfo *)that_h.get();
+    if (!that)
+        return;
+    that->onEnvironmentReceived(parcel_id, envifo);
+}
+
+LLSettingsDropTarget::LLSettingsDropTarget(const LLSettingsDropTarget::Params& p)
+    : LLView(p), mEnvironmentInfoPanel(NULL), mDndEnabled(false)
+{}
+
+BOOL LLSettingsDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+	EDragAndDropType cargo_type,
+	void* cargo_data,
+	EAcceptance* accept,
+	std::string& tooltip_msg)
+{
+    BOOL handled = FALSE;
+
+    if (getParent() && mDndEnabled)
+    {
+        handled = TRUE;
+
+        switch (cargo_type)
+        {
+        case DAD_SETTINGS:
+        {
+            LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
+            if (inv_item && mEnvironmentInfoPanel)
+            {
+                LLUUID item_id = inv_item->getUUID();
+                if (gInventory.getItem(item_id))
+                {
+                    *accept = ACCEPT_YES_COPY_SINGLE;
+                    if (drop)
+                    {
+                        // might be better to use name of the element
+                        mEnvironmentInfoPanel->onPickerCommitted(item_id, mTrack);
+                    }
+                }
+            }
+            else
+            {
+                *accept = ACCEPT_NO;
+            }
+            break;
+        }
+        default:
+            *accept = ACCEPT_NO;
+            break;
+        }
+    }
+    return handled;
+}
diff --git a/indra/newview/llpanelenvironment.h b/indra/newview/llpanelenvironment.h
new file mode 100644
index 0000000000000000000000000000000000000000..38e3f09e34d4dce3250e17d8ba8502315cf0f216
--- /dev/null
+++ b/indra/newview/llpanelenvironment.h
@@ -0,0 +1,222 @@
+/** 
+ * @file llpanelenvironment.h
+ * @brief LLPanelExperiences class definition
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2013, 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$
+ */
+
+#ifndef LL_LLPANELENVIRONMENT_H
+#define LL_LLPANELENVIRONMENT_H
+
+#include "llaccordionctrltab.h"
+#include "llradiogroup.h"
+#include "llcheckboxctrl.h"
+#include "llsliderctrl.h"
+#include "llsettingsdaycycle.h"
+#include "llenvironment.h"
+#include "llparcel.h"
+#include "llsettingspicker.h"
+#include "llfloatereditextdaycycle.h"
+#include "llestateinfomodel.h"
+
+class LLViewerRegion;
+
+class LLPanelEnvironmentInfo : public LLPanel
+{
+    friend class LLSettingsDropTarget;
+public:
+                                LLPanelEnvironmentInfo();
+    virtual                     ~LLPanelEnvironmentInfo();
+
+    virtual BOOL                postBuild() override;
+    virtual void                onOpen(const LLSD& key) override;
+
+    virtual BOOL                isDirty() const override            { return getIsDirty(); }
+    virtual void                onVisibilityChange(BOOL new_visibility) override;
+
+    virtual void                refresh() override;
+
+    virtual bool                isRegion() const = 0;
+    virtual LLParcel *          getParcel() = 0;
+    virtual bool                canEdit() = 0;
+    virtual S32                 getParcelId() = 0;
+
+protected:
+    LOG_CLASS(LLPanelEnvironmentInfo);
+
+    static const std::string    BTN_SELECTINV;
+    static const std::string    BTN_EDIT;
+    static const std::string    BTN_USEDEFAULT;
+    static const std::string    BTN_RST_ALTITUDES;
+    static const std::string    SLD_DAYLENGTH;
+    static const std::string    SLD_DAYOFFSET;
+    static const std::string    SLD_ALTITUDES;
+    static const std::string    ICN_GROUND;
+    static const std::string    ICN_WATER;
+    static const std::string    CHK_ALLOWOVERRIDE;
+    static const std::string    BTN_APPLY;
+    static const std::string    BTN_CANCEL;
+    static const std::string    LBL_TIMEOFDAY;
+    static const std::string    PNL_SETTINGS;
+    static const std::string    PNL_ENVIRONMENT_ALTITUDES;
+    static const std::string    PNL_BUTTONS;
+    static const std::string    PNL_DISABLED;
+    static const std::string    PNL_REGION_MSG;
+    static const std::string    TXT_DISABLED;
+    static const std::string    SDT_DROP_TARGET;
+
+    static const std::string    STR_LABEL_USEDEFAULT;
+    static const std::string    STR_LABEL_USEREGION;
+    static const std::string    STR_ALTITUDE_DESCRIPTION;
+    static const std::string    STR_NO_PARCEL;
+    static const std::string    STR_CROSS_REGION;
+    static const std::string    STR_LEGACY;
+    static const std::string    STR_DISALLOWED;
+    static const std::string    STR_TOO_SMALL;
+
+    static const S32            MINIMUM_PARCEL_SIZE;
+
+    static const U32            DIRTY_FLAG_DAYCYCLE;
+    static const U32            DIRTY_FLAG_DAYLENGTH;
+    static const U32            DIRTY_FLAG_DAYOFFSET;
+    static const U32            DIRTY_FLAG_ALTITUDES;
+
+    static const U32            DIRTY_FLAG_MASK;
+
+    bool                        setControlsEnabled(bool enabled);
+    void                        setDirtyFlag(U32 flag);
+    void                        clearDirtyFlag(U32 flag);
+    bool                        getIsDirty() const                  { return (mDirtyFlag != 0); }
+    bool                        getIsDirtyFlag(U32 flag) const      { return ((mDirtyFlag & flag) != 0); }
+    U32                         getDirtyFlag() const                { return mDirtyFlag; }
+    void                        updateAltLabel(const std::string &alt_prefix, U32 sky_index, F32 alt_value);
+    void                        readjustAltLabels();
+
+    void                        onSldDayLengthChanged(F32 value);
+    void                        onSldDayOffsetChanged(F32 value);
+    void                        onAltSliderCallback(LLUICtrl *cntrl, const LLSD &data);
+    void                        onAltSliderMouseUp();
+
+    void                        onBtnEdit();
+    void                        onBtnSelect();
+    void                        onBtnDefault();
+    void                        onBtnRstAltitudes();
+
+    void                        udpateApparentTimeOfDay();
+
+    void                        onPickerCommitted(LLUUID item_id, std::string source);
+    void                        onPickerCommitted(LLUUID item_id, S32 track_num = LLEnvironment::NO_TRACK);
+    void                        onEditCommitted(LLSettingsDay::ptr_t newday);
+    void                        onDayLenOffsetMouseUp();
+    void                        commitDayLenOffsetChanges(bool need_callback);
+
+    void                        onPickerAssetDownloaded(LLSettingsBase::ptr_t settings);
+    void                        onEnvironmentReceived(S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo);
+    static void                 _onEnvironmentReceived(LLHandle<LLPanel> that_h, S32 parcel_id, LLEnvironment::EnvironmentInfo::ptr_t envifo);
+
+    virtual bool                isLargeEnough() = 0;
+    virtual void                refreshFromSource() = 0;
+
+    std::string                 getNameForTrackIndex(S32 index);
+
+    LLFloaterSettingsPicker *   getSettingsPicker(bool create = true);
+    LLFloaterEditExtDayCycle *  getEditFloater(bool create = true);
+    void                        updateEditFloater(const LLEnvironment::EnvironmentInfo::ptr_t &nextenv, bool enable);
+
+    void                        setCrossRegion(bool val) { mCrossRegion = val; }
+    void                        setNoSelection(bool val) { mNoSelection = val; }
+    void                        setNoEnvironmentSupport(bool val) { mNoEnvironment = val; }
+
+    LLEnvironment::EnvironmentInfo::ptr_t   mCurrentEnvironment;
+
+    void                        onEnvironmentChanged(LLEnvironment::EnvSelection_t env, S32 version);
+
+    class AltitudeData
+    {
+    public:
+        AltitudeData() :
+            mTrackIndex(0), mLabelIndex(0), mAltitude(0)
+        {}
+        AltitudeData(U32 track_index, U32 label_index, F32 altitude) :
+            mTrackIndex(track_index), mLabelIndex(label_index), mAltitude(altitude)
+        {}
+
+        U32 mTrackIndex;
+        U32 mLabelIndex;
+        F32 mAltitude;
+    };
+    typedef std::map<std::string, AltitudeData>      altitudes_data_t;
+    altitudes_data_t                mAltitudes;
+    S32                             mCurEnvVersion; // used to filter duplicate callbacks/refreshes
+
+protected:
+    typedef boost::signals2::connection connection_t;
+
+    void                            refreshFromEstate();
+    bool                            mAllowOverride;
+
+private:
+    static void                     onIdlePlay(void *);
+
+    connection_t                    mCommitConnection;
+    connection_t                    mChangeMonitor;
+    connection_t                    mUpdateConnection;
+
+    LLHandle<LLFloater>             mSettingsFloater;
+    LLHandle<LLFloater>             mEditFloater;
+    S32                             mDirtyFlag;
+    S32                             mEditorLastParcelId;
+    LLUUID                          mEditorLastRegionId;
+    bool                            mCrossRegion;
+    bool                            mNoSelection;
+    bool                            mNoEnvironment;
+
+};
+
+class LLSettingsDropTarget : public LLView
+{
+public:
+    struct Params : public LLInitParam::Block<Params, LLView::Params>
+    {
+        Params()
+        {
+            changeDefault(mouse_opaque, false);
+            changeDefault(follows.flags, FOLLOWS_ALL);
+        }
+    };
+    LLSettingsDropTarget(const Params&);
+    ~LLSettingsDropTarget() {};
+
+    virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+        EDragAndDropType cargo_type,
+        void* cargo_data,
+        EAcceptance* accept,
+        std::string& tooltip_msg);
+    void setPanel(LLPanelEnvironmentInfo* panel, std::string track) { mEnvironmentInfoPanel = panel;  mTrack = track; };
+    void setDndEnabled(bool dnd_enabled) { mDndEnabled = dnd_enabled; };
+
+protected:
+    LLPanelEnvironmentInfo* mEnvironmentInfoPanel;
+    std::string mTrack;
+    bool                    mDndEnabled;
+};
+#endif // LL_LLPANELENVIRONMENT_H
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index ce6834b4b3fddd3ef0a8f587d68958fdb58304cd..7373c7412ce977c3a5faec28b3e3cea22c3fc2fd 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -155,6 +155,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
 		case DAD_GESTURE:
 		case DAD_CALLINGCARD:
 		case DAD_MESH:
+        case DAD_SETTINGS:
 		{
 			LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
 			if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index be31a2ed5dc06e82e7518a30e8fe04b6aaeecf66..02cd22c3071864f370ed1484a15558cbdc24773e 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -58,6 +58,7 @@
 #include "llsidepanelinventory.h"
 #include "llfolderview.h"
 #include "llradiogroup.h"
+#include "llenvironment.h"
 
 const std::string FILTERS_FILENAME("filters.xml");
 
@@ -128,6 +129,9 @@ LLPanelMainInventory::LLPanelMainInventory(const LLPanel::Params& p)
 	mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
 	mCommitCallbackRegistrar.add("Inventory.Share",  boost::bind(&LLAvatarActions::shareWithAvatars, this));
 
+    mEnableCallbackRegistrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl *, const LLSD &) { return LLPanelMainInventory::hasSettingsInventory(); });
+
+
 	mSavedFolderState = new LLSaveFolderState();
 	mSavedFolderState->setApply(FALSE);
 }
@@ -904,6 +908,7 @@ void LLFloaterInventoryFinder::updateElementsFromFilter()
 	getChild<LLUICtrl>("check_sound")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
 	getChild<LLUICtrl>("check_texture")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
 	getChild<LLUICtrl>("check_snapshot")->setValue((S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
+    getChild<LLUICtrl>("check_settings")->setValue((S32)(filter_types & 0x1 << LLInventoryType::IT_SETTINGS));
 	getChild<LLUICtrl>("check_show_empty")->setValue(show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
 
 	getChild<LLUICtrl>("check_created_by_me")->setValue(show_created_by_me);
@@ -990,6 +995,12 @@ void LLFloaterInventoryFinder::draw()
 		filtered_by_all_types = FALSE;
 	}
 
+    if (!getChild<LLUICtrl>("check_settings")->getValue())
+    {
+        filter &= ~(0x1 << LLInventoryType::IT_SETTINGS);
+        filtered_by_all_types = FALSE;
+    }
+
 	if (!filtered_by_all_types || (mPanelMainInventory->getPanel()->getFilter().getFilterTypes() & LLInventoryFilter::FILTERTYPE_DATE))
 	{
 		// don't include folders in filter, unless I've selected everything or filtering by date
@@ -1107,6 +1118,7 @@ void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
 	self->getChild<LLUICtrl>("check_sound")->setValue(TRUE);
 	self->getChild<LLUICtrl>("check_texture")->setValue(TRUE);
 	self->getChild<LLUICtrl>("check_snapshot")->setValue(TRUE);
+    self->getChild<LLUICtrl>("check_settings")->setValue(TRUE);
 }
 
 //static
@@ -1126,6 +1138,7 @@ void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
 	self->getChild<LLUICtrl>("check_sound")->setValue(FALSE);
 	self->getChild<LLUICtrl>("check_texture")->setValue(FALSE);
 	self->getChild<LLUICtrl>("check_snapshot")->setValue(FALSE);
+    self->getChild<LLUICtrl>("check_settings")->setValue(FALSE);
 }
 
 //////////////////////////////////////////////////////////////////////////////////
@@ -1517,5 +1530,10 @@ void LLPanelMainInventory::setUploadCostIfNeeded()
 	}
 }
 
+bool LLPanelMainInventory::hasSettingsInventory()
+{
+    return LLEnvironment::instance().isInventoryEnabled();
+}
+
 // List Commands                                                              //
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 732a3b04e3dc92e56a5433c6f59248c33c35b9a3..a6bdee233d5f23eac700757a3a824ccf4a8ac139 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -161,6 +161,7 @@ class LLPanelMainInventory : public LLPanel, LLInventoryObserver
 	BOOL isActionChecked(const LLSD& userdata);
 	void onCustomAction(const LLSD& command_name);
 	bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+    static bool hasSettingsInventory();
 	/**
 	 * Set upload cost in "Upload" sub menu.
 	 */
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 7756b92a3af1c15a0b5d5e1cef85003799cd1e38..ecadc9443b93e30be5d0db60047b731d8711dbc8 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -143,6 +143,7 @@ class LLTaskInvFVBridge : public LLFolderViewModelItemInventory
 	virtual bool hasChildren() const { return FALSE; }
 	virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
 	virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
+    virtual LLSettingsType::type_e getSettingsType() const { return LLSettingsType::ST_NONE; }
 	virtual EInventorySortGroup getSortGroup() const { return SG_ITEM; }
 	virtual LLInventoryObject* getInventoryObject() const { return findInvObject(); }
 
@@ -702,6 +703,7 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
 		case DAD_GESTURE:
 		case DAD_CALLINGCARD:
 		case DAD_MESH:
+        case DAD_SETTINGS:
 			accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
 			if(accept && drop)
 			{
@@ -1121,6 +1123,33 @@ LLUIImagePtr LLTaskWearableBridge::getIcon() const
 	return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE );
 }
 
+///----------------------------------------------------------------------------
+/// Class LLTaskSettingsBridge
+///----------------------------------------------------------------------------
+
+class LLTaskSettingsBridge : public LLTaskInvFVBridge
+{
+public:
+    LLTaskSettingsBridge(LLPanelObjectInventory* panel,
+        const LLUUID& uuid,
+        const std::string& name,
+        U32 flags) :
+        LLTaskInvFVBridge(panel, uuid, name, flags) {}
+
+    virtual LLUIImagePtr getIcon() const;
+    virtual LLSettingsType::type_e  getSettingsType() const;
+};
+
+LLUIImagePtr LLTaskSettingsBridge::getIcon() const
+{
+    return LLInventoryIcon::getIcon(mAssetType, mInventoryType, mFlags, FALSE);
+}
+
+LLSettingsType::type_e LLTaskSettingsBridge::getSettingsType() const 
+{ 
+    return LLSettingsType::ST_NONE; 
+}
+
 ///----------------------------------------------------------------------------
 /// LLTaskInvFVBridge impl
 //----------------------------------------------------------------------------
@@ -1202,6 +1231,12 @@ LLTaskInvFVBridge* LLTaskInvFVBridge::createObjectBridge(LLPanelObjectInventory*
 						 object_id,
 						 object_name);
 		break;
+	case LLAssetType::AT_SETTINGS:
+		new_bridge = new LLTaskSettingsBridge(panel,
+										  object_id,
+										  object_name,
+                                          itemflags);
+		break;
 	default:
 		LL_INFOS() << "Unhandled inventory type (llassetstorage.h): "
 				<< (S32)type << LL_ENDL;
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 3c74aed734ccdd7864fa7dc55387b99e48a2d382..6e61584d33f4d70ceb9cb4572d86de5608b0c6d0 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -64,8 +64,8 @@
 #include "llvector4a.h"
 
 // Functions pulled from pipeline.cpp
-glh::matrix4f glh_get_current_modelview();
-glh::matrix4f glh_get_current_projection();
+glh::matrix4f get_current_modelview();
+glh::matrix4f get_current_projection();
 // Functions pulled from llviewerdisplay.cpp
 bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model);
 
@@ -642,7 +642,7 @@ void LLPanelPrimMediaControls::updateShape()
 		glh::matrix4f mat;
 		if (!is_hud) 
 		{
-			mat = glh_get_current_projection() * glh_get_current_modelview();
+			mat = get_current_projection() * get_current_modelview();
 		}
 		else {
 			glh::matrix4f proj, modelview;
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index f3a4cf36eed9f00d4e6e04fbf27e75606d66cd82..b8aa976657fc0316f8e06b851d337c01e6a90721 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -170,14 +170,16 @@ void LLPanelSnapshotPostcard::sendPostcard()
     std::string url = gAgent.getRegion()->getCapability("SendPostcard");
     if (!url.empty())
     {
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLPostcardUploadInfo(
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLPostcardUploadInfo>(
             getChild<LLUICtrl>("name_form")->getValue().asString(),
             getChild<LLUICtrl>("to_form")->getValue().asString(),
             getChild<LLUICtrl>("subject_form")->getValue().asString(),
             getChild<LLUICtrl>("msg_form")->getValue().asString(),
             mSnapshotFloater->getPosTakenGlobal(),
             mSnapshotFloater->getImageData(),
-            boost::bind(&LLPanelSnapshotPostcard::sendPostcardFinished, _4)));
+            [](LLUUID, LLUUID, LLUUID, LLSD response) {
+                LLPanelSnapshotPostcard::sendPostcardFinished(response);
+            }));
 
         LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
     }
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 6ad6a172b165648b3b380eb2669b2344b9a7cc52..05d9346f89a13d03011ca4325d9407439d7dec4c 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -300,7 +300,7 @@ void LLPanelVolume::getState( )
 		{
 			LightColorSwatch->setEnabled( TRUE );
 			LightColorSwatch->setValid( TRUE );
-			LightColorSwatch->set(volobjp->getLightBaseColor());
+			LightColorSwatch->set(volobjp->getLightSRGBBaseColor());
 		}
 
 		LLTextureCtrl* LightTextureCtrl = getChild<LLTextureCtrl>("light texture control");
@@ -328,7 +328,7 @@ void LLPanelVolume::getState( )
 		getChild<LLUICtrl>("Light Focus")->setValue(params.mV[1]);
 		getChild<LLUICtrl>("Light Ambiance")->setValue(params.mV[2]);
 
-		mLightSavedColor = volobjp->getLightColor();
+		mLightSavedColor = volobjp->getLightSRGBBaseColor();
 	}
 	else
 	{
@@ -585,7 +585,7 @@ void LLPanelVolume::refresh()
 		mRootObject = NULL;
 	}
 
-	BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
+	BOOL visible = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE;
 
 	getChildView("Light FOV")->setVisible( visible);
 	getChildView("Light Focus")->setVisible( visible);
@@ -807,7 +807,7 @@ void LLPanelVolume::onLightSelectColor(const LLSD& data)
 	{
 		LLColor4	clr = LightColorSwatch->get();
 		LLColor3	clr3( clr );
-		volobjp->setLightColor(clr3);
+		volobjp->setLightSRGBColor(clr3);
 		mLightSavedColor = clr;
 	}
 }
@@ -881,7 +881,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
 	if(LightColorSwatch)
 	{
 		LLColor4	clr = LightColorSwatch->get();
-		volobjp->setLightColor(LLColor3(clr));
+		volobjp->setLightSRGBColor(LLColor3(clr));
 	}
 
 	LLTextureCtrl*	LightTextureCtrl = self->getChild<LLTextureCtrl>("light texture control");
diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp
index 5eadd65884c31e0ad92401b7be7bc86b644629c4..a23830e8e1764e17eda4bc0e8a8338ca6fbef1a7 100644
--- a/indra/newview/llplacesinventorypanel.cpp
+++ b/indra/newview/llplacesinventorypanel.cpp
@@ -78,6 +78,7 @@ LLFolderView * LLPlacesInventoryPanel::createFolderRoot(LLUUID root_id )
     p.view_model = &mInventoryViewModel;
     p.use_label_suffix = mParams.use_label_suffix;
     p.allow_multiselect = mAllowMultiSelect;
+    p.allow_drag = mAllowDrag;
     p.show_empty_message = mShowEmptyMessage;
     p.show_item_link_overlays = mShowItemLinkOverlays;
     p.root = NULL;
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 787bd68e5894a98fff109d5575dcea998aa6d078..70ce275734488e6c7b583a3461a52ef981326cbc 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -1091,7 +1091,7 @@ void LLPreviewGesture::saveIfNeeded()
         const LLViewerRegion* region = gAgent.getRegion();
         if (!region)
         {
-            LL_WARNS() << "Not connected to a region, cannot save notecard." << LL_ENDL;
+            LL_WARNS() << "Not connected to a region, cannot save gesture." << LL_ENDL;
             return;
         }
         std::string agent_url = region->getCapability("UpdateGestureAgentInventory");
@@ -1111,13 +1111,15 @@ void LLPreviewGesture::saveIfNeeded()
                 refresh();
                 item->setComplete(true);
 
-                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_GESTURE, buffer,
-                    boost::bind(&LLPreviewGesture::finishInventoryUpload, _1, _2)));
+                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_GESTURE, buffer,
+                    [](LLUUID itemId, LLUUID newAssetId, LLUUID, LLSD) {
+                        LLPreviewGesture::finishInventoryUpload(itemId, newAssetId);
+                    });
                 url = agent_url;
             }
             else if (!mObjectUUID.isNull() && !task_url.empty())
             {
-                uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, NULL));
+                uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_GESTURE, buffer, nullptr);
                 url = task_url;
             }
 
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 2f534ac2456eb9690c6892d9dde30ab652e9d895..7ef0ef0e8b78a5bd294fd7ae942012f632f80c36 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -524,14 +524,19 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem, bool sync)
 
                 if (mObjectUUID.isNull() && !agent_url.empty())
                 {
-                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
-                        boost::bind(&LLPreviewNotecard::finishInventoryUpload, _1, _2, _3)));
+                    uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        [](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD) {
+                            LLPreviewNotecard::finishInventoryUpload(itemId, newAssetId, newItemId);
+                        });
                     url = agent_url;
                 }
                 else if (!mObjectUUID.isNull() && !task_url.empty())
                 {
-                    uploadInfo = LLResourceUploadInfo::ptr_t(new LLBufferedAssetUploadInfo(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
-                        boost::bind(&LLPreviewNotecard::finishTaskUpload, _1, _3, mObjectUUID)));
+                    LLUUID object_uuid(mObjectUUID);
+                    uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(mObjectUUID, mItemUUID, LLAssetType::AT_NOTECARD, buffer, 
+                        [object_uuid](LLUUID itemId, LLUUID, LLUUID newAssetId, LLSD) {
+                            LLPreviewNotecard::finishTaskUpload(itemId, newAssetId, object_uuid);
+                        });
                     url = task_url;
                 }
 
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index d177384b5ac8c602b19d64e0b0c919d06aabac0f..7a68d1e270755c185dcce8b04775fd768bf4c8b8 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -33,7 +33,6 @@
 #include "llcheckboxctrl.h"
 #include "llcombobox.h"
 #include "lldir.h"
-#include "llenvmanager.h"
 #include "llexternaleditor.h"
 #include "llfilepicker.h"
 #include "llfloaterreg.h"
@@ -1693,9 +1692,11 @@ void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
         if (!url.empty())
         {
             std::string buffer(mScriptEd->mEditor->getText());
-            LLBufferedAssetUploadInfo::invnUploadFinish_f proc = boost::bind(&LLPreviewLSL::finishedLSLUpload, _1, _4);
 
-            LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mItemUUID, buffer, proc));
+            LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLScriptAssetUpload>(mItemUUID, buffer, 
+                [](LLUUID itemId, LLUUID, LLUUID, LLSD response) {
+                    LLPreviewLSL::finishedLSLUpload(itemId, response);
+                }));
 
             LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
         }
@@ -2243,11 +2244,13 @@ void LLLiveLSLEditor::saveIfNeeded(bool sync /*= true*/)
     if (!url.empty())
     {
         std::string buffer(mScriptEd->mEditor->getText());
-        LLBufferedAssetUploadInfo::taskUploadFinish_f proc = boost::bind(&LLLiveLSLEditor::finishLSLUpload, _1, _2, _3, _4, isRunning);
 
-        LLResourceUploadInfo::ptr_t uploadInfo(new LLScriptAssetUpload(mObjectUUID, mItemUUID, 
+        LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLScriptAssetUpload>(mObjectUUID, mItemUUID, 
                 monoChecked() ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, 
-                isRunning, mScriptEd->getAssociatedExperience(), buffer, proc));
+                isRunning, mScriptEd->getAssociatedExperience(), buffer, 
+                [isRunning](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) { 
+                    LLLiveLSLEditor::finishLSLUpload(itemId, taskId, newAssetId, response, isRunning);
+                }));
 
         LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo);
     }
diff --git a/indra/newview/llscriptruntimeperms.h b/indra/newview/llscriptruntimeperms.h
index 51f57afdc91a2f94a0df3dea63d09f6a51ccb3e6..f692c0ad013c868673d6dd4446b6eb584ced0559 100644
--- a/indra/newview/llscriptruntimeperms.h
+++ b/indra/newview/llscriptruntimeperms.h
@@ -37,7 +37,7 @@ typedef struct _script_perm {
 	question(q), permbit(b), caution(c) {}
 } script_perm_t;
 
-const U32 NUM_SCRIPT_PERMISSIONS = 16;
+const U32 NUM_SCRIPT_PERMISSIONS = 18;
 const S32 SCRIPT_PERMISSION_DEBIT = 0;
 const S32 SCRIPT_PERMISSION_TRIGGER_ANIMATION = 3;
 const S32 SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS = 14;
@@ -58,7 +58,9 @@ static const boost::array<script_perm_t, NUM_SCRIPT_PERMISSIONS> SCRIPT_PERMISSI
 	_script_perm("JoinAnExperience",	(0x1 << 13), false),
 	_script_perm("SilentlyManageEstateAccess", (0x1 << 14), false),
 	_script_perm("OverrideYourAnimations", (0x1 << 15), false),
-	_script_perm("ScriptReturnObjects",	(0x1 << 16), false)
-}};
+	_script_perm("ScriptReturnObjects",	(0x1 << 16), false),
+    _script_perm("ForceSitAvatar",      (0x1 << 17), false),
+    _script_perm("ChangeEnvSettings",   (0x1 << 18), false)
+    } };
 
 #endif // LL_LLSCRIPTRUNTIME_PERMS_H
diff --git a/indra/newview/llsettingspicker.cpp b/indra/newview/llsettingspicker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2d21063e798624e7904c812c7d9f2a2e25a078a
--- /dev/null
+++ b/indra/newview/llsettingspicker.cpp
@@ -0,0 +1,509 @@
+/** 
+* @author Rider Linden
+* @brief LLSettingsPicker class header file including related functions
+*
+* $LicenseInfo:firstyear=2018&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llsettingspicker.h"
+
+#include "llcombobox.h"
+#include "llfiltereditor.h"
+#include "llfolderviewmodel.h"
+#include "llinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodelbackgroundfetch.h"
+#include "llinventoryobserver.h"
+#include "llinventorypanel.h"
+#include "llsettingsvo.h"
+
+#include "lldraghandle.h"
+#include "llviewercontrol.h"
+#include "llagent.h"
+
+//=========================================================================
+namespace
+{
+    const std::string FLOATER_DEFINITION_XML("floater_settings_picker.xml");
+
+    const std::string FLT_INVENTORY_SEARCH("flt_inventory_search");
+    const std::string CMB_TRACK_SELECTION("track_selection");
+    const std::string PNL_INVENTORY("pnl_inventory");
+    const std::string PNL_COMBO("pnl_combo");
+    const std::string BTN_SELECT("btn_select");
+    const std::string BTN_CANCEL("btn_cancel");
+
+    // strings in xml
+
+    const std::string STR_TITLE_PREFIX = "pick title";
+    const std::string STR_TITLE_TRACK = "pick_track";
+    const std::string STR_TITLE_SETTINGS = "pick_settings";
+    const std::string STR_TRACK_WATER = "track_water";
+    const std::string STR_TRACK_GROUND = "track_ground";
+    const std::string STR_TRACK_SKY = "track_sky";
+}
+//=========================================================================
+
+LLFloaterSettingsPicker::LLFloaterSettingsPicker(LLView * owner, LLUUID initial_item_id, const LLSD &params):
+    LLFloater(params),
+    mOwnerHandle(),
+    mActive(true),
+    mContextConeOpacity(0.0f),
+    mSettingItemID(initial_item_id),
+    mTrackMode(TRACK_NONE),
+    mImmediateFilterPermMask(PERM_NONE)
+{
+    mOwnerHandle = owner->getHandle();
+
+    buildFromFile(FLOATER_DEFINITION_XML);
+    setCanMinimize(FALSE);
+}
+
+
+LLFloaterSettingsPicker::~LLFloaterSettingsPicker() 
+{
+
+}
+
+//-------------------------------------------------------------------------
+BOOL LLFloaterSettingsPicker::postBuild()
+{
+    if (!LLFloater::postBuild())
+        return FALSE;
+
+    std::string prefix = getString(STR_TITLE_PREFIX);
+    std::string label = getString(STR_TITLE_SETTINGS);
+    setTitle(prefix + " " + label);
+
+    mFilterEdit = getChild<LLFilterEditor>(FLT_INVENTORY_SEARCH);
+    mFilterEdit->setCommitCallback([this](LLUICtrl*, const LLSD& param){ onFilterEdit(param.asString()); });
+    
+    mInventoryPanel = getChild<LLInventoryPanel>(PNL_INVENTORY);
+    if (mInventoryPanel)
+    {
+        U32 filter_types = 0x0;
+        filter_types |= 0x1 << LLInventoryType::IT_SETTINGS;
+
+        mInventoryPanel->setFilterTypes(filter_types);
+        mInventoryPanel->setFilterPermMask(mImmediateFilterPermMask);
+
+        mInventoryPanel->setSelectCallback([this](const LLFloaterSettingsPicker::itemlist_t &items, bool useraction){ onSelectionChange(items, useraction); });
+        mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+        mInventoryPanel->setSuppressOpenItemAction(true);
+
+        // Disable auto selecting first filtered item because it takes away
+        // selection from the item set by LLTextureCtrl owning this floater.
+        mInventoryPanel->getRootFolder()->setAutoSelectOverride(TRUE);
+
+        // don't put keyboard focus on selected item, because the selection callback
+        // will assume that this was user input
+        if (!mSettingItemID.isNull())
+        {
+            //todo: this is bad idea
+            mInventoryPanel->setSelection(mSettingItemID, TAKE_FOCUS_NO);
+        }
+        getChild<LLView>(BTN_SELECT)->setEnabled(mSettingItemID.notNull());
+    }
+
+    mNoCopySettingsSelected = FALSE;
+
+    childSetAction(BTN_CANCEL, [this](LLUICtrl*, const LLSD& param){ onButtonCancel(); });
+    childSetAction(BTN_SELECT, [this](LLUICtrl*, const LLSD& param){ onButtonSelect(); });
+
+    getChild<LLPanel>(PNL_COMBO)->setVisible(mTrackMode != TRACK_NONE);
+
+    // update permission filter once UI is fully initialized
+    mSavedFolderState.setApply(FALSE);
+
+    return TRUE;
+}
+
+void LLFloaterSettingsPicker::onClose(bool app_quitting)
+{
+    if (app_quitting)
+        return;
+
+    mCloseSignal();
+    LLView *owner = mOwnerHandle.get();
+    if (owner)
+    {
+        owner->setFocus(TRUE);
+    }
+    mSettingItemID.setNull();
+    mInventoryPanel->getRootFolder()->clearSelection();
+}
+
+void LLFloaterSettingsPicker::setValue(const LLSD& value)
+{
+    mSettingItemID = value.asUUID();
+}
+
+LLSD LLFloaterSettingsPicker::getValue() const 
+{
+    return LLSD(mSettingItemID);
+}
+
+void LLFloaterSettingsPicker::setSettingsFilter(LLSettingsType::type_e type)
+{
+    U64 filter = 0xFFFFFFFFFFFFFFFF;
+    if (type != LLSettingsType::ST_NONE)
+    {
+        filter = static_cast<S64>(0x1) << static_cast<S64>(type);
+    }
+
+    mInventoryPanel->setFilterSettingsTypes(filter);
+}
+
+void LLFloaterSettingsPicker::setTrackMode(ETrackMode mode)
+{
+    mTrackMode = mode;
+    getChild<LLPanel>(PNL_COMBO)->setVisible(mode != TRACK_NONE);
+
+    std::string prefix = getString(STR_TITLE_PREFIX);
+    std::string label;
+    if (mode != TRACK_NONE)
+    {
+        label = getString(STR_TITLE_TRACK);
+    }
+    else
+    {
+        label = getString(STR_TITLE_SETTINGS);
+    }
+    setTitle(prefix + " " + label);
+}
+
+void LLFloaterSettingsPicker::draw()
+{
+    LLView *owner = mOwnerHandle.get();
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, owner);
+
+    LLFloater::draw();
+}
+
+
+//=========================================================================
+void LLFloaterSettingsPicker::onFilterEdit(const std::string& search_string)
+{
+    std::string upper_case_search_string = search_string;
+    LLStringUtil::toUpper(upper_case_search_string);
+
+    if (upper_case_search_string.empty())
+    {
+        if (mInventoryPanel->getFilterSubString().empty())
+        {
+            // current filter and new filter empty, do nothing
+            return;
+        }
+
+        mSavedFolderState.setApply(TRUE);
+        mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+        // add folder with current item to list of previously opened folders
+        LLOpenFoldersWithSelection opener;
+        mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
+        mInventoryPanel->getRootFolder()->scrollToShowSelection();
+
+    }
+    else if (mInventoryPanel->getFilterSubString().empty())
+    {
+        // first letter in search term, save existing folder open state
+        if (!mInventoryPanel->getFilter().isNotDefault())
+        {
+            mSavedFolderState.setApply(FALSE);
+            mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState);
+        }
+    }
+
+    mInventoryPanel->setFilterSubString(search_string);
+}
+
+void LLFloaterSettingsPicker::onSelectionChange(const LLFloaterSettingsPicker::itemlist_t &items, bool user_action)
+{
+    bool is_item = false;
+    LLUUID asset_id;
+    if (items.size())
+    {
+        LLFolderViewItem* first_item = items.front();
+
+        mNoCopySettingsSelected = false;
+        if (first_item)
+        {
+            LLItemBridge *bridge_model = dynamic_cast<LLItemBridge *>(first_item->getViewModelItem());
+            if (bridge_model && bridge_model->getItem())
+            {
+                if (!bridge_model->isItemCopyable())
+                {
+                    mNoCopySettingsSelected = true;
+                }
+                setSettingsItemId(bridge_model->getItem()->getUUID(), false);
+                asset_id = bridge_model->getItem()->getAssetUUID();
+                mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+                is_item = true;
+
+                if (user_action)
+                {
+                    mChangeIDSignal(mSettingItemID);
+                }
+            }
+        }
+    }
+    bool track_picker_enabled = mTrackMode != TRACK_NONE;
+
+    getChild<LLView>(CMB_TRACK_SELECTION)->setEnabled(is_item && track_picker_enabled && mSettingAssetID == asset_id);
+    getChild<LLView>(BTN_SELECT)->setEnabled(is_item && (!track_picker_enabled || mSettingAssetID == asset_id));
+    if (track_picker_enabled && asset_id.notNull() && mSettingAssetID != asset_id)
+    {
+        LLUUID item_id = mSettingItemID;
+        LLHandle<LLFloater> handle = getHandle();
+        LLSettingsVOBase::getSettingsAsset(asset_id,
+            [item_id, handle](LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status, LLExtStat) { LLFloaterSettingsPicker::onAssetLoadedCb(handle, item_id, asset_id, settings, status); });
+    }
+}
+
+void LLFloaterSettingsPicker::onAssetLoadedCb(LLHandle<LLFloater> handle, LLUUID item_id, LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status)
+{
+    if (handle.isDead() || status)
+    {
+        return;
+    }
+
+    LLFloaterSettingsPicker *picker = static_cast<LLFloaterSettingsPicker *>(handle.get());
+
+    if (picker->mSettingItemID != item_id)
+    {
+        return;
+    }
+
+    picker->onAssetLoaded(asset_id, settings);
+}
+
+void LLFloaterSettingsPicker::onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings)
+{
+    LLComboBox* track_selection = getChild<LLComboBox>(CMB_TRACK_SELECTION);
+    track_selection->clear();
+    track_selection->removeall();
+    if (!settings)
+    {
+        LL_WARNS() << "Failed to load asset " << asset_id << LL_ENDL;
+        return;
+    }
+    LLSettingsDay::ptr_t pday = std::dynamic_pointer_cast<LLSettingsDay>(settings);
+
+    if (!pday)
+    {
+        LL_WARNS() << "Wrong asset type received by id " << asset_id << LL_ENDL;
+        return;
+    }
+
+    if (mTrackMode == TRACK_WATER)
+    {
+        track_selection->add(getString(STR_TRACK_WATER), LLSD::Integer(LLSettingsDay::TRACK_WATER), ADD_TOP, true);
+    }
+    else if (mTrackMode == TRACK_SKY)
+    {
+        // track 1 always present
+        track_selection->add(getString(STR_TRACK_GROUND), LLSD::Integer(LLSettingsDay::TRACK_GROUND_LEVEL), ADD_TOP, true);
+        LLUIString formatted_label = getString(STR_TRACK_SKY);
+        for (int i = 2; i < LLSettingsDay::TRACK_MAX; i++)
+        {
+            if (!pday->isTrackEmpty(i))
+            {
+                formatted_label.setArg("[NUM]", llformat("%d", i));
+                track_selection->add(formatted_label.getString(), LLSD::Integer(i), ADD_TOP, true);
+            }
+        }
+    }
+    
+    mSettingAssetID = asset_id;
+    track_selection->setEnabled(true);
+    track_selection->selectFirstItem();
+    getChild<LLView>(BTN_SELECT)->setEnabled(true);
+}
+
+void LLFloaterSettingsPicker::onButtonCancel()
+{
+    closeFloater();
+}
+
+void LLFloaterSettingsPicker::onButtonSelect()
+{
+    if (mCommitSignal)
+    {
+        LLSD res;
+        res["ItemId"] = mSettingItemID;
+        res["Track"] = getChild<LLComboBox>(CMB_TRACK_SELECTION)->getValue();
+        (*mCommitSignal)(this, res);
+    }
+    closeFloater();
+}
+
+BOOL LLFloaterSettingsPicker::handleDoubleClick(S32 x, S32 y, MASK mask)
+{
+    BOOL result = FALSE;
+    if (mSettingItemID.notNull()
+        && mInventoryPanel)
+    {
+        S32 inventory_x = x - mInventoryPanel->getRect().mLeft;
+        S32 inventory_y = y - mInventoryPanel->getRect().mBottom;
+        if (mInventoryPanel->parentPointInView(inventory_x, inventory_y))
+        {
+            // make sure item is selected and visible
+            LLFolderViewItem* item_viewp = mInventoryPanel->getItemByID(mSettingItemID);
+            if (item_viewp && item_viewp->getIsCurSelection() && item_viewp->getVisible())
+            {
+                LLRect target_rect;
+                item_viewp->localRectToOtherView(item_viewp->getLocalRect(), &target_rect, this);
+                if (target_rect.pointInRect(x, y))
+                {
+                    // Quick-apply
+                    if (mCommitSignal)
+                    {
+                        LLSD res;
+                        res["ItemId"] = mSettingItemID;
+                        res["Track"] = getChild<LLComboBox>(CMB_TRACK_SELECTION)->getValue();
+                        (*mCommitSignal)(this, res);
+                    }
+                    closeFloater();
+                    // hit inside panel on selected item, double click should do nothing
+                    result = TRUE;
+                }
+            }
+        }
+    }
+
+    if (!result)
+    {
+        result = LLFloater::handleDoubleClick(x, y, mask);
+    }
+    return result;
+}
+
+BOOL LLFloaterSettingsPicker::handleKeyHere(KEY key, MASK mask)
+{
+    if ((key == KEY_RETURN) && (mask == MASK_NONE))
+    {
+        LLFolderViewItem* item_viewp = mInventoryPanel->getItemByID(mSettingItemID);
+        if (item_viewp && item_viewp->getIsCurSelection() && item_viewp->getVisible())
+        {
+            // Quick-apply
+            if (mCommitSignal)
+            {
+                LLSD res;
+                res["ItemId"] = mSettingItemID;
+                res["Track"] = getChild<LLComboBox>(CMB_TRACK_SELECTION)->getValue();
+                (*mCommitSignal)(this, res);
+            }
+            closeFloater();
+            return TRUE;
+        }
+    }
+
+    return LLFloater::handleKeyHere(key, mask);
+}
+
+void LLFloaterSettingsPicker::onFocusLost()
+{
+    if (isInVisibleChain())
+    {
+        closeFloater();
+    }
+}
+
+//=========================================================================
+void LLFloaterSettingsPicker::setActive(bool active)
+{
+    mActive = active;
+}
+
+void LLFloaterSettingsPicker::setSettingsItemId(const LLUUID &settings_id, bool set_selection)
+{
+    if (mSettingItemID != settings_id && mActive)
+    {
+        mNoCopySettingsSelected = false;
+        mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
+        mSettingItemID = settings_id;
+        if (mSettingItemID.isNull())
+        {
+            mInventoryPanel->getRootFolder()->clearSelection();
+        }
+        else
+        {
+            LLInventoryItem* itemp = gInventory.getItem(settings_id);
+            if (itemp && !itemp->getPermissions().allowCopyBy(gAgent.getID()))
+            {
+                mNoCopySettingsSelected = true;
+            }
+        }
+
+        if (set_selection)
+        {
+            mInventoryPanel->setSelection(settings_id, TAKE_FOCUS_NO);
+        }
+    }
+}
+
+LLInventoryItem* LLFloaterSettingsPicker::findItem(const LLUUID& asset_id, bool copyable_only, bool ignore_library)
+{
+    LLViewerInventoryCategory::cat_array_t cats;
+    LLViewerInventoryItem::item_array_t items;
+    LLAssetIDMatches asset_id_matches(asset_id);
+
+    gInventory.collectDescendentsIf(LLUUID::null,
+        cats,
+        items,
+        LLInventoryModel::INCLUDE_TRASH,
+        asset_id_matches);
+
+    if (items.size())
+    {
+        // search for copyable version first
+        for (S32 i = 0; i < items.size(); i++)
+        {
+            LLInventoryItem* itemp = items[i];
+            LLPermissions item_permissions = itemp->getPermissions();
+            if (item_permissions.allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+            {
+                if(!ignore_library || !gInventory.isObjectDescendentOf(itemp->getUUID(),gInventory.getLibraryRootFolderID()))
+                {
+                    return itemp;
+                }
+            }
+        }
+        // otherwise just return first instance, unless copyable requested
+        if (copyable_only)
+        {
+            return nullptr;
+        }
+        else
+        {
+            if(!ignore_library || !gInventory.isObjectDescendentOf(items[0]->getUUID(),gInventory.getLibraryRootFolderID()))
+            {
+                return items[0];
+            }
+        }
+    }
+
+    return nullptr;
+}
diff --git a/indra/newview/llsettingspicker.h b/indra/newview/llsettingspicker.h
new file mode 100644
index 0000000000000000000000000000000000000000..859f92fbe8e46f7081fa5e9b9565810cd8580c22
--- /dev/null
+++ b/indra/newview/llsettingspicker.h
@@ -0,0 +1,137 @@
+/** 
+ * @file llsettingspicker.h
+ * @author Rider Linden
+ * @brief LLSettingsPicker class header file including related functions
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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$
+ */
+
+#ifndef LL_SETTINGSPICKER_H
+#define LL_SETTINGSPICKER_H
+
+#include "llinventorysettings.h"
+#include "llfloater.h"
+#include "llpermissionsflags.h"
+#include "llfolderview.h"
+#include "llinventory.h"
+#include "llsettingsdaycycle.h"
+
+#include <boost/signals2.hpp>
+
+//=========================================================================
+class LLFilterEditor;
+class LLInventoryPanel;
+
+//=========================================================================
+class LLFloaterSettingsPicker : public LLFloater
+{
+public:
+    enum ETrackMode
+    {
+        TRACK_NONE,
+        TRACK_WATER,
+        TRACK_SKY
+    };
+    typedef std::function<void()>                           close_callback_t;
+    typedef std::function<void(const LLUUID& item_id)>     id_changed_callback_t;
+
+    LLFloaterSettingsPicker(LLView * owner, LLUUID setting_item_id, const LLSD &params = LLSD());
+
+    virtual                 ~LLFloaterSettingsPicker() override;
+
+    void                    setActive(bool active);
+
+    virtual BOOL            postBuild() override;
+    virtual void            onClose(bool app_quitting) override;
+    virtual void            draw() override;
+
+    void                    setSettingsItemId(const LLUUID &settings_id, bool set_selection = true);
+    LLUUID                  getSettingsItemId() const              { return mSettingItemID; }
+
+    void                    setSettingsFilter(LLSettingsType::type_e type);
+    LLSettingsType::type_e  getSettingsFilter() const { return mSettingsType; }
+
+    // Only for day cycle
+    void                    setTrackMode(ETrackMode mode);
+    void                    setTrackWater() { mTrackMode = TRACK_WATER; }
+    void                    setTrackSky() { mTrackMode = TRACK_SKY; }
+
+    // Takes a UUID, wraps get/setImageAssetID
+    virtual void            setValue(const LLSD& value) override;
+    virtual LLSD            getValue() const override;
+
+    static LLUUID                findItemID(const LLUUID& asset_id, bool copyable_only, bool ignore_library = false) 
+    {
+        LLInventoryItem *pitem = findItem(asset_id, copyable_only, ignore_library);
+        if (pitem)
+            return pitem->getUUID();
+        return LLUUID::null;
+    }
+
+    static std::string           findItemName(const LLUUID& asset_id, bool copyable_only, bool ignore_library = false)
+    {
+        LLInventoryItem *pitem = findItem(asset_id, copyable_only, ignore_library);
+        if (pitem)
+            return pitem->getName();
+        return std::string();
+    }
+
+    static LLInventoryItem *     findItem(const LLUUID& asset_id, bool copyable_only, bool ignore_library);
+
+
+private:
+    typedef std::deque<LLFolderViewItem *>  itemlist_t;
+
+    void                    onFilterEdit(const std::string& search_string);
+    void                    onSelectionChange(const itemlist_t &items, bool user_action);
+    static void             onAssetLoadedCb(LLHandle<LLFloater> handle, LLUUID item_id, LLUUID asset_id, LLSettingsBase::ptr_t settings, S32 status);
+    void                    onAssetLoaded(LLUUID asset_id, LLSettingsBase::ptr_t settings);
+    void                    onButtonCancel();
+    void                    onButtonSelect();
+    virtual BOOL            handleDoubleClick(S32 x, S32 y, MASK mask) override;
+    BOOL                    handleKeyHere(KEY key, MASK mask) override;
+    void                    onFocusLost() override;
+
+
+    LLHandle<LLView>        mOwnerHandle;
+    LLUUID                  mSettingItemID;
+    LLUUID                  mSettingAssetID;
+    ETrackMode              mTrackMode;
+
+    LLFilterEditor *        mFilterEdit;
+    LLInventoryPanel *      mInventoryPanel;
+    LLSettingsType::type_e  mSettingsType;
+
+    F32                     mContextConeOpacity;
+    PermissionMask          mImmediateFilterPermMask;
+
+    bool                    mActive;
+    bool				    mNoCopySettingsSelected;
+
+    LLSaveFolderState	    mSavedFolderState;
+
+//     boost::signals2::signal<void(LLUUID id)>                mCommitSignal;
+    boost::signals2::signal<void()>                         mCloseSignal;
+    boost::signals2::signal<void(const LLUUID& item_id)>   mChangeIDSignal;
+};
+
+#endif  // LL_LLTEXTURECTRL_H
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c72a0706cdceb47a71aab25492144fd0f23b8b50
--- /dev/null
+++ b/indra/newview/llsettingsvo.cpp
@@ -0,0 +1,1453 @@
+/**
+* @file llsettingsvo.cpp
+* @author Rider Linden
+* @brief Subclasses for viewer specific settings behaviors.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewercontrol.h"
+#include "llsettingsvo.h"
+
+#include "pipeline.h"
+
+#include <algorithm>
+#include <cstdio>
+#include <boost/make_shared.hpp>
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "v3colorutil.h"
+
+#include "llglslshader.h"
+#include "llviewershadermgr.h"
+
+#include "llagent.h"
+#include "llassettype.h"
+#include "llfloaterperms.h"
+#include "llnotificationsutil.h"
+
+#include "llviewerregion.h"
+#include "llviewerassetupload.h"
+#include "llviewerinventory.h"
+
+#include "llenvironment.h"
+#include "llsky.h"
+
+#include "llpermissions.h"
+
+#include "llinventorymodel.h"
+#include "llassetstorage.h"
+#include "llvfile.h"
+#include "lldrawpoolwater.h"
+
+#include <boost/algorithm/string/replace.hpp>
+#include "llinventoryobserver.h"
+#include "llinventorydefines.h"
+
+#include "lltrans.h"
+
+#undef  VERIFY_LEGACY_CONVERSION
+
+//=========================================================================
+namespace 
+{
+    LLSD ensure_array_4(LLSD in, F32 fill);
+    LLSD read_legacy_preset_data(const std::string &name, const std::string& path, LLSD  &messages);
+
+    //-------------------------------------------------------------------------
+    class LLSettingsInventoryCB : public LLInventoryCallback
+    {
+    public:
+        typedef std::function<void(const LLUUID &)> callback_t;
+
+        LLSettingsInventoryCB(callback_t cbfn) :
+            mCbfn(cbfn)
+        { }
+
+        void fire(const LLUUID& inv_item) override  { if (mCbfn) mCbfn(inv_item); }
+
+    private:
+        callback_t  mCbfn;
+    };
+
+    //-------------------------------------------------------------------------
+}
+
+
+//=========================================================================
+void LLSettingsVOBase::createNewInventoryItem(LLSettingsType::type_e stype, const LLUUID &parent_id, inventory_result_fn callback)
+{
+    LLTransactionID tid;
+    U32 nextOwnerPerm = LLFloaterPerms::getNextOwnerPerms("Settings");
+    nextOwnerPerm |= PERM_COPY;
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    tid.generate();
+
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([callback](const LLUUID &inventoryId) {
+        LLSettingsVOBase::onInventoryItemCreated(inventoryId, LLSettingsBase::ptr_t(), callback);
+    });
+
+    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
+        parent_id, LLTransactionID::tnull,
+        LLSettingsType::getDefaultName(stype), "",
+        stype, nextOwnerPerm, cb);
+}
+
+
+void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback)
+{
+    U32 nextOwnerPerm = LLPermissions::DEFAULT.getMaskNextOwner();
+    createInventoryItem(settings, nextOwnerPerm, parent_id, settings_name, callback);
+}
+
+void LLSettingsVOBase::createInventoryItem(const LLSettingsBase::ptr_t &settings, U32 next_owner_perm, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback)
+{
+    LLTransactionID tid;
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    tid.generate();
+
+    LLPointer<LLInventoryCallback> cb = new LLSettingsInventoryCB([settings, callback](const LLUUID &inventoryId) {
+            LLSettingsVOBase::onInventoryItemCreated(inventoryId, settings, callback);
+        });
+
+    if (settings_name.empty())
+    {
+        settings_name = settings->getName();
+    }
+    create_inventory_settings(gAgent.getID(), gAgent.getSessionID(),
+        parent_id, tid,
+        settings_name, "",
+        settings->getSettingsTypeValue(), next_owner_perm, cb);
+}
+
+void LLSettingsVOBase::onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback)
+{
+    LLViewerInventoryItem *pitem = gInventory.getItem(inventoryId);
+    if (pitem)
+    {
+        LLPermissions perm = pitem->getPermissions();
+        if (perm.getMaskEveryone() != PERM_COPY)
+        {
+            perm.setMaskEveryone(PERM_COPY);
+            pitem->setPermissions(perm);
+            pitem->updateServer(FALSE);
+        }
+    }
+    if (!settings)
+    {   // The item was created as new with no settings passed in.  Simulator should have given it the default for the type... check ID, 
+        // no need to upload asset.
+        LLUUID asset_id;
+        if (pitem)
+        {
+            asset_id = pitem->getAssetUUID();
+        }
+        if (callback)
+            callback(asset_id, inventoryId, LLUUID::null, LLSD());
+        return;
+    }
+    // We need to update some inventory stuff here.... maybe.
+    updateInventoryItem(settings, inventoryId, callback, false);
+}
+
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback, bool update_name)
+{
+    const LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
+        return;
+    }
+
+    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    LLViewerInventoryItem *inv_item = gInventory.getItem(inv_item_id);
+    if (inv_item)
+    {
+        bool need_update(false);
+        LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
+
+        if (settings->getFlag(LLSettingsBase::FLAG_NOTRANS) && new_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+        {
+            LLPermissions perm(inv_item->getPermissions());
+            perm.setBaseBits(LLUUID::null, FALSE, PERM_TRANSFER);
+            perm.setOwnerBits(LLUUID::null, FALSE, PERM_TRANSFER);
+            new_item->setPermissions(perm);
+            need_update |= true;
+        }
+        if (update_name && (settings->getName() != new_item->getName()))
+        {
+            new_item->rename(settings->getName());
+            settings->setName(new_item->getName()); // account for corrections
+            need_update |= true;
+        }
+        if (need_update)
+        {
+            new_item->updateServer(FALSE);
+            gInventory.updateItem(new_item);
+            gInventory.notifyObservers();
+        }
+    }
+
+    std::stringstream buffer; 
+    LLSD settingdata(settings->getSettings());
+    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
+
+    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(), 
+        [settings, callback](LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response) {
+            LLSettingsVOBase::onAgentAssetUploadComplete(itemId, newAssetId, newItemId, response, settings, callback);
+        });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback)
+{
+    const LLViewerRegion* region = gAgent.getRegion();
+    if (!region)
+    {
+        LL_WARNS("SETTINGS") << "Not connected to a region, cannot save setting." << LL_ENDL;
+        return;
+    }
+
+    std::string agent_url(region->getCapability("UpdateSettingsAgentInventory"));
+
+    if (!LLEnvironment::instance().isInventoryEnabled())
+    {
+        LL_WARNS("SETTINGS") << "Region does not support settings inventory objects." << LL_ENDL;
+        LLNotificationsUtil::add("SettingsUnsuported");
+        return;
+    }
+
+    std::stringstream buffer;
+    LLSD settingdata(settings->getSettings());
+
+    LLSDSerialize::serialize(settingdata, buffer, LLSDSerialize::LLSD_NOTATION);
+
+    LLResourceUploadInfo::ptr_t uploadInfo = std::make_shared<LLBufferedAssetUploadInfo>(object_id, inv_item_id, LLAssetType::AT_SETTINGS, buffer.str(),
+        [settings, callback](LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response) {
+        LLSettingsVOBase::onTaskAssetUploadComplete(itemId, taskId, newAssetId, response, settings, callback);
+    });
+
+    LLViewerAssetUpload::EnqueueInventoryUpload(agent_url, uploadInfo);
+}
+
+void LLSettingsVOBase::onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
+{
+    LL_INFOS("SETTINGS") << "itemId:" << itemId << " newAssetId:" << newAssetId << " newItemId:" << newItemId << " response:" << response << LL_ENDL;
+    psettings->setAssetId(newAssetId);
+    if (callback)
+        callback( newAssetId, itemId, LLUUID::null, response );
+}
+
+void LLSettingsVOBase::onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback)
+{
+    LL_INFOS("SETTINGS") << "Upload to task complete!" << LL_ENDL;
+    psettings->setAssetId(newAssetId);
+    if (callback)
+        callback(newAssetId, itemId, taskId, response);
+}
+
+
+void LLSettingsVOBase::getSettingsAsset(const LLUUID &assetId, LLSettingsVOBase::asset_download_fn callback)
+{
+    gAssetStorage->getAssetData(assetId, LLAssetType::AT_SETTINGS,
+        [callback](LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType, void *, S32 status, LLExtStat ext_status) 
+            { onAssetDownloadComplete(vfs, asset_id, status, ext_status, callback); },
+        nullptr, true);
+
+}
+
+void LLSettingsVOBase::onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, LLSettingsVOBase::asset_download_fn callback)
+{
+    LLSettingsBase::ptr_t settings;
+    if (!status)
+    {
+        LLVFile file(vfs, asset_id, LLAssetType::AT_SETTINGS, LLVFile::READ);
+        S32 size = file.getSize();
+
+        std::string buffer(size + 1, '\0');
+        file.read((U8 *)buffer.data(), size);
+
+        std::stringstream llsdstream(buffer);
+        LLSD llsdsettings;
+
+        if (LLSDSerialize::deserialize(llsdsettings, llsdstream, -1))
+        {
+            settings = createFromLLSD(llsdsettings);
+        }
+
+        if (!settings)
+        {
+            status = 1;
+            LL_WARNS("SETTINGS") << "Unable to create settings object." << LL_ENDL;
+        }
+        else
+        {
+            settings->setAssetId(asset_id);
+        }
+    }
+    else
+    {
+        LL_WARNS("SETTINGS") << "Error retrieving asset " << asset_id << ". Status code=" << status << "(" << LLAssetStorage::getErrorString(status) << ") ext_status=" << ext_status << LL_ENDL;
+    }
+    if (callback)
+        callback(asset_id, settings, status, ext_status);
+}
+
+void LLSettingsVOBase::getSettingsInventory(const LLUUID &inventoryId, inventory_download_fn callback)
+{
+
+}
+
+bool LLSettingsVOBase::exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format)
+{
+    try
+    {
+        std::ofstream file(filename, std::ios::out | std::ios::trunc);
+        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+
+        if (!file)
+        {
+            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for writing." << LL_ENDL;
+            return false;
+        }
+
+        LLSDSerialize::serialize(settings->getSettings(), file, format);
+    }
+    catch (const std::ios_base::failure &e)
+    {
+        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
+        return false;
+    }
+
+    return true;
+}
+
+LLSettingsBase::ptr_t LLSettingsVOBase::importFile(const std::string &filename)
+{
+    LLSD settings;
+
+    try
+    {
+        std::ifstream file(filename, std::ios::in);
+        file.exceptions(std::ios_base::failbit | std::ios_base::badbit);
+
+        if (!file)
+        {
+            LL_WARNS("SETTINGS") << "Unable to open '" << filename << "' for reading." << LL_ENDL;
+            return LLSettingsBase::ptr_t();
+        }
+
+        if (!LLSDSerialize::deserialize(settings, file, -1))
+        {
+            LL_WARNS("SETTINGS") << "Unable to deserialize settings from '" << filename << "'" << LL_ENDL;
+            return LLSettingsBase::ptr_t();
+        }
+    }
+    catch (const std::ios_base::failure &e)
+    {
+        LL_WARNS("SETTINGS") << "Unable to save settings to file '" << filename << "': " << e.what() << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    return createFromLLSD(settings);
+}
+
+LLSettingsBase::ptr_t LLSettingsVOBase::createFromLLSD(const LLSD &settings)
+{
+    if (!settings.has(SETTING_TYPE))
+    {
+        LL_WARNS("SETTINGS") << "No settings type in LLSD" << LL_ENDL;
+        return LLSettingsBase::ptr_t();
+    }
+
+    std::string settingtype = settings[SETTING_TYPE].asString();
+
+    LLSettingsBase::ptr_t psetting;
+
+    if (settingtype == "water")
+    {
+        return LLSettingsVOWater::buildWater(settings);
+    }
+    else if (settingtype == "sky")
+    {
+        return LLSettingsVOSky::buildSky(settings);
+    }
+    else if (settingtype == "daycycle")
+    {
+        return LLSettingsVODay::buildDay(settings);
+    }
+
+    LL_WARNS("SETTINGS") << "Unable to determine settings type for '" << settingtype << "'." << LL_ENDL;
+    return LLSettingsBase::ptr_t();
+
+}
+
+//=========================================================================
+LLSettingsVOSky::LLSettingsVOSky(const LLSD &data, bool isAdvanced)
+: LLSettingsSky(data)
+, m_isAdvanced(isAdvanced)
+{
+}
+
+LLSettingsVOSky::LLSettingsVOSky()
+: LLSettingsSky()
+, m_isAdvanced(false)
+{
+}
+
+//-------------------------------------------------------------------------
+LLSettingsSky::ptr_t LLSettingsVOSky::buildSky(LLSD settings)
+{
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+
+    LLSD results = LLSettingsBase::settingValidation(settings, validations);
+
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    return std::make_shared<LLSettingsVOSky>(settings, true);
+}
+
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings, LLSD &messages)
+{
+
+    LLSD newsettings = LLSettingsSky::translateLegacySettings(oldsettings);
+    if (newsettings.isUndefined())
+    {
+        messages["REASONS"] = LLTrans::getString("SettingTranslateError", LLSDMap("NAME", name));
+        return LLSettingsSky::ptr_t();
+    }
+
+    newsettings[SETTING_NAME] = name;
+
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+    LLSD results = LLSettingsBase::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        messages["REASONS"] = LLTrans::getString("SettingValidationError", LLSDMap("NAME", name));
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD oldsettings = LLSettingsVOSky::convertToLegacy(skyp, isAdvanced());
+
+    if (!llsd_equals(oldsettings, oldsettings))
+    {
+        LL_WARNS("SKY") << "Conversion to/from legacy does not match!\n" 
+            << "Old: " << oldsettings
+            << "new: " << oldsettings << LL_ENDL;
+    }
+
+#endif
+
+    return skyp;
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path, messages);
+
+    if (!legacy_data)
+    {   // messages filled in by read_legacy_preset_data
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+
+    return buildFromLegacyPreset(LLURI::unescape(name), legacy_data, messages);
+}
+
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildDefaultSky()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsSky::defaults();
+
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
+
+        LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+        LLSD results = LLSettingsBase::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+            LLSettingsSky::ptr_t();
+        }
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(default_settings);
+    return skyp;
+}
+
+LLSettingsSky::ptr_t LLSettingsVOSky::buildClone() const
+{
+    LLSD settings = cloneSettings();
+    U32 flags = getFlags();
+
+    LLSettingsSky::validation_list_t validations = LLSettingsSky::validationList();
+    LLSD results = LLSettingsBase::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Sky setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsSky::ptr_t();
+    }
+
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(settings);
+    skyp->setFlags(flags);
+    return skyp;
+}
+
+void LLSettingsVOSky::convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings)
+{
+    // These may need to be inferred from new settings' density profiles
+    // if the legacy settings values are not available.
+    if (settings.has(SETTING_LEGACY_HAZE))
+    {
+        LLSD legacyhaze = settings[SETTING_LEGACY_HAZE];
+
+        // work-around for setter formerly putting ambient values in wrong loc...
+        if (legacyhaze.has(SETTING_AMBIENT))
+        {
+            legacy[SETTING_AMBIENT] = ensure_array_4(legacyhaze[SETTING_AMBIENT], 1.0f);
+        }
+        else if (settings.has(SETTING_AMBIENT))
+        {
+            legacy[SETTING_AMBIENT] = ensure_array_4(settings[SETTING_AMBIENT], 1.0f);
+        }
+
+        legacy[SETTING_BLUE_DENSITY] = ensure_array_4(legacyhaze[SETTING_BLUE_DENSITY], 1.0);
+        legacy[SETTING_BLUE_HORIZON] = ensure_array_4(legacyhaze[SETTING_BLUE_HORIZON], 1.0);
+
+        legacy[SETTING_DENSITY_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DENSITY_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
+        legacy[SETTING_DISTANCE_MULTIPLIER] = LLSDArray(legacyhaze[SETTING_DISTANCE_MULTIPLIER].asReal())(0.0f)(0.0f)(1.0f);
+
+        legacy[SETTING_HAZE_DENSITY]        = LLSDArray(legacyhaze[SETTING_HAZE_DENSITY])(0.0f)(0.0f)(1.0f);
+        legacy[SETTING_HAZE_HORIZON]        = LLSDArray(legacyhaze[SETTING_HAZE_HORIZON])(0.0f)(0.0f)(1.0f);
+    }
+}
+
+LLSD LLSettingsVOSky::convertToLegacy(const LLSettingsSky::ptr_t &psky, bool isAdvanced)
+{
+    LLSD legacy(LLSD::emptyMap());
+    LLSD settings = psky->getSettings();
+    
+    convertAtmosphericsToLegacy(legacy, settings);
+
+    legacy[SETTING_CLOUD_COLOR] = ensure_array_4(settings[SETTING_CLOUD_COLOR], 1.0);
+    legacy[SETTING_CLOUD_POS_DENSITY1] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY1], 1.0);
+    legacy[SETTING_CLOUD_POS_DENSITY2] = ensure_array_4(settings[SETTING_CLOUD_POS_DENSITY2], 1.0);
+    legacy[SETTING_CLOUD_SCALE] = LLSDArray(settings[SETTING_CLOUD_SCALE])(LLSD::Real(0.0))(LLSD::Real(0.0))(LLSD::Real(1.0));       
+    legacy[SETTING_CLOUD_SCROLL_RATE] = settings[SETTING_CLOUD_SCROLL_RATE];
+    legacy[SETTING_LEGACY_ENABLE_CLOUD_SCROLL] = LLSDArray(LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][0].asReal())))
+        (LLSD::Boolean(!is_approx_zero(settings[SETTING_CLOUD_SCROLL_RATE][1].asReal())));     
+    legacy[SETTING_CLOUD_SHADOW] = LLSDArray(settings[SETTING_CLOUD_SHADOW].asReal())(0.0f)(0.0f)(1.0f);    
+    legacy[SETTING_GAMMA] = LLSDArray(settings[SETTING_GAMMA])(0.0f)(0.0f)(1.0f);
+    legacy[SETTING_GLOW] = ensure_array_4(settings[SETTING_GLOW], 1.0);
+    legacy[SETTING_LIGHT_NORMAL] = ensure_array_4(psky->getLightDirection().getValue(), 0.0f);
+    legacy[SETTING_MAX_Y] = LLSDArray(settings[SETTING_MAX_Y])(0.0f)(0.0f)(1.0f);
+    legacy[SETTING_STAR_BRIGHTNESS] = settings[SETTING_STAR_BRIGHTNESS].asReal() / 250.0f; // convert from 0-500 -> 0-2 ala pre-FS-compat changes
+    legacy[SETTING_SUNLIGHT_COLOR] = ensure_array_4(settings[SETTING_SUNLIGHT_COLOR], 1.0f);
+    
+    LLVector3 dir = psky->getLightDirection();
+
+    F32 phi     = asin(dir.mV[2]);
+    F32 cos_phi = cosf(phi);
+    F32 theta   = (cos_phi != 0) ? asin(dir.mV[1] / cos_phi) : 0.0f;
+
+    theta = -theta;
+
+    // get angles back into valid ranges for legacy viewer...
+    //
+    while (theta < 0)
+    {
+        theta += F_PI * 2;
+    }
+    
+    if (theta > 4 * F_PI)
+    {
+        theta = fmod(theta, 2 * F_PI);
+    }
+    
+    while (phi < -F_PI)
+    {
+        phi += 2 * F_PI;
+    }
+    
+    if (phi > 3 * F_PI)
+    {
+        phi = F_PI + fmod(phi - F_PI, 2 * F_PI);
+    }
+
+    legacy[SETTING_LEGACY_EAST_ANGLE] = theta;
+    legacy[SETTING_LEGACY_SUN_ANGLE]  = phi;
+ 
+   return legacy;    
+}
+
+//-------------------------------------------------------------------------
+void LLSettingsVOSky::updateSettings()
+{
+    LLSettingsSky::updateSettings();
+    LLVector3 sun_direction  = getSunDirection();
+    LLVector3 moon_direction = getMoonDirection();
+
+    // Want the dot prod of sun w/ high noon vector (0,0,1), which is just the z component
+    F32 dp = llmax(sun_direction[2], 0.0f); // clamped to 0 when sun is down
+
+    // Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
+    // between sunlight and point lights in windlight to normalize point lights.
+    //
+    // After some A/B comparison of relesae vs EEP, tweak to allow strength to fall below 2 
+    // at night, for better match. (mSceneLightStrength is a divisor, so lower value means brighter
+    // local lights)
+	F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
+    mSceneLightStrength = 2.0f * (0.75f + sun_dynamic_range * dp);
+
+    gSky.setSunAndMoonDirectionsCFR(sun_direction, moon_direction);
+    gSky.setSunTextures(getSunTextureId(), getNextSunTextureId());
+    gSky.setMoonTextures(getMoonTextureId(), getNextMoonTextureId());
+    gSky.setCloudNoiseTextures(getCloudNoiseTextureId(), getNextCloudNoiseTextureId());
+    gSky.setBloomTextures(getBloomTextureId(), getNextBloomTextureId());
+
+    gSky.setSunScale(getSunScale());
+    gSky.setMoonScale(getMoonScale());
+}
+
+void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    LLVector4 light_direction = LLEnvironment::instance().getClampedLightNorm();
+
+    if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
+	{        
+    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);
+	shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+	} 
+	else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
+	{
+    shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, light_direction.mV);        
+
+    LLVector4 vect_c_p_d1(mSettings[SETTING_CLOUD_POS_DENSITY1]);
+    vect_c_p_d1 += LLVector4(LLEnvironment::instance().getCloudScrollDelta());
+    shader->uniform4fv(LLShaderMgr::CLOUD_POS_DENSITY1, 1, vect_c_p_d1.mV);
+
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    LLColor4 sunDiffuse = psky->getSunlightColor();
+    LLColor4 moonDiffuse = psky->getMoonlightColor();
+
+    shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, sunDiffuse.mV);
+    shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, moonDiffuse.mV);
+
+    LLColor4 cloud_color(psky->getCloudColor(), 1.0);
+    shader->uniform4fv(LLShaderMgr::CLOUD_COLOR, 1, cloud_color.mV);
+	}
+    
+    shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);
+
+    LLColor4 ambient(getTotalAmbient());
+    shader->uniform4fv(LLShaderMgr::AMBIENT, 1, ambient.mV);
+
+    shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, getIsSunUp() ? 1 : 0);
+    shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor());
+    shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier());
+    shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier());
+    
+    F32 g             = getGamma();    
+    F32 display_gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
+
+    shader->uniform1f(LLShaderMgr::GAMMA, g);
+    shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, display_gamma);
+}
+
+LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
+{
+    static parammapping_t param_map;
+
+    if (param_map.empty())
+    {
+// LEGACY_ATMOSPHERICS
+
+        // Todo: default 'legacy' values duplicate the ones from functions like getBlueDensity() find a better home for them
+        // There is LLSettingsSky::defaults(), but it doesn't contain everything since it is geared towards creating new settings.
+        param_map[SETTING_AMBIENT] = DefaultParam(LLShaderMgr::AMBIENT, LLColor3(0.25f, 0.25f, 0.25f).getValue());
+        param_map[SETTING_BLUE_DENSITY] = DefaultParam(LLShaderMgr::BLUE_DENSITY, LLColor3(0.2447f, 0.4487f, 0.7599f).getValue());
+        param_map[SETTING_BLUE_HORIZON] = DefaultParam(LLShaderMgr::BLUE_HORIZON, LLColor3(0.4954f, 0.4954f, 0.6399f).getValue());
+        param_map[SETTING_HAZE_DENSITY] = DefaultParam(LLShaderMgr::HAZE_DENSITY, LLSD(0.7f));
+        param_map[SETTING_HAZE_HORIZON] = DefaultParam(LLShaderMgr::HAZE_HORIZON, LLSD(0.19f));
+        param_map[SETTING_DENSITY_MULTIPLIER] = DefaultParam(LLShaderMgr::DENSITY_MULTIPLIER, LLSD(0.0001f));
+        param_map[SETTING_DISTANCE_MULTIPLIER] = DefaultParam(LLShaderMgr::DISTANCE_MULTIPLIER, LLSD(0.8f));
+
+        // Following values are always present, so we can just zero these ones, but used values from defaults()
+        LLSD sky_defaults = LLSettingsSky::defaults();
+        
+        param_map[SETTING_CLOUD_POS_DENSITY2] = DefaultParam(LLShaderMgr::CLOUD_POS_DENSITY2, sky_defaults[SETTING_CLOUD_POS_DENSITY2]);
+        param_map[SETTING_CLOUD_SCALE] = DefaultParam(LLShaderMgr::CLOUD_SCALE, sky_defaults[SETTING_CLOUD_SCALE]);
+        param_map[SETTING_CLOUD_SHADOW] = DefaultParam(LLShaderMgr::CLOUD_SHADOW, sky_defaults[SETTING_CLOUD_SHADOW]);
+        param_map[SETTING_CLOUD_VARIANCE] = DefaultParam(LLShaderMgr::CLOUD_VARIANCE, sky_defaults[SETTING_CLOUD_VARIANCE]);
+        param_map[SETTING_GLOW] = DefaultParam(LLShaderMgr::GLOW, sky_defaults[SETTING_GLOW]);
+        param_map[SETTING_MAX_Y] = DefaultParam(LLShaderMgr::MAX_Y, sky_defaults[SETTING_MAX_Y]);
+
+        //param_map[SETTING_SUNLIGHT_COLOR] = DefaultParam(LLShaderMgr::SUNLIGHT_COLOR, sky_defaults[SETTING_SUNLIGHT_COLOR]);
+        //param_map[SETTING_CLOUD_COLOR] = DefaultParam(LLShaderMgr::CLOUD_COLOR, sky_defaults[SETTING_CLOUD_COLOR]);
+
+        param_map[SETTING_MOON_BRIGHTNESS] = DefaultParam(LLShaderMgr::MOON_BRIGHTNESS, sky_defaults[SETTING_MOON_BRIGHTNESS]);
+        param_map[SETTING_SKY_MOISTURE_LEVEL] = DefaultParam(LLShaderMgr::MOISTURE_LEVEL, sky_defaults[SETTING_SKY_MOISTURE_LEVEL]);
+        param_map[SETTING_SKY_DROPLET_RADIUS] = DefaultParam(LLShaderMgr::DROPLET_RADIUS, sky_defaults[SETTING_SKY_DROPLET_RADIUS]);
+        param_map[SETTING_SKY_ICE_LEVEL] = DefaultParam(LLShaderMgr::ICE_LEVEL, sky_defaults[SETTING_SKY_ICE_LEVEL]);
+
+// AdvancedAtmospherics TODO
+// Provide mappings for new shader params here
+    }
+
+    return param_map;
+}
+
+//=========================================================================
+const F32 LLSettingsVOWater::WATER_FOG_LIGHT_CLAMP(0.3f);
+
+//-------------------------------------------------------------------------
+LLSettingsVOWater::LLSettingsVOWater(const LLSD &data) :
+    LLSettingsWater(data)
+{
+
+}
+
+LLSettingsVOWater::LLSettingsVOWater() :
+    LLSettingsWater()
+{
+
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildWater(LLSD settings)
+{
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Water setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsWater::ptr_t();
+    }
+
+    return std::make_shared<LLSettingsVOWater>(settings);
+}
+
+//-------------------------------------------------------------------------
+LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings, LLSD &messages)
+{
+    LLSD newsettings(LLSettingsWater::translateLegacySettings(oldsettings));
+    if (newsettings.isUndefined())
+    {
+        messages["REASONS"] = LLTrans::getString("SettingTranslateError", LLSDMap("NAME", name));
+        return LLSettingsWater::ptr_t();
+    }
+
+    newsettings[SETTING_NAME] = name; 
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        messages["REASONS"] = LLTrans::getString("SettingValidationError", name);
+        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsWater::ptr_t();
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD oldsettings = LLSettingsVOWater::convertToLegacy(waterp);
+
+    if (!llsd_equals(oldsettings, oldsettings))
+    {
+        LL_WARNS("WATER") << "Conversion to/from legacy does not match!\n"
+            << "Old: " << oldsettings
+            << "new: " << oldsettings << LL_ENDL;
+    }
+
+#endif
+    return waterp;
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path, messages);
+
+    if (!legacy_data)
+    {   // messages filled in by read_legacy_preset_data
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+
+    return buildFromLegacyPreset(LLURI::unescape(name), legacy_data, messages);
+}
+
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildDefaultWater()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsWater::defaults();
+
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
+
+        LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+        LLSD results = LLSettingsWater::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+            return LLSettingsWater::ptr_t();
+        }
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(default_settings);
+
+    return waterp;
+}
+
+LLSettingsWater::ptr_t LLSettingsVOWater::buildClone() const
+{
+    LLSD settings = cloneSettings();
+    U32 flags = getFlags();
+    LLSettingsWater::validation_list_t validations = LLSettingsWater::validationList();
+    LLSD results = LLSettingsWater::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Water setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsWater::ptr_t();
+    }
+
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
+    waterp->setFlags(flags);
+    return waterp;
+}
+
+LLSD LLSettingsVOWater::convertToLegacy(const LLSettingsWater::ptr_t &pwater)
+{
+    LLSD legacy(LLSD::emptyMap());
+    LLSD settings = pwater->getSettings();
+
+    legacy[SETTING_LEGACY_BLUR_MULTIPLIER] = settings[SETTING_BLUR_MULTIPLIER];
+    legacy[SETTING_LEGACY_FOG_COLOR] = ensure_array_4(settings[SETTING_FOG_COLOR], 1.0f);
+    legacy[SETTING_LEGACY_FOG_DENSITY] = settings[SETTING_FOG_DENSITY];
+    legacy[SETTING_LEGACY_FOG_MOD] = settings[SETTING_FOG_MOD];
+    legacy[SETTING_LEGACY_FRESNEL_OFFSET] = settings[SETTING_FRESNEL_OFFSET];
+    legacy[SETTING_LEGACY_FRESNEL_SCALE] = settings[SETTING_FRESNEL_SCALE];
+    legacy[SETTING_LEGACY_NORMAL_MAP] = settings[SETTING_NORMAL_MAP];
+    legacy[SETTING_LEGACY_NORMAL_SCALE] = settings[SETTING_NORMAL_SCALE];
+    legacy[SETTING_LEGACY_SCALE_ABOVE] = settings[SETTING_SCALE_ABOVE];
+    legacy[SETTING_LEGACY_SCALE_BELOW] = settings[SETTING_SCALE_BELOW];
+    legacy[SETTING_LEGACY_WAVE1_DIR] = settings[SETTING_WAVE1_DIR];
+    legacy[SETTING_LEGACY_WAVE2_DIR] = settings[SETTING_WAVE2_DIR];
+    
+    return legacy;
+}
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+void LLSettingsVOWater::applySpecial(void *ptarget, bool force)
+{
+    LLGLSLShader *shader = (LLGLSLShader *)ptarget;
+
+    LLEnvironment& env = LLEnvironment::instance();
+
+    if (force || (shader->mShaderGroup == LLGLSLShader::SG_WATER))
+	{
+        F32 water_height = env.getWaterHeight();
+
+        //transform water plane to eye space
+        glh::vec3f norm(0.f, 0.f, 1.f);
+        glh::vec3f p(0.f, 0.f, water_height + 0.1f);
+
+        F32 modelView[16];
+        for (U32 i = 0; i < 16; i++)
+        {
+            modelView[i] = (F32)gGLModelView[i];
+        }
+
+        glh::matrix4f mat(modelView);
+        glh::matrix4f invtrans = mat.inverse().transpose();
+        glh::vec3f enorm;
+        glh::vec3f ep;
+        invtrans.mult_matrix_vec(norm, enorm);
+        enorm.normalize();
+        mat.mult_matrix_vec(p, ep);
+
+        LLVector4 waterPlane(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
+
+        shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, waterPlane.mV);
+
+        LLVector4 light_direction = env.getClampedLightNorm();
+
+        F32 waterFogKS = 1.f / llmax(light_direction.mV[2], WATER_FOG_LIGHT_CLAMP);
+
+        shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS);
+
+        F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - water_height;
+        bool underwater = (eyedepth <= 0.0f);
+
+        F32 waterFogDensity = env.getCurrentWater()->getModifiedWaterFogDensity(underwater);
+        shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, waterFogDensity);
+
+        LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor(), 0.0f);
+        shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
+
+        F32 blend_factor = env.getCurrentWater()->getBlendFactor();
+        shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+        // update to normal lightnorm, water shader itself will use rotated lightnorm as necessary
+        shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, light_direction.mV);
+    }
+}
+
+void LLSettingsVOWater::updateSettings()
+{
+    // base class clears dirty flag so as to not trigger recursive update
+    LLSettingsBase::updateSettings();
+
+    LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER);
+    if (pwaterpool)
+    {
+        pwaterpool->setTransparentTextures(getTransparentTextureID(), getNextTransparentTextureID());
+        pwaterpool->setOpaqueTexture(GetDefaultOpaqueTextureAssetId());
+        pwaterpool->setNormalMaps(getNormalMapID(), getNextNormalMapID());
+    }
+}
+
+LLSettingsWater::parammapping_t LLSettingsVOWater::getParameterMap() const
+{
+    static parammapping_t param_map;
+
+    if (param_map.empty())
+    {
+        //LLSD water_defaults = LLSettingsWater::defaults();
+        //param_map[SETTING_FOG_COLOR] = DefaultParam(LLShaderMgr::WATER_FOGCOLOR, water_defaults[SETTING_FOG_COLOR]);
+        // let this get set by LLSettingsVOWater::applySpecial so that it can properly reflect the underwater modifier
+        //param_map[SETTING_FOG_DENSITY] = DefaultParam(LLShaderMgr::WATER_FOGDENSITY, water_defaults[SETTING_FOG_DENSITY]);
+    }
+    return param_map;
+}
+
+//=========================================================================
+LLSettingsVODay::LLSettingsVODay(const LLSD &data):
+    LLSettingsDay(data)
+{}
+
+LLSettingsVODay::LLSettingsVODay():
+    LLSettingsDay()
+{}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDay(LLSD settings)
+{
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t pday = std::make_shared<LLSettingsVODay>(settings);
+    if (pday)
+        pday->initialize();
+
+    return pday;
+}
+
+//-------------------------------------------------------------------------
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPreset(const std::string &name, const std::string &path, const LLSD &oldsettings, LLSD &messages)
+{
+    LLSD newsettings(defaults());
+    std::set<std::string> framenames;
+    std::set<std::string> notfound;
+
+    std::string base_path(gDirUtilp->getDirName(path));
+    std::string water_path(base_path);
+    std::string sky_path(base_path);
+
+    gDirUtilp->append(water_path, "water");
+    gDirUtilp->append(sky_path, "skies");
+
+    newsettings[SETTING_NAME] = name;
+
+    LLSD watertrack = LLSDArray(
+        LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
+        (SETTING_KEYNAME, "water:Default"));
+
+    LLSD skytrack = LLSD::emptyArray();
+
+    for (LLSD::array_const_iterator it = oldsettings.beginArray(); it != oldsettings.endArray(); ++it)
+    {
+        std::string framename = (*it)[1].asString();
+        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
+            (SETTING_KEYNAME, "sky:" + framename);
+        framenames.insert(framename);
+        skytrack.append(entry);
+    }
+
+    newsettings[SETTING_TRACKS] = LLSDArray(watertrack)(skytrack);
+
+    LLSD frames(LLSD::emptyMap());
+
+    {
+        LLSettingsWater::ptr_t pwater = LLSettingsVOWater::buildFromLegacyPresetFile("Default", water_path, messages);
+        if (!pwater)
+        {   // messages filled in by buildFromLegacyPresetFile
+            return LLSettingsDay::ptr_t();
+        }
+        frames["water:Default"] = pwater->getSettings();
+    }
+
+    for (std::set<std::string>::iterator itn = framenames.begin(); itn != framenames.end(); ++itn)
+    {
+        LLSettingsSky::ptr_t psky = LLSettingsVOSky::buildFromLegacyPresetFile((*itn), sky_path, messages);
+        if (!psky)
+        {   // messages filled in by buildFromLegacyPresetFile
+            return LLSettingsDay::ptr_t();
+        }
+        frames["sky:" + (*itn)] = psky->getSettings();
+    }
+
+    newsettings[SETTING_FRAMES] = frames;
+
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        messages["REASONS"] = LLTrans::getString("SettingValidationError", LLSDMap("NAME", name));
+        LL_WARNS("SETTINGS") << "Day setting validation failed!: " << results << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
+
+#ifdef VERIFY_LEGACY_CONVERSION
+    LLSD testsettings = LLSettingsVODay::convertToLegacy(dayp);
+
+    if (!llsd_equals(oldsettings, testsettings))
+    {
+        LL_WARNS("DAYCYCLE") << "Conversion to/from legacy does not match!\n" 
+            << "Old: " << oldsettings
+            << "new: " << testsettings << LL_ENDL;
+    }
+
+#endif
+
+    dayp->initialize();
+
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages)
+{
+    LLSD legacy_data = read_legacy_preset_data(name, path, messages);
+
+    if (!legacy_data)
+    {   // messages filled in by read_legacy_preset_data
+        LL_WARNS("SETTINGS") << "Could not load legacy Windlight \"" << name << "\" from " << path << LL_ENDL;
+        return ptr_t();
+    }
+    // Name for LLSettingsDay only, path to get related files from filesystem
+    return buildFromLegacyPreset(LLURI::unescape(name), path, legacy_data, messages);
+}
+
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skydefs, LLSD waterdef)
+{
+    LLSD frames(LLSD::emptyMap());
+
+    for (LLSD::map_iterator itm = skydefs.beginMap(); itm != skydefs.endMap(); ++itm)
+    {
+        std::string newname = "sky:" + (*itm).first;
+        LLSD newsettings = LLSettingsSky::translateLegacySettings((*itm).second);
+        
+        newsettings[SETTING_NAME] = newname;
+        frames[newname] = newsettings;
+
+        LL_WARNS("SETTINGS") << "created region sky '" << newname << "'" << LL_ENDL;
+    }
+
+    LLSD watersettings = LLSettingsWater::translateLegacySettings(waterdef);
+    std::string watername = "water:"+ watersettings[SETTING_NAME].asString();
+    watersettings[SETTING_NAME] = watername;
+    frames[watername] = watersettings;
+
+    LLSD watertrack = LLSDArray(
+            LLSDMap(SETTING_KEYKFRAME, LLSD::Real(0.0f))
+            (SETTING_KEYNAME, watername));
+
+    LLSD skytrack(LLSD::emptyArray());
+    for (LLSD::array_const_iterator it = daycycle.beginArray(); it != daycycle.endArray(); ++it)
+    {
+        LLSD entry = LLSDMap(SETTING_KEYKFRAME, (*it)[0].asReal())
+            (SETTING_KEYNAME, "sky:" + (*it)[1].asString());
+        skytrack.append(entry);
+    }
+
+    LLSD newsettings = LLSDMap
+        ( SETTING_NAME, "Region (legacy)" )
+        ( SETTING_TRACKS, LLSDArray(watertrack)(skytrack))
+        ( SETTING_FRAMES, frames )
+        ( SETTING_TYPE, "daycycle" );
+
+    LLSettingsSky::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(newsettings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!:" << results << LL_ENDL;
+        return LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(newsettings);
+    
+    if (dayp)
+    {
+        // true for validation - either validate here, or when cloning for floater.
+        dayp->initialize(true);
+    }
+    return dayp;
+}
+
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDefaultDayCycle()
+{
+    static LLSD default_settings;
+
+    if (!default_settings.size())
+    {
+        default_settings = LLSettingsDay::defaults();
+        default_settings[SETTING_NAME] = DEFAULT_SETTINGS_NAME;
+
+        LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+        LLSD results = LLSettingsDay::settingValidation(default_settings, validations);
+        if (!results["success"].asBoolean())
+        {
+            LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+            LLSettingsDay::ptr_t();
+        }
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(default_settings);
+
+    dayp->initialize();
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildFromEnvironmentMessage(LLSD settings)
+{
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
+
+    dayp->initialize();
+    return dayp;
+}
+
+
+void LLSettingsVODay::buildFromOtherSetting(LLSettingsBase::ptr_t settings, LLSettingsVODay::asset_built_fn cb)
+{
+    if (settings->getSettingsType() == "daycycle")
+    {
+        if (cb)
+            cb(std::static_pointer_cast<LLSettingsDay>(settings));
+    }
+    else
+    {
+        LLSettingsVOBase::getSettingsAsset(LLSettingsDay::GetDefaultAssetId(),
+            [settings, cb](LLUUID, LLSettingsBase::ptr_t pday, S32, LLExtStat){ combineIntoDayCycle(std::static_pointer_cast<LLSettingsDay>(pday), settings, cb); });
+    }
+}
+
+void LLSettingsVODay::combineIntoDayCycle(LLSettingsDay::ptr_t pday, LLSettingsBase::ptr_t settings, asset_built_fn cb)
+{
+    if (settings->getSettingsType() == "sky")
+    {
+        pday->setName("sky: " + settings->getName());
+        pday->clearCycleTrack(1);
+        pday->setSettingsAtKeyframe(settings, 0.0, 1);
+    }
+    else if (settings->getSettingsType() == "water")
+    {
+        pday->setName("water: " + settings->getName());
+        pday->clearCycleTrack(0);
+        pday->setSettingsAtKeyframe(settings, 0.0, 0);
+    }
+    else
+    {
+        pday.reset();
+    }
+
+    if (cb)
+        cb(pday);
+}
+
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildClone() const
+{
+    LLSD settings = cloneSettings();
+
+    LLSettingsDay::validation_list_t validations = LLSettingsDay::validationList();
+    LLSD results = LLSettingsDay::settingValidation(settings, validations);
+    if (!results["success"].asBoolean())
+    {
+        LL_WARNS("SETTINGS") << "Day setting validation failed!\n" << results << LL_ENDL;
+        LLSettingsDay::ptr_t();
+    }
+
+    LLSettingsDay::ptr_t dayp = std::make_shared<LLSettingsVODay>(settings);
+
+    U32 flags = getFlags();
+    if (flags)
+        dayp->setFlags(flags);
+
+    dayp->initialize();
+    return dayp;
+}
+
+LLSettingsDay::ptr_t LLSettingsVODay::buildDeepCloneAndUncompress() const
+{
+    // no need for SETTING_TRACKS or SETTING_FRAMES, so take base LLSD
+    LLSD settings = llsd_clone(mSettings);
+
+    U32 flags = getFlags();
+    LLSettingsDay::ptr_t day_clone = std::make_shared<LLSettingsVODay>(settings);
+
+    for (S32 i = 0; i < LLSettingsDay::TRACK_MAX; ++i)
+    {
+        const LLSettingsDay::CycleTrack_t& track = getCycleTrackConst(i);
+        LLSettingsDay::CycleTrack_t::const_iterator iter = track.begin();
+        while (iter != track.end())
+        {
+            // 'Unpack', usually for editing
+            // - frames 'share' settings multiple times
+            // - settings can reuse LLSDs they were initialized from
+            // We do not want for edited frame to change multiple frames in same track, so do a clone
+            day_clone->setSettingsAtKeyframe(iter->second->buildDerivedClone(), iter->first, i);
+            iter++;
+        }
+    }
+    day_clone->setFlags(flags);
+    return day_clone;
+}
+
+LLSD LLSettingsVODay::convertToLegacy(const LLSettingsVODay::ptr_t &pday)
+{
+    CycleTrack_t &trackwater = pday->getCycleTrack(TRACK_WATER);
+
+    LLSettingsWater::ptr_t pwater;
+    if (!trackwater.empty())
+    {
+        pwater = std::static_pointer_cast<LLSettingsWater>((*trackwater.begin()).second);
+    }
+
+    if (!pwater)
+        pwater = LLSettingsVOWater::buildDefaultWater();
+    
+    LLSD llsdwater = LLSettingsVOWater::convertToLegacy(pwater);
+    
+    CycleTrack_t &tracksky = pday->getCycleTrack(1);   // first sky track
+    std::map<std::string, LLSettingsSky::ptr_t> skys;
+    
+    LLSD llsdcycle(LLSD::emptyArray());
+    
+    for(CycleTrack_t::iterator it = tracksky.begin(); it != tracksky.end(); ++it)
+    {
+        size_t hash = (*it).second->getHash();
+        std::stringstream name;
+        
+        name << hash;
+        
+        skys[name.str()] = std::static_pointer_cast<LLSettingsSky>((*it).second);
+        
+        F32 frame = ((tracksky.size() == 1) && (it == tracksky.begin())) ? -1.0f : (*it).first;
+        llsdcycle.append( LLSDArray(LLSD::Real(frame))(name.str()) );
+    }
+
+    LLSD llsdskylist(LLSD::emptyMap());
+    
+    for (std::map<std::string, LLSettingsSky::ptr_t>::iterator its = skys.begin(); its != skys.end(); ++its)
+    {
+        LLSD llsdsky = LLSettingsVOSky::convertToLegacy((*its).second, false);
+        llsdsky[SETTING_NAME] = (*its).first;
+        
+        llsdskylist[(*its).first] = llsdsky;
+    }
+
+    return LLSDArray(LLSD::emptyMap())(llsdcycle)(llsdskylist)(llsdwater);
+}
+
+LLSettingsSkyPtr_t  LLSettingsVODay::getDefaultSky() const
+{
+    return LLSettingsVOSky::buildDefaultSky();
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::getDefaultWater() const
+{
+    return LLSettingsVOWater::buildDefaultWater();
+}
+
+LLSettingsSkyPtr_t LLSettingsVODay::buildSky(LLSD settings) const
+{
+    LLSettingsSky::ptr_t skyp = std::make_shared<LLSettingsVOSky>(settings);
+
+    if (skyp->validate())
+        return skyp;
+
+    return LLSettingsSky::ptr_t();
+}
+
+LLSettingsWaterPtr_t LLSettingsVODay::buildWater(LLSD settings) const
+{
+    LLSettingsWater::ptr_t waterp = std::make_shared<LLSettingsVOWater>(settings);
+
+    if (waterp->validate())
+        return waterp;
+
+    return LLSettingsWater::ptr_t();
+}
+
+//=========================================================================
+namespace
+{
+    LLSD ensure_array_4(LLSD in, F32 fill)
+    {
+        if (in.size() >= 4)
+            return in;
+
+        LLSD out(LLSD::emptyArray());
+
+        for (S32 idx = 0; idx < in.size(); ++idx)
+        {
+            out.append(in[idx]);
+        }
+
+        while (out.size() < 4)
+        {
+            out.append(LLSD::Real(fill));
+        }
+        return out;
+    }
+
+    // This is a disturbing hack
+    std::string legacy_name_to_filename(const std::string &name, bool convertdash = false)
+    {
+        std::string fixedname(LLURI::escape(name));
+
+        if (convertdash)
+            boost::algorithm::replace_all(fixedname, "-", "%2D");
+
+        return fixedname;
+    }
+
+    //---------------------------------------------------------------------
+    LLSD read_legacy_preset_data(const std::string &name, const std::string& path, LLSD &messages)
+    {
+        llifstream xml_file;
+
+        std::string full_path(path);
+        std::string full_name(name);
+        full_name += ".xml";
+        gDirUtilp->append(full_path, full_name);
+
+        xml_file.open(full_path.c_str());
+        if (!xml_file)
+        {
+            std::string bad_path(full_path);
+            full_path = path;
+            full_name = legacy_name_to_filename(name);
+            full_name += ".xml";
+            gDirUtilp->append(full_path, full_name);
+
+            LL_INFOS("LEGACYSETTING") << "Could not open \"" << bad_path << "\" trying escaped \"" << full_path << "\"" << LL_ENDL;
+
+            xml_file.open(full_path.c_str());
+            if (!xml_file)
+            {
+                LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
+
+                full_path = path;
+                full_name = legacy_name_to_filename(name, true);
+                full_name += ".xml";
+                gDirUtilp->append(full_path, full_name);
+                xml_file.open(full_path.c_str());
+                if (!xml_file)
+                {
+                    messages["REASONS"] = LLTrans::getString("SettingImportFileError", LLSDMap("FILE", bad_path));
+                    LL_WARNS("LEGACYSETTING") << "Unable to open legacy windlight \"" << name << "\" from " << path << LL_ENDL;
+                    return LLSD();
+                }
+            }
+        }
+
+        LLSD params_data;
+        LLPointer<LLSDParser> parser = new LLSDXMLParser();
+        if (parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED) == LLSDParser::PARSE_FAILURE)
+        {
+            xml_file.close();
+            messages["REASONS"] = LLTrans::getString("SettingParseFileError", LLSDMap("FILE", full_path));
+            return LLSD();
+        }
+        xml_file.close();
+
+        return params_data;
+    }
+}
diff --git a/indra/newview/llsettingsvo.h b/indra/newview/llsettingsvo.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f29013ecfd469efe9a6309a74a924c0328b7924
--- /dev/null
+++ b/indra/newview/llsettingsvo.h
@@ -0,0 +1,189 @@
+/**
+* @file llsettingsvo.h
+* @author Rider Linden
+* @brief Subclasses for viewer specific settings behaviors.
+*
+* $LicenseInfo:2011&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2017, 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$
+*/
+
+#ifndef LL_SETTINGS_VO_H
+#define LL_SETTINGS_VO_H
+
+#include "llsettingsbase.h"
+#include "llsettingssky.h"
+#include "llsettingswater.h"
+#include "llsettingsdaycycle.h"
+
+#include "llsdserialize.h"
+
+#include "llextendedstatus.h"
+#include <boost/signals2.hpp>
+
+class LLVFS;
+class LLInventoryItem;
+class LLGLSLShader;
+
+//=========================================================================
+class LLSettingsVOBase : public LLSettingsBase
+{
+public:
+    typedef std::function<void(LLUUID asset_id, LLSettingsBase::ptr_t settins, S32 status, LLExtStat extstat)>  asset_download_fn;
+    typedef std::function<void(LLInventoryItem *inv_item, LLSettingsBase::ptr_t settings, S32 status, LLExtStat extstat)> inventory_download_fn;
+    typedef std::function<void(LLUUID asset_id, LLUUID inventory_id, LLUUID object_id, LLSD results)>           inventory_result_fn;
+
+    static void     createNewInventoryItem(LLSettingsType::type_e stype, const LLUUID &parent_id, inventory_result_fn callback = inventory_result_fn());
+    static void     createInventoryItem(const LLSettingsBase::ptr_t &settings, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback = inventory_result_fn());
+    static void     createInventoryItem(const LLSettingsBase::ptr_t &settings, U32 next_owner_perm, const LLUUID &parent_id, std::string settings_name, inventory_result_fn callback = inventory_result_fn());
+
+    static void     updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID inv_item_id, inventory_result_fn callback = inventory_result_fn(), bool update_name = true);
+    static void     updateInventoryItem(const LLSettingsBase::ptr_t &settings, LLUUID object_id, LLUUID inv_item_id, inventory_result_fn callback = inventory_result_fn());
+
+    static void     getSettingsAsset(const LLUUID &assetId, asset_download_fn callback);
+    static void     getSettingsInventory(const LLUUID &inventoryId, inventory_download_fn callback = inventory_download_fn());
+
+    static bool     exportFile(const LLSettingsBase::ptr_t &settings, const std::string &filename, LLSDSerialize::ELLSD_Serialize format = LLSDSerialize::LLSD_NOTATION);
+    static LLSettingsBase::ptr_t importFile(const std::string &filename);
+    static LLSettingsBase::ptr_t createFromLLSD(const LLSD &settings);
+
+private:
+    struct SettingsSaveData
+    {
+        typedef std::shared_ptr<SettingsSaveData> ptr_t;
+        std::string             mType;
+        std::string             mTempFile;
+        LLSettingsBase::ptr_t   mSettings;
+        LLTransactionID         mTransId;
+    };
+
+    LLSettingsVOBase() {}
+
+    static void     onInventoryItemCreated(const LLUUID &inventoryId, LLSettingsBase::ptr_t settings, inventory_result_fn callback);
+
+    static void     onAgentAssetUploadComplete(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback);
+    static void     onTaskAssetUploadComplete(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, LLSettingsBase::ptr_t psettings, inventory_result_fn callback);
+    
+    static void     onAssetDownloadComplete(LLVFS *vfs, const LLUUID &asset_id, S32 status, LLExtStat ext_status, asset_download_fn callback);
+};
+
+//=========================================================================
+class LLSettingsVOSky : public LLSettingsSky
+{
+public:
+    LLSettingsVOSky(const LLSD &data, bool advanced = false);
+
+    static ptr_t    buildSky(LLSD settings);
+
+    static ptr_t buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings, LLSD &messages);
+    static ptr_t    buildDefaultSky();
+    virtual ptr_t   buildClone() const SETTINGS_OVERRIDE;
+
+    static ptr_t buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages);
+
+    static LLSD     convertToLegacy(const ptr_t &, bool isAdvanced);
+
+    bool isAdvanced() const { return  m_isAdvanced; }
+
+    virtual void updateShader(LLGLSLShader* shader) { applySpecial(shader, true); }
+
+protected:
+    LLSettingsVOSky();
+
+    // Interpret new settings in terms of old atmospherics params
+    static void convertAtmosphericsToLegacy(LLSD& legacy, LLSD& settings);
+
+    virtual void    updateSettings() override;
+
+    virtual void    applySpecial(void *, bool) override;
+
+    virtual parammapping_t getParameterMap() const override;
+
+    bool m_isAdvanced = false;
+    F32 mSceneLightStrength = 3.0f;
+};
+
+//=========================================================================
+class LLSettingsVOWater : public LLSettingsWater
+{
+public:
+    LLSettingsVOWater(const LLSD &data);
+
+    static ptr_t    buildWater(LLSD settings);
+
+    static ptr_t buildFromLegacyPreset(const std::string &name, const LLSD &oldsettings, LLSD &messages);
+    static ptr_t    buildDefaultWater();
+    virtual ptr_t   buildClone() const SETTINGS_OVERRIDE;
+
+    static ptr_t buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages);
+
+    static LLSD     convertToLegacy(const ptr_t &);
+
+    virtual void    updateShader(LLGLSLShader* shader) { applySpecial(shader, true); }
+
+protected:
+    LLSettingsVOWater();
+
+    virtual void    updateSettings() override;
+    virtual void    applySpecial(void *, bool) override;
+
+    virtual parammapping_t getParameterMap() const override;
+
+
+private:
+    static const F32 WATER_FOG_LIGHT_CLAMP;
+
+};
+
+//=========================================================================
+class LLSettingsVODay : public LLSettingsDay
+{
+public:
+    typedef std::function<void(LLSettingsDay::ptr_t day)>  asset_built_fn;
+
+    LLSettingsVODay(const LLSD &data);
+
+    static ptr_t    buildDay(LLSD settings);
+
+    static ptr_t buildFromLegacyPreset(const std::string &name, const std::string &path, const LLSD &oldsettings, LLSD &messages);
+    static ptr_t buildFromLegacyPresetFile(const std::string &name, const std::string &path, LLSD &messages);
+    static ptr_t    buildFromLegacyMessage(const LLUUID &regionId, LLSD daycycle, LLSD skys, LLSD water);
+    static ptr_t    buildDefaultDayCycle();
+    static ptr_t    buildFromEnvironmentMessage(LLSD settings);
+    static void     buildFromOtherSetting(LLSettingsBase::ptr_t settings, asset_built_fn cb);
+    virtual ptr_t   buildClone() const SETTINGS_OVERRIDE;
+    virtual ptr_t   buildDeepCloneAndUncompress() const SETTINGS_OVERRIDE;
+
+    static LLSD     convertToLegacy(const ptr_t &);
+    
+    virtual LLSettingsSkyPtr_t      getDefaultSky() const override;
+    virtual LLSettingsWaterPtr_t    getDefaultWater() const override;
+    virtual LLSettingsSkyPtr_t      buildSky(LLSD) const override;
+    virtual LLSettingsWaterPtr_t    buildWater(LLSD) const override;
+
+protected:
+    LLSettingsVODay();
+
+private:
+    static void     combineIntoDayCycle(LLSettingsDay::ptr_t, LLSettingsBase::ptr_t, asset_built_fn);
+};
+
+
+#endif
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp
index d508621b41ff29e23bc6aaaf973e29416b4f556f..b23e24a2227e4008065ffcb17ed0b489b0e82f66 100644
--- a/indra/newview/llsidepaneliteminfo.cpp
+++ b/indra/newview/llsidepaneliteminfo.cpp
@@ -336,6 +336,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 	BOOL is_complete = item->isFinished();
 	const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType());
 	const BOOL is_calling_card = (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
+	const BOOL is_settings = (item->getInventoryType() == LLInventoryType::IT_SETTINGS);
 	const LLPermissions& perm = item->getPermissions();
 	const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm, 
 								GP_OBJECT_MANIPULATE);
@@ -665,14 +666,14 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 	LLUICtrl* edit_cost = getChild<LLUICtrl>("Edit Cost");
 
 	// Check for ability to change values.
-	if (is_obj_modify && can_agent_sell 
+    if (is_obj_modify && can_agent_sell 
 		&& gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
 	{
 		getChildView("CheckPurchase")->setEnabled(is_complete);
 
 		getChildView("NextOwnerLabel")->setEnabled(TRUE);
 		getChildView("CheckNextOwnerModify")->setEnabled((base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
-		getChildView("CheckNextOwnerCopy")->setEnabled((base_mask & PERM_COPY) && !cannot_restrict_permissions);
+		getChildView("CheckNextOwnerCopy")->setEnabled((base_mask & PERM_COPY) && !cannot_restrict_permissions && !is_settings);
 		getChildView("CheckNextOwnerTransfer")->setEnabled((next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
 
 		combo_sale_type->setEnabled(is_complete && is_for_sale);
@@ -691,6 +692,25 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item)
 		edit_cost->setEnabled(FALSE);
 	}
 
+    // Hide any properties that are not relevant to settings
+    if (is_settings)
+    {
+        getChild<LLUICtrl>("GroupLabel")->setEnabled(false);
+        getChild<LLUICtrl>("GroupLabel")->setVisible(false);
+        getChild<LLUICtrl>("CheckShareWithGroup")->setEnabled(false);
+        getChild<LLUICtrl>("CheckShareWithGroup")->setVisible(false);
+        getChild<LLUICtrl>("AnyoneLabel")->setEnabled(false);
+        getChild<LLUICtrl>("AnyoneLabel")->setVisible(false);
+        getChild<LLUICtrl>("CheckEveryoneCopy")->setEnabled(false);
+        getChild<LLUICtrl>("CheckEveryoneCopy")->setVisible(false);
+        getChild<LLUICtrl>("CheckPurchase")->setEnabled(false);
+        getChild<LLUICtrl>("CheckPurchase")->setVisible(false);
+        getChild<LLUICtrl>("ComboBoxSaleType")->setEnabled(false);
+        getChild<LLUICtrl>("ComboBoxSaleType")->setVisible(false);
+        getChild<LLUICtrl>("Edit Cost")->setEnabled(false);
+        getChild<LLUICtrl>("Edit Cost")->setVisible(false);
+    }
+
 	// Set values.
 	getChild<LLUICtrl>("CheckPurchase")->setValue(is_for_sale);
 	getChild<LLUICtrl>("CheckNextOwnerModify")->setValue(LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
diff --git a/indra/newview/llskinningutil.cpp b/indra/newview/llskinningutil.cpp
index 8e1f80abfc41a4c98ff6f4a73a40b9996279bcff..1fb63c7444c1d9a21253bb2b65a4583b171ac64d 100644
--- a/indra/newview/llskinningutil.cpp
+++ b/indra/newview/llskinningutil.cpp
@@ -34,8 +34,12 @@
 #include "llvolume.h"
 #include "llrigginginfo.h"
 
+#define DEBUG_SKINNING  LL_DEBUG
+#define MAT_USE_SSE     1
+
 void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, const LLMeshSkinInfo *skin)
 {
+#if DEBUG_SKINNING
     static S32 dump_count = 0;
     const S32 max_dump = 10;
 
@@ -81,12 +85,12 @@ void dump_avatar_and_skin_state(const std::string& reason, LLVOAvatar *avatar, c
 
         dump_count++;
     }
+#endif
 }
 
-U32 LLSkinningUtil::getMaxJointCount()
+S32 LLSkinningUtil::getMaxJointCount()
 {
-    U32 result = LL_MAX_JOINTS_PER_MESH_OBJECT;
-	return result;
+    return (S32)LL_MAX_JOINTS_PER_MESH_OBJECT;
 }
 
 U32 LLSkinningUtil::getMeshJointCount(const LLMeshSkinInfo *skin)
@@ -116,6 +120,8 @@ void LLSkinningUtil::scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin
     skin->mInvalidJointsScrubbed = true;
 }
 
+#define MAT_USE_SSE 1
+
 void LLSkinningUtil::initSkinningMatrixPalette(
     LLMatrix4* mat,
     S32 count, 
@@ -126,9 +132,9 @@ void LLSkinningUtil::initSkinningMatrixPalette(
     for (U32 j = 0; j < count; ++j)
     {
         LLJoint *joint = avatar->getJoint(skin->mJointNums[j]);
+        llassert(joint);
         if (joint)
         {
-#define MAT_USE_SSE
 #ifdef MAT_USE_SSE
             LLMatrix4a bind, world, res;
             bind.loadu(skin->mInvBindMatrix[j]);
@@ -143,6 +149,7 @@ void LLSkinningUtil::initSkinningMatrixPalette(
         else
         {
             mat[j] = skin->mInvBindMatrix[j];
+#if DEBUG_SKINNING
             // This  shouldn't  happen   -  in  mesh  upload,  skinned
             // rendering  should  be disabled  unless  all joints  are
             // valid.  In other  cases of  skinned  rendering, invalid
@@ -153,16 +160,15 @@ void LLSkinningUtil::initSkinningMatrixPalette(
             LL_WARNS_ONCE("Avatar") << avatar->getFullname() 
                                     << " avatar build state: isBuilt() " << avatar->isBuilt() 
                                     << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
-#if 0
-            dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin);
 #endif
+            dump_avatar_and_skin_state("initSkinningMatrixPalette joint not found", avatar, skin);
         }
     }
 }
 
 void LLSkinningUtil::checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin)
 {
-#ifdef SHOW_ASSERT                  // same condition that controls llassert()
+#if DEBUG_SKINNING
 	const S32 max_joints = skin->mJointNames.size();
     for (U32 j=0; j<num_vertices; j++)
     {
@@ -261,6 +267,7 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar)
     {
         for (U32 j = 0; j < skin->mJointNames.size(); ++j)
         {
+    #if DEBUG_SKINNING     
             LLJoint *joint = NULL;
             if (skin->mJointNums[j] == -1)
             {
@@ -278,11 +285,16 @@ void LLSkinningUtil::initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar)
                 {
                     LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " unable to find joint " << skin->mJointNames[j] << LL_ENDL;
                     LL_WARNS_ONCE("Avatar") << avatar->getFullname() << " avatar build state: isBuilt() " << avatar->isBuilt() << " mInitFlags " << avatar->mInitFlags << LL_ENDL;
-#if 0
                     dump_avatar_and_skin_state("initJointNums joint not found", avatar, skin);
-#endif
+                    skin->mJointNums[j] = 0;
                 }
             }
+    #else
+            LLJoint *joint = (skin->mJointNums[j] == -1) ? avatar->getJoint(skin->mJointNames[j]) : avatar->getJoint(skin->mJointNums[j]);
+            skin->mJointNums[j] = joint ? joint->getJointNum() : 0;            
+    #endif
+            // insure we have *a* valid joint to reference
+            llassert(skin->mJointNums[j] >= 0);
         }
         skin->mJointNumsInitialized = true;
     }
@@ -340,14 +352,17 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
 
                                 // FIXME could precompute these matMuls.
                                 LLMatrix4a bind_shape;
-                                bind_shape.loadu(skin->mBindShapeMatrix);
                                 LLMatrix4a inv_bind;
-                                inv_bind.loadu(skin->mInvBindMatrix[joint_index]);
                                 LLMatrix4a mat;
-                                matMul(bind_shape, inv_bind, mat);
                                 LLVector4a pos_joint_space;
+
+                                bind_shape.loadu(skin->mBindShapeMatrix);
+                                inv_bind.loadu(skin->mInvBindMatrix[joint_index]);
+                                matMul(bind_shape, inv_bind, mat);
+
                                 mat.affineTransform(pos, pos_joint_space);
                                 pos_joint_space.mul(wght[k]);
+
                                 LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents();
                                 update_min_max(extents[0], extents[1], pos_joint_space);
                             }
@@ -362,6 +377,8 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
                 vol_face.mJointRiggingInfoTab.setNeedsUpdate(false);
             }
         }
+
+#if DEBUG_SKINNING
         if (vol_face.mJointRiggingInfoTab.size()!=0)
         {
             LL_DEBUGS("RigSpammish") << "we have rigging info for vf " << &vol_face 
@@ -372,10 +389,40 @@ void LLSkinningUtil::updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *a
             LL_DEBUGS("RigSpammish") << "no rigging info for vf " << &vol_face 
                                      << " num_verts " << vol_face.mNumVertices << LL_ENDL; 
         }
+#endif
 
     }
 }
 
+void LLSkinningUtil::updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab)
+{
+    LL_RECORD_BLOCK_TIME(FTM_FACE_RIGGING_INFO);
+    for (S32 i=0; i < num_verts; i++)
+    {
+        LLVector4a& pos  = positions[i];
+        LLVector4a& wght = weights[i];
+        for (U32 k=0; k<4; ++k)
+        {
+            S32 joint_num = skin->mJointNums[joint_indices[k]];
+            llassert(joint_num >= 0 && joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS);
+            {
+                rig_info_tab[joint_num].setIsRiggedTo(true);
+                LLMatrix4a bind_shape;
+                bind_shape.loadu(skin->mBindShapeMatrix);
+                LLMatrix4a inv_bind;
+                inv_bind.loadu(skin->mInvBindMatrix[joint_indices[k]]);
+                LLMatrix4a mat;
+                matMul(bind_shape, inv_bind, mat);
+                LLVector4a pos_joint_space;
+                mat.affineTransform(pos, pos_joint_space);
+                pos_joint_space.mul(wght[k]);
+                LLVector4a *extents = rig_info_tab[joint_num].getRiggedExtents();
+                update_min_max(extents[0], extents[1], pos_joint_space);
+            }
+        }
+    }
+}
+
 // This is used for extracting rotation from a bind shape matrix that
 // already has scales baked in
 LLQuaternion LLSkinningUtil::getUnscaledQuaternion(const LLMatrix4& mat4)
diff --git a/indra/newview/llskinningutil.h b/indra/newview/llskinningutil.h
index 2c77e030aa525fd682020fffcc77ffbda0c912b2..549aa6a29f7c9c81607296010513c10bb92119b8 100644
--- a/indra/newview/llskinningutil.h
+++ b/indra/newview/llskinningutil.h
@@ -27,22 +27,47 @@
 #ifndef LLSKINNINGUTIL_H
 #define LLSKINNINGUTIL_H
 
+#include "v2math.h"
+#include "v4math.h"
+#include "llvector4a.h"
+#include "llmatrix4a.h"
+
 class LLVOAvatar;
 class LLMeshSkinInfo;
-class LLMatrix4a;
 class LLVolumeFace;
+class LLJointRiggingInfoTab;
 
 namespace LLSkinningUtil
 {
-    U32 getMaxJointCount();
+    S32 getMaxJointCount();
     U32 getMeshJointCount(const LLMeshSkinInfo *skin);
     void scrubInvalidJoints(LLVOAvatar *avatar, LLMeshSkinInfo* skin);
     void initSkinningMatrixPalette(LLMatrix4* mat, S32 count, const LLMeshSkinInfo* skin, LLVOAvatar *avatar);
     void checkSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
     void scrubSkinWeights(LLVector4a* weights, U32 num_vertices, const LLMeshSkinInfo* skin);
     void getPerVertexSkinMatrix(F32* weights, LLMatrix4a* mat, bool handle_bad_scale, LLMatrix4a& final_mat, U32 max_joints);
+
+    LL_FORCE_INLINE void getPerVertexSkinMatrixWithIndices(
+        F32*        weights,
+        U8*         idx,
+        LLMatrix4a* mat,
+        LLMatrix4a& final_mat,
+        LLMatrix4a* src)
+    {    
+        final_mat.clear();
+        src[0].setMul(mat[idx[0]], weights[0]);
+        src[1].setMul(mat[idx[1]], weights[1]);
+        final_mat.add(src[0]);
+        final_mat.add(src[1]);
+        src[2].setMul(mat[idx[2]], weights[2]);        
+        src[3].setMul(mat[idx[3]], weights[3]);
+        final_mat.add(src[2]);
+        final_mat.add(src[3]);
+    }
+
     void initJointNums(LLMeshSkinInfo* skin, LLVOAvatar *avatar);
     void updateRiggingInfo(const LLMeshSkinInfo* skin, LLVOAvatar *avatar, LLVolumeFace& vol_face);
+    void updateRiggingInfo_(LLMeshSkinInfo* skin, LLVOAvatar *avatar, S32 num_verts, LLVector4a* weights, LLVector4a* positions, U8* joint_indices, LLJointRiggingInfoTab &rig_info_tab);
 	LLQuaternion getUnscaledQuaternion(const LLMatrix4& mat4);
 };
 
diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp
index 5e2442798b1ec4d74fab8ef99698d31795036956..ac7dbcacaa114f43406a925b66848d86ae866576 100644
--- a/indra/newview/llsky.cpp
+++ b/indra/newview/llsky.cpp
@@ -51,19 +51,16 @@
 #include "llvosky.h"
 #include "llcubemap.h"
 #include "llviewercontrol.h"
-#include "llenvmanager.h"
-
+#include "llenvironment.h"
+#include "llvoavatarself.h"
 #include "llvowlsky.h"
 
 F32 azimuth_from_vector(const LLVector3 &v);
 F32 elevation_from_vector(const LLVector3 &v);
 
-LLSky				gSky;
-// ---------------- LLSky ----------------
-
-const F32 LLSky::NIGHTTIME_ELEVATION = -8.0f; // degrees
-const F32 LLSky::NIGHTTIME_ELEVATION_COS = (F32)sin(NIGHTTIME_ELEVATION*DEG_TO_RAD);
+LLSky gSky;
 
+// ---------------- LLSky ----------------
 //////////////////////////////////////////////////////////////////////
 // Construction/Destruction
 //////////////////////////////////////////////////////////////////////
@@ -77,8 +74,6 @@ LLSky::LLSky()
 
 	mLightingGeneration = 0;
 	mUpdatedThisFrame = TRUE;
-	mOverrideSimSunPosition = FALSE;
-	mSunPhase = 0.f;
 }
 
 
@@ -134,211 +129,89 @@ void LLSky::resetVertexBuffers()
 	}
 }
 
-void LLSky::setOverrideSun(BOOL override)
+void LLSky::setSunScale(F32 sun_scale)
 {
-	if (!mOverrideSimSunPosition && override)
-	{
-		mLastSunDirection = getSunDirection();
-	}
-	else if (mOverrideSimSunPosition && !override)
-	{
-		setSunDirection(mLastSunDirection, LLVector3::zero);
+    if(mVOSkyp.notNull())
+    {
+        mVOSkyp->setSunScale(sun_scale);
 	}
-	mOverrideSimSunPosition = override;
 }
 
-void LLSky::setSunDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity)
+void LLSky::setMoonScale(F32 moon_scale)
 {
-	if(mVOSkyp.notNull()) {
-		mVOSkyp->setSunDirection(sun_direction, sun_ang_velocity);
+    if(mVOSkyp.notNull())
+    {
+        mVOSkyp->setMoonScale(moon_scale);
 	}
 }
 
-
-void LLSky::setSunTargetDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity)
-{
-	mSunTargDir = sun_direction;
-}
-
-
-LLVector3 LLSky::getSunDirection() const
+void LLSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next)
 {
-	if (mVOSkyp)
-	{
-		return mVOSkyp->getToSun();
-	}
-	else
-	{
-		return LLVector3::z_axis;
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setSunTextures(sun_texture, sun_texture_next);
 	}
 }
 
-
-LLVector3 LLSky::getMoonDirection() const
+void LLSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next)
 {
-	if (mVOSkyp)
-	{
-		return mVOSkyp->getToMoon();
-	}
-	else
-	{
-		return LLVector3::z_axis;
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setMoonTextures(moon_texture, moon_texture_next);
 	}
 }
 
-
-LLColor4 LLSky::getSunDiffuseColor() const
+void LLSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next)
 {
-	if (mVOSkyp)
-	{
-		return LLColor4(mVOSkyp->getSunDiffuseColor());
-	}
-	else
-	{
-		return LLColor4(1.f, 1.f, 1.f, 1.f);
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setCloudNoiseTextures(cloud_noise_texture, cloud_noise_texture_next);
 	}
 }
 
-LLColor4 LLSky::getSunAmbientColor() const
-{
-	if (mVOSkyp)
-	{
-		return LLColor4(mVOSkyp->getSunAmbientColor());
-	}
-	else
-	{
-		return LLColor4(0.f, 0.f, 0.f, 1.f);
-	}
-}
-
-
-LLColor4 LLSky::getMoonDiffuseColor() const
+void LLSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next)
 {
-	if (mVOSkyp)
-	{
-		return LLColor4(mVOSkyp->getMoonDiffuseColor());
-	}
-	else
-	{
-		return LLColor4(1.f, 1.f, 1.f, 1.f);
-	}
-}
-
-LLColor4 LLSky::getMoonAmbientColor() const
-{
-	if (mVOSkyp)
-	{
-		return LLColor4(mVOSkyp->getMoonAmbientColor());
-	}
-	else
-	{
-		return LLColor4(0.f, 0.f, 0.f, 0.f);
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setBloomTextures(bloom_texture, bloom_texture_next);
 	}
 }
 
-
-LLColor4 LLSky::getTotalAmbientColor() const
+void LLSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_direction, const LLVector3 &moon_direction)
 {
-	if (mVOSkyp)
-	{
-		return mVOSkyp->getTotalAmbientColor();
-	}
-	else
-	{
-		return LLColor4(1.f, 1.f, 1.f, 1.f);
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setSunAndMoonDirectionsCFR(sun_direction, moon_direction);
 	}
 }
 
-
-BOOL LLSky::sunUp() const
+void LLSky::setSunDirectionCFR(const LLVector3 &sun_direction)
 {
-	if (mVOSkyp)
-	{
-		return mVOSkyp->isSunUp();
-	}
-	else
-	{
-		return TRUE;
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setSunDirectionCFR(sun_direction);
 	}
 }
 
-
-LLColor4U LLSky::getFadeColor() const
+void LLSky::setMoonDirectionCFR(const LLVector3 &moon_direction)
 {
-	if (mVOSkyp)
-	{
-		return mVOSkyp->getFadeColor();
-	}
-	else
-	{
-		return LLColor4(1.f, 1.f, 1.f, 1.f);
+    if(mVOSkyp.notNull()) {
+        mVOSkyp->setMoonDirectionCFR(moon_direction);
 	}
 }
 
-
 //////////////////////////////////////////////////////////////////////
 // Public Methods
 //////////////////////////////////////////////////////////////////////
 
-void LLSky::init(const LLVector3 &sun_direction)
+void LLSky::init()
 {
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
 	mVOWLSkyp = static_cast<LLVOWLSky*>(gObjectList.createObjectViewer(LLViewerObject::LL_VO_WL_SKY, NULL));
-	mVOWLSkyp->initSunDirection(sun_direction, LLVector3::zero);
+    mVOWLSkyp->init();
 	gPipeline.createObject(mVOWLSkyp.get());
 
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
 	mVOSkyp = (LLVOSky *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_SKY, NULL);
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	mVOSkyp->initSunDirection(sun_direction, LLVector3());
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	gPipeline.createObject((LLViewerObject *)mVOSkyp);
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
+    mVOSkyp->init();
+	gPipeline.createObject(mVOSkyp.get());
 
 	mVOGroundp = (LLVOGround*)gObjectList.createObjectViewer(LLViewerObject::LL_VO_GROUND, NULL);
-	LLVOGround *groundp = mVOGroundp;
-	gPipeline.createObject((LLViewerObject *)groundp);
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio"));	
-
-	////////////////////////////
-	//
-	// Legacy code, ignore
-	//
-	//
-
-	// Get the parameters.
-	mSunDefaultPosition = gSavedSettings.getVector3("SkySunDefaultPosition");
-
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
-
-	if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || mOverrideSimSunPosition)
-	{
-		setSunDirection(mSunDefaultPosition, LLVector3(0.f, 0.f, 0.f));
-	}
-	else
-	{
-		setSunDirection(sun_direction, LLVector3(0.f, 0.f, 0.f));
-	}
+	gPipeline.createObject(mVOGroundp.get());
 
-	LLGLState::checkStates();
-	LLGLState::checkTextureChannels();
+	gSky.setFogRatio(gSavedSettings.getF32("RenderFogRatio"));
 
 	mUpdatedThisFrame = TRUE;
 }
@@ -361,37 +234,21 @@ void LLSky::setWind(const LLVector3& average_wind)
 	}
 }
 
+void LLSky::addSunMoonBeacons()
+{	
+	if (!gAgentAvatarp || !mVOSkyp) return;
 
-void LLSky::propagateHeavenlyBodies(F32 dt)
-{
-	if (!mOverrideSimSunPosition)
+	static LLUICachedControl<bool> show_sun_beacon("sunbeacon", false);
+	static LLUICachedControl<bool> show_moon_beacon("moonbeacon", false);
+
+	if (show_sun_beacon)
 	{
-		LLVector3 curr_dir = getSunDirection();
-		LLVector3 diff = mSunTargDir - curr_dir;
-		const F32 dist = diff.normVec();
-		if (dist > 0)
-		{
-			const F32 step = llmin (dist, 0.00005f);
-			//const F32 step = min (dist, 0.0001);
-			diff *= step;
-			curr_dir += diff;
-			curr_dir.normVec();
-			if (mVOSkyp)
-			{
-				mVOSkyp->setSunDirection(curr_dir, LLVector3());
-			}
-		}
+		renderSunMoonBeacons(gAgentAvatarp->getPositionAgent(), mVOSkyp->getSun().getDirection(), LLColor4(1.f, 0.5f, 0.f, 0.5f));
+	}
+	if (show_moon_beacon)
+	{
+		renderSunMoonBeacons(gAgentAvatarp->getPositionAgent(), mVOSkyp->getMoon().getDirection(), LLColor4(1.f, 0.f, 0.8f, 0.5f));
 	}
-}
-
-F32 LLSky::getSunPhase() const
-{
-	return mSunPhase;
-}
-
-void LLSky::setSunPhase(const F32 phase)
-{
-	mSunPhase = phase;
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -399,11 +256,11 @@ void LLSky::setSunPhase(const F32 phase)
 //////////////////////////////////////////////////////////////////////
 
 
-LLColor4 LLSky::getFogColor() const
+LLColor4 LLSky::getSkyFogColor() const
 {
 	if (mVOSkyp)
 	{
-		return mVOSkyp->getFogColor();
+		return mVOSkyp->getSkyFogColor();
 	}
 
 	return LLColor4(1.f, 1.f, 1.f, 1.f);
diff --git a/indra/newview/llsky.h b/indra/newview/llsky.h
index 7b98c97840b3f6f21f10eb12c15eb00a5ab876bc..8c0d70c16c93d3b310febd87a3b4fb75748e8c8b 100644
--- a/indra/newview/llsky.h
+++ b/indra/newview/llsky.h
@@ -48,16 +48,23 @@ class LLSky
 	LLSky();
 	~LLSky();
 
-	void init(const LLVector3 &sun_direction);
-
+	void init();
 	void cleanup();
 
-	void setOverrideSun(BOOL override);
-	BOOL getOverrideSun() { return mOverrideSimSunPosition; }
-	void setSunDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity);
-	void setSunTargetDirection(const LLVector3 &sun_direction, const LLVector3 &sun_ang_velocity);
+    // These directions should be in CFR coord sys (+x at, +z up, +y right)
+    void setSunAndMoonDirectionsCFR(const LLVector3 &sun_direction, const LLVector3 &moon_direction);
+    void setSunDirectionCFR(const LLVector3 &sun_direction);
+    void setMoonDirectionCFR(const LLVector3 &moon_direction);
+
+    void setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next);
+    void setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next);
+    void setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next);
+    void setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next);
 
-	LLColor4 getFogColor() const;
+    void setSunScale(F32 sun_scale);
+    void setMoonScale(F32 moon_scale);
+
+	LLColor4 getSkyFogColor() const;
 
 	void setCloudDensityAtAgent(F32 cloud_density);
 	void setWind(const LLVector3& wind);
@@ -66,8 +73,6 @@ class LLSky
 	void updateCull();
 	void updateSky();
 
-	void propagateHeavenlyBodies(F32 dt);					// dt = seconds
-
 	S32  mLightingGeneration;
 	BOOL mUpdatedThisFrame;
 
@@ -75,44 +80,21 @@ class LLSky
 	F32 getFogRatio() const;
 	LLColor4U getFadeColor() const;
 
-	LLVector3 getSunDirection() const;
-	LLVector3 getMoonDirection() const;
-	LLColor4 getSunDiffuseColor() const;
-	LLColor4 getMoonDiffuseColor() const;
-	LLColor4 getSunAmbientColor() const;
-	LLColor4 getMoonAmbientColor() const;
-	LLColor4 getTotalAmbientColor() const;
-	BOOL sunUp() const;
-
-	F32 getSunPhase() const;
-	void setSunPhase(const F32 phase);
-
 	void destroyGL();
 	void restoreGL();
 	void resetVertexBuffers();
 
+	void addSunMoonBeacons();
+	void renderSunMoonBeacons(const LLVector3& pos_agent, const LLVector3& direction, LLColor4 color);
+
 public:
 	LLPointer<LLVOSky>		mVOSkyp;	// Pointer to the LLVOSky object (only one, ever!)
 	LLPointer<LLVOGround>	mVOGroundp;
-
 	LLPointer<LLVOWLSky>	mVOWLSkyp;
 
-	LLVector3 mSunTargDir;
-
-	// Legacy stuff
-	LLVector3 mSunDefaultPosition;
-
-	static const F32 NIGHTTIME_ELEVATION;	// degrees
-	static const F32 NIGHTTIME_ELEVATION_COS;
-
 protected:
-	BOOL			mOverrideSimSunPosition;
-
-	F32				mSunPhase;
-	LLColor4		mFogColor;				// Color to use for fog and haze
-
-	LLVector3		mLastSunDirection;
+    LLColor4 mFogColor;
 };
 
-extern LLSky    gSky;
+extern LLSky gSky;
 #endif
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 1dc1e65fe5a253d4d13e63065ed828d82fe48c69..77bbcdada65d5dfd00113c36a336a551ce3cc563 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -55,8 +55,6 @@
 #include "llviewershadermgr.h"
 #include "llcontrolavatar.h"
 
-//#pragma optimize("", off)
-
 static LLTrace::BlockTimerStatHandle FTM_FRUSTUM_CULL("Frustum Culling");
 static LLTrace::BlockTimerStatHandle FTM_CULL_REBOUND("Cull Rebound Partition");
 
@@ -1091,6 +1089,11 @@ class LLOctreeCull : public LLViewerOctreeCull
 
 	virtual bool earlyFail(LLViewerOctreeGroup* base_group)
 	{
+        if (LLPipeline::sReflectionRender)
+        {
+            return false;
+        }
+
 		LLSpatialGroup* group = (LLSpatialGroup*)base_group;
 		group->checkOcclusion();
 
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9bbdd2b718e65325cab13a6a6044c24c1bac4019..3d9de4f92588b21c4596811b9ac0a1634d5441d8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -184,8 +184,6 @@
 #include "llnamebox.h"
 #include "llnameeditor.h"
 #include "llpostprocess.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
 #include "llagentlanguage.h"
 #include "llwearable.h"
 #include "llinventorybridge.h"
@@ -201,6 +199,8 @@
 #include "llexperiencelog.h"
 #include "llcleanup.h"
 
+#include "llenvironment.h"
+
 #include "llstacktrace.h"
 
 #if LL_WINDOWS
@@ -337,7 +337,6 @@ bool idle_startup()
 	static std::string auth_desc;
 	static std::string auth_message;
 
-	static LLVector3 initial_sun_direction(1.f, 0.f, 0.f);
 	static LLVector3 agent_start_position_region(10.f, 10.f, 10.f);		// default for when no space server
 
 	// last location by default
@@ -955,21 +954,6 @@ bool idle_startup()
 		LLFile::mkdir(gDirUtilp->getChatLogsDir());
 		LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
 
-
-		//good a place as any to create user windlight directories
-		std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", ""));
-		LLFile::mkdir(user_windlight_path_name.c_str());		
-
-		std::string user_windlight_skies_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/skies", ""));
-		LLFile::mkdir(user_windlight_skies_path_name.c_str());
-
-		std::string user_windlight_water_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/water", ""));
-		LLFile::mkdir(user_windlight_water_path_name.c_str());
-
-		std::string user_windlight_days_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight/days", ""));
-		LLFile::mkdir(user_windlight_days_path_name.c_str());
-
-
 		if (show_connect_box)
 		{
 			LLSLURL slurl;
@@ -1486,8 +1470,7 @@ bool idle_startup()
 		LLGLState::checkStates();
 		LLGLState::checkTextureChannels();
 
-		LLEnvManagerNew::getInstance()->usePrefs(); // Load all presets and settings
-		gSky.init(initial_sun_direction);
+		gSky.init();
 
 		LLGLState::checkStates();
 		LLGLState::checkTextureChannels();
@@ -1896,7 +1879,11 @@ bool idle_startup()
 		}
 
 		display_startup();
-        
+
+        // Load stored local environment if needed. Only should be done once at least
+        // initial region data got loaded to avoid race condition with region's environment
+        LLEnvironment::instance().loadFromSettings();
+
         // *TODO : Uncomment that line once the whole grid migrated to SLM and suppress it from LLAgent::handleTeleportFinished() (llagent.cpp)
         //check_merchant_status();
 
@@ -2573,7 +2560,8 @@ void register_viewer_callbacks(LLMessageSystem* msg)
 
 	msg->setHandlerFunc("InitiateDownload", process_initiate_download);
 	msg->setHandlerFunc("LandStatReply", LLFloaterTopObjects::handle_land_reply);
-	msg->setHandlerFunc("GenericMessage", process_generic_message);
+    msg->setHandlerFunc("GenericMessage", process_generic_message);
+    msg->setHandlerFunc("LargeGenericMessage", process_large_generic_message);
 
 	msg->setHandlerFuncFast(_PREHASH_FeatureDisabled, process_feature_disabled_message);
 }
@@ -3653,26 +3641,6 @@ bool process_login_success_response()
 		}
 	}
 
-	LLSD global_textures = response["global-textures"][0];
-	if(global_textures.size())
-	{
-		// Extract sun and moon texture IDs.  These are used
-		// in the LLVOSky constructor, but I can't figure out
-		// how to pass them in.  JC
-		LLUUID id = global_textures["sun_texture_id"];
-		if(id.notNull())
-		{
-			gSunTextureID = id;
-		}
-
-		id = global_textures["moon_texture_id"];
-		if(id.notNull())
-		{
-			gMoonTextureID = id;
-		}
-
-	}
-
 	// set the location of the Agent Appearance service, from which we can request
 	// avatar baked textures if they are supported by the current region
 	std::string agent_appearance_url = response["agent_appearance_service"];
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index e2deb7ce1d39c11919beb991b6f850ea38692cc4..2e52414d71950c5d5cf1ca87e4bf47367ecc7d3f 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -1822,29 +1822,28 @@ void LLTextureCache::purgeTextures(bool validate)
 		 iter != time_idx_set.end(); ++iter)
 	{
 		S32 idx = iter->second;
-		bool purge_entry = false;
-		std::string filename = getTextureFileName(entries[idx].mID);
-		if (cache_size >= purged_cache_size)
-		{
-			purge_entry = true;
-		}
-		else if (validate)
+		bool purge_entry = false;		
+        if (validate)
 		{
 			// make sure file exists and is the correct size
 			U32 uuididx = entries[idx].mID.mData[0];
 			if (uuididx == validate_idx)
 			{
+                std::string filename = getTextureFileName(entries[idx].mID);
  				LL_DEBUGS("TextureCache") << "Validating: " << filename << "Size: " << entries[idx].mBodySize << LL_ENDL;
 				// mHeaderAPRFilePoolp because this is under header mutex in main thread
 				S32 bodysize = LLAPRFile::size(filename, mHeaderAPRFilePoolp);
 				if (bodysize != entries[idx].mBodySize)
 				{
-					LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize
-							<< filename << LL_ENDL;
+					LL_WARNS("TextureCache") << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mBodySize << filename << LL_ENDL;
 					purge_entry = true;
 				}
 			}
 		}
+		else if (cache_size >= purged_cache_size)
+		{
+			purge_entry = true;
+		}
 		else
 		{
 			break;
@@ -1853,6 +1852,7 @@ void LLTextureCache::purgeTextures(bool validate)
 		if (purge_entry)
 		{
 			purge_count++;
+            std::string filename = getTextureFileName(entries[idx].mID);
 	 		LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL;
 			cache_size -= entries[idx].mBodySize;
 			removeEntry(idx, entries[idx], filename) ;			
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index 6046f2b9df1808e4f0cfa53525f102fb78e330c1..e1c752b58ed09a39e3c5e710d44bc6bcf03d0c0e 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -45,6 +45,11 @@ class LLTextureCache : public LLWorkerThread
 	friend class LLTextureCacheLocalFileWorker;
 
 private:
+
+#if LL_WINDOWS
+#pragma pack(push,1)
+#endif
+
 	// Entries
 	static const U32 sHeaderEncoderStringSize = 32;
 	struct EntriesInfo
@@ -73,7 +78,10 @@ class LLTextureCache : public LLWorkerThread
 		U32 mTime; // seconds since 1/1/1970
 	};
 
-	
+#if LL_WINDOWS
+#pragma pack(pop)
+#endif
+
 public:
 
 	class Responder : public LLResponder
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index e2bb904eff0ffdd003fad4596ee8e94cfde648ec..6a0464c657dcab89060297840918b2dff8f9012a 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -73,10 +73,6 @@
 
 #include "llavatarappearancedefines.h"
 
-static const F32 CONTEXT_CONE_IN_ALPHA = 0.0f;
-static const F32 CONTEXT_CONE_OUT_ALPHA = 1.f;
-static const F32 CONTEXT_FADE_TIME = 0.08f;
-
 static const S32 LOCAL_TRACKING_ID_COLUMN = 1;
 
 //static const char CURRENT_IMAGE_NAME[] = "Current Texture";
@@ -398,7 +394,7 @@ BOOL LLFloaterTexturePicker::postBuild()
 
 		
 
-		if (!mImageAssetID.isNull())
+		if(!mImageAssetID.isNull())
 		{
 			mInventoryPanel->setSelection(findItemID(mImageAssetID, FALSE), TAKE_FOCUS_NO);
 		}
@@ -442,59 +438,8 @@ BOOL LLFloaterTexturePicker::postBuild()
 // virtual
 void LLFloaterTexturePicker::draw()
 {
-	if (mOwner)
-	{
-		// draw cone of context pointing back to texture swatch	
-		LLRect owner_rect;
-		mOwner->localRectToOtherView(mOwner->getLocalRect(), &owner_rect, this);
-		LLRect local_rect = getLocalRect();
-		if (gFocusMgr.childHasKeyboardFocus(this) && mOwner->isInVisibleChain() && mContextConeOpacity > 0.001f)
-		{
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			LLGLEnable(GL_CULL_FACE);
-			gGL.begin(LLRender::QUADS);
-			{
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mTop);
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mTop);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mTop);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-
-
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_OUT_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
-				gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
-				gGL.color4f(0.f, 0.f, 0.f, CONTEXT_CONE_IN_ALPHA * mContextConeOpacity);
-				gGL.vertex2i(owner_rect.mRight, owner_rect.mBottom);
-				gGL.vertex2i(owner_rect.mLeft, owner_rect.mBottom);
-			}
-			gGL.end();
-		}
-	}
-
-	if (gFocusMgr.childHasMouseCapture(getDragHandle()))
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
-	else
-	{
-		mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME));
-	}
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, mOwner);
 
 	updateImageStats();
 
@@ -810,27 +755,27 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem
 void LLFloaterTexturePicker::onModeSelect(LLUICtrl* ctrl, void *userdata)
 {
 	LLFloaterTexturePicker* self = (LLFloaterTexturePicker*) userdata;
-	int mode = self->mModeSelector->getSelectedIndex();
+	int index = self->mModeSelector->getSelectedIndex();
 
-	self->getChild<LLButton>("Default")->setVisible(mode == 0);
-	self->getChild<LLButton>("Blank")->setVisible(mode == 0);
-	self->getChild<LLButton>("None")->setVisible(mode == 0);
-	self->getChild<LLButton>("Pipette")->setVisible(mode == 0);
-	self->getChild<LLFilterEditor>("inventory search editor")->setVisible(mode == 0);
-	self->getChild<LLInventoryPanel>("inventory panel")->setVisible(mode == 0);
+	self->getChild<LLButton>("Default")->setVisible(index == 0 ? TRUE : FALSE);
+	self->getChild<LLButton>("Blank")->setVisible(index == 0 ? TRUE : FALSE);
+	self->getChild<LLButton>("None")->setVisible(index == 0 ? TRUE : FALSE);
+	self->getChild<LLButton>("Pipette")->setVisible(index == 0 ? TRUE : FALSE);
+	self->getChild<LLFilterEditor>("inventory search editor")->setVisible(index == 0 ? TRUE : FALSE);
+	self->getChild<LLInventoryPanel>("inventory panel")->setVisible(index == 0 ? TRUE : FALSE);
 
 	/*self->getChild<LLCheckBox>("show_folders_check")->setVisible(mode);
 	  no idea under which conditions the above is even shown, needs testing. */
 
-	self->getChild<LLButton>("l_add_btn")->setVisible(mode == 1);
-	self->getChild<LLButton>("l_rem_btn")->setVisible(mode == 1);
-	self->getChild<LLButton>("l_upl_btn")->setVisible(mode == 1);
-	self->getChild<LLScrollListCtrl>("l_name_list")->setVisible(mode == 1);
+	self->getChild<LLButton>("l_add_btn")->setVisible(index == 1 ? TRUE : FALSE);
+	self->getChild<LLButton>("l_rem_btn")->setVisible(index == 1 ? TRUE : FALSE);
+	self->getChild<LLButton>("l_upl_btn")->setVisible(index == 1 ? TRUE : FALSE);
+	self->getChild<LLScrollListCtrl>("l_name_list")->setVisible(index == 1 ? TRUE : FALSE);
 
-	self->getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(mode == 2);
-	self->getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(false);// mode == 2);
+	self->getChild<LLComboBox>("l_bake_use_texture_combo_box")->setVisible(index == 2 ? TRUE : FALSE);
+	self->getChild<LLCheckBoxCtrl>("hide_base_mesh_region")->setVisible(FALSE);// index == 2 ? TRUE : FALSE);
 
-	if (mode == 2)
+	if (index == 2)
 	{
 		self->stopUsingPipette();
 
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index af6b37f2dfbda3e27a50cb42efe871d772eaddae..6a29be4aa17919d2f5eac2f5ff14768b38eff659 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -271,14 +271,15 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal
 			mLineEditor->setMaxTextChars(edit_text_max_chars);
 			mLineEditor->setText(edit_text_contents);
 
-			if("SaveOutfitAs"  == mNotification->getName())
+			std::string notif_name = mNotification->getName();
+			if (("SaveOutfitAs" == notif_name) || ("SaveSettingAs" == notif_name))
 			{
 				mLineEditor->setPrevalidate(&LLTextValidate::validateASCII);
 			}
 
 			// decrease limit of line editor of teleport offer dialog to avoid truncation of
 			// location URL in invitation message, see EXT-6891
-			if ("OfferTeleport" == mNotification->getName())
+			if ("OfferTeleport" == notif_name)
 			{
 				mLineEditor->setMaxTextLength(gSavedSettings.getS32(
 						"teleport_offer_invitation_max_length"));
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 7d77a8983f7de8b9ec32d22fa838230922ddebf2..50868d0fa5aaa29b6501fff756fb3d8a14b83b4c 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -270,7 +270,8 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
 	addEntry(DAD_GESTURE, 		new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dActivateGesture,		&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dUpdateInventory,			&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_LINK, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dNULL,						&LLToolDragAndDrop::dad3dNULL));
 	addEntry(DAD_MESH, 			new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL,	&LLToolDragAndDrop::dad3dNULL,					&LLToolDragAndDrop::dad3dGiveInventory,			&LLToolDragAndDrop::dad3dMeshObject,				&LLToolDragAndDrop::dad3dNULL));
-	// TODO: animation on self could play it?  edit it?
+    addEntry(DAD_SETTINGS,      new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL,                  &LLToolDragAndDrop::dad3dGiveInventory,         &LLToolDragAndDrop::dad3dUpdateInventory,           &LLToolDragAndDrop::dad3dNULL));
+    // TODO: animation on self could play it?  edit it?
 	// TODO: gesture on self could play it?  edit it?
 };
 
@@ -1626,6 +1627,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
 	case DAD_CALLINGCARD:
 	case DAD_MESH:
 	case DAD_CATEGORY:
+    case DAD_SETTINGS:
 	{
 		LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data;
 		if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID())
diff --git a/indra/newview/lltoolgun.cpp b/indra/newview/lltoolgun.cpp
index 6c9155be851675281d6fccc722c0cd2d25bc8571..9539081f303b9d77d80c5f210134b402ef2d0cd5 100644
--- a/indra/newview/lltoolgun.cpp
+++ b/indra/newview/lltoolgun.cpp
@@ -107,11 +107,18 @@ BOOL LLToolGun::handleHover(S32 x, S32 y, MASK mask)
 
 			if (gSavedSettings.getBOOL("MouseSun"))
 			{
-				gSky.setSunDirection(LLViewerCamera::getInstance()->getAtAxis(), LLVector3(0.f, 0.f, 0.f));
-				gSky.setOverrideSun(TRUE);
+                LLVector3 sunpos = LLViewerCamera::getInstance()->getAtAxis();
+				gSky.setSunDirectionCFR(sunpos);
 				gSavedSettings.setVector3("SkySunDefaultPosition", LLViewerCamera::getInstance()->getAtAxis());
 			}
 
+            if (gSavedSettings.getBOOL("MouseMoon"))
+			{
+                LLVector3 moonpos = LLViewerCamera::getInstance()->getAtAxis();
+				gSky.setMoonDirectionCFR(moonpos);
+				gSavedSettings.setVector3("SkyMoonDefaultPosition", LLViewerCamera::getInstance()->getAtAxis());
+			}
+
 			gViewerWindow->moveCursorToCenter();
 			gViewerWindow->hideCursor();
 		}
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index 2ec5c41b8862ca77dc0841edc9f8eeb80d5ab771..728d0c9417218af854b2dee3e534fcb76d201f7f 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -570,8 +570,8 @@ void LLTracker::renderBeacon(LLVector3d pos_global,
 		color_frac = 1.f - 0.6f*(dist/LLViewerCamera::getInstance()->getFar());
 	}
 
-	LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getFogColor();
-	LLColor4 fogged_color_under = color_frac * color_under + (1 - color_frac) * gSky.getFogColor();
+	LLColor4 fogged_color = color_frac * color + (1 - color_frac)*gSky.getSkyFogColor();
+	LLColor4 fogged_color_under = color_frac * color_under + (1 - color_frac) * gSky.getSkyFogColor();
 
 	F32 FADE_DIST = 3.f;
 	fogged_color.mV[3] = llmax(0.2f, llmin(0.5f,(dist-FADE_DIST)/FADE_DIST));
diff --git a/indra/newview/lltrackpicker.cpp b/indra/newview/lltrackpicker.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe6256a8a9b594b5366f4b77302680e18be4618b
--- /dev/null
+++ b/indra/newview/lltrackpicker.cpp
@@ -0,0 +1,134 @@
+/** 
+* @author AndreyK Productengine
+* @brief LLTrackPicker class header file including related functions
+*
+* $LicenseInfo:firstyear=2018&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2018, 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$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltrackpicker.h"
+
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+
+
+//=========================================================================
+namespace
+{
+    const std::string FLOATER_DEFINITION_XML("floater_pick_track.xml");
+
+    const std::string BTN_SELECT("btn_select");
+    const std::string BTN_CANCEL("btn_cancel");
+    const std::string RDO_TRACK_SELECTION("track_selection");
+    const std::string RDO_TRACK_PREFIX("radio_sky");
+}
+//=========================================================================
+
+LLFloaterTrackPicker::LLFloaterTrackPicker(LLView * owner, const LLSD &params) :
+    LLFloater(params),
+    mContextConeOpacity(0.0f),
+    mOwnerHandle()
+{
+    mOwnerHandle = owner->getHandle();
+    buildFromFile(FLOATER_DEFINITION_XML);
+}
+
+LLFloaterTrackPicker::~LLFloaterTrackPicker()
+{
+}
+
+BOOL LLFloaterTrackPicker::postBuild()
+{
+    childSetAction(BTN_CANCEL, [this](LLUICtrl*, const LLSD& param){ onButtonCancel(); });
+    childSetAction(BTN_SELECT, [this](LLUICtrl*, const LLSD& param){ onButtonSelect(); });
+    return TRUE;
+}
+
+void LLFloaterTrackPicker::onClose(bool app_quitting)
+{
+    if (app_quitting)
+        return;
+
+    LLView *owner = mOwnerHandle.get();
+    if (owner)
+    {
+        owner->setFocus(TRUE);
+    }
+}
+
+void LLFloaterTrackPicker::showPicker(const LLSD &args)
+{
+    LLSD::array_const_iterator iter;
+    LLSD::array_const_iterator end = args.endArray();
+
+    bool select_item = true;
+    for (iter = args.beginArray(); iter != end; ++iter)
+    {
+        S32 track_id = (*iter)["id"].asInteger();
+        bool can_enable = (*iter)["enabled"].asBoolean();
+        LLCheckBoxCtrl *view = getChild<LLCheckBoxCtrl>(RDO_TRACK_PREFIX + llformat("%d", track_id), true);
+        view->setEnabled(can_enable);
+        view->setLabelArg("[ALT]", (*iter).has("altitude") ? ((*iter)["altitude"].asString() + "m") : " ");
+
+        // Mark first avaliable item as selected
+        if (can_enable && select_item)
+        {
+            select_item = false;
+            getChild<LLRadioGroup>(RDO_TRACK_SELECTION, true)->setSelectedByValue(LLSD(track_id), TRUE);
+        }
+    }
+
+    openFloater(getKey());
+    setFocus(TRUE);
+}
+
+void LLFloaterTrackPicker::draw()
+{
+    LLView *owner = mOwnerHandle.get();
+    static LLCachedControl<F32> max_opacity(gSavedSettings, "PickerContextOpacity", 0.4f);
+    drawConeToOwner(mContextConeOpacity, max_opacity, owner);
+
+    LLFloater::draw();
+}
+
+void LLFloaterTrackPicker::onButtonCancel()
+{
+    closeFloater();
+}
+
+void LLFloaterTrackPicker::onButtonSelect()
+{
+    if (mCommitSignal)
+    {
+        (*mCommitSignal)(this, getChild<LLRadioGroup>(RDO_TRACK_SELECTION, true)->getSelectedValue());
+    }
+    closeFloater();
+}
+
+void LLFloaterTrackPicker::onFocusLost()
+{
+    if (isInVisibleChain())
+    {
+        closeFloater();
+    }
+}
diff --git a/indra/newview/lltrackpicker.h b/indra/newview/lltrackpicker.h
new file mode 100644
index 0000000000000000000000000000000000000000..dab3b72915b0f70c5ed5543b28a84151d8cc701e
--- /dev/null
+++ b/indra/newview/lltrackpicker.h
@@ -0,0 +1,58 @@
+/** 
+ * @file lltrackpicker.h
+ * @author AndreyK Productengine
+ * @brief LLTrackPicker class header file including related functions
+ *
+ * $LicenseInfo:firstyear=2018&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2018, 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$
+ */
+
+#ifndef LL_TRACKPICKER_H
+#define LL_TRACKPICKER_H
+
+#include "llfloater.h"
+
+
+//=========================================================================
+
+class LLFloaterTrackPicker : public LLFloater
+{
+public:
+    LLFloaterTrackPicker(LLView * owner, const LLSD &params = LLSD());
+    virtual ~LLFloaterTrackPicker() override;
+
+    virtual BOOL postBuild() override;
+    virtual void onClose(bool app_quitting) override;
+    void         showPicker(const LLSD &args);
+
+    virtual void            draw() override;
+
+    void         onButtonCancel();
+    void         onButtonSelect();
+
+private:
+    void                    onFocusLost() override;
+
+    F32              mContextConeOpacity;
+    LLHandle<LLView> mOwnerHandle;
+};
+
+#endif  // LL_TRACKPICKER_H
diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h
index 50131682e7f98f7a3f1d476ce7b4714564bf004d..cefe2154315d96ac4a92f8d2e2048cb73cf9bb63 100644
--- a/indra/newview/llviewerassetstorage.h
+++ b/indra/newview/llviewerassetstorage.h
@@ -69,14 +69,14 @@ class LLViewerAssetStorage : public LLAssetStorage
 	// virtual
 	void _queueDataRequest(const LLUUID& uuid,
 						   LLAssetType::EType type,
-						   void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                           LLGetAssetCallback callback,
 						   void *user_data,
 						   BOOL duplicate,
 						   BOOL is_priority);
 
     void queueRequestHttp(const LLUUID& uuid,
                           LLAssetType::EType type,
-                          void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                          LLGetAssetCallback callback,
                           void *user_data,
                           BOOL duplicate,
                           BOOL is_priority);
@@ -86,7 +86,7 @@ class LLViewerAssetStorage : public LLAssetStorage
     void assetRequestCoro(LLViewerAssetRequest *req,
                           const LLUUID uuid,
                           LLAssetType::EType atype,
-                          void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
+                          LLGetAssetCallback callback,
                           void *user_data);
 
     std::string getAssetURL(const std::string& cap_url, const LLUUID& uuid, LLAssetType::EType atype);
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index f07c14d01f8108e7a32b26924a58dcecd661c680..4804ef6ddcb4f19583a0de80acd9a9e410d02f09 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -87,6 +87,7 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
 	addEntry(LLViewerAssetType::AT_UNKNOWN,				new ViewerAssetEntry(DAD_NONE));
 
 	addEntry(LLViewerAssetType::AT_NONE, 				new ViewerAssetEntry(DAD_NONE));
+    addEntry(LLViewerAssetType::AT_SETTINGS,            new ViewerAssetEntry(DAD_SETTINGS));
 };
 
 EDragAndDropType LLViewerAssetType::lookupDragAndDropType(EType asset_type)
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index 51c8f4ab794f9b19ac7ebe3457b0998d8c92980f..d53cc3f74571070c61112dfbe3bf3ce6b0540b44 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -505,7 +505,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType:
     mTaskId(LLUUID::null),
     mContents(buffer),
     mInvnFinishFn(finish),
-    mTaskFinishFn(NULL),
+    mTaskFinishFn(nullptr),
     mStoredToVFS(false)
 {
     setItemId(itemId);
@@ -519,7 +519,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LL
     mTaskId(LLUUID::null),
     mContents(),
     mInvnFinishFn(finish),
-    mTaskFinishFn(NULL),
+    mTaskFinishFn(nullptr),
     mStoredToVFS(false)
 {
     setItemId(itemId);
@@ -552,7 +552,7 @@ LLBufferedAssetUploadInfo::LLBufferedAssetUploadInfo(LLUUID taskId, LLUUID itemI
     mTaskUpload(true),
     mTaskId(taskId),
     mContents(buffer),
-    mInvnFinishFn(NULL),
+    mInvnFinishFn(nullptr),
     mTaskFinishFn(finish),
     mStoredToVFS(false)
 {
@@ -757,6 +757,10 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
                 LLUploadDialog::modalUploadFinished();
             return;
         }
+        if (!result.has("success"))
+        {
+            result["success"] = LLSD::Boolean((ulstate == "complete") && status);
+        }
 
         S32 uploadPrice = result["upload_price"].asInteger();
 
diff --git a/indra/newview/llviewerassetupload.h b/indra/newview/llviewerassetupload.h
index 08b03e30597abac060a545100eeaa18f9c948d6e..d9eacf31675bf73a80d3d7fb289a999c2d7ec60c 100644
--- a/indra/newview/llviewerassetupload.h
+++ b/indra/newview/llviewerassetupload.h
@@ -40,7 +40,7 @@
 class LLResourceUploadInfo
 {
 public:
-    typedef boost::shared_ptr<LLResourceUploadInfo> ptr_t;
+    typedef std::shared_ptr<LLResourceUploadInfo> ptr_t;
 
     LLResourceUploadInfo(
         LLTransactionID transactId,
@@ -171,8 +171,8 @@ class LLNewFileResourceUploadInfo : public LLResourceUploadInfo
 class LLBufferedAssetUploadInfo : public LLResourceUploadInfo
 {
 public:
-    typedef boost::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
-    typedef boost::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
+    typedef std::function<void(LLUUID itemId, LLUUID newAssetId, LLUUID newItemId, LLSD response)> invnUploadFinish_f;
+    typedef std::function<void(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response)> taskUploadFinish_f;
 
     LLBufferedAssetUploadInfo(LLUUID itemId, LLAssetType::EType assetType, std::string buffer, invnUploadFinish_f finish);
     LLBufferedAssetUploadInfo(LLUUID itemId, LLPointer<LLImageFormatted> image, invnUploadFinish_f finish);
diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index 778e27572728557f3269cdf06642c56f25398ee6..27a87ee1a0bce923e33448b3210fae0b6f7fbfb7 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -81,31 +81,6 @@ glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height
 	return glh::matrix4f(m);
 }
 
-glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar)
-{
-	GLfloat f = 1.f/tanf(DEG_TO_RAD*fovy/2.f);
-
-	return glh::matrix4f(f/aspect, 0, 0, 0,
-						 0, f, 0, 0,
-						 0, 0, (zFar+zNear)/(zNear-zFar), (2.f*zFar*zNear)/(zNear-zFar),
-						 0, 0, -1.f, 0);
-}
-
-glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up)
-{
-	LLVector3 f = center-eye;
-	f.normVec();
-	up.normVec();
-	LLVector3 s = f % up;
-	LLVector3 u = s % f;
-
-	return glh::matrix4f(s[0], s[1], s[2], 0,
-					  u[0], u[1], u[2], 0,
-					  -f[0], -f[1], -f[2], 0,
-					  0, 0, 0, 1);
-	
-}
-
 // Build time optimization, generate this once in .cpp file
 template class LLViewerCamera* LLSingleton<class LLViewerCamera>::getInstance();
 
diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h
index 5901de289f02315a2d3a34dd94e9222e65679025..fb07a3fb2df41a8482de8e447d3b02cad2fb0a70 100644
--- a/indra/newview/llviewercamera.h
+++ b/indra/newview/llviewercamera.h
@@ -35,14 +35,6 @@
 #include "lltrace.h"
 
 class LLViewerObject;
-
-// This rotation matrix moves the default OpenGL reference frame 
-// (-Z at, Y up) to Cory's favorite reference frame (X at, Z up)
-const F32 OGL_TO_CFR_ROTATION[16] = {  0.f,  0.f, -1.f,  0.f, 	// -Z becomes X
-									  -1.f,  0.f,  0.f,  0.f, 	// -X becomes Y
-									   0.f,  1.f,  0.f,  0.f,	//  Y becomes Z
-									   0.f,  0.f,  0.f,  1.f };
-
 const BOOL FOR_SELECTION = TRUE;
 const BOOL NOT_FOR_SELECTION = FALSE;
 
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index a699491e1bfbca510a86823b93b8d05aacd125e7..c65431d6f62a5dc1bd0d9feed75ea0ea30959ea5 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -94,6 +94,7 @@ LLControlGroup gWarningSettings("Warnings"); // persists ignored dialogs/warning
 std::string gLastRunVersion;
 
 extern BOOL gResizeScreenTexture;
+extern BOOL gResizeShadowTexture;
 extern BOOL gDebugGL;
 ////////////////////////////////////////////////////////////////////////////
 // Listeners
@@ -190,6 +191,19 @@ bool handleRenderTransparentWaterChanged(const LLSD& newvalue)
 	return true;
 }
 
+
+static bool handleShadowsResized(const LLSD& newvalue)
+{
+	gPipeline.requestResizeShadowTexture();
+	return true;
+}
+
+static bool handleWindowResized(const LLSD& newvalue)
+{
+	gPipeline.requestResizeScreenTexture();
+	return true;
+}
+
 static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
 {
 	if (gPipeline.isInit())
@@ -608,15 +622,14 @@ void settings_setup_listeners()
 	gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
 	gSavedSettings.getControl("RenderUseTriStrips")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
 	gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
-	gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
-	gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+	gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleWindowResized, _2));
 	gSavedSettings.getControl("RenderDepthOfField")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderFSAASamples")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
 	gSavedSettings.getControl("RenderSpecularResY")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
 	gSavedSettings.getControl("RenderSpecularExponent")->getSignal()->connect(boost::bind(&handleLUTBufferChanged, _2));
 	gSavedSettings.getControl("RenderAnisotropic")->getSignal()->connect(boost::bind(&handleAnisotropicChanged, _2));
-	gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
+	gSavedSettings.getControl("RenderShadowResolutionScale")->getSignal()->connect(boost::bind(&handleShadowsResized, _2));
 	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
 	gSavedSettings.getControl("RenderGlow")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
 	gSavedSettings.getControl("RenderGlowResolutionPow")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 6df849674f26b56349b38b5ce5d4553ce43a1363..2b1f4b138fc4749d8afe32c4ab557dac36291090 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -74,11 +74,11 @@
 #include "llviewerregion.h"
 #include "lldrawpoolwater.h"
 #include "lldrawpoolbump.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
 #include "llpostprocess.h"
 #include "llscenemonitor.h"
 
+#include "llenvironment.h"
+
 extern LLPointer<LLViewerTexture> gStartTexture;
 extern bool gShiftFrame;
 
@@ -94,6 +94,7 @@ BOOL gForceRenderLandFence = FALSE;
 BOOL gDisplaySwapBuffers = FALSE;
 BOOL gDepthDirty = FALSE;
 BOOL gResizeScreenTexture = FALSE;
+BOOL gResizeShadowTexture = FALSE;
 BOOL gWindowResized = FALSE;
 BOOL gSnapshot = FALSE;
 BOOL gShaderProfileFrame = FALSE;
@@ -130,9 +131,6 @@ void display_startup()
 
 	gPipeline.updateGL();
 
-	// Update images?
-	//gImageList.updateImages(0.01f);
-	
 	// Written as branch to appease GCC which doesn't like different
 	// pointer types across ternary ops
 	//
@@ -199,10 +197,6 @@ void display_update_camera()
 	LLViewerCamera::getInstance()->setFar(final_far);
 	gViewerWindow->setup3DRender();
 	
-	// update all the sky/atmospheric/water settings
-	LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance());
-	LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance());
-
 	// Update land visibility too
 	LLWorld::getInstance()->setLandFarClip(final_far);
 }
@@ -250,6 +244,7 @@ static LLTrace::BlockTimerStatHandle FTM_HUD_UPDATE("HUD Update");
 static LLTrace::BlockTimerStatHandle FTM_DISPLAY_UPDATE_GEOM("Update Geom");
 static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UNBIND("Texture Unbind");
 static LLTrace::BlockTimerStatHandle FTM_TELEPORT_DISPLAY("Teleport Display");
+static LLTrace::BlockTimerStatHandle FTM_EEP_UPDATE("Env Update");
 
 // Paint the display!
 void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
@@ -269,6 +264,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		return;
 	}
 
+    if (gResizeShadowTexture)
+	{ //skip render on frames where window has been resized
+		gPipeline.resizeShadowTexture();
+		gResizeShadowTexture = FALSE;
+	}
+
 	if (LLPipeline::sRenderDeferred)
 	{ //hack to make sky show up in deferred snapshots
 		for_snapshot = FALSE;
@@ -569,7 +570,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 	if (gDisconnected)
 	{
 		LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
-		LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
 		render_ui();
 		swap();
 	}
@@ -634,6 +634,12 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		display_update_camera();
 		stop_glerror();
 				
+		{
+			LL_RECORD_BLOCK_TIME(FTM_EEP_UPDATE);
+            // update all the sky/atmospheric/water settings
+            LLEnvironment::instance().update(LLViewerCamera::getInstance());
+		}
+
 		// *TODO: merge these two methods
 		{
 			LL_RECORD_BLOCK_TIME(FTM_HUD_UPDATE);
@@ -656,7 +662,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		stop_glerror();
 
 		S32 water_clip = 0;
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_ENVIRONMENT) > 1) &&
 			 (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WATER) || 
 			  gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER)))
 		{
@@ -732,8 +738,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 				LLGLState::checkTextureChannels();
 				LLGLState::checkClientArrays();
 
-				glh::matrix4f proj = glh_get_current_projection();
-				glh::matrix4f mod = glh_get_current_modelview();
+				glh::matrix4f proj = get_current_projection();
+				glh::matrix4f mod = get_current_modelview();
 				glViewport(0,0,512,512);
 				LLVOAvatar::updateFreezeCounter() ;
 
@@ -742,8 +748,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 					LLVOAvatar::updateImpostors();
 				}
 
-				glh_set_current_projection(proj);
-				glh_set_current_modelview(mod);
+				set_current_projection(proj);
+				set_current_modelview(mod);
 				gGL.matrixMode(LLRender::MM_PROJECTION);
 				gGL.loadMatrix(proj.m);
 				gGL.matrixMode(LLRender::MM_MODELVIEW);
@@ -901,7 +907,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		//	gGL.popMatrix();
 		//}
 
-		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater();
+		LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE;
 
 		LLGLState::checkStates();
 		LLGLState::checkClientArrays();
@@ -923,7 +929,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 				gPipeline.mScreen.bindTarget();
 				if (LLPipeline::sUnderWaterRender && !gPipeline.canUseWindLightShaders())
 				{
-					const LLColor4 &col = LLDrawPoolWater::sWaterFogColor;
+					const LLColor4 &col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
 					glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
 				}
 				gPipeline.mScreen.clear();
@@ -1026,7 +1032,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 
 		if (LLPipeline::sRenderDeferred)
 		{
-			gPipeline.renderDeferredLighting();
+			gPipeline.renderDeferredLighting(&gPipeline.mScreen);
 		}
 
 		LLPipeline::sUnderWaterRender = FALSE;
@@ -1039,7 +1045,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI");
 		if (!for_snapshot)
 		{
-			LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
 			render_ui();
 			swap();
 		}
@@ -1081,8 +1086,8 @@ void render_hud_attachments()
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.pushMatrix();
 		
-	glh::matrix4f current_proj = glh_get_current_projection();
-	glh::matrix4f current_mod = glh_get_current_modelview();
+	glh::matrix4f current_proj = get_current_projection();
+	glh::matrix4f current_mod = get_current_modelview();
 
 	// clamp target zoom level to reasonable values
 	gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f);
@@ -1174,8 +1179,8 @@ void render_hud_attachments()
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.popMatrix();
 	
-	glh_set_current_projection(current_proj);
-	glh_set_current_modelview(current_mod);
+	set_current_projection(current_proj);
+	set_current_modelview(current_mod);
 }
 
 LLRect get_whole_screen_region()
@@ -1257,29 +1262,32 @@ bool setup_hud_matrices(const LLRect& screen_region)
 	// set up transform to keep HUD objects in front of camera
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.loadMatrix(proj.m);
-	glh_set_current_projection(proj);
+	set_current_projection(proj);
 	
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.loadMatrix(model.m);
-	glh_set_current_modelview(model);
+	set_current_modelview(model);
 	return TRUE;
 }
 
 void render_ui(F32 zoom_factor, int subfield)
 {
+    LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
+
 	LLGLState::checkStates();
 	
-	glh::matrix4f saved_view = glh_get_current_modelview();
+	glh::matrix4f saved_view = get_current_modelview();
 
 	if (!gSnapshot)
 	{
 		gGL.pushMatrix();
 		gGL.loadMatrix(gGLLastModelView);
-		glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+		set_current_modelview(copy_matrix(gGLLastModelView));
 	}
 	
 	if(LLSceneMonitor::getInstance()->needsUpdate())
 	{
+        LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_SCENE_MON);
 		gGL.pushMatrix();
 		gViewerWindow->setup2DRender();
 		LLSceneMonitor::getInstance()->compare();
@@ -1295,7 +1303,7 @@ void render_ui(F32 zoom_factor, int subfield)
 		{
 			gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
 		}
-
+		
 		LL_RECORD_BLOCK_TIME(FTM_RENDER_HUD);
 		render_hud_elements();
 		render_hud_attachments();
@@ -1313,6 +1321,7 @@ void render_ui(F32 zoom_factor, int subfield)
 		{
 			if (!gDisconnected)
 			{
+                LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_3D);
 				render_ui_3d();
 				LLGLState::checkStates();
 			}
@@ -1321,12 +1330,14 @@ void render_ui(F32 zoom_factor, int subfield)
 				render_disconnected_background();
 			}
 
+            LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_2D);
 			render_ui_2d();
 			LLGLState::checkStates();
 		}
 		gGL.flush();
 
 		{
+            LL_RECORD_BLOCK_TIME(FTM_RENDER_UI_DEBUG_TEXT);
 			gViewerWindow->setup2DRender();
 			gViewerWindow->updateDebugText();
 			gViewerWindow->drawDebugText();
@@ -1337,7 +1348,7 @@ void render_ui(F32 zoom_factor, int subfield)
 
 	if (!gSnapshot)
 	{
-		glh_set_current_modelview(saved_view);
+		set_current_modelview(saved_view);
 		gGL.popMatrix();
 	}
 }
diff --git a/indra/newview/llviewerdisplay.h b/indra/newview/llviewerdisplay.h
index f6467d7f93c4a65bdd0cb385732fcb87f34060a6..e8072193ea1836ea371e1d8e59763b077f14c196 100644
--- a/indra/newview/llviewerdisplay.h
+++ b/indra/newview/llviewerdisplay.h
@@ -40,6 +40,7 @@ extern BOOL	gTeleportDisplay;
 extern LLFrameTimer	gTeleportDisplayTimer;
 extern BOOL			gForceRenderLandFence;
 extern BOOL gResizeScreenTexture;
+extern BOOL gResizeShadowTexture;
 extern BOOL gWindowResized;
 
 #endif // LL_LLVIEWERDISPLAY_H
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 7d3a762c26ba4898c4e506f57d8608f70eb1e951..414ae1fad63688b611c735a1f1573b1e0c4f970c 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -57,17 +57,15 @@
 #include "llfloaterchatvoicevolume.h"
 #include "llfloaterconversationlog.h"
 #include "llfloaterconversationpreview.h"
-#include "llfloaterdeleteenvpreset.h"
 #include "llfloaterdeleteprefpreset.h"
 #include "llfloaterdestinations.h"
-#include "llfloatereditdaycycle.h"
-#include "llfloatereditsky.h"
-#include "llfloatereditwater.h"
-#include "llfloaterenvironmentsettings.h"
+#include "llfloatereditextdaycycle.h"
+#include "llfloaterenvironmentadjust.h"
 #include "llfloaterexperienceprofile.h"
 #include "llfloaterexperiences.h"
 #include "llfloaterexperiencepicker.h"
 #include "llfloaterevent.h"
+#include "llfloaterfixedenvironment.h"
 #include "llfloaterfonttest.h"
 #include "llfloaterforgetuser.h"
 #include "llfloatergesture.h"
@@ -92,6 +90,7 @@
 #include "llfloatermemleak.h"
 #include "llfloatermodelpreview.h"
 #include "llfloatermyscripts.h"
+#include "llfloatermyenvironment.h"
 #include "llfloaternamedesc.h"
 #include "llfloaternotificationsconsole.h"
 #include "llfloaternotificationstabbed.h"
@@ -226,11 +225,14 @@ void LLViewerFloaterReg::registerFloaters()
 	LLFloaterReg::add("destinations", "floater_destinations.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDestinations>);
 
 	LLFloaterReg::add("env_post_process", "floater_post_process.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPostProcess>);
-	LLFloaterReg::add("env_settings", "floater_environment_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentSettings>);
-	LLFloaterReg::add("env_delete_preset", "floater_delete_env_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDeleteEnvPreset>);
-	LLFloaterReg::add("env_edit_sky", "floater_edit_sky_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditSky>);
-	LLFloaterReg::add("env_edit_water", "floater_edit_water_preset.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditWater>);
-	LLFloaterReg::add("env_edit_day_cycle", "floater_edit_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditDayCycle>);
+
+    LLFloaterReg::add("env_fixed_environmentent_water", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentWater>);
+    LLFloaterReg::add("env_fixed_environmentent_sky", "floater_fixedenvironment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterFixedEnvironmentSky>);
+
+    LLFloaterReg::add("env_adjust_snapshot", "floater_adjust_environment.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEnvironmentAdjust>);
+
+    LLFloaterReg::add("env_edit_extdaycycle", "floater_edit_ext_day_cycle.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEditExtDayCycle>);
+    LLFloaterReg::add("my_environments", "floater_my_environments.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMyEnvironment>);
 
     LLFloaterReg::add("event", "floater_event.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterEvent>);
     LLFloaterReg::add("experiences", "floater_experiences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterExperiences>);
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
index 9cb2e0336a337a0786b1bd1892e4cf05c63faef7..afa84a5afc15a3b3b09fff993e6a72a306d15bad 100644
--- a/indra/newview/llviewerfoldertype.cpp
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -133,7 +133,8 @@ LLViewerFolderDictionary::LLViewerFolderDictionary()
 	addEntry(LLFolderType::FT_OUTFIT, 				new ViewerFolderEntry("New Outfit",				"Inv_LookFolderOpen",	"Inv_LookFolderClosed",	TRUE,      true));
 	addEntry(LLFolderType::FT_MY_OUTFITS, 			new ViewerFolderEntry("My Outfits",				"Inv_SysOpen",			"Inv_SysClosed",		TRUE,      true));
 	addEntry(LLFolderType::FT_MESH, 				new ViewerFolderEntry("Meshes",					"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
-	
+	addEntry(LLFolderType::FT_SETTINGS, 		    new ViewerFolderEntry("Settings",			    "Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
+
 	bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible");
 	addEntry(LLFolderType::FT_INBOX, 				new ViewerFolderEntry("Received Items",			"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     boxes_invisible));
 	addEntry(LLFolderType::FT_OUTBOX, 				new ViewerFolderEntry("Merchant Outbox",		"Inv_SysOpen",			"Inv_SysClosed",		FALSE,     true));
diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp
index 3df53a4a306a5db21736c5e1b1443c68a7ca93d6..d3de9d72bfa979b86b9536b8592b122c90ee478f 100644
--- a/indra/newview/llviewergenericmessage.cpp
+++ b/indra/newview/llviewergenericmessage.cpp
@@ -70,8 +70,6 @@ void send_generic_message(const std::string& method,
 	gAgent.sendReliableMessage();
 }
 
-
-
 void process_generic_message(LLMessageSystem* msg, void**)
 {
 	LLUUID agent_id;
@@ -93,3 +91,25 @@ void process_generic_message(LLMessageSystem* msg, void**)
 			<< LL_ENDL;
 	}
 }
+
+void process_large_generic_message(LLMessageSystem* msg, void**)
+{
+    LLUUID agent_id;
+    msg->getUUID("AgentData", "AgentID", agent_id);
+    if (agent_id != gAgent.getID())
+    {
+        LL_WARNS() << "GenericMessage for wrong agent" << LL_ENDL;
+        return;
+    }
+
+    std::string request;
+    LLUUID invoice;
+    LLDispatcher::sparam_t strings;
+    LLDispatcher::unpackLargeMessage(msg, request, invoice, strings);
+
+    if (!gGenericDispatcher.dispatch(request, invoice, strings))
+    {
+        LL_WARNS() << "GenericMessage " << request << " failed to dispatch"
+            << LL_ENDL;
+    }
+}
diff --git a/indra/newview/llviewergenericmessage.h b/indra/newview/llviewergenericmessage.h
index 9d451ec0bcb6f07bc0a5c9a6c07fc0d20234c369..170f38a48552931faed09f1bea03b5e350c3092f 100644
--- a/indra/newview/llviewergenericmessage.h
+++ b/indra/newview/llviewergenericmessage.h
@@ -38,6 +38,7 @@ void send_generic_message(const std::string& method,
 						  const LLUUID& invoice = LLUUID::null);
 
 void process_generic_message(LLMessageSystem* msg, void**);
+void process_large_generic_message(LLMessageSystem* msg, void**);
 
 
 extern LLDispatcher gGenericDispatcher;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 6ff02ffe66b3999b13c011993e35e31f2376b5ee..d0cbd1181bf39d25252cf84aa6d10c390d4ff897 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -70,6 +70,7 @@
 #include "llfloaterperms.h"
 #include "llclipboard.h"
 #include "llhttpretrypolicy.h"
+#include "llsettingsvo.h"
 
 // do-nothing ops for use in callbacks.
 void no_op_inventory_func(const LLUUID&) {} 
@@ -1098,7 +1099,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 						   const LLUUID& parent, const LLTransactionID& transaction_id,
 						   const std::string& name,
 						   const std::string& desc, LLAssetType::EType asset_type,
-						   LLInventoryType::EType inv_type, LLWearableType::EType wtype,
+						   LLInventoryType::EType inv_type, U8 subtype,
 						   U32 next_owner_perm,
 						   LLPointer<LLInventoryCallback> cb)
 {
@@ -1133,7 +1134,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 	msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm);
 	msg->addS8Fast(_PREHASH_Type, (S8)asset_type);
 	msg->addS8Fast(_PREHASH_InvType, (S8)inv_type);
-	msg->addU8Fast(_PREHASH_WearableType, (U8)wtype);
+	msg->addU8Fast(_PREHASH_WearableType, (U8)subtype);
 	msg->addStringFast(_PREHASH_Name, server_name);
 	msg->addStringFast(_PREHASH_Description, desc);
 	
@@ -1147,9 +1148,36 @@ void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent
 	LLAvatarNameCache::get(avatar_id, &av_name);
 	create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
 						  parent, LLTransactionID::tnull, av_name.getUserName(), item_desc, LLAssetType::AT_CALLINGCARD,
-						  LLInventoryType::IT_CALLINGCARD, NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, cb);
+                          LLInventoryType::IT_CALLINGCARD, NO_INV_SUBTYPE, PERM_MOVE | PERM_TRANSFER, cb);
 }
 
+void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, LLAssetType::EType asset_type,
+    LLWearableType::EType wtype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb)
+{
+    create_inventory_item(agent_id, session_id, parent, transaction_id,
+        name, desc, asset_type, LLInventoryType::IT_WEARABLE, static_cast<U8>(wtype),
+        next_owner_perm, cb);
+}
+
+void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, 
+    LLSettingsType::type_e settype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb)
+{
+    create_inventory_item(agent_id, session_id, parent, transaction_id,
+        name, desc, LLAssetType::AT_SETTINGS, LLInventoryType::IT_SETTINGS, 
+        static_cast<U8>(settype), next_owner_perm, cb);
+}
+
+
 void copy_inventory_item(
 	const LLUUID& agent_id,
 	const LLUUID& current_owner,
@@ -1701,7 +1729,7 @@ void create_new_item(const std::string& name,
 						  desc,
 						  asset_type,
 						  inv_type,
-						  NOT_WEARABLE,
+                          NO_INV_SUBTYPE,
 						  next_owner_perm,
 						  cb);
 }	
@@ -1794,6 +1822,32 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
 					  LLInventoryType::IT_GESTURE,
 					  PERM_ALL);	// overridden in create_new_item
 	}
+    else if (("sky" == type_name) || ("water" == type_name) || ("daycycle" == type_name))
+    {
+        LLSettingsType::type_e stype(LLSettingsType::ST_NONE);
+
+        if ("sky" == type_name)
+        {
+            stype = LLSettingsType::ST_SKY;
+        }
+        else if ("water" == type_name)
+        {
+            stype = LLSettingsType::ST_WATER;
+        }
+        else if ("daycycle" == type_name)
+        {
+            stype = LLSettingsType::ST_DAYCYCLE;
+        }
+        else
+        {
+            LL_ERRS(LOG_INV) << "Unknown settings type: '" << type_name << "'" << LL_ENDL;
+            return;
+        }
+
+        LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS);
+
+        LLSettingsVOBase::createNewInventoryItem(stype, parent_id);
+    }
 	else
 	{
 		// Use for all clothing and body parts.  Adding new wearable types requires updating LLWearableDictionary.
@@ -1974,6 +2028,19 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const
 	return LLWearableType::inventoryFlagsToWearableType(getFlags());
 }
 
+bool LLViewerInventoryItem::isSettingsType() const
+{
+    return (getInventoryType() == LLInventoryType::IT_SETTINGS);
+}
+
+LLSettingsType::type_e LLViewerInventoryItem::getSettingsType() const
+{
+    if (!isSettingsType())
+    {
+        return LLSettingsType::ST_NONE;
+    }
+    return LLSettingsType::fromInventoryFlags(getFlags());
+}
 
 time_t LLViewerInventoryItem::getCreationDate() const
 {
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index b3053e365bd2ce49a052338b9947b8636486bbe7..d537b2868200728b3cf0d04742cd7cbb280d520b 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -31,6 +31,7 @@
 #include "llframetimer.h"
 #include "llwearable.h"
 #include "llinitdestroyclass.h" //for LLDestroyClass
+#include "llinventorysettings.h"
 
 #include <boost/signals2.hpp>	// boost::signals2::trackable
 
@@ -74,6 +75,9 @@ class LLViewerInventoryItem : public LLInventoryItem, public boost::signals2::tr
 	virtual LLInventoryType::EType getInventoryType() const;
 	virtual bool isWearableType() const;
 	virtual LLWearableType::EType getWearableType() const;
+    virtual bool isSettingsType() const;
+    virtual LLSettingsType::type_e getSettingsType() const;
+
 	virtual U32 getFlags() const;
 	virtual time_t getCreationDate() const;
 	virtual U32 getCRC32() const; // really more of a checksum.
@@ -295,7 +299,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback
 
 	// virtual
 	void fire(const LLUUID& item_id)
-{
+    {
 		mFireFunc(item_id);
 	}
 
@@ -336,17 +340,32 @@ class LLInventoryCallbackManager : public LLDestroyClass<LLInventoryCallbackMana
 extern LLInventoryCallbackManager gInventoryCallbacks;
 
 
-#define NOT_WEARABLE (LLWearableType::EType)0
+const U8 NO_INV_SUBTYPE{ 0 };
 
 // *TODO: Find a home for these
 void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
 						   const LLUUID& parent, const LLTransactionID& transaction_id,
 						   const std::string& name,
 						   const std::string& desc, LLAssetType::EType asset_type,
-						   LLInventoryType::EType inv_type, LLWearableType::EType wtype,
+						   LLInventoryType::EType inv_type, U8 subtype,
 						   U32 next_owner_perm,
 						   LLPointer<LLInventoryCallback> cb);
 
+void create_inventory_wearable(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name,
+    const std::string& desc, LLAssetType::EType asset_type,
+    LLWearableType::EType wtype,
+    U32 next_owner_perm,
+    LLPointer<LLInventoryCallback> cb);
+
+void create_inventory_settings(const LLUUID& agent_id, const LLUUID& session_id,
+    const LLUUID& parent, const LLTransactionID& transaction_id,
+    const std::string& name, const std::string& desc, 
+    LLSettingsType::type_e settype, 
+    U32 next_owner_perm, LLPointer<LLInventoryCallback> cb);
+
+
 void create_inventory_callingcard(const LLUUID& avatar_id, const LLUUID& parent = LLUUID::null, LLPointer<LLInventoryCallback> cb=NULL);
 
 /**
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index b7bd131246a4ec3e647e229c3c494d6e8417c6ab..a448a95904bee8bcf65690f13b3da612164fe901 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -141,11 +141,10 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy )
 	//----------------------------------------------------------------
 	// render children
 	//----------------------------------------------------------------
-	for (child_list_t::iterator iter = mChildren.begin();
-		 iter != mChildren.end(); ++iter)
+	for (LLJoint* j : mChildren)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
-		F32 jointLOD = joint->getLOD();
+		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(j);
+		F32 jointLOD = joint ? joint->getLOD() : 0;
 		if (pixelArea >= jointLOD || sDisableLOD)
 		{
 			triangle_count += joint->render( pixelArea, TRUE, is_dummy );
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index 43a81ada4952ce35fb83e8fb4f757ee7a47fba33..6990f56a080c3116066bcee0814f222c0a077913 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -112,7 +112,7 @@ void LLViewerJointMesh::uploadJointMatrices()
 	S32 joint_num;
 	LLPolyMesh *reference_mesh = mMesh->getReferenceMesh();
 	LLDrawPool *poolp = mFace ? mFace->getPool() : NULL;
-	BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
+	BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE;
 
 	//calculate joint matrices
 	for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.size(); joint_num++)
@@ -246,7 +246,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 
 	stop_glerror();
 	
-	LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getVertexShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny);
+	LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getShaderLevel() > 0 || LLGLSLShader::sNoFixedFunction) ? 0.f : mShiny);
 
 	//----------------------------------------------------------------
 	// setup current texture
@@ -307,14 +307,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
 
 	if (mMesh->hasWeights())
 	{
-		if ((mFace->getPool()->getVertexShaderLevel() > 0))
+		if ((mFace->getPool()->getShaderLevel() > 0))
 		{
 			if (first_pass)
 			{
 				uploadJointMatrices();
 			}
 			mask = mask | LLVertexBuffer::MAP_WEIGHT;
-			if (mFace->getPool()->getVertexShaderLevel() > 1)
+			if (mFace->getPool()->getShaderLevel() > 1)
 			{
 				mask = mask | LLVertexBuffer::MAP_CLOTHWEIGHT;
 			}
@@ -390,7 +390,7 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w
 	}
 
 	LLDrawPool *poolp = mFace->getPool();
-	BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE;
+	BOOL hardware_skinning = (poolp && poolp->getShaderLevel() > 0) ? TRUE : FALSE;
 
 	if (!hardware_skinning && terse_update)
 	{ //no need to do terse updates if we're doing software vertex skinning
@@ -538,7 +538,7 @@ void LLViewerJointMesh::updateJointGeometry()
 		  && mFace
 		  && mMesh->hasWeights()
 		  && mFace->getVertexBuffer()
-		  && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
+		  && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) == 0))
 	{
 		return;
 	}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index ad15a81dfb9a1a9fe7de761709b2843c8f6bd563..b6c7be2ed3550d403fc6af79fbd7111c3b824400 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -52,9 +52,8 @@
 #include "llagentpilot.h"
 #include "llcompilequeue.h"
 #include "llconsole.h"
-#include "lldaycyclemanager.h"
 #include "lldebugview.h"
-#include "llenvmanager.h"
+#include "llenvironment.h"
 #include "llfilepicker.h"
 #include "llfirstuse.h"
 #include "llfloaterabout.h"
@@ -121,9 +120,6 @@
 #include "llworldmap.h"
 #include "pipeline.h"
 #include "llviewerjoystick.h"
-#include "llwaterparammanager.h"
-#include "llwlanimator.h"
-#include "llwlparammanager.h"
 #include "llfloatercamera.h"
 #include "lluilistener.h"
 #include "llappearancemgr.h"
@@ -136,6 +132,7 @@
 #include <boost/regex.hpp>
 #include <boost/algorithm/string.hpp>
 #include "llcleanup.h"
+#include "llviewershadermgr.h"
 
 using namespace LLAvatarAppearanceDefines;
 
@@ -2274,8 +2271,8 @@ class LLAdvancedEnableRenderDeferred: public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
+		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
+			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0;
 		return new_value;
 	}
 };
@@ -2287,8 +2284,8 @@ class LLAdvancedEnableRenderDeferredOptions: public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");
+		bool new_value = gGLManager.mHasFramebufferObject && LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1 &&
+			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 && gSavedSettings.getBOOL("RenderDeferred");
 		return new_value;
 	}
 };
@@ -7080,7 +7077,21 @@ BOOL object_is_wearable()
 	{
 		return FALSE;
 	}
-	return gAgentAvatarp->canAttachMoreObjects();
+    if (!gAgentAvatarp->canAttachMoreObjects())
+    {
+        return FALSE;
+    }
+	LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+	for (LLObjectSelection::valid_root_iterator iter = LLSelectMgr::getInstance()->getSelection()->valid_root_begin();
+		 iter != LLSelectMgr::getInstance()->getSelection()->valid_root_end(); iter++)
+	{
+		LLSelectNode* node = *iter;		
+		if (node->mPermissions->getOwner() == gAgent.getID())
+		{
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 
@@ -7378,6 +7389,8 @@ void handle_dump_attachments(void*)
 // these are used in the gl menus to set control values, generically.
 class LLToggleControl : public view_listener_t
 {
+protected:
+
 	bool handleEvent(const LLSD& userdata)
 	{
 		std::string control_name = userdata.asString();
@@ -7454,6 +7467,24 @@ class LLAdvancedClickRenderBenchmark: public view_listener_t
 	}
 };
 
+// these are used in the gl menus to set control values that require shader recompilation
+class LLToggleShaderControl : public view_listener_t
+{
+	bool handleEvent(const LLSD& userdata)
+	{
+        std::string control_name = userdata.asString();
+		BOOL checked = gSavedSettings.getBOOL( control_name );
+		gSavedSettings.setBOOL( control_name, !checked );
+        LLPipeline::refreshCachedSettings();
+        //gPipeline.updateRenderDeferred();
+		//gPipeline.releaseGLBuffers();
+		//gPipeline.createGLBuffers();
+		//gPipeline.resetVertexBuffers();
+        LLViewerShaderMgr::instance()->setShaders();
+		return !checked;
+	}
+};
+
 void menu_toggle_attached_lights(void* user_data)
 {
 	LLPipeline::sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights");
@@ -8255,6 +8286,14 @@ class LLViewToggleBeacon : public view_listener_t
 				gSavedSettings.setBOOL( "scriptsbeacon", LLPipeline::getRenderScriptedBeacons() );
 			}
 		}
+		else if (beacon == "sunbeacon")
+		{
+			gSavedSettings.setBOOL("sunbeacon", !gSavedSettings.getBOOL("sunbeacon"));
+		}
+		else if (beacon == "moonbeacon")
+		{
+			gSavedSettings.setBOOL("moonbeacon", !gSavedSettings.getBOOL("moonbeacon"));
+		}
 		else if (beacon == "renderbeacons")
 		{
 			LLPipeline::toggleRenderBeacons();
@@ -8471,42 +8510,73 @@ class LLToolsSelectTool : public view_listener_t
 /// WINDLIGHT callbacks
 class LLWorldEnvSettings : public view_listener_t
 {	
+    void defocusEnvFloaters()
+    {
+        //currently there is only one instance of each floater
+        std::vector<std::string> env_floaters_names = { "env_edit_extdaycycle", "env_fixed_environmentent_water", "env_fixed_environmentent_sky" };
+        for (std::vector<std::string>::const_iterator it = env_floaters_names.begin(); it != env_floaters_names.end(); ++it)
+        {
+            LLFloater* env_floater = LLFloaterReg::findTypedInstance<LLFloater>(*it);
+            if (env_floater)
+            {
+                env_floater->setFocus(FALSE);
+            }
+        }
+    }
+
 	bool handleEvent(const LLSD& userdata)
 	{
-		std::string tod = userdata.asString();
+		std::string event_name = userdata.asString();
 		
-		if (tod == "editor")
+		if (event_name == "sunrise")
 		{
-			LLFloaterReg::toggleInstance("env_settings");
-			return true;
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNRISE);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+            defocusEnvFloaters();
 		}
-
-		if (tod == "sunrise")
+		else if (event_name == "noon")
 		{
-			LLEnvManagerNew::instance().setUseSkyPreset("Sunrise");
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDDAY);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+            defocusEnvFloaters();
 		}
-		else if (tod == "noon")
+		else if (event_name == "sunset")
 		{
-			LLEnvManagerNew::instance().setUseSkyPreset("Midday");
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_SUNSET);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+            defocusEnvFloaters();
 		}
-		else if (tod == "sunset")
+		else if (event_name == "midnight")
 		{
-			LLEnvManagerNew::instance().setUseSkyPreset("Sunset");
+            LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_LOCAL, LLEnvironment::KNOWN_SKY_MIDNIGHT);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+            defocusEnvFloaters();
 		}
-		else if (tod == "midnight")
+        else if (event_name == "region")
 		{
-			LLEnvManagerNew::instance().setUseSkyPreset("Midnight");
+            LLEnvironment::instance().clearEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().setSelectedEnvironment(LLEnvironment::ENV_LOCAL);
+            LLEnvironment::instance().updateEnvironment();
+            defocusEnvFloaters();
 		}
+        else if (event_name == "pause_clouds")
+        {
+            if (LLEnvironment::instance().isCloudScrollPaused())
+                LLEnvironment::instance().resumeCloudScroll();
 		else
+                LLEnvironment::instance().pauseCloudScroll();
+        }
+        else if (event_name == "adjust_tool")
 		{
-			LLEnvManagerNew &envmgr = LLEnvManagerNew::instance();
-			// reset all environmental settings to track the region defaults, make this reset 'sticky' like the other sun settings.
-			bool use_fixed_sky = false;
-			bool use_region_settings = true;
-			envmgr.setUserPrefs(envmgr.getWaterPresetName(),
-					    envmgr.getSkyPresetName(),
-					    envmgr.getDayCycleName(),
-					    use_fixed_sky, use_region_settings);
+            LLFloaterReg::showInstance("env_adjust_snapshot");
+        }
+        else if (event_name == "my_environs")
+        {
+            LLFloaterReg::showInstance("my_environments");
 		}
 
 		return true;
@@ -8518,39 +8588,46 @@ class LLWorldEnableEnvSettings : public view_listener_t
 	bool handleEvent(const LLSD& userdata)
 	{
 		bool result = false;
-		std::string tod = userdata.asString();
+		std::string event_name = userdata.asString();
 
-		if (LLEnvManagerNew::instance().getUseRegionSettings())
+        if (event_name == "pause_clouds")
 		{
-			return (tod == "region");
+            return LLEnvironment::instance().isCloudScrollPaused();
 		}
 
-		if (LLEnvManagerNew::instance().getUseFixedSky())
+        LLSettingsSky::ptr_t sky = LLEnvironment::instance().getEnvironmentFixedSky(LLEnvironment::ENV_LOCAL);
+
+		if (!sky)
 		{
-			if (tod == "sunrise")
+			return (event_name == "region");
+		}
+
+        std::string skyname = (sky) ? sky->getName() : "";
+        LLUUID skyid = (sky) ? sky->getAssetId() : LLUUID::null;
+
+		if (event_name == "sunrise")
 			{
-				result = (LLEnvManagerNew::instance().getSkyPresetName() == "Sunrise");
+            result = (skyid == LLEnvironment::KNOWN_SKY_SUNRISE);
 			}
-			else if (tod == "noon")
+		else if (event_name == "noon")
 			{
-				result = (LLEnvManagerNew::instance().getSkyPresetName() == "Midday");
+            result = (skyid == LLEnvironment::KNOWN_SKY_MIDDAY);
 			}
-			else if (tod == "sunset")
+		else if (event_name == "sunset")
 			{
-				result = (LLEnvManagerNew::instance().getSkyPresetName() == "Sunset");
+            result = (skyid == LLEnvironment::KNOWN_SKY_SUNSET);
 			}
-			else if (tod == "midnight")
+		else if (event_name == "midnight")
 			{
-				result = (LLEnvManagerNew::instance().getSkyPresetName() == "Midnight");
+            result = (skyid == LLEnvironment::KNOWN_SKY_MIDNIGHT);
 			}
-			else if (tod == "region")
+		else if (event_name == "region")
 			{
 				return false;
 			}
 			else
 			{
-				LL_WARNS() << "Unknown time-of-day item:  " << tod << LL_ENDL;
-			}
+			LL_WARNS() << "Unknown time-of-day item:  " << event_name << LL_ENDL;
 		}
 		return result;
 	}
@@ -8564,39 +8641,27 @@ class LLWorldEnvPreset : public view_listener_t
 
 		if (item == "new_water")
 		{
-			LLFloaterReg::showInstance("env_edit_water", "new");
+            LLFloaterReg::showInstance("env_fixed_environmentent_water", "new");
 		}
 		else if (item == "edit_water")
 		{
-			LLFloaterReg::showInstance("env_edit_water", "edit");
-		}
-		else if (item == "delete_water")
-		{
-			LLFloaterReg::showInstance("env_delete_preset", "water");
+            LLFloaterReg::showInstance("env_fixed_environmentent_water", "edit");
 		}
 		else if (item == "new_sky")
 		{
-			LLFloaterReg::showInstance("env_edit_sky", "new");
+            LLFloaterReg::showInstance("env_fixed_environmentent_sky", "new");
 		}
 		else if (item == "edit_sky")
 		{
-			LLFloaterReg::showInstance("env_edit_sky", "edit");
-		}
-		else if (item == "delete_sky")
-		{
-			LLFloaterReg::showInstance("env_delete_preset", "sky");
+            LLFloaterReg::showInstance("env_fixed_environmentent_sky", "edit");
 		}
 		else if (item == "new_day_cycle")
 		{
-			LLFloaterReg::showInstance("env_edit_day_cycle", "new");
+            LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory"));
 		}
 		else if (item == "edit_day_cycle")
 		{
-			LLFloaterReg::showInstance("env_edit_day_cycle", "edit");
-		}
-		else if (item == "delete_day_cycle")
-		{
-			LLFloaterReg::showInstance("env_delete_preset", "day_cycle");
+			LLFloaterReg::showInstance("env_edit_extdaycycle", LLSDMap("edit_context", "inventory"));
 		}
 		else
 		{
@@ -8611,30 +8676,6 @@ class LLWorldEnableEnvPreset : public view_listener_t
 {
 	bool handleEvent(const LLSD& userdata)
 	{
-		std::string item = userdata.asString();
-
-		if (item == "delete_water")
-		{
-			LLWaterParamManager::preset_name_list_t user_waters;
-			LLWaterParamManager::instance().getUserPresetNames(user_waters);
-			return !user_waters.empty();
-		}
-		else if (item == "delete_sky")
-		{
-			LLWLParamManager::preset_name_list_t user_skies;
-			LLWLParamManager::instance().getUserPresetNames(user_skies);
-			return !user_skies.empty();
-		}
-		else if (item == "delete_day_cycle")
-		{
-			LLDayCycleManager::preset_name_list_t user_days;
-			LLDayCycleManager::instance().getUserPresetNames(user_days);
-			return !user_days.empty();
-		}
-		else
-		{
-			LL_WARNS() << "Unknown item" << LL_ENDL;
-		}
 
 		return false;
 	}
@@ -9227,6 +9268,7 @@ void initialize_menus()
 	enable.add("Object.EnableSit", boost::bind(&enable_object_sit, _1));
 
 	view_listener_t::addMenu(new LLObjectEnableReturn(), "Object.EnableReturn");
+	enable.add("Object.EnableDuplicate", boost::bind(&LLSelectMgr::canDuplicate, LLSelectMgr::getInstance()));
 	view_listener_t::addMenu(new LLObjectEnableReportAbuse(), "Object.EnableReportAbuse");
 
 	enable.add("Avatar.EnableMute", boost::bind(&enable_object_mute));
@@ -9266,6 +9308,7 @@ void initialize_menus()
 	view_listener_t::addMenu(new LLShowAgentProfile(), "ShowAgentProfile");
 	view_listener_t::addMenu(new LLToggleAgentProfile(), "ToggleAgentProfile");
 	view_listener_t::addMenu(new LLToggleControl(), "ToggleControl");
+    view_listener_t::addMenu(new LLToggleShaderControl(), "ToggleShaderControl");
 	view_listener_t::addMenu(new LLCheckControl(), "CheckControl");
 	view_listener_t::addMenu(new LLGoToObject(), "GoToObject");
 	commit.add("PayObject", boost::bind(&handle_give_money_dialog));
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 741ce7a18253491f303dcd520a34818b7bb3eeaf..d1d3a7fc1205a77bfb6563192e581966ee6b110c 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -416,7 +416,7 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification
 	for (std::vector<std::string>::const_iterator in_iter = filenames.begin(); in_iter != filenames.end(); ++in_iter)
 	{
 		std::string filename = (*in_iter);
-			
+		
 		std::string name = gDirUtilp->getBaseFileName(filename, true);
 		std::string asset_name = name;
 		LLStringUtil::replaceNonstandardASCII(asset_name, '?');
@@ -431,20 +431,20 @@ void do_bulk_upload(std::vector<std::string> filenames, const LLSD& notification
 		if (LLResourceUploadInfo::findAssetTypeAndCodecOfExtension(ext, asset_type, codec) &&
 			LLAgentBenefitsMgr::current().findUploadCost(asset_type, expected_upload_cost))
 		{
-			LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
-													   filename,
-													   asset_name,
-													   asset_name, 0,
-													   LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
-													   LLFloaterPerms::getNextOwnerPerms("Uploads"),
-													   LLFloaterPerms::getGroupPerms("Uploads"),
-													   LLFloaterPerms::getEveryonePerms("Uploads"),
-													   expected_upload_cost));
-			
-			upload_new_resource(uploadInfo, NULL, NULL);
-		}
+		LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+			filename,
+			asset_name,
+			asset_name, 0,
+			LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
+			LLFloaterPerms::getNextOwnerPerms("Uploads"),
+			LLFloaterPerms::getGroupPerms("Uploads"),
+			LLFloaterPerms::getEveryonePerms("Uploads"),
+			expected_upload_cost));
+
+		upload_new_resource(uploadInfo);
 	}
 }
+}
 
 bool get_bulk_upload_expected_cost(const std::vector<std::string>& filenames, S32& total_cost, S32& file_count, S32& bvh_count)
 {
@@ -781,7 +781,7 @@ LLUUID upload_new_resource(
 	bool show_inventory)
 {	
 
-    LLResourceUploadInfo::ptr_t uploadInfo(new LLNewFileResourceUploadInfo(
+    LLResourceUploadInfo::ptr_t uploadInfo(std::make_shared<LLNewFileResourceUploadInfo>(
         src_filename,
         name, desc, compression_info,
         destination_folder_type, inv_type,
@@ -864,7 +864,7 @@ void upload_done_callback(
 					create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
 							      folder_id, data->mAssetInfo.mTransactionID, data->mAssetInfo.getName(),
 							      data->mAssetInfo.getDescription(), data->mAssetInfo.mType,
-							      data->mInventoryType, NOT_WEARABLE, next_owner_perms,
+                                  data->mInventoryType, NO_INV_SUBTYPE, next_owner_perms,
 							      LLPointer<LLInventoryCallback>(NULL));
 				}
 				else
@@ -900,7 +900,7 @@ void upload_done_callback(
 		LLStringUtil::trim(asset_name);
 
 		std::string display_name = LLStringUtil::null;
-		LLAssetStorage::LLStoreAssetCallback callback = NULL;
+		LLAssetStorage::LLStoreAssetCallback callback;
 		void *userdata = NULL;
 		upload_new_resource(
 			next_file,
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index 4e8348b5e5254eccc9975cb7d381943869ec2f1c..4e6250d9b40f77192f7770e58997cf42364ff8a1 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -60,7 +60,7 @@ LLUUID upload_new_resource(
 
 void upload_new_resource(
     LLResourceUploadInfo::ptr_t &uploadInfo,
-    LLAssetStorage::LLStoreAssetCallback callback = NULL,
+    LLAssetStorage::LLStoreAssetCallback callback = LLAssetStorage::LLStoreAssetCallback(),
     void *userdata = NULL);
 
 
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index f4603463e2ea888a27becf52d0247ce701ac4d14..e07762646180211cf9415a085c0965c5a95f59b2 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3747,6 +3747,7 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data)
 void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
 {
 	LLVector3 sun_direction;
+    LLVector3 moon_direction;
 	LLVector3 sun_ang_velocity;
 	F32 phase;
 	U64	space_time_usec;
@@ -3768,12 +3769,10 @@ void process_time_synch(LLMessageSystem *mesgsys, void **user_data)
 
 	LL_DEBUGS("WindlightSync") << "Sun phase: " << phase << " rad = " << fmodf(phase / F_TWO_PI + 0.25, 1.f) * 24.f << " h" << LL_ENDL;
 
-	gSky.setSunPhase(phase);
-	gSky.setSunTargetDirection(sun_direction, sun_ang_velocity);
-	if ( !(gSavedSettings.getBOOL("SkyOverrideSimSunPosition") || gSky.getOverrideSun()) )
-	{
-		gSky.setSunDirection(sun_direction, sun_ang_velocity);
-	}
+	/* LAPRAS
+        We decode these parts of the message but ignore them
+        as the real values are provided elsewhere. */
+    (void)sun_direction, (void)moon_direction, (void)phase;
 }
 
 void process_sound_trigger(LLMessageSystem *msg, void **)
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 00a652384c189c66fa79f49a20a4be990f838d4c..6365df09e13834e241806460fa332d85b8f6fc8e 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -1116,10 +1116,6 @@ void LLOcclusionCullingGroup::checkOcclusion()
 					LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_WAIT);
 					while (!available && max_loop-- > 0)
 					{
-						//do some usefu work while we wait
-						F32 max_time = llmin(gFrameIntervalSeconds.value()*10.f, 1.f);
-						LLAppViewer::instance()->updateTextureThreads(max_time);
-						
 						glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
 					}
 				}
@@ -1272,7 +1268,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
 						{
 							LL_RECORD_BLOCK_TIME(FTM_OCCLUSION_DRAW_WATER);
 
-							LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
+							LLGLSquashToFarClip squash;
 							if (camera->getOrigin().isExactlyZero())
 							{ //origin is invalid, draw entire box
 								gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0);
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index d91d0abb991ecb81f4b7e5457a50935f48531287..e197591ef86b7f42c22018420861b4430f4ade1b 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -70,6 +70,8 @@
 #include "llvieweraudio.h"
 #include "llcorehttputil.h"
 
+#include "llenvironment.h"
+
 const F32 PARCEL_COLLISION_DRAW_SECS = 1.f;
 
 
@@ -646,6 +648,31 @@ LLParcel *LLViewerParcelMgr::getAgentParcel() const
 	return mAgentParcel;
 }
 
+
+LLParcel * LLViewerParcelMgr::getAgentOrSelectedParcel() const
+{
+    LLParcel *parcel(nullptr);
+
+    LLParcelSelectionHandle sel_handle(getFloatingParcelSelection());
+    if (sel_handle)
+    {
+        LLParcelSelection *selection(sel_handle.get());
+        if (selection)
+        {
+            parcel = selection->getParcel();
+            if (parcel && (parcel->getLocalID() == INVALID_PARCEL_ID))
+            {
+                parcel = NULL;
+            }
+        }
+    }
+
+    if (!parcel)
+        parcel = LLViewerParcelMgr::instance().getAgentParcel();
+
+    return parcel;
+}
+
 // Return whether the agent can build on the land they are on
 bool LLViewerParcelMgr::allowAgentBuild() const
 {
@@ -1286,6 +1313,13 @@ const std::string& LLViewerParcelMgr::getAgentParcelName() const
 }
 
 
+const S32 LLViewerParcelMgr::getAgentParcelId() const
+{
+    if (mAgentParcel)
+        return mAgentParcel->getLocalID();
+    return INVALID_PARCEL_ID;
+}
+
 void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_agent_region)
 {
 	if(!parcel) 
@@ -1516,6 +1550,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
     BOOL	region_deny_transacted_override = false; // Deprecated
     BOOL	region_deny_age_unverified_override = false;
     BOOL    region_allow_access_override = true;
+    BOOL    region_allow_environment_override = true;
+    S32     parcel_environment_version = 0;
     BOOL	agent_parcel_update = false; // updating previous(existing) agent parcel
 
     S32		other_clean_time = 0;
@@ -1606,6 +1642,12 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
         msg->getBOOLFast(_PREHASH_RegionAllowAccessBlock, _PREHASH_RegionAllowAccessOverride, region_allow_access_override);
     }
 
+    if (msg->getNumberOfBlocks(_PREHASH_ParcelEnvironmentBlock))
+    {
+        msg->getS32Fast(_PREHASH_ParcelEnvironmentBlock, _PREHASH_ParcelEnvironmentVersion, parcel_environment_version);
+        msg->getBOOLFast(_PREHASH_ParcelEnvironmentBlock, _PREHASH_RegionAllowEnvironmentOverride, region_allow_environment_override);
+    }
+
 	msg->getS32("ParcelData", "OtherCleanTime", other_clean_time );
 
 	LL_DEBUGS("ParcelMgr") << "Processing parcel " << local_id << " update, target(sequence): " << sequence_id << LL_ENDL;
@@ -1625,6 +1667,9 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
             }
         }
 
+        S32 cur_parcel_environment_version = parcel->getParcelEnvironmentVersion();
+        bool environment_changed = (cur_parcel_environment_version != parcel_environment_version);
+
 		parcel->init(owner_id,
 			FALSE, FALSE, FALSE,
 			claim_date, claim_price_per_meter, rent_price_per_meter,
@@ -1650,6 +1695,9 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 		parcel->setRegionDenyAnonymousOverride(region_deny_anonymous_override);
 		parcel->setRegionDenyAgeUnverifiedOverride(region_deny_age_unverified_override);
         parcel->setRegionAllowAccessOverride(region_allow_access_override);
+        parcel->setParcelEnvironmentVersion(cur_parcel_environment_version);
+        parcel->setRegionAllowEnvironmentOverride(region_allow_environment_override);
+
 		parcel->unpackMessage(msg);
 
 		if (parcel == parcel_mgr.mAgentParcel)
@@ -1683,12 +1731,23 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
 					instance->mTeleportFinishedSignal(instance->mTeleportInProgressPosition, false);
 				}
 			}
-		}
-		else if (agent_parcel_update)
-		{
-			// updated agent parcel
-			parcel_mgr.mAgentParcel->unpackMessage(msg);
-		}
+            parcel->setParcelEnvironmentVersion(parcel_environment_version);
+            LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
+            // Notify anything that wants to know when the agent changes parcels
+            gAgent.changeParcels();
+            instance->mTeleportInProgress = FALSE;
+        }
+        else if (agent_parcel_update)
+        {
+            parcel->setParcelEnvironmentVersion(parcel_environment_version);
+            // updated agent parcel
+            parcel_mgr.mAgentParcel->unpackMessage(msg);
+            if ((LLEnvironment::instance().isExtendedEnvironmentEnabled() && environment_changed))
+            {
+                LL_DEBUGS("ENVIRONMENT") << "Parcel environment version is " << parcel->getParcelEnvironmentVersion() << LL_ENDL;
+                LLEnvironment::instance().requestParcel(local_id);
+            }
+        }
 	}
 
 	// Handle updating selections, if necessary.
@@ -2616,3 +2675,9 @@ void LLViewerParcelMgr::onTeleportFailed()
 {
 	mTeleportFailedSignal();
 }
+
+bool  LLViewerParcelMgr::getTeleportInProgress()
+{
+    return mTeleportInProgress // case where parcel data arrives after teleport
+        || gAgent.getTeleportState() > LLAgent::TELEPORT_NONE; // For LOCAL, no mTeleportInProgress
+}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 288077fafc8a9624cf25b59446c6d37c108abf53..508a63c3981db9fe687ed1d12df0931b8b4044b7 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -154,6 +154,7 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 
 	//LLParcel *getParcelSelection() const;
 	LLParcel *getAgentParcel() const;
+    LLParcel *getAgentOrSelectedParcel() const;
 
 	BOOL	inAgentParcel(const LLVector3d &pos_global) const;
 
@@ -262,6 +263,7 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 
 	// accessors for mAgentParcel
 	const std::string& getAgentParcelName() const;
+    const S32 getAgentParcelId() const;
 
 	// Create a landmark at the "appropriate" location for the
 	// currently selected parcel.
@@ -286,6 +288,7 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr>
 	boost::signals2::connection setTeleportFailedCallback(teleport_failed_callback_t cb);
 	void onTeleportFinished(bool local, const LLVector3d& new_pos);
 	void onTeleportFailed();
+	bool getTeleportInProgress();
 
 	static BOOL isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power);
 	static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 654a028ec40790e5d46eef36e655c26f1c5eee64..e67826454b91686891477c85d1491bafe9f80bb6 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -80,6 +80,7 @@
 #include "lleventcoro.h"
 #include "llcorehttputil.h"
 #include "llcallstack.h"
+#include "llsettingsdaycycle.h"
 
 #ifdef LL_WINDOWS
 	#pragma warning(disable:4355)
@@ -2896,6 +2897,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("EstateAccess");
 	capabilityNames.append("EstateChangeInfo");
 	capabilityNames.append("EventQueueGet");
+    capabilityNames.append("ExtEnvironment");
 
 	capabilityNames.append("FetchLib2");
 	capabilityNames.append("FetchLibDescendents2");
@@ -2917,6 +2919,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("IsExperienceAdmin");
 	capabilityNames.append("IsExperienceContributor");
 	capabilityNames.append("RegionExperiences");
+    capabilityNames.append("ExperienceQuery");
 	capabilityNames.append("GetMetadata");
 	capabilityNames.append("GetObjectCost");
 	capabilityNames.append("GetObjectPhysicsData");
@@ -2967,6 +2970,8 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
 	capabilityNames.append("UpdateNotecardTaskInventory");
 	capabilityNames.append("UpdateScriptAgent");
 	capabilityNames.append("UpdateScriptTask");
+    capabilityNames.append("UpdateSettingsAgentInventory");
+    capabilityNames.append("UpdateSettingsTaskInventory");
 	capabilityNames.append("UploadBakedTexture");
     capabilityNames.append("UserInfo");
 	capabilityNames.append("ViewerAsset"); 
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 2548ff14230387ac1ff2d9c39e722b04861e760f..1b226ac2c69e2e0b0aab63a14675945f37202618 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -131,6 +131,7 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	inline BOOL isPrelude()					const;
 	inline BOOL getAllowTerraform() 		const;
 	inline BOOL getRestrictPushObject()		const;
+    inline BOOL getAllowEnvironmentOverride()   const;
 	inline BOOL getReleaseNotesRequested()		const;
 
 	bool isAlive(); // can become false if circuit disconnects
@@ -637,6 +638,11 @@ inline BOOL LLViewerRegion::getRestrictPushObject() const
 	return ((mRegionFlags & REGION_FLAGS_RESTRICT_PUSHOBJECT) != 0);
 }
 
+inline BOOL LLViewerRegion::getAllowEnvironmentOverride() const
+{
+    return ((mRegionFlags & REGION_FLAGS_ALLOW_ENVIRONMENT_OVERRIDE) != 0);
+}
+
 inline BOOL LLViewerRegion::getReleaseNotesRequested() const
 {
 	return mReleaseNotesRequested;
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 6d8b27ff2d84f159033073b353c29d22f6f00c9e..f108d9632073678d218eb13389e1b252cb4e3732 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -31,27 +31,24 @@
 
 #include "llfeaturemanager.h"
 #include "llviewershadermgr.h"
-
-#include "llfile.h"
-#include "llviewerwindow.h"
-#include "llwindow.h"
 #include "llviewercontrol.h"
-#include "pipeline.h"
+
+#include "llrender.h"
+#include "llenvironment.h"
+#include "llatmosphere.h"
 #include "llworld.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
 #include "llsky.h"
 #include "llvosky.h"
-#include "llrender.h"
+
+#include "pipeline.h"
+
+#include "llfile.h"
+#include "llviewerwindow.h"
+#include "llwindow.h"
+
 #include "lljoint.h"
 #include "llskinningutil.h"
 
-#ifdef LL_RELEASE_FOR_DOWNLOAD
-#define UNIFORM_ERRS LL_WARNS_ONCE("Shader")
-#else
-#define UNIFORM_ERRS LL_ERRS("Shader")
-#endif
-
 static LLStaticHashedString sTexture0("texture0");
 static LLStaticHashedString sTexture1("texture1");
 static LLStaticHashedString sTex0("tex0");
@@ -154,6 +151,7 @@ LLGLSLShader		gSkinnedObjectShinySimpleWaterProgram;
 LLGLSLShader		gTerrainProgram;
 LLGLSLShader		gTerrainWaterProgram;
 LLGLSLShader		gWaterProgram;
+LLGLSLShader        gWaterEdgeProgram;
 LLGLSLShader		gUnderWaterProgram;
 
 //interface shaders
@@ -178,7 +176,8 @@ LLGLSLShader		gImpostorProgram;
 // WindLight shader handles
 LLGLSLShader			gWLSkyProgram;
 LLGLSLShader			gWLCloudProgram;
-
+LLGLSLShader            gWLSunProgram;
+LLGLSLShader            gWLMoonProgram;
 
 // Effects Shaders
 LLGLSLShader			gGlowProgram;
@@ -200,6 +199,7 @@ LLGLSLShader			gDeferredSkinnedBumpProgram;
 LLGLSLShader			gDeferredSkinnedAlphaProgram;
 LLGLSLShader			gDeferredBumpProgram;
 LLGLSLShader			gDeferredTerrainProgram;
+LLGLSLShader            gDeferredTerrainWaterProgram;
 LLGLSLShader			gDeferredTreeProgram;
 LLGLSLShader			gDeferredTreeShadowProgram;
 LLGLSLShader			gDeferredAvatarProgram;
@@ -215,6 +215,7 @@ LLGLSLShader			gDeferredSoftenWaterProgram;
 LLGLSLShader			gDeferredShadowProgram;
 LLGLSLShader			gDeferredShadowCubeProgram;
 LLGLSLShader			gDeferredShadowAlphaMaskProgram;
+LLGLSLShader			gDeferredShadowFullbrightAlphaMaskProgram;
 LLGLSLShader			gDeferredAvatarShadowProgram;
 LLGLSLShader			gDeferredAvatarAlphaShadowProgram;
 LLGLSLShader			gDeferredAvatarAlphaMaskShadowProgram;
@@ -238,6 +239,8 @@ LLGLSLShader			gFXAAProgram;
 LLGLSLShader			gDeferredPostNoDoFProgram;
 LLGLSLShader			gDeferredWLSkyProgram;
 LLGLSLShader			gDeferredWLCloudProgram;
+LLGLSLShader			gDeferredWLSunProgram;
+LLGLSLShader			gDeferredWLMoonProgram;
 LLGLSLShader			gDeferredStarProgram;
 LLGLSLShader			gDeferredFullbrightShinyProgram;
 LLGLSLShader			gDeferredSkinnedFullbrightShinyProgram;
@@ -249,17 +252,20 @@ LLGLSLShader			gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
 LLGLSLShader			gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
 
 LLViewerShaderMgr::LLViewerShaderMgr() :
-	mVertexShaderLevel(SHADER_COUNT, 0),
+	mShaderLevel(SHADER_COUNT, 0),
 	mMaxAvatarShaderLevel(0)
-{	
-	/// Make sure WL Sky is the first program
-	//ONLY shaders that need WL Param management should be added here
+{   
+    /// Make sure WL Sky is the first program
+    //ONLY shaders that need WL Param management should be added here
 	mShaderList.push_back(&gWLSkyProgram);
 	mShaderList.push_back(&gWLCloudProgram);
+	mShaderList.push_back(&gWLSunProgram);
+	mShaderList.push_back(&gWLMoonProgram);
 	mShaderList.push_back(&gAvatarProgram);
 	mShaderList.push_back(&gObjectShinyProgram);
 	mShaderList.push_back(&gObjectShinyNonIndexedProgram);
 	mShaderList.push_back(&gWaterProgram);
+	mShaderList.push_back(&gWaterEdgeProgram);
 	mShaderList.push_back(&gAvatarEyeballProgram); 
 	mShaderList.push_back(&gObjectSimpleProgram);
 	mShaderList.push_back(&gObjectSimpleImpostorProgram);
@@ -314,22 +320,6 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredSunProgram);
 	mShaderList.push_back(&gDeferredSoftenProgram);
 	mShaderList.push_back(&gDeferredSoftenWaterProgram);
-	mShaderList.push_back(&gDeferredMaterialProgram[1]);
-	mShaderList.push_back(&gDeferredMaterialProgram[5]);
-	mShaderList.push_back(&gDeferredMaterialProgram[9]);
-	mShaderList.push_back(&gDeferredMaterialProgram[13]);
-	mShaderList.push_back(&gDeferredMaterialProgram[1+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialProgram[5+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialProgram[9+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialProgram[13+LLMaterial::SHADER_COUNT]);	
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[1]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[5]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[9]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[13]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[1+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[5+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[9+LLMaterial::SHADER_COUNT]);
-	mShaderList.push_back(&gDeferredMaterialWaterProgram[13+LLMaterial::SHADER_COUNT]);	
 	mShaderList.push_back(&gDeferredAlphaProgram);
 	mShaderList.push_back(&gDeferredAlphaImpostorProgram);
 	mShaderList.push_back(&gDeferredAlphaWaterProgram);
@@ -345,14 +335,17 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredAvatarEyesProgram);
 	mShaderList.push_back(&gDeferredWaterProgram);
 	mShaderList.push_back(&gDeferredUnderWaterProgram);	
+    mShaderList.push_back(&gDeferredTerrainWaterProgram);
 	mShaderList.push_back(&gDeferredAvatarAlphaProgram);
 	mShaderList.push_back(&gDeferredWLSkyProgram);
 	mShaderList.push_back(&gDeferredWLCloudProgram);
+    mShaderList.push_back(&gDeferredWLMoonProgram);
+    mShaderList.push_back(&gDeferredWLSunProgram);    
 }
 
 LLViewerShaderMgr::~LLViewerShaderMgr()
 {
-	mVertexShaderLevel.clear();
+	mShaderLevel.clear();
 	mShaderList.clear();
 }
 
@@ -389,9 +382,9 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)
 //============================================================================
 // Set Levels
 
-S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type)
+S32 LLViewerShaderMgr::getShaderLevel(S32 type)
 {
-	return LLPipeline::sDisableShaders ? 0 : mVertexShaderLevel[type];
+	return LLPipeline::sDisableShaders ? 0 : mShaderLevel[type];
 }
 
 //============================================================================
@@ -399,306 +392,341 @@ S32 LLViewerShaderMgr::getVertexShaderLevel(S32 type)
 
 void LLViewerShaderMgr::setShaders()
 {
-	//setShaders might be called redundantly by gSavedSettings, so return on reentrance
-	static bool reentrance = false;
-	
-	if (!gPipeline.mInitialized || !sInitialized || reentrance || sSkipReload)
-	{
-		return;
-	}
-
-	static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
-	LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1);
-
-	//NEVER use more than 16 texture channels (work around for prevalent driver bug)
-	LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16);
-
-	if (gGLManager.mGLSLVersionMajor < 1 ||
-		(gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20))
-	{ //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier
-		LLGLSLShader::sIndexedTextureChannels = 1;
-	}
-
-	reentrance = true;
-
-	if (LLRender::sGLCoreProfile)
-	{  
-		if (!gSavedSettings.getBOOL("VertexShaderEnable"))
-		{ //vertex shaders MUST be enabled to use core profile
-			gSavedSettings.setBOOL("VertexShaderEnable", TRUE);
-		}
-	}
-	
-	//setup preprocessor definitions
-	LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits);
-	
-	// Make sure the compiled shader map is cleared before we recompile shaders.
-	mShaderObjects.clear();
-	
-	initAttribsAndUniforms();
-	gPipeline.releaseGLBuffers();
-
-	if (gSavedSettings.getBOOL("VertexShaderEnable"))
-	{
-		LLPipeline::sWaterReflections = gGLManager.mHasCubeMap;
-		LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); 
-		LLPipeline::updateRenderDeferred();
-	}
-	else
-	{
-		LLPipeline::sRenderGlow = FALSE;
-		LLPipeline::sWaterReflections = FALSE;
-	}
-	
-	//hack to reset buffers that change behavior with shaders
-	gPipeline.resetVertexBuffers();
-
-	if (gViewerWindow)
-	{
-		gViewerWindow->setCursor(UI_CURSOR_WAIT);
-	}
-
-	// Lighting
-	gPipeline.setLightingDetail(-1);
-
-	// Shaders
-	LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL;
-	LL_INFOS("ShaderLoading") << llformat("Using GLSL %d.%d", gGLManager.mGLSLVersionMajor, gGLManager.mGLSLVersionMinor) << LL_ENDL;
-
-	for (S32 i = 0; i < SHADER_COUNT; i++)
-	{
-		mVertexShaderLevel[i] = 0;
-	}
-	mMaxAvatarShaderLevel = 0;
-
-	LLGLSLShader::sNoFixedFunction = false;
-	LLVertexBuffer::unbind();
-	if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") 
-		&& (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10)
-		&& gSavedSettings.getBOOL("VertexShaderEnable"))
-	{
-		//using shaders, disable fixed function
-		LLGLSLShader::sNoFixedFunction = true;
-
-		S32 light_class = 2;
-		S32 env_class = 2;
-		S32 obj_class = 2;
-		S32 effect_class = 2;
-		S32 wl_class = 2;
-		S32 water_class = 2;
-		S32 deferred_class = 0;
-		S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0;
-
-		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
-		if (!use_transform_feedback)
-		{
-			transform_class = 0;
-		}
-		
-		if (LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
-		    gSavedSettings.getBOOL("RenderDeferred") &&
-			gSavedSettings.getBOOL("RenderAvatarVP") &&
-			gSavedSettings.getBOOL("WindLightUseAtmosShaders"))
-		{
-			if (gSavedSettings.getS32("RenderShadowDetail") > 0)
-			{ //shadows
-				deferred_class = 2;
-			}
-			else
-			{ //no shadows
-				deferred_class = 1;
-			}
-
-			//make sure hardware skinning is enabled
-			//gSavedSettings.setBOOL("RenderAvatarVP", TRUE);
-			
-			//make sure atmospheric shaders are enabled
-			//gSavedSettings.setBOOL("WindLightUseAtmosShaders", TRUE);
-		}
-
-
-		if (!(LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders")
-			  && gSavedSettings.getBOOL("WindLightUseAtmosShaders")))
-		{
-			// user has disabled WindLight in their settings, downgrade
-			// windlight shaders to stub versions.
-			wl_class = 1;
-		}
-
-		
-		// Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders
-		if (mVertexShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull())
-		{
-			gSky.mVOSkyp->forceSkyUpdate();
-		}
-
-		
-		// Load lighting shaders
-		mVertexShaderLevel[SHADER_LIGHTING] = light_class;
-		mVertexShaderLevel[SHADER_INTERFACE] = light_class;
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class;
-		mVertexShaderLevel[SHADER_WATER] = water_class;
-		mVertexShaderLevel[SHADER_OBJECT] = obj_class;
-		mVertexShaderLevel[SHADER_EFFECT] = effect_class;
-		mVertexShaderLevel[SHADER_WINDLIGHT] = wl_class;
-		mVertexShaderLevel[SHADER_DEFERRED] = deferred_class;
-		mVertexShaderLevel[SHADER_TRANSFORM] = transform_class;
-
-		BOOL loaded = loadBasicShaders();
-
-		if (loaded)
-		{
-			gPipeline.mVertexShadersEnabled = TRUE;
-			gPipeline.mVertexShadersLoaded = 1;
-
-			// Load all shaders to set max levels
-			loaded = loadShadersEnvironment();
-
-			if (loaded)
-			{
-				loaded = loadShadersWater();
-			}
-
-			if (loaded)
-			{
-				loaded = loadShadersWindLight();
-			}
+    //setShaders might be called redundantly by gSavedSettings, so return on reentrance
+    static bool reentrance = false;
+    
+    if (!gPipeline.mInitialized || !sInitialized || reentrance || sSkipReload)
+    {
+        return;
+    }
 
-			if (loaded)
-			{
-				loaded = loadShadersEffects();
-			}
+    static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
+    LLGLSLShader::sIndexedTextureChannels = llmax(llmin(gGLManager.mNumTextureImageUnits, (S32) max_texture_index), 1);
 
-			if (loaded)
-			{
-				loaded = loadShadersInterface();
-			}
+    //NEVER use more than 16 texture channels (work around for prevalent driver bug)
+    LLGLSLShader::sIndexedTextureChannels = llmin(LLGLSLShader::sIndexedTextureChannels, 16);
 
-			if (loaded)
+    if (gGLManager.mGLSLVersionMajor < 1 ||
+        (gGLManager.mGLSLVersionMajor == 1 && gGLManager.mGLSLVersionMinor <= 20))
+    { //NEVER use indexed texture rendering when GLSL version is 1.20 or earlier
+        LLGLSLShader::sIndexedTextureChannels = 1;
+    }
 
-		    {
-				loaded = loadTransformShaders();
-			}
+    reentrance = true;
 
-			if (loaded)
-			{
-				// Load max avatar shaders to set the max level
-				mVertexShaderLevel[SHADER_AVATAR] = 3;
-				mMaxAvatarShaderLevel = 3;
-				
-				if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject())
-				{ //hardware skinning is enabled and rigged attachment shaders loaded correctly
-					BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
-					S32 avatar_class = 1;
-				
-					// cloth is a class3 shader
-					if(avatar_cloth)
-					{
-						avatar_class = 3;
-					}
-
-					// Set the actual level
-					mVertexShaderLevel[SHADER_AVATAR] = avatar_class;
-					loadShadersAvatar();
-					if (mVertexShaderLevel[SHADER_AVATAR] != avatar_class)
-					{
-						if (mVertexShaderLevel[SHADER_AVATAR] == 0)
-						{
-							gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
-						}
-						if(llmax(mVertexShaderLevel[SHADER_AVATAR]-1,0) >= 3)
-						{
-							avatar_cloth = true;
-						}
-						else
-						{
-							avatar_cloth = false;
-						}
-						gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth);
-					}
-				}
-				else
-				{ //hardware skinning not possible, neither is deferred rendering
-					mVertexShaderLevel[SHADER_AVATAR] = 0;
-					mVertexShaderLevel[SHADER_DEFERRED] = 0;
-
-					if (gSavedSettings.getBOOL("RenderAvatarVP"))
-					{
-						gSavedSettings.setBOOL("RenderDeferred", FALSE);
-						gSavedSettings.setBOOL("RenderAvatarCloth", FALSE);
-						gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
-					}
-
-					loadShadersAvatar(); // unloads
-
-					loaded = loadShadersObject();
-				}
-			}
+    //setup preprocessor definitions
+    LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits);
+    
+    // Make sure the compiled shader map is cleared before we recompile shaders.
+    mVertexShaderObjects.clear();
+    mFragmentShaderObjects.clear();
+    
+    initAttribsAndUniforms();
+    gPipeline.releaseGLBuffers();
 
-			if (!loaded)
-			{ //some shader absolutely could not load, try to fall back to a simpler setting
-				if (gSavedSettings.getBOOL("WindLightUseAtmosShaders"))
-				{ //disable windlight and try again
-					gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE);
-					reentrance = false;
-					setShaders();
-					return;
-				}
-
-				if (gSavedSettings.getBOOL("VertexShaderEnable"))
-				{ //disable shaders outright and try again
-					gSavedSettings.setBOOL("VertexShaderEnable", FALSE);
-					reentrance = false;
-					setShaders();
-					return;
-				}
-			}		
-
-			if (loaded && !loadShadersDeferred())
-			{ //everything else succeeded but deferred failed, disable deferred and try again
-				gSavedSettings.setBOOL("RenderDeferred", FALSE);
-				reentrance = false;
-				setShaders();
-				return;
-			}
-		}
-		else
-		{
-			LLGLSLShader::sNoFixedFunction = false;
-			gPipeline.mVertexShadersEnabled = FALSE;
-			gPipeline.mVertexShadersLoaded = 0;
-			mVertexShaderLevel[SHADER_LIGHTING] = 0;
-			mVertexShaderLevel[SHADER_INTERFACE] = 0;
-			mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-			mVertexShaderLevel[SHADER_WATER] = 0;
-			mVertexShaderLevel[SHADER_OBJECT] = 0;
-			mVertexShaderLevel[SHADER_EFFECT] = 0;
-			mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-			mVertexShaderLevel[SHADER_AVATAR] = 0;
-		}
-	}
-	else
-	{
-		LLGLSLShader::sNoFixedFunction = false;
-		gPipeline.mVertexShadersEnabled = FALSE;
-		gPipeline.mVertexShadersLoaded = 0;
-		mVertexShaderLevel[SHADER_LIGHTING] = 0;
-		mVertexShaderLevel[SHADER_INTERFACE] = 0;
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-		mVertexShaderLevel[SHADER_WATER] = 0;
-		mVertexShaderLevel[SHADER_OBJECT] = 0;
-		mVertexShaderLevel[SHADER_EFFECT] = 0;
-		mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-		mVertexShaderLevel[SHADER_AVATAR] = 0;
-	}
-	
-	if (gViewerWindow)
-	{
-		gViewerWindow->setCursor(UI_CURSOR_ARROW);
-	}
-	gPipeline.createGLBuffers();
+    LLPipeline::sWaterReflections = gGLManager.mHasCubeMap;
+    LLPipeline::sRenderGlow = gSavedSettings.getBOOL("RenderGlow"); 
+    LLPipeline::updateRenderDeferred();
+    
+    //hack to reset buffers that change behavior with shaders
+    gPipeline.resetVertexBuffers();
+
+    if (gViewerWindow)
+    {
+        gViewerWindow->setCursor(UI_CURSOR_WAIT);
+    }
+
+    // Lighting
+    gPipeline.setLightingDetail(-1);
+
+    // Shaders
+    LL_INFOS("ShaderLoading") << "\n~~~~~~~~~~~~~~~~~~\n Loading Shaders:\n~~~~~~~~~~~~~~~~~~" << LL_ENDL;
+    LL_INFOS("ShaderLoading") << llformat("Using GLSL %d.%d", gGLManager.mGLSLVersionMajor, gGLManager.mGLSLVersionMinor) << LL_ENDL;
+
+    for (S32 i = 0; i < SHADER_COUNT; i++)
+    {
+        mShaderLevel[i] = 0;
+    }
+    mMaxAvatarShaderLevel = 0;
+
+    LLGLSLShader::sNoFixedFunction = false;
+    LLVertexBuffer::unbind();
+
+    llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10));
+
+    bool canRenderDeferred       = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
+    bool hasWindLightShaders     = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");
+    S32 shadow_detail            = gSavedSettings.getS32("RenderShadowDetail");
+    bool useRenderDeferred       = canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");
+    bool doingWindLight          = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+
+    //using shaders, disable fixed function
+    LLGLSLShader::sNoFixedFunction = true;
+
+    S32 light_class = 3;
+    S32 interface_class = 2;
+    S32 env_class = 2;
+    S32 obj_class = 2;
+    S32 effect_class = 2;
+    S32 wl_class = 1;
+    S32 water_class = 2;
+    S32 deferred_class = 0;
+    S32 transform_class = gGLManager.mHasTransformFeedback ? 1 : 0;
+
+    static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
+    if (!use_transform_feedback)
+    {
+        transform_class = 0;
+    }
+
+    if (useRenderDeferred)
+    {
+        //shadows
+        switch (shadow_detail)
+        {                
+            case 1:
+                deferred_class = 2; // PCF shadows
+            break; 
+
+            case 2:
+                deferred_class = 2; // PCF shadows
+            break; 
+
+            case 0: 
+            default:
+                deferred_class = 1; // no shadows
+            break; 
+        }
+    }
+
+    if (doingWindLight)
+    {
+        // user has disabled WindLight in their settings, downgrade
+        // windlight shaders to stub versions.
+        wl_class = 2;
+    }
+    else
+    {
+        light_class = 2;
+    }
+
+    // Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders
+    if (!wl_class || (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull()))
+    {
+        gSky.mVOSkyp->forceSkyUpdate();
+    }
+
+    // Load lighting shaders
+    mShaderLevel[SHADER_LIGHTING] = light_class;
+    mShaderLevel[SHADER_INTERFACE] = interface_class;
+    mShaderLevel[SHADER_ENVIRONMENT] = env_class;
+    mShaderLevel[SHADER_WATER] = water_class;
+    mShaderLevel[SHADER_OBJECT] = obj_class;
+    mShaderLevel[SHADER_EFFECT] = effect_class;
+    mShaderLevel[SHADER_WINDLIGHT] = wl_class;
+    mShaderLevel[SHADER_DEFERRED] = deferred_class;
+    mShaderLevel[SHADER_TRANSFORM] = transform_class;
+
+    BOOL loaded = loadBasicShaders();
+    if (loaded)
+    {
+        LL_INFOS() << "Loaded basic shaders." << LL_ENDL;
+    }
+    else
+    {
+        LL_WARNS() << "Failed to load basic shaders." << LL_ENDL;
+        llassert(loaded);
+    }
+
+    if (loaded)
+    {
+        gPipeline.mVertexShadersEnabled = TRUE;
+        gPipeline.mVertexShadersLoaded = 1;
+
+        // Load all shaders to set max levels
+        loaded = loadShadersEnvironment();
+
+        if (loaded)
+        {
+            LL_INFOS() << "Loaded environment shaders." << LL_ENDL;
+        }
+        else
+        {
+            LL_WARNS() << "Failed to load environment shaders." << LL_ENDL;
+            llassert(loaded);
+        }
+
+        if (loaded)
+        {
+            loaded = loadShadersWater();
+            if (loaded)
+            {
+                LL_INFOS() << "Loaded water shaders." << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS() << "Failed to load water shaders." << LL_ENDL;
+                llassert(loaded);
+            }
+        }
+
+        if (loaded)
+        {
+            loaded = loadShadersWindLight();
+            if (loaded)
+            {
+                LL_INFOS() << "Loaded windlight shaders." << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS() << "Failed to load windlight shaders." << LL_ENDL;
+                llassert(loaded);
+            }
+        }
+
+        if (loaded)
+        {
+            loaded = loadShadersEffects();
+            if (loaded)
+            {
+                LL_INFOS() << "Loaded effects shaders." << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS() << "Failed to load effects shaders." << LL_ENDL;
+                llassert(loaded);
+            }
+        }
+
+        if (loaded)
+        {
+            loaded = loadShadersInterface();
+            if (loaded)
+            {
+                LL_INFOS() << "Loaded interface shaders." << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS() << "Failed to load interface shaders." << LL_ENDL;
+                llassert(loaded);
+            }
+        }
+
+        if (loaded)
+
+        {
+            loaded = loadTransformShaders();
+            if (loaded)
+            {
+                LL_INFOS() << "Loaded transform shaders." << LL_ENDL;
+            }
+            else
+            {
+                LL_WARNS() << "Failed to load transform shaders." << LL_ENDL;
+                llassert(loaded);
+            }
+        }
+
+        if (loaded)
+        {
+            // Load max avatar shaders to set the max level
+            mShaderLevel[SHADER_AVATAR] = 3;
+            mMaxAvatarShaderLevel = 3;
+                
+            if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject())
+            { //hardware skinning is enabled and rigged attachment shaders loaded correctly
+                BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth");
+
+                // cloth is a class3 shader
+                S32 avatar_class = avatar_cloth ? 3 : 1;
+                
+                // Set the actual level
+                mShaderLevel[SHADER_AVATAR] = avatar_class;
+
+                loaded = loadShadersAvatar();
+                llassert(loaded);
+
+                if (mShaderLevel[SHADER_AVATAR] != avatar_class)
+                {
+                    if (mShaderLevel[SHADER_AVATAR] == 0)
+                    {
+                        gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
+                    }
+                    if(llmax(mShaderLevel[SHADER_AVATAR]-1,0) >= 3)
+                    {
+                        avatar_cloth = true;
+                    }
+                    else
+                    {
+                        avatar_cloth = false;
+                    }
+                    gSavedSettings.setBOOL("RenderAvatarCloth", avatar_cloth);
+                }
+            }
+            else
+            { //hardware skinning not possible, neither is deferred rendering
+                mShaderLevel[SHADER_AVATAR] = 0;
+                mShaderLevel[SHADER_DEFERRED] = 0;
+
+                if (gSavedSettings.getBOOL("RenderAvatarVP"))
+                {
+                    gSavedSettings.setBOOL("RenderDeferred", FALSE);
+                    gSavedSettings.setBOOL("RenderAvatarCloth", FALSE);
+                    gSavedSettings.setBOOL("RenderAvatarVP", FALSE);
+                }
+
+                loadShadersAvatar(); // unloads
+
+                loaded = loadShadersObject();
+                llassert(loaded);
+            }
+        }
+
+        if (!loaded)
+        { //some shader absolutely could not load, try to fall back to a simpler setting
+            if (gSavedSettings.getBOOL("WindLightUseAtmosShaders"))
+            { //disable windlight and try again
+                gSavedSettings.setBOOL("WindLightUseAtmosShaders", FALSE);
+                LL_WARNS() << "Falling back to no windlight shaders." << LL_ENDL;
+                reentrance = false;
+                setShaders();
+                return;
+            }
+        }       
+
+        llassert(loaded);
+
+        if (loaded && !loadShadersDeferred())
+        { //everything else succeeded but deferred failed, disable deferred and try again
+            gSavedSettings.setBOOL("RenderDeferred", FALSE);
+            LL_WARNS() << "Falling back to no deferred shaders." << LL_ENDL;
+            reentrance = false;
+            setShaders();
+            return;
+        }
+    }
+    else
+    {
+        LLGLSLShader::sNoFixedFunction = false;
+        gPipeline.mVertexShadersEnabled = FALSE;
+        gPipeline.mVertexShadersLoaded = 0;
+        mShaderLevel[SHADER_LIGHTING] = 0;
+        mShaderLevel[SHADER_INTERFACE] = 0;
+        mShaderLevel[SHADER_ENVIRONMENT] = 0;
+        mShaderLevel[SHADER_WATER] = 0;
+        mShaderLevel[SHADER_OBJECT] = 0;
+        mShaderLevel[SHADER_EFFECT] = 0;
+        mShaderLevel[SHADER_WINDLIGHT] = 0;
+        mShaderLevel[SHADER_AVATAR] = 0;
+    }
+    
+    if (gViewerWindow)
+    {
+        gViewerWindow->setCursor(UI_CURSOR_ARROW);
+    }
+    gPipeline.createGLBuffers();
 
-	reentrance = false;
+    reentrance = false;
 }
 
 void LLViewerShaderMgr::unloadShaders()
@@ -780,6 +808,7 @@ void LLViewerShaderMgr::unloadShaders()
 	
 
 	gWaterProgram.unload();
+    gWaterEdgeProgram.unload();
 	gUnderWaterProgram.unload();
 	gTerrainProgram.unload();
 	gTerrainWaterProgram.unload();
@@ -795,6 +824,8 @@ void LLViewerShaderMgr::unloadShaders()
 
 	gWLSkyProgram.unload();
 	gWLCloudProgram.unload();
+    gWLSunProgram.unload();
+    gWLMoonProgram.unload();
 
 	gPostColorFilterProgram.unload();
 	gPostNightVisionProgram.unload();
@@ -814,15 +845,15 @@ void LLViewerShaderMgr::unloadShaders()
 	gTransformColorProgram.unload();
 	gTransformTangentProgram.unload();
 
-	mVertexShaderLevel[SHADER_LIGHTING] = 0;
-	mVertexShaderLevel[SHADER_OBJECT] = 0;
-	mVertexShaderLevel[SHADER_AVATAR] = 0;
-	mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
-	mVertexShaderLevel[SHADER_WATER] = 0;
-	mVertexShaderLevel[SHADER_INTERFACE] = 0;
-	mVertexShaderLevel[SHADER_EFFECT] = 0;
-	mVertexShaderLevel[SHADER_WINDLIGHT] = 0;
-	mVertexShaderLevel[SHADER_TRANSFORM] = 0;
+	mShaderLevel[SHADER_LIGHTING] = 0;
+	mShaderLevel[SHADER_OBJECT] = 0;
+	mShaderLevel[SHADER_AVATAR] = 0;
+	mShaderLevel[SHADER_ENVIRONMENT] = 0;
+	mShaderLevel[SHADER_WATER] = 0;
+	mShaderLevel[SHADER_INTERFACE] = 0;
+	mShaderLevel[SHADER_EFFECT] = 0;
+	mShaderLevel[SHADER_WINDLIGHT] = 0;
+	mShaderLevel[SHADER_TRANSFORM] = 0;
 
 	gPipeline.mVertexShadersLoaded = 0;
 }
@@ -856,7 +887,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 	if (gGLManager.mIsMobileGF)
 		sum_lights_class = 3;
 #endif
-	
+
 	// Use the feature table to mask out the max light level to use.  Also make sure it's at least 1.
 	S32 max_light_class = gSavedSettings.getS32("RenderShaderLightingMaxLevel");
 	sum_lights_class = llclamp(sum_lights_class, 1, max_light_class);
@@ -865,34 +896,55 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 	// (in order of shader function call depth for reference purposes, deepest level first)
 
 	vector< pair<string, S32> > shaders;
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/sumLightsV.glsl",				sum_lights_class ) );
-	shaders.push_back( make_pair( "lighting/lightV.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl",		mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl",		sum_lights_class ) );
-	shaders.push_back( make_pair( "lighting/lightSpecularV.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	shaders.push_back( make_pair( "windlight/atmosphericsV.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	shaders.push_back( make_pair( "avatar/avatarSkinV.glsl",				1 ) );
-	shaders.push_back( make_pair( "avatar/objectSkinV.glsl",				1 ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",       mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",  mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",    mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",               mShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "lighting/sumLightsV.glsl",               sum_lights_class ) );
+	shaders.push_back( make_pair( "lighting/lightV.glsl",                   mShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "lighting/lightFuncSpecularV.glsl",       mShaderLevel[SHADER_LIGHTING] ) );
+	shaders.push_back( make_pair( "lighting/sumLightsSpecularV.glsl",       sum_lights_class ) );
+	shaders.push_back( make_pair( "lighting/lightSpecularV.glsl",           mShaderLevel[SHADER_LIGHTING] ) );
+    shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl",       mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "windlight/atmosphericsV.glsl",           mShaderLevel[SHADER_WINDLIGHT] ) );
+	shaders.push_back( make_pair( "avatar/avatarSkinV.glsl",                1 ) );
+	shaders.push_back( make_pair( "avatar/objectSkinV.glsl",                1 ) );
 	if (gGLManager.mGLSLVersionMajor >= 2 || gGLManager.mGLSLVersionMinor >= 30)
 	{
-		shaders.push_back( make_pair( "objects/indexedTextureV.glsl",			1 ) );
+		shaders.push_back( make_pair( "objects/indexedTextureV.glsl",           1 ) );
 	}
-	shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl",		1 ) );
+	shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl",        1 ) );
 
 	boost::unordered_map<std::string, std::string> attribs;
 	attribs["MAX_JOINTS_PER_MESH_OBJECT"] = 
 		boost::lexical_cast<std::string>(LLSkinningUtil::getMaxJointCount());
 
+    BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable");
+	BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable");
+    BOOL local_light_kill = gSavedSettings.getBOOL("LocalLightDisable");
+
+    if (ambient_kill)
+    {
+        attribs["AMBIENT_KILL"] = "1";
+    }
+
+    if (sunlight_kill)
+    {
+        attribs["SUNLIGHT_KILL"] = "1";
+    }
+
+    if (local_light_kill)
+    {
+       attribs["LOCAL_LIGHT_KILL"] = "1";
+    }
+
 	// We no longer have to bind the shaders to global glhandles, they are automatically added to a map now.
 	for (U32 i = 0; i < shaders.size(); i++)
 	{
 		// Note usage of GL_VERTEX_SHADER_ARB
 		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER_ARB, &attribs) == 0)
 		{
+			LL_SHADER_LOADING_WARNS() << "Failed to load vertex shader " << shaders[i].first << LL_ENDL;
 			return FALSE;
 		}
 	}
@@ -908,43 +960,51 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
 		ch = llmax(LLGLSLShader::sIndexedTextureChannels-1, 1);
 	}
 
-	std::vector<S32> index_channels;
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/gammaF.glsl",					mVertexShaderLevel[SHADER_WINDLIGHT]) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",			mVertexShaderLevel[SHADER_WINDLIGHT] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "windlight/transportF.glsl",				mVertexShaderLevel[SHADER_WINDLIGHT] ) );	
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "environment/waterFogF.glsl",				mVertexShaderLevel[SHADER_WATER] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(-1);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl",					mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyF.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",	mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",			mVertexShaderLevel[SHADER_LIGHTING] ) );
-	index_channels.push_back(ch);	 shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) );
-	
+	std::vector<S32> index_channels;    
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl",      mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterF.glsl",     mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/atmosphericsHelpersF.glsl",       mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/gammaF.glsl",                 mShaderLevel[SHADER_WINDLIGHT]) );
+    index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/atmosphericsFuncs.glsl",       mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/atmosphericsF.glsl",          mShaderLevel[SHADER_WINDLIGHT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "windlight/transportF.glsl",             mShaderLevel[SHADER_WINDLIGHT] ) ); 
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "environment/waterFogF.glsl",                mShaderLevel[SHADER_WATER] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "environment/encodeNormF.glsl",	mShaderLevel[SHADER_ENVIRONMENT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "environment/srgbF.glsl",                    mShaderLevel[SHADER_ENVIRONMENT] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/deferredUtil.glsl",                    1) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/shadowUtil.glsl",                      1) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "deferred/aoUtil.glsl",                          1) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl",                    mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl",                   mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl",          mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl",         mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl",               mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl",              mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl",    mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl",               mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl",          mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(-1);    shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightF.glsl",                  mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl",                 mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl",            mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl",           mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightWaterF.glsl",             mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl",    mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl",   mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl",  mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightShinyF.glsl",             mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl",   mShaderLevel[SHADER_LIGHTING] ) );
+	index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl",            mShaderLevel[SHADER_LIGHTING] ) );
+    index_channels.push_back(ch);    shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
+    
 	for (U32 i = 0; i < shaders.size(); i++)
 	{
 		// Note usage of GL_FRAGMENT_SHADER_ARB
 		if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, &attribs, index_channels[i]) == 0)
 		{
+			LL_SHADER_LOADING_WARNS() << "Failed to load fragment shader " << shaders[i].first << LL_ENDL;
 			return FALSE;
 		}
 	}
@@ -956,7 +1016,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_ENVIRONMENT] == 0)
+	if (mShaderLevel[SHADER_ENVIRONMENT] == 0)
 	{
 		gTerrainProgram.unload();
 		return TRUE;
@@ -968,19 +1028,23 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()
 		gTerrainProgram.mFeatures.calculatesLighting = true;
 		gTerrainProgram.mFeatures.calculatesAtmospherics = true;
 		gTerrainProgram.mFeatures.hasAtmospherics = true;
+		gTerrainProgram.mFeatures.hasTransport = true;
+		gTerrainProgram.mFeatures.hasGamma = true;
+		gTerrainProgram.mFeatures.hasSrgb = true;
 		gTerrainProgram.mFeatures.mIndexedTextureChannels = 0;
 		gTerrainProgram.mFeatures.disableTextureIndex = true;
 		gTerrainProgram.mFeatures.hasGamma = true;
-		gTerrainProgram.mShaderFiles.clear();
-		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
-		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
-		success = gTerrainProgram.createShader(NULL, NULL);
+        gTerrainProgram.mShaderFiles.clear();
+        gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
+        gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gTerrainProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
+        success = gTerrainProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (!success)
 	{
-		mVertexShaderLevel[SHADER_ENVIRONMENT] = 0;
+		mShaderLevel[SHADER_ENVIRONMENT] = 0;
 		return FALSE;
 	}
 	
@@ -994,9 +1058,10 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 	BOOL success = TRUE;
 	BOOL terrainWaterSuccess = TRUE;
 
-	if (mVertexShaderLevel[SHADER_WATER] == 0)
+	if (mShaderLevel[SHADER_WATER] == 0)
 	{
 		gWaterProgram.unload();
+		gWaterEdgeProgram.unload();
 		gUnderWaterProgram.unload();
 		gTerrainWaterProgram.unload();
 		return TRUE;
@@ -1009,11 +1074,32 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		gWaterProgram.mFeatures.calculatesAtmospherics = true;
 		gWaterProgram.mFeatures.hasGamma = true;
 		gWaterProgram.mFeatures.hasTransport = true;
+        gWaterProgram.mFeatures.hasSrgb = true;
 		gWaterProgram.mShaderFiles.clear();
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];
+		gWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		gWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
 		success = gWaterProgram.createShader(NULL, NULL);
+		llassert(success);
+	}
+
+	if (success)
+	{
+	// load water shader
+		gWaterEdgeProgram.mName = "Water Edge Shader";
+		gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true;
+		gWaterEdgeProgram.mFeatures.hasGamma = true;
+		gWaterEdgeProgram.mFeatures.hasTransport = true;
+        gWaterEdgeProgram.mFeatures.hasSrgb = true;
+		gWaterEdgeProgram.mShaderFiles.clear();
+		gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
+		gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gWaterEdgeProgram.addPermutation("WATER_EDGE", "1");
+		gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
+		success = gWaterEdgeProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1021,13 +1107,14 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		//load under water vertex shader
 		gUnderWaterProgram.mName = "Underwater Shader";
 		gUnderWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gUnderWaterProgram.mFeatures.hasWaterFog = true;
 		gUnderWaterProgram.mShaderFiles.clear();
 		gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gUnderWaterProgram.mShaderFiles.push_back(make_pair("environment/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];
-		gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
-		
+		gUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_WATER];        
+		gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;       
 		success = gUnderWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1041,31 +1128,40 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		gTerrainWaterProgram.mFeatures.mIndexedTextureChannels = 0;
 		gTerrainWaterProgram.mFeatures.disableTextureIndex = true;
 		gTerrainWaterProgram.mShaderFiles.clear();
-		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));
+		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterV.glsl", GL_VERTEX_SHADER_ARB));
 		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTerrainWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];
+		gTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_ENVIRONMENT];
 		gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+
+        gTerrainWaterProgram.clearPermutations();
+
+        if (LLPipeline::RenderDeferred)
+        {
+            gTerrainWaterProgram.addPermutation("ALM", "1");
+        }
+
 		terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, NULL);
+		llassert(terrainWaterSuccess);
 	}	
 
 	/// Keep track of water shader levels
-	if (gWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER]
-		|| gUnderWaterProgram.mShaderLevel != mVertexShaderLevel[SHADER_WATER])
+	if (gWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER]
+		|| gUnderWaterProgram.mShaderLevel != mShaderLevel[SHADER_WATER])
 	{
-		mVertexShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel);
+		mShaderLevel[SHADER_WATER] = llmin(gWaterProgram.mShaderLevel, gUnderWaterProgram.mShaderLevel);
 	}
 
 	if (!success)
 	{
-		mVertexShaderLevel[SHADER_WATER] = 0;
+		mShaderLevel[SHADER_WATER] = 0;
 		return FALSE;
 	}
 
 	// if we failed to load the terrain water shaders and we need them (using class2 water),
 	// then drop down to class1 water.
-	if (mVertexShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess)
+	if (mShaderLevel[SHADER_WATER] > 1 && !terrainWaterSuccess)
 	{
-		mVertexShaderLevel[SHADER_WATER]--;
+		mShaderLevel[SHADER_WATER]--;
 		return loadShadersWater();
 	}
 	
@@ -1078,7 +1174,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_EFFECT] == 0)
+	if (mShaderLevel[SHADER_EFFECT] == 0)
 	{
 		gGlowProgram.unload();
 		gGlowExtractProgram.unload();
@@ -1093,7 +1189,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 		gGlowProgram.mShaderFiles.clear();
 		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+		gGlowProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
 		success = gGlowProgram.createShader(NULL, NULL);
 		if (!success)
 		{
@@ -1107,7 +1203,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 		gGlowExtractProgram.mShaderFiles.clear();
 		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT];
+		gGlowExtractProgram.mShaderLevel = mShaderLevel[SHADER_EFFECT];
 		success = gGlowExtractProgram.createShader(NULL, NULL);
 		if (!success)
 		{
@@ -1121,7 +1217,13 @@ BOOL LLViewerShaderMgr::loadShadersEffects()
 
 BOOL LLViewerShaderMgr::loadShadersDeferred()
 {
-	if (mVertexShaderLevel[SHADER_DEFERRED] == 0)
+    bool use_sun_shadow = mShaderLevel[SHADER_DEFERRED] > 1;
+
+    BOOL ambient_kill = gSavedSettings.getBOOL("AmbientDisable");
+	BOOL sunlight_kill = gSavedSettings.getBOOL("SunlightDisable");
+    BOOL local_light_kill = gSavedSettings.getBOOL("LocalLightDisable");
+
+	if (mShaderLevel[SHADER_DEFERRED] == 0)
 	{
 		gDeferredTreeProgram.unload();
 		gDeferredTreeShadowProgram.unload();
@@ -1136,6 +1238,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredBumpProgram.unload();
 		gDeferredImpostorProgram.unload();
 		gDeferredTerrainProgram.unload();
+		gDeferredTerrainWaterProgram.unload();
 		gDeferredLightProgram.unload();
 		for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; ++i)
 		{
@@ -1149,9 +1252,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSoftenWaterProgram.unload();
 		gDeferredShadowProgram.unload();
 		gDeferredShadowCubeProgram.unload();
-		gDeferredShadowAlphaMaskProgram.unload();
+        gDeferredShadowAlphaMaskProgram.unload();
+        gDeferredShadowFullbrightAlphaMaskProgram.unload();
 		gDeferredAvatarShadowProgram.unload();
+        gDeferredAvatarAlphaShadowProgram.unload();
+        gDeferredAvatarAlphaMaskShadowProgram.unload();
 		gDeferredAttachmentShadowProgram.unload();
+        gDeferredAttachmentAlphaShadowProgram.unload();
+        gDeferredAttachmentAlphaMaskShadowProgram.unload();
 		gDeferredAvatarProgram.unload();
 		gDeferredAvatarAlphaProgram.unload();
 		gDeferredAlphaProgram.unload();
@@ -1171,6 +1279,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredUnderWaterProgram.unload();
 		gDeferredWLSkyProgram.unload();
 		gDeferredWLCloudProgram.unload();
+        gDeferredWLSunProgram.unload();
+        gDeferredWLMoonProgram.unload();
 		gDeferredStarProgram.unload();
 		gDeferredFullbrightShinyProgram.unload();
 		gDeferredSkinnedFullbrightShinyProgram.unload();
@@ -1197,7 +1307,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredHighlightProgram.mShaderFiles.clear();
 		gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredHighlightProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gDeferredHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gDeferredHighlightProgram.createShader(NULL, NULL);
 	}
 
@@ -1207,7 +1317,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredHighlightNormalProgram.mShaderFiles.clear();
 		gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredHighlightNormalProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gDeferredHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gHighlightNormalProgram.createShader(NULL, NULL);
 	}
 
@@ -1217,83 +1327,97 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredHighlightSpecularProgram.mShaderFiles.clear();
 		gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredHighlightSpecularProgram.mShaderFiles.push_back(make_pair("deferred/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gDeferredHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];		
 		success = gDeferredHighlightSpecularProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
 		gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader";
+        gDeferredDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredDiffuseProgram.mFeatures.hasSrgb = true;
 		gDeferredDiffuseProgram.mShaderFiles.clear();
 		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDiffuseProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
 		gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader";
+        gDeferredDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
 	if (success)
 	{
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
+		gDeferredNonIndexedDiffuseAlphaMaskProgram.mFeatures.encodesNormal = true;
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
-	
+    
 	if (success)
 	{
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader";
+		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mFeatures.encodesNormal = true;
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.clear();
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader";
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear();
+        gDeferredNonIndexedDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredNonIndexedDiffuseProgram.mFeatures.hasSrgb = true;
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredNonIndexedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
-		
 
 	if (success)
 	{
 		gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
 		gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true;
+		gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true;
+        gDeferredSkinnedDiffuseProgram.mFeatures.hasSrgb = true;
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.clear();
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader";
 		gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true;
+        gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = true;
 		gDeferredSkinnedBumpProgram.mShaderFiles.clear();
 		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
@@ -1304,16 +1428,47 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasSrgb = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.encodesNormal = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
+		gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true;
+        
 		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSkinnedAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+		gDeferredSkinnedAlphaProgram.clearPermutations();
 		gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
 		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1");
-		gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
+        gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
+
+		if (use_sun_shadow)
+		{
+			gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", "1");
+		}
+
+        if (ambient_kill)
+        {
+            gDeferredSkinnedAlphaProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredSkinnedAlphaProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredSkinnedAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
+
 		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
-		
+		llassert(success);
+
 		// Hack to include uniforms for lighting without linking in lighting file
 		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
@@ -1322,11 +1477,13 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredBumpProgram.mName = "Deferred Bump Shader";
+		gDeferredBumpProgram.mFeatures.encodesNormal = true;
 		gDeferredBumpProgram.mShaderFiles.clear();
 		gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredBumpProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	gDeferredMaterialProgram[1].mFeatures.hasLighting = false;
@@ -1351,6 +1508,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		if (success)
 		{
+            mShaderList.push_back(&gDeferredMaterialProgram[i]);
+
 			gDeferredMaterialProgram[i].mName = llformat("Deferred Material Shader %d", i);
 			
 			U32 alpha_mode = i & 0x3;
@@ -1358,48 +1517,138 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 			gDeferredMaterialProgram[i].mShaderFiles.clear();
 			gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
 			gDeferredMaterialProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gDeferredMaterialProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-			gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0");
-			gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0");
-			gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
-			gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-			bool has_skin = i & 0x10;
-			gDeferredMaterialProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0");
-
-			if (has_skin)
-			{
-				gDeferredMaterialProgram[i].mFeatures.hasObjectSkinning = true;
-			}
+			gDeferredMaterialProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
-			success = gDeferredMaterialProgram[i].createShader(NULL, NULL);
-		}
+			gDeferredMaterialProgram[i].clearPermutations();
 
-		if (success)
-		{
-			gDeferredMaterialWaterProgram[i].mName = llformat("Deferred Underwater Material Shader %d", i);
+			bool has_normal_map   = (i & 0x8) > 0;
+			bool has_specular_map = (i & 0x4) > 0;
 
-			U32 alpha_mode = i & 0x3;
+			if (has_normal_map)
+			{
+				gDeferredMaterialProgram[i].addPermutation("HAS_NORMAL_MAP", "1");
+			}
 
-			gDeferredMaterialWaterProgram[i].mShaderFiles.clear();
-			gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
-			gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gDeferredMaterialWaterProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-			gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER;
-
-			gDeferredMaterialWaterProgram[i].addPermutation("HAS_NORMAL_MAP", i & 0x8? "1" : "0");
-			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SPECULAR_MAP", i & 0x4 ? "1" : "0");
-			gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
-			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-			bool has_skin = i & 0x10;
-			gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN",has_skin ? "1" : "0");
-			gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1");
-
-			if (has_skin)
+			if (has_specular_map)
 			{
-				gDeferredMaterialWaterProgram[i].mFeatures.hasObjectSkinning = true;
+				gDeferredMaterialProgram[i].addPermutation("HAS_SPECULAR_MAP", "1");
 			}
 
-			success = gDeferredMaterialWaterProgram[i].createShader(NULL, NULL);//&mWLUniforms);
+            if (ambient_kill)
+            {
+                gDeferredMaterialProgram[i].addPermutation("AMBIENT_KILL", "1");
+            }
+
+            if (sunlight_kill)
+            {
+                gDeferredMaterialProgram[i].addPermutation("SUNLIGHT_KILL", "1");
+            }
+
+            if (local_light_kill)
+            {
+                gDeferredMaterialProgram[i].addPermutation("LOCAL_LIGHT_KILL", "1");
+            }
+
+            gDeferredMaterialProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
+
+            if (use_sun_shadow)
+            {
+                gDeferredMaterialProgram[i].addPermutation("HAS_SUN_SHADOW", "1");
+            }
+
+            bool has_skin = i & 0x10;
+            gDeferredMaterialProgram[i].mFeatures.hasSrgb = true;
+            gDeferredMaterialProgram[i].mFeatures.hasTransport = true;
+            gDeferredMaterialProgram[i].mFeatures.encodesNormal = true;
+            gDeferredMaterialProgram[i].mFeatures.calculatesAtmospherics = true;
+            gDeferredMaterialProgram[i].mFeatures.hasAtmospherics = true;
+            gDeferredMaterialProgram[i].mFeatures.hasGamma = true;
+            gDeferredMaterialProgram[i].mFeatures.hasShadows = use_sun_shadow;
+            
+            if (has_skin)
+            {
+                gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1");
+                gDeferredMaterialProgram[i].mFeatures.hasObjectSkinning = true;
+            }
+
+            success = gDeferredMaterialProgram[i].createShader(NULL, NULL);
+            llassert(success);
+		}
+
+		if (success)
+		{
+            mShaderList.push_back(&gDeferredMaterialWaterProgram[i]);
+
+            gDeferredMaterialWaterProgram[i].mName = llformat("Deferred Underwater Material Shader %d", i);
+
+            U32 alpha_mode = i & 0x3;
+
+            gDeferredMaterialWaterProgram[i].mShaderFiles.clear();
+            gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialV.glsl", GL_VERTEX_SHADER_ARB));
+            gDeferredMaterialWaterProgram[i].mShaderFiles.push_back(make_pair("deferred/materialF.glsl", GL_FRAGMENT_SHADER_ARB));
+            gDeferredMaterialWaterProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+            gDeferredMaterialWaterProgram[i].mShaderGroup = LLGLSLShader::SG_WATER;
+
+            gDeferredMaterialWaterProgram[i].clearPermutations();
+
+            bool has_normal_map   = (i & 0x8) > 0;
+            bool has_specular_map = (i & 0x4) > 0;
+
+            if (has_normal_map)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("HAS_NORMAL_MAP", "1");
+            }
+
+            if (has_specular_map)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("HAS_SPECULAR_MAP", "1");
+            }
+
+            gDeferredMaterialWaterProgram[i].addPermutation("DIFFUSE_ALPHA_MODE", llformat("%d", alpha_mode));
+            if (use_sun_shadow)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("HAS_SUN_SHADOW", "1");
+            }
+
+            bool has_skin = i & 0x10;
+            if (has_skin)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN", "1");
+            }
+            gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1");
+
+            if (ambient_kill)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("AMBIENT_KILL", "1");
+            }
+
+            if (sunlight_kill)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("SUNLIGHT_KILL", "1");
+            }
+
+            if (local_light_kill)
+            {
+                gDeferredMaterialWaterProgram[i].addPermutation("LOCAL_LIGHT_KILL", "1");
+            }
+
+            gDeferredMaterialWaterProgram[i].mFeatures.hasWaterFog = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasSrgb = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.encodesNormal = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.calculatesAtmospherics = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasAtmospherics = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasGamma = true;
+
+            gDeferredMaterialWaterProgram[i].mFeatures.hasTransport = true;
+            gDeferredMaterialWaterProgram[i].mFeatures.hasShadows = use_sun_shadow;
+            
+            if (has_skin)
+            {
+                gDeferredMaterialWaterProgram[i].mFeatures.hasObjectSkinning = true;
+            }
+
+            success = gDeferredMaterialWaterProgram[i].createShader(NULL, NULL);//&mWLUniforms);
+            llassert(success);
 		}
 	}
 
@@ -1426,9 +1675,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredTreeProgram.mName = "Deferred Tree Shader";
 		gDeferredTreeProgram.mShaderFiles.clear();
+        gDeferredTreeProgram.mFeatures.encodesNormal = true;
 		gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTreeProgram.mShaderFiles.push_back(make_pair("deferred/treeF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredTreeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredTreeProgram.createShader(NULL, NULL);
 	}
 
@@ -1436,44 +1686,95 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredTreeShadowProgram.mName = "Deferred Tree Shadow Shader";
 		gDeferredTreeShadowProgram.mShaderFiles.clear();
+		gDeferredTreeShadowProgram.mFeatures.isDeferred = true;
+		gDeferredTreeShadowProgram.mFeatures.hasShadows = true;
 		gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredTreeShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredTreeShadowProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredImpostorProgram.mName = "Deferred Impostor Shader";
+		gDeferredImpostorProgram.mFeatures.hasSrgb = true;
+		gDeferredImpostorProgram.mFeatures.encodesNormal = true;
+		//gDeferredImpostorProgram.mFeatures.isDeferred = true;
 		gDeferredImpostorProgram.mShaderFiles.clear();
 		gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		success = gDeferredImpostorProgram.createShader(NULL, NULL);
+        gDeferredImpostorProgram.mShaderFiles.push_back(make_pair("deferred/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gDeferredImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        success = gDeferredImpostorProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
-	{		
+	{       
 		gDeferredLightProgram.mName = "Deferred Light Shader";
+		gDeferredLightProgram.mFeatures.isDeferred = true;
+		gDeferredLightProgram.mFeatures.hasShadows = true;
+        gDeferredLightProgram.mFeatures.hasSrgb = true;
+
 		gDeferredLightProgram.mShaderFiles.clear();
 		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        gDeferredLightProgram.clearPermutations();
+
+        if (ambient_kill)
+        {
+            gDeferredLightProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredLightProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredLightProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
 
 		success = gDeferredLightProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	for (U32 i = 0; i < LL_DEFERRED_MULTI_LIGHT_COUNT; i++)
 	{
-	if (success)
-	{
+		if (success)
+		{
 			gDeferredMultiLightProgram[i].mName = llformat("Deferred MultiLight Shader %d", i);
+			gDeferredMultiLightProgram[i].mFeatures.isDeferred = true;
+			gDeferredMultiLightProgram[i].mFeatures.hasShadows = true;
+            gDeferredMultiLightProgram[i].mFeatures.hasSrgb = true;
+
+            gDeferredMultiLightProgram[i].clearPermutations();
 			gDeferredMultiLightProgram[i].mShaderFiles.clear();
 			gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
 			gDeferredMultiLightProgram[i].mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gDeferredMultiLightProgram[i].mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+			gDeferredMultiLightProgram[i].mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 			gDeferredMultiLightProgram[i].addPermutation("LIGHT_COUNT", llformat("%d", i+1));
+
+            if (ambient_kill)
+            {
+                gDeferredMultiLightProgram[i].addPermutation("AMBIENT_KILL", "1");
+            }
+
+            if (sunlight_kill)
+            {
+                gDeferredMultiLightProgram[i].addPermutation("SUNLIGHT_KILL", "1");
+            }
+
+            if (local_light_kill)
+            {
+                gDeferredMultiLightProgram[i].addPermutation("LOCAL_LIGHT_KILL", "1");
+            }
+
 			success = gDeferredMultiLightProgram[i].createShader(NULL, NULL);
+            llassert(success);
 		}
 	}
 
@@ -1481,22 +1782,54 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	{
 		gDeferredSpotLightProgram.mName = "Deferred SpotLight Shader";
 		gDeferredSpotLightProgram.mShaderFiles.clear();
+		gDeferredSpotLightProgram.mFeatures.hasSrgb = true;
+		gDeferredSpotLightProgram.mFeatures.isDeferred = true;
+		gDeferredSpotLightProgram.mFeatures.hasShadows = true;
+
+        gDeferredSpotLightProgram.clearPermutations();
 		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/spotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        if (ambient_kill)
+        {
+            gDeferredSpotLightProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredSpotLightProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredSpotLightProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
 
 		success = gDeferredSpotLightProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredMultiSpotLightProgram.mName = "Deferred MultiSpotLight Shader";
+		gDeferredMultiSpotLightProgram.mFeatures.hasSrgb = true;
+		gDeferredMultiSpotLightProgram.mFeatures.isDeferred = true;
+		gDeferredMultiSpotLightProgram.mFeatures.hasShadows = true;
+
+        gDeferredMultiSpotLightProgram.clearPermutations();
 		gDeferredMultiSpotLightProgram.mShaderFiles.clear();
 		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredMultiSpotLightProgram.mShaderFiles.push_back(make_pair("deferred/multiSpotLightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredMultiSpotLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredMultiSpotLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        if (local_light_kill)
+        {
+            gDeferredMultiSpotLightProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
 
 		success = gDeferredMultiSpotLightProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
@@ -1504,37 +1837,48 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		std::string fragment;
 		std::string vertex = "deferred/sunLightV.glsl";
 
-		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
-		{
-			fragment = "deferred/sunLightSSAOF.glsl";
-		}
-		else
-		{
-			fragment = "deferred/sunLightF.glsl";
-			if (mVertexShaderLevel[SHADER_DEFERRED] == 1)
-			{ //no shadows, no SSAO, no frag coord
-				vertex = "deferred/sunLightNoFragCoordV.glsl";
-			}
-		}
-
-		gDeferredSunProgram.mName = "Deferred Sun Shader";
+        bool use_ao = gSavedSettings.getBOOL("RenderDeferredSSAO");
+
+        if (use_ao)
+        {
+            fragment = "deferred/sunLightSSAOF.glsl";
+        }
+        else
+        {
+            fragment = "deferred/sunLightF.glsl";
+            if (mShaderLevel[SHADER_DEFERRED] == 1)
+            { //no shadows, no SSAO, no frag coord
+                vertex = "deferred/sunLightNoFragCoordV.glsl";
+            }
+        }
+
+        gDeferredSunProgram.mName = "Deferred Sun Shader";
+        gDeferredSunProgram.mFeatures.isDeferred    = true;
+        gDeferredSunProgram.mFeatures.hasShadows    = true;
+        gDeferredSunProgram.mFeatures.hasAmbientOcclusion = use_ao;
+
+        gDeferredSunProgram.mName = "Deferred Sun Shader";
 		gDeferredSunProgram.mShaderFiles.clear();
 		gDeferredSunProgram.mShaderFiles.push_back(make_pair(vertex, GL_VERTEX_SHADER_ARB));
 		gDeferredSunProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
-		gDeferredSunProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
-		success = gDeferredSunProgram.createShader(NULL, NULL);
+        success = gDeferredSunProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredBlurLightProgram.mName = "Deferred Blur Light Shader";
+		gDeferredBlurLightProgram.mFeatures.isDeferred = true;
+
 		gDeferredBlurLightProgram.mShaderFiles.clear();
 		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredBlurLightProgram.mShaderFiles.push_back(make_pair("deferred/blurLightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredBlurLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredBlurLightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredBlurLightProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
@@ -1545,63 +1889,105 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
-		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
-		{
-			gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		}
-		else
-		{ //shave off some texture units for shadow maps
-			gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
-		}
-			
-		gDeferredAlphaProgram.mShaderFiles.clear();
-		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1");
-		gDeferredAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-
-		success = gDeferredAlphaProgram.createShader(NULL, NULL);
-
-		// Hack
-		gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
-		gDeferredAlphaProgram.mFeatures.hasLighting = true;
-	}
+		gDeferredAlphaProgram.mFeatures.hasSrgb = true;
+		gDeferredAlphaProgram.mFeatures.encodesNormal = true;
+		gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
+        gDeferredAlphaProgram.mFeatures.hasGamma = true;
+        gDeferredAlphaProgram.mFeatures.hasTransport = true;
+        gDeferredAlphaProgram.mFeatures.hasShadows = use_sun_shadow;
+
+        if (mShaderLevel[SHADER_DEFERRED] < 1)
+        {
+            gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+        }
+        else
+        { //shave off some texture units for shadow maps
+            gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
+        }
+            
+        gDeferredAlphaProgram.mShaderFiles.clear();
+        gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+        gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+        gDeferredAlphaProgram.clearPermutations();
+        gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
+        gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1");
+        if (use_sun_shadow)
+        {
+            gDeferredAlphaProgram.addPermutation("HAS_SHADOW", "1");
+        }
+
+        if (ambient_kill)
+        {
+            gDeferredAlphaProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredAlphaProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
+
+        gDeferredAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        success = gDeferredAlphaProgram.createShader(NULL, NULL);
+        llassert(success);
+
+        // Hack
+        gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
+        gDeferredAlphaProgram.mFeatures.hasLighting = true;
+    }
 
-	if (success)
-	{
-		gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Shader";
+    if (success)
+    {
+        gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Impostor Shader";
 
+// Begin Hack
 		gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false;
 		gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false;
+
+        gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true;
 		gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true;
-		gDeferredAlphaImpostorProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
-		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
-		{
-			gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
-		}
-		else
-		{ //shave off some texture units for shadow maps
-			gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
-		}
+        gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true;
+        gDeferredAlphaImpostorProgram.mFeatures.hasShadows = use_sun_shadow;
 
-		gDeferredAlphaImpostorProgram.mShaderFiles.clear();
-		gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1");
-		gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1");
+        if (mShaderLevel[SHADER_DEFERRED] < 1)
+        {
+            gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+        }
+        else
+        { //shave off some texture units for shadow maps
+            gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
+        }
 
-		gDeferredAlphaImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredAlphaImpostorProgram.mShaderFiles.clear();
+        gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+        gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
 
-		success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL);
+        gDeferredAlphaImpostorProgram.clearPermutations();
+        gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1");
+        gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1");
+        gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1");
 
-		// Hack
-		gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = true;
-		gDeferredAlphaImpostorProgram.mFeatures.hasLighting = true;
-	}
+        if (use_sun_shadow)
+        {
+            gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", "1");
+        }
+
+        gDeferredAlphaImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL);
+        llassert(success);
+
+// End Hack
+        gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = true;
+        gDeferredAlphaImpostorProgram.mFeatures.hasLighting = true;
+    }
 
 	if (success)
 	{
@@ -1610,7 +1996,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.mFeatures.hasLighting = false;
 		gDeferredAlphaWaterProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
-		if (mVertexShaderLevel[SHADER_DEFERRED] < 1)
+		gDeferredAlphaWaterProgram.mFeatures.hasWaterFog = true;
+		gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true;
+		gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true;
+		gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true;
+		gDeferredAlphaWaterProgram.mFeatures.hasGamma = true;
+		gDeferredAlphaWaterProgram.mFeatures.hasTransport = true;
+		gDeferredAlphaWaterProgram.mFeatures.hasShadows = use_sun_shadow;
+
+		if (mShaderLevel[SHADER_DEFERRED] < 1)
 		{
 			gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		}
@@ -1622,13 +2017,34 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAlphaWaterProgram.mShaderFiles.clear();
 		gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+		gDeferredAlphaWaterProgram.clearPermutations();
 		gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1");
 		gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1");
-		gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1");
-		gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAlphaWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1");
+		if (use_sun_shadow)
+		{
+			gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", "1");
+		}
+
+        if (ambient_kill)
+        {
+            gDeferredAlphaWaterProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredAlphaWaterProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredAlphaWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
+        gDeferredAlphaWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAlphaWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 
 		// Hack
 		gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = true;
@@ -1642,11 +2058,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarEyesProgram.mFeatures.hasGamma = true;
 		gDeferredAvatarEyesProgram.mFeatures.hasTransport = true;
 		gDeferredAvatarEyesProgram.mFeatures.disableTextureIndex = true;
+		gDeferredAvatarEyesProgram.mFeatures.hasSrgb = true;
+		gDeferredAvatarEyesProgram.mFeatures.encodesNormal = true;
+		gDeferredAvatarEyesProgram.mFeatures.hasShadows = true;
+
 		gDeferredAvatarEyesProgram.mShaderFiles.clear();
 		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/avatarEyesV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarEyesProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAvatarEyesProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarEyesProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarEyesProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1655,12 +2076,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightProgram.mFeatures.hasTransport = true;
+		gDeferredFullbrightProgram.mFeatures.hasSrgb = true;		
 		gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightProgram.mShaderFiles.clear();
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1669,13 +2092,15 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasTransport = true;
+		gDeferredFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;		
 		gDeferredFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1");
-		gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1684,14 +2109,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightWaterProgram.mFeatures.hasTransport = true;
+		gDeferredFullbrightWaterProgram.mFeatures.hasWaterFog = true;
+		gDeferredFullbrightWaterProgram.mFeatures.hasSrgb = true;
 		gDeferredFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1");
 		success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1700,59 +2128,71 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasTransport = true;
+		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasWaterFog = true;
+		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.hasSrgb = true;
 		gDeferredFullbrightAlphaMaskWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.clear();
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightAlphaMaskWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1");
 		gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1");
 		success = gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredFullbrightShinyProgram.mName = "Deferred FullbrightShiny Shader";
 		gDeferredFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredFullbrightShinyProgram.mFeatures.hasAtmospherics = true;
 		gDeferredFullbrightShinyProgram.mFeatures.hasGamma = true;
 		gDeferredFullbrightShinyProgram.mFeatures.hasTransport = true;
+		gDeferredFullbrightShinyProgram.mFeatures.hasSrgb = true;
 		gDeferredFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels-1;
 		gDeferredFullbrightShinyProgram.mShaderFiles.clear();
 		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredSkinnedFullbrightProgram.mName = "Skinned Fullbright Shader";
 		gDeferredSkinnedFullbrightProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredSkinnedFullbrightProgram.mFeatures.hasAtmospherics = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.hasTransport = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true;
 		gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true;
+		gDeferredSkinnedFullbrightProgram.mFeatures.hasSrgb = true;
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.clear();
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gDeferredSkinnedFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredSkinnedFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader";
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasAtmospherics = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasGamma = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
 		gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true;
+        gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasSrgb = true;
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear();
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1765,8 +2205,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredEmissiveProgram.mShaderFiles.clear();
 		gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredEmissiveProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1776,11 +2217,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWaterProgram.mFeatures.calculatesAtmospherics = true;
 		gDeferredWaterProgram.mFeatures.hasGamma = true;
 		gDeferredWaterProgram.mFeatures.hasTransport = true;
+		gDeferredWaterProgram.mFeatures.encodesNormal = true;
+        gDeferredWaterProgram.mFeatures.hasSrgb = true;
+
 		gDeferredWaterProgram.mShaderFiles.clear();
 		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+		gDeferredWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gDeferredWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1788,23 +2234,54 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		// load water shader
 		gDeferredUnderWaterProgram.mName = "Deferred Under Water Shader";
 		gDeferredUnderWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredUnderWaterProgram.mFeatures.hasWaterFog = true;
 		gDeferredUnderWaterProgram.mFeatures.hasGamma = true;
 		gDeferredUnderWaterProgram.mFeatures.hasTransport = true;
+		gDeferredUnderWaterProgram.mFeatures.hasSrgb = true;
+		gDeferredUnderWaterProgram.mFeatures.encodesNormal = true;
+		//gDeferredUnderWaterProgram.mFeatures.hasShadows = true;
+
 		gDeferredUnderWaterProgram.mShaderFiles.clear();
 		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredUnderWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        gDeferredUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gDeferredUnderWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredSoftenProgram.mName = "Deferred Soften Shader";
 		gDeferredSoftenProgram.mShaderFiles.clear();
+		gDeferredSoftenProgram.mFeatures.hasSrgb = true;
+		gDeferredSoftenProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredSoftenProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSoftenProgram.mFeatures.hasTransport = true;
+		gDeferredSoftenProgram.mFeatures.hasGamma = true;
+		gDeferredSoftenProgram.mFeatures.isDeferred = true;
+		gDeferredSoftenProgram.mFeatures.hasShadows = use_sun_shadow;
+
+        gDeferredSoftenProgram.clearPermutations();
 		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
 
-		gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredSoftenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+        if (ambient_kill)
+        {
+            gDeferredSoftenProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredSoftenProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredSoftenProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
@@ -1812,6 +2289,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		}
 				
 		success = gDeferredSoftenProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1821,9 +2299,33 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredSoftenWaterProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
 
-		gDeferredSoftenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredSoftenWaterProgram.clearPermutations();
+		gDeferredSoftenWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredSoftenWaterProgram.addPermutation("WATER_FOG", "1");
 		gDeferredSoftenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		gDeferredSoftenWaterProgram.mFeatures.hasWaterFog = true;
+		gDeferredSoftenWaterProgram.mFeatures.hasSrgb = true;
+		gDeferredSoftenWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredSoftenWaterProgram.mFeatures.hasAtmospherics = true;
+		gDeferredSoftenWaterProgram.mFeatures.hasTransport = true;
+		gDeferredSoftenWaterProgram.mFeatures.hasGamma = true;
+        gDeferredSoftenWaterProgram.mFeatures.isDeferred = true;
+        gDeferredSoftenWaterProgram.mFeatures.hasShadows = use_sun_shadow;
+
+        if (ambient_kill)
+        {
+            gDeferredSoftenWaterProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredSoftenWaterProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredSoftenWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
 
 		if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
 		{ //if using SSAO, take screen space light map into account as if shadows are enabled
@@ -1831,55 +2333,98 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		}
 
 		success = gDeferredSoftenWaterProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredShadowProgram.mName = "Deferred Shadow Shader";
+		gDeferredShadowProgram.mFeatures.isDeferred = true;
+		gDeferredShadowProgram.mFeatures.hasShadows = true;
 		gDeferredShadowProgram.mShaderFiles.clear();
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
+		gDeferredShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
 		success = gDeferredShadowProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader";
+		gDeferredShadowCubeProgram.mFeatures.isDeferred = true;
+		gDeferredShadowCubeProgram.mFeatures.hasShadows = true;
 		gDeferredShadowCubeProgram.mShaderFiles.clear();
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowCubeV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowCubeProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredShadowCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredShadowCubeProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
+		gDeferredShadowCubeProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredShadowCubeProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
+	{
+		gDeferredShadowFullbrightAlphaMaskProgram.mName = "Deferred Shadow Fullbright Alpha Mask Shader";
+		gDeferredShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+
+		gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.clear();
+		gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+        gDeferredShadowFullbrightAlphaMaskProgram.clearPermutations();
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
+        gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
+		gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+		success = gDeferredShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL);
+		llassert(success);
+	}
+    
+    if (success)
 	{
 		gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";
 		gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.clear();
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredShadowAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
+		gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader";
 		gDeferredAvatarShadowProgram.mFeatures.hasSkinning = true;
+
 		gDeferredAvatarShadowProgram.mShaderFiles.clear();
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredAvatarShadowProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
+		gDeferredAvatarShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
-    if (success)
+	if (success)
 	{
 		gDeferredAvatarAlphaShadowProgram.mName = "Deferred Avatar Alpha Shadow Shader";
 		gDeferredAvatarAlphaShadowProgram.mFeatures.hasSkinning = true;
@@ -1887,8 +2432,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAvatarAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaShadowProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
     if (success)
@@ -1899,23 +2445,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAvatarAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarAlphaMaskShadowProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader";
 		gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true;
+
 		gDeferredAttachmentShadowProgram.mShaderFiles.clear();
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		if (gGLManager.mHasDepthClamp)
+		{
+			gDeferredAttachmentShadowProgram.addPermutation("DEPTH_CLAMP", "1");
+		}
+		gDeferredAttachmentShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
-    
-    if (success)
+
+	if (success)
 	{
 		gDeferredAttachmentAlphaShadowProgram.mName = "Deferred Attachment Alpha Shadow Shader";
 		gDeferredAttachmentAlphaShadowProgram.mFeatures.hasObjectSkinning = true;
@@ -1923,8 +2475,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAttachmentAlphaShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAttachmentAlphaShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAttachmentAlphaShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentAlphaShadowProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
     if (success)
@@ -1935,29 +2488,70 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaShadowV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAttachmentAlphaMaskShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentAlphaMaskShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gDeferredAttachmentAlphaMaskShadowProgram.addPermutation("DEPTH_CLAMP", gGLManager.mHasDepthClamp ? "1" : "0");
-		gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAttachmentAlphaMaskShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAttachmentAlphaMaskShadowProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
-		gTerrainProgram.mName = "Deferred Terrain Shader";
+		gDeferredTerrainProgram.mName = "Deferred Terrain Shader";
+		gDeferredTerrainProgram.mFeatures.encodesNormal = true;
+		gDeferredTerrainProgram.mFeatures.hasSrgb = true;
+		gDeferredTerrainProgram.mFeatures.calculatesLighting = false;
+		gDeferredTerrainProgram.mFeatures.hasLighting = false;
+		gDeferredTerrainProgram.mFeatures.isAlphaLighting = true;
+		gDeferredTerrainProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+		gDeferredTerrainProgram.mFeatures.hasWaterFog = true;
+		gDeferredTerrainProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredTerrainProgram.mFeatures.hasAtmospherics = true;
+		gDeferredTerrainProgram.mFeatures.hasGamma = true;
+		gDeferredTerrainProgram.mFeatures.hasTransport = true;
+
 		gDeferredTerrainProgram.mShaderFiles.clear();
 		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
-		success = gDeferredTerrainProgram.createShader(NULL, NULL);
+		gDeferredTerrainProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        success = gDeferredTerrainProgram.createShader(NULL, NULL);
+		llassert(success);
+	}
+
+	if (success)
+	{
+		gDeferredTerrainWaterProgram.mName = "Deferred Terrain Underwater Shader";
+		gDeferredTerrainWaterProgram.mFeatures.encodesNormal = true;
+		gDeferredTerrainWaterProgram.mFeatures.hasSrgb = true;
+		gDeferredTerrainWaterProgram.mFeatures.calculatesLighting = false;
+		gDeferredTerrainWaterProgram.mFeatures.hasLighting = false;
+		gDeferredTerrainWaterProgram.mFeatures.isAlphaLighting = true;
+		gDeferredTerrainWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+		gDeferredTerrainWaterProgram.mFeatures.hasWaterFog = true;
+		gDeferredTerrainWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredTerrainWaterProgram.mFeatures.hasAtmospherics = true;
+		gDeferredTerrainWaterProgram.mFeatures.hasGamma = true;
+		gDeferredTerrainWaterProgram.mFeatures.hasTransport = true;
+
+		gDeferredTerrainWaterProgram.mShaderFiles.clear();
+		gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredTerrainWaterProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredTerrainWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+		gDeferredTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+		gDeferredTerrainWaterProgram.addPermutation("WATER_FOG", "1");
+		success = gDeferredTerrainWaterProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredAvatarProgram.mName = "Avatar Shader";
 		gDeferredAvatarProgram.mFeatures.hasSkinning = true;
+		gDeferredAvatarProgram.mFeatures.encodesNormal = true;
 		gDeferredAvatarProgram.mShaderFiles.clear();
 		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredAvatarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredAvatarProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
@@ -1968,15 +2562,45 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false;
 		gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;
 		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasSrgb = true;
+		gDeferredAvatarAlphaProgram.mFeatures.encodesNormal = true;
+		gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasTransport = true;
+        gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;
+        gDeferredAvatarAlphaProgram.mFeatures.isDeferred = true;
+		gDeferredAvatarAlphaProgram.mFeatures.hasShadows = true;
+
 		gDeferredAvatarAlphaProgram.mShaderFiles.clear();
-		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
-		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+        gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+		gDeferredAvatarAlphaProgram.clearPermutations();
 		gDeferredAvatarAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
 		gDeferredAvatarAlphaProgram.addPermutation("IS_AVATAR_SKIN", "1");
-		gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", mVertexShaderLevel[SHADER_DEFERRED] > 1 ? "1" : "0");
-		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		if (use_sun_shadow)
+		{
+			gDeferredAvatarAlphaProgram.addPermutation("HAS_SHADOW", "1");
+		}
+
+        if (ambient_kill)
+        {
+            gDeferredAvatarAlphaProgram.addPermutation("AMBIENT_KILL", "1");
+        }
+
+        if (sunlight_kill)
+        {
+            gDeferredAvatarAlphaProgram.addPermutation("SUNLIGHT_KILL", "1");
+        }
+
+        if (local_light_kill)
+        {
+            gDeferredAvatarAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
+        }
+		gDeferredAvatarAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 
 		success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL);
+		llassert(success);
 
 		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;
 		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
@@ -1985,95 +2609,160 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 	if (success)
 	{
 		gDeferredPostGammaCorrectProgram.mName = "Deferred Gamma Correction Post Process";
+		gDeferredPostGammaCorrectProgram.mFeatures.hasSrgb = true;
+		gDeferredPostGammaCorrectProgram.mFeatures.isDeferred = true;
 		gDeferredPostGammaCorrectProgram.mShaderFiles.clear();
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostGammaCorrectProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredGammaCorrect.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredPostGammaCorrectProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+        gDeferredPostGammaCorrectProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostGammaCorrectProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gFXAAProgram.mName = "FXAA Shader";
+		gFXAAProgram.mFeatures.isDeferred = true;
 		gFXAAProgram.mShaderFiles.clear();
 		gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
 		gFXAAProgram.mShaderFiles.push_back(make_pair("deferred/fxaaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gFXAAProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gFXAAProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredPostProgram.mName = "Deferred Post Shader";
+		gFXAAProgram.mFeatures.isDeferred = true;
 		gDeferredPostProgram.mShaderFiles.clear();
 		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredPostProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredCoFProgram.mName = "Deferred CoF Shader";
 		gDeferredCoFProgram.mShaderFiles.clear();
+		gDeferredCoFProgram.mFeatures.isDeferred = true;
 		gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredCoFProgram.mShaderFiles.push_back(make_pair("deferred/cofF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredCoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredCoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredCoFProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader";
+		gDeferredDoFCombineProgram.mFeatures.isDeferred = true;
 		gDeferredDoFCombineProgram.mShaderFiles.clear();
 		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredDoFCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredDoFCombineProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredDoFCombineProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
+		gDeferredPostNoDoFProgram.mFeatures.isDeferred = true;
 		gDeferredPostNoDoFProgram.mShaderFiles.clear();
 		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredPostNoDoFProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader";
-		//gWLSkyProgram.mFeatures.hasGamma = true;
 		gDeferredWLSkyProgram.mShaderFiles.clear();
+		gDeferredWLSkyProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredWLSkyProgram.mFeatures.hasTransport = true;
+		gDeferredWLSkyProgram.mFeatures.hasGamma = true;
+		gDeferredWLSkyProgram.mFeatures.hasSrgb = true;
+
 		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+
 		success = gDeferredWLSkyProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
 	{
 		gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program";
 		gDeferredWLCloudProgram.mShaderFiles.clear();
+		gDeferredWLCloudProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredWLCloudProgram.mFeatures.hasTransport = true;
+        gDeferredWLCloudProgram.mFeatures.hasGamma = true;
+        gDeferredWLCloudProgram.mFeatures.hasSrgb = true;
+        
 		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gDeferredWLCloudProgram.createShader(NULL, NULL);
+		llassert(success);
 	}
 
 	if (success)
+	{
+	    gDeferredWLSunProgram.mName = "Deferred Windlight Sun Program";
+        gDeferredWLSunProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredWLSunProgram.mFeatures.hasTransport = true;
+        gDeferredWLSunProgram.mFeatures.hasGamma = true;
+        gDeferredWLSunProgram.mFeatures.hasAtmospherics = true;
+        gDeferredWLSunProgram.mFeatures.isFullbright = true;
+        gDeferredWLSunProgram.mFeatures.disableTextureIndex = true;
+        gDeferredWLSunProgram.mFeatures.hasSrgb = true;
+        gDeferredWLSunProgram.mShaderFiles.clear();
+        gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
+        gDeferredWLSunProgram.mShaderFiles.push_back(make_pair("deferred/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gDeferredWLSunProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        gDeferredWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        success = gDeferredWLSunProgram.createShader(NULL, NULL);
+        llassert(success);
+    }
+
+    if (success)
+    {
+        gDeferredWLMoonProgram.mName = "Deferred Windlight Moon Program";
+        gDeferredWLMoonProgram.mFeatures.calculatesAtmospherics = true;
+        gDeferredWLMoonProgram.mFeatures.hasTransport = true;
+        gDeferredWLMoonProgram.mFeatures.hasGamma = true;
+        gDeferredWLMoonProgram.mFeatures.hasAtmospherics = true;
+        gDeferredWLMoonProgram.mFeatures.hasSrgb = true;
+        gDeferredWLMoonProgram.mFeatures.isFullbright = true;
+        gDeferredWLMoonProgram.mFeatures.disableTextureIndex = true;
+        
+        gDeferredWLMoonProgram.mShaderFiles.clear();
+        gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonV.glsl", GL_VERTEX_SHADER_ARB));
+        gDeferredWLMoonProgram.mShaderFiles.push_back(make_pair("deferred/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gDeferredWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+        gDeferredWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+ 	 	success = gDeferredWLMoonProgram.createShader(NULL, NULL);
+        llassert(success);
+ 	}
+
+ 	if (success)
 	{
 		gDeferredStarProgram.mName = "Deferred Star Program";
 		gDeferredStarProgram.mShaderFiles.clear();
 		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB));
 		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gDeferredStarProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gDeferredStarProgram.createShader(NULL, NULL);
+        llassert(success);
 	}
 
 	if (success)
@@ -2082,7 +2771,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gNormalMapGenProgram.mShaderFiles.clear();
 		gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenV.glsl", GL_VERTEX_SHADER_ARB));
 		gNormalMapGenProgram.mShaderFiles.push_back(make_pair("deferred/normgenF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gNormalMapGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		gNormalMapGenProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
 		gNormalMapGenProgram.mShaderGroup = LLGLSLShader::SG_SKY;
 		success = gNormalMapGenProgram.createShader(NULL, NULL);
 	}
@@ -2094,7 +2783,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 {
 	BOOL success = TRUE;
 	
-	if (mVertexShaderLevel[SHADER_OBJECT] == 0)
+	if (mShaderLevel[SHADER_OBJECT] == 0)
 	{
 		gObjectShinyProgram.unload();
 		gObjectFullbrightShinyProgram.unload();
@@ -2155,12 +2844,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true;
 		gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true;
 		gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true;
+        gObjectSimpleNonIndexedProgram.mFeatures.hasAlphaMask = true; // Fix for MAINT-8836
 		gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true;
-		gObjectSimpleNonIndexedProgram.mFeatures.hasAlphaMask = true;
 		gObjectSimpleNonIndexedProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL);
 	}
 	
@@ -2176,7 +2865,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedTexGenProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedTexGenProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleNonIndexedTexGenProgram.createShader(NULL, NULL);
 	}
 	
@@ -2193,7 +2882,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2210,7 +2899,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.clear();
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleTexGenV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleNonIndexedTexGenWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleNonIndexedTexGenWaterProgram.createShader(NULL, NULL);
 	}
@@ -2228,7 +2917,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL);
 	}
 	
@@ -2245,7 +2934,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNonIndexedV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2263,7 +2952,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNoColorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectAlphaMaskNoColorProgram.createShader(NULL, NULL);
 	}
 	
@@ -2280,7 +2969,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.clear();
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectAlphaMaskNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectAlphaMaskNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectAlphaMaskNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectAlphaMaskNoColorWaterProgram.createShader(NULL, NULL);
 	}
@@ -2298,7 +2987,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gTreeProgram.mShaderFiles.clear();
 		gTreeProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gTreeProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTreeProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gTreeProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gTreeProgram.createShader(NULL, NULL);
 	}
 	
@@ -2315,7 +3004,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gTreeWaterProgram.mShaderFiles.clear();
 		gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/treeV.glsl", GL_VERTEX_SHADER_ARB));
 		gTreeWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTreeWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gTreeWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gTreeWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gTreeWaterProgram.createShader(NULL, NULL);
 	}
@@ -2331,7 +3020,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.clear();
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2343,10 +3032,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true;		
 		gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
+		gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasSrgb = true;
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2359,10 +3049,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveNonIndexedProgram.mFeatures.hasTransport = true;
 		gObjectEmissiveNonIndexedProgram.mFeatures.isFullbright = true;
 		gObjectEmissiveNonIndexedProgram.mFeatures.disableTextureIndex = true;
+		gObjectEmissiveNonIndexedProgram.mFeatures.hasSrgb = true;
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.clear();
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2377,7 +3068,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2389,11 +3080,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNoColorProgram.mFeatures.hasGamma = true;
 		gObjectFullbrightNoColorProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightNoColorProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightNoColorProgram.mFeatures.hasSrgb = true;
 		gObjectFullbrightNoColorProgram.mFeatures.disableTextureIndex = true;
 		gObjectFullbrightNoColorProgram.mShaderFiles.clear();
 		gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNoColorProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNoColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightNoColorProgram.createShader(NULL, NULL);
 	}
 
@@ -2408,7 +3100,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightNoColorV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightNoColorWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightNoColorWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightNoColorWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightNoColorWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightNoColorWaterProgram.createShader(NULL, NULL);
 	}
@@ -2425,7 +3117,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyNonIndexedProgram.mShaderFiles.clear();
 		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
-		gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2441,12 +3133,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
-		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
 	
-	if (success)
+    if (success)
 	{
 		gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader";
 		gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
@@ -2458,7 +3150,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL);
 	}
 
@@ -2475,7 +3167,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL);
 	}
@@ -2484,10 +3176,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 	{
 		gImpostorProgram.mName = "Impostor Shader";
 		gImpostorProgram.mFeatures.disableTextureIndex = true;
+		gImpostorProgram.mFeatures.hasSrgb = true;
 		gImpostorProgram.mShaderFiles.clear();
 		gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB));
 		gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gImpostorProgram.createShader(NULL, NULL);
 	}
 
@@ -2504,7 +3197,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectPreviewProgram.mShaderFiles.clear();
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectPreviewProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectPreviewProgram.createShader(NULL, NULL);
 		gObjectPreviewProgram.mFeatures.hasLighting = true;
 	}
@@ -2521,7 +3214,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleProgram.mShaderFiles.clear();
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleProgram.createShader(NULL, NULL);
 	}
 
@@ -2541,7 +3234,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleImpostorProgram.mShaderFiles.clear();
 		gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		
 		success = gObjectSimpleImpostorProgram.createShader(NULL, NULL);
 	}
@@ -2558,7 +3251,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterProgram.mShaderFiles.clear();
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleWaterProgram.createShader(NULL, NULL);
 	}
@@ -2572,10 +3265,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectBumpProgram.mFeatures.hasAtmospherics = true;
 		gObjectBumpProgram.mFeatures.hasLighting = true;
 		gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/
+		gObjectBumpProgram.mFeatures.encodesNormal = true;
 		gObjectBumpProgram.mShaderFiles.clear();
 		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectBumpProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectBumpProgram.createShader(NULL, NULL);
 		if (success)
 		{ //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1
@@ -2600,7 +3294,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.clear();
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
@@ -2617,7 +3311,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear();
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL);
 	}
@@ -2629,11 +3323,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightProgram.mFeatures.hasGamma = true;
 		gObjectFullbrightProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightProgram.mFeatures.isFullbright = true;
+		gObjectFullbrightProgram.mFeatures.hasSrgb = true;
 		gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightProgram.mShaderFiles.clear();
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightProgram.createShader(NULL, NULL);
 	}
 
@@ -2648,7 +3343,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightWaterProgram.createShader(NULL, NULL);
 	}
@@ -2660,11 +3355,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveProgram.mFeatures.hasGamma = true;
 		gObjectEmissiveProgram.mFeatures.hasTransport = true;
 		gObjectEmissiveProgram.mFeatures.isFullbright = true;
+		gObjectEmissiveProgram.mFeatures.hasSrgb = true;
 		gObjectEmissiveProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectEmissiveProgram.mShaderFiles.clear();
 		gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectEmissiveProgram.createShader(NULL, NULL);
 	}
 
@@ -2679,7 +3375,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectEmissiveWaterProgram.mShaderFiles.clear();
 		gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectEmissiveWaterProgram.createShader(NULL, NULL);
 	}
@@ -2692,11 +3388,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightAlphaMaskProgram.mFeatures.hasTransport = true;
 		gObjectFullbrightAlphaMaskProgram.mFeatures.isFullbright = true;
 		gObjectFullbrightAlphaMaskProgram.mFeatures.hasAlphaMask = true;
+		gObjectFullbrightAlphaMaskProgram.mFeatures.hasSrgb = true;
 		gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0;
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear();
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
@@ -2712,7 +3409,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear();
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL);
 	}
@@ -2729,7 +3426,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyProgram.mShaderFiles.clear();
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		
-		gObjectShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectShinyProgram.createShader(NULL, NULL);
 	}
 
@@ -2745,7 +3442,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectShinyWaterProgram.mShaderFiles.clear();
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
-		gObjectShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectShinyWaterProgram.createShader(NULL, NULL);
 	}
@@ -2762,7 +3459,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		success = gObjectFullbrightShinyProgram.createShader(NULL, NULL);
 	}
 
@@ -2779,12 +3476,12 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
 		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+		gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 		gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
 		success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
 	}
 
-	if (mVertexShaderLevel[SHADER_AVATAR] > 0)
+	if (mShaderLevel[SHADER_AVATAR] > 0)
 	{ //load hardware skinned attachment shaders
 		if (success)
 		{
@@ -2800,7 +3497,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectSimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL);
 		}
 
@@ -2814,10 +3511,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectFullbrightProgram.mFeatures.hasAlphaMask = true;			
 			gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true;
+			gSkinnedObjectFullbrightProgram.mFeatures.hasSrgb = true;
 			gSkinnedObjectFullbrightProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL);
 		}
 
@@ -2830,10 +3528,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectEmissiveProgram.mFeatures.isFullbright = true;
 			gSkinnedObjectEmissiveProgram.mFeatures.hasObjectSkinning = true;
 			gSkinnedObjectEmissiveProgram.mFeatures.disableTextureIndex = true;
+            gSkinnedObjectEmissiveProgram.mFeatures.hasSrgb = true;
 			gSkinnedObjectEmissiveProgram.mShaderFiles.clear();
 			gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectEmissiveProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL);
 		}
 
@@ -2850,7 +3549,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectEmissiveWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -2868,7 +3567,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL);
 		}
 
@@ -2886,7 +3585,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectShinySimpleProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL);
 		}
 
@@ -2907,7 +3606,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -2926,7 +3625,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -2946,7 +3645,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
 		}
 
@@ -2966,14 +3665,14 @@ BOOL LLViewerShaderMgr::loadShadersObject()
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear();
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
 			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
-			gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
+			gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
 			success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL);
 		}
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_OBJECT] = 0;
+		mShaderLevel[SHADER_OBJECT] = 0;
 		return FALSE;
 	}
 	
@@ -2984,7 +3683,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_AVATAR] == 0)
+	if (mShaderLevel[SHADER_AVATAR] == 0)
 	{
 		gAvatarProgram.unload();
 		gAvatarWaterProgram.unload();
@@ -3007,7 +3706,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarProgram.mShaderFiles.clear();
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarProgram.createShader(NULL, NULL);
 			
 		if (success)
@@ -3025,15 +3724,15 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));
 			gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
 			// Note: no cloth under water:
-			gAvatarWaterProgram.mShaderLevel = llmin(mVertexShaderLevel[SHADER_AVATAR], 1);	
+			gAvatarWaterProgram.mShaderLevel = llmin(mShaderLevel[SHADER_AVATAR], 1);	
 			gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;				
 			success = gAvatarWaterProgram.createShader(NULL, NULL);
 		}
 
 		/// Keep track of avatar levels
-		if (gAvatarProgram.mShaderLevel != mVertexShaderLevel[SHADER_AVATAR])
+		if (gAvatarProgram.mShaderLevel != mShaderLevel[SHADER_AVATAR])
 		{
-			mMaxAvatarShaderLevel = mVertexShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel;
+			mMaxAvatarShaderLevel = mShaderLevel[SHADER_AVATAR] = gAvatarProgram.mShaderLevel;
 		}
 	}
 
@@ -3045,7 +3744,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarPickProgram.mShaderFiles.clear();
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarPickProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarPickProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarPickProgram.createShader(NULL, NULL);
 	}
 
@@ -3063,13 +3762,13 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()
 		gAvatarEyeballProgram.mShaderFiles.clear();
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB));
 		gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAvatarEyeballProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR];
+		gAvatarEyeballProgram.mShaderLevel = mShaderLevel[SHADER_AVATAR];
 		success = gAvatarEyeballProgram.createShader(NULL, NULL);
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_AVATAR] = 0;
+		mShaderLevel[SHADER_AVATAR] = 0;
 		mMaxAvatarShaderLevel = 0;
 		return FALSE;
 	}
@@ -3081,7 +3780,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 {
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_INTERFACE] == 0)
+	if (mShaderLevel[SHADER_INTERFACE] == 0)
 	{
 		gHighlightProgram.unload();
 		return TRUE;
@@ -3093,7 +3792,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightProgram.mShaderFiles.clear();
 		gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gHighlightProgram.createShader(NULL, NULL);
 	}
 
@@ -3103,7 +3802,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightNormalProgram.mShaderFiles.clear();
 		gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightNormV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightNormalProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightNormalProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gHighlightNormalProgram.createShader(NULL, NULL);
 	}
 
@@ -3113,7 +3812,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gHighlightSpecularProgram.mShaderFiles.clear();
 		gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightSpecV.glsl", GL_VERTEX_SHADER_ARB));
 		gHighlightSpecularProgram.mShaderFiles.push_back(make_pair("interface/highlightF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gHighlightSpecularProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];		
+		gHighlightSpecularProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gHighlightSpecularProgram.createShader(NULL, NULL);
 	}
 
@@ -3123,7 +3822,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gUIProgram.mShaderFiles.clear();
 		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB));
 		gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gUIProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gUIProgram.createShader(NULL, NULL);
 	}
 
@@ -3133,7 +3832,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gPathfindingProgram.mShaderFiles.clear();
 		gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingV.glsl", GL_VERTEX_SHADER_ARB));
 		gPathfindingProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gPathfindingProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gPathfindingProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gPathfindingProgram.createShader(NULL, NULL);
 	}
 
@@ -3143,7 +3842,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gPathfindingNoNormalsProgram.mShaderFiles.clear();
 		gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingNoNormalV.glsl", GL_VERTEX_SHADER_ARB));
 		gPathfindingNoNormalsProgram.mShaderFiles.push_back(make_pair("interface/pathfindingF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gPathfindingNoNormalsProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gPathfindingNoNormalsProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gPathfindingNoNormalsProgram.createShader(NULL, NULL);
 	}
 
@@ -3153,7 +3852,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gCustomAlphaProgram.mShaderFiles.clear();
 		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB));
 		gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gCustomAlphaProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gCustomAlphaProgram.createShader(NULL, NULL);
 	}
 
@@ -3163,7 +3862,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gSplatTextureRectProgram.mShaderFiles.clear();
 		gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER_ARB));
 		gSplatTextureRectProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gSplatTextureRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gSplatTextureRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gSplatTextureRectProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3179,7 +3878,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gGlowCombineProgram.mShaderFiles.clear();
 		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gGlowCombineProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gGlowCombineProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3196,7 +3895,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gGlowCombineFXAAProgram.mShaderFiles.clear();
 		gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAV.glsl", GL_VERTEX_SHADER_ARB));
 		gGlowCombineFXAAProgram.mShaderFiles.push_back(make_pair("interface/glowcombineFXAAF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gGlowCombineFXAAProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gGlowCombineFXAAProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gGlowCombineFXAAProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3214,7 +3913,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gTwoTextureAddProgram.mShaderFiles.clear();
 		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB));
 		gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gTwoTextureAddProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gTwoTextureAddProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3231,7 +3930,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gTwoTextureCompareProgram.mShaderFiles.clear();
 		gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB));
 		gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gTwoTextureCompareProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gTwoTextureCompareProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gTwoTextureCompareProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3248,7 +3947,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOneTextureFilterProgram.mShaderFiles.clear();
 		gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB));
 		gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOneTextureFilterProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOneTextureFilterProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3264,7 +3963,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOneTextureNoColorProgram.mShaderFiles.clear();
 		gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB));
 		gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOneTextureNoColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOneTextureNoColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOneTextureNoColorProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3279,7 +3978,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gSolidColorProgram.mShaderFiles.clear();
 		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB));
 		gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gSolidColorProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gSolidColorProgram.createShader(NULL, NULL);
 		if (success)
 		{
@@ -3295,7 +3994,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOcclusionProgram.mShaderFiles.clear();
 		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB));
 		gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOcclusionProgram.createShader(NULL, NULL);
 	}
 
@@ -3305,7 +4004,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gOcclusionCubeProgram.mShaderFiles.clear();
 		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionCubeV.glsl", GL_VERTEX_SHADER_ARB));
 		gOcclusionCubeProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gOcclusionCubeProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gOcclusionCubeProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gOcclusionCubeProgram.createShader(NULL, NULL);
 	}
 
@@ -3315,7 +4014,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDebugProgram.mShaderFiles.clear();
 		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB));
 		gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDebugProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDebugProgram.createShader(NULL, NULL);
 	}
 
@@ -3325,7 +4024,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gClipProgram.mShaderFiles.clear();
 		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipV.glsl", GL_VERTEX_SHADER_ARB));
 		gClipProgram.mShaderFiles.push_back(make_pair("interface/clipF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gClipProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gClipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gClipProgram.createShader(NULL, NULL);
 	}
 
@@ -3335,7 +4034,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDownsampleDepthProgram.mShaderFiles.clear();
 		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
 		gDownsampleDepthProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDownsampleDepthProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDownsampleDepthProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDownsampleDepthProgram.createShader(NULL, NULL);
 	}
 
@@ -3345,7 +4044,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gBenchmarkProgram.mShaderFiles.clear();
 		gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB));
 		gBenchmarkProgram.mShaderFiles.push_back(make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gBenchmarkProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gBenchmarkProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gBenchmarkProgram.createShader(NULL, NULL);
 	}
 
@@ -3355,17 +4054,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gDownsampleDepthRectProgram.mShaderFiles.clear();
 		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
 		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
-		success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
-	}
-
-	if (success)
-	{
-		gDownsampleDepthRectProgram.mName = "DownsampleDepthRect Shader";
-		gDownsampleDepthRectProgram.mShaderFiles.clear();
-		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthV.glsl", GL_VERTEX_SHADER_ARB));
-		gDownsampleDepthRectProgram.mShaderFiles.push_back(make_pair("interface/downsampleDepthRectF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gDownsampleDepthRectProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gDownsampleDepthRectProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gDownsampleDepthRectProgram.createShader(NULL, NULL);
 	}
 
@@ -3375,13 +4064,13 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
 		gAlphaMaskProgram.mShaderFiles.clear();
 		gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskV.glsl", GL_VERTEX_SHADER_ARB));
 		gAlphaMaskProgram.mShaderFiles.push_back(make_pair("interface/alphamaskF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE];
+		gAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
 		success = gAlphaMaskProgram.createShader(NULL, NULL);
 	}
 
 	if( !success )
 	{
-		mVertexShaderLevel[SHADER_INTERFACE] = 0;
+		mShaderLevel[SHADER_INTERFACE] = 0;
 		return FALSE;
 	}
 	
@@ -3392,36 +4081,80 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()
 {	
 	BOOL success = TRUE;
 
-	if (mVertexShaderLevel[SHADER_WINDLIGHT] < 2)
+	if (mShaderLevel[SHADER_WINDLIGHT] < 2)
 	{
 		gWLSkyProgram.unload();
 		gWLCloudProgram.unload();
+		gWLSunProgram.unload();
+		gWLMoonProgram.unload();
 		return TRUE;
 	}
 
-	if (success)
-	{
-		gWLSkyProgram.mName = "Windlight Sky Shader";
-		//gWLSkyProgram.mFeatures.hasGamma = true;
-		gWLSkyProgram.mShaderFiles.clear();
-		gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB));
-		gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
-		gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
-		success = gWLSkyProgram.createShader(NULL, NULL);
-	}
+    if (success)
+    {
+        gWLSkyProgram.mName = "Windlight Sky Shader";
+        gWLSkyProgram.mShaderFiles.clear();
+        gWLSkyProgram.mFeatures.calculatesAtmospherics = true;
+        gWLSkyProgram.mFeatures.hasTransport = true;
+        gWLSkyProgram.mFeatures.hasGamma = true;
+        gWLSkyProgram.mFeatures.hasSrgb = true;
+        gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyV.glsl", GL_VERTEX_SHADER_ARB));
+        gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gWLSkyProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
+        gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        success = gWLSkyProgram.createShader(NULL, NULL);
+    }
 
-	if (success)
-	{
-		gWLCloudProgram.mName = "Windlight Cloud Program";
-		//gWLCloudProgram.mFeatures.hasGamma = true;
-		gWLCloudProgram.mShaderFiles.clear();
-		gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
-		gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
-		gWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];
-		gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
-		success = gWLCloudProgram.createShader(NULL, NULL);
-	}
+    if (success)
+    {
+        gWLCloudProgram.mName = "Windlight Cloud Program";
+        gWLCloudProgram.mShaderFiles.clear();
+        gWLCloudProgram.mFeatures.calculatesAtmospherics = true;
+        gWLCloudProgram.mFeatures.hasTransport = true;
+        gWLCloudProgram.mFeatures.hasGamma = true;
+        gWLCloudProgram.mFeatures.hasSrgb = true;
+        gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsV.glsl", GL_VERTEX_SHADER_ARB));
+        gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gWLCloudProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
+        gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        success = gWLCloudProgram.createShader(NULL, NULL);
+    }
+
+    if (success)
+    {
+        gWLSunProgram.mName = "Windlight Sun Program";
+        gWLSunProgram.mShaderFiles.clear();
+        gWLSunProgram.mFeatures.calculatesAtmospherics = true;
+        gWLSunProgram.mFeatures.hasTransport = true;
+        gWLSunProgram.mFeatures.hasGamma = true;
+        gWLSunProgram.mFeatures.hasAtmospherics = true;
+        gWLSunProgram.mFeatures.isFullbright = true;
+        gWLSunProgram.mFeatures.disableTextureIndex = true;
+        gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscV.glsl", GL_VERTEX_SHADER_ARB));
+        gWLSunProgram.mShaderFiles.push_back(make_pair("windlight/sunDiscF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gWLSunProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
+        gWLSunProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        success = gWLSunProgram.createShader(NULL, NULL);
+    }
+
+    if (success)
+    {
+        gWLMoonProgram.mName = "Windlight Moon Program";
+        gWLMoonProgram.mShaderFiles.clear();
+        gWLMoonProgram.mFeatures.calculatesAtmospherics = true;
+        gWLMoonProgram.mFeatures.hasTransport = true;
+        gWLMoonProgram.mFeatures.hasGamma = true;
+        gWLMoonProgram.mFeatures.hasAtmospherics = true;
+        gWLMoonProgram.mFeatures.isFullbright = true;
+        gWLMoonProgram.mFeatures.disableTextureIndex = true;
+        gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonV.glsl", GL_VERTEX_SHADER_ARB));
+        gWLMoonProgram.mShaderFiles.push_back(make_pair("windlight/moonF.glsl", GL_FRAGMENT_SHADER_ARB));
+        gWLMoonProgram.mShaderLevel = mShaderLevel[SHADER_WINDLIGHT];
+        gWLMoonProgram.mShaderGroup = LLGLSLShader::SG_SKY;
+        success = gWLMoonProgram.createShader(NULL, NULL);
+    }
 
 	return success;
 }
@@ -3430,7 +4163,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 {
 	BOOL success = TRUE;
 	
-	if (mVertexShaderLevel[SHADER_TRANSFORM] < 1)
+	if (mShaderLevel[SHADER_TRANSFORM] < 1)
 	{
 		gTransformPositionProgram.unload();
 		gTransformTexCoordProgram.unload();
@@ -3442,10 +4175,10 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 
 	if (success)
 	{
-		gTransformPositionProgram.mName = "Position Transform Shader";
+        gTransformPositionProgram.mName = "Position Transform Shader";
 		gTransformPositionProgram.mShaderFiles.clear();
 		gTransformPositionProgram.mShaderFiles.push_back(make_pair("transform/positionV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformPositionProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformPositionProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"position_out",
@@ -3460,7 +4193,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformTexCoordProgram.mName = "TexCoord Transform Shader";
 		gTransformTexCoordProgram.mShaderFiles.clear();
 		gTransformTexCoordProgram.mShaderFiles.push_back(make_pair("transform/texcoordV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformTexCoordProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformTexCoordProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"texcoord_out",
@@ -3474,7 +4207,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformNormalProgram.mName = "Normal Transform Shader";
 		gTransformNormalProgram.mShaderFiles.clear();
 		gTransformNormalProgram.mShaderFiles.push_back(make_pair("transform/normalV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformNormalProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformNormalProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"normal_out",
@@ -3488,7 +4221,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformColorProgram.mName = "Color Transform Shader";
 		gTransformColorProgram.mShaderFiles.clear();
 		gTransformColorProgram.mShaderFiles.push_back(make_pair("transform/colorV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+		gTransformColorProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"color_out",
@@ -3502,7 +4235,7 @@ BOOL LLViewerShaderMgr::loadTransformShaders()
 		gTransformTangentProgram.mName = "Binormal Transform Shader";
 		gTransformTangentProgram.mShaderFiles.clear();
 		gTransformTangentProgram.mShaderFiles.push_back(make_pair("transform/binormalV.glsl", GL_VERTEX_SHADER_ARB));
-		gTransformTangentProgram.mShaderLevel = mVertexShaderLevel[SHADER_TRANSFORM];
+        gTransformTangentProgram.mShaderLevel = mShaderLevel[SHADER_TRANSFORM];
 
 		const char* varyings[] = {
 			"tangent_out",
@@ -3522,8 +4255,7 @@ std::string LLViewerShaderMgr::getShaderDirPrefix(void)
 
 void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader)
 {
-	LLWLParamManager::getInstance()->updateShaderUniforms(shader);
-	LLWaterParamManager::getInstance()->updateShaderUniforms(shader);
+    LLEnvironment::instance().updateShaderUniforms(shader);
 }
 
 LLViewerShaderMgr::shader_iter LLViewerShaderMgr::beginShaders() const
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 9edaa97e576806b60c63e8b3ac88b89fecf718f6..081221f15be877a6950b33c2d262cdbcf780c514 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -48,7 +48,7 @@ class LLViewerShaderMgr: public LLShaderMgr
 	void initAttribsAndUniforms(void);
 	void setShaders();
 	void unloadShaders();
-	S32 getVertexShaderLevel(S32 type);
+    S32  getShaderLevel(S32 type);
 	BOOL loadBasicShaders();
 	BOOL loadShadersEffects();
 	BOOL loadShadersDeferred();
@@ -60,7 +60,7 @@ class LLViewerShaderMgr: public LLShaderMgr
 	BOOL loadShadersWindLight();
 	BOOL loadTransformShaders();
 
-	std::vector<S32> mVertexShaderLevel;
+	std::vector<S32> mShaderLevel;
 	S32	mMaxAvatarShaderLevel;
 
 	enum EShaderClass
@@ -129,24 +129,6 @@ class LLViewerShaderMgr: public LLShaderMgr
 	/* virtual */ void updateShaderUniforms(LLGLSLShader * shader);
 
 private:
-	
-	std::vector<std::string> mShinyUniforms;
-
-	//water parameters
-	std::vector<std::string> mWaterUniforms;
-
-	std::vector<std::string> mWLUniforms;
-
-	//terrain parameters
-	std::vector<std::string> mTerrainUniforms;
-
-	//glow parameters
-	std::vector<std::string> mGlowUniforms;
-
-	std::vector<std::string> mGlowExtractUniforms;
-
-	std::vector<std::string> mAvatarUniforms;
-
 	// the list of shaders we need to propagate parameters to.
 	std::vector<LLGLSLShader *> mShaderList;
 
@@ -255,6 +237,7 @@ extern LLGLSLShader			gSkinnedObjectShinySimpleWaterProgram;
 extern LLGLSLShader			gTerrainProgram;
 extern LLGLSLShader			gTerrainWaterProgram;
 extern LLGLSLShader			gWaterProgram;
+extern LLGLSLShader			gWaterEdgeProgram;
 extern LLGLSLShader			gUnderWaterProgram;
 extern LLGLSLShader			gGlowProgram;
 extern LLGLSLShader			gGlowExtractProgram;
@@ -281,6 +264,8 @@ extern LLGLSLShader			gImpostorProgram;
 // WindLight shader handles
 extern LLGLSLShader			gWLSkyProgram;
 extern LLGLSLShader			gWLCloudProgram;
+extern LLGLSLShader			gWLSunProgram;
+extern LLGLSLShader			gWLMoonProgram;
 
 // Post Process Shaders
 extern LLGLSLShader			gPostColorFilterProgram;
@@ -301,6 +286,7 @@ extern LLGLSLShader			gDeferredSkinnedBumpProgram;
 extern LLGLSLShader			gDeferredSkinnedAlphaProgram;
 extern LLGLSLShader			gDeferredBumpProgram;
 extern LLGLSLShader			gDeferredTerrainProgram;
+extern LLGLSLShader			gDeferredTerrainWaterProgram;
 extern LLGLSLShader			gDeferredTreeProgram;
 extern LLGLSLShader			gDeferredTreeShadowProgram;
 extern LLGLSLShader			gDeferredLightProgram;
@@ -315,6 +301,7 @@ extern LLGLSLShader			gDeferredSoftenWaterProgram;
 extern LLGLSLShader			gDeferredShadowProgram;
 extern LLGLSLShader			gDeferredShadowCubeProgram;
 extern LLGLSLShader			gDeferredShadowAlphaMaskProgram;
+extern LLGLSLShader			gDeferredShadowFullbrightAlphaMaskProgram;
 extern LLGLSLShader			gDeferredPostProgram;
 extern LLGLSLShader			gDeferredCoFProgram;
 extern LLGLSLShader			gDeferredDoFCombineProgram;
@@ -339,6 +326,8 @@ extern LLGLSLShader			gDeferredAvatarEyesProgram;
 extern LLGLSLShader			gDeferredAvatarAlphaProgram;
 extern LLGLSLShader			gDeferredWLSkyProgram;
 extern LLGLSLShader			gDeferredWLCloudProgram;
+extern LLGLSLShader			gDeferredWLSunProgram;
+extern LLGLSLShader			gDeferredWLMoonProgram;
 extern LLGLSLShader			gDeferredStarProgram;
 extern LLGLSLShader			gDeferredFullbrightShinyProgram;
 extern LLGLSLShader			gDeferredSkinnedFullbrightShinyProgram;
diff --git a/indra/newview/llviewertexlayer.h b/indra/newview/llviewertexlayer.h
index 027ae255ec3b53fef615dd18eec97b96ee6613d0..dec7f0ddfce23cc4cdcea189b59ebc8bd3e31c1e 100644
--- a/indra/newview/llviewertexlayer.h
+++ b/indra/newview/llviewertexlayer.h
@@ -111,7 +111,7 @@ class LLViewerTexLayerSetBuffer : public LLTexLayerSetBuffer, public LLViewerDyn
 	// Pass these along for tex layer rendering.
 	virtual void			preRender(BOOL clear_depth) { preRenderTexLayerSet(); }
 	virtual void			postRender(BOOL success) { postRenderTexLayerSet(success); }
-	virtual BOOL			render() { return renderTexLayerSet(); }
+	virtual BOOL			render() { return renderTexLayerSet(mBoundTarget); }
 	
 	//--------------------------------------------------------------------
 	// Updates
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 0e181bf53d838d8d35190e4a287e5ff4e4ec3594..e2de7ac825e7e5f76b2e4f1bf7097b7438a3f621 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -31,6 +31,7 @@
 #include "llagent.h"
 #include "llaudioengine.h"
 #include "llavataractions.h"
+#include "llenvironment.h"
 #include "llfloaterreg.h"
 #include "llfloatersidepanelcontainer.h"
 #include "llfloaterworldmap.h"
@@ -540,7 +541,9 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const
 			case LLAssetType::AT_ANIMATION:		img_name = "Inv_Animation";	break;
 			case LLAssetType::AT_GESTURE:		img_name = "Inv_Gesture";	break;
 			case LLAssetType::AT_MESH:      	img_name = "Inv_Mesh";	    break;
-			default:                        	img_name = "Inv_Invalid";   break; // use the Inv_Invalid icon for undefined object types (see MAINT-3981)
+            case LLAssetType::AT_SETTINGS:      img_name = "Inv_Settings"; break;
+			default:                        	img_name = "Inv_Invalid";  break; // use the Inv_Invalid icon for undefined object types (see MAINT-3981)
+
 		}
 
 		return LLUI::getUIImage(img_name);
@@ -852,8 +855,18 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
 	
 	if (getEnabled() && acceptsTextInput())
 	{
+		bool supported = false;
 		switch( cargo_type )
 		{
+			case DAD_SETTINGS:
+			{
+				supported = LLEnvironment::instance().isExtendedEnvironmentEnabled();
+				if (!supported && tooltip_msg.empty())
+				{
+					tooltip_msg.assign(LLTrans::getString("TooltipNotecardNotAllowedTypeDrop"));
+				}
+				break;
+			}
 			case DAD_CALLINGCARD:
 			case DAD_TEXTURE:
 			case DAD_SOUND:
@@ -867,52 +880,50 @@ BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
 			case DAD_GESTURE:
 			case DAD_MESH:
 			{
-				LLInventoryItem *item = (LLInventoryItem *)cargo_data;
-				if( item && allowsEmbeddedItems() )
+				supported = true;
+				break;
+			}
+
+		default:
+			supported = false;
+			break;
+		}
+
+		LLInventoryItem *item = (LLInventoryItem *)cargo_data;
+		if (item && allowsEmbeddedItems() && supported)
+		{
+			U32 mask_next = item->getPermissions().getMaskNextOwner();
+			if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
+			{
+				if( drop )
 				{
-					U32 mask_next = item->getPermissions().getMaskNextOwner();
-					if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
-					{
-						if( drop )
-						{
-							deselect();
-							S32 old_cursor = mCursorPos;
-							setCursorAtLocalPos( x, y, TRUE );
-							S32 insert_pos = mCursorPos;
-							setCursorPos(old_cursor);
-							BOOL inserted = insertEmbeddedItem( insert_pos, item );
-							if( inserted && (old_cursor > mCursorPos) )
-							{
-								setCursorPos(mCursorPos + 1);
-							}
-
-							needsReflow();
-							
-						}
-						*accept = ACCEPT_YES_COPY_MULTI;
-					}
-					else
+					deselect();
+					S32 old_cursor = mCursorPos;
+					setCursorAtLocalPos( x, y, TRUE );
+					S32 insert_pos = mCursorPos;
+					setCursorPos(old_cursor);
+					BOOL inserted = insertEmbeddedItem( insert_pos, item );
+					if( inserted && (old_cursor > mCursorPos) )
 					{
-						*accept = ACCEPT_NO;
-						if (tooltip_msg.empty())
-						{
-							// *TODO: Translate
-							tooltip_msg.assign("Only items with unrestricted\n"
-												"'next owner' permissions \n"
-												"can be attached to notecards.");
-						}
+						setCursorPos(mCursorPos + 1);
 					}
+
+					needsReflow();
 				}
-				else
+				*accept = ACCEPT_YES_COPY_MULTI;
+			}
+			else
+			{
+				*accept = ACCEPT_NO;
+				if (tooltip_msg.empty())
 				{
-					*accept = ACCEPT_NO;
+					tooltip_msg.assign(LLTrans::getString("TooltipNotecardOwnerRestrictedDrop"));
 				}
-				break;
 			}
-
-		default:
+		}
+		else
+		{
 			*accept = ACCEPT_NO;
-			break;
 		}
 	}
 	else
@@ -1112,7 +1123,9 @@ BOOL LLViewerTextEditor::openEmbeddedItem(LLPointer<LLInventoryItem> item, llwch
 		case LLAssetType::AT_CALLINGCARD:
 			openEmbeddedCallingcard( item, wc );
 			return TRUE;
-
+		case LLAssetType::AT_SETTINGS:
+			openEmbeddedSetting(item, wc);
+			return TRUE;
 		case LLAssetType::AT_NOTECARD:
 		case LLAssetType::AT_LSL_TEXT:
 		case LLAssetType::AT_CLOTHING:
@@ -1187,6 +1200,18 @@ void LLViewerTextEditor::openEmbeddedCallingcard( LLInventoryItem* item, llwchar
 	}
 }
 
+void LLViewerTextEditor::openEmbeddedSetting(LLInventoryItem* item, llwchar wc)
+{
+	if (LLEnvironment::instance().isInventoryEnabled())
+	{
+		showCopyToInvDialog(item, wc);
+	}
+	else
+	{
+		LLNotificationsUtil::add("NoEnvironmentSettings");
+	}
+}
+
 void LLViewerTextEditor::showUnsavedAlertDialog( LLInventoryItem* item )
 {
 	LLSD payload;
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index 44f104dde11c2fc7ed39dde59fa1a49f119caf87..a6d7fef4099bc6790168a3d387ce1121702d89b3 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -107,6 +107,7 @@ class LLViewerTextEditor : public LLTextEditor
 	void			openEmbeddedSound( LLInventoryItem* item, llwchar wc );
 	void			openEmbeddedLandmark( LLPointer<LLInventoryItem> item_ptr, llwchar wc );
 	void			openEmbeddedCallingcard( LLInventoryItem* item, llwchar wc);
+	void			openEmbeddedSetting(LLInventoryItem* item, llwchar wc);
 	void			showCopyToInvDialog( LLInventoryItem* item, llwchar wc );
 	void			showUnsavedAlertDialog( LLInventoryItem* item );
 
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 305f891a86a2ee3c80dce32563f56462a0d38060..a2cec9a6133f676376cc3623b747b12541df5164 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -98,8 +98,8 @@ const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64;
 const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez;
 const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128;
 const S32 DEFAULT_ICON_DIMENTIONS = 32;
-S32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.
-S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
+U32 LLViewerTexture::sMinLargeImageSize = 65536; //256 * 256.
+U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
 bool LLViewerTexture::sFreezeImageUpdates = false;
 F32 LLViewerTexture::sCurrentTime = 0.0f;
 F32  LLViewerTexture::sTexelPixelRatio = 1.0f;
@@ -3481,7 +3481,10 @@ BOOL LLViewerMediaTexture::findFaces()
 			U32 end = tex->getNumFaces(ch);
 		for(U32 i = 0; i < end; i++)
 		{
-			mMediaFaceList.push_back((*face_list)[i]);
+			if ((*face_list)[i]->isMediaAllowed())
+			{
+				mMediaFaceList.push_back((*face_list)[i]);
+			}
 		}
 	}
 	}
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 7cbcc931b15436bf9f8da53b6c8050e0b4f42ee8..69568cc8255cadf45d160a1298b00eefc126ca03 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -125,6 +125,8 @@ class LLViewerTexture : public LLGLTexture
 	virtual BOOL isMissingAsset() const ;
 	virtual void dump();	// debug info to LL_INFOS()
 	
+    virtual bool isViewerMediaTexture() const { return false; }
+
 	/*virtual*/ bool bindDefaultImage(const S32 stage = 0) ;
 	/*virtual*/ bool bindDebugImage(const S32 stage = 0) ;
 	/*virtual*/ void forceImmediateUpdate() ;
@@ -228,8 +230,8 @@ class LLViewerTexture : public LLGLTexture
 	static S8  sCameraMovingDiscardBias;
 	static F32 sCameraMovingBias;
 	static S32 sMaxSculptRez ;
-	static S32 sMinLargeImageSize ;
-	static S32 sMaxSmallImageSize ;
+	static U32 sMinLargeImageSize ;
+	static U32 sMaxSmallImageSize ;
 	static bool sFreezeImageUpdates;
 	static F32  sCurrentTime ;
 
@@ -579,6 +581,8 @@ class LLViewerMediaTexture : public LLViewerTexture
 	BOOL isPlaying() const {return mIsPlaying;}
 	void setMediaImpl() ;
 
+    virtual bool isViewerMediaTexture() const { return true; }
+
 	void initVirtualSize() ;	
 	void invalidateMediaImpl() ;
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index ff5dff1c9b156dad0e52bdcd8af8dd76cc45476f..ae1eec81e0cbfa2c4a08e23bef90735835811b4b 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -360,6 +360,8 @@ class LLDebugText
 		static const std::string beacon_scripted_touch = LLTrans::getString("BeaconScriptedTouch");
 		static const std::string beacon_sound = LLTrans::getString("BeaconSound");
 		static const std::string beacon_media = LLTrans::getString("BeaconMedia");
+		static const std::string beacon_sun = LLTrans::getString("BeaconSun");
+		static const std::string beacon_moon = LLTrans::getString("BeaconMoon");
 		static const std::string particle_hiding = LLTrans::getString("ParticleHiding");
 
 		// Draw the statistics in a light gray
@@ -604,7 +606,7 @@ class LLDebugText
 			addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount));
 			ypos += y_inc;
 
-			addText(xpos, ypos, llformat("%d Render Calls", last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize)));
+			addText(xpos, ypos, llformat("%d Render Calls", (U32)last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize)));
             ypos += y_inc;
 
 			addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects()));
@@ -794,6 +796,20 @@ class LLDebugText
 			}
 		}
 
+		static LLUICachedControl<bool> show_sun_beacon("sunbeacon", false);
+		static LLUICachedControl<bool> show_moon_beacon("moonbeacon", false);
+
+		if (show_sun_beacon)
+		{
+			addText(xpos, ypos, beacon_sun);
+			ypos += y_inc;
+		}
+		if (show_moon_beacon)
+		{
+			addText(xpos, ypos, beacon_moon);
+			ypos += y_inc;
+		}
+
 		if(log_texture_traffic)
 		{	
 			U32 old_y = ypos ;
@@ -3855,7 +3871,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls,
 						F32 scale = vovolume->getLightRadius();
 						gGL.scalef(scale, scale, scale);
 
-						LLColor4 color(vovolume->getLightColor(), .5f);
+						LLColor4 color(vovolume->getLightSRGBColor(), .5f);
 						gGL.color4fv(color.mV);
 					
 						//F32 pixel_area = 100000.f;
@@ -4832,7 +4848,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 				{
 					// Required for showing the GUI in snapshots and performing bloom composite overlay
 					// Call even if show_ui is FALSE
-					LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
 					render_ui(scale_factor, subfield);
 					swap();
 				}
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 7fb4cc682261b84ca3a114cfdbfdd17ff1586ae2..f391621e48aab7762de50cbcb91fe5338f5a84bb 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -2956,7 +2956,7 @@ void LLVOAvatar::idleUpdateLoadingEffect()
 void LLVOAvatar::idleUpdateWindEffect()
 {
 	// update wind effect
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
+	if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH))
 	{
 		F32 hover_strength = 0.f;
 		F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast;
@@ -4658,7 +4658,7 @@ U32 LLVOAvatar::renderSkinned()
 		}
 	}
 
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0)
 	{
 		if (mNeedsSkin)
 		{
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index d651d540b9cd89c7fa601303ca4785512ef681c2..345e87eea82f2172412f988ea95efe109ae2da5c 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -288,24 +288,12 @@ void LLVOGrass::idleUpdate(LLAgent &agent, const F64 &time)
 		// So drones work.
 		return;
 	}
-
-	if(LLVOTree::isTreeRenderingStopped()) //stop rendering grass
+	if (!LLVOTree::isTreeRenderingStopped() && !mNumBlades)//restart grass rendering
 	{
-		if(mNumBlades)
-		{
-			mNumBlades = 0 ;
-			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
-		}
-		return;
-	}
-	else if(!mNumBlades)//restart grass rendering
-	{
-		mNumBlades = GRASS_MAX_BLADES ;
+		mNumBlades = GRASS_MAX_BLADES;
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
-		
 		return;
 	}
-
 	if (mPatch && (mLastPatchUpdateTime != mPatch->getLastUpdateTime()))
 	{
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
@@ -352,11 +340,15 @@ BOOL LLVOGrass::updateLOD()
 	{
 		return FALSE;
 	}
+
+    LLFace* face = mDrawable->getFace(0);
+
 	if(LLVOTree::isTreeRenderingStopped())
 	{
 		if(mNumBlades)
 		{
 			mNumBlades = 0 ;
+            face->setSize(0, 0);
 			gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
 		}
 		return TRUE ;
@@ -366,8 +358,6 @@ BOOL LLVOGrass::updateLOD()
 		mNumBlades = GRASS_MAX_BLADES;
 	}
 
-	LLFace* face = mDrawable->getFace(0);
-
 	F32 tan_angle = 0.f;
 	S32 num_blades = 0;
 
diff --git a/indra/newview/llvoground.cpp b/indra/newview/llvoground.cpp
index 71a7623fb4ef659509a4b1f6b02ee3fa317199a9..52a6395618400c0b10b5ef76afcdf24c2bf56e80 100644
--- a/indra/newview/llvoground.cpp
+++ b/indra/newview/llvoground.cpp
@@ -126,7 +126,7 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable)
 	left_dir.normVec();
 
 	// Our center top point
-	LLColor4 ground_color = gSky.getFogColor();
+	LLColor4 ground_color = gSky.getSkyFogColor();
 	ground_color.mV[3] = 1.f;
 	face->setFaceColor(ground_color);
 	
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index c131cb886f4b2f1d202e9289ff6635890f8694cd..2037aca7e97d5d2ba5b03e07cfde9c94e412ef95 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -48,170 +48,63 @@
 #include "llworld.h"
 #include "pipeline.h"
 #include "lldrawpoolwlsky.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
+#include "v3colorutil.h"
+
+#include "llsettingssky.h"
+#include "llenvironment.h"
+
+#include "lltrace.h"
+#include "llfasttimer.h"
 
 #undef min
 #undef max
 
-static const S32 NUM_TILES_X = 8;
-static const S32 NUM_TILES_Y = 4;
-static const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
+namespace
+{
+    const S32 NUM_TILES_X = 8;
+    const S32 NUM_TILES_Y = 4;
+    const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
+    const S32 NUM_CUBEMAP_FACES = 6;
 
 // Heavenly body constants
-static const F32 SUN_DISK_RADIUS	= 0.5f;
-static const F32 MOON_DISK_RADIUS	= SUN_DISK_RADIUS * 0.9f;
-static const F32 SUN_INTENSITY = 1e5;
+    const F32 SUN_DISK_RADIUS	= 0.5f;
+    const F32 MOON_DISK_RADIUS	= SUN_DISK_RADIUS * 0.9f;
+    const F32 SUN_INTENSITY = 1e5;
 
 // Texture coordinates:
-static const LLVector2 TEX00 = LLVector2(0.f, 0.f);
-static const LLVector2 TEX01 = LLVector2(0.f, 1.f);
-static const LLVector2 TEX10 = LLVector2(1.f, 0.f);
-static const LLVector2 TEX11 = LLVector2(1.f, 1.f);
-
-// Exported globals
-LLUUID gSunTextureID = IMG_SUN;
-LLUUID gMoonTextureID = IMG_MOON;
-
-class LLFastLn
-{
-public:
-	LLFastLn() 
-	{
-		mTable[0] = 0;
-		for( S32 i = 1; i < 257; i++ )
-		{
-			mTable[i] = log((F32)i);
-		}
-	}
-
-	F32 ln( F32 x )
-	{
-		const F32 OO_255 = 0.003921568627450980392156862745098f;
-		const F32 LN_255 = 5.5412635451584261462455391880218f;
-
-		if( x < OO_255 )
-		{
-			return log(x);
-		}
-		else
-		if( x < 1 )
-		{
-			x *= 255.f;
-			S32 index = llfloor(x);
-			F32 t = x - index;
-			F32 low = mTable[index];
-			F32 high = mTable[index + 1];
-			return low + t * (high - low) - LN_255;
-		}
-		else
-		if( x <= 255 )
-		{
-			S32 index = llfloor(x);
-			F32 t = x - index;
-			F32 low = mTable[index];
-			F32 high = mTable[index + 1];
-			return low + t * (high - low);
-		}
-		else
-		{
-			return log( x );
-		}
-	}
+    const LLVector2 TEX00 = LLVector2(0.f, 0.f);
+    const LLVector2 TEX01 = LLVector2(0.f, 1.f);
+    const LLVector2 TEX10 = LLVector2(1.f, 0.f);
+    const LLVector2 TEX11 = LLVector2(1.f, 1.f);
 
-	F32 pow( F32 x, F32 y )
-	{
-		return (F32)LL_FAST_EXP(y * ln(x));
-	}
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATETIMER("VOSky Update Timer Tick");
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_CALC("VOSky Update Calculations");
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_CREATETEXTURES("VOSky Update Textures");
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATEFORCED("VOSky Update Forced");
 
+    F32Seconds UPDATE_EXPRY(0.25f);
 
-private:
-	F32 mTable[257]; // index 0 is unused
-};
-
-static LLFastLn gFastLn;
-
-
-// Functions used a lot.
-
-inline F32 LLHaze::calcPhase(const F32 cos_theta) const
-{
-	const F32 g2 = mG * mG;
-	const F32 den = 1 + g2 - 2 * mG * cos_theta;
-	return (1 - g2) * gFastLn.pow(den, -1.5);
+    const F32 UPDATE_MIN_DELTA_THRESHOLD = 0.0005f;
 }
-
-inline void color_pow(LLColor3 &col, const F32 e)
-{
-	col.mV[0] = gFastLn.pow(col.mV[0], e);
-	col.mV[1] = gFastLn.pow(col.mV[1], e);
-	col.mV[2] = gFastLn.pow(col.mV[2], e);
-}
-
-inline LLColor3 color_norm(const LLColor3 &col)
-{
-	const F32 m = color_max(col);
-	if (m > 1.f)
-	{
-		return 1.f/m * col;
-	}
-	else return col;
-}
-
-inline void color_gamma_correct(LLColor3 &col)
-{
-	const F32 gamma_inv = 1.f/1.2f;
-	if (col.mV[0] != 0.f)
-	{
-		col.mV[0] = gFastLn.pow(col.mV[0], gamma_inv);
-	}
-	if (col.mV[1] != 0.f)
-	{
-		col.mV[1] = gFastLn.pow(col.mV[1], gamma_inv);
-	}
-	if (col.mV[2] != 0.f)
-	{
-		col.mV[2] = gFastLn.pow(col.mV[2], gamma_inv);
-	}
-}
-
-static LLColor3 calc_air_sca_sea_level()
-{
-	static LLColor3 WAVE_LEN(675, 520, 445);
-	static LLColor3 refr_ind = refr_ind_calc(WAVE_LEN);
-	static LLColor3 n21 = refr_ind * refr_ind - LLColor3(1, 1, 1);
-	static LLColor3 n4 = n21 * n21;
-	static LLColor3 wl2 = WAVE_LEN * WAVE_LEN * 1e-6f;
-	static LLColor3 wl4 = wl2 * wl2;
-	static LLColor3 mult_const = fsigma * 2.0f/ 3.0f * 1e24f * (F_PI * F_PI) * n4;
-	static F32 dens_div_N = F32( ATM_SEA_LEVEL_NDENS / Ndens2);
-	return dens_div_N * color_div ( mult_const, wl4 );
-}
-
-// static constants.
-LLColor3 const LLHaze::sAirScaSeaLevel = calc_air_sca_sea_level();
-F32 const LLHaze::sAirScaIntense = color_intens(LLHaze::sAirScaSeaLevel);	
-F32 const LLHaze::sAirScaAvg = LLHaze::sAirScaIntense / 3.f;
-
-
 /***************************************
 		SkyTex
 ***************************************/
 
 S32 LLSkyTex::sComponents = 4;
 S32 LLSkyTex::sResolution = 64;
-F32 LLSkyTex::sInterpVal = 0.f;
 S32 LLSkyTex::sCurrent = 0;
 
 
 LLSkyTex::LLSkyTex() :
 	mSkyData(NULL),
-	mSkyDirs(NULL)
+	mSkyDirs(NULL),
+    mIsShiny(false)
 {
 }
 
-void LLSkyTex::init()
+void LLSkyTex::init(bool isShiny)
 {
+    mIsShiny = isShiny;
 	mSkyData = new LLColor4[sResolution * sResolution];
 	mSkyDirs = new LLVector3[sResolution * sResolution];
 
@@ -249,6 +142,32 @@ LLSkyTex::~LLSkyTex()
 	mSkyDirs = NULL;
 }
 
+S32 LLSkyTex::getResolution()
+{
+    return sResolution;
+}
+
+S32 LLSkyTex::getCurrent()
+{
+    return sCurrent;
+}
+
+S32 LLSkyTex::stepCurrent() {
+    sCurrent++;
+    sCurrent &= 1;
+    return sCurrent;
+}
+
+S32 LLSkyTex::getNext()
+{
+    return ((sCurrent+1) & 1);
+}
+
+S32 LLSkyTex::getWhich(const BOOL curr)
+{
+    int tex = curr ? sCurrent : getNext();
+    return tex;
+}
 
 void LLSkyTex::initEmpty(const S32 tex)
 {
@@ -271,9 +190,8 @@ void LLSkyTex::initEmpty(const S32 tex)
 	createGLImage(tex);
 }
 
-void LLSkyTex::create(const F32 brightness)
+void LLSkyTex::create()
 {
-	/// Brightness ignored for now.
 	U8* data = mImageRaw[sCurrent]->getData();
 	for (S32 i = 0; i < sResolution; ++i)
 	{
@@ -289,26 +207,202 @@ void LLSkyTex::create(const F32 brightness)
 	createGLImage(sCurrent);
 }
 
-
-
-
 void LLSkyTex::createGLImage(S32 which)
 {	
+    if (mIsShiny)
+    {
+        mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA);
+    }
+    else
+    {
+        mTexture[which]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
+    }
 	mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL);
 	mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
 }
 
 void LLSkyTex::bindTexture(BOOL curr)
 {
-	gGL.getTexUnit(0)->bind(mTexture[getWhich(curr)], true);
+    int tex = getWhich(curr);
+	gGL.getTexUnit(0)->bind(mTexture[tex], true);
+}
+
+LLImageRaw* LLSkyTex::getImageRaw(BOOL curr)
+{
+    int tex = getWhich(curr);
+    return mImageRaw[tex];
 }
 
 /***************************************
-		Sky
+    LLHeavenBody
 ***************************************/
 
 F32	LLHeavenBody::sInterpVal = 0;
 
+LLHeavenBody::LLHeavenBody(const F32 rad)
+: mDirectionCached(LLVector3(0,0,0)),
+  mDirection(LLVector3(0,0,0)),
+  mIntensity(0.f),
+  mDiskRadius(rad),
+  mDraw(FALSE),
+  mHorizonVisibility(1.f),
+  mVisibility(1.f),
+  mVisible(FALSE)
+{
+	mColor.setToBlack();
+	mColorCached.setToBlack();
+}
+
+const LLQuaternion& LLHeavenBody::getRotation() const
+{
+    return mRotation;
+}
+
+void LLHeavenBody::setRotation(const LLQuaternion& rot)
+{
+    mRotation = rot;
+}
+
+const LLVector3& LLHeavenBody::getDirection() const
+{
+    return mDirection;
+}
+
+void LLHeavenBody::setDirection(const LLVector3 &direction)
+{
+    mDirection = direction;
+}
+
+void LLHeavenBody::setAngularVelocity(const LLVector3 &ang_vel)
+{
+    mAngularVelocity = ang_vel;
+}
+
+const LLVector3& LLHeavenBody::getAngularVelocity() const
+{
+    return mAngularVelocity;
+}
+
+const LLVector3& LLHeavenBody::getDirectionCached() const
+{
+    return mDirectionCached;
+}
+
+void LLHeavenBody::renewDirection()
+{
+    mDirectionCached = mDirection;
+}
+
+const LLColor3& LLHeavenBody::getColorCached() const
+{
+    return mColorCached;
+}
+
+void LLHeavenBody::setColorCached(const LLColor3& c)
+{
+    mColorCached = c;
+}
+
+const LLColor3& LLHeavenBody::getColor() const
+{
+    return mColor;
+}
+
+void LLHeavenBody::setColor(const LLColor3& c)
+{
+    mColor = c;
+}
+
+void LLHeavenBody::renewColor()
+{
+    mColorCached = mColor;
+}
+
+F32 LLHeavenBody::interpVal()
+{
+    return sInterpVal;
+}
+
+void LLHeavenBody::setInterpVal(const F32 v)
+{
+    sInterpVal = v;
+}
+
+LLColor3 LLHeavenBody::getInterpColor() const
+{
+	return sInterpVal * mColor + (1 - sInterpVal) * mColorCached;
+}
+
+const F32& LLHeavenBody::getVisibility() const
+{
+    return mVisibility;
+}
+
+void LLHeavenBody::setVisibility(const F32 c)
+{
+    mVisibility = c;
+}
+
+bool LLHeavenBody::isVisible() const
+{
+    return mVisible;
+}
+
+void LLHeavenBody::setVisible(const bool v)
+{
+    mVisible = v;
+}
+
+const F32& LLHeavenBody::getIntensity() const
+{
+    return mIntensity;
+}
+
+void LLHeavenBody::setIntensity(const F32 c)
+{
+    mIntensity = c;
+}
+
+void LLHeavenBody::setDiskRadius(const F32 radius)
+{
+    mDiskRadius = radius;
+}
+
+F32	LLHeavenBody::getDiskRadius() const
+{
+    return mDiskRadius;
+}
+
+void LLHeavenBody::setDraw(const bool draw)
+{
+    mDraw = draw;
+}
+
+bool LLHeavenBody::getDraw() const
+{
+    return mDraw;
+}
+
+const LLVector3& LLHeavenBody::corner(const S32 n) const
+{
+    return mQuadCorner[n];
+}
+
+LLVector3& LLHeavenBody::corner(const S32 n)
+{
+    return mQuadCorner[n];
+}
+
+const LLVector3* LLHeavenBody::corners() const
+{
+    return mQuadCorner;
+}
+
+/***************************************
+		Sky
+***************************************/
+
+
 S32 LLVOSky::sResolution = LLSkyTex::getResolution();
 S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X;
 S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y;
@@ -323,39 +417,24 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 	mCloudDensity(0.2f),
 	mWind(0.f),
 	mForceUpdate(FALSE),
+    mNeedUpdate(TRUE),
+    mCubeMapUpdateStage(-1),
 	mWorldScale(1.f),
 	mBumpSunDir(0.f, 0.f, 1.f)
 {
-	bool error = false;
-	
 	/// WL PARAMS
-	dome_radius = 1.f;
-	dome_offset_ratio = 0.f;
-	sunlight_color = LLColor3();
-	ambient = LLColor3();
-	gamma = 1.f;
-	lightnorm = LLVector4();
-	blue_density = LLColor3();
-	blue_horizon = LLColor3();
-	haze_density = 0.f;
-	haze_horizon = 1.f;
-	density_multiplier = 0.f;
-	max_y = 0.f;
-	glow = LLColor3();
-	cloud_shadow = 0.f;
-	cloud_color = LLColor3();
-	cloud_scale = 0.f;
-	cloud_pos_density1 = LLColor3();
-	cloud_pos_density2 = LLColor3();
 
 	mInitialized = FALSE;
 	mbCanSelect = FALSE;
 	mUpdateTimer.reset();
 
-	for (S32 i = 0; i < 6; i++)
+    mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
+    mForceUpdateThrottle.reset();
+
+	for (S32 i = 0; i < NUM_CUBEMAP_FACES; i++)
 	{
-		mSkyTex[i].init();
-		mShinyTex[i].init();
+		mSkyTex[i].init(false);
+		mShinyTex[i].init(true);
 	}
 	for (S32 i=0; i<FACE_COUNT; i++)
 	{
@@ -366,32 +445,12 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 	mAtmHeight = ATM_HEIGHT;
 	mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS);
 
-	mSunDefaultPosition = LLVector3(LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error));
-	if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition"))
-	{
-		initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0));
-	}
-	mAmbientScale = gSavedSettings.getF32("SkyAmbientScale");
-	mNightColorShift = gSavedSettings.getColor3("SkyNightColorShift");
-	mFogColor.mV[VRED] = mFogColor.mV[VGREEN] = mFogColor.mV[VBLUE] = 0.5f;
-	mFogColor.mV[VALPHA] = 0.0f;
-	mFogRatio = 1.2f;
-
 	mSun.setIntensity(SUN_INTENSITY);
 	mMoon.setIntensity(0.1f * SUN_INTENSITY);
 
-	mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-	mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-	mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
-	mBloomTexturep->setNoDelete() ;
-	mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-
 	mHeavenlyBodyUpdated = FALSE ;
 
 	mDrawRefl = 0;
-	mHazeConcentration = 0.f;
 	mInterpVal = 0.f;
 }
 
@@ -406,50 +465,107 @@ LLVOSky::~LLVOSky()
 
 void LLVOSky::init()
 {
-   	const F32 haze_int = color_intens(mHaze.calcSigSca(0));
-	mHazeConcentration = haze_int /
-		(color_intens(LLHaze::calcAirSca(0)) + haze_int);
-
-	calcAtmospherics();
+    llassert(!mInitialized);
+
+    // Update sky at least once to get correct initial sun/moon directions and lighting calcs performed
+    LLEnvironment::instance().getCurrentSky()->update();
+
+	updateDirections();
+
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    // invariants across whole sky tex process...
+    m_atmosphericsVars.blue_density = psky->getBlueDensity();    
+    m_atmosphericsVars.blue_horizon = psky->getBlueHorizon();
+    m_atmosphericsVars.haze_density = psky->getHazeDensity();
+    m_atmosphericsVars.haze_horizon = psky->getHazeHorizon();
+    m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier();
+    m_atmosphericsVars.max_y = psky->getMaxY();
+    m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm();
+    m_atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor();
+    m_atmosphericsVars.ambient = psky->getAmbientColor();    
+    m_atmosphericsVars.glow = psky->getGlow();
+    m_atmosphericsVars.cloud_shadow = psky->getCloudShadow();
+    m_atmosphericsVars.dome_radius = psky->getDomeRadius();
+    m_atmosphericsVars.dome_offset = psky->getDomeOffset();
+    m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y);
+    m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(m_atmosphericsVars.max_y);
+    m_atmosphericsVars.total_density = psky->getTotalDensity();
+    m_atmosphericsVars.gamma = psky->getGamma();
 
 	// Initialize the cached normalized direction vectors
-	for (S32 side = 0; side < 6; ++side)
+	for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side)
 	{
 		for (S32 tile = 0; tile < NUM_TILES; ++tile)
 		{
 			initSkyTextureDirs(side, tile);
-			createSkyTexture(side, tile);
+            createSkyTexture(m_atmosphericsVars, side, tile);
 		}
-	}
-
-	for (S32 i = 0; i < 6; ++i)
-	{
-		mSkyTex[i].create(1.0f);
-		mShinyTex[i].create(1.0f);
+        mSkyTex[side].create();
+        mShinyTex[side].create();
 	}
 
 	initCubeMap();
+
 	mInitialized = true;
 
 	mHeavenlyBodyUpdated = FALSE ;
+
+    mRainbowMap = LLViewerTextureManager::getFetchedTexture(psky->getRainbowTextureId(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+    mHaloMap    = LLViewerTextureManager::getFetchedTexture(psky->getHaloTextureId(),  FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+}
+
+
+void LLVOSky::calc()
+{
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    // invariants across whole sky tex process...
+    m_atmosphericsVars.blue_density = psky->getBlueDensity();    
+    m_atmosphericsVars.blue_horizon = psky->getBlueHorizon();
+    m_atmosphericsVars.haze_density = psky->getHazeDensity();
+    m_atmosphericsVars.haze_horizon = psky->getHazeHorizon();
+    m_atmosphericsVars.density_multiplier = psky->getDensityMultiplier();
+    m_atmosphericsVars.distance_multiplier = psky->getDistanceMultiplier();
+    m_atmosphericsVars.max_y = psky->getMaxY();
+    m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm();
+    m_atmosphericsVars.sunlight = psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor();
+    m_atmosphericsVars.ambient = psky->getAmbientColor();    
+    m_atmosphericsVars.glow = psky->getGlow();
+    m_atmosphericsVars.cloud_shadow = psky->getCloudShadow();
+    m_atmosphericsVars.dome_radius = psky->getDomeRadius();
+    m_atmosphericsVars.dome_offset = psky->getDomeOffset();
+    m_atmosphericsVars.light_atten = psky->getLightAttenuation(m_atmosphericsVars.max_y);
+    m_atmosphericsVars.light_transmittance = psky->getLightTransmittance(m_atmosphericsVars.max_y);
+    m_atmosphericsVars.gamma = psky->getGamma();
+
+	mSun.setColor(psky->getSunDiffuse());
+	mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f));
+
+	mSun.renewDirection();
+	mSun.renewColor();
+	mMoon.renewDirection();
+	mMoon.renewColor();
 }
 
 void LLVOSky::initCubeMap() 
 {
 	std::vector<LLPointer<LLImageRaw> > images;
-	for (S32 side = 0; side < 6; side++)
+	for (S32 side = 0; side < NUM_CUBEMAP_FACES; side++)
 	{
 		images.push_back(mShinyTex[side].getImageRaw());
 	}
-	if (mCubeMap)
+	
+	if (!mCubeMap && gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
 	{
-		mCubeMap->init(images);
+        mCubeMap = new LLCubeMap(false);
 	}
-	else if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
+
+    if (mCubeMap)
 	{
-		mCubeMap = new LLCubeMap();
 		mCubeMap->init(images);
 	}
+
 	gGL.getTexUnit(0)->disable();
 }
 
@@ -457,7 +573,7 @@ void LLVOSky::initCubeMap()
 void LLVOSky::cleanupGL()
 {
 	S32 i;
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < NUM_CUBEMAP_FACES; i++)
 	{
 		mSkyTex[i].cleanupGL();
 	}
@@ -470,37 +586,27 @@ void LLVOSky::cleanupGL()
 void LLVOSky::restoreGL()
 {
 	S32 i;
-	for (i = 0; i < 6; i++)
+	for (i = 0; i < NUM_CUBEMAP_FACES; i++)
 	{
 		mSkyTex[i].restoreGL();
 	}
-	mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-	mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
-	mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-	mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
-	mBloomTexturep->setNoDelete() ;
-	mBloomTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
-
-	calcAtmospherics();	
-
-	if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
-	    && LLCubeMap::sUseCubeMaps)
+
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    if (psky)
 	{
-		LLCubeMap* cube_map = getCubeMap();
+        setSunTextures(psky->getSunTextureId(), psky->getNextSunTextureId());
+        setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId());
+    }
 
-		std::vector<LLPointer<LLImageRaw> > images;
-		for (S32 side = 0; side < 6; side++)
-		{
-			images.push_back(mShinyTex[side].getImageRaw());
-		}
+	updateDirections();
 
-		if(cube_map)
+	if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps)
 		{
-			cube_map->init(images);
-			mForceUpdate = TRUE;
+		initCubeMap();
 		}
-	}
+
+    forceSkyUpdate();
 
 	if (mDrawable)
 	{
@@ -541,8 +647,10 @@ void LLVOSky::initSkyTextureDirs(const S32 side, const S32 tile)
 	}
 }
 
-void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
+void LLVOSky::createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 tile)
 {
+	LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
 	S32 tile_x = tile % NUM_TILES_X;
 	S32 tile_y = tile / NUM_TILES_X;
 
@@ -554,704 +662,347 @@ void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
 	{
 		for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
 		{
-			mSkyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y)), x, y);
-			mShinyTex[side].setPixel(calcSkyColorInDir(mSkyTex[side].getDir(x, y), true), x, y);
+			mSkyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mSkyTex[side].getDir(x, y), false), x, y);
+			mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(psky, vars, mShinyTex[side].getDir(x, y), true), x, y);
 		}
 	}
 }
 
-static inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
+void LLVOSky::updateDirections(void)
 {
-	return LLColor3(left.mV[0]/right.mV[0],
-					 left.mV[1]/right.mV[1],
-					 left.mV[2]/right.mV[2]);
-}
-
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-static inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
-{
-	return LLColor3(left.mV[0]*right.mV[0],
-					 left.mV[1]*right.mV[1],
-					 left.mV[2]*right.mV[2]);
-}
-
-
-static inline LLColor3 componentExp(LLColor3 const &v)
-{
-	return LLColor3(exp(v.mV[0]),
-					 exp(v.mV[1]),
-					 exp(v.mV[2]));
+    mSun.setDirection(psky->getSunDirection());
+	mMoon.setDirection(psky->getMoonDirection());
+    mSun.setRotation(psky->getSunRotation());
+	mMoon.setRotation(psky->getMoonRotation());
+	mSun.renewDirection();
+	mMoon.renewDirection();
 }
 
-static inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
+void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time)
 {
-	return LLColor3(pow(v.mV[0], exponent),
-					pow(v.mV[1], exponent),
-					pow(v.mV[2], exponent));
 }
 
-static inline LLColor3 componentSaturate(LLColor3 const &v)
+void LLVOSky::forceSkyUpdate()
 {
-	return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
-					 std::max(std::min(v.mV[1], 1.f), 0.f),
-					 std::max(std::min(v.mV[2], 1.f), 0.f));
-}
+    mForceUpdate = TRUE;
 
+    memset(&m_lastAtmosphericsVars, 0x00, sizeof(AtmosphericsVars));
 
-static inline LLColor3 componentSqrt(LLColor3 const &v)
-{
-	return LLColor3(sqrt(v.mV[0]),
-					 sqrt(v.mV[1]),
-					 sqrt(v.mV[2]));
+    mCubeMapUpdateStage = -1;
 }
 
-static inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
+bool LLVOSky::updateSky()
 {
-	left.mV[0] *= right.mV[0];
-	left.mV[1] *= right.mV[1];
-	left.mV[2] *= right.mV[2];
-}
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-static inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
-{
-	return (left + ((right - left) * amount));
-}
-
-static inline LLColor3 smear(F32 val)
-{
-	return LLColor3(val, val, val);
-}
-
-void LLVOSky::initAtmospherics(void)
-{	
-	bool error;
-	
-	// uniform parameters for convenience
-	dome_radius = LLWLParamManager::getInstance()->getDomeRadius();
-	dome_offset_ratio = LLWLParamManager::getInstance()->getDomeOffset();
-	sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error));
-	ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error));
-	//lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error);
-	gamma = LLWLParamManager::getInstance()->mCurParams.getFloat("gamma", error);
-	blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error));
-	blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error));
-	haze_density = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_density", error);
-	haze_horizon = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_horizon", error);
-	density_multiplier = LLWLParamManager::getInstance()->mCurParams.getFloat("density_multiplier", error);
-	max_y = LLWLParamManager::getInstance()->mCurParams.getFloat("max_y", error);
-	glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error));
-	cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", error);
-	cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error));
-	cloud_scale = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_scale", error);
-	cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error));
-	cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error));
-
-	// light norm is different.  We need the sun's direction, not the light direction
-	// which could be from the moon.  And we need to clamp it
-	// just like for the gpu
-	LLVector3 sunDir = gSky.getSunDirection();
-
-	// CFR_TO_OGL
-	lightnorm = LLVector4(sunDir.mV[1], sunDir.mV[2], sunDir.mV[0], 0);
-	unclamped_lightnorm = lightnorm;
-	if(lightnorm.mV[1] < -0.1f)
+	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
 	{
-		lightnorm.mV[1] = -0.1f;
+		return TRUE;
 	}
-	
-}
 
-LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny)
-{
-	F32 saturation = 0.3f;
-	if (dir.mV[VZ] < -0.02f)
+	if (mDead)
 	{
-		LLColor4 col = LLColor4(llmax(mFogColor[0],0.2f), llmax(mFogColor[1],0.2f), llmax(mFogColor[2],0.22f),0.f);
-		if (isShiny)
-		{
-			LLColor3 desat_fog = LLColor3(mFogColor);
-			F32 brightness = desat_fog.brightness();
-			// So that shiny somewhat shows up at night.
-			if (brightness < 0.15f)
-			{
-				brightness = 0.15f;
-				desat_fog = smear(0.15f);
-			}
-			LLColor3 greyscale = smear(brightness);
-			desat_fog = desat_fog * saturation + greyscale * (1.0f - saturation);
-			if (!gPipeline.canUseWindLightShaders())
-			{
-				col = LLColor4(desat_fog, 0.f);
-			}
-			else 
-			{
-				col = LLColor4(desat_fog * 0.5f, 0.f);
-			}
-		}
-		float x = 1.0f-fabsf(-0.1f-dir.mV[VZ]);
-		x *= x;
-		col.mV[0] *= x*x;
-		col.mV[1] *= powf(x, 2.5f);
-		col.mV[2] *= x*x*x;
-		return col;
+		// It's dead.  Don't update it.
+		return TRUE;
 	}
 
-	// undo OGL_TO_CFR_ROTATION and negate vertical direction.
-	LLVector3 Pn = LLVector3(-dir[1] , -dir[2], -dir[0]);
-
-	LLColor3 vary_HazeColor(0,0,0);
-	LLColor3 vary_CloudColorSun(0,0,0);
-	LLColor3 vary_CloudColorAmbient(0,0,0);
-	F32 vary_CloudDensity(0);
-	LLVector2 vary_HorizontalProjection[2];
-	vary_HorizontalProjection[0] = LLVector2(0,0);
-	vary_HorizontalProjection[1] = LLVector2(0,0);
-
-	calcSkyColorWLVert(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient,
-						vary_CloudDensity, vary_HorizontalProjection);
-	
-	LLColor3 sky_color =  calcSkyColorWLFrag(Pn, vary_HazeColor, vary_CloudColorSun, vary_CloudColorAmbient, 
-								vary_CloudDensity, vary_HorizontalProjection);
-	if (isShiny)
+	if (gGLManager.mIsDisabled)
 	{
-		F32 brightness = sky_color.brightness();
-		LLColor3 greyscale = smear(brightness);
-		sky_color = sky_color * saturation + greyscale * (1.0f - saturation);
-		sky_color *= (0.5f + 0.5f * brightness);
-	}
-	return LLColor4(sky_color, 0.0f);
-}
-
-// turn on floating point precision
-// in vs2003 for this function.  Otherwise
-// sky is aliased looking 7:10 - 8:50
-#if LL_MSVC && __MSVC_VER__ < 8
-#pragma optimize("p", on)
-#endif
-
-void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
-							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
-							LLVector2 vary_HorizontalProjection[2])
-{
-	// project the direction ray onto the sky dome.
-	F32 phi = acos(Pn[1]);
-	F32 sinA = sin(F_PI - phi);
-	if (fabsf(sinA) < 0.01f)
-	{ //avoid division by zero
-		sinA = 0.01f;
+		return TRUE;
 	}
 
-	F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA;
+	static S32 next_frame = 0;
+	const S32 total_no_tiles = NUM_CUBEMAP_FACES * NUM_TILES;
+	const S32 cycle_frame_no = total_no_tiles + 1;
+	
+    mNeedUpdate = mForceUpdate;
 
-	Pn *= Plen;
+	++next_frame;
+	next_frame = next_frame % cycle_frame_no;
 
-	vary_HorizontalProjection[0] = LLVector2(Pn[0], Pn[2]);
-	vary_HorizontalProjection[0] /= - 2.f * Plen;
+	mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
+	LLHeavenBody::setInterpVal( mInterpVal );
+	updateDirections();
 
-	// Set altitude
-	if (Pn[1] > 0.f)
-	{
-		Pn *= (max_y / Pn[1]);
-	}
-	else
+    if (!mCubeMap)
 	{
-		Pn *= (-32000.f / Pn[1]);
+        mCubeMapUpdateStage = NUM_CUBEMAP_FACES;
+        mForceUpdate = FALSE;
+        return TRUE;
 	}
+	
+    if (mCubeMapUpdateStage < 0)
+    {
+        LL_RECORD_BLOCK_TIME(FTM_VOSKY_CALC);
+        calc();
 
-	Plen = Pn.length();
-	Pn /= Plen;
-
-	// Initialize temp variables
-	LLColor3 sunlight = sunlight_color;
-
-	// Sunlight attenuation effect (hue and brightness) due to atmosphere
-	// this is used later for sunlight modulation at various altitudes
-	LLColor3 light_atten =
-		(blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
-
-	// Calculate relative weights
-	LLColor3 temp2(0.f, 0.f, 0.f);
-	LLColor3 temp1 = blue_density + smear(haze_density);
-	LLColor3 blue_weight = componentDiv(blue_density, temp1);
-	LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
-
-	// Compute sunlight from P & lightnorm (for long rays like sky)
-	temp2.mV[1] = llmax(F_APPROXIMATELY_ZERO, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
-
-	temp2.mV[1] = 1.f / temp2.mV[1];
-	componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
-
-	// Distance
-	temp2.mV[2] = Plen * density_multiplier;
-
-	// Transparency (-> temp1)
-	temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
-
-
-	// Compute haze glow
-	temp2.mV[0] = Pn * LLVector3(lightnorm);
-
-	temp2.mV[0] = 1.f - temp2.mV[0];
-		// temp2.x is 0 at the sun and increases away from sun
-	temp2.mV[0] = llmax(temp2.mV[0], .001f);	
-		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
-	temp2.mV[0] *= glow.mV[0];
-		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
-	temp2.mV[0] = pow(temp2.mV[0], glow.mV[2]);
-		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
-	// Add "minimum anti-solar illumination"
-	temp2.mV[0] += .25f;
-
-
-	// Haze color above cloud
-	vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient)
-				+ componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + ambient)
-			 );	
-
-	// Increase ambient when there are more clouds
-	LLColor3 tmpAmbient = ambient + (LLColor3::white - ambient) * cloud_shadow * 0.5f;
-
-	// Dim sunlight by cloud shadow percentage
-	sunlight *= (1.f - cloud_shadow);
-
-	// Haze color below cloud
-	LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient)
-				+ componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)
-			 );	
-
-	// Final atmosphere additive
-	componentMultBy(vary_HazeColor, LLColor3::white - temp1);
-
-	sunlight = sunlight_color;
-	temp2.mV[1] = llmax(0.f, lightnorm[1] * 2.f);
-	temp2.mV[1] = 1.f / temp2.mV[1];
-	componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
+        bool same_atmospherics = approximatelyEqual(m_lastAtmosphericsVars, m_atmosphericsVars, UPDATE_MIN_DELTA_THRESHOLD);
 
-	// Attenuate cloud color by atmosphere
-	temp1 = componentSqrt(temp1);	//less atmos opacity (more transparency) below clouds
+        mNeedUpdate = mNeedUpdate || !same_atmospherics;
 
-	// At horizon, blend high altitude sky color towards the darker color below the clouds
-	vary_HazeColor +=
-		componentMult(additiveColorBelowCloud - vary_HazeColor, LLColor3::white - componentSqrt(temp1));
-		
-	if (Pn[1] < 0.f)
-	{
-		// Eric's original: 
-		// LLColor3 dark_brown(0.143f, 0.129f, 0.114f);
-		LLColor3 dark_brown(0.082f, 0.076f, 0.066f);
-		LLColor3 brown(0.430f, 0.386f, 0.322f);
-		LLColor3 sky_lighting = sunlight + ambient;
-		F32 haze_brightness = vary_HazeColor.brightness();
-
-		if (Pn[1] < -0.05f)
-		{
-			vary_HazeColor = colorMix(dark_brown, brown, -Pn[1] * 0.9f) * sky_lighting * haze_brightness;
-		}
-		
-		if (Pn[1] > -0.1f)
+        if (mNeedUpdate && (mForceUpdateThrottle.hasExpired() || mForceUpdate))
 		{
-			vary_HazeColor = colorMix(LLColor3::white * haze_brightness, vary_HazeColor, fabs((Pn[1] + 0.05f) * -20.f));
+            // start updating cube map sides
+            updateFog(LLViewerCamera::getInstance()->getFar());
+            mCubeMapUpdateStage = 0;
+            mForceUpdate = FALSE;
 		}
 	}
-}
+    else if (mCubeMapUpdateStage == NUM_CUBEMAP_FACES)
+	{
+        LL_RECORD_BLOCK_TIME(FTM_VOSKY_UPDATEFORCED);
+        LLSkyTex::stepCurrent();
+
+        bool is_alm_wl_sky = gPipeline.canUseWindLightShaders();
+
+        int tex = mSkyTex[0].getWhich(TRUE);
+
+        for (int side = 0; side < NUM_CUBEMAP_FACES; side++)
+        {
+            LLImageRaw* raw1 = nullptr;
+            LLImageRaw* raw2 = nullptr;
+
+            if (!is_alm_wl_sky)
+            {
+                raw1 = mSkyTex[side].getImageRaw(TRUE);
+                raw2 = mSkyTex[side].getImageRaw(FALSE);
+                raw2->copy(raw1);
+                mSkyTex[side].createGLImage(tex);
+            }
+
+            raw1 = mShinyTex[side].getImageRaw(TRUE);
+            raw2 = mShinyTex[side].getImageRaw(FALSE);
+            raw2->copy(raw1);
+            mShinyTex[side].createGLImage(tex);
+        }
+        next_frame = 0;
+
+        // update the sky texture
+        if (!is_alm_wl_sky)
+        {
+            for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
+            {
+                mSkyTex[i].create();
+            }
+        }
+
+        for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
+        {
+            mShinyTex[i].create();
+        }
+
+        // update the environment map
+        initCubeMap();
+
+        m_lastAtmosphericsVars = m_atmosphericsVars;
+
+        mNeedUpdate = FALSE;
+        mForceUpdate = FALSE;
+
+        mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
+        gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+
+        if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
+        {
+            gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+        }
+        mCubeMapUpdateStage = -1;
+    }
+    // run 0 to 5 faces, each face in own frame
+    else if (mCubeMapUpdateStage >= 0 && mCubeMapUpdateStage < NUM_CUBEMAP_FACES)
+		{
+        LL_RECORD_BLOCK_TIME(FTM_VOSKY_CREATETEXTURES);
+        S32 side = mCubeMapUpdateStage;
+        // CPU hungry part, createSkyTexture() is math heavy
+        // Prior to EEP it was mostly per tile, but since EPP it is per face.
+        // This still can be optimized further
+        // (i.e. potentially can be made per tile again, can be moved to thread
+        // instead of executing per face, or may be can be moved to shaders)
+        for (S32 tile = 0; tile < NUM_TILES; tile++)
+        {
+            createSkyTexture(m_atmosphericsVars, side, tile);
+        }
+        mCubeMapUpdateStage++;
+    }
 
-#if LL_MSVC && __MSVC_VER__ < 8
-#pragma optimize("p", off)
-#endif
+	return TRUE;
+}
 
-LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
-							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
-							LLVector2 vary_HorizontalProjection[2])
+void LLVOSky::updateTextures()
 {
-	LLColor3 res;
-
-	LLColor3 color0 = vary_HazeColor;
-	
-	if (!gPipeline.canUseWindLightShaders())
-	{
-		LLColor3 color1 = color0 * 2.0f;
-		color1 = smear(1.f) - componentSaturate(color1);
-		componentPow(color1, gamma);
-		res = smear(1.f) - color1;
-	} 
-	else 
+	if (mSunTexturep[0])
 	{
-		res = color0;
+		mSunTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
 	}
 
-#	ifndef LL_RELEASE_FOR_DOWNLOAD
-
-	LLColor3 color2 = 2.f * color0;
-
-	LLColor3 color3 = LLColor3(1.f, 1.f, 1.f) - componentSaturate(color2);
-	componentPow(color3, gamma);
-	color3 = LLColor3(1.f, 1.f, 1.f) - color3;
-
-	static enum {
-		OUT_DEFAULT		= 0,
-		OUT_SKY_BLUE	= 1,
-		OUT_RED			= 2,
-		OUT_PN			= 3,
-		OUT_HAZE		= 4,
-	} debugOut = OUT_DEFAULT;
-
-	switch(debugOut) 
+    if (mSunTexturep[1])
 	{
-		case OUT_DEFAULT:
-			break;
-		case OUT_SKY_BLUE:
-			res = LLColor3(0.4f, 0.4f, 0.9f);
-			break;
-		case OUT_RED:
-			res = LLColor3(1.f, 0.f, 0.f);
-			break;
-		case OUT_PN:
-			res = LLColor3(Pn[0], Pn[1], Pn[2]);
-			break;
-		case OUT_HAZE:
-			res = vary_HazeColor;
-			break;
-	}
-#	endif // LL_RELEASE_FOR_DOWNLOAD
-	return res;
+		mSunTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
 }
 
-LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
+    if (mMoonTexturep[0])
 {
-	return componentMult(diffuse, sundiffuse) * 4.0f +
-			componentMult(ambient, sundiffuse) * 2.0f + sunambient;
+		mMoonTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
 }
 
-LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
+    if (mMoonTexturep[1])
 {
-	return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f;
+		mMoonTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
 }
 
-
-void LLVOSky::calcAtmospherics(void)
-{
-	initAtmospherics();
-
-	LLColor3 vary_HazeColor;
-	LLColor3 vary_SunlightColor;
-	LLColor3 vary_AmbientColor;
+    if (mBloomTexturep[0])
 	{
-		// Initialize temp variables
-		LLColor3 sunlight = sunlight_color;
-
-		// Sunlight attenuation effect (hue and brightness) due to atmosphere
-		// this is used later for sunlight modulation at various altitudes
-		LLColor3 light_atten =
-			(blue_density * 1.0 + smear(haze_density * 0.25f)) * (density_multiplier * max_y);
-
-		// Calculate relative weights
-		LLColor3 temp2(0.f, 0.f, 0.f);
-		LLColor3 temp1 = blue_density + smear(haze_density);
-		LLColor3 blue_weight = componentDiv(blue_density, temp1);
-		LLColor3 haze_weight = componentDiv(smear(haze_density), temp1);
-
-		// Compute sunlight from P & lightnorm (for long rays like sky)
-		/// USE only lightnorm.
-		// temp2[1] = llmax(0.f, llmax(0.f, Pn[1]) * 1.0f + lightnorm[1] );
-		
-		// and vary_sunlight will work properly with moon light
-		F32 lighty = unclamped_lightnorm[1];
-		if(lighty < LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			lighty = -lighty;
+		mBloomTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
 		}
 
-		temp2.mV[1] = llmax(0.f, lighty);
-		if(temp2.mV[1] > 0.f)
+    if (mBloomTexturep[1])
 		{
-			temp2.mV[1] = 1.f / temp2.mV[1];
+		mBloomTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
 		}
-		componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
-
-		// Distance
-		temp2.mV[2] = density_multiplier;
-
-		// Transparency (-> temp1)
-		temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
-
-		// vary_AtmosAttenuation = temp1; 
-
-		//increase ambient when there are more clouds
-		LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5f;
-
-		//haze color
-		vary_HazeColor =
-			(blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient)	
-			+ componentMult(haze_horizon * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)
-				 );	
-
-		//brightness of surface both sunlight and ambient
-		vary_SunlightColor = componentMult(sunlight, temp1) * 1.f;
-		vary_SunlightColor.clamp();
-		vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
-		vary_SunlightColor = componentPow(vary_SunlightColor, gamma);
-		vary_SunlightColor = smear(1.0f) - vary_SunlightColor;
-		vary_AmbientColor = componentMult(tmpAmbient, temp1) * 0.5;
-		vary_AmbientColor.clamp();
-		vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
-		vary_AmbientColor = componentPow(vary_AmbientColor, gamma);
-		vary_AmbientColor = smear(1.0f) - vary_AmbientColor;
-
-		componentMultBy(vary_HazeColor, LLColor3(1.f, 1.f, 1.f) - temp1);
-
 	}
 
-	mSun.setColor(vary_SunlightColor);
-	mMoon.setColor(LLColor3(1.0f, 1.0f, 1.0f));
+LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
+{
+	pipeline->allocDrawable(this);
+	mDrawable->setLit(FALSE);
 
-	mSun.renewDirection();
-	mSun.renewColor();
-	mMoon.renewDirection();
-	mMoon.renewColor();
+	LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
+	poolp->setSkyTex(mSkyTex);
+	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
 
-	float dp = getToSunLast() * LLVector3(0,0,1.f);
-	if (dp < 0)
+	for (S32 i = 0; i < NUM_CUBEMAP_FACES; ++i)
 	{
-		dp = 0;
+		mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
 	}
 
-	// Since WL scales everything by 2, there should always be at least a 2:1 brightness ratio
-	// between sunlight and point lights in windlight to normalize point lights.
-	F32 sun_dynamic_range = llmax(gSavedSettings.getF32("RenderSunDynamicRange"), 0.0001f);
-	LLWLParamManager::getInstance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp);
+	mFace[FACE_SUN]   = mDrawable->addFace(poolp, nullptr);
+	mFace[FACE_MOON]  = mDrawable->addFace(poolp, nullptr);
+	mFace[FACE_BLOOM] = mDrawable->addFace(poolp, nullptr);
 
-	mSunDiffuse = vary_SunlightColor;
-	mSunAmbient = vary_AmbientColor;
-	mMoonDiffuse = vary_SunlightColor;
-	mMoonAmbient = vary_AmbientColor;
+	mFace[FACE_SUN]->setMediaAllowed(false);
+	mFace[FACE_MOON]->setMediaAllowed(false);
+	mFace[FACE_BLOOM]->setMediaAllowed(false);
 
-	mTotalAmbient = vary_AmbientColor;
-	mTotalAmbient.setAlpha(1);
-	
-	mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
-	mFadeColor.setAlpha(0);
+	return mDrawable;
 }
 
-void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time)
+void LLVOSky::setSunScale(F32 sun_scale)
 {
+    mSunScale  = sun_scale;
 }
 
-BOOL LLVOSky::updateSky()
+void LLVOSky::setMoonScale(F32 moon_scale)
 {
-	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
-	{
-		return TRUE;
+    mMoonScale = moon_scale;
 	}
 	
-	if (mDead)
-	{
-		// It's dead.  Don't update it.
-		return TRUE;
-	}
-	if (gGLManager.mIsDisabled)
-	{
-		return TRUE;
-	}
+void LLVOSky::setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next)
+	{
+    // We test the UUIDs here because we explicitly do not want the default image returned by getFetchedTexture in that case...
+    mSunTexturep[0] = sun_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+    mSunTexturep[1] = sun_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(sun_texture_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
 
-	static S32 next_frame = 0;
-	const S32 total_no_tiles = 6 * NUM_TILES;
-	const S32 cycle_frame_no = total_no_tiles + 1;
+    bool can_use_wl = gPipeline.canUseWindLightShaders();
 
-	if (mUpdateTimer.getElapsedTimeF32() > 0.001f)
+    if (mFace[FACE_SUN])
 	{
-		mUpdateTimer.reset();
-		const S32 frame = next_frame;
-
-		++next_frame;
-		next_frame = next_frame % cycle_frame_no;
+        if (mSunTexturep[0])
+		{
+	        mSunTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+        }
 
-		mInterpVal = (!mInitialized) ? 1 : (F32)next_frame / cycle_frame_no;
-		// sInterpVal = (F32)next_frame / cycle_frame_no;
-		LLSkyTex::setInterpVal( mInterpVal );
-		LLHeavenBody::setInterpVal( mInterpVal );
-		calcAtmospherics();
+        LLViewerTexture* current_tex0 = mFace[FACE_SUN]->getTexture(LLRender::DIFFUSE_MAP);
+        LLViewerTexture* current_tex1 = mFace[FACE_SUN]->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP);
 
-		if (mForceUpdate || total_no_tiles == frame)
-		{
-			LLSkyTex::stepCurrent();
-			
-			const static F32 LIGHT_DIRECTION_THRESHOLD = (F32) cos(DEG_TO_RAD * 1.f);
-			const static F32 COLOR_CHANGE_THRESHOLD = 0.01f;
-
-			LLVector3 direction = mSun.getDirection();
-			direction.normalize();
-			const F32 dot_lighting = direction * mLastLightingDirection;
-
-			LLColor3 delta_color;
-			delta_color.setVec(mLastTotalAmbient.mV[0] - mTotalAmbient.mV[0],
-							   mLastTotalAmbient.mV[1] - mTotalAmbient.mV[1],
-							   mLastTotalAmbient.mV[2] - mTotalAmbient.mV[2]);
-
-			if ( mForceUpdate 
-				 || (((dot_lighting < LIGHT_DIRECTION_THRESHOLD)
-				 || (delta_color.length() > COLOR_CHANGE_THRESHOLD)
-				 || !mInitialized)
-				&& !direction.isExactlyZero()))
+        if (current_tex0 && (mSunTexturep[0] != current_tex0) && current_tex0->isViewerMediaTexture())
 			{
-				mLastLightingDirection = direction;
-				mLastTotalAmbient = mTotalAmbient;
-				mInitialized = TRUE;
+            static_cast<LLViewerMediaTexture*>(current_tex0)->removeMediaFromFace(mFace[FACE_SUN]);
+        }
 
-				if (mCubeMap)
+        if (current_tex1 && (mSunTexturep[1] != current_tex1) && current_tex1->isViewerMediaTexture())
 				{
-                    if (mForceUpdate)
-					{
-						updateFog(LLViewerCamera::getInstance()->getFar());
-						for (int side = 0; side < 6; side++) 
-						{
-							for (int tile = 0; tile < NUM_TILES; tile++) 
-							{
-								createSkyTexture(side, tile);
-							}
+            static_cast<LLViewerMediaTexture*>(current_tex1)->removeMediaFromFace(mFace[FACE_SUN]);
 						}
 
-						calcAtmospherics();
+        mFace[FACE_SUN]->setTexture(LLRender::DIFFUSE_MAP, mSunTexturep[0]);
 
-						for (int side = 0; side < 6; side++) 
+        if (can_use_wl)
+        {
+            if (mSunTexturep[1])
 						{
-							LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE);
-							LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE);
-							raw2->copy(raw1);
-							mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE));
-
-							raw1 = mShinyTex[side].getImageRaw(TRUE);
-							raw2 = mShinyTex[side].getImageRaw(FALSE);
-							raw2->copy(raw1);
-							mShinyTex[side].createGLImage(mShinyTex[side].getWhich(FALSE));
+	            mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);            
 						}
-						next_frame = 0;	
+            mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]);
 					}
 				}
 			}
 
-			/// *TODO really, sky texture and env map should be shared on a single texture
-			/// I'll let Brad take this at some point
-
-			// update the sky texture
-			for (S32 i = 0; i < 6; ++i)
+void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next)
 			{
-				mSkyTex[i].create(1.0f);
-				mShinyTex[i].create(1.0f);
-			}
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 			
-			// update the environment map
-			if (mCubeMap)
-			{
-				std::vector<LLPointer<LLImageRaw> > images;
-				images.reserve(6);
-				for (S32 side = 0; side < 6; side++)
-				{
-					images.push_back(mShinyTex[side].getImageRaw(TRUE));
-				}
-				mCubeMap->init(images);
-				gGL.getTexUnit(0)->disable();
-			}
+    bool can_use_wl = gPipeline.canUseWindLightShaders();
 
-			gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
-			// *TODO: decide whether we need to update the stars vertex buffer in LLVOWLSky -Brad.
-			//gPipeline.markRebuild(gSky.mVOWLSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+    mMoonTexturep[0] = moon_texture.isNull()      ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+    mMoonTexturep[1] = moon_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(moon_texture_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
 
-			mForceUpdate = FALSE;
-		}
-		else
+    if (mFace[FACE_MOON])
+    {
+        if (mMoonTexturep[0])
 		{
-			const S32 side = frame / NUM_TILES;
-			const S32 tile = frame % NUM_TILES;
-			createSkyTexture(side, tile);
-		}
+	        mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
 	}
+        mFace[FACE_MOON]->setTexture(LLRender::DIFFUSE_MAP, mMoonTexturep[0]);
 
-	if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
+        if (mMoonTexturep[1] && can_use_wl)
 	{
-		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+	        mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
+            mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]);
 	}
-	return TRUE;
-}
-
-void LLVOSky::updateTextures()
-{
-	if (mSunTexturep)
-	{
-		mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
-		mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
-		mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
 	}
 }
 
-LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
+void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next)
 {
-	pipeline->allocDrawable(this);
-	mDrawable->setLit(FALSE);
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-	LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
-	poolp->setSkyTex(mSkyTex);
-	mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY);
+    mCloudNoiseTexturep[0] = cloud_noise_texture.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+    mCloudNoiseTexturep[1] = cloud_noise_texture_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(cloud_noise_texture_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
 	
-	for (S32 i = 0; i < 6; ++i)
+    if (mCloudNoiseTexturep[0])
 	{
-		mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
+	    mCloudNoiseTexturep[0]->setAddressMode(LLTexUnit::TAM_WRAP);
 	}
 
-	mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
-	mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
-	mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
-
-	return mDrawable;
+    if (mCloudNoiseTexturep[1])
+    {
+	    mCloudNoiseTexturep[1]->setAddressMode(LLTexUnit::TAM_WRAP);
+    }
 }
 
-//by bao
-//fake vertex buffer updating
-//to guarantee at least updating one VBO buffer every frame
-//to walk around the bug caused by ATI card --> DEV-3855
-//
-void LLVOSky::createDummyVertexBuffer()
+void LLVOSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next)
 {
-	if(!mFace[FACE_DUMMY])
-	{
-		LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
-		mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL);
-	}
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
 
-	if(!mFace[FACE_DUMMY]->getVertexBuffer())
-	{
-		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB);
-		buff->allocateBuffer(1, 1, TRUE);
-		mFace[FACE_DUMMY]->setVertexBuffer(buff);
-	}
-}
+    LLUUID bloom_tex = bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture;
+    LLUUID bloom_tex_next = bloom_texture_next.isNull() ? (bloom_texture.isNull() ? psky->GetDefaultBloomTextureId() : bloom_texture) : bloom_texture_next;
 
-static LLTrace::BlockTimerStatHandle FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update");
+    mBloomTexturep[0] = bloom_tex.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
+    mBloomTexturep[1] = bloom_tex_next.isNull() ? nullptr : LLViewerTextureManager::getFetchedTexture(bloom_tex_next, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI);
 
-void LLVOSky::updateDummyVertexBuffer()
+    if (mBloomTexturep[0])
 {	
-	if(!LLVertexBuffer::sEnableVBOs)
-		return ;
+	    mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+    }
 
-	if(mHeavenlyBodyUpdated)
+    if (mBloomTexturep[1])
 	{
-		mHeavenlyBodyUpdated = FALSE ;
-		return ;
+	    mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
+    }
 	}
 
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_FAKE_VBO_UPDATE) ;
-
-	if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer())
-		createDummyVertexBuffer() ;
-
-	LLStrider<LLVector3> vertices ;
-	mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices,  0);
-	*vertices = mCameraPosAgent ;
-	mFace[FACE_DUMMY]->getVertexBuffer()->flush();
-}
-//----------------------------------
-//end of fake vertex buffer updating
-//----------------------------------
 static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry");
 
 BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
@@ -1260,13 +1011,14 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	if (mFace[FACE_REFLECTION] == NULL)
 	{
 		LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
-		if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() != 0)
+		if (gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() != 0)
 		{
 			mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL);
 		}
 	}
 
 	mCameraPosAgent = drawable->getPositionAgent();
+
 	mEarthCenter.mV[0] = mCameraPosAgent.mV[0];
 	mEarthCenter.mV[1] = mCameraPosAgent.mV[1];
 
@@ -1286,7 +1038,7 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	U16 index_offset;
 	LLFace *face;	
 
-	for (S32 side = 0; side < 6; ++side)
+	for (S32 side = 0; side < NUM_CUBEMAP_FACES; ++side)
 	{
 		face = mFace[FACE_SIDE0 + side]; 
 
@@ -1341,63 +1093,39 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	right.normalize();
 	up.normalize();
 
-	const static F32 elevation_factor = 0.0f/sResolution;
-	const F32 cos_max_angle = cosHorizon(elevation_factor);
-	mSun.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_SUN, TRUE, mSun, cos_max_angle, up, right));
-	mMoon.setDraw(updateHeavenlyBodyGeometry(drawable, FACE_MOON, FALSE, mMoon, cos_max_angle, up, right));
+    bool draw_sun  = updateHeavenlyBodyGeometry(drawable, mSunScale, FACE_SUN, mSun, up, right);
+    bool draw_moon = updateHeavenlyBodyGeometry(drawable, mMoonScale, FACE_MOON, mMoon, up, right);
+
+    draw_sun  &= LLEnvironment::getInstance()->getIsSunUp();
+    draw_moon &= LLEnvironment::getInstance()->getIsMoonUp();
+
+	mSun.setDraw(draw_sun);
+	mMoon.setDraw(draw_moon);
 
 	const F32 water_height = gAgent.getRegion()->getWaterHeight() + 0.01f;
 		// LLWorld::getInstance()->getWaterHeight() + 0.01f;
 	const F32 camera_height = mCameraPosAgent.mV[2];
 	const F32 height_above_water = camera_height - water_height;
 
-	BOOL sun_flag = FALSE;
-
+	bool sun_flag = FALSE;
 	if (mSun.isVisible())
 	{
-		if (mMoon.isVisible())
-		{
-			sun_flag = look_at * mSun.getDirection() > 0;
-		}
-		else
-		{
-			sun_flag = TRUE;
+        sun_flag = !mMoon.isVisible() || ((look_at * mSun.getDirection()) > 0);
 		}
-	}
-	
-	if (height_above_water > 0)
-	{
-		BOOL render_ref = gPipeline.getPool(LLDrawPool::POOL_WATER)->getVertexShaderLevel() == 0;
 
-		if (sun_flag)
-		{
-			setDrawRefl(0);
+    bool above_water = (height_above_water > 0);
+    bool render_ref  = above_water && gPipeline.getPool(LLDrawPool::POOL_WATER)->getShaderLevel() == 0;
+    setDrawRefl(above_water ? (sun_flag ? 0 : 1) : -1);
 			if (render_ref)
 			{
 				updateReflectionGeometry(drawable, height_above_water, mSun);
 			}
-		}
-		else
-		{
-			setDrawRefl(1);
-			if (render_ref)
-			{
-				updateReflectionGeometry(drawable, height_above_water, mMoon);
-			}
-		}
-	}
-	else
-	{
-		setDrawRefl(-1);
-	}
 
 	LLPipeline::sCompiles++;
 	return TRUE;
 }
 
-BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, const BOOL is_sun,
-										 LLHeavenBody& hb, const F32 cos_max_angle,
-										 const LLVector3 &up, const LLVector3 &right)
+bool LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 f, LLHeavenBody& hb, const LLVector3 &up, const LLVector3 &right)
 {
 	mHeavenlyBodyUpdated = TRUE ;
 
@@ -1408,52 +1136,39 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 	S32 index_offset;
 	LLFace *facep;
 
-	LLVector3 to_dir = hb.getDirection();
 
-	if (!is_sun)
+    LLQuaternion rot    = hb.getRotation();
+	LLVector3 to_dir    = LLVector3::x_axis * rot;
+
+    LLVector3 hb_right = to_dir % LLVector3::z_axis;
+	LLVector3 hb_up    = hb_right % to_dir;
+
+    // at zenith so math below fails spectacularly
+    if ((to_dir * LLVector3::z_axis) > 0.99f)
 	{
-		to_dir.mV[2] = llmax(to_dir.mV[2]+0.1f, 0.1f);
+        hb_right  = LLVector3::y_axis_neg * rot;
+	    hb_up     = LLVector3::z_axis     * rot;
 	}
-	LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
 
+	LLVector3 draw_pos = to_dir * HEAVENLY_BODY_DIST;
 
-	LLVector3 hb_right = to_dir % LLVector3::z_axis;
-	LLVector3 hb_up = hb_right % to_dir;
 	hb_right.normalize();
 	hb_up.normalize();
 
-	//const static F32 cos_max_turn = sqrt(3.f) / 2; // 30 degrees
-	//const F32 cos_turn_right = 1. / (llmax(cos_max_turn, hb_right * right));
-	//const F32 cos_turn_up = 1. / llmax(cos_max_turn, hb_up * up);
-
 	const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
 	F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
 	F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
 
-	// Parameters for the water reflection
-	hb.setU(HEAVENLY_BODY_FACTOR * horiz_enlargement * hb.getDiskRadius() * hb_right);
-	hb.setV(HEAVENLY_BODY_FACTOR * vert_enlargement * hb.getDiskRadius() * hb_up);
-	// End of parameters for the water reflection
-
-	const LLVector3 scaled_right = HEAVENLY_BODY_DIST * hb.getU();
-	const LLVector3 scaled_up = HEAVENLY_BODY_DIST * hb.getV();
+	const LLVector3 scaled_right = horiz_enlargement * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_right;
+	const LLVector3 scaled_up    = vert_enlargement  * scale * HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR * hb.getDiskRadius() * hb_up;
 
-	//const LLVector3 scaled_right = horiz_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_right;//right;
-	//const LLVector3 scaled_up = vert_enlargement * HEAVENLY_BODY_SCALE * hb.getDiskRadius() * hb_up;//up;
 	LLVector3 v_clipped[4];
 
-	hb.corner(0) = draw_pos - scaled_right + scaled_up;
-	hb.corner(1) = draw_pos - scaled_right - scaled_up;
-	hb.corner(2) = draw_pos + scaled_right + scaled_up;
-	hb.corner(3) = draw_pos + scaled_right - scaled_up;
+	v_clipped[0] = draw_pos - scaled_right + scaled_up;
+	v_clipped[1] = draw_pos - scaled_right - scaled_up;
+	v_clipped[2] = draw_pos + scaled_right + scaled_up;
+	v_clipped[3] = draw_pos + scaled_right - scaled_up;
 
-
-	F32 t_left, t_right;
-	if (!clip_quad_to_horizon(t_left, t_right, v_clipped, hb.corners(), cos_max_angle))
-	{
-		hb.setVisible(FALSE);
-		return FALSE;
-	}
 	hb.setVisible(TRUE);
 
 	facep = mFace[f]; 
@@ -1503,164 +1218,9 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 
 	facep->getVertexBuffer()->flush();
 
-	if (is_sun)
-	{
-		if ((t_left > 0) && (t_right > 0))
-		{
-			F32 t = (t_left + t_right) * 0.5f;
-			mSun.setHorizonVisibility(0.5f * (1 + cos(t * F_PI)));
-		}
-		else
-		{
-			mSun.setHorizonVisibility();
-		}
-		updateSunHaloGeometry(drawable);
-	}
-
-	return TRUE;
-}
-
-
-
-
-// Clips quads with top and bottom sides parallel to horizon.
-
-BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
-						  const LLVector3 v_corner[4], const F32 cos_max_angle)
-{
-	t_left = clip_side_to_horizon(v_corner[1], v_corner[0], cos_max_angle);
-	t_right = clip_side_to_horizon(v_corner[3], v_corner[2], cos_max_angle);
-
-	if ((t_left >= 1) || (t_right >= 1))
-	{
-		return FALSE;
-	}
-
-	//const BOOL left_clip = (t_left > 0);
-	//const BOOL right_clip = (t_right > 0);
-
-	//if (!left_clip && !right_clip)
-	{
-		for (S32 vtx = 0; vtx < 4; ++vtx)
-		{
-			v_clipped[vtx]  = v_corner[vtx];
-		}
-	}
-/*	else
-	{
-		v_clipped[0] = v_corner[0];
-		v_clipped[1] = left_clip ? ((1 - t_left) * v_corner[1] + t_left * v_corner[0])
-									: v_corner[1];
-		v_clipped[2] = v_corner[2];
-		v_clipped[3] = right_clip ? ((1 - t_right) * v_corner[3] + t_right * v_corner[2])
-									: v_corner[3];
-	}*/
-
 	return TRUE;
 }
 
-
-F32 clip_side_to_horizon(const LLVector3& V0, const LLVector3& V1, const F32 cos_max_angle)
-{
-	const LLVector3 V = V1 - V0;
-	const F32 k2 = 1.f/(cos_max_angle * cos_max_angle) - 1;
-	const F32 A = V.mV[0] * V.mV[0] + V.mV[1] * V.mV[1] - k2 * V.mV[2] * V.mV[2];
-	const F32 B = V0.mV[0] * V.mV[0] + V0.mV[1] * V.mV[1] - k2 * V0.mV[2] * V.mV[2];
-	const F32 C = V0.mV[0] * V0.mV[0] + V0.mV[1] * V0.mV[1] - k2 * V0.mV[2] * V0.mV[2];
-
-	if (fabs(A) < 1e-7)
-	{
-		return -0.1f;	// v0 is cone origin and v1 is on the surface of the cone.
-	}
-
-	const F32 det = sqrt(B*B - A*C);
-	const F32 t1 = (-B - det) / A;
-	const F32 t2 = (-B + det) / A;
-	const F32 z1 = V0.mV[2] + t1 * V.mV[2];
-	const F32 z2 = V0.mV[2] + t2 * V.mV[2];
-	if (z1 * cos_max_angle < 0)
-	{
-		return t2;
-	}
-	else if (z2 * cos_max_angle < 0)
-	{
-		return t1;
-	}
-	else if ((t1 < 0) || (t1 > 1))
-	{
-		return t2;
-	}
-	else
-	{
-		return t1;
-	}
-}
-
-
-void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable )
-{
-#if 0
-	const LLVector3* v_corner = mSun.corners();
-
-	LLStrider<LLVector3> verticesp;
-	LLStrider<LLVector3> normalsp;
-	LLStrider<LLVector2> texCoordsp;
-	LLStrider<U16> indicesp;
-	S32 index_offset;
-	LLFace *face;
-
-	const LLVector3 right = 2 * (v_corner[2] - v_corner[0]);
-	LLVector3 up = 2 * (v_corner[2] - v_corner[3]);
-	up.normalize();
-	F32 size = right.length();
-	up = size * up;
-	const LLVector3 draw_pos = 0.25 * (v_corner[0] + v_corner[1] + v_corner[2] + v_corner[3]);
-	
-	LLVector3 v_glow_corner[4];
-
-	v_glow_corner[0] = draw_pos - right + up;
-	v_glow_corner[1] = draw_pos - right - up;
-	v_glow_corner[2] = draw_pos + right + up;
-	v_glow_corner[3] = draw_pos + right - up;
-
-	face = mFace[FACE_BLOOM]; 
-
-	if (face->mVertexBuffer.isNull())
-	{
-		face->setSize(4, 6);
-		face->setGeomIndex(0);
-		face->setIndicesIndex(0);
-		face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-		face->mVertexBuffer->allocateBuffer(4, 6, TRUE);
-	}
-
-	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
-	if (-1 == index_offset)
-	{
-		return;
-	}
-
-	for (S32 vtx = 0; vtx < 4; ++vtx)
-	{
-		*(verticesp++)  = v_glow_corner[vtx] + mCameraPosAgent;
-	}
-
-	*(texCoordsp++) = TEX01;
-	*(texCoordsp++) = TEX00;
-	*(texCoordsp++) = TEX11;
-	*(texCoordsp++) = TEX10;
-
-	*indicesp++ = index_offset + 0;
-	*indicesp++ = index_offset + 2;
-	*indicesp++ = index_offset + 1;
-
-	*indicesp++ = index_offset + 1;
-	*indicesp++ = index_offset + 2;
-	*indicesp++ = index_offset + 3;
-#endif
-}
-
-
 F32 dtReflection(const LLVector3& p, F32 cos_dir_from_top, F32 sin_dir_from_top, F32 diff_angl_dir)
 {
 	LLVector3 P = p;
@@ -1722,9 +1282,6 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 	LLVector3 look_at_right = look_at % LLVector3::z_axis;
 	look_at_right.normalize();
 
-	const static F32 cos_horizon_angle = cosHorizon(0.0f/sResolution);
-	//const static F32 horizon_angle = acos(cos_horizon_angle);
-
 	const F32 enlargm_factor = ( 1 - to_dir.mV[2] );
 	F32 horiz_enlargement = 1 + enlargm_factor * 0.3f;
 	F32 vert_enlargement = 1 + enlargm_factor * 0.2f;
@@ -1739,22 +1296,10 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 	LLVector3 top_hb = v_corner[0] = stretch_corner[0] = hb_pos - Right + Up;
 	v_corner[1] = stretch_corner[1] = hb_pos - Right - Up;
 
-	F32 dt_hor, dt;
-	dt_hor = clip_side_to_horizon(v_corner[1], v_corner[0], cos_horizon_angle);
-
 	LLVector2 TEX0t = TEX00;
 	LLVector2 TEX1t = TEX10;
 	LLVector3 lower_corner = v_corner[1];
 
-	if ((dt_hor > 0) && (dt_hor < 1))
-	{
-		TEX0t = LLVector2(0, dt_hor);
-		TEX1t = LLVector2(1, dt_hor);
-		lower_corner = (1 - dt_hor) * v_corner[1] + dt_hor * v_corner[0];
-	}
-	else
-		dt_hor = llmax(0.0f, llmin(1.0f, dt_hor));
-
 	top_hb.normalize();
 	const F32 cos_angle_of_view = fabs(top_hb.mV[VZ]);
 	const F32 extension = llmin (5.0f, 1.0f / cos_angle_of_view);
@@ -1766,9 +1311,6 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 	stretch_corner[0] = lower_corner + extension * (stretch_corner[0] - lower_corner);
 	stretch_corner[1] = lower_corner + extension * (stretch_corner[1] - lower_corner);
 
-	dt = dt_hor;
-
-
 	F32 cos_dir_from_top[2];
 
 	LLVector3 dir = stretch_corner[0];
@@ -1857,9 +1399,8 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 
 		F32 dt_tex = dtReflection(P, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
 
-		dt = dt_tex;
-		TEX0tt = LLVector2(0, dt);
-		TEX1tt = LLVector2(1, dt);
+		TEX0tt = LLVector2(0, dt_tex);
+		TEX1tt = LLVector2(1, dt_tex);
 		quads++;
 	}
 	else
@@ -1870,6 +1411,8 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 
 	LLFace *face = mFace[FACE_REFLECTION]; 
 
+    if (face)
+    {
 	if (!face->getVertexBuffer() || quads*4 != face->getGeomCount())
 	{
 		face->setSize(quads * 4, quads * 6);
@@ -1906,7 +1449,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 	const F32 attenuation = min_attenuation
 		+ cos_angle_of_view * (max_attenuation - min_attenuation);
 
-	LLColor4 hb_refl_col = (1-attenuation) * hb_col + attenuation * mFogColor;
+        LLColor4 hb_refl_col = (1 - attenuation) * hb_col + attenuation * getSkyFogColor();
 	face->setFaceColor(hb_refl_col);
 	
 	LLVector3 v_far[2];
@@ -1981,8 +1524,6 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 		left *= raws_inv;
 		right *= raws_inv;
 
-		F32 dt_raw = dt;
-
 		for (S32 raw = 0; raw < raws; ++raw)
 		{
 			F32 dt_v0 = raw * raws_inv;
@@ -1991,8 +1532,7 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 			const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
 			const LLVector3 EL = BL + left;
 			const LLVector3 ER = BR + right;
-			dt_v0 = dt_raw;
-			dt_raw = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
+                dt_v0 = dt_v1 = dtReflection(EL, cos_dir_from_top[0], sin_dir_from_top, diff_angl_dir);
 			for (S32 col = 0; col < cols; ++col)
 			{
 				F32 dt_h0 = col * cols_inv;
@@ -2022,256 +1562,65 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 
 	face->getVertexBuffer()->flush();
 }
-
-
-
+}
 
 void LLVOSky::updateFog(const F32 distance)
 {
-	if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG))
+    LLEnvironment& environment = LLEnvironment::instance();
+    if (environment.getCurrentSky() != nullptr)
 	{
-		if (!LLGLSLShader::sNoFixedFunction)
-		{
-			glFogf(GL_FOG_DENSITY, 0);
-			glFogfv(GL_FOG_COLOR, (F32 *) &LLColor4::white.mV);
-			glFogf(GL_FOG_END, 1000000.f);
+        LLVector3 light_dir = LLVector3(environment.getClampedLightNorm());
+        m_legacyAtmospherics.updateFog(distance, light_dir);
 		}
-		return;
 	}
 
-	const BOOL hide_clip_plane = TRUE;
-	LLColor4 target_fog(0.f, 0.2f, 0.5f, 0.f);
-
-	const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f;
-	// LLWorld::getInstance()->getWaterHeight();
-	F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2];
-
-	F32 near_clip_height = LLViewerCamera::getInstance()->getAtAxis().mV[VZ] * LLViewerCamera::getInstance()->getNear();
-	camera_height += near_clip_height;
-
-	F32 fog_distance = 0.f;
-	LLColor3 res_color[3];
-
-	LLColor3 sky_fog_color = LLColor3::white;
-	LLColor3 render_fog_color = LLColor3::white;
-
-	LLVector3 tosun = getToSunLast();
-	const F32 tosun_z = tosun.mV[VZ];
-	tosun.mV[VZ] = 0.f;
-	tosun.normalize();
-	LLVector3 perp_tosun;
-	perp_tosun.mV[VX] = -tosun.mV[VY];
-	perp_tosun.mV[VY] = tosun.mV[VX];
-	LLVector3 tosun_45 = tosun + perp_tosun;
-	tosun_45.normalize();
-
-	F32 delta = 0.06f;
-	tosun.mV[VZ] = delta;
-	perp_tosun.mV[VZ] = delta;
-	tosun_45.mV[VZ] = delta;
-	tosun.normalize();
-	perp_tosun.normalize();
-	tosun_45.normalize();
-
-	// Sky colors, just slightly above the horizon in the direction of the sun, perpendicular to the sun, and at a 45 degree angle to the sun.
-	initAtmospherics();
-	res_color[0] = calcSkyColorInDir(tosun);
-	res_color[1] = calcSkyColorInDir(perp_tosun);
-	res_color[2] = calcSkyColorInDir(tosun_45);
-
-	sky_fog_color = color_norm(res_color[0] + res_color[1] + res_color[2]);
-
-	F32 full_off = -0.25f;
-	F32 full_on = 0.00f;
-	F32 on = (tosun_z - full_off) / (full_on - full_off);
-	on = llclamp(on, 0.01f, 1.f);
-	sky_fog_color *= 0.5f * on;
-
-
-	// We need to clamp these to non-zero, in order for the gamma correction to work. 0^y = ???
-	S32 i;
-	for (i = 0; i < 3; i++)
+void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr)
 	{
-		sky_fog_color.mV[i] = llmax(0.0001f, sky_fog_color.mV[i]);
-	}
-
-	color_gamma_correct(sky_fog_color);
-
-	render_fog_color = sky_fog_color;
+    mSun.setDirection(sun_dir_cfr);	
+	mMoon.setDirection(moon_dir_cfr);
 
-	F32 fog_density = 0.f;
-	fog_distance = mFogRatio * distance;
-	
-	if (camera_height > water_height)
+	// Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
+	// on the upward facing faces of cubes.
 	{
-		LLColor4 fog(render_fog_color);
-		if (!LLGLSLShader::sNoFixedFunction)
-		{
-			glFogfv(GL_FOG_COLOR, fog.mV);
-		}
-		mGLFogCol = fog;
+	    // Same as dot product with the up direction + clamp.
+	    F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
+	    sunDot *= sunDot;	
 
-		if (hide_clip_plane)
-		{
-			// For now, set the density to extend to the cull distance.
-			const F32 f_log = 2.14596602628934723963618357029f; // sqrt(fabs(log(0.01f)))
-			fog_density = f_log/fog_distance;
-			if (!LLGLSLShader::sNoFixedFunction)
-			{
-				glFogi(GL_FOG_MODE, GL_EXP2);
-			}
-		}
-		else
-		{
-			const F32 f_log = 4.6051701859880913680359829093687f; // fabs(log(0.01f))
-			fog_density = (f_log)/fog_distance;
-			if (!LLGLSLShader::sNoFixedFunction)
-			{
-				glFogi(GL_FOG_MODE, GL_EXP);
-			}
-		}
-	}
-	else
-	{
-		F32 depth = water_height - camera_height;
-		
-		// get the water param manager variables
-		float water_fog_density = LLWaterParamManager::getInstance()->getFogDensity();
-		LLColor4 water_fog_color(LLDrawPoolWater::sWaterFogColor.mV);
+	    // Create normalized vector that has the sunDir pushed south about an hour and change.
+	    LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
 		
-		// adjust the color based on depth.  We're doing linear approximations
-		float depth_scale = gSavedSettings.getF32("WaterGLFogDepthScale");
-		float depth_modifier = 1.0f - llmin(llmax(depth / depth_scale, 0.01f), 
-			gSavedSettings.getF32("WaterGLFogDepthFloor"));
-
-		LLColor4 fogCol = water_fog_color * depth_modifier;
-		fogCol.setAlpha(1);
-
-		// set the gl fog color
-		mGLFogCol = fogCol;
-
-		// set the density based on what the shaders use
-		fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale");
-
-		if (!LLGLSLShader::sNoFixedFunction)
-		{
-			glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
-			glFogi(GL_FOG_MODE, GL_EXP2);
-		}
-	}
-
-	mFogColor = sky_fog_color;
-	mFogColor.setAlpha(1);
-	LLDrawPoolWater::sWaterFogEnd = fog_distance*2.2f;
-
-	if (!LLGLSLShader::sNoFixedFunction)
-	{
-		LLGLSFog gls_fog;
-		glFogf(GL_FOG_END, fog_distance*2.2f);
-		glFogf(GL_FOG_DENSITY, fog_density);
-		glHint(GL_FOG_HINT, GL_NICEST);
-	}
-	stop_glerror();
-}
-
-
-// Functions used a lot.
-F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
-{
-	F32 mv = color_max(col);
-	if (0 == mv)
-	{
-		return 0;
-	}
-
-	col *= 1.f / mv;
-	color_pow(col, e);
-	if (postmultiply)
-	{
-		col *= mv;
-	}
-	return mv;
-}
-
-// Returns angle (RADIANs) between the horizontal projection of "v" and the x_axis.
-// Range of output is 0.0f to 2pi //359.99999...f
-// Returns 0.0f when "v" = +/- z_axis.
-F32 azimuth(const LLVector3 &v)
-{
-	F32 azimuth = 0.0f;
-	if (v.mV[VX] == 0.0f)
-	{
-		if (v.mV[VY] > 0.0f)
-		{
-			azimuth = F_PI * 0.5f;
-		}
-		else if (v.mV[VY] < 0.0f)
-		{
-			azimuth = F_PI * 1.5f;// 270.f;
+	    // Blend between normal sun dir and adjusted sun dir based on how close we are
+	    // to having the sun overhead.
+	    mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot);
+	    mBumpSunDir.normalize();
 		}
+	updateDirections();
 	}
-	else
-	{
-		azimuth = (F32) atan(v.mV[VY] / v.mV[VX]);
-		if (v.mV[VX] < 0.0f)
-		{
-			azimuth += F_PI;
-		}
-		else if (v.mV[VY] < 0.0f)
-		{
-			azimuth += F_PI * 2;
-		}
-	}	
-	return azimuth;
-}
-
-void LLVOSky::initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
-{
-	LLVector3 sun_direction = (sun_dir.length() == 0) ? LLVector3::x_axis : sun_dir;
-	sun_direction.normalize();
-	mSun.setDirection(sun_direction);
-	mSun.renewDirection();
-	mSun.setAngularVelocity(sun_ang_velocity);
-	mMoon.setDirection(-mSun.getDirection());
-	mMoon.renewDirection();
-	mLastLightingDirection = mSun.getDirection();
 
-	calcAtmospherics();
-
-	if ( !mInitialized )
+void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr)
 	{
-		init();
-		LLSkyTex::stepCurrent();
-	}		
-}
-
-void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
-{
-	LLVector3 sun_direction = (sun_dir.length() == 0) ? LLVector3::x_axis : sun_dir;
-	sun_direction.normalize();
+    mSun.setDirection(sun_dir_cfr);	
 
 	// Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
 	// on the upward facing faces of cubes.
-	LLVector3 newDir = sun_direction;
-
+    {
 	// Same as dot product with the up direction + clamp.
-	F32 sunDot = llmax(0.f, newDir.mV[2]);
+	    F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
 	sunDot *= sunDot;	
 
 	// Create normalized vector that has the sunDir pushed south about an hour and change.
-	LLVector3 adjustedDir = (newDir + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
+	    LLVector3 adjustedDir = (sun_dir_cfr + LLVector3(0.f, -0.70711f, 0.70711f)) * 0.5f;
 
 	// Blend between normal sun dir and adjusted sun dir based on how close we are
 	// to having the sun overhead.
-	mBumpSunDir = adjustedDir * sunDot + newDir * (1.0f - sunDot);
+	    mBumpSunDir = adjustedDir * sunDot + sun_dir_cfr * (1.0f - sunDot);
 	mBumpSunDir.normalize();
+    }
+	updateDirections();
+}
 
-	F32 dp = mLastLightingDirection * sun_direction;
-	mSun.setDirection(sun_direction);
-	mSun.setAngularVelocity(sun_ang_velocity);
-	mMoon.setDirection(-sun_direction);
-	calcAtmospherics();
-	if (dp < 0.995f) { //the sun jumped a great deal, update immediately
-		mForceUpdate = TRUE;
-	}
+void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr)
+{
+	mMoon.setDirection(moon_dir_cfr);
+	updateDirections();
 }
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 9cfb9773bd8ccb16486e77d3aac7497b851db688..39e42bbb2420c9d185bb398ff1ba9d8ef8d0d898 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -30,86 +30,22 @@
 #include "stdtypes.h"
 #include "v3color.h"
 #include "v4coloru.h"
+#include "llquaternion.h"
 #include "llviewertexture.h"
 #include "llviewerobject.h"
 #include "llframetimer.h"
+#include "v3colorutil.h"
+#include "llsettingssky.h"
+#include "lllegacyatmospherics.h"
 
-
-//////////////////////////////////
-//
-// Lots of constants
-//
-// Will clean these up at some point...
-//
-
-const F32 HORIZON_DIST			= 1024.0f;
 const F32 SKY_BOX_MULT			= 16.0f;
-const F32 HEAVENLY_BODY_DIST		= HORIZON_DIST - 10.f;
+const F32 HEAVENLY_BODY_DIST	= HORIZON_DIST - 20.f;
 const F32 HEAVENLY_BODY_FACTOR	= 0.1f;
 const F32 HEAVENLY_BODY_SCALE	= HEAVENLY_BODY_DIST * HEAVENLY_BODY_FACTOR;
-const F32 EARTH_RADIUS			= 6.4e6f;       // exact radius = 6.37 x 10^6 m
-const F32 ATM_EXP_FALLOFF		= 0.000126f;
-const F32 ATM_SEA_LEVEL_NDENS	= 2.55e25f;
-// Somewhat arbitrary:
-const F32 ATM_HEIGHT			= 100000.f;
-
-const F32 FIRST_STEP = 5000.f;
-const F32 INV_FIRST_STEP = 1.f/FIRST_STEP;
-const S32 NO_STEPS = 15;
-const F32 INV_NO_STEPS = 1.f/NO_STEPS;
-
-
-// constants used in calculation of scattering coeff of clear air
-const F32 sigma		= 0.035f;
-const F32 fsigma	= (6.f + 3.f * sigma) / (6.f-7.f*sigma);
-const F64 Ndens		= 2.55e25;
-const F64 Ndens2	= Ndens*Ndens;
-
-// HACK: Allow server to change sun and moon IDs.
-// I can't figure out how to pass the appropriate
-// information into the LLVOSky constructor.  JC
-extern LLUUID gSunTextureID;
-extern LLUUID gMoonTextureID;
-
-
-LL_FORCE_INLINE LLColor3 color_div(const LLColor3 &col1, const LLColor3 &col2)
-{
-	return LLColor3( 
-		col1.mV[0] / col2.mV[0],
-		col1.mV[1] / col2.mV[1],
-		col1.mV[2] / col2.mV[2] );
-}
-
-LLColor3 color_norm(const LLColor3 &col);
-BOOL clip_quad_to_horizon(F32& t_left, F32& t_right, LLVector3 v_clipped[4],
-						  const LLVector3 v_corner[4], const F32 cos_max_angle);
-F32 clip_side_to_horizon(const LLVector3& v0, const LLVector3& v1, const F32 cos_max_angle);
-
-inline F32 color_intens ( const LLColor3 &col )
-{
-	return col.mV[0] + col.mV[1] + col.mV[2];
-}
-
-inline F32 color_max(const LLColor3 &col)
-{
-	return llmax(col.mV[0], col.mV[1], col.mV[2]);
-}
-
-inline F32 color_max(const LLColor4 &col)
-{
-	return llmax(col.mV[0], col.mV[1], col.mV[2]);
-}
-
-
-inline F32 color_min(const LLColor3 &col)
-{
-	return llmin(col.mV[0], col.mV[1], col.mV[2]);
-}
 
 class LLFace;
 class LLHaze;
 
-
 class LLSkyTex
 {
 	friend class LLVOSky;
@@ -121,33 +57,28 @@ class LLSkyTex
 	LLColor4		*mSkyData;
 	LLVector3		*mSkyDirs;			// Cache of sky direction vectors
 	static S32		sCurrent;
-	static F32		sInterpVal;
 
 public:
-	static F32 getInterpVal()					{ return sInterpVal; }
-	static void setInterpVal(const F32 v)		{ sInterpVal = v; }
-	static BOOL doInterpolate()					{ return sInterpVal > 0.001f; }
-
 	void bindTexture(BOOL curr = TRUE);
 	
 protected:
 	LLSkyTex();
-	void init();
+	void init(bool isShiny);
 	void cleanupGL();
 	void restoreGL();
 
 	~LLSkyTex();
 
 
-	static S32 getResolution()					{ return sResolution; }
-	static S32 getCurrent()						{ return sCurrent; }
-	static S32 stepCurrent()					{ sCurrent++; sCurrent &= 1; return sCurrent; }
-	static S32 getNext()						{ return ((sCurrent+1) & 1); }
-	static S32 getWhich(const BOOL curr)		{ return curr ? sCurrent : getNext(); }
+	static S32 getResolution();
+	static S32 getCurrent();
+	static S32 stepCurrent();
+	static S32 getNext();
+	static S32 getWhich(const BOOL curr);
 
 	void initEmpty(const S32 tex);
 	
-	void create(F32 brightness);
+	void create();
 
 	void setDir(const LLVector3 &dir, const S32 i, const S32 j)
 	{
@@ -183,8 +114,10 @@ class LLSkyTex
 		return col;
 	}
 
-	LLImageRaw* getImageRaw(BOOL curr=TRUE)			{ return mImageRaw[getWhich(curr)]; }
+	LLImageRaw* getImageRaw(BOOL curr=TRUE);
 	void createGLImage(BOOL curr=TRUE);
+
+    bool mIsShiny;
 };
 
 /// TODO Move into the stars draw pool (and rename them appropriately).
@@ -197,244 +130,70 @@ class LLHeavenBody
 	LLColor3		mColorCached;
 	F32				mIntensity;
 	LLVector3		mDirection;				// direction of the local heavenly body
+    LLQuaternion    mRotation;
 	LLVector3		mAngularVelocity;		// velocity of the local heavenly body
 
 	F32				mDiskRadius;
-	BOOL			mDraw;					// FALSE - do not draw.
+	bool			mDraw;					// FALSE - do not draw.
 	F32				mHorizonVisibility;		// number [0, 1] due to how horizon
 	F32				mVisibility;			// same but due to other objects being in throng.
-	BOOL			mVisible;
+	bool			mVisible;
 	static F32		sInterpVal;
 	LLVector3		mQuadCorner[4];
-	LLVector3		mU;
-	LLVector3		mV;
 	LLVector3		mO;
 
 public:
-	LLHeavenBody(const F32 rad) :
-		mDirectionCached(LLVector3(0,0,0)),
-		mDirection(LLVector3(0,0,0)),
-		mIntensity(0.f),
-		mDiskRadius(rad), mDraw(FALSE),
-		mHorizonVisibility(1.f), mVisibility(1.f),
-		mVisible(FALSE)
-	{
-		mColor.setToBlack();
-		mColorCached.setToBlack();
-	}
+	LLHeavenBody(const F32 rad);
 	~LLHeavenBody() {}
 
-	const LLVector3& getDirection()	const				{ return mDirection; }
-	void setDirection(const LLVector3 &direction)		{ mDirection = direction; }
-	void setAngularVelocity(const LLVector3 &ang_vel)	{ mAngularVelocity = ang_vel; }
-	const LLVector3& getAngularVelocity() const			{ return mAngularVelocity; }
-
-	const LLVector3& getDirectionCached() const			{ return mDirectionCached; }
-	void renewDirection()								{ mDirectionCached = mDirection; }
-
-	const LLColor3& getColorCached() const				{ return mColorCached; }
-	void setColorCached(const LLColor3& c)				{ mColorCached = c; }
-	const LLColor3& getColor() const					{ return mColor; }
-	void setColor(const LLColor3& c)					{ mColor = c; }
-
-	void renewColor()									{ mColorCached = mColor; }
-
-	static F32 interpVal()								{ return sInterpVal; }
-	static void setInterpVal(const F32 v)				{ sInterpVal = v; }
-
-	LLColor3 getInterpColor() const
-	{
-		return sInterpVal * mColor + (1 - sInterpVal) * mColorCached;
-	}
-
-	const F32& getHorizonVisibility() const				{ return mHorizonVisibility; }
-	void setHorizonVisibility(const F32 c = 1)			{ mHorizonVisibility = c; }
-	const F32& getVisibility() const					{ return mVisibility; }
-	void setVisibility(const F32 c = 1)					{ mVisibility = c; }
-	F32 getHaloBrighness() const
-	{
-		return llmax(0.f, llmin(0.9f, mHorizonVisibility)) * mVisibility;
-	}
-	BOOL isVisible() const								{ return mVisible; }
-	void setVisible(const BOOL v)						{ mVisible = v; }
-
-	const F32& getIntensity() const						{ return mIntensity; }
-	void setIntensity(const F32 c)						{ mIntensity = c; }
-
-	void setDiskRadius(const F32 radius)				{ mDiskRadius = radius; }
-	F32	getDiskRadius()	const							{ return mDiskRadius; }
-
-	void setDraw(const BOOL draw)						{ mDraw = draw; }
-	BOOL getDraw() const								{ return mDraw; }
+    const LLQuaternion& getRotation() const;
+    void                setRotation(const LLQuaternion& rot);
 
-	const LLVector3& corner(const S32 n) const			{ return mQuadCorner[n]; }
-	LLVector3& corner(const S32 n)						{ return mQuadCorner[n]; }
-	const LLVector3* corners() const					{ return mQuadCorner; }
-
-	const LLVector3& getU() const						{ return mU; }
-	const LLVector3& getV() const						{ return mV; }
-	void setU(const LLVector3& u)						{ mU = u; }
-	void setV(const LLVector3& v)						{ mV = v; }
-};
+	const LLVector3& getDirection()	const;
+	void setDirection(const LLVector3 &direction);
+	void setAngularVelocity(const LLVector3 &ang_vel);
+	const LLVector3& getAngularVelocity() const;
 
+	const LLVector3& getDirectionCached() const;
+	void renewDirection();
 
-LL_FORCE_INLINE LLColor3 refr_ind_calc(const LLColor3 &wave_length)
-{
-	LLColor3 refr_ind;
-	for (S32 i = 0; i < 3; ++i)
-	{
-		const F32 wl2 = wave_length.mV[i] * wave_length.mV[i] * 1e-6f;
-		refr_ind.mV[i] = 6.43e3f + ( 2.95e6f / ( 146.0f - 1.f/wl2 ) ) + ( 2.55e4f / ( 41.0f - 1.f/wl2 ) );
-		refr_ind.mV[i] *= 1.0e-8f;
-		refr_ind.mV[i] += 1.f;
-	}
-	return refr_ind;
-}
-
-
-class LLHaze
-{
-public:
-	LLHaze() : mG(0), mFalloff(1), mAbsCoef(0.f) {mSigSca.setToBlack();}
-	LLHaze(const F32 g, const LLColor3& sca, const F32 fo = 2.f) : 
-			mG(g), mSigSca(0.25f/F_PI * sca), mFalloff(fo), mAbsCoef(0.f)
-	{
-		mAbsCoef = color_intens(mSigSca) / sAirScaIntense;
-	}
-
-	LLHaze(const F32 g, const F32 sca, const F32 fo = 2.f) : mG(g),
-			mSigSca(0.25f/F_PI * LLColor3(sca, sca, sca)), mFalloff(fo)
-	{
-		mAbsCoef = 0.01f * sca / sAirScaAvg;
-	}
-
-	F32 getG() const				{ return mG; }
+	const LLColor3& getColorCached() const;
+	void setColorCached(const LLColor3& c);
+	const LLColor3& getColor() const;
+	void setColor(const LLColor3& c);
 
-	void setG(const F32 g)
-	{
-		mG = g;
-	}
+	void renewColor();
 
-	const LLColor3& getSigSca() const // sea level
-	{
-		return mSigSca;
-	} 
+	static F32 interpVal();
+	static void setInterpVal(const F32 v);
 
-	void setSigSca(const LLColor3& s)
-	{
-		mSigSca = s;
-		mAbsCoef = 0.01f * color_intens(mSigSca) / sAirScaIntense;
-	}
+	LLColor3 getInterpColor() const;
 
-	void setSigSca(const F32 s0, const F32 s1, const F32 s2)
-	{
-		mSigSca = sAirScaAvg * LLColor3 (s0, s1, s2);
-		mAbsCoef = 0.01f * (s0 + s1 + s2) / 3;
-	}
+	const F32& getVisibility() const;
+	void setVisibility(const F32 c = 1);
 
-	F32 getFalloff() const
-	{
-		return mFalloff;
-	}
+	bool isVisible() const;
+	void setVisible(const bool v);
 
-	void setFalloff(const F32 fo)
-	{
-		mFalloff = fo;
-	}
+	const F32& getIntensity() const;
+	void setIntensity(const F32 c);
 
-	F32 getAbsCoef() const
-	{
-		return mAbsCoef;
-	}
+	void setDiskRadius(const F32 radius);
+	F32	getDiskRadius()	const;
 
-	inline static F32 calcFalloff(const F32 h)
-	{
-		return (h <= 0) ? 1.0f : (F32)LL_FAST_EXP(-ATM_EXP_FALLOFF * h);
-	}
+	void setDraw(const bool draw);
+	bool getDraw() const;
 
-	inline LLColor3 calcSigSca(const F32 h) const
-	{
-		return calcFalloff(h * mFalloff) * mSigSca;
-	}
-
-	inline void calcSigSca(const F32 h, LLColor3 &result) const
-	{
-		result = mSigSca;
-		result *= calcFalloff(h * mFalloff);
-	}
-
-	LLColor3 calcSigExt(const F32 h) const
-	{
-		return calcFalloff(h * mFalloff) * (1 + mAbsCoef) * mSigSca;
-	}
-
-	F32 calcPhase(const F32 cos_theta) const;
-
-	static inline LLColor3 calcAirSca(const F32 h);
-	static inline void calcAirSca(const F32 h, LLColor3 &result);
-
-private:
-	static LLColor3 const sAirScaSeaLevel;
-	static F32 const sAirScaIntense;
-	static F32 const sAirScaAvg;
-
-protected:
-	F32			mG;
-	LLColor3	mSigSca;
-	F32			mFalloff;	// 1 - slow, >1 - faster
-	F32			mAbsCoef;
+	const LLVector3& corner(const S32 n) const;
+	LLVector3& corner(const S32 n);
+	const LLVector3* corners() const;
 };
 
-
 class LLCubeMap;
 
-// turn on floating point precision
-// in vs2003 for this class.  Otherwise
-// black dots go everywhere from 7:10 - 8:50
-#if LL_MSVC && __MSVC_VER__ < 8
-#pragma optimize("p", on)		
-#endif
-
-
 class LLVOSky : public LLStaticViewerObject
 {
-public:
-	/// WL PARAMS
-	F32 dome_radius;
-	F32 dome_offset_ratio;
-	LLColor3 sunlight_color;
-	LLColor3 ambient;
-	F32 gamma;
-	LLVector4 lightnorm;
-	LLVector4 unclamped_lightnorm;
-	LLColor3 blue_density;
-	LLColor3 blue_horizon;
-	F32 haze_density;
-	F32 haze_horizon;
-	F32 density_multiplier;
-	F32 max_y;
-	LLColor3 glow;
-	F32 cloud_shadow;
-	LLColor3 cloud_color;
-	F32 cloud_scale;
-	LLColor3 cloud_pos_density1;
-	LLColor3 cloud_pos_density2;
-	
-public:
-	void initAtmospherics(void);
-	void calcAtmospherics(void);
-	LLColor3 createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient);
-	LLColor3 createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient);
-
-	void calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
-							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
-							LLVector2 vary_HorizontalProjection[2]);
-
-	LLColor3 calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor,	LLColor3 & vary_CloudColorSun, 
-							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
-							LLVector2 vary_HorizontalProjection[2]);
-
-public:
+public:	
 	enum
 	{
 		FACE_SIDE0,
@@ -447,7 +206,6 @@ class LLVOSky : public LLStaticViewerObject
 		FACE_MOON, // was 7
 		FACE_BLOOM, // was 8
 		FACE_REFLECTION, // was 10
-		FACE_DUMMY, //for an ATI bug --bao
 		FACE_COUNT
 	};
 	
@@ -461,8 +219,10 @@ class LLVOSky : public LLStaticViewerObject
 	void cleanupGL();
 	void restoreGL();
 
+    void calc();
+
 	/*virtual*/ void idleUpdate(LLAgent &agent, const F64 &time);
-	BOOL updateSky();
+	bool updateSky();
 	
 	// Graphical stuff for objects - maybe broken out into render class
 	// later?
@@ -470,65 +230,31 @@ class LLVOSky : public LLStaticViewerObject
 	/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
 	/*virtual*/ BOOL		updateGeometry(LLDrawable *drawable);
 
-	void initSkyTextureDirs(const S32 side, const S32 tile);
-	void createSkyTexture(const S32 side, const S32 tile);
-
-	LLColor4 calcSkyColorInDir(const LLVector3& dir, bool isShiny = false);
-	
-	LLColor3 calcRadianceAtPoint(const LLVector3& pos) const
-	{
-		F32 radiance = mBrightnessScaleGuess * mSun.getIntensity();
-		return LLColor3(radiance, radiance, radiance);
-	}
-
-	const LLHeavenBody& getSun() const						{ return mSun; }
+	const LLHeavenBody& getSun() const						{ return mSun;  }
 	const LLHeavenBody& getMoon() const						{ return mMoon; }
 
-	const LLVector3& getToSunLast() const					{ return mSun.getDirectionCached(); }
-	const LLVector3& getToSun() const						{ return mSun.getDirection(); }
-	const LLVector3& getToMoon() const						{ return mMoon.getDirection(); }
-	const LLVector3& getToMoonLast() const					{ return mMoon.getDirectionCached(); }
-	BOOL isSunUp() const									{ return mSun.getDirectionCached().mV[2] > -0.05f; }
-	void calculateColors();
-
-	LLColor3 getSunDiffuseColor() const						{ return mSunDiffuse; }
-	LLColor3 getMoonDiffuseColor() const					{ return mMoonDiffuse; }
-	LLColor4 getSunAmbientColor() const						{ return mSunAmbient; }
-	LLColor4 getMoonAmbientColor() const					{ return mMoonAmbient; }
-	const LLColor4& getTotalAmbientColor() const			{ return mTotalAmbient; }
-	LLColor4 getFogColor() const							{ return mFogColor; }
-	LLColor4 getGLFogColor() const							{ return mGLFogCol; }
-	
-	BOOL isSameFace(S32 idx, const LLFace* face) const { return mFace[idx] == face; }
-
-	void initSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity);
-
-	void setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity);
+	bool isSameFace(S32 idx, const LLFace* face) const { return mFace[idx] == face; }
 
-	BOOL updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 side, const BOOL is_sun,
-									LLHeavenBody& hb, const F32 sin_max_angle,
-									const LLVector3 &up, const LLVector3 &right);
+    // directions provided should already be in CFR coord sys (+x at, +z up, +y right)
+    void setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir, const LLVector3 &moon_dir);
+    void setSunDirectionCFR(const LLVector3 &sun_direction);
+    void setMoonDirectionCFR(const LLVector3 &moon_direction);
 
-	F32 cosHorizon(const F32 delta = 0) const
-	{
-		const F32 sin_angle = EARTH_RADIUS/(EARTH_RADIUS + mCameraPosAgent.mV[2]);
-		return delta - (F32)sqrt(1.f - sin_angle * sin_angle);
-	}
-
-	void updateSunHaloGeometry(LLDrawable *drawable);
+	bool updateHeavenlyBodyGeometry(LLDrawable *drawable, F32 scale, const S32 side, LLHeavenBody& hb, const LLVector3 &up, const LLVector3 &right);
 	void updateReflectionGeometry(LLDrawable *drawable, F32 H, const LLHeavenBody& HB);
-
 	
-	const LLHaze& getHaze() const						{ return mHaze; }
-	LLHaze&	getHaze()									{ return mHaze; }
-	F32 getHazeConcentration() const					{ return mHazeConcentration; }
-	void setHaze(const LLHaze& h)						{ mHaze = h; }
 	F32 getWorldScale() const							{ return mWorldScale; }
 	void setWorldScale(const F32 s)						{ mWorldScale = s; }
 	void updateFog(const F32 distance);
-	void setFogRatio(const F32 fog_ratio)				{ mFogRatio = fog_ratio; }
-	LLColor4U getFadeColor() const						{ return mFadeColor; }
-	F32 getFogRatio() const								{ return mFogRatio; }
+
+    void setFogRatio(const F32 fog_ratio)               { m_legacyAtmospherics.setFogRatio(fog_ratio); }
+    F32  getFogRatio() const                            { return m_legacyAtmospherics.getFogRatio(); }
+
+    LLColor4 getSkyFogColor() const                        { return m_legacyAtmospherics.getFogColor(); }
+    LLColor4 getGLFogColor() const                      { return m_legacyAtmospherics.getGLFogColor(); }
+
+    LLColor4U getFadeColor() const;
+
 	void setCloudDensity(F32 cloud_density)				{ mCloudDensity = cloud_density; }
 	void setWind ( const LLVector3& wind )				{ mWind = wind.length(); }
 
@@ -538,24 +264,55 @@ class LLVOSky : public LLStaticViewerObject
 	LLCubeMap *getCubeMap() const						{ return mCubeMap; }
 	S32 getDrawRefl() const								{ return mDrawRefl; }
 	void setDrawRefl(const S32 r)						{ mDrawRefl = r; }
-	BOOL isReflFace(const LLFace* face) const			{ return face == mFace[FACE_REFLECTION]; }
+	bool isReflFace(const LLFace* face) const			{ return face == mFace[FACE_REFLECTION]; }
 	LLFace* getReflFace() const							{ return mFace[FACE_REFLECTION]; }
 
-	LLViewerTexture*	getSunTex() const					{ return mSunTexturep; }
-	LLViewerTexture*	getMoonTex() const					{ return mMoonTexturep; }
-	LLViewerTexture*	getBloomTex() const					{ return mBloomTexturep; }
-	void forceSkyUpdate(void)							{ mForceUpdate = TRUE; }
+	LLViewerTexture*	getSunTex() const				{ return mSunTexturep[0]; }
+	LLViewerTexture*	getMoonTex() const				{ return mMoonTexturep[0]; }
+	LLViewerTexture*	getBloomTex() const			    { return mBloomTexturep[0]; }
+    LLViewerTexture*	getCloudNoiseTex() const		{ return mCloudNoiseTexturep[0]; }
+
+    LLViewerTexture*	getRainbowTex() const			{ return mRainbowMap; }
+    LLViewerTexture*	getHaloTex() const			{ return mHaloMap;  }
+
+    LLViewerTexture*	getSunTexNext() const			{ return mSunTexturep[1]; }
+	LLViewerTexture*	getMoonTexNext() const			{ return mMoonTexturep[1]; }
+	LLViewerTexture*	getBloomTexNext() const			{ return mBloomTexturep[1]; }
+    LLViewerTexture*	getCloudNoiseTexNext() const	{ return mCloudNoiseTexturep[1]; }
+
+    void setSunTextures(const LLUUID& sun_texture, const LLUUID& sun_texture_next);
+    void setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next);
+    void setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next);
+    void setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next);
+
+    void setSunScale(F32 sun_scale);
+    void setMoonScale(F32 sun_scale);
+
+	void forceSkyUpdate(void);
 
 public:
 	LLFace	*mFace[FACE_COUNT];
 	LLVector3	mBumpSunDir;
 
+    F32 getInterpVal() const { return mInterpVal; }
+
 protected:
 	~LLVOSky();
 
-	LLPointer<LLViewerFetchedTexture> mSunTexturep;
-	LLPointer<LLViewerFetchedTexture> mMoonTexturep;
-	LLPointer<LLViewerFetchedTexture> mBloomTexturep;
+	void updateDirections(void);
+
+	void initSkyTextureDirs(const S32 side, const S32 tile);
+	void createSkyTexture(AtmosphericsVars& vars, const S32 side, const S32 tile);
+
+	LLPointer<LLViewerFetchedTexture> mSunTexturep[2];
+	LLPointer<LLViewerFetchedTexture> mMoonTexturep[2];
+    LLPointer<LLViewerFetchedTexture> mCloudNoiseTexturep[2];
+	LLPointer<LLViewerFetchedTexture> mBloomTexturep[2];
+    LLPointer<LLViewerFetchedTexture> mRainbowMap;
+    LLPointer<LLViewerFetchedTexture> mHaloMap;
+
+    F32 mSunScale  = 1.0f;
+    F32 mMoonScale = 1.0f;
 
 	static S32			sResolution;
 	static S32			sTileResX;
@@ -575,73 +332,30 @@ class LLVOSky : public LLStaticViewerObject
 	LLColor3			mBrightestPointNew;
 	F32					mBrightnessScaleGuess;
 	LLColor3			mBrightestPointGuess;
-	LLHaze				mHaze;
-	F32					mHazeConcentration;
-	BOOL				mWeatherChange;
+	bool				mWeatherChange;
 	F32					mCloudDensity;
 	F32					mWind;
 	
-	BOOL				mInitialized;
-	BOOL				mForceUpdate;				//flag to force instantaneous update of cubemap
-	LLVector3			mLastLightingDirection;
-	LLColor3			mLastTotalAmbient;
+	bool				mInitialized;
+	bool				mForceUpdate;	
+    bool				mNeedUpdate;				// flag to force update of cubemap
+	S32					mCubeMapUpdateStage;		// state of cubemap uodate: -1 idle; 0-5 per-face updates; 6 finalizing
+
 	F32					mAmbientScale;
 	LLColor3			mNightColorShift;
 	F32					mInterpVal;
-
-	LLColor4			mFogColor;
-	LLColor4			mGLFogCol;
-	
-	F32					mFogRatio;
 	F32					mWorldScale;
 
-	LLColor4			mSunAmbient;
-	LLColor4			mMoonAmbient;
-	LLColor4			mTotalAmbient;
-	LLColor3			mSunDiffuse;
-	LLColor3			mMoonDiffuse;
-	LLColor4U			mFadeColor;					// Color to fade in from	
-
-	LLPointer<LLCubeMap>	mCubeMap;					// Cube map for the environment
-	S32					mDrawRefl;
+	LLPointer<LLCubeMap> mCubeMap;					// Cube map for the environment
+	S32					 mDrawRefl;
 
 	LLFrameTimer		mUpdateTimer;
+    LLTimer             mForceUpdateThrottle;
+	bool                mHeavenlyBodyUpdated ;
 
-public:
-	//by bao
-	//fake vertex buffer updating
-	//to guarantee at least updating one VBO buffer every frame
-	//to work around the bug caused by ATI card --> DEV-3855
-	//
-	void createDummyVertexBuffer() ;
-	void updateDummyVertexBuffer() ;
-
-	BOOL mHeavenlyBodyUpdated ;
+    AtmosphericsVars    m_atmosphericsVars;
+    AtmosphericsVars    m_lastAtmosphericsVars;
+    LLAtmospherics      m_legacyAtmospherics;
 };
 
-// turn it off
-#if LL_MSVC && __MSVC_VER__ < 8
-#pragma optimize("p", off)		
-#endif
-
-// Utility functions
-F32 azimuth(const LLVector3 &v);
-F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply = FALSE);
-
-
-/* Proportion of light that is scattered into 'path' from 'in' over distance dt. */
-/* assumes that vectors 'path' and 'in' are normalized. Scattering coef / 2pi */
-
-inline LLColor3 LLHaze::calcAirSca(const F32 h)
-{
-	return calcFalloff(h) * sAirScaSeaLevel;
-}
-
-inline void LLHaze::calcAirSca(const F32 h, LLColor3 &result)
-{
-	result = sAirScaSeaLevel;
-	result *= calcFalloff(h);
-}
-
-
 #endif
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 369ddebe2d811baade49de50dd4b37c0b43ecd9c..8e46ccd555d866fc246536b5ad2aace5b3411635 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -536,12 +536,14 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 
 		LLStrider<LLVector3> vertices;
 		LLStrider<LLVector3> normals;
+        LLStrider<LLColor4U> colors;
 		LLStrider<LLVector2> tex_coords;
 		LLStrider<U16> indicesp;
 
 		mReferenceBuffer->getVertexStrider(vertices);
 		mReferenceBuffer->getNormalStrider(normals);
 		mReferenceBuffer->getTexCoord0Strider(tex_coords);
+        mReferenceBuffer->getColorStrider(colors);
 		mReferenceBuffer->getIndexStrider(indicesp);
 				
 		S32 vertex_count = 0;
@@ -551,24 +553,27 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 		*(normals++) =		LLVector3(-SRR2, -SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR3, -SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(-SRR3, -SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
 		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR2, -SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
-
-
+        
 		*(indicesp++) = 0;
 		index_count++;
 		*(indicesp++) = 1;
@@ -587,21 +592,25 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 		*(normals++) =		LLVector3(-SRR2, SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR3, SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(-SRR3, SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
 		*(vertices++) =		LLVector3(-0.5f*LEAF_WIDTH, 0.f, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR2, SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.5f*LEAF_WIDTH, 0.f, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(indicesp++) = 4;
@@ -623,21 +632,25 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 		*(normals++) =		LLVector3(SRR2, -SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR3, SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR3, -SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(SRR2, SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(indicesp++) = 8;
@@ -659,21 +672,25 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 		*(normals++) =		LLVector3(-SRR2, -SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(-SRR3, SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(-SRR3, -SRR3, SRR3);
 		*(tex_coords++) =	LLVector2(LEAF_LEFT, LEAF_TOP);
 		*(vertices++) =		LLVector3(0.f, -0.5f*LEAF_WIDTH, 1.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(normals++) =		LLVector3(-SRR2, SRR2, 0.f);
 		*(tex_coords++) =	LLVector2(LEAF_RIGHT, LEAF_BOTTOM);
 		*(vertices++) =		LLVector3(0.f, 0.5f*LEAF_WIDTH, 0.f);
+        *(colors++) =       LLColor4U::white;
 		vertex_count++;
 
 		*(indicesp++) = 12;
@@ -786,6 +803,7 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable)
 					*(vertices++) =		LLVector3(x1*radius, y1*radius, z);
 					*(normals++) =		LLVector3(x1, y1, 0.f);
 					*(tex_coords++) = tc;
+                    *(colors++) =       LLColor4U::white;
 					vertex_count++;
 				}
 			}
@@ -910,15 +928,17 @@ void LLVOTree::updateMesh()
 	LLStrider<LLVector3> vertices;
 	LLStrider<LLVector3> normals;
 	LLStrider<LLVector2> tex_coords;
+    LLStrider<LLColor4U> colors;
 	LLStrider<U16> indices;
 	U16 idx_offset = 0;
 
 	buff->getVertexStrider(vertices);
 	buff->getNormalStrider(normals);
 	buff->getTexCoord0Strider(tex_coords);
+    buff->getColorStrider(colors);
 	buff->getIndexStrider(indices);
 
-	genBranchPipeline(vertices, normals, tex_coords, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
+	genBranchPipeline(vertices, normals, tex_coords, colors, indices, idx_offset, scale_mat, mTrunkLOD, stop_depth, mDepth, mTrunkDepth, 1.0, mTwist, droop, mBranches, alpha);
 	
 	mReferenceBuffer->flush();
 	buff->flush();
@@ -927,6 +947,7 @@ void LLVOTree::updateMesh()
 void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices, 
 						 LLStrider<LLVector3>& normals, 
 						 LLStrider<LLVector2>& tex_coords, 
+                         LLStrider<LLColor4U>& colors, 
 						 LLStrider<U16>& indices,
 						 U16& cur_idx,
 						 LLMatrix4& matrix,
@@ -939,11 +960,13 @@ void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
 	LLStrider<LLVector3> v;
 	LLStrider<LLVector3> n;
 	LLStrider<LLVector2> t;
+    LLStrider<LLColor4U> c;
 	LLStrider<U16> idx;
 
 	mReferenceBuffer->getVertexStrider(v);
 	mReferenceBuffer->getNormalStrider(n);
 	mReferenceBuffer->getTexCoord0Strider(t);
+    mReferenceBuffer->getColorStrider(c);
 	mReferenceBuffer->getIndexStrider(idx);
 	
 	//copy/transform vertices into mesh - check
@@ -955,6 +978,7 @@ void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
 		norm.normalize();
 		*normals++ = norm;
 		*tex_coords++ = t[index];
+        *colors++ = c[index];
 	}
 
 	//copy offset indices into mesh - check
@@ -972,6 +996,7 @@ void LLVOTree::appendMesh(LLStrider<LLVector3>& vertices,
 void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices, 
 								 LLStrider<LLVector3>& normals, 
 								 LLStrider<LLVector2>& tex_coords, 
+                                 LLStrider<LLColor4U>& colors,
 								 LLStrider<U16>& indices,
 								 U16& index_offset,
 								 LLMatrix4& matrix, 
@@ -1013,7 +1038,7 @@ void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices,
 				LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);
 
 				norm_mat.invert();
-				appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 
+				appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, 
 							sLODVertexOffset[trunk_LOD], sLODVertexCount[trunk_LOD], sLODIndexCount[trunk_LOD], sLODIndexOffset[trunk_LOD]);
 			}
 			
@@ -1032,7 +1057,7 @@ void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices,
 				LLMatrix4 rot_mat(rot);
 				rot_mat *= trans_mat;
 
-				genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
+				genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha);
 			}
 			//  Recurse to continue trunk
 			if (trunk_depth)
@@ -1043,7 +1068,7 @@ void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices,
 
 				LLMatrix4 rot_mat(70.5f*DEG_TO_RAD, LLVector4(0,0,1));
 				rot_mat *= trans_mat; // rotate a bit around Z when ascending 
-				genBranchPipeline(vertices, normals, tex_coords, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
+				genBranchPipeline(vertices, normals, tex_coords, colors, indices, index_offset, rot_mat, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha);
 			}
 		}
 		else
@@ -1062,7 +1087,7 @@ void LLVOTree::genBranchPipeline(LLStrider<LLVector3>& vertices,
 				glh::matrix4f norm((F32*) scale_mat.mMatrix);
 				LLMatrix4 norm_mat = LLMatrix4(norm.inverse().transpose().m);
 
-				appendMesh(vertices, normals, tex_coords, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0);	
+				appendMesh(vertices, normals, tex_coords, colors, indices, index_offset, scale_mat, norm_mat, 0, LEAF_VERTICES, LEAF_INDICES, 0);	
 			}
 		}
 	}
diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h
index c16ed70bb45971b5aa95e025b447e061b776e91b..93c22d2da3127d03411b65ab596704af74a4468d 100644
--- a/indra/newview/llvotree.h
+++ b/indra/newview/llvotree.h
@@ -79,7 +79,8 @@ class LLVOTree : public LLViewerObject
 
 	void appendMesh(LLStrider<LLVector3>& vertices, 
 						 LLStrider<LLVector3>& normals, 
-						 LLStrider<LLVector2>& tex_coords, 
+						 LLStrider<LLVector2>& tex_coords,
+                         LLStrider<LLColor4U>& colors,
 						 LLStrider<U16>& indices,
 						 U16& idx_offset,
 						 LLMatrix4& matrix,
@@ -92,6 +93,7 @@ class LLVOTree : public LLViewerObject
 	void genBranchPipeline(LLStrider<LLVector3>& vertices, 
 								 LLStrider<LLVector3>& normals, 
 								 LLStrider<LLVector2>& tex_coords, 
+                                 LLStrider<LLColor4U>& colors,
 								 LLStrider<U16>& indices,
 								 U16& index_offset,
 								 LLMatrix4& matrix, 
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 0a1efd564f6a7446c8eaebf58bcdc4b457996db5..2ffd462ac3c8a6f94408c1e89c785d51c1c971e2 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -3147,14 +3147,19 @@ void LLVOVolume::setIsLight(BOOL is_light)
 	}
 }
 
-void LLVOVolume::setLightColor(const LLColor3& color)
+void LLVOVolume::setLightSRGBColor(const LLColor3& color)
+{
+    setLightLinearColor(linearColor3(color));
+}
+
+void LLVOVolume::setLightLinearColor(const LLColor3& color)
 {
 	LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
 	if (param_block)
 	{
-		if (param_block->getColor() != color)
+		if (param_block->getLinearColor() != color)
 		{
-			param_block->setColor(LLColor4(color, param_block->getColor().mV[3]));
+			param_block->setLinearColor(LLColor4(color, param_block->getLinearColor().mV[3]));
 			parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
 			gPipeline.markTextured(mDrawable);
 			mFaceMappingChanged = TRUE;
@@ -3167,9 +3172,9 @@ void LLVOVolume::setLightIntensity(F32 intensity)
 	LLLightParams *param_block = (LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
 	if (param_block)
 	{
-		if (param_block->getColor().mV[3] != intensity)
+		if (param_block->getLinearColor().mV[3] != intensity)
 		{
-			param_block->setColor(LLColor4(LLColor3(param_block->getColor()), intensity));
+			param_block->setLinearColor(LLColor4(LLColor3(param_block->getLinearColor()), intensity));
 			parameterChanged(LLNetworkData::PARAMS_LIGHT, true);
 		}
 	}
@@ -3221,25 +3226,17 @@ BOOL LLVOVolume::getIsLight() const
 	return getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT);
 }
 
-LLColor3 LLVOVolume::getLightBaseColor() const
+LLColor3 LLVOVolume::getLightSRGBBaseColor() const
 {
-	const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
-	if (param_block)
-	{
-		return LLColor3(param_block->getColor());
-	}
-	else
-	{
-		return LLColor3(1,1,1);
-	}
+    return srgbColor3(getLightLinearBaseColor());
 }
 
-LLColor3 LLVOVolume::getLightColor() const
+LLColor3 LLVOVolume::getLightLinearBaseColor() const
 {
 	const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
 	if (param_block)
 	{
-		return LLColor3(param_block->getColor()) * param_block->getColor().mV[3];
+		return LLColor3(param_block->getLinearColor());
 	}
 	else
 	{
@@ -3247,6 +3244,26 @@ LLColor3 LLVOVolume::getLightColor() const
 	}
 }
 
+LLColor3 LLVOVolume::getLightLinearColor() const
+{
+    const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
+    if (param_block)
+    {
+        return LLColor3(param_block->getLinearColor()) * param_block->getLinearColor().mV[3];
+    }
+    else
+    {
+        return LLColor3(1, 1, 1);
+    }
+}
+
+LLColor3 LLVOVolume::getLightSRGBColor() const
+{
+    LLColor3 ret = getLightLinearColor();
+    ret = srgbColor3(ret);
+    return ret;
+}
+
 LLUUID LLVOVolume::getLightTextureID() const
 {
 	if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
@@ -3283,18 +3300,16 @@ F32 LLVOVolume::getSpotLightPriority() const
 
 void LLVOVolume::updateSpotLightPriority()
 {
+    F32 r = getLightRadius();
 	LLVector3 pos = mDrawable->getPositionAgent();
+
 	LLVector3 at(0,0,-1);
 	at *= getRenderRotation();
-
-	F32 r = getLightRadius()*0.5f;
-
 	pos += at * r;
 
 	at = LLViewerCamera::getInstance()->getAtAxis();
-
 	pos -= at * r;
-	
+
 	mSpotLightPriority = gPipeline.calcPixelArea(pos, LLVector3(r,r,r), *LLViewerCamera::getInstance());
 
 	if (mLightTexture.notNull())
@@ -3340,7 +3355,7 @@ F32 LLVOVolume::getLightIntensity() const
 	const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
 	if (param_block)
 	{
-		return param_block->getColor().mV[3];
+		return param_block->getLinearColor().mV[3];
 	}
 	else
 	{
@@ -3361,12 +3376,12 @@ F32 LLVOVolume::getLightRadius() const
 	}
 }
 
-F32 LLVOVolume::getLightFalloff() const
+F32 LLVOVolume::getLightFalloff(const F32 fudge_factor) const
 {
 	const LLLightParams *param_block = (const LLLightParams *)getParameterEntry(LLNetworkData::PARAMS_LIGHT);
 	if (param_block)
 	{
-		return param_block->getFalloff();
+		return param_block->getFalloff() * fudge_factor;
 	}
 	else
 	{
@@ -4575,12 +4590,10 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
 					}
 				}
 
+                BOOL no_texture = !face->getTexture() || !face->getTexture()->hasGLTexture();
+                BOOL mask       = no_texture ? FALSE : face->getTexture()->getMask(face->surfaceToTexture(tc, p, n));
 				if (face &&
-					(ignore_alpha ||
-					pick_transparent || 
-					!face->getTexture() || 
-					!face->getTexture()->hasGLTexture() || 
-					face->getTexture()->getMask(face->surfaceToTexture(tc, p, n))))
+					(ignore_alpha || pick_transparent || no_texture || mask))
 				{
 					local_end = p;
 					if (face_hitp != NULL)
@@ -4785,18 +4798,44 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
                 U32 max_joints = LLSkinningUtil::getMaxJointCount();
                 rigged_vert_count += dst_face.mNumVertices;
                 rigged_face_count++;
-				for (U32 j = 0; j < dst_face.mNumVertices; ++j)
-				{
-					LLMatrix4a final_mat;
-                    LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
+
+            #if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
+                if (vol_face.mJointIndices) // fast path with preconditioned joint indices
+                {
+                    LLMatrix4a src[4];
+                    U8* joint_indices_cursor = vol_face.mJointIndices;
+                    LLVector4a* just_weights = vol_face.mJustWeights;
+                    for (U32 j = 0; j < dst_face.mNumVertices; ++j)
+				    {
+					    LLMatrix4a final_mat;
+                        F32* w = just_weights[j].getF32ptr();
+                        LLSkinningUtil::getPerVertexSkinMatrixWithIndices(w, joint_indices_cursor, mat, final_mat, src);
+                        joint_indices_cursor += 4;
+
+					    LLVector4a& v = vol_face.mPositions[j];
+					    LLVector4a t;
+					    LLVector4a dst;
+					    bind_shape_matrix.affineTransform(v, t);
+					    final_mat.affineTransform(t, dst);
+					    pos[j] = dst;
+				    }
+                }
+                else
+            #endif
+                {
+				    for (U32 j = 0; j < dst_face.mNumVertices; ++j)
+				    {
+					    LLMatrix4a final_mat;
+                        LLSkinningUtil::getPerVertexSkinMatrix(weight[j].getF32ptr(), mat, false, final_mat, max_joints);
 				
-					LLVector4a& v = vol_face.mPositions[j];
-					LLVector4a t;
-					LLVector4a dst;
-					bind_shape_matrix.affineTransform(v, t);
-					final_mat.affineTransform(t, dst);
-					pos[j] = dst;
-				}
+					    LLVector4a& v = vol_face.mPositions[j];
+					    LLVector4a t;
+					    LLVector4a dst;
+					    bind_shape_matrix.affineTransform(v, t);
+					    final_mat.affineTransform(t, dst);
+					    pos[j] = dst;
+				    }
+                }
 
 				//update bounding box
 				// VFExtents change
@@ -4977,7 +5016,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 	if (   type == LLRenderPass::PASS_ALPHA 
 		&& facep->getTextureEntry()->getMaterialParams().notNull() 
 		&& !facep->getVertexBuffer()->hasDataType(LLVertexBuffer::TYPE_TANGENT)
-		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1)
+		&& LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1)
 	{
 		LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL;
 	}
@@ -5512,6 +5551,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						LLViewerTexture* tex = facep->getTexture();
 						U32 type = gPipeline.getPoolTypeFromTE(te, tex);
 
+                        F32 te_alpha = te->getColor().mV[3];
 
 						if (te->getGlow())
 						{
@@ -5519,6 +5559,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						}
 
 						LLMaterial* mat = te->getMaterialParams().get();
+                        bool fullbright = te->getFullbright();
 
 						if (mat && LLPipeline::sRenderDeferred)
 						{
@@ -5526,14 +5567,18 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 							bool is_alpha = type == LLDrawPool::POOL_ALPHA &&
 								(alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND ||
-								te->getColor().mV[3] < 0.999f);
+								te_alpha < 0.999f);
 
 							if (is_alpha)
 							{ //this face needs alpha blending, override alpha mode
 								alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
 							}
 
-							if (!is_alpha || te->getColor().mV[3] > 0.f)  // //only add the face if it will actually be visible
+                            if (fullbright && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE))
+                            {
+                                pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
+                            }
+							else if (!is_alpha || te_alpha > 0.f)  // //only add the face if it will actually be visible
 							{ 
 								U32 mask = mat->getShaderMask(alpha_mode);
 								pool->addRiggedFace(facep, mask);
@@ -5545,8 +5590,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 							}
 						}
 						else if (mat)
-						{
-							bool fullbright = te->getFullbright();
+						{							
 							bool is_alpha = type == LLDrawPool::POOL_ALPHA;
 							U8 mode = mat->getDiffuseAlphaMode();
 							bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
@@ -5883,7 +5927,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 		spec_mask = spec_mask | LLVertexBuffer::MAP_EMISSIVE;
 	}
 
-	BOOL batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+	BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
 
 	if (batch_textures)
 	{
@@ -6451,8 +6495,12 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 								mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
 			}
 
+            F32 te_alpha = te->getColor().mV[3]; 
 			bool use_legacy_bump = te->getBumpmap() && (te->getBumpmap() < 18) && (!mat || mat->getNormalID().isNull());
-			bool opaque = te->getColor().mV[3] >= 0.999f;
+			bool opaque = te_alpha >= 0.999f;
+            bool transparent = te_alpha < 0.999f;
+
+            is_alpha = (is_alpha || transparent) ? TRUE : FALSE;
 
 			if (mat && LLPipeline::sRenderDeferred && !hud_group)
 			{
@@ -6481,14 +6529,20 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 					}
 					else
 					{
-						if (mat->getEnvironmentIntensity() > 0 ||
-							te->getShiny() > 0)
+						if (mat->getEnvironmentIntensity() > 0 || te->getShiny() > 0)
 						{
 							material_pass = true;
 						}
 						else
 						{
-							registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+                            if (opaque)
+						    {
+							    registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT);
+                            }
+                            else
+                            {
+                                registerFace(group, facep, LLRenderPass::PASS_ALPHA);
+                            }
 						}
 					}
 				}
@@ -6496,7 +6550,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 				{
 					registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
 				}
-				else if (te->getColor().mV[3] < 0.999f)
+				else if (transparent)
 				{
 					registerFace(group, facep, LLRenderPass::PASS_ALPHA);
 				}
@@ -6544,7 +6598,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 			else if (mat)
 			{
 				U8 mode = mat->getDiffuseAlphaMode();
-				if (te->getColor().mV[3] < 0.999f)
+
+                is_alpha = (is_alpha || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND));
+
+				if (is_alpha)
 				{
 					mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
 				}
@@ -6553,7 +6610,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 				{
 					registerFace(group, facep, fullbright ? LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK : LLRenderPass::PASS_ALPHA_MASK);
 				}
-				else if (is_alpha || (te->getColor().mV[3] < 0.999f))
+				else if (is_alpha )
 				{
 					registerFace(group, facep, LLRenderPass::PASS_ALPHA);
 				}
@@ -6669,7 +6726,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 						{
 							registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
 						}
-				}
+				    }
 				}
 				
 				
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 13db9c39b75bd965de5bc0ff8d68c76d09754f91..de00ef494e65ea908d5adf1d7e600581544d6111 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -242,7 +242,11 @@ class LLVOVolume : public LLViewerObject
 
 	// For Lights
 	void setIsLight(BOOL is_light);
-	void setLightColor(const LLColor3& color);
+    //set the gamma-corrected (sRGB) color of this light
+	void setLightSRGBColor(const LLColor3& color);
+    //set the linear color of this light
+    void setLightLinearColor(const LLColor3& color);
+
 	void setLightIntensity(F32 intensity);
 	void setLightRadius(F32 radius);
 	void setLightFalloff(F32 falloff);
@@ -251,8 +255,21 @@ class LLVOVolume : public LLViewerObject
 	void setSpotLightParams(LLVector3 params);
 
 	BOOL getIsLight() const;
-	LLColor3 getLightBaseColor() const; // not scaled by intensity
-	LLColor3 getLightColor() const; // scaled by intensity
+
+
+    // Get the light color in sRGB color space NOT scaled by intensity.
+	LLColor3 getLightSRGBBaseColor() const; 
+
+    // Get the light color in linear color space NOT scaled by intensity.
+    LLColor3 getLightLinearBaseColor() const;
+    
+    // Get the light color in linear color space scaled by intensity 
+    //  this is the value that should be fed into shaders
+    LLColor3 getLightLinearColor() const;
+
+    // Get the light color in sRGB color space scaled by intensity.
+    LLColor3 getLightSRGBColor() const; 
+
 	LLUUID	getLightTextureID() const;
 	bool isLightSpotlight() const;
 	LLVector3 getSpotLightParams() const;
@@ -262,7 +279,7 @@ class LLVOVolume : public LLViewerObject
 	LLViewerTexture* getLightTexture();
 	F32 getLightIntensity() const;
 	F32 getLightRadius() const;
-	F32 getLightFalloff() const;
+	F32 getLightFalloff(const F32 fudge_factor = 1.f) const;
 	F32 getLightCutoff() const;
 	
 	// Flexible Objects
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 2cb5fc81b0fa53f48e15d4e6929533850ec7bbc0..368a3f23351822c03944e403660f887091bd756f 100644
--- a/indra/newview/llvowlsky.cpp
+++ b/indra/newview/llvowlsky.cpp
@@ -32,14 +32,12 @@
 #include "llsky.h"
 #include "lldrawpoolwlsky.h"
 #include "llface.h"
-#include "llwlparammanager.h"
 #include "llviewercontrol.h"
+#include "llenvironment.h"
+#include "llsettingssky.h"
 
-#define DOME_SLICES 1
-const F32 LLVOWLSky::DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f;
-
-const U32 LLVOWLSky::MIN_SKY_DETAIL = 3;
-const U32 LLVOWLSky::MAX_SKY_DETAIL = 180;
+static const U32 MIN_SKY_DETAIL = 8;
+static const U32 MAX_SKY_DETAIL = 180;
 
 inline U32 LLVOWLSky::getNumStacks(void)
 {
@@ -51,16 +49,6 @@ inline U32 LLVOWLSky::getNumSlices(void)
 	return 2 * llmin(MAX_SKY_DETAIL, llmax(MIN_SKY_DETAIL, gSavedSettings.getU32("WLSkyDetail")));
 }
 
-inline U32 LLVOWLSky::getFanNumVerts(void)
-{
-	return getNumSlices() + 1;
-}
-
-inline U32 LLVOWLSky::getFanNumIndices(void)
-{
-	return getNumSlices() * 3;
-}
-
 inline U32 LLVOWLSky::getStripsNumVerts(void)
 {
 	return (getNumStacks() - 1) * getNumSlices();
@@ -87,11 +75,6 @@ LLVOWLSky::LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regi
 	initStars();
 }
 
-void LLVOWLSky::initSunDirection(LLVector3 const & sun_direction,
-		LLVector3 const & sun_angular_velocity)
-{
-}
-
 void LLVOWLSky::idleUpdate(LLAgent &agent, const F64 &time)
 {
 	
@@ -120,8 +103,9 @@ inline F32 LLVOWLSky::calcPhi(U32 i)
 	F32 t = float(i) / float(getNumStacks());
 
 	// ^4 the parameter of the tesselation to bias things toward 0 (the dome's apex)
-	t = t*t*t*t;
-	
+	t *= t;
+	t *= t;
+
 	// invert and square the parameter of the tesselation to bias things toward 1 (the horizon)
 	t = 1.f - t;
 	t = t*t;
@@ -130,167 +114,20 @@ inline F32 LLVOWLSky::calcPhi(U32 i)
 	return (F_PI / 8.f) * t;
 }
 
-#if !DOME_SLICES
-static const F32 Q = (1.f + sqrtf(5.f))/2.f; //golden ratio
-
-//icosahedron verts (based on asset b0c7b76e-28c6-1f87-a1de-752d5e3cd264, contact Runitai Linden for a copy)
-static const LLVector3 icosahedron_vert[] =
-{
-	LLVector3(0,1.f,Q),
-	LLVector3(0,-1.f,Q),
-	LLVector3(0,-1.f,-Q),
-	LLVector3(0,1.f,-Q),
-
-	LLVector3(Q,0,1.f),
-	LLVector3(-Q,0,1.f),
-	LLVector3(-Q,0,-1.f),
-	LLVector3(Q,0,-1.f),
-
-	LLVector3(1,-Q,0.f),
-	LLVector3(-1,-Q,0.f),
-	LLVector3(-1,Q,0.f),
-	LLVector3(1,Q,0.f),
-};
-
-//indices
-static const U32 icosahedron_ind[] = 
-{
-	5,0,1,
-	10,0,5,
-	5,1,9,
-	10,5,6,
-	6,5,9,
-	11,0,10,
-	3,11,10,
-	3,10,6,
-	3,6,2,
-	7,3,2,
-	8,7,2,
-	4,7,8,
-	1,4,8,
-	9,8,2,
-	9,2,6,
-	11,3,7,
-	4,0,11,
-	4,11,7,
-	1,0,4,
-	1,8,9,
-};
-
-
-//split every triangle in LLVertexBuffer into even fourths (assumes index triangle lists)
-void subdivide(LLVertexBuffer& in, LLVertexBuffer* ret)
-{
-	S32 tri_in = in.getNumIndices()/3;
-
-	ret->allocateBuffer(tri_in*4*3, tri_in*4*3, TRUE);
-
-	LLStrider<LLVector3> vin, vout;
-	LLStrider<U16> indin, indout;
-
-	ret->getVertexStrider(vout);
-	in.getVertexStrider(vin);
-
-	ret->getIndexStrider(indout);
-	in.getIndexStrider(indin);
-	
-	
-	for (S32 i = 0; i < tri_in; i++)
-	{
-		LLVector3 v0 = vin[*indin++];
-		LLVector3 v1 = vin[*indin++];
-		LLVector3 v2 = vin[*indin++];
-
-		LLVector3 v3 = (v0 + v1) * 0.5f;
-		LLVector3 v4 = (v1 + v2) * 0.5f;
-		LLVector3 v5 = (v2 + v0) * 0.5f;
-
-		*vout++ = v0;
-		*vout++ = v3;
-		*vout++ = v5;
-
-		*vout++ = v3;
-		*vout++ = v4;
-		*vout++ = v5;
-
-		*vout++ = v3;
-		*vout++ = v1;
-		*vout++ = v4;
-
-		*vout++ = v5;
-		*vout++ = v4;
-		*vout++ = v2;
-	}
-	
-	for (S32 i = 0; i < ret->getNumIndices(); i++)
-	{
-		*indout++ = i;
-	}
-
-}
-
-void chop(LLVertexBuffer& in, LLVertexBuffer* out)
-{
-	//chop off all triangles below horizon 
-	F32 d = LLWLParamManager::sParamMgr->getDomeOffset() * LLWLParamManager::sParamMgr->getDomeRadius();
-	
-	std::vector<LLVector3> vert;
-	
-	LLStrider<LLVector3> vin;
-	LLStrider<U16> index;
-
-	in.getVertexStrider(vin);
-	in.getIndexStrider(index);
-
-	U32 tri_count = in.getNumIndices()/3;
-	for (U32 i = 0; i < tri_count; i++)
-	{
-		LLVector3 &v1 = vin[index[i*3+0]];
-		LLVector3 &v2 = vin[index[i*3+1]];
-		LLVector3 &v3 = vin[index[i*3+2]];
-
-		if (v1.mV[1] > d ||
-			v2.mV[1] > d ||
-			v3.mV[1] > d)
-		{
-			v1.mV[1] = llmax(v1.mV[1], d);
-			v2.mV[1] = llmax(v1.mV[1], d);
-			v3.mV[1] = llmax(v1.mV[1], d);
-
-			vert.push_back(v1);
-			vert.push_back(v2);
-			vert.push_back(v3);
-		}
-	}
-
-	out->allocateBuffer(vert.size(), vert.size(), TRUE);
-
-	LLStrider<LLVector3> vout;
-	out->getVertexStrider(vout);
-	out->getIndexStrider(index);
-
-	for (U32 i = 0; i < vert.size(); i++)
-	{
-		*vout++ = vert[i];
-		*index++ = i;
-	}	
-}
-#endif // !DOME_SLICES
-
 void LLVOWLSky::resetVertexBuffers()
 {
-	mFanVerts = NULL;
 	mStripsVerts.clear();
-	mStarsVerts = NULL;
+	mStarsVerts = nullptr;
+    mFsSkyVerts = nullptr;
 
 	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
 }
 	
 void LLVOWLSky::cleanupGL()
 {
-	mFanVerts = NULL;
 	mStripsVerts.clear();
-	mStarsVerts = NULL;
+	mStarsVerts = nullptr;
+    mFsSkyVerts = nullptr;
 
 	LLDrawPoolWLSky::cleanupGL();
 }
@@ -305,38 +142,51 @@ static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Windlight Sky Geometry");
 
 BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 {
-	LL_RECORD_BLOCK_TIME(FTM_GEO_SKY);
+    LL_RECORD_BLOCK_TIME(FTM_GEO_SKY);
 	LLStrider<LLVector3>	vertices;
 	LLStrider<LLVector2>	texCoords;
 	LLStrider<U16>			indices;
 
-#if DOME_SLICES
-	{
-		mFanVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
-		if (!mFanVerts->allocateBuffer(getFanNumVerts(), getFanNumIndices(), TRUE))
+    if (mFsSkyVerts.isNull())
+    {
+        mFsSkyVerts = new LLVertexBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
+
+        if (!mFsSkyVerts->allocateBuffer(4, 6, TRUE))
 		{
-			LL_WARNS() << "Failed to allocate Vertex Buffer on sky update to "
-				<< getFanNumVerts() << " vertices and "
-				<< getFanNumIndices() << " indices" << LL_ENDL;
+			LL_WARNS() << "Failed to allocate Vertex Buffer on full screen sky update" << LL_ENDL;
 		}
 
-		BOOL success = mFanVerts->getVertexStrider(vertices)
-			&& mFanVerts->getTexCoord0Strider(texCoords)
-			&& mFanVerts->getIndexStrider(indices);
+		BOOL success = mFsSkyVerts->getVertexStrider(vertices)
+			        && mFsSkyVerts->getTexCoord0Strider(texCoords)
+			        && mFsSkyVerts->getIndexStrider(indices);
 
 		if(!success) 
 		{
-			LL_ERRS() << "Failed updating WindLight sky geometry." << LL_ENDL;
+			LL_ERRS() << "Failed updating WindLight fullscreen sky geometry." << LL_ENDL;
 		}
 
-		buildFanBuffer(vertices, texCoords, indices);
+        *vertices++ = LLVector3(-1.0f, -1.0f, 0.0f);
+        *vertices++ = LLVector3( 1.0f, -1.0f, 0.0f);
+        *vertices++ = LLVector3(-1.0f,  1.0f, 0.0f);
+        *vertices++ = LLVector3( 1.0f,  1.0f, 0.0f);
 
-		mFanVerts->flush();
-	}
+		*texCoords++ = LLVector2(0.0f, 0.0f);
+        *texCoords++ = LLVector2(1.0f, 0.0f);
+        *texCoords++ = LLVector2(0.0f, 1.0f);
+        *texCoords++ = LLVector2(1.0f, 1.0f);
+
+		*indices++ = 0;
+		*indices++ = 1;
+		*indices++ = 2;
+        *indices++ = 1;
+		*indices++ = 3;
+		*indices++ = 2;
+
+        mFsSkyVerts->flush();
+    }
 
 	{
-		LLCachedControl<S32> max_vbo_size(gSavedSettings, "RenderMaxVBOSize", 512);
-		const U32 max_buffer_bytes = max_vbo_size * 1024;
+		const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024;
 		const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
 		const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask);
 
@@ -398,8 +248,11 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 				LL_ERRS() << "Failed updating WindLight sky geometry." << LL_ENDL;
 			}
 
+            U32 vertex_count = 0;
+            U32 index_count  = 0;
+
 			// fill it
-			buildStripsBuffer(begin_stack, end_stack,  vertices, texCoords, indices);
+			buildStripsBuffer(begin_stack, end_stack, vertex_count, index_count, vertices, texCoords, indices);
 
 			// and unlock the buffer
 			segment->flush();
@@ -407,85 +260,6 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable)
 	
 		LL_INFOS() << "completed in " << llformat("%.2f", timer.getElapsedTimeF32().value()) << "seconds" << LL_ENDL;
 	}
-#else
-	mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB);
-	
-	const F32 RADIUS = LLWLParamManager::sParamMgr->getDomeRadius();
-
-	LLPointer<LLVertexBuffer> temp = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
-	temp->allocateBuffer(12, 60, TRUE);
-
-	BOOL success = temp->getVertexStrider(vertices)
-		&& temp->getIndexStrider(indices);
-
-	if (success)
-	{
-		for (U32 i = 0; i < 12; i++)
-		{
-			*vertices++ = icosahedron_vert[i];
-		}
-
-		for (U32 i = 0; i < 60; i++)
-		{
-			*indices++ = icosahedron_ind[i];
-		}
-	}
-
-
-	LLPointer<LLVertexBuffer> temp2;
-	
-	for (U32 i = 0; i < 8; i++)
-	{
-		temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
-		subdivide(*temp, temp2);
-		temp = temp2;
-	}
-	
-	temp->getVertexStrider(vertices);
-	for (S32 i = 0; i < temp->getNumVerts(); i++)
-	{
-		LLVector3 v = vertices[i];
-		v.normVec();
-		vertices[i] = v*RADIUS;
-	}
-
-	temp2 = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, 0);
-	chop(*temp, temp2);
-
-	mStripsVerts->allocateBuffer(temp2->getNumVerts(), temp2->getNumIndices(), TRUE);
-	
-	success = mStripsVerts->getVertexStrider(vertices)
-		&& mStripsVerts->getTexCoordStrider(texCoords)
-		&& mStripsVerts->getIndexStrider(indices);
-
-	LLStrider<LLVector3> v;
-	temp2->getVertexStrider(v);
-	LLStrider<U16> ind;
-	temp2->getIndexStrider(ind);
-
-	if (success)
-	{
-		for (S32 i = 0; i < temp2->getNumVerts(); ++i)
-		{
-			LLVector3 vert = *v++;
-			vert.normVec();
-			F32 z0 = vert.mV[2];
-			F32 x0 = vert.mV[0];
-			
-			vert *= RADIUS;
-			
-			*vertices++ = vert;
-			*texCoords++ = LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
-		}
-
-		for (S32 i = 0; i < temp2->getNumIndices(); ++i)
-		{
-			*indices++ = *ind++;
-		}
-	}
-
-	mStripsVerts->flush();
-#endif
 
 	updateStarColors();
 	updateStarGeometry(drawable);
@@ -505,6 +279,21 @@ void LLVOWLSky::drawStars(void)
 	}
 }
 
+void LLVOWLSky::drawFsSky(void)
+{
+    if (mFsSkyVerts.isNull())
+	{
+		updateGeometry(mDrawable);
+	}
+
+    LLGLDisable disable_blend(GL_BLEND);
+
+	mFsSkyVerts->setBuffer(LLDrawPoolWLSky::ADV_ATMO_SKY_VERTEX_DATA_MASK);
+	mFsSkyVerts->drawRange(LLRender::TRIANGLES, 0, mFsSkyVerts->getNumVerts() - 1, mFsSkyVerts->getNumIndices(), 0);
+	gPipeline.addTrianglesDrawn(mFsSkyVerts->getNumIndices(), LLRender::TRIANGLES);
+	LLVertexBuffer::unbind();
+}
+
 void LLVOWLSky::drawDome(void)
 {
 	if (mStripsVerts.empty())
@@ -516,7 +305,6 @@ void LLVOWLSky::drawDome(void)
 
 	const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK;
 	
-#if DOME_SLICES
 	std::vector< LLPointer<LLVertexBuffer> >::const_iterator strips_vbo_iter, end_strips;
 	end_strips = mStripsVerts.end();
 	for(strips_vbo_iter = mStripsVerts.begin(); strips_vbo_iter != end_strips; ++strips_vbo_iter)
@@ -532,21 +320,13 @@ void LLVOWLSky::drawDome(void)
 		gPipeline.addTrianglesDrawn(strips_segment->getNumIndices(), LLRender::TRIANGLE_STRIP);
 	}
 
-#else
-	mStripsVerts->setBuffer(data_mask);
-	gGL.syncMatrices();
-	glDrawRangeElements(
-		GL_TRIANGLES,
-		0, mStripsVerts->getNumVerts()-1, mStripsVerts->getNumIndices(),
-		GL_UNSIGNED_SHORT,
-		mStripsVerts->getIndicesPointer());
-#endif
-
 	LLVertexBuffer::unbind();
 }
 
 void LLVOWLSky::initStars()
 {
+    const F32 DISTANCE_TO_STARS = LLEnvironment::instance().getCurrentSky()->getDomeRadius();
+
 	// Initialize star map
 	mStarVertices.resize(getStarsNumVerts());
 	mStarColors.resize(getStarsNumVerts());
@@ -581,72 +361,15 @@ void LLVOWLSky::initStars()
 	}
 }
 
-void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices,
-							   LLStrider<LLVector2> & texCoords,
-							   LLStrider<U16> & indices)
-{
-	const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius();
-
-	U32 i, num_slices;
-	F32 phi0, theta, x0, y0, z0;
-
-	// paranoia checking for SL-55986/SL-55833
-	U32 count_verts = 0;
-	U32 count_indices = 0;
-
-	// apex
-	*vertices++		= LLVector3(0.f, RADIUS, 0.f);
-	*texCoords++	= LLVector2(0.5f, 0.5f);
-	++count_verts;
-
-	num_slices = getNumSlices();
-
-	// and fan in a circle around the apex
-	phi0 = calcPhi(1);
-	for(i = 0; i < num_slices; ++i) {
-		theta = 2.f * F_PI * float(i) / float(num_slices);
-
-		// standard transformation from  spherical to
-		// rectangular coordinates
-		x0 = sin(phi0) * cos(theta);
-		y0 = cos(phi0);
-		z0 = sin(phi0) * sin(theta);
-
-		*vertices++		= LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS);
-		// generate planar uv coordinates
-		// note: x and z are transposed in order for things to animate
-		// correctly in the global coordinate system where +x is east and
-		// +y is north
-		*texCoords++	= LLVector2((-z0 + 1.f) / 2.f, (-x0 + 1.f) / 2.f);
-		++count_verts;
-
-		if (i > 0)
-		{
-			*indices++ = 0;
-			*indices++ = i;
-			*indices++ = i+1;
-			count_indices += 3;
-		}
-	}
-
-	// the last vertex of the last triangle should wrap around to 
-	// the beginning
-	*indices++ = 0;
-	*indices++ = num_slices;
-	*indices++ = 1;
-	count_indices += 3;
-
-	// paranoia checking for SL-55986/SL-55833
-	llassert(getFanNumVerts() == count_verts);
-	llassert(getFanNumIndices() == count_indices);
-}
-
-void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
+void LLVOWLSky::buildStripsBuffer(U32 begin_stack,
+                                  U32 end_stack,
+                                  U32& vertex_count,
+                                  U32& index_count,
 								  LLStrider<LLVector3> & vertices,
 								  LLStrider<LLVector2> & texCoords,
 								  LLStrider<U16> & indices)
 {
-	const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius();
+    const F32 RADIUS = LLEnvironment::instance().getCurrentSky()->getDomeRadius();
 
 	U32 i, j, num_slices, num_stacks;
 	F32 phi0, theta, x0, y0, z0;
@@ -661,7 +384,11 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
 	llassert(end_stack <= num_stacks);
 
 	// stacks are iterated one-indexed since phi(0) was handled by the fan above
-	for(i = begin_stack + 1; i <= end_stack+1; ++i) 
+#if NEW_TESS
+	for(i = begin_stack; i <= end_stack; ++i) 
+#else
+    for(i = begin_stack + 1; i <= end_stack+1; ++i) 
+#endif
 	{
 		phi0 = calcPhi(i);
 
@@ -675,7 +402,10 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
 			y0 = cos(phi0);
 			z0 = sin(phi0) * sin(theta);
 
-			if (i == num_stacks-2)
+#if NEW_TESS
+            *vertices++ = LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS);
+#else
+            if (i == num_stacks-2)
 			{
 				*vertices++ = LLVector3(x0*RADIUS, y0*RADIUS-1024.f*2.f, z0*RADIUS);
 			}
@@ -687,6 +417,8 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
 			{
 				*vertices++		= LLVector3(x0 * RADIUS, y0 * RADIUS, z0 * RADIUS);
 			}
+#endif
+
 			++count_verts;
 
 			// generate planar uv coordinates
@@ -725,6 +457,9 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack,
 		*indices++ = i * num_slices + k ;
 		count_indices++ ;
 	}
+
+    vertex_count = count_verts;
+    index_count = count_indices;
 }
 
 void LLVOWLSky::updateStarColors()
@@ -819,7 +554,7 @@ BOOL LLVOWLSky::updateStarGeometry(LLDrawable *drawable)
 		LLVector3 left = at%LLVector3(0,0,1);
 		LLVector3 up = at%left;
 
-		F32 sc = 0.5f+ll_frand()*1.25f;
+		F32 sc = 16.0f + (ll_frand() * 20.0f);
 		left *= sc;
 		up *= sc;
 
diff --git a/indra/newview/llvowlsky.h b/indra/newview/llvowlsky.h
index 1d419b5fea290e62762794636aab1fe37ac182de..2b7ebe75dd7ef05fcb957d67cd895098db359bc6 100644
--- a/indra/newview/llvowlsky.h
+++ b/indra/newview/llvowlsky.h
@@ -31,17 +31,8 @@
 
 class LLVOWLSky : public LLStaticViewerObject {
 private:
-	static const F32 DISTANCE_TO_STARS;
-
-	// anything less than 3 makes it impossible to create a closed dome.
-	static const U32 MIN_SKY_DETAIL;
-	// anything bigger than about 180 will cause getStripsNumVerts() to exceed 65535.
-	static const U32 MAX_SKY_DETAIL;
-
 	inline static U32 getNumStacks(void);
 	inline static U32 getNumSlices(void);
-	inline static U32 getFanNumVerts(void);
-	inline static U32 getFanNumIndices(void);
 	inline static U32 getStripsNumVerts(void);
 	inline static U32 getStripsNumIndices(void);
 	inline static U32 getStarsNumVerts(void);
@@ -50,9 +41,6 @@ class LLVOWLSky : public LLStaticViewerObject {
 public:
 	LLVOWLSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
 
-	void initSunDirection(LLVector3 const & sun_direction,
-		LLVector3 const & sun_angular_velocity);
-
 	/*virtual*/ void		 idleUpdate(LLAgent &agent, const F64 &time);
 	/*virtual*/ BOOL		 isActive(void) const;
 	/*virtual*/ LLDrawable * createDrawable(LLPipeline *pipeline);
@@ -60,6 +48,7 @@ class LLVOWLSky : public LLStaticViewerObject {
 
 	void drawStars(void);
 	void drawDome(void);
+    void drawFsSky(void); // fullscreen sky for advanced atmo
 	void resetVertexBuffers(void);
 	
 	void cleanupGL();
@@ -72,16 +61,13 @@ class LLVOWLSky : public LLStaticViewerObject {
 	// helper function for initializing the stars.
 	void initStars();
 
-	// helper function for building the fan vertex buffer.
-	static void buildFanBuffer(LLStrider<LLVector3> & vertices,
-							   LLStrider<LLVector2> & texCoords,
-							   LLStrider<U16> & indices);
-
 	// helper function for building the strips vertex buffer.
 	// note begin_stack and end_stack follow stl iterator conventions,
 	// begin_stack is the first stack to be included, end_stack is the first
 	// stack not to be included.
 	static void buildStripsBuffer(U32 begin_stack, U32 end_stack,
+                                  U32& vertex_count,
+                                  U32& index_count,
 								  LLStrider<LLVector3> & vertices,
 								  LLStrider<LLVector2> & texCoords,
 								  LLStrider<U16> & indices);
@@ -93,7 +79,7 @@ class LLVOWLSky : public LLStaticViewerObject {
 	BOOL updateStarGeometry(LLDrawable *drawable);
 
 private:
-	LLPointer<LLVertexBuffer>					mFanVerts;
+    LLPointer<LLVertexBuffer>					mFsSkyVerts;
 	std::vector< LLPointer<LLVertexBuffer> >	mStripsVerts;
 	LLPointer<LLVertexBuffer>					mStarsVerts;
 
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
deleted file mode 100644
index b484b6d70962dec919ef253a8a6c350c62d5c5b2..0000000000000000000000000000000000000000
--- a/indra/newview/llwaterparammanager.cpp
+++ /dev/null
@@ -1,442 +0,0 @@
-/**
- * @file llwaterparammanager.cpp
- * @brief Implementation for the LLWaterParamManager class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llwaterparammanager.h"
-
-#include "llrender.h"
-
-#include "pipeline.h"
-#include "llsky.h"
-
-#include "lldiriterator.h"
-#include "llfloaterreg.h"
-#include "llsliderctrl.h"
-#include "llspinctrl.h"
-#include "llcheckboxctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewercontrol.h"
-#include "llviewercamera.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llsdserialize.h"
-
-#include "v4math.h"
-#include "llviewercontrol.h"
-#include "lldrawpoolwater.h"
-#include "llagent.h"
-#include "llagentcamera.h"
-#include "llviewerregion.h"
-
-#include "llwlparammanager.h"
-#include "llwaterparamset.h"
-
-#include "curl/curl.h"
-
-LLWaterParamManager::LLWaterParamManager() :
-	mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"),
-	mFogDensity(4, "waterFogDensity", 2),
-	mUnderWaterFogMod(0.25, "underWaterFogMod"),
-	mNormalScale(2.f, 2.f, 2.f, "normScale"),
-	mFresnelScale(0.5f, "fresnelScale"),
-	mFresnelOffset(0.4f, "fresnelOffset"),
-	mScaleAbove(0.025f, "scaleAbove"),
-	mScaleBelow(0.2f, "scaleBelow"),
-	mBlurMultiplier(0.1f, "blurMultiplier"),
-	mWave1Dir(.5f, .5f, "wave1Dir"),
-	mWave2Dir(.5f, .5f, "wave2Dir"),
-	mDensitySliderValue(1.0f),
-	mWaterFogKS(1.0f)
-{
-}
-
-LLWaterParamManager::~LLWaterParamManager()
-{
-}
-
-void LLWaterParamManager::loadAllPresets()
-{
-	// First, load system (coming out of the box) water presets.
-	loadPresetsFromDir(getSysDir());
-
-	// Then load user presets. Note that user day presets will modify any system ones already loaded.
-	loadPresetsFromDir(getUserDir());
-}
-
-void LLWaterParamManager::loadPresetsFromDir(const std::string& dir)
-{
-	LL_DEBUGS("AppInit", "Shaders") << "Loading water presets from " << dir << LL_ENDL;
-
-	LLDirIterator dir_iter(dir, "*.xml");
-	while (1)
-	{
-		std::string file;
-		if (!dir_iter.next(file))
-		{
-			break; // no more files
-		}
-
-		std::string path = gDirUtilp->add(dir, file);
-		if (!loadPreset(path))
-		{
-			LL_WARNS() << "Error loading water preset from " << path << LL_ENDL;
-		}
-	}
-}
-
-bool LLWaterParamManager::loadPreset(const std::string& path)
-{
-	llifstream xml_file;
-	std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
-
-	xml_file.open(path.c_str());
-	if (!xml_file)
-	{
-		return false;
-	}
-
-	LL_DEBUGS("AppInit", "Shaders") << "Loading water " << name << LL_ENDL;
-
-	LLSD params_data;
-	LLPointer<LLSDParser> parser = new LLSDXMLParser();
-	parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
-	xml_file.close();
-
-	if (hasParamSet(name))
-	{
-		setParamSet(name, params_data);
-	}
-	else
-	{
-		addParamSet(name, params_data);
-	}
-
-	return true;
-}
-
-void LLWaterParamManager::savePreset(const std::string & name)
-{
-	llassert(!name.empty());
-
-	// make an empty llsd
-	LLSD paramsData(LLSD::emptyMap());
-	std::string pathName(getUserDir() + LLURI::escape(name) + ".xml");
-
-	// fill it with LLSD windlight params
-	paramsData = mParamList[name].getAll();
-
-	// write to file
-	llofstream presetsXML(pathName.c_str());
-	LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
-	formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
-	presetsXML.close();
-
-	propagateParameters();
-}
-
-void LLWaterParamManager::propagateParameters(void)
-{
-	// bind the variables only if we're using shaders
-	if(gPipeline.canUseVertexShaders())
-	{
-		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
-		end_shaders = LLViewerShaderMgr::instance()->endShaders();
-		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
-		{
-			if (shaders_iter->mProgramObject != 0
-				&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
-			{
-				shaders_iter->mUniformsDirty = TRUE;
-			}
-		}
-	}
-
-	bool err;
-	F32 fog_density_slider = 
-		log(mCurParams.getFloat(mFogDensity.mName, err)) / 
-		log(mFogDensity.mBase);
-
-	setDensitySliderValue(fog_density_slider);
-}
-
-void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)
-{
-	if (shader->mShaderGroup == LLGLSLShader::SG_WATER)
-	{
-		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV);
-shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
-		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, LLDrawPoolWater::sWaterFogColor.mV);
-		shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, mWaterPlane.mV);
-		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, getFogDensity());
-		shader->uniform1f(LLShaderMgr::WATER_FOGKS, mWaterFogKS);
-		shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);
-	}
-}
-
-void LLWaterParamManager::applyParams(const LLSD& params, bool interpolate)
-{
-	if (params.size() == 0)
-	{
-		LL_WARNS() << "Undefined water params" << LL_ENDL;
-		return;
-	}
-
-	if (interpolate)
-	{
-		LLWLParamManager::getInstance()->mAnimator.startInterpolation(params);
-	}
-	else
-	{
-		mCurParams.setAll(params);
-	}
-}
-
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_WATERPARAM("Update Water Params");
-
-void LLWaterParamManager::update(LLViewerCamera * cam)
-{
-	LL_RECORD_BLOCK_TIME(FTM_UPDATE_WATERPARAM);
-	
-	// update the shaders and the menu
-	propagateParameters();
-	
-	// only do this if we're dealing with shaders
-	if(gPipeline.canUseVertexShaders()) 
-	{
-		//transform water plane to eye space
-		glh::vec3f norm(0.f, 0.f, 1.f);
-		glh::vec3f p(0.f, 0.f, gAgent.getRegion()->getWaterHeight()+0.1f);
-		
-		F32 modelView[16];
-		for (U32 i = 0; i < 16; i++)
-		{
-			modelView[i] = (F32) gGLModelView[i];
-		}
-
-		glh::matrix4f mat(modelView);
-		glh::matrix4f invtrans = mat.inverse().transpose();
-		glh::vec3f enorm;
-		glh::vec3f ep;
-		invtrans.mult_matrix_vec(norm, enorm);
-		enorm.normalize();
-		mat.mult_matrix_vec(p, ep);
-
-		mWaterPlane = LLVector4(enorm.v[0], enorm.v[1], enorm.v[2], -ep.dot(enorm));
-
-		LLVector3 sunMoonDir;
-		if (gSky.getSunDirection().mV[2] > LLSky::NIGHTTIME_ELEVATION_COS) 	 
-		{ 	 
-			sunMoonDir = gSky.getSunDirection(); 	 
-		} 	 
-		else  	 
-		{ 	 
-			sunMoonDir = gSky.getMoonDirection(); 	 
-		}
-		sunMoonDir.normVec();
-		mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP);
-
-		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
-		end_shaders = LLViewerShaderMgr::instance()->endShaders();
-		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
-		{
-			if (shaders_iter->mProgramObject != 0
-				&& shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)
-			{
-				shaders_iter->mUniformsDirty = TRUE;
-			}
-		}
-	}
-}
-
-bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param)
-{
-	// add a new one if not one there already
-	preset_map_t::iterator mIt = mParamList.find(name);
-	if(mIt == mParamList.end()) 
-	{	
-		mParamList[name] = param;
-		mPresetListChangeSignal();
-		return true;
-	}
-
-	return false;
-}
-
-BOOL LLWaterParamManager::addParamSet(const std::string& name, LLSD const & param)
-{
-	LLWaterParamSet param_set;
-	param_set.setAll(param);
-	return addParamSet(name, param_set);
-}
-
-bool LLWaterParamManager::getParamSet(const std::string& name, LLWaterParamSet& param)
-{
-	// find it and set it
-	preset_map_t::iterator mIt = mParamList.find(name);
-	if(mIt != mParamList.end()) 
-	{
-		param = mParamList[name];
-		param.mName = name;
-		return true;
-	}
-
-	return false;
-}
-
-bool LLWaterParamManager::hasParamSet(const std::string& name)
-{
-	LLWaterParamSet dummy;
-	return getParamSet(name, dummy);
-}
-
-bool LLWaterParamManager::setParamSet(const std::string& name, LLWaterParamSet& param)
-{
-	mParamList[name] = param;
-
-	return true;
-}
-
-bool LLWaterParamManager::setParamSet(const std::string& name, const LLSD & param)
-{
-	// quick, non robust (we won't be working with files, but assets) check
-	if(!param.isMap()) 
-	{
-		return false;
-	}
-	
-	mParamList[name].setAll(param);
-
-	return true;
-}
-
-bool LLWaterParamManager::removeParamSet(const std::string& name, bool delete_from_disk)
-{
-	// remove from param list
-	preset_map_t::iterator it = mParamList.find(name);
-	if (it == mParamList.end())
-	{
-		LL_WARNS("WindLight") << "No water preset named " << name << LL_ENDL;
-		return false;
-	}
-
-	mParamList.erase(it);
-
-	// remove from file system if requested
-	if (delete_from_disk)
-	{
-		if (gDirUtilp->deleteFilesInDir(getUserDir(), LLURI::escape(name) + ".xml") < 1)
-		{
-			LL_WARNS("WindLight") << "Error removing water preset " << name << " from disk" << LL_ENDL;
-		}
-	}
-
-	// signal interested parties
-	mPresetListChangeSignal();
-	return true;
-}
-
-bool LLWaterParamManager::isSystemPreset(const std::string& preset_name) const
-{
-	// *TODO: file system access is excessive here.
-	return gDirUtilp->fileExists(getSysDir() + LLURI::escape(preset_name) + ".xml");
-}
-
-void LLWaterParamManager::getPresetNames(preset_name_list_t& presets) const
-{
-	presets.clear();
-
-	for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
-	{
-		presets.push_back(it->first);
-	}
-}
-
-void LLWaterParamManager::getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const
-{
-	user_presets.clear();
-	system_presets.clear();
-
-	for (preset_map_t::const_iterator it = mParamList.begin(); it != mParamList.end(); ++it)
-	{
-		if (isSystemPreset(it->first))
-		{
-			system_presets.push_back(it->first);
-		}
-		else
-		{
-			user_presets.push_back(it->first);
-		}
-	}
-}
-
-void LLWaterParamManager::getUserPresetNames(preset_name_list_t& user_presets) const
-{
-	preset_name_list_t dummy;
-	getPresetNames(user_presets, dummy);
-}
-
-boost::signals2::connection LLWaterParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
-{
-	return mPresetListChangeSignal.connect(cb);
-}
-
-F32 LLWaterParamManager::getFogDensity(void)
-{
-	bool err;
-
-	F32 fogDensity = mCurParams.getFloat("waterFogDensity", err);
-	
-	// modify if we're underwater
-	const F32 water_height = gAgent.getRegion() ? gAgent.getRegion()->getWaterHeight() : 0.f;
-	F32 camera_height = gAgentCamera.getCameraPositionAgent().mV[2];
-	if(camera_height <= water_height)
-	{
-		// raise it to the underwater fog density modifier
-		fogDensity = pow(fogDensity, mCurParams.getFloat("underWaterFogMod", err));
-	}
-
-	return fogDensity;
-}
-
-// virtual static
-void LLWaterParamManager::initSingleton()
-{
-	LL_DEBUGS("Windlight") << "Initializing water" << LL_ENDL;
-	loadAllPresets();
-}
-
-// static
-std::string LLWaterParamManager::getSysDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/water", "");
-}
-
-// static
-std::string LLWaterParamManager::getUserDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/water", "");
-}
diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h
deleted file mode 100644
index 3f169e439a607d52110112e5c2f19326f5a2e795..0000000000000000000000000000000000000000
--- a/indra/newview/llwaterparammanager.h
+++ /dev/null
@@ -1,413 +0,0 @@
-/**
- * @file llwaterparammanager.h
- * @brief Implementation for the LLWaterParamManager class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_WATER_PARAMMANAGER_H
-#define LL_WATER_PARAMMANAGER_H
-
-#include <list>
-#include <map>
-#include "llwaterparamset.h"
-#include "llviewercamera.h"
-#include "v4color.h"
-
-const F32 WATER_FOG_LIGHT_CLAMP = 0.3f;
-
-// color control
-struct WaterColorControl {
-	
-	F32 mR, mG, mB, mA, mI;			/// the values
-	std::string mName;				/// name to use to dereference params
-	std::string mSliderName;		/// name of the slider in menu
-	bool mHasSliderName;			/// only set slider name for true color types
-
-	inline WaterColorControl(F32 red, F32 green, F32 blue, F32 alpha,
-							 F32 intensity, const std::string& n, const std::string& sliderName = LLStringUtil::null)
-		: mR(red), mG(green), mB(blue), mA(alpha), mI(intensity), mName(n), mSliderName(sliderName)
-	{
-		// if there's a slider name, say we have one
-		mHasSliderName = false;
-		if (mSliderName != "") {
-			mHasSliderName = true;
-		}
-	}
-
-	inline WaterColorControl & operator = (LLColor4 const & val) 
-	{
-		mR = val.mV[0];
-		mG = val.mV[1];
-		mB = val.mV[2];
-		mA = val.mV[3];		
-		return *this;
-	}
-
-	inline operator LLColor4 (void) const
-	{
-		return LLColor4(mR, mG, mB, mA);
-	}
-
-	inline WaterColorControl & operator = (LLVector4 const & val) 
-	{
-		mR = val.mV[0];
-		mG = val.mV[1];
-		mB = val.mV[2];
-		mA = val.mV[3];		
-		return *this;
-	}
-
-	inline operator LLVector4 (void) const 
-	{
-		return LLVector4(mR, mG, mB, mA);
-	}
-
-	inline operator LLVector3 (void) const 
-	{
-		return LLVector3(mR, mG, mB);
-	}
-
-	inline void update(LLWaterParamSet & params) const 
-	{
-		params.set(mName, mR, mG, mB, mA);
-	}
-};
-
-struct WaterVector3Control 
-{
-	F32 mX;
-	F32 mY;
-	F32 mZ;
-
-	std::string mName;
-
-	// basic constructor
-	inline WaterVector3Control(F32 valX, F32 valY, F32 valZ, const std::string& n)
-		: mX(valX), mY(valY), mZ(valZ), mName(n)
-	{
-	}
-
-	inline WaterVector3Control & operator = (LLVector3 const & val) 
-	{
-		mX = val.mV[0];
-		mY = val.mV[1];
-		mZ = val.mV[2];
-
-		return *this;
-	}
-
-	inline void update(LLWaterParamSet & params) const 
-	{
-		params.set(mName, mX, mY, mZ);
-	}
-
-};
-
-struct WaterVector2Control 
-{
-	F32 mX;
-	F32 mY;
-
-	std::string mName;
-
-	// basic constructor
-	inline WaterVector2Control(F32 valX, F32 valY, const std::string& n)
-		: mX(valX), mY(valY), mName(n)
-	{
-	}
-
-	inline WaterVector2Control & operator = (LLVector2 const & val) 
-	{
-		mX = val.mV[0];
-		mY = val.mV[1];
-
-		return *this;
-	}
-
-	inline void update(LLWaterParamSet & params) const 
-	{
-		params.set(mName, mX, mY);
-	}
-};
-
-// float slider control
-struct WaterFloatControl 
-{
-	F32 mX;
-	std::string mName;
-	F32 mMult;
-
-	inline WaterFloatControl(F32 val, const std::string& n, F32 m=1.0f)
-		: mX(val), mName(n), mMult(m)
-	{
-	}
-
-	inline WaterFloatControl & operator = (LLVector4 const & val) 
-	{
-		mX = val.mV[0];
-
-		return *this;
-	}
-
-	inline operator F32 (void) const 
-	{
-		return mX;
-	}
-
-	inline void update(LLWaterParamSet & params) const 
-	{
-		params.set(mName, mX);
-	}
-};
-
-// float slider control
-struct WaterExpFloatControl 
-{
-	F32 mExp;
-	std::string mName;
-	F32 mBase;
-
-	inline WaterExpFloatControl(F32 val, const std::string& n, F32 b)
-		: mExp(val), mName(n), mBase(b)
-	{
-	}
-
-	inline WaterExpFloatControl & operator = (F32 val) 
-	{
-		mExp = log(val) / log(mBase);
-
-		return *this;
-	}
-
-	inline operator F32 (void) const 
-	{
-		return pow(mBase, mExp);
-	}
-
-	inline void update(LLWaterParamSet & params) const 
-	{
-		params.set(mName, pow(mBase, mExp));
-	}
-};
-
-
-/// WindLight parameter manager class - what controls all the wind light shaders
-class LLWaterParamManager : public LLSingleton<LLWaterParamManager>
-{
-	LLSINGLETON(LLWaterParamManager);
-	~LLWaterParamManager();
-	LOG_CLASS(LLWaterParamManager);
-public:
-	typedef std::list<std::string> preset_name_list_t;
-	typedef std::map<std::string, LLWaterParamSet> preset_map_t;
-	typedef boost::signals2::signal<void()> preset_list_signal_t;
-
-	/// save the parameter presets to file
-	void savePreset(const std::string & name);
-
-	/// send the parameters to the shaders
-	void propagateParameters(void);
-
-	// display specified water
-	void applyParams(const LLSD& params, bool interpolate);
-
-	/// update information for the shader
-	void update(LLViewerCamera * cam);
-
-	/// Update shader uniforms that have changed.
-	void updateShaderUniforms(LLGLSLShader * shader);
-
-	/// add a param to the list
-	bool addParamSet(const std::string& name, LLWaterParamSet& param);
-
-	/// add a param to the list
-	BOOL addParamSet(const std::string& name, LLSD const & param);
-
-	/// get a param from the list
-	bool getParamSet(const std::string& name, LLWaterParamSet& param);
-
-	/// check whether the preset is in the list
-	bool hasParamSet(const std::string& name);
-
-	/// set the param in the list with a new param
-	bool setParamSet(const std::string& name, LLWaterParamSet& param);
-	
-	/// set the param in the list with a new param
-	bool setParamSet(const std::string& name, LLSD const & param);	
-
-	/// gets rid of a parameter and any references to it
-	/// returns true if successful
-	bool removeParamSet(const std::string& name, bool delete_from_disk);
-
-	/// @return true if the preset comes out of the box
-	bool isSystemPreset(const std::string& preset_name) const;
-
-	/// @return all named water presets.
-	const preset_map_t& getPresets() const { return mParamList; }
-
-	/// @return user and system preset names as a single list
-	void getPresetNames(preset_name_list_t& presets) const;
-
-	/// @return user and system preset names separately
-	void getPresetNames(preset_name_list_t& user_presets, preset_name_list_t& system_presets) const;
-
-	/// @return list of user presets names
-	void getUserPresetNames(preset_name_list_t& user_presets) const;
-
-	/// Emitted when a preset gets added or deleted.
-	boost::signals2::connection setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb);
-
-	/// set the normap map we want for water
-	bool setNormalMapID(const LLUUID& img);
-
-	void setDensitySliderValue(F32 val);
-
-	/// getters for all the different things water param manager maintains
-	LLUUID getNormalMapID(void);
-	LLVector2 getWave1Dir(void);
-	LLVector2 getWave2Dir(void);
-	F32 getScaleAbove(void);
-	F32 getScaleBelow(void);
-	LLVector3 getNormalScale(void);
-	F32 getFresnelScale(void);
-	F32 getFresnelOffset(void);
-	F32 getBlurMultiplier(void);
-	F32 getFogDensity(void);
-	LLColor4 getFogColor(void);
-
-public:
-
-	LLWaterParamSet mCurParams;
-
-	/// Atmospherics
-	WaterColorControl mFogColor;
-	WaterExpFloatControl mFogDensity;
-	WaterFloatControl mUnderWaterFogMod;
-
-	/// wavelet scales and directions
-	WaterVector3Control mNormalScale;
-	WaterVector2Control mWave1Dir;
-	WaterVector2Control mWave2Dir;
-
-	// controls how water is reflected and refracted
-	WaterFloatControl mFresnelScale;
-	WaterFloatControl mFresnelOffset;
-	WaterFloatControl mScaleAbove;
-	WaterFloatControl mScaleBelow;
-	WaterFloatControl mBlurMultiplier;
-	
-	F32 mDensitySliderValue;
-
-private:
-	/*virtual*/ void initSingleton();
-	void loadAllPresets();
-	void loadPresetsFromDir(const std::string& dir);
-	bool loadPreset(const std::string& path);
-
-	static std::string getSysDir();
-	static std::string getUserDir();
-
-	LLVector4 mWaterPlane;
-	F32 mWaterFogKS;
-
-	// list of all the parameters, listed by name
-	preset_map_t mParamList;
-
-	preset_list_signal_t mPresetListChangeSignal;
-};
-
-inline void LLWaterParamManager::setDensitySliderValue(F32 val)
-{
-	val /= 10.0f;
-	val = 1.0f - val;
-	val *= val * val;
-//	val *= val;
-	mDensitySliderValue = val;
-}
-
-inline LLUUID LLWaterParamManager::getNormalMapID()
-{	
-	return mCurParams.mParamValues["normalMap"].asUUID();
-}
-
-inline bool LLWaterParamManager::setNormalMapID(const LLUUID& id)
-{
-	mCurParams.mParamValues["normalMap"] = id;
-	return true;
-}
-
-inline LLVector2 LLWaterParamManager::getWave1Dir(void)
-{
-	bool err;
-	return mCurParams.getVector2("wave1Dir", err);
-}
-
-inline LLVector2 LLWaterParamManager::getWave2Dir(void)
-{
-	bool err;
-	return mCurParams.getVector2("wave2Dir", err);
-}
-
-inline F32 LLWaterParamManager::getScaleAbove(void)
-{
-	bool err;
-	return mCurParams.getFloat("scaleAbove", err);
-}
-
-inline F32 LLWaterParamManager::getScaleBelow(void)
-{
-	bool err;
-	return mCurParams.getFloat("scaleBelow", err);
-}
-
-inline LLVector3 LLWaterParamManager::getNormalScale(void)
-{
-	bool err;
-	return mCurParams.getVector3("normScale", err);
-}
-
-inline F32 LLWaterParamManager::getFresnelScale(void)
-{
-	bool err;
-	return mCurParams.getFloat("fresnelScale", err);
-}
-
-inline F32 LLWaterParamManager::getFresnelOffset(void)
-{
-	bool err;
-	return mCurParams.getFloat("fresnelOffset", err);
-}
-
-inline F32 LLWaterParamManager::getBlurMultiplier(void)
-{
-	bool err;
-	return mCurParams.getFloat("blurMultiplier", err);
-}
-
-inline LLColor4 LLWaterParamManager::getFogColor(void)
-{
-	bool err;
-	return LLColor4(mCurParams.getVector4("waterFogColor", err));
-}
-
-#endif
diff --git a/indra/newview/llwaterparamset.cpp b/indra/newview/llwaterparamset.cpp
deleted file mode 100644
index 9cc91d2246ac2f3ee6021e5cb27e3c0840c24ef0..0000000000000000000000000000000000000000
--- a/indra/newview/llwaterparamset.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/**
- * @file llwaterparamset.cpp
- * @brief Implementation for the LLWaterParamSet class.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llwaterparamset.h"
-#include "llsd.h"
-
-#include "llwaterparammanager.h"
-#include "lluictrlfactory.h"
-#include "llsliderctrl.h"
-#include "llviewertexturelist.h"
-#include "llviewercontrol.h"
-#include "lluuid.h"
-
-#include <llgl.h>
-
-#include <sstream>
-
-LLWaterParamSet::LLWaterParamSet(void) :
-	mName("Unnamed Preset")
-{
-	LLSD vec4;
-	LLSD vec3;
-	LLSD real(0.0f);
-
-	vec4 = LLSD::emptyArray();
-	vec4.append(22.f/255.f);
-	vec4.append(43.f/255.f);
-	vec4.append(54.f/255.f);
-	vec4.append(0.f/255.f);
-
-	vec3 = LLSD::emptyArray();
-	vec3.append(2);
-	vec3.append(2);
-	vec3.append(2);
-
-	LLSD wave1, wave2;
-	wave1 = LLSD::emptyArray();
-	wave2 = LLSD::emptyArray();
-	wave1.append(0.5f);
-	wave1.append(-.17f);
-	wave2.append(0.58f);
-	wave2.append(-.67f);
-
-	mParamValues.insert("waterFogColor", vec4);
-	mParamValues.insert("waterFogDensity", 16.0f);
-	mParamValues.insert("underWaterFogMod", 0.25f);
-	mParamValues.insert("normScale", vec3);
-	mParamValues.insert("fresnelScale", 0.5f);
-	mParamValues.insert("fresnelOffset", 0.4f);
-	mParamValues.insert("scaleAbove", 0.025f);
-	mParamValues.insert("scaleBelow", 0.2f);
-	mParamValues.insert("blurMultiplier", 0.01f);
-	mParamValues.insert("wave1Dir", wave1);
-	mParamValues.insert("wave2Dir", wave2);
-	mParamValues.insert("normalMap", DEFAULT_WATER_NORMAL);
-
-}
-
-void LLWaterParamSet::set(const std::string& paramName, float x) 
-{	
-	// handle case where no array
-	if(mParamValues[paramName].isReal()) 
-	{
-		mParamValues[paramName] = x;
-	} 
-	
-	// handle array
-	else if(mParamValues[paramName].isArray() &&
-			mParamValues[paramName][0].isReal())
-	{
-		mParamValues[paramName][0] = x;
-	}
-}
-
-void LLWaterParamSet::set(const std::string& paramName, float x, float y) {
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-}
-
-void LLWaterParamSet::set(const std::string& paramName, float x, float y, float z)
-{
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-	mParamValues[paramName][2] = z;
-}
-
-void LLWaterParamSet::set(const std::string& paramName, float x, float y, float z, float w) 
-{
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-	mParamValues[paramName][2] = z;
-	mParamValues[paramName][3] = w;
-}
-
-void LLWaterParamSet::set(const std::string& paramName, const float * val) 
-{
-	mParamValues[paramName][0] = val[0];
-	mParamValues[paramName][1] = val[1];
-	mParamValues[paramName][2] = val[2];
-	mParamValues[paramName][3] = val[3];
-}
-
-void LLWaterParamSet::set(const std::string& paramName, const LLVector4 & val) 
-{
-	mParamValues[paramName][0] = val.mV[0];
-	mParamValues[paramName][1] = val.mV[1];
-	mParamValues[paramName][2] = val.mV[2];
-	mParamValues[paramName][3] = val.mV[3];
-}
-
-void LLWaterParamSet::set(const std::string& paramName, const LLColor4 & val) 
-{
-	mParamValues[paramName][0] = val.mV[0];
-	mParamValues[paramName][1] = val.mV[1];
-	mParamValues[paramName][2] = val.mV[2];
-	mParamValues[paramName][3] = val.mV[3];
-}
-
-LLVector4 LLWaterParamSet::getVector4(const std::string& paramName, bool& error) 
-{
-	
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (!cur_val.isArray() || cur_val.size() != 4) 
-	{
-		error = true;
-		return LLVector4(0,0,0,0);
-	}
-	
-	LLVector4 val;
-	val.mV[0] = (F32) cur_val[0].asReal();
-	val.mV[1] = (F32) cur_val[1].asReal();
-	val.mV[2] = (F32) cur_val[2].asReal();
-	val.mV[3] = (F32) cur_val[3].asReal();
-	
-	error = false;
-	return val;
-}
-
-LLVector3 LLWaterParamSet::getVector3(const std::string& paramName, bool& error) 
-{
-	
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (!cur_val.isArray()|| cur_val.size() != 3) 
-	{
-		error = true;
-		return LLVector3(0,0,0);
-	}
-	
-	LLVector3 val;
-	val.mV[0] = (F32) cur_val[0].asReal();
-	val.mV[1] = (F32) cur_val[1].asReal();
-	val.mV[2] = (F32) cur_val[2].asReal();
-	
-	error = false;
-	return val;
-}
-
-LLVector2 LLWaterParamSet::getVector2(const std::string& paramName, bool& error) 
-{
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (!cur_val.isArray() || cur_val.size() != 2) 
-	{
-		error = true;
-		return LLVector2(0,0);
-	}
-	
-	LLVector2 val;
-	val.mV[0] = (F32) cur_val[0].asReal();
-	val.mV[1] = (F32) cur_val[1].asReal();
-	
-	error = false;
-	return val;
-}
-
-F32 LLWaterParamSet::getFloat(const std::string& paramName, bool& error) 
-{
-	
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (cur_val.isArray() && cur_val.size() != 0)
-	{
-		error = false;
-		return (F32) cur_val[0].asReal();	
-	}
-	
-	if(cur_val.isReal())
-	{
-		error = false;
-		return (F32) cur_val.asReal();
-	}
-	
-	error = true;
-	return 0;
-}
-
-// Added for interpolation effect in DEV-33645
-// Based on LLWLParamSet::mix, but written by Jacob without an intimate knowledge of how WindLight works.
-// The function definition existed in the header but was never implemented.  If you think there is something
-// wrong with this, you're probably right.  Ask Jacob, Q, or a member of the original WindLight team.
-void LLWaterParamSet::mix(LLWaterParamSet& src, LLWaterParamSet& dest, F32 weight)
-{
-	// Setup
-	LLSD srcVal, destVal;													// LLSD holders for get/set calls, reusable
-
-	// Iterate through values
-	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
-	{
-		// If param exists in both src and dest, set the holder variables, otherwise skip
-		if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
-		{
-			srcVal = src.mParamValues[iter->first];
-			destVal = dest.mParamValues[iter->first];
-		}
-		else
-		{
-			continue;
-		}
-		
-		if(iter->second.isReal())									// If it's a real, interpolate directly
-		{
-			iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight);
-		}		
-		else if(iter->second.isArray() && iter->second[0].isReal()	// If it's an array of reals, loop through the reals and interpolate on those
-				&& iter->second.size() == srcVal.size() && iter->second.size() == destVal.size())
-		{
-			// Actually do interpolation: old value + (difference in values * factor)
-			for(int i=0; i < iter->second.size(); ++i) 
-			{
-				// iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal();	// old way of doing it -- equivalent but one more operation
-				iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight);
-			}
-		}
-		else														// Else, skip
-		{
-			continue;
-		}
-	}
-}
diff --git a/indra/newview/llwaterparamset.h b/indra/newview/llwaterparamset.h
deleted file mode 100644
index 368cb0ccba9362e43ed9bbf2b555ec0e6d024a11..0000000000000000000000000000000000000000
--- a/indra/newview/llwaterparamset.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/**
- * @file llwlparamset.h
- * @brief Interface for the LLWaterParamSet class.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_WATER_PARAM_SET_H
-#define LL_WATER_PARAM_SET_H
-
-#include <string>
-#include <map>
-
-#include "v4math.h"
-#include "v4color.h"
-#include "llviewershadermgr.h"
-#include "llstringtable.h"
-
-class LLWaterParamSet;
-
-/// A class representing a set of parameter values for the Water shaders.
-class LLWaterParamSet 
-{
-	friend class LLWaterParamManager;
-
-public:
-	std::string mName;	
-	
-private:
-
-	LLSD mParamValues;
-	std::vector<LLStaticHashedString> mParamHashedNames;
-
-	void updateHashedNames();
-
-public:
-
-	LLWaterParamSet();
-
-	/// Bind this set of parameter values to the uniforms of a particular shader.
-	void update(LLGLSLShader * shader) const;
-
-	/// set the total llsd
-	void setAll(const LLSD& val);
-	
-	/// get the total llsd
-	const LLSD& getAll();		
-
-	/// Set a float parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The float value to set.
-	void set(const std::string& paramName, float x);
-
-	/// Set a float2 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	void set(const std::string& paramName, float x, float y);
-
-	/// Set a float3 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	/// \param z			The z component's value to set.
-	void set(const std::string& paramName, float x, float y, float z);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	/// \param z			The z component's value to set.
-	/// \param w			The w component's value to set.
-	void set(const std::string& paramName, float x, float y, float z, float w);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			An array of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const float * val);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			A struct of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const LLVector4 & val);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			A struct of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const LLColor4 & val);
-
-	/// Get a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type
-	LLVector4 getVector4(const std::string& paramName, bool& error);
-
-	/// Get a float3 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type
-	LLVector3 getVector3(const std::string& paramName, bool& error);
-	
-	/// Get a float2 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type
-	LLVector2 getVector2(const std::string& paramName, bool& error);
-	
-	/// Get an integer parameter
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type	
-	F32 getFloat(const std::string& paramName, bool& error);
-		
-	/// interpolate two parameter sets
-	/// \param src			The parameter set to start with
-	/// \param dest			The parameter set to end with
-	/// \param weight		The amount to interpolate
-	void mix(LLWaterParamSet& src, LLWaterParamSet& dest, 
-		F32 weight);
-
-};
-
-inline void LLWaterParamSet::setAll(const LLSD& val)
-{
-	if(val.isMap()) {
-		LLSD::map_const_iterator mIt = val.beginMap();
-		for(; mIt != val.endMap(); mIt++)
-		{
-			mParamValues[mIt->first] = mIt->second;
-		}
-	}
-	updateHashedNames();
-}
-
-inline void LLWaterParamSet::updateHashedNames()
-{
-	mParamHashedNames.clear();
-	// Iterate through values
-	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
-	{
-		mParamHashedNames.push_back(LLStaticHashedString(iter->first));
-	}
-}
-
-inline const LLSD& LLWaterParamSet::getAll()
-{
-	return mParamValues;
-}
-
-#endif // LL_WaterPARAM_SET_H
diff --git a/indra/newview/llwlanimator.cpp b/indra/newview/llwlanimator.cpp
deleted file mode 100644
index c8879e73ebad1597da3488eeb00a931ea826f613..0000000000000000000000000000000000000000
--- a/indra/newview/llwlanimator.cpp
+++ /dev/null
@@ -1,324 +0,0 @@
-/**
- * @file llwlanimator.cpp
- * @brief Implementation for the LLWLAnimator class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llwlanimator.h"
-#include "llsky.h"
-#include "pipeline.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
-
-extern LLControlGroup gSavedSettings;
-
-F64 LLWLAnimator::INTERP_TOTAL_SECONDS = 3.f;
-
-LLWLAnimator::LLWLAnimator() : mStartTime(0.f), mDayRate(1.f), mDayTime(0.f),
-							mIsRunning(FALSE), mIsInterpolating(FALSE), mTimeType(TIME_LINDEN),
-							mInterpStartTime(), mInterpEndTime()
-{
-	mInterpBeginWL = new LLWLParamSet();
-	mInterpBeginWater = new LLWaterParamSet();
-	mInterpEndWater = new LLWaterParamSet();
-}
-
-void LLWLAnimator::update(LLWLParamSet& curParams)
-{
-	//llassert(mUseLindenTime != mUseLocalTime);
-
-	F64 curTime;
-	curTime = getDayTime();
-
-	// don't do anything if empty
-	if(mTimeTrack.size() == 0)
-	{
-		return;
-	}
-
-	// start it off
-	mFirstIt = mTimeTrack.begin();
-	mSecondIt = mTimeTrack.begin();
-	mSecondIt++;
-
-	// grab the two tween iterators
-	while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first)
-	{
-		mFirstIt++;
-		mSecondIt++;
-	}
-
-	// scroll it around when you get to the end
-	if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime)
-	{
-		mSecondIt = mTimeTrack.begin();
-		mFirstIt = mTimeTrack.end();
-		mFirstIt--;
-	}
-
-	F32 weight = 0;
-
-	if(mFirstIt->first < mSecondIt->first)
-	{
-	
-		// get the delta time and the proper weight
-		weight = F32 (curTime - mFirstIt->first) / 
-			(mSecondIt->first - mFirstIt->first);
-	
-	// handle the ends
-	}
-	else if(mFirstIt->first > mSecondIt->first)
-	{
-		
-		// right edge of time line
-		if(curTime >= mFirstIt->first)
-		{
-			weight = F32 (curTime - mFirstIt->first) /
-			((1 + mSecondIt->first) - mFirstIt->first);
-		// left edge of time line
-		}
-		else
-		{
-			weight = F32 ((1 + curTime) - mFirstIt->first) /
-			((1 + mSecondIt->first) - mFirstIt->first);
-		}
-
-	// handle same as whatever the last one is
-	}
-	else
-	{
-		weight = 1;
-	}
-
-	if(mIsInterpolating)
-	{
-		// *TODO_JACOB: this is kind of laggy.  Not sure why.  The part that lags is the curParams.mix call, and none of the other mixes.  It works, though.
-		clock_t current = clock();
-		if(current >= mInterpEndTime)
-		{
-			mIsInterpolating = false;
-			return;
-		}
-		
-		// determine moving target for final interpolation value
-		// *TODO: this will not work with lazy loading of sky presets.
-		LLWLParamSet buf = LLWLParamSet();
-		buf.setAll(LLWLParamManager::getInstance()->mParamList[mFirstIt->second].getAll());	// just give it some values, otherwise it has no params to begin with (see comment in constructor)
-		buf.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight);	// mix to determine moving target for interpolation finish (as below)
-
-		// mix from previous value to moving target
-		weight = (current - mInterpStartTime) / (INTERP_TOTAL_SECONDS * CLOCKS_PER_SEC);
-		curParams.mix(*mInterpBeginWL, buf, weight);
-		
-		// mix water
-		LLWaterParamManager::getInstance()->mCurParams.mix(*mInterpBeginWater, *mInterpEndWater, weight);
-	}
-	else
-	{
-	// do the interpolation and set the parameters
-		// *TODO: this will not work with lazy loading of sky presets.
-		curParams.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight);
-	}
-}
-
-F64 LLWLAnimator::getDayTime()
-{
-	if(!mIsRunning)
-	{
-		return mDayTime;
-	}
-	else if(mTimeType == TIME_LINDEN)
-	{
-		F32 phase = gSky.getSunPhase() / F_PI;
-
-		// we're not solving the non-linear equation that determines sun phase
-		// we're just linearly interpolating between the major points
-
-		if (phase <= 5.0 / 4.0)
-		{
-			// mDayTime from 0.33 to 0.75 (6:00 to 21:00)
-			mDayTime = (1.0 / 3.0) * phase + (1.0 / 3.0);
-		}
-		else if (phase > 7.0 / 4.0)
-		{
-			// maximum value for phase is 2
-			// mDayTime from 0.25 to 0.33 (3:00 to 6:00)
-			mDayTime = (1.0 / 3.0) - (1.0 / 3.0) * (2 - phase);
-		}
-		else
-		{
-			// phase == 3/2 is where day restarts (24:00)
-			// mDayTime from 0.75 to 0.999 and 0 to 0.25 (21:00 to 03:00)
-			mDayTime = phase - (1.0 / 2.0);
-
-			if(mDayTime > 1)
-			{
-				mDayTime--;
-			}
-		}
-
-		return mDayTime;
-	}
-	else if(mTimeType == TIME_LOCAL)
-	{
-		return getLocalTime();
-	}
-
-	// get the time;
-	mDayTime = (LLTimer::getElapsedSeconds() - mStartTime) / mDayRate;
-
-	// clamp it
-	if(mDayTime < 0)
-	{
-		mDayTime = 0;
-	} 
-	while(mDayTime > 1)
-	{
-		mDayTime--;
-	}
-
-	return (F32)mDayTime;
-}
-
-void LLWLAnimator::setDayTime(F64 dayTime)
-{
-	//retroactively set start time;
-	mStartTime = LLTimer::getElapsedSeconds() - dayTime * mDayRate;
-	mDayTime = dayTime;
-
-	// clamp it
-	if(mDayTime < 0)
-	{
-		mDayTime = 0;
-	}
-	else if(mDayTime > 1)
-	{
-		mDayTime = 1;
-	}
-}
-
-
-void LLWLAnimator::setTrack(std::map<F32, LLWLParamKey>& curTrack,
-							F32 dayRate, F64 dayTime, bool run)
-{
-	mTimeTrack = curTrack;
-	mDayRate = dayRate;
-	setDayTime(dayTime);
-
-	mIsRunning = run;
-}
-
-void LLWLAnimator::startInterpolation(const LLSD& targetWater)
-{
-	mInterpBeginWL->setAll(LLWLParamManager::getInstance()->mCurParams.getAll());
-	mInterpBeginWater->setAll(LLWaterParamManager::getInstance()->mCurParams.getAll());
-	
-	mInterpStartTime = clock();
-	mInterpEndTime = mInterpStartTime + clock_t(INTERP_TOTAL_SECONDS) * CLOCKS_PER_SEC;
-
-	// Don't set any ending WL -- this is continuously calculated as the animator updates since it's a moving target
-	mInterpEndWater->setAll(targetWater);
-
-	mIsInterpolating = true;
-}
-
-std::string LLWLAnimator::timeToString(F32 curTime)
-{
-	S32 hours;
-	S32 min;
-	bool isPM = false;
-
-	// get hours and minutes
-	hours = (S32) (24.0 * curTime);
-	curTime -= ((F32) hours / 24.0f);
-	min = ll_round(24.0f * 60.0f * curTime);
-
-	// handle case where it's 60
-	if(min == 60) 
-	{
-		hours++;
-		min = 0;
-	}
-
-	// set for PM
-	if(hours >= 12 && hours < 24)
-	{
-		isPM = true;
-	}
-
-	// convert to non-military notation
-	if(hours >= 24) 
-	{
-		hours = 12;
-	} 
-	else if(hours > 12) 
-	{
-		hours -= 12;
-	} 
-	else if(hours == 0) 
-	{
-		hours = 12;
-	}
-
-	// make the string
-	std::stringstream newTime;
-	newTime << hours << ":";
-	
-	// double 0
-	if(min < 10) 
-	{
-		newTime << 0;
-	}
-	
-	// finish it
-	newTime << min << " ";
-	if(isPM) 
-	{
-		newTime << "PM";
-	} 
-	else 
-	{
-		newTime << "AM";
-	}
-
-	return newTime.str();
-}
-
-F64 LLWLAnimator::getLocalTime()
-{
-	char buffer[9];
-	time_t rawtime;
-	struct tm* timeinfo;
-
-	time(&rawtime);
-	timeinfo = localtime(&rawtime);
-	strftime(buffer, 9, "%H:%M:%S", timeinfo);
-	std::string timeStr(buffer);
-
-	F64 tod = ((F64)atoi(timeStr.substr(0,2).c_str())) / 24.f +
-			  ((F64)atoi(timeStr.substr(3,2).c_str())) / 1440.f + 
-			  ((F64)atoi(timeStr.substr(6,2).c_str())) / 86400.f;
-	return tod;
-}
diff --git a/indra/newview/llwlanimator.h b/indra/newview/llwlanimator.h
deleted file mode 100644
index e2e49c73051555cddda76bfa33a6431b42b979e1..0000000000000000000000000000000000000000
--- a/indra/newview/llwlanimator.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * @file llwlanimator.h
- * @brief Interface for the LLWLAnimator class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_WL_ANIMATOR_H
-#define LL_WL_ANIMATOR_H
-
-#include "llwlparamset.h"
-#include "llenvmanager.h"
-#include "llwaterparamset.h"
-#include <string>
-#include <map>
-
-class LLWLAnimator {
-public:
-	typedef enum e_time
-	{
-		TIME_LINDEN,
-		TIME_LOCAL,
-		TIME_CUSTOM
-	} ETime;
-
-	F64 mStartTime;
-	F32 mDayRate;
-	F64 mDayTime;
-	
-	// track to play
-	std::map<F32, LLWLParamKey> mTimeTrack;
-	std::map<F32, LLWLParamKey>::iterator mFirstIt, mSecondIt;
-
-	// simple constructor
-	LLWLAnimator();
-
-	~LLWLAnimator()
-	{
-		delete mInterpBeginWL;
-		delete mInterpBeginWater;
-		delete mInterpEndWater;
-	}
-
-	// update the parameters
-	void update(LLWLParamSet& curParams);
-
-	// get time in seconds
-	//F64 getTime(void);
-
-	// returns a float 0 - 1 saying what time of day is it?
-	F64 getDayTime(void);
-
-	// sets a float 0 - 1 saying what time of day it is
-	void setDayTime(F64 dayTime);
-
-	// set an animation track
-	void setTrack(std::map<F32, LLWLParamKey>& track,
-		F32 dayRate, F64 dayTime = 0, bool run = true);
-
-	void deactivate()
-	{
-		mIsRunning = false;
-	}
-
-	void activate(ETime time)
-	{
-		mIsRunning = true;
-		mTimeType = time;
-	}
-
-	void startInterpolation(const LLSD& targetWater);
-
-	bool getIsRunning()
-	{
-		return mIsRunning;
-	}
-
-	bool getUseCustomTime()
-	{
-		return mTimeType == TIME_CUSTOM;
-	}
-
-	bool getUseLocalTime()
-	{
-		return mTimeType == TIME_LOCAL;
-	}
-
-	bool getUseLindenTime()
-	{
-		return mTimeType == TIME_LINDEN;
-	}
-
-	void setTimeType(ETime time)
-	{
-		mTimeType = time;
-	}
-
-	ETime getTimeType()
-	{
-		return mTimeType;
-	}
-
-	/// convert the present time to a digital clock time
-	static std::string timeToString(F32 curTime);
-
-	/// get local time between 0 and 1
-	static F64 getLocalTime();
-
-private:
-	ETime mTimeType;
-	bool mIsRunning, mIsInterpolating;
-	LLWLParamSet *mInterpBeginWL;
-	LLWaterParamSet *mInterpBeginWater, *mInterpEndWater;
-	clock_t mInterpStartTime, mInterpEndTime;
-
-	static F64 INTERP_TOTAL_SECONDS;
-};
-
-#endif // LL_WL_ANIMATOR_H
-
diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp
index 106f17f61b8eea9cff13ae7245546677f8487d58..0a331d1823e41f0700ac46076468b8716302dfe9 100644
--- a/indra/newview/llwldaycycle.cpp
+++ b/indra/newview/llwldaycycle.cpp
@@ -46,6 +46,7 @@ LLWLDayCycle::~LLWLDayCycle()
 
 void LLWLDayCycle::loadDayCycle(const LLSD& day_data, LLWLParamKey::EScope scope)
 {
+#if 0
 	LL_DEBUGS() << "Loading day cycle (day_data.size() = " << day_data.size() << ", scope = " << scope << ")" << LL_ENDL;
 	mTimeMap.clear();
 
@@ -88,6 +89,7 @@ void LLWLDayCycle::loadDayCycle(const LLSD& day_data, LLWLParamKey::EScope scope
 		// then add the keyframe
 		addKeyframe((F32)day_data[i][0].asReal(), frame);
 	}
+#endif
 }
 
 void LLWLDayCycle::loadDayCycleFromFile(const std::string & fileName)
@@ -158,35 +160,35 @@ LLSD LLWLDayCycle::asLLSD()
 	return day_data;
 }
 
-bool LLWLDayCycle::getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const
-{
-	bool result = true;
-	LLWLParamManager& wl_mgr = LLWLParamManager::instance();
-
-	refs.clear();
-	for (std::map<F32, LLWLParamKey>::const_iterator iter = mTimeMap.begin(); iter != mTimeMap.end(); ++iter)
-	{
-		const LLWLParamKey& key = iter->second;
-		if (!wl_mgr.getParamSet(key, refs[key]))
-		{
-			LL_WARNS() << "Cannot find sky [" << key.name << "] referenced by a day cycle" << LL_ENDL;
-			result = false;
-		}
-	}
-
-	return result;
-}
+// bool LLWLDayCycle::getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const
+// {
+// 	bool result = true;
+// 	LLWLParamManager& wl_mgr = LLWLParamManager::instance();
+// 
+// 	refs.clear();
+// 	for (std::map<F32, LLWLParamKey>::const_iterator iter = mTimeMap.begin(); iter != mTimeMap.end(); ++iter)
+// 	{
+// 		const LLWLParamKey& key = iter->second;
+// 		if (!wl_mgr.getParamSet(key, refs[key]))
+// 		{
+// 			LL_WARNS() << "Cannot find sky [" << key.name << "] referenced by a day cycle" << LL_ENDL;
+// 			result = false;
+// 		}
+// 	}
+// 
+// 	return result;
+// }
 
 bool LLWLDayCycle::getSkyMap(LLSD& sky_map) const
 {
-	std::map<LLWLParamKey, LLWLParamSet> refs;
-
-	if (!getSkyRefs(refs))
-	{
-		return false;
-	}
-
-	sky_map = LLWLParamManager::createSkyMap(refs);
+// 	std::map<LLWLParamKey, LLWLParamSet> refs;
+// 
+// 	if (!getSkyRefs(refs))
+// 	{
+// 		return false;
+// 	}
+// 
+// 	sky_map = LLWLParamManager::createSkyMap(refs);
 	return true;
 }
 
@@ -235,23 +237,23 @@ bool LLWLDayCycle::changeKeyframeTime(F32 oldTime, F32 newTime)
 	return addKeyframe(newTime, frame);
 }
 
-bool LLWLDayCycle::changeKeyframeParam(F32 time, LLWLParamKey key)
-{
-	LL_DEBUGS() << "Changing key frame param (" << time << ", " << key.toLLSD() << ")" << LL_ENDL;
-
-	// just remove and add back
-	// make sure param exists
-	LLWLParamSet tmp;
-	bool stat = LLWLParamManager::getInstance()->getParamSet(key, tmp);
-	if(stat == false) 
-	{
-		LL_DEBUGS() << "Failed to change key frame param (" << time << ", " << key.toLLSD() << ")" << LL_ENDL;
-		return stat;
-	}
-
-	mTimeMap[time] = key;
-	return true;
-}
+// bool LLWLDayCycle::changeKeyframeParam(F32 time, LLWLParamKey key)
+// {
+// 	LL_DEBUGS() << "Changing key frame param (" << time << ", " << key.toLLSD() << ")" << LL_ENDL;
+// 
+// 	// just remove and add back
+// 	// make sure param exists
+// 	LLWLParamSet tmp;
+// 	bool stat = LLWLParamManager::getInstance()->getParamSet(key, tmp);
+// 	if(stat == false) 
+// 	{
+// 		LL_DEBUGS() << "Failed to change key frame param (" << time << ", " << key.toLLSD() << ")" << LL_ENDL;
+// 		return stat;
+// 	}
+// 
+// 	mTimeMap[time] = key;
+// 	return true;
+// }
 
 
 bool LLWLDayCycle::removeKeyframe(F32 time)
@@ -285,19 +287,19 @@ bool LLWLDayCycle::getKeytime(LLWLParamKey frame, F32& key_time) const
 	return false;
 }
 
-bool LLWLDayCycle::getKeyedParam(F32 time, LLWLParamSet& param)
-{
-	// just scroll on through till you find it
-	std::map<F32, LLWLParamKey>::iterator mIt = mTimeMap.find(time);
-	if(mIt != mTimeMap.end())
-	{
-		return LLWLParamManager::getInstance()->getParamSet(mIt->second, param);
-	}
-
-	// return error if not found
-	LL_DEBUGS() << "Key " << time << " not found" << LL_ENDL;
-	return false;
-}
+// bool LLWLDayCycle::getKeyedParam(F32 time, LLWLParamSet& param)
+// {
+// 	// just scroll on through till you find it
+// 	std::map<F32, LLWLParamKey>::iterator mIt = mTimeMap.find(time);
+// 	if(mIt != mTimeMap.end())
+// 	{
+// 		return LLWLParamManager::getInstance()->getParamSet(mIt->second, param);
+// 	}
+// 
+// 	// return error if not found
+// 	LL_DEBUGS() << "Key " << time << " not found" << LL_ENDL;
+// 	return false;
+// }
 
 bool LLWLDayCycle::getKeyedParamName(F32 time, std::string & name)
 {
diff --git a/indra/newview/llwldaycycle.h b/indra/newview/llwldaycycle.h
index c8585564edbf822a5441d627f40df658aaa34572..2f9a2e5c4af1fe524354c41499a748b72f643a8f 100644
--- a/indra/newview/llwldaycycle.h
+++ b/indra/newview/llwldaycycle.h
@@ -32,10 +32,8 @@ class LLWLDayCycle;
 #include <vector>
 #include <map>
 #include <string>
-#include "llwlparamset.h"
-#include "llwlanimator.h"
+#include "llenvmanager.h"
 struct LLWLParamKey;
-#include "llenvmanager.h" // for LLEnvKey::EScope
 
 class LLWLDayCycle
 {
@@ -78,7 +76,7 @@ class LLWLDayCycle
 	LLSD asLLSD();
 
 	// get skies referenced by this day cycle
-	bool getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const;
+//	bool getSkyRefs(std::map<LLWLParamKey, LLWLParamSet>& refs) const;
 
 	// get referenced skies as LLSD
 	bool getSkyMap(LLSD& sky_map) const;
@@ -110,7 +108,7 @@ class LLWLDayCycle
 
 	/// get the param set at a given time
 	/// returns true if found one
-	bool getKeyedParam(F32 time, LLWLParamSet& param);
+//	bool getKeyedParam(F32 time, LLWLParamSet& param);
 
 	/// get the name
 	/// returns true if it found one
diff --git a/indra/newview/llwlhandlers.cpp b/indra/newview/llwlhandlers.cpp
index ea65a0c6d96a38bbe1a9d3aed6f4d857e3898608..6b8374fd48ca8753bfb50b6b6ac663f1145df326 100644
--- a/indra/newview/llwlhandlers.cpp
+++ b/indra/newview/llwlhandlers.cpp
@@ -30,15 +30,15 @@
 
 #include "llagent.h"
 #include "llviewerregion.h"
-#include "llenvmanager.h"
 #include "llnotificationsutil.h"
 #include "llcorehttputil.h"
 
+#include "llparcel.h"
 /****
  * LLEnvironmentRequest
  ****/
 // static
-bool LLEnvironmentRequest::initiate()
+bool LLEnvironmentRequest::initiate(LLEnvironment::environment_apply_fn cb)
 {
 	LLViewerRegion* cur_region = gAgent.getRegion();
 
@@ -51,15 +51,15 @@ bool LLEnvironmentRequest::initiate()
 	if (!cur_region->capabilitiesReceived())
 	{
 		LL_INFOS("WindlightCaps") << "Deferring windlight settings request until we've got region caps" << LL_ENDL;
-		cur_region->setCapabilitiesReceivedCallback(boost::bind(&LLEnvironmentRequest::onRegionCapsReceived, _1));
+        cur_region->setCapabilitiesReceivedCallback([cb](LLUUID region_id) { LLEnvironmentRequest::onRegionCapsReceived(region_id, cb); });
 		return false;
 	}
 
-	return doRequest();
+	return doRequest(cb);
 }
 
 // static
-void LLEnvironmentRequest::onRegionCapsReceived(const LLUUID& region_id)
+void LLEnvironmentRequest::onRegionCapsReceived(const LLUUID& region_id, LLEnvironment::environment_apply_fn cb)
 {
 	if (region_id != gAgent.getRegion()->getRegionID())
 	{
@@ -68,23 +68,26 @@ void LLEnvironmentRequest::onRegionCapsReceived(const LLUUID& region_id)
 	}
 
 	LL_DEBUGS("WindlightCaps") << "Received region capabilities" << LL_ENDL;
-	doRequest();
+	doRequest(cb);
 }
 
 // static
-bool LLEnvironmentRequest::doRequest()
+bool LLEnvironmentRequest::doRequest(LLEnvironment::environment_apply_fn cb)
 {
 	std::string url = gAgent.getRegionCapability("EnvironmentSettings");
 	if (url.empty())
 	{
 		LL_INFOS("WindlightCaps") << "Skipping windlight setting request - we don't have this capability" << LL_ENDL;
 		// region is apparently not capable of this; don't respond at all
+        // (there shouldn't be any regions where this is the case... but
+        LL_INFOS("ENVIRONMENT") << "No legacy windlight caps... just set the region to be the default day." << LL_ENDL;
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_REGION, LLSettingsDay::GetDefaultAssetId());
 		return false;
 	}
 
     std::string coroname =
         LLCoros::instance().launch("LLEnvironmentRequest::environmentRequestCoro",
-        boost::bind(&LLEnvironmentRequest::environmentRequestCoro, url));
+        [url, cb]() { LLEnvironmentRequest::environmentRequestCoro(url, cb); });
 
     LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
     return true;
@@ -93,7 +96,7 @@ bool LLEnvironmentRequest::doRequest()
 S32 LLEnvironmentRequest::sLastRequest = 0;
 
 //static 
-void LLEnvironmentRequest::environmentRequestCoro(std::string url)
+void LLEnvironmentRequest::environmentRequestCoro(std::string url, LLEnvironment::environment_apply_fn cb)
 {
     LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
     S32 requestId = ++LLEnvironmentRequest::sLastRequest;
@@ -103,6 +106,8 @@ void LLEnvironmentRequest::environmentRequestCoro(std::string url)
 
     LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
 
+    LL_WARNS("WindlightCaps") << "Using legacy Windlight caps." << LL_ENDL;
+
     if (requestId != LLEnvironmentRequest::sLastRequest)
     {
         LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
@@ -114,11 +119,12 @@ void LLEnvironmentRequest::environmentRequestCoro(std::string url)
     if (!status)
     {
         LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " << LL_ENDL;
-        LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
+        LLEnvironment::instance().setEnvironment(LLEnvironment::ENV_REGION, LLSettingsDay::GetDefaultAssetId());
+
         return;
     }
     result = result["content"];
-    LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
+    LL_INFOS("WindlightCaps") << "Received region legacy  windlight settings" << LL_ENDL;
 
     LLUUID regionId;
     if (gAgent.getRegion())
@@ -134,7 +140,12 @@ void LLEnvironmentRequest::environmentRequestCoro(std::string url)
         return;
     }
 
-    LLEnvManagerNew::getInstance()->onRegionSettingsResponse(result);
+    if (cb)
+    {
+        LLEnvironment::EnvironmentInfo::ptr_t pinfo = LLEnvironment::EnvironmentInfo::extractLegacy(result);
+
+        cb(INVALID_PARCEL_ID, pinfo);
+    }
 }
 
 
@@ -146,7 +157,7 @@ clock_t LLEnvironmentApply::UPDATE_WAIT_SECONDS = clock_t(3.f);
 clock_t LLEnvironmentApply::sLastUpdate = clock_t(0.f);
 
 // static
-bool LLEnvironmentApply::initiateRequest(const LLSD& content)
+bool LLEnvironmentApply::initiateRequest(const LLSD& content, LLEnvironment::environment_apply_fn cb)
 {
 	clock_t current = clock();
 
@@ -162,7 +173,7 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 	sLastUpdate = current;
 
 	// Send update request.
-	std::string url = gAgent.getRegionCapability("EnvironmentSettings");
+	std::string url = gAgent.getRegionCapability("ExtEnvironment");
 	if (url.empty())
 	{
 		LL_WARNS("WindlightCaps") << "Applying windlight settings not supported" << LL_ENDL;
@@ -174,11 +185,11 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
 
     std::string coroname =
         LLCoros::instance().launch("LLEnvironmentApply::environmentApplyCoro",
-        boost::bind(&LLEnvironmentApply::environmentApplyCoro, url, content));
+        [url, content, cb]() { LLEnvironmentApply::environmentApplyCoro(url, content, cb); });
 	return true;
 }
 
-void LLEnvironmentApply::environmentApplyCoro(std::string url, LLSD content)
+void LLEnvironmentApply::environmentApplyCoro(std::string url, LLSD content, LLEnvironment::environment_apply_fn cb)
 {
     LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
     LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
@@ -242,13 +253,11 @@ void LLEnvironmentApply::environmentApplyCoro(std::string url, LLSD content)
         }
 
         LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << result["regionID"].asUUID() << LL_ENDL;
-        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
 
     } while (false);
 
     if (!notify.isUndefined())
     {
         LLNotificationsUtil::add("WLRegionApplyFail", notify);
-        LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
     }
 }
diff --git a/indra/newview/llwlhandlers.h b/indra/newview/llwlhandlers.h
index eb2bbf9553596d85f38e1c4e9e31a4f64dc6c1fc..b09d2df60f7c66c97f5bb2cb9f412632a7524287 100644
--- a/indra/newview/llwlhandlers.h
+++ b/indra/newview/llwlhandlers.h
@@ -29,19 +29,20 @@
 
 #include "llviewerprecompiledheaders.h"
 #include "llcoros.h"
+#include "llenvironment.h"
 
 class LLEnvironmentRequest
 {
 	LOG_CLASS(LLEnvironmentRequest);
 public:
 	/// @return true if request was successfully sent
-	static bool initiate();
+    static bool initiate(LLEnvironment::environment_apply_fn cb);
 
 private:
-	static void onRegionCapsReceived(const LLUUID& region_id);
-	static bool doRequest();
+    static void onRegionCapsReceived(const LLUUID& region_id, LLEnvironment::environment_apply_fn cb);
+    static bool doRequest(LLEnvironment::environment_apply_fn cb);
 
-    static void environmentRequestCoro(std::string url);
+    static void environmentRequestCoro(std::string url, LLEnvironment::environment_apply_fn cb);
 
     static S32 sLastRequest;
 };
@@ -51,13 +52,15 @@ class LLEnvironmentApply
 	LOG_CLASS(LLEnvironmentApply);
 public:
 	/// @return true if request was successfully sent
-	static bool initiateRequest(const LLSD& content);
+    static bool initiateRequest(const LLSD& content, LLEnvironment::environment_apply_fn cb);
 
 private:
 	static clock_t sLastUpdate;
 	static clock_t UPDATE_WAIT_SECONDS;
 
-    static void environmentApplyCoro(std::string url, LLSD content);
+    static void environmentApplyCoro(std::string url, LLSD content, LLEnvironment::environment_apply_fn cb);
 };
 
+
+
 #endif // LL_LLWLHANDLERS_H
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
deleted file mode 100644
index 4b4393b07b9996341347af02dde54f58cc2b73f5..0000000000000000000000000000000000000000
--- a/indra/newview/llwlparammanager.cpp
+++ /dev/null
@@ -1,710 +0,0 @@
-/**
- * @file llwlparammanager.cpp
- * @brief Implementation for the LLWLParamManager class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llwlparammanager.h"
-
-#include "pipeline.h"
-#include "llsky.h"
-
-#include "lldiriterator.h"
-#include "llfloaterreg.h"
-#include "llsliderctrl.h"
-#include "llspinctrl.h"
-#include "llcheckboxctrl.h"
-#include "lluictrlfactory.h"
-#include "llviewercamera.h"
-#include "llcombobox.h"
-#include "lllineeditor.h"
-#include "llsdserialize.h"
-
-#include "v4math.h"
-#include "llviewerdisplay.h"
-#include "llviewercontrol.h"
-#include "llviewerwindow.h"
-#include "lldrawpoolwater.h"
-#include "llagent.h"
-#include "llviewerregion.h"
-
-#include "llwlparamset.h"
-#include "llpostprocess.h"
-
-#include "llviewershadermgr.h"
-#include "llglslshader.h"
-
-#include "curl/curl.h"
-#include "llstreamtools.h"
-
-LLWLParamManager::LLWLParamManager() :
-
-	//set the defaults for the controls
-
-	/// Sun Delta Terrain tweak variables.
-	mSunDeltaYaw(180.0f),
-	mSceneLightStrength(2.0f),
-	mWLGamma(1.0f, "gamma"),
-
-	mBlueHorizon(0.25f, 0.25f, 1.0f, 1.0f, "blue_horizon", "WLBlueHorizon"),
-	mHazeDensity(1.0f, "haze_density"),
-	mBlueDensity(0.25f, 0.25f, 0.25f, 1.0f, "blue_density", "WLBlueDensity"),
-	mDensityMult(1.0f, "density_multiplier", 1000),
-	mHazeHorizon(1.0f, "haze_horizon"),
-	mMaxAlt(4000.0f, "max_y"),
-
-	// Lighting
-	mLightnorm(0.f, 0.707f, -0.707f, 1.f, "lightnorm"),
-	mSunlight(0.5f, 0.5f, 0.5f, 1.0f, "sunlight_color", "WLSunlight"),
-	mAmbient(0.5f, 0.75f, 1.0f, 1.19f, "ambient", "WLAmbient"),
-	mGlow(18.0f, 0.0f, -0.01f, 1.0f, "glow"),
-
-	// Clouds
-	mCloudColor(0.5f, 0.5f, 0.5f, 1.0f, "cloud_color", "WLCloudColor"),
-	mCloudMain(0.5f, 0.5f, 0.125f, 1.0f, "cloud_pos_density1"),
-	mCloudCoverage(0.0f, "cloud_shadow"),
-	mCloudDetail(0.0f, 0.0f, 0.0f, 1.0f, "cloud_pos_density2"),
-	mDistanceMult(1.0f, "distance_multiplier"),
-	mCloudScale(0.42f, "cloud_scale"),
-
-	// sky dome
-	mDomeOffset(0.96f),
-	mDomeRadius(15000.f)
-{
-}
-
-LLWLParamManager::~LLWLParamManager()
-{
-}
-
-void LLWLParamManager::clearParamSetsOfScope(LLWLParamKey::EScope scope)
-{
-	if (LLWLParamKey::SCOPE_LOCAL == scope)
-	{
-		LL_WARNS("Windlight") << "Tried to clear windlight sky presets from local system!  This shouldn't be called..." << LL_ENDL;
-		return;
-	}
-
-	std::set<LLWLParamKey> to_remove;
-	for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = mParamList.begin(); iter != mParamList.end(); ++iter)
-	{
-		if(iter->first.scope == scope)
-		{
-			to_remove.insert(iter->first);
-		}
-	}
-
-	for(std::set<LLWLParamKey>::iterator iter = to_remove.begin(); iter != to_remove.end(); ++iter)
-	{
-		mParamList.erase(*iter);
-	}
-}
-
-// returns all skies referenced by the day cycle, with their final names
-// side effect: applies changes to all internal structures!
-std::map<LLWLParamKey, LLWLParamSet> LLWLParamManager::finalizeFromDayCycle(LLWLParamKey::EScope scope)
-{
-	LL_DEBUGS() << "mDay before finalizing:" << LL_ENDL;
-	{
-		for (std::map<F32, LLWLParamKey>::iterator iter = mDay.mTimeMap.begin(); iter != mDay.mTimeMap.end(); ++iter)
-		{
-			LLWLParamKey& key = iter->second;
-			LL_DEBUGS() << iter->first << "->" << key.name << LL_ENDL;
-		}
-	}
-
-	std::map<LLWLParamKey, LLWLParamSet> final_references;
-
-	// Move all referenced to desired scope, renaming if necessary
-	// First, save skies referenced
-	std::map<LLWLParamKey, LLWLParamSet> current_references; // all skies referenced by the day cycle, with their current names
-	// guard against skies with same name and different scopes
-	std::set<std::string> inserted_names;
-	std::map<std::string, unsigned int> conflicted_names; // integer later used as a count, for uniquely renaming conflicts
-
-	LLWLDayCycle& cycle = mDay;
-	for(std::map<F32, LLWLParamKey>::iterator iter = cycle.mTimeMap.begin();
-		iter != cycle.mTimeMap.end();
-		++iter)
-	{
-		LLWLParamKey& key = iter->second;
-		std::string desired_name = key.name;
-		replace_newlines_with_whitespace(desired_name); // already shouldn't have newlines, but just in case
-		if(inserted_names.find(desired_name) == inserted_names.end())
-		{
-			inserted_names.insert(desired_name);
-		}
-		else
-		{
-			// make exist in map
-			conflicted_names[desired_name] = 0;
-		}
-		current_references[key] = mParamList[key];
-	}
-
-	// forget all old skies in target scope, and rebuild, renaming as needed
-	clearParamSetsOfScope(scope);
-	for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = current_references.begin(); iter != current_references.end(); ++iter)
-	{
-		const LLWLParamKey& old_key = iter->first;
-
-		std::string desired_name(old_key.name);
-		replace_newlines_with_whitespace(desired_name);
-
-		LLWLParamKey new_key(desired_name, scope); // name will be replaced later if necessary
-
-		// if this sky is one with a non-unique name, rename via appending a number
-		// an existing preset of the target scope gets to keep its name
-		if (scope != old_key.scope && conflicted_names.find(desired_name) != conflicted_names.end())
-		{
-			std::string& new_name = new_key.name;
-
-			do
-			{
-				// if this executes more than once, this is an absurdly pathological case
-				// (e.g. "x" repeated twice, but "x 1" already exists, so need to use "x 2")
-				std::stringstream temp;
-				temp << desired_name << " " << (++conflicted_names[desired_name]);
-				new_name = temp.str();
-			} while (inserted_names.find(new_name) != inserted_names.end());
-
-			// yay, found one that works
-			inserted_names.insert(new_name); // track names we consume here; shouldn't be necessary due to ++int? but just in case
-
-			// *TODO factor out below into a rename()?
-
-			LL_INFOS("Windlight") << "Renamed " << old_key.name << " (scope" << old_key.scope << ") to "
-				<< new_key.name << " (scope " << new_key.scope << ")" << LL_ENDL;
-
-			// update name in sky
-			iter->second.mName = new_name;
-
-			// update keys in day cycle
-			for(std::map<F32, LLWLParamKey>::iterator frame = cycle.mTimeMap.begin(); frame != cycle.mTimeMap.end(); ++frame)
-			{
-				if (frame->second == old_key)
-				{
-					frame->second = new_key;
-				}
-			}
-
-			// add to master sky map
-			mParamList[new_key] = iter->second;
-		}
-
-		final_references[new_key] = iter->second;
-	}
-
-	LL_DEBUGS() << "mDay after finalizing:" << LL_ENDL;
-	{
-		for (std::map<F32, LLWLParamKey>::iterator iter = mDay.mTimeMap.begin(); iter != mDay.mTimeMap.end(); ++iter)
-		{
-			LLWLParamKey& key = iter->second;
-			LL_DEBUGS() << iter->first << "->" << key.name << LL_ENDL;
-		}
-	}
-
-	return final_references;
-}
-
-// static
-LLSD LLWLParamManager::createSkyMap(std::map<LLWLParamKey, LLWLParamSet> refs)
-{
-	LLSD skies = LLSD::emptyMap();
-	for(std::map<LLWLParamKey, LLWLParamSet>::iterator iter = refs.begin(); iter != refs.end(); ++iter)
-	{
-		skies.insert(iter->first.name, iter->second.getAll());
-	}
-	return skies;
-}
-
-void LLWLParamManager::addAllSkies(const LLWLParamKey::EScope scope, const LLSD& sky_presets)
-{
-	for(LLSD::map_const_iterator iter = sky_presets.beginMap(); iter != sky_presets.endMap(); ++iter)
-	{
-		LLWLParamSet set;
-		set.setAll(iter->second);
-		mParamList[LLWLParamKey(iter->first, scope)] = set;
-	}
-}
-
-void LLWLParamManager::refreshRegionPresets(const LLSD& region_sky_presets)
-{
-	// Remove all region sky presets because they may belong to a previously visited region.
-	clearParamSetsOfScope(LLEnvKey::SCOPE_REGION);
-
-	// Add all sky presets belonging to the current region.
-	addAllSkies(LLEnvKey::SCOPE_REGION, region_sky_presets);
-}
-
-void LLWLParamManager::loadAllPresets()
-{
-	// First, load system (coming out of the box) sky presets.
-	loadPresetsFromDir(getSysDir());
-
-	// Then load user presets. Note that user day presets will modify any system ones already loaded.
-	loadPresetsFromDir(getUserDir());
-}
-
-void LLWLParamManager::loadPresetsFromDir(const std::string& dir)
-{
-	LL_INFOS("AppInit", "Shaders") << "Loading sky presets from " << dir << LL_ENDL;
-
-	LLDirIterator dir_iter(dir, "*.xml");
-	while (1)
-	{
-		std::string file;
-		if (!dir_iter.next(file))
-		{
-			break; // no more files
-		}
-
-		std::string path = gDirUtilp->add(dir, file);
-		if (!loadPreset(path))
-		{
-			LL_WARNS() << "Error loading sky preset from " << path << LL_ENDL;
-		}
-	}
-}
-
-bool LLWLParamManager::loadPreset(const std::string& path)
-{
-	llifstream xml_file;
-	std::string name(gDirUtilp->getBaseFileName(LLURI::unescape(path), /*strip_exten = */ true));
-
-	xml_file.open(path.c_str());
-	if (!xml_file)
-	{
-		return false;
-	}
-
-	LL_DEBUGS("AppInit", "Shaders") << "Loading sky " << name << LL_ENDL;
-
-	LLSD params_data;
-	LLPointer<LLSDParser> parser = new LLSDXMLParser();
-	parser->parse(xml_file, params_data, LLSDSerialize::SIZE_UNLIMITED);
-	xml_file.close();
-
-	LLWLParamKey key(name, LLEnvKey::SCOPE_LOCAL);
-	if (hasParamSet(key))
-	{
-		setParamSet(key, params_data);
-	}
-	else
-	{
-		addParamSet(key, params_data);
-	}
-
-	return true;
-}
-
-void LLWLParamManager::savePreset(LLWLParamKey key)
-{
-	llassert(key.scope == LLEnvKey::SCOPE_LOCAL && !key.name.empty());
-
-	// make an empty llsd
-	LLSD paramsData(LLSD::emptyMap());
-	std::string pathName(getUserDir() + escapeString(key.name) + ".xml");
-
-	// fill it with LLSD windlight params
-	paramsData = mParamList[key].getAll();
-
-	// write to file
-	llofstream presetsXML(pathName.c_str());
-	LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
-	formatter->format(paramsData, presetsXML, LLSDFormatter::OPTIONS_PRETTY);
-	presetsXML.close();
-
-	propagateParameters();
-}
-
-void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)
-{
-	if (gPipeline.canUseWindLightShaders())
-	{
-		mCurParams.update(shader);
-	}
-
-	if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)
-	{
-		shader->uniform4fv(LLShaderMgr::LIGHTNORM, 1, mRotatedLightDir.mV);
-		shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
-	} 
-
-	else if (shader->mShaderGroup == LLGLSLShader::SG_SKY)
-	{
-		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, mClampedLightDir.mV);
-	}
-
-	shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);
-	
-}
-
-static LLTrace::BlockTimerStatHandle FTM_UPDATE_WLPARAM("Update Windlight Params");
-
-void LLWLParamManager::propagateParameters(void)
-{
-	LL_RECORD_BLOCK_TIME(FTM_UPDATE_WLPARAM);
-	
-	LLVector4 sunDir;
-	LLVector4 moonDir;
-
-	// set the sun direction from SunAngle and EastAngle
-	F32 sinTheta = sin(mCurParams.getEastAngle());
-	F32 cosTheta = cos(mCurParams.getEastAngle());
-
-	F32 sinPhi = sin(mCurParams.getSunAngle());
-	F32 cosPhi = cos(mCurParams.getSunAngle());
-
-	sunDir.mV[0] = -sinTheta * cosPhi;
-	sunDir.mV[1] = sinPhi;
-	sunDir.mV[2] = cosTheta * cosPhi;
-	sunDir.mV[3] = 0;
-
-	moonDir = -sunDir;
-
-	// is the normal from the sun or the moon
-	if(sunDir.mV[1] >= 0)
-	{
-		mLightDir = sunDir;
-	}
-	else if(sunDir.mV[1] < 0 && sunDir.mV[1] > LLSky::NIGHTTIME_ELEVATION_COS)
-	{
-		// clamp v1 to 0 so sun never points up and causes weirdness on some machines
-		LLVector3 vec(sunDir.mV[0], sunDir.mV[1], sunDir.mV[2]);
-		vec.mV[1] = 0;
-		vec.normVec();
-		mLightDir = LLVector4(vec, 0.f);
-	}
-	else
-	{
-		mLightDir = moonDir;
-	}
-
-	// calculate the clamp lightnorm for sky (to prevent ugly banding in sky
-	// when haze goes below the horizon
-	mClampedLightDir = sunDir;
-
-	if (mClampedLightDir.mV[1] < -0.1f)
-	{
-		mClampedLightDir.mV[1] = -0.1f;
-	}
-
-	mCurParams.set("lightnorm", mLightDir);
-
-	// bind the variables for all shaders only if we're using WindLight
-	LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
-	end_shaders = LLViewerShaderMgr::instance()->endShaders();
-	for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) 
-	{
-		if (shaders_iter->mProgramObject != 0
-			&& (gPipeline.canUseWindLightShaders()
-				|| shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
-		{
-			shaders_iter->mUniformsDirty = TRUE;
-		}
-	}
-
-	// get the cfr version of the sun's direction
-	LLVector3 cfrSunDir(sunDir.mV[2], sunDir.mV[0], sunDir.mV[1]);
-
-	// set direction and don't allow overriding
-	gSky.setSunDirection(cfrSunDir, LLVector3(0,0,0));
-	gSky.setOverrideSun(TRUE);
-}
-
-void LLWLParamManager::update(LLViewerCamera * cam)
-{
-	LL_RECORD_BLOCK_TIME(FTM_UPDATE_WLPARAM);
-	
-	// update clouds, sun, and general
-	mCurParams.updateCloudScrolling();
-	
-	// update only if running
-	if(mAnimator.getIsRunning()) 
-	{
-		mAnimator.update(mCurParams);
-	}
-
-	// update the shaders and the menu
-	propagateParameters();
-	
-	F32 camYaw = cam->getYaw();
-
-	stop_glerror();
-
-	// *TODO: potential optimization - this block may only need to be
-	// executed some of the time.  For example for water shaders only.
-	{
-		F32 camYawDelta = mSunDeltaYaw * DEG_TO_RAD;
-		
-		LLVector3 lightNorm3(mLightDir);
-		lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f));
-		mRotatedLightDir = LLVector4(lightNorm3, 0.f);
-
-		LLViewerShaderMgr::shader_iter shaders_iter, end_shaders;
-		end_shaders = LLViewerShaderMgr::instance()->endShaders();
-		for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter)
-		{
-			if (shaders_iter->mProgramObject != 0
-				&& (gPipeline.canUseWindLightShaders()
-				|| shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER))
-			{
-				shaders_iter->mUniformsDirty = TRUE;
-			}
-		}
-	}
-}
-
-bool LLWLParamManager::applyDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time)
-{
-	mDay.loadDayCycle(params, scope);
-	resetAnimator(time, true); // set to specified time and start animator
-	return true;
-}
-
-void LLWLParamManager::setDefaultDay()
-{
-	mDay.loadDayCycleFromFile("Default.xml");
-}
-
-bool LLWLParamManager::applySkyParams(const LLSD& params)
-{
-	mAnimator.deactivate();
-	mCurParams.setAll(params);
-	return true;
-}
-
-void LLWLParamManager::setDefaultSky()
-{
-	getParamSet(LLWLParamKey("Default", LLWLParamKey::SCOPE_LOCAL), mCurParams);
-}
-
-
-void LLWLParamManager::resetAnimator(F32 curTime, bool run)
-{
-	mAnimator.setTrack(mDay.mTimeMap, mDay.mDayRate, 
-		curTime, run);
-
-	return;
-}
-
-bool LLWLParamManager::addParamSet(const LLWLParamKey& key, LLWLParamSet& param)
-{
-	// add a new one if not one there already
-	std::map<LLWLParamKey, LLWLParamSet>::iterator mIt = mParamList.find(key);
-	if(mIt == mParamList.end()) 
-	{	
-		llassert(!key.name.empty());
-		// *TODO: validate params
-		mParamList[key] = param;
-		mPresetListChangeSignal();
-		return true;
-	}
-
-	return false;
-}
-
-BOOL LLWLParamManager::addParamSet(const LLWLParamKey& key, LLSD const & param)
-{
-	LLWLParamSet param_set;
-	param_set.setAll(param);
-	return addParamSet(key, param_set);
-}
-
-bool LLWLParamManager::getParamSet(const LLWLParamKey& key, LLWLParamSet& param)
-{
-	// find it and set it
-	std::map<LLWLParamKey, LLWLParamSet>::iterator mIt = mParamList.find(key);
-	if(mIt != mParamList.end()) 
-	{
-		param = mParamList[key];
-		param.mName = key.name;
-		return true;
-	}
-
-	return false;
-}
-
-bool LLWLParamManager::hasParamSet(const LLWLParamKey& key)
-{
-	LLWLParamSet dummy;
-	return getParamSet(key, dummy);
-}
-
-bool LLWLParamManager::setParamSet(const LLWLParamKey& key, LLWLParamSet& param)
-{
-	llassert(!key.name.empty());
-	// *TODO: validate params
-	mParamList[key] = param;
-
-	return true;
-}
-
-bool LLWLParamManager::setParamSet(const LLWLParamKey& key, const LLSD & param)
-{
-	llassert(!key.name.empty());
-	// *TODO: validate params
-
-	// quick, non robust (we won't be working with files, but assets) check
-	// this might not actually be true anymore....
-	if(!param.isMap()) 
-	{
-		return false;
-	}
-	
-	LLWLParamSet param_set;
-	param_set.setAll(param);
-	return setParamSet(key, param_set);
-}
-
-void LLWLParamManager::removeParamSet(const LLWLParamKey& key, bool delete_from_disk)
-{
-	// *NOTE: Removing a sky preset invalidates day cycles that refer to it.
-
-	if (key.scope == LLEnvKey::SCOPE_REGION)
-	{
-		LL_WARNS() << "Removing region skies not supported" << LL_ENDL;
-		llassert(key.scope == LLEnvKey::SCOPE_LOCAL);
-		return;
-	}
-
-	// remove from param list
-	std::map<LLWLParamKey, LLWLParamSet>::iterator it = mParamList.find(key);
-	if (it == mParamList.end())
-	{
-		LL_WARNS("WindLight") << "No sky preset named " << key.name << LL_ENDL;
-		return;
-	}
-
-	mParamList.erase(it);
-	mDay.removeReferencesTo(key);
-
-	// remove from file system if requested
-	if (delete_from_disk)
-	{
-		std::string path_name(getUserDir());
-		std::string escaped_name = escapeString(key.name);
-
-		if(gDirUtilp->deleteFilesInDir(path_name, escaped_name + ".xml") < 1)
-		{
-			LL_WARNS("WindLight") << "Error removing sky preset " << key.name << " from disk" << LL_ENDL;
-		}
-	}
-
-	// signal interested parties
-	mPresetListChangeSignal();
-}
-
-bool LLWLParamManager::isSystemPreset(const std::string& preset_name) const
-{
-	// *TODO: file system access is excessive here.
-	return gDirUtilp->fileExists(getSysDir() + escapeString(preset_name) + ".xml");
-}
-
-void LLWLParamManager::getPresetNames(preset_name_list_t& region, preset_name_list_t& user, preset_name_list_t& sys) const
-{
-	region.clear();
-	user.clear();
-	sys.clear();
-
-	for (std::map<LLWLParamKey, LLWLParamSet>::const_iterator it = mParamList.begin(); it != mParamList.end(); it++)
-	{
-		const LLWLParamKey& key = it->first;
-		const std::string& name = key.name;
-
-		if (key.scope == LLEnvKey::SCOPE_REGION)
-		{
-			region.push_back(name);
-		}
-		else
-		{
-			if (isSystemPreset(name))
-			{
-				sys.push_back(name);
-			}
-			else
-			{
-				user.push_back(name);
-			}
-		}
-	}
-}
-
-void LLWLParamManager::getUserPresetNames(preset_name_list_t& user) const
-{
-	preset_name_list_t region, sys; // unused
-	getPresetNames(region, user, sys);
-}
-
-void LLWLParamManager::getPresetKeys(preset_key_list_t& keys) const
-{
-	keys.clear();
-
-	for (std::map<LLWLParamKey, LLWLParamSet>::const_iterator it = mParamList.begin(); it != mParamList.end(); it++)
-	{
-		keys.push_back(it->first);
-	}
-}
-
-boost::signals2::connection LLWLParamManager::setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb)
-{
-	return mPresetListChangeSignal.connect(cb);
-}
-
-// virtual static
-void LLWLParamManager::initSingleton()
-{
-	LL_DEBUGS("Windlight") << "Initializing sky" << LL_ENDL;
-
-	loadAllPresets();
-
-	// but use linden time sets it to what the estate is
-	mAnimator.setTimeType(LLWLAnimator::TIME_LINDEN);
-}
-
-// static
-std::string LLWLParamManager::getSysDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "windlight/skies", "");
-}
-
-// static
-std::string LLWLParamManager::getUserDir()
-{
-	return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS , "windlight/skies", "");
-}
-
-// static
-std::string LLWLParamManager::escapeString(const std::string& str)
-{
-	// Don't use LLURI::escape() because it doesn't encode '-' characters
-	// which may break handling of some system presets like "A-12AM".
-	char* curl_str = curl_escape(str.c_str(), str.size());
-	std::string escaped_str(curl_str);
-	curl_free(curl_str);
-
-	return escaped_str;
-}
diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h
deleted file mode 100644
index 61f86b747fe05dccd337ea3d13de28b5426ab288..0000000000000000000000000000000000000000
--- a/indra/newview/llwlparammanager.h
+++ /dev/null
@@ -1,323 +0,0 @@
-/**
- * @file llwlparammanager.h
- * @brief Implementation for the LLWLParamManager class.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_WLPARAMMANAGER_H
-#define LL_WLPARAMMANAGER_H
-
-#include <list>
-#include <map>
-#include "llwlparamset.h"
-#include "llwlanimator.h"
-#include "llwldaycycle.h"
-#include "llviewercamera.h"
-#include "lltrans.h"
-
-class LLGLSLShader;
- 
-// color control
-struct WLColorControl {
-	
-	F32 r, g, b, i;				/// the values
-	std::string mName;			/// name to use to dereference params
-	std::string mSliderName;	/// name of the slider in menu
-	bool hasSliderName;			/// only set slider name for true color types
-	bool isSunOrAmbientColor;			/// flag for if it's the sun or ambient color controller
-	bool isBlueHorizonOrDensity;		/// flag for if it's the Blue Horizon or Density color controller
-
-	inline WLColorControl(F32 red, F32 green, F32 blue, F32 intensity,
-						  const std::string& n, const std::string& sliderName = LLStringUtil::null)
-		: r(red), g(green), b(blue), i(intensity), mName(n), mSliderName(sliderName)
-	{
-		// if there's a slider name, say we have one
-		hasSliderName = false;
-		if (mSliderName != "") {
-			hasSliderName = true;
-		}
-
-		// if it's the sun controller
-		isSunOrAmbientColor = false;
-		if (mSliderName == "WLSunlight" || mSliderName == "WLAmbient") {
-			isSunOrAmbientColor = true;
-		}
-
-		isBlueHorizonOrDensity = false;
-		if (mSliderName == "WLBlueHorizon" || mSliderName == "WLBlueDensity") {
-			isBlueHorizonOrDensity = true;
-		}
-	}
-
-	inline WLColorControl & operator = (LLVector4 const & val) {
-		r = val.mV[0];
-		g = val.mV[1];
-		b = val.mV[2];
-		i = val.mV[3];
-		return *this;
-	}
-
-	inline operator LLVector4 (void) const {
-		return LLVector4(r, g, b, i);
-	}
-
-	inline operator LLVector3 (void) const {
-		return LLVector3(r, g, b);
-	}
-
-	inline void update(LLWLParamSet & params) const {
-		params.set(mName, r, g, b, i);
-	}
-};
-
-// float slider control
-struct WLFloatControl {
-	F32 x;
-	std::string mName;
-	F32 mult;
-
-	inline WLFloatControl(F32 val, const std::string& n, F32 m=1.0f)
-		: x(val), mName(n), mult(m)
-	{
-	}
-
-	inline WLFloatControl & operator = (F32 val) {
-		x = val;
-		return *this;
-	}
-
-	inline operator F32 (void) const {
-		return x;
-	}
-
-	inline void update(LLWLParamSet & params) const {
-		params.set(mName, x);
-	}
-};
-
-/// WindLight parameter manager class - what controls all the wind light shaders
-class LLWLParamManager : public LLSingleton<LLWLParamManager>
-{
-	LLSINGLETON(LLWLParamManager);
-	~LLWLParamManager();
-	LOG_CLASS(LLWLParamManager);
-
-public:
-	typedef std::list<std::string> preset_name_list_t;
-	typedef std::list<LLWLParamKey> preset_key_list_t;
-	typedef boost::signals2::signal<void()> preset_list_signal_t;
-
-	/// save the parameter presets to file
-	void savePreset(const LLWLParamKey key);
-
-	/// Set shader uniforms dirty, so they'll update automatically.
-	void propagateParameters(void);
-	
-	/// Update shader uniforms that have changed.
-	void updateShaderUniforms(LLGLSLShader * shader);
-
-	/// setup the animator to run
-	void resetAnimator(F32 curTime, bool run);
-
-	/// update information camera dependent parameters
-	void update(LLViewerCamera * cam);
-
-	/// apply specified day cycle, setting time to noon by default
-	bool applyDayCycleParams(const LLSD& params, LLEnvKey::EScope scope, F32 time = 0.5);
-
-	/// Apply Default.xml map
-	void setDefaultDay();
-
-	/// apply specified fixed sky params
-	bool applySkyParams(const LLSD& params);
-
-	void setDefaultSky();
-
-	// get where the light is pointing
-	inline LLVector4 getLightDir(void) const;
-
-	// get where the light is pointing
-	inline LLVector4 getClampedLightDir(void) const;
-
-	// get where the light is pointing
-	inline LLVector4 getRotatedLightDir(void) const;
-	
-	/// get the dome's offset
-	inline F32 getDomeOffset(void) const;
-
-	/// get the radius of the dome
-	inline F32 getDomeRadius(void) const;
-	
-	/// add a param set (preset) to the list
-	bool addParamSet(const LLWLParamKey& key, LLWLParamSet& param);
-
-	/// add a param set (preset) to the list
-	BOOL addParamSet(const LLWLParamKey& key, LLSD const & param);
-
-	/// get a param set (preset) from the list
-	bool getParamSet(const LLWLParamKey& key, LLWLParamSet& param);
-
-	/// check whether the preset is in the list
-	bool hasParamSet(const LLWLParamKey& key);
-
-	/// set the param in the list with a new param
-	bool setParamSet(const LLWLParamKey& key, LLWLParamSet& param);
-	
-	/// set the param in the list with a new param
-	bool setParamSet(const LLWLParamKey& key, LLSD const & param);
-
-	/// gets rid of a parameter and any references to it
-	/// ignores "delete_from_disk" if the scope is not local
-	void removeParamSet(const LLWLParamKey& key, bool delete_from_disk);
-
-	/// clear parameter mapping of a given scope
-	void clearParamSetsOfScope(LLEnvKey::EScope scope);
-
-	/// @return true if the preset comes out of the box
-	bool isSystemPreset(const std::string& preset_name) const;
-
-	/// @return user and system preset names as a single list
-	void getPresetNames(preset_name_list_t& region, preset_name_list_t& user, preset_name_list_t& sys) const;
-
-	/// @return user preset names
-	void getUserPresetNames(preset_name_list_t& user) const;
-
-	/// @return keys of all known presets
-	void getPresetKeys(preset_key_list_t& keys) const;
-
-	/// Emitted when a preset gets added or deleted.
-	boost::signals2::connection setPresetListChangeCallback(const preset_list_signal_t::slot_type& cb);
-
-	/// add all skies in LLSD using the given scope
-	void addAllSkies(LLEnvKey::EScope scope, const LLSD& preset_map);
-
-	/// refresh region-scope presets
-	void refreshRegionPresets(const LLSD& region_sky_presets);
-
-	// returns all skies referenced by the current day cycle (in mDay), with their final names
-	// side effect: applies changes to all internal structures!  (trashes all unreferenced skies in scope, keys in day cycle rescoped to scope, etc.)
-	std::map<LLWLParamKey, LLWLParamSet> finalizeFromDayCycle(LLWLParamKey::EScope scope);
-
-	// returns all skies in map (intended to be called with output from a finalize)
-	static LLSD createSkyMap(std::map<LLWLParamKey, LLWLParamSet> map);
-
-	/// escape string in a way different from LLURI::escape()
-	static std::string escapeString(const std::string& str);
-
-	// helper variables
-	LLWLAnimator mAnimator;
-
-	/// actual direction of the sun
-	LLVector4 mLightDir;
-
-	/// light norm adjusted so haze works correctly
-	LLVector4 mRotatedLightDir;
-
-	/// clamped light norm for shaders that
-	/// are adversely affected when the sun goes below the
-	/// horizon
-	LLVector4 mClampedLightDir;
-
-	// list of params and how they're cycled for days
-	LLWLDayCycle mDay;
-
-	LLWLParamSet mCurParams;
-
-	/// Sun Delta Terrain tweak variables.
-	F32 mSunDeltaYaw;
-	WLFloatControl mWLGamma;
-
-	F32 mSceneLightStrength;
-	
-	/// Atmospherics
-	WLColorControl mBlueHorizon;
-	WLFloatControl mHazeDensity;
-	WLColorControl mBlueDensity;
-	WLFloatControl mDensityMult;
-	WLFloatControl mHazeHorizon;
-	WLFloatControl mMaxAlt;
-
-	/// Lighting
-	WLColorControl mLightnorm;
-	WLColorControl mSunlight;
-	WLColorControl mAmbient;
-	WLColorControl mGlow;
-
-	/// Clouds
-	WLColorControl mCloudColor;
-	WLColorControl mCloudMain;
-	WLFloatControl mCloudCoverage;
-	WLColorControl mCloudDetail;
-	WLFloatControl mDistanceMult;
-	WLFloatControl mCloudScale;
-
-	/// sky dome
-	F32 mDomeOffset;
-	F32 mDomeRadius;
-	
-
-private:
-
-	friend class LLWLAnimator;
-
-	void loadAllPresets();
-	void loadPresetsFromDir(const std::string& dir);
-	bool loadPreset(const std::string& path);
-
-	static std::string getSysDir();
-	static std::string getUserDir();
-
-	/*virtual*/ void initSingleton();
-	// list of all the parameters, listed by name
-	std::map<LLWLParamKey, LLWLParamSet> mParamList;
-
-	preset_list_signal_t mPresetListChangeSignal;
-};
-
-inline F32 LLWLParamManager::getDomeOffset(void) const
-{
-	return mDomeOffset;
-}
-
-inline F32 LLWLParamManager::getDomeRadius(void) const
-{
-	return mDomeRadius;
-}
-
-inline LLVector4 LLWLParamManager::getLightDir(void) const
-{
-	return mLightDir;
-}
-
-inline LLVector4 LLWLParamManager::getClampedLightDir(void) const
-{
-	return mClampedLightDir;
-}
-
-inline LLVector4 LLWLParamManager::getRotatedLightDir(void) const
-{
-	return mRotatedLightDir;
-}
-
-#endif
-
diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp
deleted file mode 100644
index 986f167d8d07487d631b581f22d4ac5035e1cc31..0000000000000000000000000000000000000000
--- a/indra/newview/llwlparamset.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-/**
- * @file llwlparamset.cpp
- * @brief Implementation for the LLWLParamSet class.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llwlparamset.h"
-#include "llwlanimator.h"
-
-#include "llwlparammanager.h"
-#include "llglslshader.h"
-#include "lluictrlfactory.h"
-#include "llsliderctrl.h"
-#include "pipeline.h"
-
-#include <llgl.h>
-
-#include <sstream>
-
-static LLStaticHashedString sStarBrightness("star_brightness");
-static LLStaticHashedString sPresetNum("preset_num");
-static LLStaticHashedString sSunAngle("sun_angle");
-static LLStaticHashedString sEastAngle("east_angle");
-static LLStaticHashedString sEnableCloudScroll("enable_cloud_scroll");
-static LLStaticHashedString sCloudScrollRate("cloud_scroll_rate");
-static LLStaticHashedString sLightNorm("lightnorm");
-static LLStaticHashedString sCloudDensity("cloud_pos_density1");
-static LLStaticHashedString sCloudScale("cloud_scale");
-static LLStaticHashedString sCloudShadow("cloud_shadow");
-static LLStaticHashedString sDensityMultiplier("density_multiplier");
-static LLStaticHashedString sDistanceMultiplier("distance_multiplier");
-static LLStaticHashedString sHazeDensity("haze_density");
-static LLStaticHashedString sHazeHorizon("haze_horizon");
-static LLStaticHashedString sMaxY("max_y");
-
-LLWLParamSet::LLWLParamSet(void) :
-	mName("Unnamed Preset"),
-	mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f)	
-{}
-
-static LLTrace::BlockTimerStatHandle FTM_WL_PARAM_UPDATE("WL Param Update");
-
-void LLWLParamSet::update(LLGLSLShader * shader) const 
-{	
-	LL_RECORD_BLOCK_TIME(FTM_WL_PARAM_UPDATE);
-	LLSD::map_const_iterator i = mParamValues.beginMap();
-	std::vector<LLStaticHashedString>::const_iterator n = mParamHashedNames.begin();
-	for(;(i != mParamValues.endMap()) && (n != mParamHashedNames.end());++i, n++)
-	{
-		const LLStaticHashedString& param = *n;
-		
-		// check that our pre-hashed names are still tracking the mParamValues map correctly
-		//
-		llassert(param.String() == i->first);
-
-		if (param == sStarBrightness || param == sPresetNum || param == sSunAngle ||
-			param == sEastAngle || param == sEnableCloudScroll ||
-			param == sCloudScrollRate || param == sLightNorm ) 
-		{
-			continue;
-		}
-		
-		if (param == sCloudDensity)
-		{
-			LLVector4 val;
-			val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset;
-			val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset;
-			val.mV[2] = (F32) i->second[2].asReal();
-			val.mV[3] = (F32) i->second[3].asReal();
-
-			stop_glerror();
-			shader->uniform4fv(param, 1, val.mV);
-			stop_glerror();
-		}
-		else if (param == sCloudScale || param == sCloudShadow ||
-				 param == sDensityMultiplier || param == sDistanceMultiplier ||
-				 param == sHazeDensity || param == sHazeHorizon ||
-				 param == sMaxY )
-		{
-			F32 val = (F32) i->second[0].asReal();
-
-			stop_glerror();
-			shader->uniform1f(param, val);
-			stop_glerror();
-		}
-		else // param is the uniform name
-		{
-			// handle all the different cases
-			if (i->second.isArray() && i->second.size() == 4)
-			{
-				LLVector4 val;
-
-				val.mV[0] = (F32) i->second[0].asReal();
-				val.mV[1] = (F32) i->second[1].asReal();
-				val.mV[2] = (F32) i->second[2].asReal();
-				val.mV[3] = (F32) i->second[3].asReal();															
-
-				stop_glerror();
-				shader->uniform4fv(param, 1, val.mV);
-				stop_glerror();
-			} 
-			else if (i->second.isReal())
-			{
-				F32 val = (F32) i->second.asReal();
-
-				stop_glerror();
-				shader->uniform1f(param, val);
-				stop_glerror();
-			} 
-			else if (i->second.isInteger())
-			{
-				S32 val = (S32) i->second.asInteger();
-
-				stop_glerror();
-				shader->uniform1i(param, val);
-				stop_glerror();
-			} 
-			else if (i->second.isBoolean())
-			{
-				S32 val = (i->second.asBoolean() ? 1 : 0);
-
-				stop_glerror();
-				shader->uniform1i(param, val);
-				stop_glerror();
-			}
-		}
-	}
-	
-	if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && !LLPipeline::sUnderWaterRender)
-	{
-		shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2);
-	} else {
-		shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0);
-	}
-}
-
-void LLWLParamSet::set(const std::string& paramName, float x) 
-{	
-	// handle case where no array
-	if(mParamValues[paramName].isReal()) 
-	{
-		mParamValues[paramName] = x;
-	} 
-	
-	// handle array
-	else if(mParamValues[paramName].isArray() &&
-			mParamValues[paramName][0].isReal())
-	{
-		mParamValues[paramName][0] = x;
-	}
-}
-
-void LLWLParamSet::set(const std::string& paramName, float x, float y)
-{
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-}
-
-void LLWLParamSet::set(const std::string& paramName, float x, float y, float z) 
-{
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-	mParamValues[paramName][2] = z;
-}
-
-void LLWLParamSet::set(const std::string& paramName, float x, float y, float z, float w) 
-{
-	mParamValues[paramName][0] = x;
-	mParamValues[paramName][1] = y;
-	mParamValues[paramName][2] = z;
-	mParamValues[paramName][3] = w;
-}
-
-void LLWLParamSet::set(const std::string& paramName, const float * val) 
-{
-	mParamValues[paramName][0] = val[0];
-	mParamValues[paramName][1] = val[1];
-	mParamValues[paramName][2] = val[2];
-	mParamValues[paramName][3] = val[3];
-}
-
-void LLWLParamSet::set(const std::string& paramName, const LLVector4 & val) 
-{
-	mParamValues[paramName][0] = val.mV[0];
-	mParamValues[paramName][1] = val.mV[1];
-	mParamValues[paramName][2] = val.mV[2];
-	mParamValues[paramName][3] = val.mV[3];
-}
-
-void LLWLParamSet::set(const std::string& paramName, const LLColor4 & val) 
-{
-	mParamValues[paramName][0] = val.mV[0];
-	mParamValues[paramName][1] = val.mV[1];
-	mParamValues[paramName][2] = val.mV[2];
-	mParamValues[paramName][3] = val.mV[3];
-}
-
-LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error) 
-{
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (!cur_val.isArray()) 
-	{
-		error = true;
-		return LLVector4(0,0,0,0);
-	}
-	
-	LLVector4 val;
-	val.mV[0] = (F32) cur_val[0].asReal();
-	val.mV[1] = (F32) cur_val[1].asReal();
-	val.mV[2] = (F32) cur_val[2].asReal();
-	val.mV[3] = (F32) cur_val[3].asReal();
-	
-	error = false;
-	return val;
-}
-
-F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error) 
-{
-	// test to see if right type
-	LLSD cur_val = mParamValues.get(paramName);
-	if (cur_val.isArray() && cur_val.size() != 0) 
-	{
-		error = false;
-		return (F32) cur_val[0].asReal();	
-	}
-	
-	if(cur_val.isReal())
-	{
-		error = false;
-		return (F32) cur_val.asReal();
-	}
-	
-	error = true;
-	return 0;
-}
-
-void LLWLParamSet::setSunAngle(float val) 
-{
-	// keep range 0 - 2pi
-	if(val > F_TWO_PI || val < 0)
-	{
-		F32 num = val / F_TWO_PI;
-		num -= floor(num);
-		val = F_TWO_PI * num;
-	}
-
-	mParamValues["sun_angle"] = val;
-}
-
-
-void LLWLParamSet::setEastAngle(float val) 
-{
-	// keep range 0 - 2pi
-	if(val > F_TWO_PI || val < 0)
-	{
-		F32 num = val / F_TWO_PI;
-		num -= floor(num);
-		val = F_TWO_PI * num;
-	}
-
-	mParamValues["east_angle"] = val;
-}
-
-void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)
-{
-	// set up the iterators
-
-	// keep cloud positions and coverage the same
-	/// TODO masking will do this later
-	F32 cloudPos1X = (F32) mParamValues["cloud_pos_density1"][0].asReal();
-	F32 cloudPos1Y = (F32) mParamValues["cloud_pos_density1"][1].asReal();
-	F32 cloudPos2X = (F32) mParamValues["cloud_pos_density2"][0].asReal();
-	F32 cloudPos2Y = (F32) mParamValues["cloud_pos_density2"][1].asReal();
-	F32 cloudCover = (F32) mParamValues["cloud_shadow"][0].asReal();
-
-	LLSD srcVal;
-	LLSD destVal;
-
-	// Iterate through values
-	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
-	{
-		// If param exists in both src and dest, set the holder variables, otherwise skip
-		if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))
-		{
-			srcVal = src.mParamValues[iter->first];
-			destVal = dest.mParamValues[iter->first];
-		}
-		else
-		{
-			continue;
-		}
-		
-		if(iter->second.isReal())									// If it's a real, interpolate directly
-		{
-			iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight);
-		}
-		else if(iter->second.isArray() && iter->second[0].isReal()	// If it's an array of reals, loop through the reals and interpolate on those
-				&& iter->second.size() == srcVal.size() && iter->second.size() == destVal.size())
-		{
-			// Actually do interpolation: old value + (difference in values * factor)
-			for(int i=0; i < iter->second.size(); ++i) 
-			{
-				// iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal();	// old way of doing it -- equivalent but one more operation
-				iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight);
-			}
-		}
-		else														// Else, skip
-		{
-			continue;
-		}		
-	}
-
-	// now mix the extra parameters
-	setStarBrightness((1 - weight) * (F32) src.getStarBrightness()
-		+ weight * (F32) dest.getStarBrightness());
-
-	// FIXME: we have established that this assert fails
-	// frequently. Someone who understands the code needs to figure
-	// out if it matters. In the meantime, disabling the checks so we
-	// can stop interfering with other development.
-
-	//llassert(src.getSunAngle() >= - F_PI && 
-	//				src.getSunAngle() <= 3 * F_PI);
-	//llassert(dest.getSunAngle() >= - F_PI && 
-	//				dest.getSunAngle() <= 3 * F_PI);
-	//llassert(src.getEastAngle() >= 0 && 
-	//				src.getEastAngle() <= 4 * F_PI);
-	//llassert(dest.getEastAngle() >= 0 && 
-	//				dest.getEastAngle() <= 4 * F_PI);
-
-	// sun angle and east angle require some handling to make sure
-	// they go in circles.  Yes quaternions would work better.
-	F32 srcSunAngle = src.getSunAngle();
-	F32 destSunAngle = dest.getSunAngle();
-	F32 srcEastAngle = src.getEastAngle();
-	F32 destEastAngle = dest.getEastAngle();
-	
-	if(fabsf(srcSunAngle - destSunAngle) > F_PI) 
-	{
-		if(srcSunAngle > destSunAngle) 
-		{
-			destSunAngle += 2 * F_PI;
-		} 
-		else 
-		{
-			srcSunAngle += 2 * F_PI;
-		}
-	}
-
-	if(fabsf(srcEastAngle - destEastAngle) > F_PI) 
-	{
-		if(srcEastAngle > destEastAngle) 
-		{
-			destEastAngle += 2 * F_PI;
-		} 
-		else 
-		{
-			srcEastAngle += 2 * F_PI;
-		}
-	}
-
-	setSunAngle((1 - weight) * srcSunAngle + weight * destSunAngle);
-	setEastAngle((1 - weight) * srcEastAngle + weight * destEastAngle);
-	
-	// now setup the sun properly
-
-	// reset those cloud positions
-	mParamValues["cloud_pos_density1"][0] = cloudPos1X;
-	mParamValues["cloud_pos_density1"][1] = cloudPos1Y;
-	mParamValues["cloud_pos_density2"][0] = cloudPos2X;
-	mParamValues["cloud_pos_density2"][1] = cloudPos2Y;
-	mParamValues["cloud_shadow"][0] = cloudCover;
-}
-
-void LLWLParamSet::updateCloudScrolling(void) 
-{
-	static LLTimer s_cloud_timer;
-
-	F64 delta_t = s_cloud_timer.getElapsedTimeAndResetF64();
-
-	if(getEnableCloudScrollX())
-	{
-		mCloudScrollXOffset += F32(delta_t * (getCloudScrollX() - 10.f) / 100.f);
-	}
-	if(getEnableCloudScrollY())
-	{
-		mCloudScrollYOffset += F32(delta_t * (getCloudScrollY() - 10.f) / 100.f);
-	}
-}
-
-void LLWLParamSet::updateHashedNames()
-{
-	mParamHashedNames.clear();
-	// Iterate through values
-	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)
-	{
-		mParamHashedNames.push_back(LLStaticHashedString(iter->first));
-	}
-}
-
diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h
deleted file mode 100644
index 6e5f1d3a4bc22daf5396a665d52803a77a7f1b59..0000000000000000000000000000000000000000
--- a/indra/newview/llwlparamset.h
+++ /dev/null
@@ -1,246 +0,0 @@
-/**
- * @file llwlparamset.h
- * @brief Interface for the LLWLParamSet class.
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, 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$
- */
-
-#ifndef LL_WLPARAM_SET_H
-#define LL_WLPARAM_SET_H
-
-#include <string>
-#include <map>
-#include <vector>
-
-#include "v4math.h"
-#include "v4color.h"
-#include "llstaticstringtable.h"
-
-class LLWLParamSet;
-class LLGLSLShader;
-
-/// A class representing a set of parameter values for the WindLight shaders.
-class LLWLParamSet {
-
-	friend class LLWLParamManager;
-
-public:
-	std::string mName;	
-	
-private:
-
-	LLSD mParamValues;
-	std::vector<LLStaticHashedString> mParamHashedNames;
-
-	float mCloudScrollXOffset, mCloudScrollYOffset;
-
-	void updateHashedNames();
-
-public:
-
-	LLWLParamSet();
-
-	/// Update this set of shader uniforms from the parameter values.
-	void update(LLGLSLShader * shader) const;
-
-	/// set the total llsd
-	void setAll(const LLSD& val);
-	
-	/// get the total llsd
-	const LLSD& getAll();		
-	
-
-	/// Set a float parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The float value to set.
-	void set(const std::string& paramName, float x);
-
-	/// Set a float2 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	void set(const std::string& paramName, float x, float y);
-
-	/// Set a float3 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	/// \param z			The z component's value to set.
-	void set(const std::string& paramName, float x, float y, float z);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param x			The x component's value to set.
-	/// \param y			The y component's value to set.
-	/// \param z			The z component's value to set.
-	/// \param w			The w component's value to set.
-	void set(const std::string& paramName, float x, float y, float z, float w);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			An array of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const float * val);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			A struct of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const LLVector4 & val);
-
-	/// Set a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param val			A struct of the 4 float values to set the parameter to.
-	void set(const std::string& paramName, const LLColor4 & val);
-
-	/// Get a float4 parameter.
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type
-	LLVector4 getVector(const std::string& paramName, bool& error);
-
-	/// Get a float parameter
-	/// \param paramName	The name of the parameter to set.
-	/// \param error		A flag to set if it's not the proper return type	
-	F32 getFloat(const std::string& paramName, bool& error);
-	
-	
-	// specific getters and setters
-	
-	
-	/// set the star's brightness
-	/// \param val brightness value
-	void setStarBrightness(F32 val);
-	
-	/// get the star brightness value;
-	F32 getStarBrightness();	
-	
-	void setSunAngle(F32 val);
-	F32 getSunAngle();	
-	
-	void setEastAngle(F32 val);
-	F32 getEastAngle();	
-	
-							
-	
-	/// set the cloud scroll x enable value
-	/// \param val scroll x value	
-	void setEnableCloudScrollX(bool val);
-
-	/// get the scroll x enable value;	
-	bool getEnableCloudScrollX();
-	
-	/// set the star's brightness
-	/// \param val scroll y bool value		
-	void setEnableCloudScrollY(bool val);	
-
-	/// get the scroll enable y value;
-	bool getEnableCloudScrollY();
-	
-	/// set the cloud scroll x enable value
-	/// \param val scroll x value	
-	void setCloudScrollX(F32 val);
-
-	/// get the scroll x enable value;	
-	F32 getCloudScrollX();
-	
-	/// set the star's brightness
-	/// \param val scroll y bool value		
-	void setCloudScrollY(F32 val);	
-
-	/// get the scroll enable y value;
-	F32 getCloudScrollY();	
-
-	/// interpolate two parameter sets
-	/// \param src			The parameter set to start with
-	/// \param dest			The parameter set to end with
-	/// \param weight		The amount to interpolate
-	void mix(LLWLParamSet& src, LLWLParamSet& dest, 
-		F32 weight);
-
-	void updateCloudScrolling(void);
-};
-
-inline void LLWLParamSet::setAll(const LLSD& val)
-{
-	if(val.isMap()) {
-		mParamValues = val;
-	}
-
-	updateHashedNames();
-}
-
-inline const LLSD& LLWLParamSet::getAll()
-{
-	return mParamValues;
-}
-
-inline void LLWLParamSet::setStarBrightness(float val) {
-	mParamValues["star_brightness"] = val;
-}
-
-inline F32 LLWLParamSet::getStarBrightness() {
-	return (F32) mParamValues["star_brightness"].asReal();
-}
-
-inline F32 LLWLParamSet::getSunAngle() {
-	return (F32) mParamValues["sun_angle"].asReal();
-}
-
-inline F32 LLWLParamSet::getEastAngle() {
-	return (F32) mParamValues["east_angle"].asReal();
-}
-
-
-inline void LLWLParamSet::setEnableCloudScrollX(bool val) {
-	mParamValues["enable_cloud_scroll"][0] = val;
-}
-
-inline bool LLWLParamSet::getEnableCloudScrollX() {
-	return mParamValues["enable_cloud_scroll"][0].asBoolean();
-}
-
-inline void LLWLParamSet::setEnableCloudScrollY(bool val) {
-	mParamValues["enable_cloud_scroll"][1] = val;
-}
-
-inline bool LLWLParamSet::getEnableCloudScrollY() {
-	return mParamValues["enable_cloud_scroll"][1].asBoolean();
-}
-
-
-inline void LLWLParamSet::setCloudScrollX(F32 val) {
-	mParamValues["cloud_scroll_rate"][0] = val;
-}
-
-inline F32 LLWLParamSet::getCloudScrollX() {
-	return (F32) mParamValues["cloud_scroll_rate"][0].asReal();
-}
-
-inline void LLWLParamSet::setCloudScrollY(F32 val) {
-	mParamValues["cloud_scroll_rate"][1] = val;
-}
-
-inline F32 LLWLParamSet::getCloudScrollY() {
-	return (F32) mParamValues["cloud_scroll_rate"][1].asReal();
-}
-
-
-#endif // LL_WLPARAM_SET_H
-
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 89f5eb86b32269000a2999edb035baf3a6ba897c..8989bae96a7fd5ed8329ca5b9ef04c8e99219bc8 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -873,6 +873,57 @@ void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_heigh
 	}
 }
 
+void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water)
+{
+	if (!gAgent.getRegion())
+	{
+		return;
+	}
+
+	if (mRegionList.empty())
+	{
+		LL_WARNS() << "No regions!" << LL_ENDL;
+		return;
+	}
+
+	for (region_list_t::iterator iter = mRegionList.begin();
+		 iter != mRegionList.end(); ++iter)
+	{
+		LLViewerRegion* regionp = *iter;
+		LLVOWater* waterp = regionp->getLand().getWaterObj();
+		if (waterp && waterp->mDrawable)
+		{
+			waterp->mDrawable->setVisible(camera);
+		    cull->pushDrawable(waterp->mDrawable);
+		}
+	}
+
+    if (include_void_water)
+    {
+		for (std::list<LLPointer<LLVOWater> >::iterator iter = mHoleWaterObjects.begin();
+			 iter != mHoleWaterObjects.end(); ++ iter)
+		{
+			LLVOWater* waterp = (*iter).get();
+		    if (waterp && waterp->mDrawable)
+            {
+                waterp->mDrawable->setVisible(camera);
+		        cull->pushDrawable(waterp->mDrawable);
+            }
+	    }
+    }
+
+	S32 dir;
+	for (dir = 0; dir < 8; dir++)
+	{
+		LLVOWater* waterp = mEdgeWaterObjects[dir];
+		if (waterp && waterp->mDrawable)
+		{
+            waterp->mDrawable->setVisible(camera);
+		    cull->pushDrawable(waterp->mDrawable);
+		}
+	}
+}
+
 void LLWorld::updateWaterObjects()
 {
 	if (!gAgent.getRegion())
diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h
index 993fbfb2cc3b73e2627512bfee95b1e5fb21cb83..98552bc4d120187aad5254ff98830ed47557e45c 100644
--- a/indra/newview/llworld.h
+++ b/indra/newview/llworld.h
@@ -138,6 +138,9 @@ class LLWorld : public LLSingleton<LLWorld>
 
 	LLViewerTexture *getDefaultWaterTexture();
 	void updateWaterObjects();
+
+    void precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water);
+
 	void waterHeightRegionInfo(std::string const& sim_name, F32 water_height);
 	void shiftRegions(const LLVector3& offset);
 
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 7bc8af4a0b3413b0f964f5e56138a7ce2f37209a..0693d08dfbb557614fbd21589b8f28649da4ba82 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -105,29 +105,12 @@ class CURLcodeMapper: public StatusMapperBase<CURLcode>
         def(CURLE_UNSUPPORTED_PROTOCOL);    /* 1 */
         def(CURLE_FAILED_INIT);             /* 2 */
         def(CURLE_URL_MALFORMAT);           /* 3 */
-        def(CURLE_URL_MALFORMAT_USER);      /* 4 - NOT USED */
         def(CURLE_COULDNT_RESOLVE_PROXY);   /* 5 */
         def(CURLE_COULDNT_RESOLVE_HOST);    /* 6 */
         def(CURLE_COULDNT_CONNECT);         /* 7 */
-        def(CURLE_FTP_WEIRD_SERVER_REPLY);  /* 8 */
-        def(CURLE_FTP_ACCESS_DENIED);       /* 9 a service was denied by the FTP server
-                                          due to lack of access - when login fails
-                                          this is not returned. */
-        def(CURLE_FTP_USER_PASSWORD_INCORRECT); /* 10 - NOT USED */
-        def(CURLE_FTP_WEIRD_PASS_REPLY);    /* 11 */
-        def(CURLE_FTP_WEIRD_USER_REPLY);    /* 12 */
-        def(CURLE_FTP_WEIRD_PASV_REPLY);    /* 13 */
-        def(CURLE_FTP_WEIRD_227_FORMAT);    /* 14 */
-        def(CURLE_FTP_CANT_GET_HOST);       /* 15 */
-        def(CURLE_FTP_CANT_RECONNECT);      /* 16 */
-        def(CURLE_FTP_COULDNT_SET_BINARY);  /* 17 */
         def(CURLE_PARTIAL_FILE);            /* 18 */
-        def(CURLE_FTP_COULDNT_RETR_FILE);   /* 19 */
-        def(CURLE_FTP_WRITE_ERROR);         /* 20 */
-        def(CURLE_FTP_QUOTE_ERROR);         /* 21 */
         def(CURLE_HTTP_RETURNED_ERROR);     /* 22 */
         def(CURLE_WRITE_ERROR);             /* 23 */
-        def(CURLE_MALFORMAT_USER);          /* 24 - NOT USED */
         def(CURLE_UPLOAD_FAILED);           /* 25 - failed upload "command" */
         def(CURLE_READ_ERROR);              /* 26 - could open/read from file */
         def(CURLE_OUT_OF_MEMORY);           /* 27 */
@@ -135,29 +118,18 @@ class CURLcodeMapper: public StatusMapperBase<CURLcode>
                  instead of a memory allocation error if CURL_DOES_CONVERSIONS
                  is defined
         */
-        def(CURLE_OPERATION_TIMEOUTED);     /* 28 - the timeout time was reached */
-        def(CURLE_FTP_COULDNT_SET_ASCII);   /* 29 - TYPE A failed */
-        def(CURLE_FTP_PORT_FAILED);         /* 30 - FTP PORT operation failed */
-        def(CURLE_FTP_COULDNT_USE_REST);    /* 31 - the REST command failed */
-        def(CURLE_FTP_COULDNT_GET_SIZE);    /* 32 - the SIZE command failed */
+        def(CURLE_OPERATION_TIMEDOUT);     /* 28 - the timeout time was reached */
         def(CURLE_HTTP_RANGE_ERROR);        /* 33 - RANGE "command" didn't work */
         def(CURLE_HTTP_POST_ERROR);         /* 34 */
         def(CURLE_SSL_CONNECT_ERROR);       /* 35 - wrong when connecting with SSL */
         def(CURLE_BAD_DOWNLOAD_RESUME);     /* 36 - couldn't resume download */
         def(CURLE_FILE_COULDNT_READ_FILE);  /* 37 */
-        def(CURLE_LDAP_CANNOT_BIND);        /* 38 */
-        def(CURLE_LDAP_SEARCH_FAILED);      /* 39 */
         def(CURLE_LIBRARY_NOT_FOUND);       /* 40 */
         def(CURLE_FUNCTION_NOT_FOUND);      /* 41 */
         def(CURLE_ABORTED_BY_CALLBACK);     /* 42 */
         def(CURLE_BAD_FUNCTION_ARGUMENT);   /* 43 */
-        def(CURLE_BAD_CALLING_ORDER);       /* 44 - NOT USED */
         def(CURLE_INTERFACE_FAILED);        /* 45 - CURLOPT_INTERFACE failed */
-        def(CURLE_BAD_PASSWORD_ENTERED);    /* 46 - NOT USED */
         def(CURLE_TOO_MANY_REDIRECTS );     /* 47 - catch endless re-direct loops */
-        def(CURLE_UNKNOWN_TELNET_OPTION);   /* 48 - User specified an unknown option */
-        def(CURLE_TELNET_OPTION_SYNTAX );   /* 49 - Malformed telnet option */
-        def(CURLE_OBSOLETE);                /* 50 - NOT USED */
         def(CURLE_SSL_PEER_CERTIFICATE);    /* 51 - peer's certificate wasn't ok */
         def(CURLE_GOT_NOTHING);             /* 52 - when this is a specific error */
         def(CURLE_SSL_ENGINE_NOTFOUND);     /* 53 - SSL crypto engine not found */
@@ -165,26 +137,19 @@ class CURLcodeMapper: public StatusMapperBase<CURLcode>
                                           default */
         def(CURLE_SEND_ERROR);              /* 55 - failed sending network data */
         def(CURLE_RECV_ERROR);              /* 56 - failure in receiving network data */
-        def(CURLE_SHARE_IN_USE);            /* 57 - share is in use */
+
         def(CURLE_SSL_CERTPROBLEM);         /* 58 - problem with the local certificate */
         def(CURLE_SSL_CIPHER);              /* 59 - couldn't use specified cipher */
         def(CURLE_SSL_CACERT);              /* 60 - problem with the CA cert (path?) */
         def(CURLE_BAD_CONTENT_ENCODING);    /* 61 - Unrecognized transfer encoding */
-        def(CURLE_LDAP_INVALID_URL);        /* 62 - Invalid LDAP URL */
+
         def(CURLE_FILESIZE_EXCEEDED);       /* 63 - Maximum file size exceeded */
-        def(CURLE_FTP_SSL_FAILED);          /* 64 - Requested FTP SSL level failed */
+
         def(CURLE_SEND_FAIL_REWIND);        /* 65 - Sending the data requires a rewind
                                           that failed */
         def(CURLE_SSL_ENGINE_INITFAILED);   /* 66 - failed to initialise ENGINE */
         def(CURLE_LOGIN_DENIED);            /* 67 - user); password or similar was not
                                           accepted and we failed to login */
-        def(CURLE_TFTP_NOTFOUND);           /* 68 - file not found on server */
-        def(CURLE_TFTP_PERM);               /* 69 - permission problem on server */
-        def(CURLE_TFTP_DISKFULL);           /* 70 - out of disk space on server */
-        def(CURLE_TFTP_ILLEGAL);            /* 71 - Illegal TFTP operation */
-        def(CURLE_TFTP_UNKNOWNID);          /* 72 - Unknown transfer ID */
-        def(CURLE_TFTP_EXISTS);             /* 73 - File already exists */
-        def(CURLE_TFTP_NOSUCHUSER);         /* 74 - No such user */
         def(CURLE_CONV_FAILED);             /* 75 - conversion failed */
         def(CURLE_CONV_REQD);               /* 76 - caller must register conversion
                                           callbacks using curl_easy_setopt options
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bec33790bd9edc5dc6e51cd6fba7cf408641b662..f0ed303f66571262eac266a3a6bbbc8898c3f2d7 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -88,6 +88,7 @@
 #include "llvocache.h"
 #include "llvoground.h"
 #include "llvosky.h"
+#include "llvowlsky.h"
 #include "llvotree.h"
 #include "llvovolume.h"
 #include "llvosurfacepatch.h"
@@ -100,8 +101,6 @@
 #include "llviewerstats.h"
 #include "llviewerjoystick.h"
 #include "llviewerdisplay.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
 #include "llspatialpartition.h"
 #include "llmutelist.h"
 #include "lltoolpie.h"
@@ -116,6 +115,9 @@
 #include "llprogressview.h"
 #include "llcleanup.h"
 
+#include "llenvironment.h"
+#include "llsettingsvo.h"
+
 #ifdef _DEBUG
 // Debug indices is disabled for now for debug performance - djs 4/24/02
 //#define DEBUG_INDICES
@@ -131,7 +133,6 @@ bool gShiftFrame = false;
 
 //cached settings
 bool LLPipeline::RenderAvatarVP;
-bool LLPipeline::VertexShaderEnable;
 bool LLPipeline::WindLightUseAtmosShaders;
 bool LLPipeline::RenderDeferred;
 F32 LLPipeline::RenderDeferredSunWash;
@@ -187,6 +188,7 @@ F32 LLPipeline::RenderShadowOffset;
 F32 LLPipeline::RenderShadowBias;
 F32 LLPipeline::RenderSpotShadowOffset;
 F32 LLPipeline::RenderSpotShadowBias;
+LLDrawable* LLPipeline::RenderSpotLight = nullptr;
 F32 LLPipeline::RenderEdgeDepthCutoff;
 F32 LLPipeline::RenderEdgeNormCutoff;
 LLVector3 LLPipeline::RenderShadowGaussian;
@@ -209,6 +211,7 @@ LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize");
 
 const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f;
 const F32 BACKLIGHT_NIGHT_MAGNITUDE_OBJECT = 0.08f;
+const F32 DEFERRED_LIGHT_FALLOFF = 0.5f;
 const U32 DEFERRED_VB_MASK = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1;
 
 extern S32 gBoxFrame;
@@ -253,6 +256,11 @@ LLTrace::BlockTimerStatHandle FTM_PIPELINE("Pipeline");
 LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY("Client Copy");
 LLTrace::BlockTimerStatHandle FTM_RENDER_DEFERRED("Deferred Shading");
 
+LLTrace::BlockTimerStatHandle FTM_RENDER_UI_HUD("HUD");
+LLTrace::BlockTimerStatHandle FTM_RENDER_UI_3D("3D");
+LLTrace::BlockTimerStatHandle FTM_RENDER_UI_2D("2D");
+LLTrace::BlockTimerStatHandle FTM_RENDER_UI_DEBUG_TEXT("Debug Text");
+LLTrace::BlockTimerStatHandle FTM_RENDER_UI_SCENE_MON("Scene Mon");
 
 static LLTrace::BlockTimerStatHandle FTM_STATESORT_DRAWABLE("Sort Drawables");
 static LLTrace::BlockTimerStatHandle FTM_STATESORT_POSTSORT("Post Sort");
@@ -298,62 +306,6 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size);
 U32 nhpo2(U32 v);
 LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage);
 
-glh::matrix4f glh_copy_matrix(F32* src)
-{
-	glh::matrix4f ret;
-	ret.set_value(src);
-	return ret;
-}
-
-glh::matrix4f glh_get_current_modelview()
-{
-	return glh_copy_matrix(gGLModelView);
-}
-
-glh::matrix4f glh_get_current_projection()
-{
-	return glh_copy_matrix(gGLProjection);
-}
-
-glh::matrix4f glh_get_last_modelview()
-{
-	return glh_copy_matrix(gGLLastModelView);
-}
-
-glh::matrix4f glh_get_last_projection()
-{
-	return glh_copy_matrix(gGLLastProjection);
-}
-
-void glh_copy_matrix(const glh::matrix4f& src, F32* dst)
-{
-	for (U32 i = 0; i < 16; i++)
-	{
-		dst[i] = src.m[i];
-	}
-}
-
-void glh_set_current_modelview(const glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLModelView);
-}
-
-void glh_set_current_projection(glh::matrix4f& mat)
-{
-	glh_copy_matrix(mat, gGLProjection);
-}
-
-glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar)
-{
-	glh::matrix4f ret(
-		2.f/(right-left), 0.f, 0.f, -(right+left)/(right-left),
-		0.f, 2.f/(top-bottom), 0.f, -(top+bottom)/(top-bottom),
-		0.f, 0.f, -2.f/(zfar-znear),  -(zfar+znear)/(zfar-znear),
-		0.f, 0.f, 0.f, 1.f);
-
-	return ret;
-}
-
 void display_update_camera();
 //----------------------------------------
 
@@ -386,6 +338,7 @@ bool	LLPipeline::sShadowRender = false;
 bool	LLPipeline::sWaterReflections = false;
 bool	LLPipeline::sRenderGlow = false;
 bool	LLPipeline::sReflectionRender = false;
+bool    LLPipeline::sDistortionRender = false;
 bool	LLPipeline::sImpostorRender = false;
 bool	LLPipeline::sImpostorRenderAlphaDepthPass = false;
 bool	LLPipeline::sUnderWaterRender = false;
@@ -398,6 +351,7 @@ bool    LLPipeline::sMemAllocationThrottled = false;
 S32		LLPipeline::sVisibleLightCount = 0;
 F32		LLPipeline::sMinRenderSize = 0.f;
 bool	LLPipeline::sRenderingHUDs;
+F32     LLPipeline::sDistortionWaterClipPlaneMargin = 1.0125f;
 
 // EventHost API LLPipeline listener.
 static LLPipelineListener sPipelineListener;
@@ -456,6 +410,11 @@ LLPipeline::LLPipeline() :
 	mNoiseMap = 0;
 	mTrueNoiseMap = 0;
 	mLightFunc = 0;
+
+    for(U32 i = 0; i < 8; i++)
+    {
+        mHWLightColors[i] = LLColor4::black;
+    }
 }
 
 void LLPipeline::connectRefreshCachedSettingsSafe(const std::string name)
@@ -572,7 +531,6 @@ void LLPipeline::init()
 	connectRefreshCachedSettingsSafe("RenderAvatarMaxNonImpostors");
 	connectRefreshCachedSettingsSafe("RenderDelayVBUpdate");
 	connectRefreshCachedSettingsSafe("UseOcclusion");
-	connectRefreshCachedSettingsSafe("VertexShaderEnable");
 	connectRefreshCachedSettingsSafe("RenderAvatarVP");
 	connectRefreshCachedSettingsSafe("WindLightUseAtmosShaders");
 	connectRefreshCachedSettingsSafe("RenderDeferred");
@@ -777,6 +735,23 @@ void LLPipeline::throttleNewMemoryAllocation(bool disable)
 	}
 }
 
+void LLPipeline::requestResizeScreenTexture()
+{
+    gResizeScreenTexture = TRUE;
+}
+
+void LLPipeline::requestResizeShadowTexture()
+{
+    gResizeShadowTexture = TRUE;
+}
+
+void LLPipeline::resizeShadowTexture()
+{
+    releaseShadowTargets();
+    allocateShadowBuffer(mScreenWidth, mScreenHeight);
+    gResizeShadowTexture = FALSE;
+}
+
 void LLPipeline::resizeScreenTexture()
 {
 	LL_RECORD_BLOCK_TIME(FTM_RESIZE_SCREEN_TEXTURE);
@@ -785,25 +760,14 @@ void LLPipeline::resizeScreenTexture()
 		GLuint resX = gViewerWindow->getWorldViewWidthRaw();
 		GLuint resY = gViewerWindow->getWorldViewHeightRaw();
 	
-		if ((resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
+		if (gResizeScreenTexture || (resX != mScreen.getWidth()) || (resY != mScreen.getHeight()))
 		{
 			releaseScreenBuffers();
-		if (!allocateScreenBuffer(resX,resY))
-			{
-#if PROBABLE_FALSE_DISABLES_OF_ALM_HERE
-				//FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled
-			//NOTE: if the session closes successfully after this call, deferred rendering will be 
-			// disabled on future sessions
-			if (LLPipeline::sRenderDeferred)
-			{
-				gSavedSettings.setBOOL("RenderDeferred", FALSE);
-				LLPipeline::refreshCachedSettings();
-
+            releaseShadowTargets();
+		    allocateScreenBuffer(resX,resY);
+            gResizeScreenTexture = FALSE;
 				}
-#endif
 			}
-		}
-	}
 }
 
 void LLPipeline::allocatePhysicsBuffer()
@@ -973,23 +937,78 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 			mDeferredLight.release();
 		}
 
-		F32 scale = llmax(0.f, RenderShadowResolutionScale);
+        allocateShadowBuffer(resX, resY);
+
+        //HACK make screenbuffer allocations start failing after 30 seconds
+        if (gSavedSettings.getBOOL("SimulateFBOFailure"))
+        {
+            return false;
+        }
+    }
+    else
+    {
+        mDeferredLight.release();
+
+        releaseShadowTargets();
+
+		mFXAABuffer.release();
+		mScreen.release();
+		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
+		mDeferredDepth.release();
+		mOcclusionDepth.release();
+						
+		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
+	}
+	
+	if (LLPipeline::sRenderDeferred)
+	{ //share depth buffer between deferred targets
+		mDeferredScreen.shareDepthBuffer(mScreen);
+	}
+
+	gGL.getTexUnit(0)->disable();
+
+	stop_glerror();
+
+	return true;
+}
+
+// must be even to avoid a stripe in the horizontal shadow blur
+inline U32 BlurHappySize(U32 x, F32 scale) { return U32( x * scale + 16.0f) & ~0xF; }
+
+bool LLPipeline::allocateShadowBuffer(U32 resX, U32 resY)
+{
+	refreshCachedSettings();
+	
+	if (LLPipeline::sRenderDeferred)
+	{
+		S32 shadow_detail = RenderShadowDetail;
+
+		const U32 occlusion_divisor = 3;
+
+		F32 scale = llmax(0.f,RenderShadowResolutionScale);
+		U32 sun_shadow_map_width  = BlurHappySize(resX, scale);
+		U32 sun_shadow_map_height = BlurHappySize(resY, scale);
 
 		if (shadow_detail > 0)
 		{ //allocate 4 sun shadow maps
-			U32 sun_shadow_map_width = ((U32(resX*scale)+1)&~1); // must be even to avoid a stripe in the horizontal shadow blur
 			for (U32 i = 0; i < 4; i++)
 			{
-				if (!mShadow[i].allocate(sun_shadow_map_width,U32(resY*scale), 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false;
-				if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE)) return false;
+				if (!mShadow[i].allocate(sun_shadow_map_width, sun_shadow_map_height, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+                {
+                    return false;
+                }
+
+                if (!mShadowOcclusion[i].allocate(sun_shadow_map_width/occlusion_divisor, sun_shadow_map_height/occlusion_divisor, 0, TRUE, FALSE, LLTexUnit::TT_TEXTURE))
+                {
+                    return false;
+                }
 			}
 		}
 		else
 		{
 			for (U32 i = 0; i < 4; i++)
 			{
-				mShadow[i].release();
-				mShadowOcclusion[i].release();
+                releaseShadowTarget(i);
 			}
 		}
 
@@ -999,54 +1018,28 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
 		if (shadow_detail > 1)
 		{ //allocate two spot shadow maps
 			U32 spot_shadow_map_width = width;
+            U32 spot_shadow_map_height = height;
 			for (U32 i = 4; i < 6; i++)
 			{
-				if (!mShadow[i].allocate(spot_shadow_map_width, height, 0, TRUE, FALSE)) return false;
-				if (!mShadowOcclusion[i].allocate(mShadow[i].getWidth()/occlusion_divisor, mShadow[i].getHeight()/occlusion_divisor, 0, TRUE, FALSE)) return false;
-			}
-		}
-		else
+                if (!mShadow[i].allocate(spot_shadow_map_width, spot_shadow_map_height, 0, TRUE, FALSE))
 		{
-			for (U32 i = 4; i < 6; i++)
-			{
-				mShadow[i].release();
-				mShadowOcclusion[i].release();
+                    return false;
 			}
-		}
-
-		//HACK make screenbuffer allocations start failing after 30 seconds
-		if (gSavedSettings.getBOOL("SimulateFBOFailure"))
+                if (!mShadowOcclusion[i].allocate(spot_shadow_map_width/occlusion_divisor, height/occlusion_divisor, 0, TRUE, FALSE))
 		{
 			return false;
 		}
 	}
+        }
 	else
 	{
-		mDeferredLight.release();
-				
-		for (U32 i = 0; i < 6; i++)
+            for (U32 i = 4; i < 6; i++)
 		{
-			mShadow[i].release();
-			mShadowOcclusion[i].release();
+                releaseShadowTarget(i);
 		}
-		mFXAABuffer.release();
-		mScreen.release();
-		mDeferredScreen.release(); //make sure to release any render targets that share a depth buffer with mDeferredScreen first
-		mDeferredDepth.release();
-		mOcclusionDepth.release();
-						
-		if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false;		
 	}
-	
-	if (LLPipeline::sRenderDeferred)
-	{ //share depth buffer between deferred targets
-		mDeferredScreen.shareDepthBuffer(mScreen);
 	}
 
-	gGL.getTexUnit(0)->disable();
-
-	stop_glerror();
-
 	return true;
 }
 
@@ -1063,7 +1056,6 @@ void LLPipeline::updateRenderDeferred()
 					 LLRenderTarget::sUseFBO &&
 					 LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&	 
 					 LLPipeline::sRenderBump &&
-					 VertexShaderEnable && 
 					 RenderAvatarVP &&
 					 WindLightUseAtmosShaders)) &&
 					!gUseWireframe;
@@ -1092,7 +1084,6 @@ void LLPipeline::refreshCachedSettings()
 			&& gSavedSettings.getBOOL("UseOcclusion") 
 			&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
 	
-	VertexShaderEnable = gSavedSettings.getBOOL("VertexShaderEnable");
 	RenderAvatarVP = gSavedSettings.getBOOL("RenderAvatarVP");
 	WindLightUseAtmosShaders = gSavedSettings.getBOOL("WindLightUseAtmosShaders");
 	RenderDeferred = gSavedSettings.getBOOL("RenderDeferred");
@@ -1167,7 +1158,7 @@ void LLPipeline::refreshCachedSettings()
 	CameraMaxCoF = gSavedSettings.getF32("CameraMaxCoF");
 	CameraDoFResScale = gSavedSettings.getF32("CameraDoFResScale");
 	RenderAutoHideSurfaceAreaLimit = gSavedSettings.getF32("RenderAutoHideSurfaceAreaLimit");
-	
+	RenderSpotLight = nullptr;
 	updateRenderDeferred();
 }
 
@@ -1191,6 +1182,7 @@ void LLPipeline::releaseGLBuffers()
 
 	mWaterRef.release();
 	mWaterDis.release();
+    mBake.release();
 	mHighlight.release();
 	
 	for (U32 i = 0; i < 3; i++)
@@ -1213,6 +1205,11 @@ void LLPipeline::releaseLUTBuffers()
 	}
 }
 
+void LLPipeline::releaseShadowBuffers()
+{
+    releaseShadowTargets();
+}
+
 void LLPipeline::releaseScreenBuffers()
 {
 	mUIScreen.release();
@@ -1223,48 +1220,39 @@ void LLPipeline::releaseScreenBuffers()
 	mDeferredDepth.release();
 	mDeferredLight.release();
 	mOcclusionDepth.release();
+}
 		
+		
+void LLPipeline::releaseShadowTarget(U32 index)
+{
+    mShadow[index].release();
+    mShadowOcclusion[index].release();
+}
+
+void LLPipeline::releaseShadowTargets()
+{
 	for (U32 i = 0; i < 6; i++)
 	{
-		mShadow[i].release();
-		mShadowOcclusion[i].release();
+        releaseShadowTarget(i);
 	}
 }
 
-
 void LLPipeline::createGLBuffers()
 {
 	stop_glerror();
 	assertInitialized();
 
 	updateRenderDeferred();
-
-	bool materials_in_water = false;
-
-#if MATERIALS_IN_REFLECTIONS
-	materials_in_water = gSavedSettings.getS32("RenderWaterMaterials");
-#endif
-
 	if (LLPipeline::sWaterReflections)
 	{ //water reflection texture
 		U32 res = (U32) llmax(gSavedSettings.getS32("RenderWaterRefResolution"), 512);
-			
-		// Set up SRGB targets if we're doing deferred-path reflection rendering
-		//
-		if (LLPipeline::sRenderDeferred && materials_in_water)
-		{
-			mWaterRef.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE);
-			//always use FBO for mWaterDis so it can be used for avatar texture bakes
-			mWaterDis.allocate(res,res,GL_SRGB8_ALPHA8,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true);
-		}
-		else
-		{
 		mWaterRef.allocate(res,res,GL_RGBA,TRUE,FALSE);
-		//always use FBO for mWaterDis so it can be used for avatar texture bakes
-		mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE, true);
-	}
+        mWaterDis.allocate(res,res,GL_RGBA,TRUE,FALSE,LLTexUnit::TT_TEXTURE);
 	}
 
+    // Use FBO for bake tex
+    mBake.allocate(512, 512, GL_RGBA, TRUE, FALSE, LLTexUnit::TT_TEXTURE, true); // SL-12781 Build > Upload > Model; 3D Preview
+
 	mHighlight.allocate(256,256,GL_RGBA, FALSE, FALSE);
 
 	stop_glerror();
@@ -1416,12 +1404,9 @@ void LLPipeline::restoreGL()
 
 bool LLPipeline::canUseVertexShaders()
 {
-	static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable";
-
 	if (sDisableShaders ||
 		!gGLManager.mHasVertexShader ||
 		!gGLManager.mHasFragmentShader ||
-		!LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||
 		(assertInitialized() && mVertexShadersLoaded != 1) )
 	{
 		return false;
@@ -1436,13 +1421,13 @@ bool LLPipeline::canUseWindLightShaders() const
 {
 	return (!LLPipeline::sDisableShaders &&
 			gWLSkyProgram.mProgramObject != 0 &&
-			LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
+			LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_WINDLIGHT) > 1);
 }
 
 bool LLPipeline::canUseWindLightShadersOnObjects() const
 {
 	return (canUseWindLightShaders() 
-		&& LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
+		&& LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0);
 }
 
 bool LLPipeline::canUseAntiAliasing() const
@@ -1471,7 +1456,7 @@ void LLPipeline::enableShadows(const bool enable_shadows)
 
 S32 LLPipeline::getMaxLightingDetail() const
 {
-	/*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
+	/*if (mShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)
 	{
 		return 3;
 	}
@@ -2158,7 +2143,8 @@ void check_references(LLSpatialGroup* group, LLDrawable* drawable)
 {
 	for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
 	{
-		if (drawable == (LLDrawable*)(*i)->getDrawable())
+        LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
+		if (drawable == drawablep)
 		{
 			LL_ERRS() << "LLDrawable deleted while actively reference by LLPipeline." << LL_ENDL;
 		}
@@ -2299,7 +2285,7 @@ void LLPipeline::checkReferences(LLDrawInfo* draw_info)
 
 void LLPipeline::checkReferences(LLSpatialGroup* group)
 {
-#if 0
+#if CHECK_PIPELINE_REFERENCES
 	if (sCull)
 	{
 		for (LLCullResult::sg_iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
@@ -2409,15 +2395,11 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 
 	sCull->clear();
 
-	bool to_texture =	LLPipeline::sUseOcclusion > 1 &&
-						!hasRenderType(LLPipeline::RENDER_TYPE_HUD) && 
-						LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
-						gPipeline.canUseVertexShaders() &&
-						sRenderGlow;
+	bool to_texture = LLPipeline::sUseOcclusion > 1 && gPipeline.canUseVertexShaders();
 
 	if (to_texture)
 	{
-		if (LLPipeline::sRenderDeferred)
+		if (LLPipeline::sRenderDeferred && can_use_occlusion)
 		{
 			mOcclusionDepth.bindTarget();
 		}
@@ -2444,38 +2426,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 	LLGLDisable test(GL_ALPHA_TEST);
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-
-	//setup a clip plane in projection matrix for reflection renders (prevents flickering from occlusion culling)
-	LLViewerRegion* region = gAgent.getRegion();
-	LLPlane plane;
-
-	if (planep)
-	{
-		plane = *planep;
-	}
-	else 
-	{
-		if (region)
-		{
-			LLVector3 pnorm;
-			F32 height = region->getWaterHeight();
-			if (water_clip < 0)
-			{ //camera is above water, clip plane points up
-				pnorm.setVec(0,0,1);
-				plane.setVec(pnorm, -height);
-			}
-			else if (water_clip > 0)
-			{	//camera is below water, clip plane points down
-				pnorm = LLVector3(0,0,-1);
-				plane.setVec(pnorm, height);
-			}
-		}
-	}
-	
-	glh::matrix4f modelview = glh_get_last_modelview();
-	glh::matrix4f proj = glh_get_last_projection();
-	LLGLUserClipPlane clip(plane, modelview, proj, water_clip != 0 && LLPipeline::sReflectionRender);
-
 	LLGLDepthTest depth(GL_TRUE, GL_FALSE);
 
 	bool bound_shader = false;
@@ -2495,19 +2445,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 	}
 	
+    if (!sReflectionRender)
+    {
+        camera.disableUserClipPlane();
+    }
+
 	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); 
 			iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 	{
 		LLViewerRegion* region = *iter;
-		if (water_clip != 0)
-		{
-			LLPlane plane(LLVector3(0,0, (F32) -water_clip), (F32) water_clip*region->getWaterHeight());
-			camera.setUserClipPlane(plane);
-		}
-		else
-		{
-			camera.disableUserClipPlane();
-		}
 
 		for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++)
 		{
@@ -2526,6 +2472,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		if(vo_part)
 		{
 			bool do_occlusion_cull = can_use_occlusion && use_occlusion && !gUseWireframe && 0 > water_clip /* && !gViewerWindow->getProgressView()->getVisible()*/;
+            do_occlusion_cull &= !sReflectionRender;
 			vo_part->cull(camera, do_occlusion_cull);
 		}
 	}
@@ -2535,8 +2482,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 		gOcclusionCubeProgram.unbind();
 	}
 
-	camera.disableUserClipPlane();
-
 	if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && 
 		gSky.mVOSkyp.notNull() && 
 		gSky.mVOSkyp->mDrawable.notNull())
@@ -2558,6 +2503,22 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 	}
 	
 	
+    if (hasRenderType(LLPipeline::RENDER_TYPE_WL_SKY) && 
+        gPipeline.canUseWindLightShaders() &&
+        gSky.mVOWLSkyp.notNull() && 
+        gSky.mVOWLSkyp->mDrawable.notNull())
+    {
+        gSky.mVOWLSkyp->mDrawable->setVisible(camera);
+        sCull->pushDrawable(gSky.mVOWLSkyp->mDrawable);
+    }
+
+    bool render_water = !sReflectionRender && (hasRenderType(LLPipeline::RENDER_TYPE_WATER) || hasRenderType(LLPipeline::RENDER_TYPE_VOIDWATER));
+
+    if (render_water)
+    {
+        LLWorld::getInstance()->precullWaterObjects(camera, sCull, render_water);
+    }
+	
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.popMatrix();
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
@@ -2570,7 +2531,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
 
 	if (to_texture)
 	{
-		if (LLPipeline::sRenderDeferred)
+		if (LLPipeline::sRenderDeferred && can_use_occlusion)
 		{
 			mOcclusionDepth.flush();
 		}
@@ -3432,7 +3393,8 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
 			group->setVisible();
 			for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
 			{
-				markVisible((LLDrawable*)(*i)->getDrawable(), camera);
+                LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();
+				markVisible(drawablep, camera);
 			}
 
 			if (!sDelayVBUpdate)
@@ -3520,7 +3482,8 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
 	{
 		for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i)
 		{
-			stateSort((LLDrawable*)(*i)->getDrawable(), camera);
+            LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable();            
+			stateSort(drawablep, camera);
 		}
 
 		if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
@@ -3549,6 +3512,14 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
 		return;
 	}
 	
+    // SL-11353
+    // ignore our own geo when rendering spotlight shadowmaps...
+    // 
+    if (RenderSpotLight && drawablep == RenderSpotLight)
+    {
+        return;
+    }
+
 	if (LLSelectMgr::getInstance()->mHideSelectedObjects)
 	{
 		if (drawablep->getVObj().notNull() &&
@@ -4062,6 +4033,7 @@ void LLPipeline::postSort(LLCamera& camera)
 
 void render_hud_elements()
 {
+	LL_RECORD_BLOCK_TIME(FTM_RENDER_UI);
 	gPipeline.disableLights();		
 	
 	LLGLDisable fog(GL_FOG);
@@ -4139,12 +4111,13 @@ void LLPipeline::renderHighlights()
 		glStencilFunc(GL_ALWAYS, 0, 0xFFFFFFFF);
 		glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
 
-        if (canUseVertexShaders())
+		gGL.setColorMask(false, false);
+
+        if (LLGLSLShader::sNoFixedFunction)
         {
             gHighlightProgram.bind();
         }
 
-		gGL.setColorMask(false, false);
 		for (std::set<HighlightItem>::iterator iter = mHighlightSet.begin(); iter != mHighlightSet.end(); ++iter)
 		{
 			renderHighlight(iter->mItem->getVObj(), 1.f);
@@ -4226,7 +4199,7 @@ void LLPipeline::renderHighlights()
 		//gGL.setSceneBlendType(LLRender::BT_ALPHA);
 	}
 
-	if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+	if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 	{
 		gHighlightProgram.bind();
 		gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4273,7 +4246,7 @@ void LLPipeline::renderHighlights()
 	// have touch-handlers.
 	mHighlightFaces.clear();
 
-	if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
+	if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0)
 	{
 		gHighlightProgram.unbind();
 	}
@@ -4282,7 +4255,7 @@ void LLPipeline::renderHighlights()
 	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::NORMAL_MAP))
 	{
 		color.setVec(1.0f, 0.5f, 0.5f, 0.5f);
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightNormalProgram.bind();
 			gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4303,7 +4276,7 @@ void LLPipeline::renderHighlights()
 			facep->renderSelected(mFaceSelectImagep, color);
 		}
 
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightNormalProgram.unbind();
 		}
@@ -4312,7 +4285,7 @@ void LLPipeline::renderHighlights()
 	if (hasRenderDebugFeatureMask(RENDER_DEBUG_FEATURE_SELECTED) && (sRenderHighlightTextureChannel == LLRender::SPECULAR_MAP))
 	{
 		color.setVec(0.0f, 0.3f, 1.0f, 0.8f);
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightSpecularProgram.bind();
 			gGL.diffuseColor4f(1,1,1,0.5f);
@@ -4333,7 +4306,7 @@ void LLPipeline::renderHighlights()
 			facep->renderSelected(mFaceSelectImagep, color);
 		}
 
-		if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
+		if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_INTERFACE) > 0))
 		{
 			gHighlightSpecularProgram.unbind();
 		}
@@ -4560,6 +4533,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
 				// Render debugging beacons.
 				gObjectList.renderObjectBeacons();
 				gObjectList.resetObjectBeacons();
+                gSky.addSunMoonBeacons();
 			}
 			else
 			{
@@ -4680,6 +4654,7 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 	}
 
 	gGLLastMatrix = NULL;
+    gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.loadMatrix(gGLModelView);
 
 	gGL.setColorMask(true, false);
@@ -4766,16 +4741,16 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
 	}
 
 	gGLLastMatrix = NULL;
+	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.loadMatrix(gGLModelView);
 
 	if (occlude)
 	{
 		occlude = false;
-		gGLLastMatrix = NULL;
-		gGL.loadMatrix(gGLModelView);
 		LLGLSLShader::bindNoShader();
 		doOcclusion(camera);
 		gGLLastMatrix = NULL;
+		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		gGL.loadMatrix(gGLModelView);
 	}
 }
@@ -5990,6 +5965,12 @@ void LLPipeline::setupAvatarLights(bool for_edit)
 {
 	assertInitialized();
 
+    LLEnvironment& environment = LLEnvironment::instance();
+    LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+
+    bool sun_up = environment.getIsSunUp();
+
+
 	if (for_edit)
 	{
 		LLColor4 diffuse(1.f, 1.f, 1.f, 0.f);
@@ -6003,13 +5984,6 @@ void LLPipeline::setupAvatarLights(bool for_edit)
 
 		LLLightState* light = gGL.getLight(1);
 
-		if (LLPipeline::sRenderDeferred)
-		{
-			/*diffuse.mV[0] = powf(diffuse.mV[0], 2.2f);
-			diffuse.mV[1] = powf(diffuse.mV[1], 2.2f);
-			diffuse.mV[2] = powf(diffuse.mV[2], 2.2f);*/
-		}
-
 		mHWLightColors[1] = diffuse;
 
 		light->setDiffuse(diffuse);
@@ -6024,12 +5998,14 @@ void LLPipeline::setupAvatarLights(bool for_edit)
 	}
 	else if (gAvatarBacklight) // Always true (unless overridden in a devs .ini)
 	{
-		LLVector3 opposite_pos = -1.f * mSunDir;
-		LLVector3 orthog_light_pos = mSunDir % LLVector3::z_axis;
+        LLVector3 light_dir = sun_up ? LLVector3(mSunDir) : LLVector3(mMoonDir);
+		LLVector3 opposite_pos = -light_dir;
+		LLVector3 orthog_light_pos = light_dir % LLVector3::z_axis;
 		LLVector4 backlight_pos = LLVector4(lerp(opposite_pos, orthog_light_pos, 0.3f), 0.0f);
 		backlight_pos.normalize();
 			
-		LLColor4 light_diffuse = mSunDiffuse;
+		LLColor4 light_diffuse = sun_up ? mSunDiffuse : mMoonDiffuse;
+
 		LLColor4 backlight_diffuse(1.f - light_diffuse.mV[VRED], 1.f - light_diffuse.mV[VGREEN], 1.f - light_diffuse.mV[VBLUE], 1.f);
 		F32 max_component = 0.001f;
 		for (S32 i = 0; i < 3; i++)
@@ -6040,7 +6016,7 @@ void LLPipeline::setupAvatarLights(bool for_edit)
 			}
 		}
 		F32 backlight_mag;
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
+		if (LLEnvironment::instance().getIsSunUp())
 		{
 			backlight_mag = BACKLIGHT_DAY_MAGNITUDE_OBJECT;
 		}
@@ -6050,13 +6026,6 @@ void LLPipeline::setupAvatarLights(bool for_edit)
 		}
 		backlight_diffuse *= backlight_mag / max_component;
 
-		if (LLPipeline::sRenderDeferred)
-		{
-			/*backlight_diffuse.mV[0] = powf(backlight_diffuse.mV[0], 2.2f);
-			backlight_diffuse.mV[1] = powf(backlight_diffuse.mV[1], 2.2f);
-			backlight_diffuse.mV[2] = powf(backlight_diffuse.mV[2], 2.2f);*/
-		}
-
 		mHWLightColors[1] = backlight_diffuse;
 
 		LLLightState* light = gGL.getLight(1);
@@ -6249,26 +6218,31 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 {
 	assertInitialized();
 	
-	// Ambient
+    LLEnvironment& environment = LLEnvironment::instance();
+    LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+
 	if (!LLGLSLShader::sNoFixedFunction)
 	{
 		gGL.syncMatrices();
-		LLColor4 ambient = gSky.getTotalAmbientColor();
-		gGL.setAmbientLightColor(ambient);
 	}
 
+    // Ambient
+    LLColor4 ambient = psky->getTotalAmbient();
+		gGL.setAmbientLightColor(ambient);
+
+    bool sun_up  = environment.getIsSunUp();
+    bool moon_up = environment.getIsMoonUp();
+
 	// Light 0 = Sun or Moon (All objects)
 	{
-		if (gSky.getSunDirection().mV[2] >= LLSky::NIGHTTIME_ELEVATION_COS)
-		{
-			mSunDir.setVec(gSky.getSunDirection());
-			mSunDiffuse.setVec(gSky.getSunDiffuseColor());
-		}
-		else
-		{
-			mSunDir.setVec(gSky.getMoonDirection());
-			mSunDiffuse.setVec(gSky.getMoonDiffuseColor());
-		}
+        LLVector4 sun_dir(environment.getSunDirection(), 0.0f);
+        LLVector4 moon_dir(environment.getMoonDirection(), 0.0f);
+
+        mSunDir.setVec(sun_dir);
+        mMoonDir.setVec(moon_dir);
+
+        mSunDiffuse.setVec(psky->getSunlightColor());
+        mMoonDiffuse.setVec(psky->getMoonlightColor());
 
 		F32 max_color = llmax(mSunDiffuse.mV[0], mSunDiffuse.mV[1], mSunDiffuse.mV[2]);
 		if (max_color > 1.f)
@@ -6277,22 +6251,33 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 		}
 		mSunDiffuse.clamp();
 
-		LLVector4 light_pos(mSunDir, 0.0f);
-		LLColor4 light_diffuse = mSunDiffuse;
+        max_color = llmax(mMoonDiffuse.mV[0], mMoonDiffuse.mV[1], mMoonDiffuse.mV[2]);
+        if (max_color > 1.f)
+        {
+            mMoonDiffuse *= 1.f/max_color;
+        }
+        mMoonDiffuse.clamp();
 
-		if (LLPipeline::sRenderDeferred)
+        // prevent underlighting from having neither lightsource facing us
+        if (!sun_up && !moon_up)
 		{
-			/*light_diffuse.mV[0] = powf(light_diffuse.mV[0], 2.2f);
-			light_diffuse.mV[1] = powf(light_diffuse.mV[1], 2.2f);
-			light_diffuse.mV[2] = powf(light_diffuse.mV[2], 2.2f);*/
+            mSunDiffuse.setVec(LLColor4(0.0, 0.0, 0.0, 1.0));
+            mMoonDiffuse.setVec(LLColor4(0.0, 0.0, 0.0, 1.0));
+            mSunDir.setVec(LLVector4(0.0, 1.0, 0.0, 0.0));
+            mMoonDir.setVec(LLVector4(0.0, 1.0, 0.0, 0.0));
 		}
 
-		mHWLightColors[0] = light_diffuse;
+        LLVector4 light_dir = sun_up ? mSunDir : mMoonDir;
+
+        mHWLightColors[0] = sun_up ? mSunDiffuse : mMoonDiffuse;
 
 		LLLightState* light = gGL.getLight(0);
-		light->setPosition(light_pos);
-		light->setDiffuse(light_diffuse);
-		light->setAmbient(LLColor4::black);
+        light->setPosition(light_dir);
+
+        light->setSunPrimary(sun_up);
+        light->setDiffuse(mHWLightColors[0]);
+        light->setDiffuseB(mMoonDiffuse);
+        light->setAmbient(psky->getTotalAmbient());
 		light->setSpecular(LLColor4::black);
 		light->setConstantAttenuation(1.f);
 		light->setLinearAttenuation(0.f);
@@ -6321,12 +6306,28 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 			{
 				continue;
 			}
+
+            if (light->isAttachment())
+            {
+                if (!sRenderAttachedLights)
+                {
+                    continue;
+                }
+            }
+
+            const LLViewerObject *vobj = drawable->getVObj();
+            if(vobj && vobj->getAvatar() && vobj->getAvatar()->isInMuteList())
+            {
+                continue;
+            }
+
 			if (drawable->isState(LLDrawable::ACTIVE))
 			{
 				mLightMovingMask |= (1<<cur_light);
 			}
 			
-			LLColor4  light_color = light->getLightColor();
+            //send linear light color to shader
+			LLColor4  light_color = light->getLightLinearColor();
 			light_color.mV[3] = 0.0f;
 
 			F32 fade = iter->fade;
@@ -6347,13 +6348,24 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 				light_color *= fade;
 			}
 
+            if (light_color.magVecSquared() < 0.001f)
+            {
+                continue;
+            }
+
 			LLVector3 light_pos(light->getRenderPosition());
 			LLVector4 light_pos_gl(light_pos, 1.0f);
 	
 			F32 light_radius = llmax(light->getLightRadius(), 0.001f);
+            F32 size = light_radius * (sRenderDeferred ? 1.5f : 1.0f);
+
+            if (size <= 0.001f)
+            {
+                continue;
+            }
 
-			F32 x = (3.f * (1.f + light->getLightFalloff())); // why this magic?  probably trying to match a historic behavior.
-			float linatten = x / (light_radius); // % of brightness at radius
+			F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic?  probably trying to match a historic behavior.
+			F32 linatten = x / (light_radius); // % of brightness at radius
 
 			mHWLightColors[cur_light] = light_color;
 			LLLightState* light_state = gGL.getLight(cur_light);
@@ -6364,9 +6376,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 			light_state->setConstantAttenuation(0.f);
 			if (sRenderDeferred)
 			{
-				F32 size = light_radius*1.5f;
 				light_state->setLinearAttenuation(size);
-				light_state->setQuadraticAttenuation(light->getLightFalloff()*0.5f+1.f);
+				light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights
 			}
 			else
 			{
@@ -6386,7 +6397,9 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 				light_state->setSpotCutoff(90.f);
 				light_state->setSpotExponent(2.f);
 	
-				const LLColor4 specular(0.f, 0.f, 0.f, 0.f);
+				LLVector3 spotParams = light->getSpotLightParams();
+
+				const LLColor4 specular(0.f, 0.f, 0.f, spotParams[2]);
 				light_state->setSpecular(specular);
 			}
 			else // omnidirectional (point) light
@@ -6394,8 +6407,8 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 				light_state->setSpotExponent(0.f);
 				light_state->setSpotCutoff(180.f);
 				
-				// we use specular.w = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
-				const LLColor4 specular(0.f, 0.f, 0.f, 1.f);
+				// we use specular.z = 1.0 as a cheap hack for the shaders to know that this is omnidirectional rather than a spotlight
+				const LLColor4 specular(0.f, 0.f, 1.f, 0.f);
 				light_state->setSpecular(specular);				
 			}
 			cur_light++;
@@ -6409,7 +6422,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 	{
 		mHWLightColors[cur_light] = LLColor4::black;
 		LLLightState* light = gGL.getLight(cur_light);
-
+        light->setSunPrimary(true);
 		light->setDiffuse(LLColor4::black);
 		light->setAmbient(LLColor4::black);
 		light->setSpecular(LLColor4::black);
@@ -6440,6 +6453,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
 
 		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);
@@ -6508,9 +6522,6 @@ void LLPipeline::enableLights(U32 mask)
 		}
 		mLightMask = mask;
 		stop_glerror();
-
-		LLColor4 ambient = gSky.getTotalAmbientColor();
-		gGL.setAmbientLightColor(ambient);
 	}
 }
 
@@ -6626,13 +6637,11 @@ void LLPipeline::enableLightsAvatarEdit(const LLColor4& color)
 	gGL.setAmbientLightColor(color);
 }
 
-void LLPipeline::enableLightsFullbright(const LLColor4& color)
+void LLPipeline::enableLightsFullbright()
 {
 	assertInitialized();
 	U32 mask = 0x1000; // Non-0 mask, set ambient
 	enableLights(mask);
-
-	gGL.setAmbientLightColor(color);
 }
 
 void LLPipeline::disableLights()
@@ -7458,6 +7467,15 @@ void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batc
 	gGLLastMatrix = NULL;		
 }
 
+void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture)
+{
+	assertInitialized();
+	gGL.loadMatrix(gGLModelView);
+	gGLLastMatrix = NULL;
+	mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+	gGL.loadMatrix(gGLModelView);
+	gGLLastMatrix = NULL;		
+}
 
 void apply_cube_face_rotation(U32 face)
 {
@@ -7550,7 +7568,7 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 	LLGLDisable blend(GL_BLEND);
 	LLGLDisable cull(GL_CULL_FACE);
 	
-	enableLightsFullbright(LLColor4(1,1,1,1));
+	enableLightsFullbright();
 
 	gGL.matrixMode(LLRender::MM_PROJECTION);
 	gGL.pushMatrix();
@@ -7589,10 +7607,10 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 		
 		gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA);
 		
-		mScreen.bindTexture(0, 0);
+		mScreen.bindTexture(0, 0, LLTexUnit::TFO_POINT);
 		
 		gGL.color4f(1,1,1,1);
-		gPipeline.enableLightsFullbright(LLColor4(1,1,1,1));
+		gPipeline.enableLightsFullbright();
 		gGL.begin(LLRender::TRIANGLE_STRIP);
 		gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
 		gGL.vertex2f(-1,-1);
@@ -7906,14 +7924,6 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 				if (channel > -1)
 				{
 					mScreen.bindTexture(0, channel);
-					gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-				}
-
-				if (!LLViewerCamera::getInstance()->cameraUnderWater())
-				{
-					shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2);
-				} else {
-					shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0);
 				}
 
 				shader->uniform1f(LLShaderMgr::DOF_MAX_COF, CameraMaxCoF);
@@ -7957,13 +7967,6 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 				mScreen.bindTexture(0, channel);
 			}
 
-			if (!LLViewerCamera::getInstance()->cameraUnderWater())
-			{
-				shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 2.2);
-			} else {
-				shader->uniform1f(LLShaderMgr::GLOBAL_GAMMA, 1.0);
-			}
-
 			gGL.begin(LLRender::TRIANGLE_STRIP);
 			gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
 			gGL.vertex2f(-1,-1);
@@ -8023,8 +8026,7 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 			channel = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP, mFXAABuffer.getUsage());
 			if (channel > -1)
 			{
-				mFXAABuffer.bindTexture(0, channel);
-				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+				mFXAABuffer.bindTexture(0, channel, LLTexUnit::TFO_BILINEAR);
 			}
 			
 			gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft;
@@ -8176,63 +8178,66 @@ void LLPipeline::renderBloom(bool for_snapshot, F32 zoom_factor, int subfield)
 
 static LLTrace::BlockTimerStatHandle FTM_BIND_DEFERRED("Bind Deferred");
 
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target)
 {
 	LL_RECORD_BLOCK_TIME(FTM_BIND_DEFERRED);
 
-	if (noise_map == 0xFFFFFFFF)
-	{
-		noise_map = mNoiseMap;
-	}
+    LLRenderTarget* deferred_target       = &mDeferredScreen;
+    LLRenderTarget* deferred_depth_target = &mDeferredDepth;
+    LLRenderTarget* deferred_light_target = &mDeferredLight;
 
 	shader.bind();
 	S32 channel = 0;
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
+    channel = shader.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
 	if (channel > -1)
 	{
-		mDeferredScreen.bindTexture(0,channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+        deferred_target->bindTexture(0,channel, LLTexUnit::TFO_POINT);
 	}
 
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
+    channel = shader.enableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
 	if (channel > -1)
 	{
-		mDeferredScreen.bindTexture(1, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+        deferred_target->bindTexture(1, channel, LLTexUnit::TFO_POINT);
 	}
 
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
+    channel = shader.enableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
 	if (channel > -1)
 	{
-		mDeferredScreen.bindTexture(2, channel);
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+        deferred_target->bindTexture(2, channel, LLTexUnit::TFO_POINT);
 	}
 
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage());
+    channel = shader.enableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
 	if (channel > -1)
 	{
-		gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE);
+        gGL.getTexUnit(channel)->bind(deferred_depth_target, TRUE);
 		stop_glerror();
+    }
 		
-		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE);		
-		//glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA);		
-
-		stop_glerror();
-
-		glh::matrix4f projection = glh_get_current_projection();
+    glh::matrix4f projection = get_current_projection();
 		glh::matrix4f inv_proj = projection.inverse();
 		
+    if (shader.getUniformLocation(LLShaderMgr::INVERSE_PROJECTION_MATRIX) != -1)
+    {
 		shader.uniformMatrix4fv(LLShaderMgr::INVERSE_PROJECTION_MATRIX, 1, FALSE, inv_proj.m);
+    }
+
+    if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1)
+    {
 		shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
 									(F32) gGLViewport[1],
 									(F32) gGLViewport[2],
 									(F32) gGLViewport[3]);
 	}
 
+    if (sReflectionRender && !shader.getUniformLocation(LLShaderMgr::MODELVIEW_MATRIX))
+    {
+        shader.uniformMatrix4fv(LLShaderMgr::MODELVIEW_MATRIX, 1, FALSE, mReflectionModelView.m);  
+    }
+
 	channel = shader.enableTexture(LLShaderMgr::DEFERRED_NOISE);
 	if (channel > -1)
 	{
-		gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, noise_map);
+        gGL.getTexUnit(channel)->bindManual(LLTexUnit::TT_TEXTURE, mNoiseMap);
 		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
 	}
 
@@ -8244,18 +8249,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 
 	stop_glerror();
 
-	channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+    light_target = light_target ? light_target : deferred_light_target;
+    channel = shader.enableTexture(LLShaderMgr::DEFERRED_LIGHT, light_target->getUsage());
 	if (channel > -1)
 	{
-		if (light_index > 0)
-		{
-			mScreen.bindTexture(0, channel);
-		}
-		else
-		{
-			mDeferredLight.bindTexture(0, channel);
-		}
-		gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+        light_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
 	}
 
 	channel = shader.enableTexture(LLShaderMgr::DEFERRED_BLOOM);
@@ -8268,13 +8266,16 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 
 	for (U32 i = 0; i < 4; i++)
 	{
+        LLRenderTarget* shadow_target = getShadowTarget(i);
+        if (shadow_target)
+        {
 		channel = shader.enableTexture(LLShaderMgr::DEFERRED_SHADOW0+i, LLTexUnit::TT_TEXTURE);
 		stop_glerror();
 		if (channel > -1)
 		{
 			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+                gGL.getTexUnit(channel)->bind(getShadowTarget(i), TRUE);
+                gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
 			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
 			stop_glerror();
 			
@@ -8283,6 +8284,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 			stop_glerror();
 		}
 	}
+    }
 
 	for (U32 i = 4; i < 6; i++)
 	{
@@ -8291,8 +8293,11 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 		if (channel > -1)
 		{
 			stop_glerror();
-			gGL.getTexUnit(channel)->bind(&mShadow[i], TRUE);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+			LLRenderTarget* shadow_target = getShadowTarget(i);
+			if (shadow_target)
+			{
+				gGL.getTexUnit(channel)->bind(shadow_target, TRUE);
+				gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
 			gGL.getTexUnit(channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
 			stop_glerror();
 			
@@ -8301,6 +8306,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 			stop_glerror();
 		}
 	}
+	}
 
 	stop_glerror();
 
@@ -8337,6 +8343,34 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 		}
 	}
 
+    if (gAtmosphere)
+    {
+        // bind precomputed textures necessary for calculating sun and sky luminance
+        channel = shader.enableTexture(LLShaderMgr::TRANSMITTANCE_TEX, LLTexUnit::TT_TEXTURE);
+        if (channel > -1)
+        {
+            shader.bindTexture(LLShaderMgr::TRANSMITTANCE_TEX, gAtmosphere->getTransmittance());
+        }
+
+        channel = shader.enableTexture(LLShaderMgr::SCATTER_TEX, LLTexUnit::TT_TEXTURE_3D);
+        if (channel > -1)
+        {
+            shader.bindTexture(LLShaderMgr::SCATTER_TEX, gAtmosphere->getScattering());
+        }
+
+        channel = shader.enableTexture(LLShaderMgr::SINGLE_MIE_SCATTER_TEX, LLTexUnit::TT_TEXTURE_3D);
+        if (channel > -1)
+        {
+            shader.bindTexture(LLShaderMgr::SINGLE_MIE_SCATTER_TEX, gAtmosphere->getMieScattering());
+        }
+
+        channel = shader.enableTexture(LLShaderMgr::ILLUMINANCE_TEX, LLTexUnit::TT_TEXTURE);
+        if (channel > -1)
+        {
+            shader.bindTexture(LLShaderMgr::ILLUMINANCE_TEX, gAtmosphere->getIlluminance());
+        }
+    }
+
 	shader.uniform4fv(LLShaderMgr::DEFERRED_SHADOW_CLIP, 1, mSunClipPlanes.mV);
 	shader.uniform1f(LLShaderMgr::DEFERRED_SUN_WASH, RenderDeferredSunWash);
 	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_NOISE, RenderShadowNoise);
@@ -8361,700 +8395,83 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 
 	//F32 shadow_offset_error = 1.f + RenderShadowOffsetError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2]);
 	F32 shadow_bias_error = RenderShadowBiasError * fabsf(LLViewerCamera::getInstance()->getOrigin().mV[2])/3000.f;
+    F32 shadow_bias       = RenderShadowBias + shadow_bias_error;
 
-	shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+    shader.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_target->getWidth(), deferred_target->getHeight());
 	shader.uniform1f(LLShaderMgr::DEFERRED_NEAR_CLIP, LLViewerCamera::getInstance()->getNear()*2.f);
 	shader.uniform1f (LLShaderMgr::DEFERRED_SHADOW_OFFSET, RenderShadowOffset); //*shadow_offset_error);
-	shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, RenderShadowBias+shadow_bias_error);
+    shader.uniform1f(LLShaderMgr::DEFERRED_SHADOW_BIAS, shadow_bias);
 	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_OFFSET, RenderSpotShadowOffset);
 	shader.uniform1f(LLShaderMgr::DEFERRED_SPOT_SHADOW_BIAS, RenderSpotShadowBias);	
 
 	shader.uniform3fv(LLShaderMgr::DEFERRED_SUN_DIR, 1, mTransformedSunDir.mV);
+    shader.uniform3fv(LLShaderMgr::DEFERRED_MOON_DIR, 1, mTransformedMoonDir.mV);
 	shader.uniform2f(LLShaderMgr::DEFERRED_SHADOW_RES, mShadow[0].getWidth(), mShadow[0].getHeight());
 	shader.uniform2f(LLShaderMgr::DEFERRED_PROJ_SHADOW_RES, mShadow[4].getWidth(), mShadow[4].getHeight());
 	shader.uniform1f(LLShaderMgr::DEFERRED_DEPTH_CUTOFF, RenderEdgeDepthCutoff);
 	shader.uniform1f(LLShaderMgr::DEFERRED_NORM_CUTOFF, RenderEdgeNormCutoff);
 	
-
 	if (shader.getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
 	{
-		glh::matrix4f norm_mat = glh_get_current_modelview().inverse().transpose();
+        glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
 		shader.uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
 	}
-}
-
-LLColor3 pow3f(LLColor3 v, F32 f)
-{
-	v.mV[0] = powf(v.mV[0], f);
-	v.mV[1] = powf(v.mV[1], f);
-	v.mV[2] = powf(v.mV[2], f);
-	return v;
-}
-
-LLVector4 pow4fsrgb(LLVector4 v, F32 f)
-{
-	v.mV[0] = powf(v.mV[0], f);
-	v.mV[1] = powf(v.mV[1], f);
-	v.mV[2] = powf(v.mV[2], f);
-	return v;
-}
-
-static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace");
-static LLTrace::BlockTimerStatHandle FTM_GI_GATHER("Gather");
-static LLTrace::BlockTimerStatHandle FTM_SUN_SHADOW("Shadow Map");
-static LLTrace::BlockTimerStatHandle FTM_SOFTEN_SHADOW("Shadow Soften");
-static LLTrace::BlockTimerStatHandle FTM_EDGE_DETECTION("Find Edges");
-static LLTrace::BlockTimerStatHandle FTM_LOCAL_LIGHTS("Local Lights");
-static LLTrace::BlockTimerStatHandle FTM_ATMOSPHERICS("Atmospherics");
-static LLTrace::BlockTimerStatHandle FTM_FULLSCREEN_LIGHTS("Fullscreen Lights");
-static LLTrace::BlockTimerStatHandle FTM_PROJECTORS("Projectors");
-static LLTrace::BlockTimerStatHandle FTM_POST("Post");
-
-
-void LLPipeline::renderDeferredLighting()
-{
-	if (!sCull)
-	{
-		return;
-	}
-
-	{
-		LL_RECORD_BLOCK_TIME(FTM_RENDER_DEFERRED);
-
-		LLViewerCamera* camera = LLViewerCamera::getInstance();
-		{
-			LLGLDepthTest depth(GL_TRUE);
-			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
-		}
-
-		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
-
-		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);
-
-		gGL.setColorMask(true, true);
-		
-		//draw a cube around every light
-		LLVertexBuffer::unbind();
-
-		LLGLEnable cull(GL_CULL_FACE);
-		LLGLEnable blend(GL_BLEND);
-
-		glh::matrix4f mat = glh_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 mSunDir;
-			LLVector4 dir(mSunDir, 0.f);
-			glh::vec4f tc(dir.mV);
-			mat.mult_matrix_vec(tc);
-			mTransformedSunDir.set(tc.v);
-		}
-
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-		gGL.matrixMode(LLRender::MM_PROJECTION);
-		gGL.pushMatrix();
-		gGL.loadIdentity();
-
-		if (RenderDeferredSSAO || RenderShadowDetail > 0)
-		{
-			mDeferredLight.bindTarget();
-			{ //paint shadow/SSAO light map (direct lighting lightmap)
-				LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
-				bindDeferredShader(gDeferredSunProgram, 0);
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				glClearColor(1,1,1,1);
-				mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
-				glClearColor(0,0,0,0);
-
-				glh::matrix4f inv_trans = glh_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];
-					}
-				}
-
-				gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
-				gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.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);
-			}
-			mDeferredLight.flush();
-		}
-		
-		if (RenderDeferredSSAO)
-		{ //soften direct lighting lightmap
-			LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
-			//blur lightmap
-			mScreen.bindTarget();
-			glClearColor(1,1,1,1);
-			mScreen.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;
-
-			// sample symmetrically with the middle sample falling exactly on 0.0
-			F32 x = 0.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();
-			}
-			
-			mScreen.flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
-
-			bindDeferredShader(gDeferredBlurLightProgram, 1);
-			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-			mDeferredLight.bindTarget();
-
-			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();
-			}
-			mDeferredLight.flush();
-			unbindDeferredShader(gDeferredBlurLightProgram);
-		}
-
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
-		gGL.matrixMode(LLRender::MM_MODELVIEW);
-		stop_glerror();
-		gGL.popMatrix();
-		stop_glerror();
-
-		mScreen.bindTarget();
-		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
-		glClearColor(0,0,0,0);
-		mScreen.clear(GL_COLOR_BUFFER_BIT);
-		
-		if (RenderDeferredAtmospheric)
-		{ //apply sunlight contribution 
-			LL_RECORD_BLOCK_TIME(FTM_ATMOSPHERICS);
-			bindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);	
-			{
-				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();
-
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-				
-				mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
-
-			unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
-		}
-
-		{ //render non-deferred geometry (fullbright, alpha, etc)
-			LLGLDisable blend(GL_BLEND);
-			LLGLDisable stencil(GL_STENCIL_TEST);
-			gGL.setSceneBlendType(LLRender::BT_ALPHA);
-
-			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();
-		}
 
-		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;
+    shader.uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV);
+    shader.uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV);
 
-			for (U32 i = 0; i < 2; i++)
-			{
-				mTargetShadowSpotLight[i] = NULL;
-			}
-
-			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)
-					{
-						LLVOAvatar *av = vobj->getAvatar();
-						if (av)
-						{
-							if (av->isTooComplex() || av->isInMuteList() || dist_vec(av->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip)
-							{
-								continue;
-							}
-						}
-						else
-						{
-							const LLViewerObject *root_obj = drawablep->getParent() ? drawablep->getParent()->getVObj() : vobj;
-							if (root_obj && dist_vec(root_obj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip)
-							{
-								continue;
-							}
-						}
-					}
-
-					LLVector4a center;
-					center.load3(drawablep->getPositionAgent().mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
-
-					LLColor3 col = volume->getLightColor();
-					
-					if (col.magVecSquared() < 0.001f)
-					{
-						continue;
-					}
-
-					if (s <= 0.001f)
-					{
-						continue;
-					}
-
-					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;
-							}
-							
-							/*col.mV[0] = powf(col.mV[0], 2.2f);
-							col.mV[1] = powf(col.mV[1], 2.2f);
-							col.mV[2] = powf(col.mV[2], 2.2f);*/
-							
-							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()*0.5f);
-							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;
-						}
-
-						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()*0.5f));
-					}
-				}
-				unbindDeferredShader(gDeferredLightProgram);
-			}
-
-			if (!spot_lights.empty())
-			{
-				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				bindDeferredShader(gDeferredSpotLightProgram);
-
-				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				gDeferredSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
-				for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
-				{
-					LL_RECORD_BLOCK_TIME(FTM_PROJECTORS);
-					LLDrawable* drawablep = *iter;
-
-					LLVOVolume* volume = drawablep->getVOVolume();
-
-					LLVector4a center;
-					center.load3(drawablep->getPositionAgent().mV);
-					const F32* c = center.getF32ptr();
-					F32 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					setupSpotLight(gDeferredSpotLightProgram, drawablep);
-					
-					LLColor3 col = volume->getLightColor();
-					/*col.mV[0] = powf(col.mV[0], 2.2f);
-					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);*/
-					
-					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()*0.5f);
-					gGL.syncMatrices();
-										
-					mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, center));
-				}
-				gDeferredSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredSpotLightProgram);
-			}
-
-			//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);
-
-			{
-				LLGLDepthTest depth(GL_FALSE);
-
-				//full screen blit
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-				gGL.matrixMode(LLRender::MM_PROJECTION);
-				gGL.pushMatrix();
-				gGL.loadIdentity();
-
-				U32 count = 0;
-
-				const U32 max_count = LL_DEFERRED_MULTI_LIGHT_COUNT;
-				LLVector4 light[max_count];
-				LLVector4 col[max_count];
-
-				F32 far_z = 0.f;
-
-				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();
-
-					/*col[count].mV[0] = powf(col[count].mV[0], 2.2f);
-					col[count].mV[1] = powf(col[count].mV[1], 2.2f);
-					col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/
-					
-					far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z);
-					//col[count] = pow4fsrgb(col[count], 2.2f);
-					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);
-
-				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-
-				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-
-				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 s = volume->getLightRadius()*1.5f;
-
-					sVisibleLightCount++;
-
-					glh::vec3f tc(c);
-					mat.mult_matrix_vec(tc);
-					
-					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
-
-					LLColor3 col = volume->getLightColor();
-					
-					/*col.mV[0] = powf(col.mV[0], 2.2f);
-					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);*/
-					
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
-					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
-					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
-				}
-
-				gDeferredMultiSpotLightProgram.disableTexture(LLShaderMgr::DEFERRED_PROJECTION);
-				unbindDeferredShader(gDeferredMultiSpotLightProgram);
-
-				gGL.popMatrix();
-				gGL.matrixMode(LLRender::MM_MODELVIEW);
-				gGL.popMatrix();
-			}
-		}
-
-		gGL.setColorMask(true, true);
-	}
-
-	mScreen.flush();
-
-	//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);
-
-		LLVector2 tc1(0,0);
-		LLVector2 tc2((F32) mScreen.getWidth()*2,
-				  (F32) mScreen.getHeight()*2);
-
-		mScreen.bindTarget();
-		// Apply gamma correction to the frame here.
-		gDeferredPostGammaCorrectProgram.bind();
-		//mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
-		S32 channel = 0;
-		channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-		if (channel > -1)
-		{
-			mScreen.bindTexture(0,channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
-		}
-		
-		gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mScreen.getWidth(), mScreen.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();
-		
-		gGL.getTexUnit(channel)->unbind(mScreen.getUsage());
-		gDeferredPostGammaCorrectProgram.unbind();
-		mScreen.flush();
-	}
-
-	gGL.matrixMode(LLRender::MM_PROJECTION);
-	gGL.popMatrix();
-	gGL.matrixMode(LLRender::MM_MODELVIEW);
-	gGL.popMatrix();	
-
-	mScreen.bindTarget();
-
-	{ //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_ALPHA_MASK,
-						 LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
-						 END_RENDER_TYPES);
-		
-		renderGeomPostDeferred(*LLViewerCamera::getInstance());
-		popRenderTypeMask();
-	}
-
-	{
-		//render highlights, etc.
-		renderHighlights();
-		mHighlightFaces.clear();
-
-		renderDebug();
+    LLEnvironment& environment = LLEnvironment::instance();
+    LLSettingsSky::ptr_t sky = environment.getCurrentSky();
 
-		LLVertexBuffer::unbind();
+    static_cast<LLSettingsVOSky*>(sky.get())->updateShader(&shader);
+}
 
-		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
-		{
-			// Render debugging beacons.
-			gObjectList.renderObjectBeacons();
-			gObjectList.resetObjectBeacons();
-		}
-	}
+LLColor3 pow3f(LLColor3 v, F32 f)
+{
+	v.mV[0] = powf(v.mV[0], f);
+	v.mV[1] = powf(v.mV[1], f);
+	v.mV[2] = powf(v.mV[2], f);
+	return v;
+}
 
-	mScreen.flush();
-						
+LLVector4 pow4fsrgb(LLVector4 v, F32 f)
+{
+	v.mV[0] = powf(v.mV[0], f);
+	v.mV[1] = powf(v.mV[1], f);
+	v.mV[2] = powf(v.mV[2], f);
+	return v;
 }
 
-void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
+static LLTrace::BlockTimerStatHandle FTM_GI_TRACE("Trace");
+static LLTrace::BlockTimerStatHandle FTM_GI_GATHER("Gather");
+static LLTrace::BlockTimerStatHandle FTM_SUN_SHADOW("Shadow Map");
+static LLTrace::BlockTimerStatHandle FTM_SOFTEN_SHADOW("Shadow Soften");
+static LLTrace::BlockTimerStatHandle FTM_EDGE_DETECTION("Find Edges");
+static LLTrace::BlockTimerStatHandle FTM_LOCAL_LIGHTS("Local Lights");
+static LLTrace::BlockTimerStatHandle FTM_ATMOSPHERICS("Atmospherics");
+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)
 {
 	if (!sCull)
 	{
 		return;
 	}
 
+    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);
-			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
-							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);	
+            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);
@@ -9077,7 +8494,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		LLGLEnable cull(GL_CULL_FACE);
 		LLGLEnable blend(GL_BLEND);
 
-		glh::matrix4f mat = glh_copy_matrix(gGLModelView);
+        glh::matrix4f mat = copy_matrix(gGLModelView);
 
 		LLStrider<LLVector3> vert; 
 		mDeferredVB->getVertexStrider(vert);
@@ -9086,13 +8503,15 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		vert[1].set(-1,-3,0);
 		vert[2].set(3,1,0);
 		
-		{
-			setupHWLights(NULL); //to set mSunDir;
-			LLVector4 dir(mSunDir, 0.f);
-			glh::vec4f tc(dir.mV);
+        setupHWLights(NULL); //to set mSun/MoonDir;
+
+        glh::vec4f tc(mSunDir.mV);
 			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();
@@ -9102,16 +8521,16 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 
 		if (RenderDeferredSSAO || RenderShadowDetail > 0)
 		{
-			mDeferredLight.bindTarget();
+            deferred_light_target->bindTarget();
 			{ //paint shadow/SSAO light map (direct lighting lightmap)
 				LL_RECORD_BLOCK_TIME(FTM_SUN_SHADOW);
-				bindDeferredShader(gDeferredSunProgram);
+                bindDeferredShader(gDeferredSunProgram, deferred_light_target);
 				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 				glClearColor(1,1,1,1);
-				mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
+                deferred_light_target->clear(GL_COLOR_BUFFER_BIT);
 				glClearColor(0,0,0,0);
 
-				glh::matrix4f inv_trans = glh_get_current_modelview().inverse().transpose();
+                glh::matrix4f inv_trans = get_current_modelview().inverse().transpose();
 
 				const U32 slice = 32;
 				F32 offset[slice*3];
@@ -9130,8 +8549,8 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 					}
 				}
 
-				gDeferredSunProgram.uniform3fv(LLShaderMgr::DEFERRED_SHADOW_OFFSET, slice, offset);
-				gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, mDeferredLight.getWidth(), mDeferredLight.getHeight());
+				gDeferredSunProgram.uniform3fv(sOffset, slice, offset);
+                gDeferredSunProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, deferred_light_target->getWidth(), deferred_light_target->getHeight());
 				
 				{
 					LLGLDisable blend(GL_BLEND);
@@ -9143,9 +8562,72 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 				
 				unbindDeferredShader(gDeferredSunProgram);
 			}
-			mDeferredLight.flush();
+            deferred_light_target->flush();
 		}
-				
+		
+		if (RenderDeferredSSAO)
+		{ //soften direct lighting lightmap
+			LL_RECORD_BLOCK_TIME(FTM_SOFTEN_SHADOW);
+			//blur lightmap
+            screen_target->bindTarget();
+			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;
+
+			// sample symmetrically with the middle sample falling exactly on 0.0
+			F32 x = 0.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();
+			}
+			
+            screen_target->flush();
+			unbindDeferredShader(gDeferredBlurLightProgram);
+
+            bindDeferredShader(gDeferredBlurLightProgram, screen_target);
+
+			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+            deferred_light_target->bindTarget();
+
+			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();
+			}
+            deferred_light_target->flush();
+			unbindDeferredShader(gDeferredBlurLightProgram);
+		}
+
 		stop_glerror();
 		gGL.popMatrix();
 		stop_glerror();
@@ -9154,16 +8636,22 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		gGL.popMatrix();
 		stop_glerror();
 
-		target->bindTarget();
-
-		//clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+        screen_target->bindTarget();
+		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
 		glClearColor(0,0,0,0);
-		target->clear(GL_COLOR_BUFFER_BIT);
+        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(gDeferredSoftenProgram);	
+            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);
@@ -9185,7 +8673,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 				gGL.popMatrix();
 			}
 
-			unbindDeferredShader(gDeferredSoftenProgram);
+			unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
 		}
 
 		{ //render non-deferred geometry (fullbright, alpha, etc)
@@ -9252,13 +8740,34 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 						}
 					}
 
+					const LLViewerObject *vobj = drawablep->getVObj();
+					if (vobj)
+					{
+						LLVOAvatar *av = vobj->getAvatar();
+						if (av)
+						{
+							if (av->isTooComplex() || av->isInMuteList() || dist_vec(av->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip)
+							{
+								continue;
+							}
+						}
+						else
+						{
+							const LLViewerObject *root_obj = drawablep->getParent() ? drawablep->getParent()->getVObj() : vobj;
+							if (root_obj && dist_vec(root_obj->getPosition(), LLViewerCamera::getInstance()->getOrigin()) > RenderFarClip)
+					{
+						continue;
+					}
+						}
+					}
 
 					LLVector4a center;
 					center.load3(drawablep->getPositionAgent().mV);
 					const F32* c = center.getF32ptr();
 					F32 s = volume->getLightRadius()*1.5f;
 
-					LLColor3 col = volume->getLightColor();
+                    //send light color to shader in linear space
+                    LLColor3 col = volume->getLightLinearColor();
 					
 					if (col.magVecSquared() < 0.001f)
 					{
@@ -9295,15 +8804,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 								continue;
 							}
 							
-							/*col.mV[0] = powf(col.mV[0], 2.2f);
-							col.mV[1] = powf(col.mV[1], 2.2f);
-							col.mV[2] = powf(col.mV[2], 2.2f);*/
-							
 							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()*0.5f);
+                            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));
@@ -9323,7 +8828,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 						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()*0.5f));
+                        light_colors.push_back(LLVector4(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF)));
 					}
 				}
 				unbindDeferredShader(gDeferredLightProgram);
@@ -9354,15 +8859,13 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 
 					setupSpotLight(gDeferredSpotLightProgram, drawablep);
 					
-					LLColor3 col = volume->getLightColor();
-					/*col.mV[0] = powf(col.mV[0], 2.2f);
-					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);*/
+                    //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.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+                    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));
@@ -9402,13 +8905,8 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 					fullscreen_lights.pop_front();
 					col[count] = light_colors.front();
 					light_colors.pop_front();
-					
-					/*col[count].mV[0] = powf(col[count].mV[0], 2.2f);
-					col[count].mV[1] = powf(col[count].mV[1], 2.2f);
-					col[count].mV[2] = powf(col[count].mV[2], 2.2f);*/
-					
+
 					far_z = llmin(light[count].mV[2]-light[count].mV[3], far_z);
-					//col[count] = pow4fsrgb(col[count], 2.2f);
 					count++;
 					if (count == max_count || fullscreen_lights.empty())
 					{
@@ -9420,13 +8918,12 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 						gDeferredMultiLightProgram[idx].uniform1f(LLShaderMgr::MULTI_LIGHT_FAR_Z, far_z);
 						far_z = 0.f;
 						count = 0; 
-						mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
+      mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 						mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+						unbindDeferredShader(gDeferredMultiLightProgram[idx]);
 					}
 				}
 				
-				unbindDeferredShader(gDeferredMultiLightProgram[0]);
-
 				bindDeferredShader(gDeferredMultiSpotLightProgram);
 
 				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
@@ -9442,7 +8939,8 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 
 					LLVector3 center = drawablep->getPositionAgent();
 					F32* c = center.mV;
-					F32 s = volume->getLightRadius()*1.5f;
+                    F32 light_size_final = volume->getLightRadius()*1.5f;
+                    F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF);
 
 					sVisibleLightCount++;
 
@@ -9451,16 +8949,13 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 					
 					setupSpotLight(gDeferredMultiSpotLightProgram, drawablep);
 
-					LLColor3 col = volume->getLightColor();
-					
-					/*col.mV[0] = powf(col.mV[0], 2.2f);
-					col.mV[1] = powf(col.mV[1], 2.2f);
-					col.mV[2] = powf(col.mV[2], 2.2f);*/
+                    //send light color to shader in linear space
+                    LLColor3 col = volume->getLightLinearColor();
 					
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::LIGHT_CENTER, 1, tc.v);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, s);
+                    gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_SIZE, light_size_final);
 					gDeferredMultiSpotLightProgram.uniform3fv(LLShaderMgr::DIFFUSE_COLOR, 1, col.mV);
-					gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, volume->getLightFalloff()*0.5f);
+                    gDeferredMultiSpotLightProgram.uniform1f(LLShaderMgr::LIGHT_FALLOFF, light_falloff_final);
 					mDeferredVB->drawArrays(LLRender::TRIANGLES, 0, 3);
 				}
 
@@ -9476,7 +8971,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		gGL.setColorMask(true, true);
 	}
 
-	/*target->flush();
+    screen_target->flush();
 
 	//gamma correct lighting
 	gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -9490,22 +8985,21 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		LLGLDepthTest depth(GL_FALSE, GL_FALSE);
 
 		LLVector2 tc1(0,0);
-		LLVector2 tc2((F32) target->getWidth()*2,
-				  (F32) target->getHeight()*2);
+        LLVector2 tc2((F32) screen_target->getWidth()*2,
+                  (F32) screen_target->getHeight()*2);
 
-		target->bindTarget();
+        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, target->getUsage());
+        channel = gDeferredPostGammaCorrectProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, screen_target->getUsage());
 		if (channel > -1)
 		{
-			target->bindTexture(0,channel);
-			gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+            screen_target->bindTexture(0, channel, LLTexUnit::TFO_POINT);
 		}
 		
-		gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, target->getWidth(), target->getHeight());
+        gDeferredPostGammaCorrectProgram.uniform2f(LLShaderMgr::DEFERRED_SCREEN_RES, screen_target->getWidth(), screen_target->getHeight());
 		
 		F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
 
@@ -9523,9 +9017,9 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		
 		gGL.end();
 		
-		gGL.getTexUnit(channel)->unbind(target->getUsage());
+        gGL.getTexUnit(channel)->unbind(screen_target->getUsage());
 		gDeferredPostGammaCorrectProgram.unbind();
-		target->flush();
+        screen_target->flush();
 	}
 
 	gGL.matrixMode(LLRender::MM_PROJECTION);
@@ -9533,7 +9027,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.popMatrix();	
 
-	target->bindTarget();*/
+    screen_target->bindTarget();
 
 	{ //render non-deferred geometry (alpha, fullbright, glow)
 		LLGLDisable blend(GL_BLEND);
@@ -9567,7 +9061,25 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		popRenderTypeMask();
 	}
 
-	//target->flush();				
+	{
+		//render highlights, etc.
+		renderHighlights();
+		mHighlightFaces.clear();
+
+		renderDebug();
+
+		LLVertexBuffer::unbind();
+
+		if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+		{
+			// Render debugging beacons.
+			gObjectList.renderObjectBeacons();
+			gObjectList.resetObjectBeacons();
+            gSky.addSunMoonBeacons();
+		}
+	}
+
+	screen_target->flush();                        
 }
 
 void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
@@ -9599,7 +9111,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
 	LLMatrix4 light_mat(quat, LLVector4(origin,1.f));
 
 	glh::matrix4f light_to_agent((F32*) light_mat.mMatrix);
-	glh::matrix4f light_to_screen = glh_get_current_modelview() * light_to_agent;
+	glh::matrix4f light_to_screen = get_current_modelview() * light_to_agent;
 
 	glh::matrix4f screen_to_light = light_to_screen.inverse();
 
@@ -9711,12 +9223,16 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
 
 void LLPipeline::unbindDeferredShader(LLGLSLShader &shader)
 {
+    LLRenderTarget* deferred_target       = &mDeferredScreen;
+    LLRenderTarget* deferred_depth_target = &mDeferredDepth;
+    LLRenderTarget* deferred_light_target = &mDeferredLight;
+
 	stop_glerror();
-	shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage());
-	shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, mDeferredLight.getUsage());
+    shader.disableTexture(LLShaderMgr::DEFERRED_NORMAL, deferred_target->getUsage());
+    shader.disableTexture(LLShaderMgr::DEFERRED_DIFFUSE, deferred_target->getUsage());
+    shader.disableTexture(LLShaderMgr::DEFERRED_SPECULAR, deferred_target->getUsage());
+    shader.disableTexture(LLShaderMgr::DEFERRED_DEPTH, deferred_depth_target->getUsage());
+    shader.disableTexture(LLShaderMgr::DEFERRED_LIGHT, deferred_light_target->getUsage());
 	shader.disableTexture(LLShaderMgr::DIFFUSE_MAP);
 	shader.disableTexture(LLShaderMgr::DEFERRED_BLOOM);
 
@@ -9770,105 +9286,95 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			skip_avatar_update = true;
 		}
 		
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(CAMERA_MODE_THIRD_PERSON);
-		}
-		LLVertexBuffer::unbind();
+        LLCamera camera = camera_in;
 
-		LLGLState::checkStates();
-		LLGLState::checkTextureChannels();
-		LLGLState::checkClientArrays();
+        camera.setFar(camera_in.getFar() * 0.75f);
+
+        bool camera_is_underwater = LLViewerCamera::getInstance()->cameraUnderWater();
 
-		LLCamera camera = camera_in;
-		camera.setFar(camera.getFar()*0.87654321f);
 		LLPipeline::sReflectionRender = true;
 		
 		gPipeline.pushRenderTypeMask();
 
-		glh::matrix4f projection = glh_get_current_projection();
+        glh::matrix4f projection = get_current_projection();
 		glh::matrix4f mat;
 
-		stop_glerror();
-		LLPlane plane;
+        S32 detail = RenderReflectionDetail;
+
+        F32 water_height      = gAgent.getRegion()->getWaterHeight(); 
+        F32 camera_height     = camera_in.getOrigin().mV[VZ];
+        F32 distance_to_water = (water_height < camera_height) ? (camera_height - water_height) : (water_height - camera_height);
+
+        LLVector3 reflection_offset      = LLVector3(0, 0, distance_to_water * 2.0f);
+        LLVector3 camera_look_at         = camera_in.getAtAxis();
+        LLVector3 reflection_look_at     = LLVector3(camera_look_at.mV[VX], camera_look_at.mV[VY], -camera_look_at.mV[VZ]);
+        LLVector3 reflect_origin         = camera_in.getOrigin() - reflection_offset;
+        LLVector3 reflect_interest_point = reflect_origin + (reflection_look_at * 5.0f);
 
-		F32 height = gAgent.getRegion()->getWaterHeight(); 
-		F32 to_clip = fabsf(camera.getOrigin().mV[2]-height);
-		F32 pad = -to_clip*0.05f; //amount to "pad" clip plane by
+        camera.setOriginAndLookAt(reflect_origin, LLVector3::z_axis, reflect_interest_point);
 
 		//plane params
+        LLPlane plane;
 		LLVector3 pnorm;
-		F32 pd;
-
 		S32 water_clip = 0;
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
+        if (!camera_is_underwater)
 		{ //camera is above water, clip plane points up
 			pnorm.setVec(0,0,1);
-			pd = -height;
-			plane.setVec(pnorm, pd);
-			water_clip = -1;
+            plane.setVec(pnorm, -water_height);
+            water_clip = 1;
 		}
 		else
 		{	//camera is below water, clip plane points down
 			pnorm = LLVector3(0,0,-1);
-			pd = height;
-			plane.setVec(pnorm, pd);
-			water_clip = 1;
+            plane.setVec(pnorm, water_height);
+            water_clip = -1;
 		}
 
-		bool materials_in_water = false;
-
-#if MATERIALS_IN_REFLECTIONS
-		materials_in_water = gSavedSettings.getS32("RenderWaterMaterials");
-#endif
-
-		if (!LLViewerCamera::getInstance()->cameraUnderWater())
-		{	//generate planar reflection map
+        S32 occlusion = LLPipeline::sUseOcclusion;
 
 			//disable occlusion culling for reflection map for now
-			S32 occlusion = LLPipeline::sUseOcclusion;
 			LLPipeline::sUseOcclusion = 0;
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			glClearColor(0,0,0,0);
 
-			mWaterRef.bindTarget();
+        glh::matrix4f current = get_current_modelview();
 
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
-			gGL.setColorMask(true, true);
-			mWaterRef.clear();
-			gGL.setColorMask(true, false);
+        if (!camera_is_underwater)
+        {   //generate planar reflection map
 
-			mWaterRef.getViewport(gGLViewport);
+			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
 
-			stop_glerror();
+            gGL.matrixMode(LLRender::MM_MODELVIEW);
+            gGL.pushMatrix();
 
-			gGL.pushMatrix();
+            glh::matrix4f mat;
+            camera.getOpenGLTransform(mat.m);
 
-			mat.set_scale(glh::vec3f(1,1,-1));
-			mat.set_translate(glh::vec3f(0,0,height*2.f));
+            glh::matrix4f scal;
+            scal.set_scale(glh::vec3f(1, 1, -1));
+            mat = scal * mat;
 
-			glh::matrix4f current = glh_get_current_modelview();
+            // convert from CFR to OGL coord sys...
+            mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
 
-			mat = current * mat;
+            mReflectionModelView = mat;
 
-			glh_set_current_modelview(mat);
+            set_current_modelview(mat);
 			gGL.loadMatrix(mat.m);
 
 			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
 
-			glh::matrix4f inv_mat = mat.inverse();
-
-			glh::vec3f origin(0,0,0);
-			inv_mat.mult_matrix_vec(origin);
-
-			camera.setOrigin(origin.v);
-
 			glCullFace(GL_FRONT);
 
-			static LLCullResult ref_result;
-
 			if (LLDrawPoolWater::sNeedsReflectionUpdate)
 			{
+                gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+                glClearColor(0,0,0,0);
+                mWaterRef.bindTarget();
+
+                gGL.setColorMask(true, true);
+                mWaterRef.clear();
+                gGL.setColorMask(true, false);
+                mWaterRef.getViewport(gGLViewport);
+
 				//initial sky pass (no user clip plane)
 				{ //mask out everything but the sky
 					gPipeline.pushRenderTypeMask();
@@ -9877,31 +9383,13 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 						LLPipeline::RENDER_TYPE_CLOUDS,
 						LLPipeline::END_RENDER_TYPES);
 
-					static LLCullResult result;
-					updateCull(camera, result);
-					stateSort(camera, result);
-
-					if (LLPipeline::sRenderDeferred && materials_in_water)
-					{
-						mWaterRef.flush();
-
-						gPipeline.grabReferences(result);
-						gPipeline.mDeferredScreen.bindTarget();
-						gGL.setColorMask(true, true);
-						glClearColor(0,0,0,0);
-						gPipeline.mDeferredScreen.clear();
-
-						renderGeomDeferred(camera);
-					}
-					else
-					{
+                    updateCull(camera, mSky);
+                    stateSort(camera, mSky);
 						renderGeom(camera, TRUE);
-					}
 
 					gPipeline.popRenderTypeMask();
 				}
 
-				gGL.setColorMask(true, false);
 				gPipeline.pushRenderTypeMask();
 
 				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
@@ -9911,10 +9399,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 					LLPipeline::RENDER_TYPE_CLOUDS,
 					LLPipeline::END_RENDER_TYPES);	
 
-				S32 detail = RenderReflectionDetail;
 				if (detail > 0)
 				{ //mask out selected geometry based on reflection detail
-
 					if (detail < 4)
 					{
 						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
@@ -9928,63 +9414,46 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 						}
 					}
 
-
-					LLGLUserClipPlane clip_plane(plane, mat, projection);
+                    LLGLUserClipPlane clip_plane(plane, mReflectionModelView, projection);
 					LLGLDisable cull(GL_CULL_FACE);
-					updateCull(camera, ref_result, -water_clip, &plane);
-					stateSort(camera, ref_result);
-				}	
-
-				if (LLDrawPoolWater::sNeedsDistortionUpdate)
-				{
-					if (RenderReflectionDetail > 0)
-					{
-						gPipeline.grabReferences(ref_result);
-						LLGLUserClipPlane clip_plane(plane, mat, projection);
-
-						if (LLPipeline::sRenderDeferred && materials_in_water)
-						{
-							renderGeomDeferred(camera);
-						}
-						else
-						{
+                    updateCull(camera, mReflectedObjects, -water_clip, &plane);
+                    stateSort(camera, mReflectedObjects);
 							renderGeom(camera);
 						}
-					}
-				}
-
-				if (LLPipeline::sRenderDeferred && materials_in_water)
-				{
-					gPipeline.mDeferredScreen.flush();
-					renderDeferredLightingToRT(&mWaterRef);
+                gPipeline.popRenderTypeMask();
+                mWaterRef.flush();
 				}
 
-				gPipeline.popRenderTypeMask();
-			}	
 			glCullFace(GL_BACK);
+            gGL.matrixMode(LLRender::MM_MODELVIEW);
 			gGL.popMatrix();
-			mWaterRef.flush();
-			glh_set_current_modelview(current);
-			LLPipeline::sUseOcclusion = occlusion;
+            
+            set_current_modelview(current);         
 		}
 
+        //LLPipeline::sUseOcclusion = occlusion;
+
 		camera.setOrigin(camera_in.getOrigin());
 		//render distortion map
 		static bool last_update = true;
 		if (last_update)
 		{
+            gPipeline.pushRenderTypeMask();
+
 			camera.setFar(camera_in.getFar());
 			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
 								LLPipeline::RENDER_TYPE_VOIDWATER,
 								LLPipeline::RENDER_TYPE_GROUND,
 								END_RENDER_TYPES);	
-			stop_glerror();
 
-			LLPipeline::sUnderWaterRender = ! LLViewerCamera::getInstance()->cameraUnderWater();
+            // intentionally inverted so that distortion map contents (objects under the water when we're above it)
+            // will properly include water fog effects
+            LLPipeline::sUnderWaterRender = !camera_is_underwater;
 
 			if (LLPipeline::sUnderWaterRender)
 			{
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_GROUND,
+                clearRenderTypeMask(
+                                    LLPipeline::RENDER_TYPE_GROUND,
 									LLPipeline::RENDER_TYPE_SKY,
 									LLPipeline::RENDER_TYPE_CLOUDS,
 									LLPipeline::RENDER_TYPE_WL_SKY,
@@ -9994,43 +9463,41 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
 			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 			
-			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
+            if (LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsDistortionUpdate)
+            {
+                LLPipeline::sDistortionRender = true;
+
+                LLColor3 col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
 			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
-			mWaterDis.bindTarget();
+
 			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
 			
+                mWaterDis.bindTarget();
 			mWaterDis.getViewport(gGLViewport);
 			
-			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
-			{
-				//clip out geometry on the same side of water as the camera
-				mat = glh_get_current_modelview();
-				LLPlane plane(-pnorm, -(pd+pad));
+                gGL.setColorMask(true, true);
+                mWaterDis.clear();
+                gGL.setColorMask(true, false);
 
-				LLGLUserClipPlane clip_plane(plane, mat, projection);
-				static LLCullResult result;
-				updateCull(camera, result, water_clip, &plane);
-				stateSort(camera, result);
+                F32 water_dist = water_height * LLPipeline::sDistortionWaterClipPlaneMargin;
+
+                //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);
 
 				gGL.setColorMask(true, true);
 				mWaterDis.clear();
-				
-
 				gGL.setColorMask(true, false);
 
-				
-				if (LLPipeline::sRenderDeferred && materials_in_water)
+                // ignore clip plane if we're underwater and viewing distortion map of objects above waterline
+                if (camera_is_underwater)
 				{
-					mWaterDis.flush();
-					gPipeline.mDeferredScreen.bindTarget();
-					gGL.setColorMask(true, true);
-					glClearColor(0,0,0,0);
-					gPipeline.mDeferredScreen.clear();
-					gPipeline.grabReferences(result);
-					renderGeomDeferred(camera);
+                    clip_plane.disable();
 				}
-				else
-				{
+
+                updateCull(camera, mRefractedObjects, water_clip, &plane);
+                stateSort(camera, mRefractedObjects);
 					renderGeom(camera);
 
 					if (LLGLSLShader::sNoFixedFunction)
@@ -10044,34 +9511,31 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 					{
 						gUIProgram.unbind();
 					}
-				}
 
-				if (LLPipeline::sRenderDeferred && materials_in_water)
-				{
-					gPipeline.mDeferredScreen.flush();
-					renderDeferredLightingToRT(&mWaterDis);
-				}
+                mWaterDis.flush();
 			}
 
-			mWaterDis.flush();
-			LLPipeline::sUnderWaterRender = false;
+            LLPipeline::sDistortionRender = false;
 			
+            gPipeline.popRenderTypeMask();
 		}
 		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
 
+        gPipeline.popRenderTypeMask();
+
+        LLPipeline::sUseOcclusion     = occlusion;
+        LLPipeline::sUnderWaterRender = false;
 		LLPipeline::sReflectionRender = false;
 
+        LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
+        LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
+
 		if (!LLRenderTarget::sUseFBO)
 		{
 			glClear(GL_DEPTH_BUFFER_BIT);
 		}
 		glClearColor(0.f, 0.f, 0.f, 0.f);
 		gViewerWindow->setup3DViewport();
-		gPipeline.popRenderTypeMask();
-		LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
-		LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
-		LLPlane npnorm(-pnorm, -pd);
-		LLViewerCamera::getInstance()->setUserClipPlane(npnorm);
 		
 		LLGLState::checkStates();
 
@@ -10153,6 +9617,13 @@ glh::matrix4f scale_translate_to_fit(const LLVector3 min, const LLVector3 max)
 static LLTrace::BlockTimerStatHandle FTM_SHADOW_RENDER("Render Shadows");
 static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA("Alpha Shadow");
 static LLTrace::BlockTimerStatHandle FTM_SHADOW_SIMPLE("Simple Shadow");
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_GEOM("Shadow Geom");
+
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_MASKED("Alpha Masked");
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_BLEND("Alpha Blend");
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree");
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass");
+static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked");
 
 void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, bool use_shader, bool use_occlusion, U32 target_width)
 {
@@ -10207,7 +9678,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	gGL.loadMatrix(proj.m);
 	gGL.matrixMode(LLRender::MM_MODELVIEW);
 	gGL.pushMatrix();
-	gGL.loadMatrix(gGLModelView);
+	gGL.loadMatrix(view.m);
 
 	stop_glerror();
 	gGLLastMatrix = NULL;
@@ -10216,6 +9687,8 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	
 	stop_glerror();
 	
+    LLEnvironment& environment = LLEnvironment::instance();
+
 	LLVertexBuffer::unbind();
 
 	{
@@ -10226,10 +9699,18 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 		else
 		{
 			gDeferredShadowProgram.bind();
+            gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 		}
 
 		gGL.diffuseColor4f(1,1,1,1);
+
+        S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
+
+        // if not using VSM, disable color writes
+        if (shadow_detail <= 2)
+        {
 		gGL.setColorMask(false, false);
+        }
 	
 		LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE);
 		
@@ -10247,41 +9728,69 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
 	
 	if (use_shader)
 	{
+        LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM);
+
 		gDeferredShadowProgram.unbind();
 		renderGeomShadow(shadow_cam);
 		gDeferredShadowProgram.bind();
+        gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 	}
 	else
 	{
+        LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM);
+
 		renderGeomShadow(shadow_cam);
 	}
 
 	{
 		LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA);
+
 		gDeferredShadowAlphaMaskProgram.bind();
 		gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+        gDeferredShadowAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 
 		U32 mask =	LLVertexBuffer::MAP_VERTEX | 
 					LLVertexBuffer::MAP_TEXCOORD0 | 
 					LLVertexBuffer::MAP_COLOR | 
 					LLVertexBuffer::MAP_TEXTURE_INDEX;
 
+        {
+            LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED);
 		renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
-		renderMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
+        }
+
+        {
+            LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND);
 		gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
 		renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
+        }
+
+        {
+            LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED);
+            gDeferredShadowFullbrightAlphaMaskProgram.bind();
+            gDeferredShadowFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+            gDeferredShadowFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+            renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
+        }
 
 		mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX;
 
+        {
+            LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_TREE);
 		gDeferredTreeShadowProgram.bind();
+            gDeferredTreeShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 		renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, mask);
 		renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask);
 		renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, mask);
 		renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, mask);
+        }
 		
+        {
+            LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS);
 		gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
 		renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
 	}
+    }
 
 	//glCullFace(GL_BACK);
 
@@ -10525,7 +10034,7 @@ void LLPipeline::generateHighlight(LLCamera& camera)
 		gGL.setColorMask(true, true);
 		mHighlight.clear();
 
-        if (canUseVertexShaders())
+        if (LLGLSLShader::sNoFixedFunction)
         {
             gHighlightProgram.bind();
         }
@@ -10564,8 +10073,16 @@ void LLPipeline::generateHighlight(LLCamera& camera)
 	}
 }
 
+LLRenderTarget* LLPipeline::getShadowTarget(U32 i)
+{
+    return &mShadow[i];
+}
 
 static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW("Gen Sun Shadow");
+static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SETUP("Sun Shadow Setup");
+static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_RENDER_DIRECTIONAL("Render Dir");
+static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_SETUP("Spot Shadow Setup");
+static LLTrace::BlockTimerStatHandle FTM_GEN_SUN_SHADOW_SPOT_RENDER("Spot Shadow Render");
 
 void LLPipeline::generateSunShadow(LLCamera& camera)
 {
@@ -10637,11 +10154,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 	gGL.setColorMask(false, false);
 
+    LLEnvironment& environment = LLEnvironment::instance();
+
 	//get sun view matrix
 	
 	//store current projection/modelview matrix
-	glh::matrix4f saved_proj = glh_get_current_projection();
-	glh::matrix4f saved_view = glh_get_current_modelview();
+	glh::matrix4f saved_proj = get_current_projection();
+	glh::matrix4f saved_view = get_current_modelview();
 	glh::matrix4f inv_view = saved_view.inverse();
 
 	glh::matrix4f view[6];
@@ -10650,6 +10169,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 	//clip contains parallel split distances for 3 splits
 	LLVector3 clip = RenderShadowClipPlanes;
 
+    LLVector3 caster_dir(environment.getIsSunUp() ? mSunDir : mMoonDir);
+
 	//F32 slope_threshold = gSavedSettings.getF32("RenderShadowSlopeThreshold");
 
 	//far clip on last split is minimum of camera view distance and 128
@@ -10666,11 +10187,11 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 	LLPlane shadow_near_clip;
 	{
 		LLVector3 p = gAgent.getPositionAgent();
-		p += mSunDir * RenderFarClip*2.f;
-		shadow_near_clip.setVec(p, mSunDir);
+		p += caster_dir * RenderFarClip*2.f;
+		shadow_near_clip.setVec(p, caster_dir);
 	}
 
-	LLVector3 lightDir = -mSunDir;
+	LLVector3 lightDir = -caster_dir;
 	lightDir.normVec();
 
 	glh::vec3f light_dir(lightDir.mV);
@@ -10745,8 +10266,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 			update_min_max(min, max, fp[i]);
 		}
 
-		near_clip = -max.mV[2];
-		F32 far_clip = -min.mV[2]*2.f;
+		near_clip    = llclamp(-max.mV[2], 0.01f, 4.0f);
+		F32 far_clip = llclamp(-min.mV[2]*2.f, 16.0f, 512.0f);
 
 		//far_clip = llmin(far_clip, 128.f);
 		far_clip = llmin(far_clip, camera.getFar());
@@ -10798,8 +10319,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 			LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j);
 
 			//restore render matrices
-			glh_set_current_modelview(saved_view);
-			glh_set_current_projection(saved_proj);
+			set_current_modelview(saved_view);
+			set_current_projection(saved_proj);
 
 			LLVector3 eye = camera.getOrigin();
 
@@ -11112,8 +10633,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 			shadow_cam.setOrigin(0,0,0);
 
-			glh_set_current_modelview(view[j]);
-			glh_set_current_projection(proj[j]);
+			set_current_modelview(view[j]);
+			set_current_projection(proj[j]);
 
 			LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
 
@@ -11126,8 +10647,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 							0.f, 0.f, 0.5f, 0.5f,
 							0.f, 0.f, 0.f, 1.f);
 
-			glh_set_current_modelview(view[j]);
-			glh_set_current_projection(proj[j]);
+			set_current_modelview(view[j]);
+			set_current_projection(proj[j]);
 
 			for (U32 i = 0; i < 16; i++)
 			{
@@ -11137,8 +10658,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 			mShadowModelview[j] = view[j];
 			mShadowProjection[j] = proj[j];
-
-	
 			mSunShadowMatrix[j] = trans*proj[j]*view[j]*inv_view;
 		
 			stop_glerror();
@@ -11151,15 +10670,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 			{
 				static LLCullResult result[4];
-
-				renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, TRUE, target_width);
+				renderShadow(view[j], proj[j], shadow_cam, result[j], TRUE, FALSE, target_width);
 			}
 
 			mShadow[j].flush();
  
 			if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
 			{
-				LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
 				mShadowCamera[j+4] = shadow_cam;
 			}
 		}
@@ -11206,8 +10723,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 		for (S32 i = 0; i < 2; i++)
 		{
-			glh_set_current_modelview(saved_view);
-			glh_set_current_projection(saved_proj);
+			set_current_modelview(saved_view);
+			set_current_projection(saved_proj);
 
 			if (mShadowSpotLight[i].isNull())
 			{
@@ -11267,8 +10784,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 							0.f, 0.f, 0.5f, 0.5f,
 							0.f, 0.f, 0.f, 1.f);
 
-			glh_set_current_modelview(view[i+4]);
-			glh_set_current_projection(proj[i+4]);
+			set_current_modelview(view[i+4]);
+			set_current_projection(proj[i+4]);
 
 			mSunShadowMatrix[i+4] = trans*proj[i+4]*view[i+4]*inv_view;
 			
@@ -11299,8 +10816,12 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 			LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4);
 
+            RenderSpotLight = drawable;            
+
 			renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width);
 
+            RenderSpotLight = nullptr;
+
 			mShadow[i+4].flush();
  		}
 	}
@@ -11312,13 +10833,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
 
 	if (!CameraOffset)
 	{
-		glh_set_current_modelview(saved_view);
-		glh_set_current_projection(saved_proj);
+		set_current_modelview(saved_view);
+		set_current_projection(saved_proj);
 	}
 	else
 	{
-		glh_set_current_modelview(view[1]);
-		glh_set_current_projection(proj[1]);
+		set_current_modelview(view[1]);
+		set_current_projection(proj[1]);
 		gGL.loadMatrix(view[1].m);
 		gGL.matrixMode(LLRender::MM_PROJECTION);
 		gGL.loadMatrix(proj[1].m);
@@ -11496,7 +11017,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 		F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG;
 		F32 aspect = tdim.mV[0]/tdim.mV[1];
 		glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f);
-		glh_set_current_projection(persp);
+		set_current_projection(persp);
 		gGL.loadMatrix(persp.m);
 
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
@@ -11507,7 +11028,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
 		mat = glh::matrix4f((GLfloat*) OGL_TO_CFR_ROTATION) * mat;
 
 		gGL.loadMatrix(mat.m);
-		glh_set_current_modelview(mat);
+		set_current_modelview(mat);
 
 		glClearColor(0.0f,0.0f,0.0f,0.0f);
 		gGL.setColorMask(true, true);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 29fe1cbd33f50ffdfb76da0fe2b638a9da435bc3..68ce3fe88dea8dd719ecc65df0e930cf4898a75a 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -61,14 +61,7 @@ bool compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn
 bool LLRayAABB(const LLVector3 &center, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0);
 bool setup_hud_matrices(); // use whole screen to render hud
 bool setup_hud_matrices(const LLRect& screen_region); // specify portion of screen (in pixels) to render hud attachments from (for picking)
-glh::matrix4f glh_copy_matrix(F32* src);
-glh::matrix4f glh_get_current_modelview();
-void glh_set_current_modelview(const glh::matrix4f& mat);
-glh::matrix4f glh_get_current_projection();
-void glh_set_current_projection(glh::matrix4f& mat);
-glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);
-glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
-glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
+
 
 extern LLTrace::BlockTimerStatHandle FTM_RENDER_GEOMETRY;
 extern LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS;
@@ -91,6 +84,11 @@ extern LLTrace::BlockTimerStatHandle FTM_STATESORT;
 extern LLTrace::BlockTimerStatHandle FTM_PIPELINE;
 extern LLTrace::BlockTimerStatHandle FTM_CLIENT_COPY;
 
+extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_HUD;
+extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_3D;
+extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_2D;
+extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_DEBUG_TEXT;
+extern LLTrace::BlockTimerStatHandle FTM_RENDER_UI_SCENE_MON;
 
 class LLPipeline
 {
@@ -102,10 +100,17 @@ class LLPipeline
 	void restoreGL();
 	void resetVertexBuffers();
 	void doResetVertexBuffers(bool forced = false);
+    void requestResizeScreenTexture(); // set flag only, no work, safer for callbacks...
+    void requestResizeShadowTexture(); // set flag only, no work, safer for callbacks...
+
 	void resizeScreenTexture();
+    void resizeShadowTexture();
+
 	void releaseGLBuffers();
 	void releaseLUTBuffers();
 	void releaseScreenBuffers();
+    void releaseShadowBuffers();
+
 	void createGLBuffers();
 	void createLUTBuffers();
 
@@ -127,6 +132,7 @@ class LLPipeline
 	//attempt to allocate screen buffers at resX, resY
 	//returns true if allocation successful, false otherwise
 	bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples);
+    bool allocateShadowBuffer(U32 resX, U32 resY);
 
 	void allocatePhysicsBuffer();
 	
@@ -213,6 +219,8 @@ class LLPipeline
 	U32         addObject(LLViewerObject *obj);
 
 	void		enableShadows(const bool enable_shadows);
+    void        releaseShadowTargets();
+    void        releaseShadowTarget(U32 index);
 
 // 	void		setLocalLighting(const bool local_lighting);
 // 	bool		isLocalLightingEnabled() const;
@@ -261,6 +269,7 @@ class LLPipeline
 
 	void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
 	void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
+    void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
 
 	void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture);
 
@@ -278,15 +287,17 @@ class LLPipeline
 	void renderGeomDeferred(LLCamera& camera);
 	void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true);
 	void renderGeomShadow(LLCamera& camera);
-	void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, U32 noise_map = 0xFFFFFFFF);
+	void bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_target = nullptr);
 	void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
 
 	void unbindDeferredShader(LLGLSLShader& shader);
-	void renderDeferredLighting();
-	void renderDeferredLightingToRT(LLRenderTarget* target);
-	
+	void renderDeferredLighting(LLRenderTarget* light_target);
+	void postDeferredGammaCorrect(LLRenderTarget* screen_target);
+
 	void generateWaterReflection(LLCamera& camera);
 	void generateSunShadow(LLCamera& camera);
+    LLRenderTarget* getShadowTarget(U32 i);
+
 	void generateHighlight(LLCamera& camera);
 	void renderHighlight(const LLViewerObject* obj, F32 fade);
 	void setHighlightObject(LLDrawable* obj) { mHighlightObject = obj; }
@@ -313,7 +324,7 @@ class LLPipeline
 	void enableLightsAvatar();
 	void enableLightsPreview();
 	void enableLightsAvatarEdit(const LLColor4& color);
-	void enableLightsFullbright(const LLColor4& color);
+	void enableLightsFullbright();
 	void disableLights();
 
 	void shiftObjects(const LLVector3 &offset);
@@ -576,6 +587,7 @@ class LLPipeline
 	static bool				sDynamicLOD;
 	static bool				sPickAvatar;
 	static bool				sReflectionRender;
+    static bool				sDistortionRender;
 	static bool				sImpostorRender;
 	static bool				sImpostorRenderAlphaDepthPass;
 	static bool				sUnderWaterRender;
@@ -589,6 +601,7 @@ class LLPipeline
 	static S32				sVisibleLightCount;
 	static F32				sMinRenderSize;
 	static bool				sRenderingHUDs;
+    static F32              sDistortionWaterClipPlaneMargin;
 
 	static LLTrace::EventStatHandle<S64> sStatBatchSize;
 
@@ -607,6 +620,10 @@ class LLPipeline
 	LLRenderTarget			mHighlight;
 	LLRenderTarget			mPhysicsDisplay;
 
+    LLCullResult            mSky;
+    LLCullResult            mReflectedObjects;
+    LLCullResult            mRefractedObjects;
+
 	//utility buffer for rendering post effects, gets abused by renderDeferredLighting
 	LLPointer<LLVertexBuffer> mDeferredVB;
 
@@ -625,22 +642,14 @@ class LLPipeline
 	glh::matrix4f			mSunShadowMatrix[6];
 	glh::matrix4f			mShadowModelview[6];
 	glh::matrix4f			mShadowProjection[6];
-	glh::matrix4f			mGIMatrix;
-	glh::matrix4f			mGIMatrixProj;
-	glh::matrix4f			mGIModelview;
-	glh::matrix4f			mGIProjection;
-	glh::matrix4f			mGINormalMatrix;
-	glh::matrix4f			mGIInvProj;
-	LLVector2				mGIRange;
-	F32						mGILightRadius;
-	
-	LLPointer<LLDrawable>				mShadowSpotLight[2];
-	F32									mSpotLightFade[2];
-	LLPointer<LLDrawable>				mTargetShadowSpotLight[2];
+    glh::matrix4f           mReflectionModelView;
+
+	LLPointer<LLDrawable>	mShadowSpotLight[2];
+	F32						mSpotLightFade[2];
+	LLPointer<LLDrawable>	mTargetShadowSpotLight[2];
 
 	LLVector4				mSunClipPlanes;
 	LLVector4				mSunOrthoClipPlanes;
-
 	LLVector2				mScreenScale;
 
 	//water reflection texture
@@ -649,6 +658,8 @@ class LLPipeline
 	//water distortion texture (refraction)
 	LLRenderTarget				mWaterDis;
 
+    LLRenderTarget				mBake;
+
 	//texture for making the glow
 	LLRenderTarget				mGlow[3];
 
@@ -657,9 +668,14 @@ class LLPipeline
 	U32					mTrueNoiseMap;
 	U32					mLightFunc;
 
-	LLColor4				mSunDiffuse;
-	LLVector3				mSunDir;
-	LLVector3				mTransformedSunDir;
+	LLColor4			mSunDiffuse;
+    LLColor4			mMoonDiffuse;
+	LLVector4			mSunDir;
+    LLVector4			mMoonDir;
+    bool                mNeedsShadowTargetClear;
+
+	LLVector4			mTransformedSunDir;
+    LLVector4			mTransformedMoonDir;
 
 	bool					mInitialized;
 	bool					mVertexShadersEnabled;
@@ -864,7 +880,6 @@ class LLPipeline
 
 	//cached settings
 	static bool WindLightUseAtmosShaders;
-	static bool VertexShaderEnable;
 	static bool RenderAvatarVP;
 	static bool RenderDeferred;
 	static F32 RenderDeferredSunWash;
@@ -920,6 +935,7 @@ class LLPipeline
 	static F32 RenderShadowBias;
 	static F32 RenderSpotShadowOffset;
 	static F32 RenderSpotShadowBias;
+    static LLDrawable* RenderSpotLight;
 	static F32 RenderEdgeDepthCutoff;
 	static F32 RenderEdgeNormCutoff;
 	static LLVector3 RenderShadowGaussian;
diff --git a/indra/newview/roles_constants.h b/indra/newview/roles_constants.h
index 24792dd7318a82bdc8c3f5a35179b354c229a33f..fecf5f9d4a82dca65a2728e48161bcdc93b73d7c 100644
--- a/indra/newview/roles_constants.h
+++ b/indra/newview/roles_constants.h
@@ -52,7 +52,6 @@ enum LLRoleChangeType
 //
 
 // KNOWN HOLES: use these for any single bit powers you need
-// bit 0x1 << 46
 // bit 0x1 << 52 and above
 
 // These powers were removed to make group roles simpler
@@ -103,6 +102,7 @@ const U64 GP_LAND_ALLOW_CREATE			= 0x1LL << 25;	// Bypass Create/Edit Objects Re
 const U64 GP_LAND_ALLOW_LANDMARK		= 0x1LL << 26;	// Bypass Landmark Restriction
 const U64 GP_LAND_ALLOW_SET_HOME		= 0x1LL << 28;	// Bypass Set Home Point Restriction
 const U64 GP_LAND_ALLOW_HOLD_EVENT		= 0x1LL << 41;	// Allowed to hold events on group-owned land
+const U64 GP_LAND_ALLOW_ENVIRONMENT     = 0x1LL << 46;  // Allowed to change the environment
 
 // Parcel Access
 const U64 GP_LAND_MANAGE_ALLOWED		= 0x1LL << 29;	// Manage Allowed List
@@ -164,6 +164,7 @@ const U64 GP_DEFAULT_OFFICER = GP_DEFAULT_MEMBER // Superset of GP_DEFAULT_MEMBE
 								| GP_LAND_ALLOW_EDIT_LAND
 								| GP_LAND_ALLOW_FLY
 								| GP_LAND_ALLOW_CREATE
+                                | GP_LAND_ALLOW_ENVIRONMENT
 								| GP_LAND_ALLOW_LANDMARK
 								| GP_LAND_CHANGE_IDENTITY
 								| GP_LAND_CHANGE_MEDIA
diff --git a/indra/newview/skins/default/textures/icons/Inv_Settings.png b/indra/newview/skins/default/textures/icons/Inv_Settings.png
new file mode 100644
index 0000000000000000000000000000000000000000..c43ba349c486e32db0ff2ec222c665a72b0d0674
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_Settings.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_SettingsDay.png b/indra/newview/skins/default/textures/icons/Inv_SettingsDay.png
new file mode 100644
index 0000000000000000000000000000000000000000..258ade13278e482c86267c7d60e48547a50fe5f1
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_SettingsDay.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_SettingsSky.png b/indra/newview/skins/default/textures/icons/Inv_SettingsSky.png
new file mode 100644
index 0000000000000000000000000000000000000000..77858b23c312ab5aae88888672a34d967ffbb62c
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_SettingsSky.png differ
diff --git a/indra/newview/skins/default/textures/icons/Inv_SettingsWater.png b/indra/newview/skins/default/textures/icons/Inv_SettingsWater.png
new file mode 100644
index 0000000000000000000000000000000000000000..46fb58c3f24add810048393a5abb95eed712ee15
Binary files /dev/null and b/indra/newview/skins/default/textures/icons/Inv_SettingsWater.png differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 5c38b838ccc23ec85e43635acc9e7cbf4ea6dea0..b041e6197cdc9e78b23200262e0adbd6b231b833 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -145,6 +145,7 @@ with the same filename but different name
   <texture name="Command_MiniCart_Icon"     file_name="toolbar_icons/mini_cart.png"    preload="true" />
   <texture name="Command_MiniMap_Icon"      file_name="toolbar_icons/mini_map.png"     preload="true" />
   <texture name="Command_Move_Icon"         file_name="toolbar_icons/move.png"         preload="true" />
+  <texture name="Command_Environments_Icon" file_name="toolbar_icons/environments.png" preload="true" />
   <texture name="Command_People_Icon"       file_name="toolbar_icons/people.png"       preload="true" />
   <texture name="Command_Picks_Icon"        file_name="toolbar_icons/picks.png"        preload="true" />
   <texture name="Command_Places_Icon"       file_name="toolbar_icons/places.png"       preload="true" />
@@ -323,6 +324,11 @@ with the same filename but different name
   <texture name="Inv_Underpants" file_name="icons/Inv_Underpants.png" preload="false" />
   <texture name="Inv_Undershirt" file_name="icons/Inv_Undershirt.png" preload="false" />
   <texture name="Inv_Link" file_name="icons/Inv_Link.png" preload="false" />
+    <texture name="Inv_Settings" file_name="icons/Inv_Settings.png" preload="false" />
+  <texture name="Inv_SettingsSky" file_name="icons/Inv_SettingsSky.png" preload="false" />
+  <texture name="Inv_SettingsWater" file_name="icons/Inv_SettingsWater.png" preload="false" />
+  <texture name="Inv_SettingsDay" file_name="icons/Inv_SettingsDay.png" preload="false" />
+
   <texture name="Inv_Invalid" file_name="icons/Inv_Invalid.png" preload="false" />
   <texture name="Inv_Unknown" file_name="icons/Inv_UnknownObject.png" preload="false" />
   <texture name="Inv_VersionFolderClosed" file_name="icons/Inv_VersionFolderClosed.png" preload="false" />
@@ -592,7 +598,7 @@ with the same filename but different name
   <texture name="Snapshot_Email" file_name="snapshot_email.png" preload="false" />
   <texture name="Snapshot_Inventory" file_name="toolbar_icons/inventory.png" preload="false" />
   <texture name="Snapshot_Profile" file_name="toolbar_icons/profile.png" preload="false" />
-    <texture name="startup_logo"  file_name="windows/startup_logo.png" preload="true" />
+  <texture name="startup_logo"  file_name="windows/startup_logo.png" preload="true" />
 
   <texture name="login_sl_logo"  file_name="windows/login_sl_logo.png" preload="true" />
   <texture name="login_sl_logo_small"  file_name="windows/login_sl_logo_small.png" preload="true" />
@@ -682,6 +688,20 @@ with the same filename but different name
   
   <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120"  scale_type="scale_outer"/>
 
+    <texture name="VirtualTrackball_Moon_Back" file_name="widgets/track_control_moon_back.png" />
+  <texture name="VirtualTrackball_Moon_Front" file_name="widgets/track_control_moon_front.png" />
+  <texture name="VirtualTrackball_Rotate_Bottom" file_name="widgets/track_control_rotate_bottom.png" />
+  <texture name="VirtualTrackball_Rotate_Left" file_name="widgets/track_control_rotate_left_side.png" />
+  <texture name="VirtualTrackball_Rotate_Right" file_name="widgets/track_control_rotate_right_side.png" />
+  <texture name="VirtualTrackball_Rotate_Top" file_name="widgets/track_control_rotate_top.png" />
+  <texture name="VirtualTrackball_Rotate_Bottom_Active" file_name="widgets/track_control_rotate_bottom_active.png" />
+  <texture name="VirtualTrackball_Rotate_Left_Active" file_name="widgets/track_control_rotate_left_side_active.png" />
+  <texture name="VirtualTrackball_Rotate_Right_Active" file_name="widgets/track_control_rotate_right_side_active.png" />
+  <texture name="VirtualTrackball_Rotate_Top_Active" file_name="widgets/track_control_rotate_top_active.png" />
+  <texture name="VirtualTrackball_Sphere" file_name="widgets/track_control_sphere.png" />
+  <texture name="VirtualTrackball_Sun_Back" file_name="widgets/track_control_sun_back.png" />
+  <texture name="VirtualTrackball_Sun_Front" file_name="widgets/track_control_sun_front.png" />
+    
     <texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
            scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
 
diff --git a/indra/newview/skins/default/textures/toolbar_icons/environments.png b/indra/newview/skins/default/textures/toolbar_icons/environments.png
new file mode 100644
index 0000000000000000000000000000000000000000..620db9f7930e8f8da888e8e48c9c9f81778f1e87
Binary files /dev/null and b/indra/newview/skins/default/textures/toolbar_icons/environments.png differ
diff --git a/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png
index b62723201284662c61736fbf853c3d83a319c818..8888e134d17dfffcbc4b2cf48cb0b4a247842b79 100644
Binary files a/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png and b/indra/newview/skins/default/textures/widgets/SliderThumb_Disabled.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_back.png b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..30f538d35b96104bb29cdaa3802194752166c84c
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_moon_back.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_moon_front.png b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..d3882c5e4ce240877adc47ffa10ac7d89b3406f9
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_moon_front.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..232c812aae5d80bb3d1e39fab9631a18751d9e32
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom_active.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom_active.png
new file mode 100644
index 0000000000000000000000000000000000000000..911618b08e609b189315de99ad1771091e120eb8
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_bottom_active.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png
new file mode 100644
index 0000000000000000000000000000000000000000..bcc78fc5e437979f166aae5d97cc320f09b26166
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side_active.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side_active.png
new file mode 100644
index 0000000000000000000000000000000000000000..2fe04b93f1f04879f5a27175b7316c8f13260804
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_left_side_active.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png
new file mode 100644
index 0000000000000000000000000000000000000000..d0827abf281db99f8cdd3646ee1f2f9fe2a6efb9
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side_active.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side_active.png
new file mode 100644
index 0000000000000000000000000000000000000000..824051562fa7bacc87de245c2cd244ed88d1d31c
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_right_side_active.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png
new file mode 100644
index 0000000000000000000000000000000000000000..13a5e9c2e8b8656619fcb7410dc4d36552789552
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_top.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_rotate_top_active.png b/indra/newview/skins/default/textures/widgets/track_control_rotate_top_active.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a7493703bf0406316f1c0580405a0d62aa60ef1
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_rotate_top_active.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sphere.png b/indra/newview/skins/default/textures/widgets/track_control_sphere.png
new file mode 100644
index 0000000000000000000000000000000000000000..a13b7725ea1cdf162e77aedf1c9089e871cedca9
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sphere.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sun_back.png b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..23c89068f88ad6821989c343021b7afb6d5eb82e
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sun_back.png differ
diff --git a/indra/newview/skins/default/textures/widgets/track_control_sun_front.png b/indra/newview/skins/default/textures/widgets/track_control_sun_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..6dfdc0442391ca1f220af987d594046ea3db6765
Binary files /dev/null and b/indra/newview/skins/default/textures/widgets/track_control_sun_front.png differ
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
index e494b2b755ac2e427bf3a3bd4ba22097ebca44c1..c7770eb81bca17235f7b1791d63bf079814ea726 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_graphics1.xml
@@ -29,7 +29,6 @@
 		<check_box initial_value="true" label="Gennemsigtig vand" name="TransparentWater"/>
 		<check_box initial_value="true" label="Glatte flader og skin" name="BumpShiny"/>
 		<check_box initial_value="true" label="Lokale lys" name="LocalLights"/>
-		<check_box initial_value="true" label="Basale flader" name="BasicShaders" tool_tip="Ved at slå dette valg fra, kan det forhindres at visse grafikkort drivere crasher."/>
 		<check_box initial_value="true" label="Atmosfæriske flader" name="WindLightUseAtmosShaders"/>
 		<check_box initial_value="true" label="Lys og skygger" name="UseLightShaders"/>
 		<check_box initial_value="true" label="&quot;Ambient Occlusion&quot;" name="UseSSAO"/>
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index eee3dc2c77792f04b43cf10feb96fbcc3373f503..ec6ba4800d50b47c5825ba76c913dbcac90eb151 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -560,6 +560,9 @@ Prøv venligst om lidt igen.
 	<string name="mesh">
 		mesh
 	</string>
+    <string name="settings">
+        indstillinger
+    </string>
 	<string name="AvatarEditingAppearance">
 		(Redigering Udseende)
 	</string>
diff --git a/indra/newview/skins/default/xui/de/floater_adjust_environment.xml b/indra/newview/skins/default/xui/de/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..776a866077be534a8177503f24dccd26433fa62b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Persönliche Beleuchtung">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Zurücksetzen" name="btn_reset" tool_tip="Schließen und auf gemeinsame Umgebung zurücksetzen"/>
+					<text name="cloud_map_label">
+						Wolkenbild:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Sonne:
+					</text>
+					<check_box label="Beacon anzeigen" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Beacon anzeigen" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_beacons.xml b/indra/newview/skins/default/xui/de/floater_beacons.xml
index 1a052bd8149926a77f5001b58af0ff258097d2d7..c44cd407de36ab6fc531e56a42b041e8b967653c 100644
--- a/indra/newview/skins/default/xui/de/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/de/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Soundquellen" name="sounds"/>
 		<check_box label="Partikelquellen" name="particles"/>
 		<check_box label="Medienquellen" name="moapbeacon"/>
+		<check_box label="Sonne" name="sun"/>
+		<check_box label="Mond" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
index 9454933264ea0fb99f982fc7d9bd09f4ed034e37..7a3fa41a24a604784fd713b4104833d4ed11d60f 100644
--- a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="Sounds"/>
 	<check_box label="Texturen" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="Texturen"/>
+	<icon name="icon_setting" tool_tip="Umgebungseinstellungen"/>
 	<button label="√ Alle" label_selected="Alle" name="check_all"/>
 	<button label="Löschen" label_selected="Keine" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/de/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/de/floater_delete_env_preset.xml
deleted file mode 100644
index ae7d5ef77d917e87a4cb53be7264312a7a6aa8ff..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/de/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="UMGEB.-VOREINST. LÖSCHEN">
-	<string name="title_water">
-		Wasser-Voreinstellung löschen
-	</string>
-	<string name="title_sky">
-		Himmel-Voreinstellung löschen
-	</string>
-	<string name="title_day_cycle">
-		Tageszyklus löschen
-	</string>
-	<string name="label_water">
-		Voreinstellung:
-	</string>
-	<string name="label_sky">
-		Voreinstellung:
-	</string>
-	<string name="label_day_cycle">
-		Tageszyklus:
-	</string>
-	<string name="msg_confirm_deletion">
-		Möchten Sie die ausgewählte Voreinstellung wirklich löschen?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Eine Voreinstellung, auf die sich ein Tageszyklus bezieht, kann nicht gelöscht werden.
-	</string>
-	<string name="combo_label">
-		-Voreinstellung auswählen-
-	</string>
-	<text name="label">
-		Voreinstellung:
-	</text>
-	<button label="Löschen" name="delete"/>
-	<button label="Abbrechen" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/de/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c21eec18930adc359261e9b818d6282d9e5b0872
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Tageszyklus bearbeiten">
+	<string name="title_new">
+		Neuen Tageszyklus erstellen
+	</string>
+	<string name="title_edit">
+		Tageszyklus bearbeiten
+	</string>
+	<string name="hint_new">
+		Geben Sie einen Namen für Ihren Tageszyklus ein, passen Sie die Steuerungen an, um den Tageszyklus zu erstellen, und klicken Sie auf &quot;Speichern&quot;.
+	</string>
+	<string name="hint_edit">
+		Um Ihren Tageszyklus zu bearbeiten, passen Sie die unten angezeigten Steuerungen an und klicken Sie auf „Speichern“.
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Himmel [ALT]
+	</string>
+	<string name="sky_label">
+		Himmel
+	</string>
+	<string name="water_label">
+		Wasser
+	</string>
+	<string name="commit_parcel">
+		Auf Parzelle anwenden
+	</string>
+	<string name="commit_region">
+		Auf Region anwenden
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Name des Tageszyklus:
+			</text>
+			<button label="Importieren" name="btn_import" tool_tip="Alte Einstellungen von Datenträger importieren."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Himmel 4" name="sky4_track"/>
+						<button label="Himmel 3" name="sky3_track"/>
+						<button label="Himmel 2" name="sky2_track"/>
+						<button label="Bodenhöhe" name="sky1_track"/>
+						<button label="Wasser" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Pfad klonen von" name="copy_track"/>
+								<button label="Pfad laden von" name="load_track"/>
+								<button label="Pfad löschen" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Schritt vor"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Schritt zurück"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="[FRAME] hinzufügen" name="add_frame"/>
+								<button label="[FRAME] laden" name="btn_load_frame"/>
+								<button label="[FRAME] löschen" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Wählen Sie einen Schlüssel-Frame aus der obigen Zeitlinie, um die Einstellungen zu bearbeiten.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Wasser" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmosphäre und Beleuchtung" name="atmosphere_panel"/>
+						<panel label="Wolken" name="clouds_panel"/>
+						<panel label="Sonne und Mond" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Speichern" name="save_btn"/>
+			<button label="Abbrechen" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/de/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c18e3335710b2542a86838cf67db8d1ac0a49160
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Festgelegte Umgebung">
+	<string name="edit_sky">
+		Himmel bearbeiten:
+	</string>
+	<string name="edit_water">
+		Wasser bearbeiten:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Laden" name="btn_load" tool_tip="Einstellungen aus dem Inventar laden"/>
+			<button label="Importieren" name="btn_import" tool_tip="Alte Einstellungen von Datenträger importieren."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Speichern" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Abbrechen" name="btn_cancel" tool_tip="Zur zuletzt gespeicherten Version zurückkehren"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
index cdacabec908fb19c3688e4a865520865cff49d53..b361b88aa89626dd8f3ab02b0d7e5e9fef86df7c 100644
--- a/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Sounds" name="check_sound"/>
 	<check_box label="Texturen" name="check_texture"/>
 	<check_box label="Fotos" name="check_snapshot"/>
+	<check_box label="Einstellungen" name="check_settings"/>
 	<button label="Alle" label_selected="Alle" name="All"/>
 	<button label="Keine" label_selected="Keine" name="None"/>
 	<check_box label="Ordner immer anzeigen" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/de/floater_my_environments.xml b/indra/newview/skins/default/xui/de/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ff5556304aa40bb02e011b35035a6f504d7b2ace
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Orte" name="my_environments" title="MEINE UMGEBUNGEN">
+	<layout_stack>
+		<layout_panel label="Filter" name="filter_panel">
+			<check_box label="Tage" name="chk_days"/>
+			<check_box label="Himmel" name="chk_skies"/>
+			<check_box label="Wasser" name="chk_water"/>
+			<filter_editor label="Umgebungen filtern" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Umgebungen" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Alle Ordner anzeigen" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Weitere Optionen"/>
+				<menu_button name="btn_newsettings" tool_tip="Neue Einstellung erstellen"/>
+				<button name="btn_del" tool_tip="Ausgewähltes Objekt löschen"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_perms_default.xml b/indra/newview/skins/default/xui/de/floater_perms_default.xml
index 6274739f702c8b538a43ca236cdfaa829eaa8276..a9b845611a207667acc540916b4048edf67c7ce7 100644
--- a/indra/newview/skins/default/xui/de/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/de/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Standardberechtigungen für die Erstellung von Kleidungsstücken und Körperteilen festlegen">
 			Tragbare Objekte
 		</text>
+		<text name="label_13" tool_tip="Standardberechtigungen für die Erstellung von Umgebungseinstellungen festlegen">
+			Einstellungen
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Abbrechen" label_selected="Abbrechen" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/de/floater_pick_track.xml b/indra/newview/skins/default/xui/de/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d5a565a2b0aaf85f0f6a5a75f1990f19d2737ad9
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="AUSWÄHLEN: PFAD">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Ursprungshimmel auswählen:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Himmel4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Himmel3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Himmel2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Boden" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Abbrechen" label_selected="Abbrechen" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml
index 41e8dc5ef486bf1c6ccf4ddc70e0841a402e4e68..cd514f5afdce948baed714a7be014a7a95173ed3 100644
--- a/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/de/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Transparentes Wasser" name="TransparentWater"/>
 	<check_box initial_value="true" label="Bumpmapping und Glanz" name="BumpShiny"/>
 	<check_box initial_value="true" label="Lokale Lichtquellen" name="LocalLights"/>
-	<check_box initial_value="true" label="Einfache Shader" name="BasicShaders" tool_tip="Deaktivieren Sie diese Option, wenn der Grafikkartentreiber Abstürze verursacht"/>
 	<slider label="Terraindetails:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Niedrig
diff --git a/indra/newview/skins/default/xui/de/floater_preview_texture.xml b/indra/newview/skins/default/xui/de/floater_preview_texture.xml
index 526c0813bd55afa89e6ba3016d33139d0c40e497..eacd11c3e6b6bc508b345f15f6718e37ab0336bc 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_texture.xml
@@ -13,7 +13,7 @@
 		[WIDTH]px x [HEIGHT]px
 	</text>
 	<text name="aspect_ratio">
-		Seitenverhältnis anzeigen
+		Vorschau Seitenverhältnis
 	</text>
 	<combo_box name="combo_aspect_ratio" tool_tip="Mit einem vordefinierten Seitenverhältnis anzeigen">
 		<combo_item name="Unconstrained">
diff --git a/indra/newview/skins/default/xui/de/floater_settings_picker.xml b/indra/newview/skins/default/xui/de/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1fe417bdee49b7711991f60ddf799919d986a51b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="AUSWÄHLEN: EINSTELLUNGEN">
+	<floater.string name="pick title">
+		Auswahl:
+	</floater.string>
+	<floater.string name="pick_track">
+		PFAD AUSWÄHLEN
+	</floater.string>
+	<floater.string name="pick_settings">
+		EINSTELLUNGEN AUSWÄHLEN
+	</floater.string>
+	<floater.string name="track_water">
+		Wasser
+	</floater.string>
+	<floater.string name="track_ground">
+		Boden
+	</floater.string>
+	<floater.string name="track_sky">
+		Himmel[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Texturen filtern" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Abbrechen" label_selected="Abbrechen" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
index b794d879f0ff7f0f9c284386222ed269d5401f9a..b818a7d4800f34d679028da3fc79cfb4ac4207d9 100644
--- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Inventar" name="inventory" value="0"/>
 		<radio_item label="Lokal" name="local" value="1"/>
+		<radio_item label="Backen" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Größe: [DIMENSIONS]
@@ -20,7 +21,6 @@
 	<button label="Leer" label_selected="Leer" name="Blank"/>
 	<button label="Keine" label_selected="Keine" name="None"/>
 	<button label="" label_selected="" name="Pipette"/>
-	<check_box initial_value="true" label="Jetzt übernehmen" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Vorschau deaktiviert"/>
 	<filter_editor label="Texturen filtern" name="inventory search editor"/>
 	<check_box initial_value="false" label="Ordner anzeigen" name="show_folders_check"/>
@@ -31,6 +31,22 @@
 		<column label="Name" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Back-Textur auswählen">
+		<combo_box.item label="Keine" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Basis-Mesh-Region verbergen" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="Abbrechen" label_selected="Abbrechen" name="Cancel"/>
+	<check_box initial_value="true" label="Jetzt übernehmen" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory.xml b/indra/newview/skins/default/xui/de/menu_inventory.xml
index e02d464a3d3ad3abbfe64caef1494ea9db9de9cd..84cded77ce7f3ab4790552cdc674defc3d3ce121 100644
--- a/indra/newview/skins/default/xui/de/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/de/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Aktivieren" name="Marketplace Activate"/>
 	<menu_item_call label="Deaktivieren" name="Marketplace Deactivate"/>
 	<menu_item_call label="Teilen" name="Share"/>
-	<menu_item_call label="Kaufen" name="Task Buy"/>
 	<menu_item_call label="Öffnen" name="Task Open"/>
 	<menu_item_call label="Abspielen" name="Task Play"/>
 	<menu_item_call label="Eigenschaften" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Neue Unterhose" name="New Underpants"/>
 		<menu_item_call label="Neue Alpha-Maske" name="New Alpha Mask"/>
 		<menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+		<menu_item_call label="Neues Universal" name="New Universal"/>
 		<menu_item_call label="Neue Physik" name="New Physics"/>
 	</menu>
 	<menu label="Neue Körperteile" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Neues Haar" name="New Hair"/>
 		<menu_item_call label="Neue Augen" name="New Eyes"/>
 	</menu>
+	<menu label="Neue Einstellungen" name="New Settings">
+		<menu_item_call label="Neuer Himmel" name="New Sky"/>
+		<menu_item_call label="Neues Wasser" name="New Water"/>
+		<menu_item_call label="Neuer Tageszyklus" name="New Day Cycle"/>
+	</menu>
 	<menu label="Als Standard verwenden für" name="upload_def">
 		<menu_item_call label="Hochgeladene Bilder" name="Image uploads"/>
 		<menu_item_call label="Hochgeladene Sounds" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Bearbeiten" name="Wearable Edit"/>
 	<menu_item_call label="Hinzufügen" name="Wearable Add"/>
 	<menu_item_call label="Ausziehen" name="Take Off"/>
+	<menu_item_call label="Nur auf mich anwenden" name="Settings Apply Local"/>
+	<menu_item_call label="Auf Parzelle anwenden" name="Settings Apply Parcel"/>
 	<menu_item_call label="In Marktplatz-Auflistungen kopieren" name="Marketplace Copy"/>
 	<menu_item_call label="In Marktplatz-Auflistungen verschieben" name="Marketplace Move"/>
 	<menu_item_call label="--keine Optionen--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/de/menu_inventory_add.xml b/indra/newview/skins/default/xui/de/menu_inventory_add.xml
index af70c08ba17479399b54112ccdbc04bf8ec5ca28..251b219a126c0b3fa0717b87bc8a4d9484f12d31 100644
--- a/indra/newview/skins/default/xui/de/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/de/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Sound ([COST] L$)..." name="Upload Sound"/>
 		<menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
 		<menu_item_call label="Modell..." name="Upload Model"/>
-		<menu_item_call label="Modellassistent..." name="Upload Model Wizard"/>
 		<menu_item_call label="Mehrfach-Upload ([COST] L$ pro Datei)..." name="Bulk Upload"/>
-		<menu_item_call label="Hochlade-Berechtigungen (Standard) festlegen" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Neuer Ordner" name="New Folder"/>
 	<menu_item_call label="Neues Skript" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Neue Unterhose" name="New Underpants"/>
 		<menu_item_call label="Neues Alpha" name="New Alpha"/>
 		<menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+		<menu_item_call label="Neues Universal" name="New Universal"/>
 		<menu_item_call label="Neue Physik" name="New Physics"/>
 	</menu>
 	<menu label="Neue Körperteile" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Neues Haar" name="New Hair"/>
 		<menu_item_call label="Neue Augen" name="New Eyes"/>
 	</menu>
+	<menu label="Neue Einstellungen" name="New Settings">
+		<menu_item_call label="Neuer Himmel" name="New Sky"/>
+		<menu_item_call label="Neues Wasser" name="New Water"/>
+		<menu_item_call label="Neuer Tageszyklus" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/de/menu_outfit_gear.xml b/indra/newview/skins/default/xui/de/menu_outfit_gear.xml
index 211cc5c54e232ccb1a588f8c49732c372fcbf614..817ec28cff4b456616d32c4f26e31bdd51d81201 100644
--- a/indra/newview/skins/default/xui/de/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/de/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Neues Alpha" name="New Alpha"/>
 		<menu_item_call label="Neue Physik" name="New Physics"/>
 		<menu_item_call label="Neue Tätowierung" name="New Tattoo"/>
+		<menu_item_call label="Neues Universal" name="New Universal"/>
 	</menu>
 	<menu label="Neue Körperteile" name="New Body Parts">
 		<menu_item_call label="Neue Form" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/de/menu_save_settings.xml b/indra/newview/skins/default/xui/de/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..458c3fdc149b7fc22f431b8521943724ff5e6465
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Speichern" name="save_settings"/>
+	<menu_item_check label="Speichern unter" name="save_as_new_settings"/>
+	<menu_item_check label="Festlegen" name="commit_changes"/>
+	<menu_item_check label="Nur auf mich anwenden" name="apply_local"/>
+	<menu_item_check label="Auf Parzelle anwenden" name="apply_parcel"/>
+	<menu_item_check label="Auf Region anwenden" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_settings_add.xml b/indra/newview/skins/default/xui/de/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebf6c2b31470423f8c94993fc36c60fdb709aad5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Neuer Himmel" name="New Sky"/>
+	<menu_item_call label="Neues Wasser" name="New Water"/>
+	<menu_item_call label="Neuer Tageszyklus" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_settings_gear.xml b/indra/newview/skins/default/xui/de/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4be4675899f234908e7cdbff16c6bc97bec263ae
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Bearbeiten" name="edit_settings"/>
+	<menu_item_call label="Nur auf mich anwenden" name="Settings Apply Local"/>
+	<menu_item_call label="Auf Parzelle anwenden" name="Settings Apply Parcel"/>
+	<menu_item_call label="Auf Region anwenden" name="Settings Apply Region"/>
+	<menu_item_call label="Kopieren" name="copy_settings"/>
+	<menu_item_call label="Einfügen" name="paste_settings"/>
+	<menu_item_call label="UUID kopieren" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index 5917a0b529e3de12cb634bc301d9503fba01370f..6ea4ae9ab3d95fefb0d0052c22535c70fee1c969 100644
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="Parzelleneigenschaften" name="Parcel Properties"/>
 			<menu_item_check label="Menü „Erweitert“" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Sonne" name="Sun">
+		<menu label="Umgebung" name="Environment">
 			<menu_item_check label="Sonnenaufgang" name="Sunrise"/>
 			<menu_item_check label="Mittag" name="Noon"/>
 			<menu_item_check label="Sonnenuntergang" name="Sunset"/>
 			<menu_item_check label="Mitternacht" name="Midnight"/>
-			<menu_item_check label="Regionseinstellungen verwenden" name="Use Region Settings"/>
-		</menu>
-		<menu label="Umwelt-Editor" name="Environment Editor">
-			<menu_item_call label="Umwelt-Einstellungen..." name="Environment Settings"/>
-			<menu label="Wasser-Voreinstellungen" name="Water Presets">
-				<menu_item_call label="Neue Voreinstellung..." name="new_water_preset"/>
-				<menu_item_call label="Voreinstellung bearbeiten..." name="edit_water_preset"/>
-				<menu_item_call label="Voreinstellung löschen..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Himmel-Voreinstellungen" name="Sky Presets">
-				<menu_item_call label="Neue Voreinstellung..." name="new_sky_preset"/>
-				<menu_item_call label="Voreinstellung bearbeiten..." name="edit_sky_preset"/>
-				<menu_item_call label="Voreinstellung löschen..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Tag-Voreinstellungen" name="Day Presets">
-				<menu_item_call label="Neue Voreinstellung..." name="new_day_preset"/>
-				<menu_item_call label="Voreinstellung bearbeiten..." name="edit_day_preset"/>
-				<menu_item_call label="Voreinstellung löschen..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Gemeinsame Umgebung verwenden" name="Use Shared Environment"/>
+			<menu_item_call label="Meine Umgebungen..." name="my_environs"/>
+			<menu_item_call label="Persönliche Beleuchtung..." name="adjustment_tool"/>
+			<menu_item_check label="Wolken pausieren" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Bauen" name="BuildTools">
@@ -346,6 +331,9 @@
 			<menu_item_check label="Automatische Alpha-Masken (nicht aufgeschoben)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Animationstexturen" name="Animation Textures"/>
 			<menu_item_check label="Texturen deaktivieren" name="Disable Textures"/>
+			<menu_item_check label="Umgebung deaktivieren" name="Disable Ambient"/>
+			<menu_item_check label="Sonnenlicht deaktivieren" name="Disable Sunlight"/>
+			<menu_item_check label="Lokale Lichtquellen deaktivieren" name="Disable Local Lights"/>
 			<menu_item_check label="Voll-Res-Texturen" name="Rull Res Textures"/>
 			<menu_item_check label="Angehängte Lichter rendern" name="Render Attached Lights"/>
 			<menu_item_check label="Angehängte Partikel rendern" name="Render Attached Particles"/>
@@ -477,6 +465,7 @@
 			<menu_item_call label="Rock" name="Skirt"/>
 			<menu_item_call label="Alpha" name="Alpha"/>
 			<menu_item_call label="Tätowierung" name="Tattoo"/>
+			<menu_item_call label="Universal" name="Universal"/>
 			<menu_item_call label="Physik" name="Physics"/>
 			<menu_item_call label="Alle Kleider" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index feb1ae23a52e5d3b6f3eb6fa3276e07beb8daa4b..d16815c0f42b2e541435ef33ef05ae794a0b3292 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -1976,6 +1976,11 @@ Tausende Regionen werden verändert und der Spaceserver wird dadurch stark belas
 		Durch Deaktivieren dieser Option können Einstellungen der Parzellenbesitzer zum Schutz vor Belästigungen, zur Aufrechterhaltung der Privatsphäre oder zum Schutz von Minderjährigen vor nicht altersgemäßen Inhalten aufgehoben werden. Bitte sprechen Sie mit den Parzellenbesitzern, falls erforderlich.
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Durch Deaktivieren dieser Option werden jegliche benutzerdefinierten Umgebungen entfernt, die von den Parzelleneigentümern zu ihren Parzellen hinzugefügt wurden. Bitte sprechen Sie mit den Parzellenbesitzern, falls erforderlich. 
+Fortfahren?
+		<usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		Die Region, die Sie besuchen möchten, enthält Inhalte, die Ihre aktuellen Einstellungen überschreiten. Sie können Ihre Einstellungen unter „Ich“ &gt; „Einstellungen“ &gt; „Allgemein“ ändern.
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2455,7 +2460,15 @@ Von einer Webseite zu diesem Formular linken, um anderen leichten Zugang zu dies
 		Diese Tageszyklusdatei verweist auf eine fehlende Himmel-Datei: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		Die Einstellungen konnten nicht auf die Region angewendet werden.  Verlassen Sie die Region und kehren Sie zurück, um das Problem zu beheben.  Angegebener Grund: [FAIL_REASON]
+		Die Einstellungen konnten nicht auf die Region angewendet werden. Grund: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Eine lokale Textur wird im Pfad [TRACK], Frame #[FRAMENO] ([FRAME]%) im Feld [FIELD] verwendet. 
+Die Einstellungen können nicht mit lokalen Texturen gespeichert werden.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Im Feld [FIELD] wird eine lokale Textur verwendet. 
+Die Einstellungen können nicht mit lokalen Texturen gespeichert werden.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Der letzte Schlüssel in diesem Tageszyklus kann nicht gelöscht werden, da ein Tageszyklus nicht leer sein kann.  Statt den letzten verbleibenden Schlüssel zu löschen, versuchen Sie stattdessen, ihn zu modifizieren und dann einen neuen zu erstellen.
@@ -4404,4 +4417,76 @@ Wählen Sie eine kleinere Landfläche aus.
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		Die Einstellungen für [NAME] konnten nicht aus der Datenbank geladen werden.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Diese Einstellungen können nicht auf die Umgebung angewendet werden.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Diese Einstellungen können nicht auf die Umgebung angewendet werden.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Diese Region unterstützt keine Umgebungseinstellungen.
+	</notification>
+	<notification label="Outfit speichern" name="SaveSettingAs">
+		Aktuelle Umgebungseinstellungen speichern unter:
+		<form name="form">
+			<input name="message">
+				[DESC] (neu)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Abbrechen"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Alte Windlight-Einstellungen [NAME] konnten nicht aus 
+[FILE] geladen werden. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Die Umgebung für diese Parzelle kann nicht eingestellt werden. 
+Bitte eine Parzelle eingeben oder auswählen, für die Sie die Änderungsrechte besitzen.
+	</notification>
+	<notification name="SettingsUnsuported">
+		Einstellungen werden von dieser Region nicht unterstützt. 
+Bitte wechseln sie zu einer Region mit aktivierten Einstellungsmöglichkeiten und versuchen Sie es erneut.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Sie werden die Änderungen an diesem [TYPE] mit der Bezeichnung &quot;[NAME]&quot; verlieren. 
+Möchten Sie diesen Vorgang wirklich fortsetzen?
+		<usetemplate ignoretext="Sind Sie sicher, dass Sie die Änderungen verlieren möchten?" name="okcancelignore" notext="Nein" yestext="Ja"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Sie sind dabei, alle angewendeten Einstellungen zu entfernen. 
+Möchten Sie diesen Vorgang wirklich fortsetzen?
+		<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Sie sind dabei, alle angewendeten persönlichen Beleuchtungseinstellungen zu entfernen. 
+Möchten Sie diesen Vorgang wirklich fortsetzen?
+		<usetemplate name="okcancelbuttons" notext="Nein" yestext="Ja"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Sie versuchen, nicht transferierbare Einstellungen in diesen Tageszyklus zu importieren. Wenn Sie fortfahren, verlieren die von Ihnen bearbeiteten Einstellungen ebenfalls ihre Transferierbarkeit. 
+
+Diese Änderung kann nicht rückgängig gemacht werden. 
+
+Möchten Sie diesen Vorgang wirklich fortsetzen?
+		<usetemplate ignoretext="Sind Sie sicher, dass Sie die Transferierbarkeit der Einstellungen aufgeben möchten?" name="okcancelignore" notext="Nein" yestext="Ja"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Sie können Einstellungen aus der Bibliothek nicht direkt bearbeiten. 
+Bitte kopieren Sie diese in Ihr Inventar und versuchen Sie es erneut.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Bei diesen Einstellungen wurde ein Problem festgestellt. Sie können momentan nicht gespeichert oder angewendet werden.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Pfad konnte nicht in [TRACK] geladen werden.
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Der Pfad konnte nicht aus [TRACK1] in [TRACK2] geladen werden.
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml
index 075a9d752a31d9e199577eae99ebaacc9585b327..a74d16e50a7c4cbe3219e44275ead462ba2bcf64 100644
--- a/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/de/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Kopftattoo" name="Head Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
-		<texture_picker label="Obere Tattoos" name="Upper Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
-		<texture_picker label="Untere Tattoos" name="Lower Tattoo" tool_tip="Zum Auswählen eines Bildes hier klicken"/>
-		<color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Kopf-Tattoo" name="Head Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Oberes Tattoo" name="Upper Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Unteres Tattoo" name="Lower Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_universal.xml b/indra/newview/skins/default/xui/de/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ae4021b8f5f50d17175ad3240b997777c6e931f
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Kopf-Tattoo" name="Head Universal Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Oberes Tattoo" name="Upper Universal Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Unteres Tattoo" name="Lower Universal Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Rock-Tattoo" name="Skirt Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Haar-Tattoo" name="Hair Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Augen-Tattoo" name="Eyes Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Tattoo linker Arm" name="Left Arm Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Tattoo linkes Bein" name="Left Leg Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Aux1-Tattoo" name="Aux1 Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Aux2-Tattoo" name="Aux2 Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<texture_picker label="Aux3-Tattoo" name="Aux3 Tattoo" tool_tip="Klicken, um ein Bild auszuwählen"/>
+			<color_swatch label="Farbe/Ton" name="Color/Tint" tool_tip="Klicken Sie hier, um die Farbauswahl zu öffnen"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_edit_wearable.xml b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml
index 94a79a0bbd929b68fdb4935df8edd90af48e9a91..83593e553f5934f7b599d01735b9114ca43b91bf 100644
--- a/indra/newview/skins/default/xui/de/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/de/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Tätowierung bearbeiten
 	</string>
+	<string name="edit_universal_title">
+		Universal bearbeiten
+	</string>
 	<string name="edit_physics_title">
 		Physik bearbeiten
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Tätowierung:
 	</string>
+	<string name="universal_desc_text">
+		Universal:
+	</string>
 	<string name="physics_desc_text">
 		Physik:
 	</string>
diff --git a/indra/newview/skins/default/xui/de/panel_region_environment.xml b/indra/newview/skins/default/xui/de/panel_region_environment.xml
index 089a3ae5fc94e6538d4b4581b4e5b2f56fb61a60..f5e249b0832957813fd6b8b93dfc1c24fe0efba8 100644
--- a/indra/newview/skins/default/xui/de/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/de/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Umgebung" name="panel_env_info">
-	<text name="water_settings_title">
-		Wählen Sie die Wasser- und Himmel-/Tageszykluseinstellungen aus, die alle Besucher Ihrer Region sehen sollen. Mehr Infos
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Second Life-Standard verwenden" name="use_sl_default_settings"/>
-		<radio_item label="Folgende Einstellungen verwenden" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Wassereinstellung
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Voreinstellung auswählen-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Himmel/Tageszyklus
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Fester Himmel" name="my_sky_settings"/>
-			<radio_item label="Tageszyklus" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Voreinstellung auswählen-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Voreinstellung auswählen-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Anwenden" name="apply_btn"/>
-	<button label="Abbrechen" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Standardeinstellungen verwenden
+	</string>
+	<string name="str_label_use_region">
+		Regionseinstellungen verwenden
+	</string>
+	<string name="str_altitude_desription">
+		Himmel [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		Es ist keine Parzelle ausgewählt. Umgebungseinstellungen sind deaktiviert.
+	</string>
+	<string name="str_cross_region">
+		Umgebungseinstellungen sind außerhalb der Regionsgrenzen nicht verfügbar.
+	</string>
+	<string name="str_legacy">
+		Umgebungseinstellungen sind für diese Region nicht verfügbar
+	</string>
+	<string name="str_disallowed">
+		Der Grundbesitzverwalter lässt keine Änderung der Parzellenumgebungen in dieser Region zu.
+	</string>
+	<string name="str_too_small">
+		Die Parzellengröße muss mindestens 128 Quadratmeter betragen, um eine Umgebung zu unterstützen.
+	</string>
+	<string name="str_empty">
+		(leer)
+	</string>
+	<string name="str_region_env">
+		(Regionsumgebung)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Inventar verwenden" name="btn_select_inventory"/>
+							<button label="Anpassen" name="btn_edit"/>
+							<check_box label="Parzelleneigentümer können die Umgebung außer Kraft setzen" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Himmel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Unbekannt
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Ziehen Sie eine Einstellung aus dem Inventar auf dieses Zielfeld, um sie als aktuellen Himmel auszuwählen."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Himmel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Unbekannt
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Ziehen Sie eine Einstellung aus dem Inventar auf dieses Zielfeld, um sie als aktuellen Himmel auszuwählen."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Himmel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Unbekannt
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Ziehen Sie eine Einstellung aus dem Inventar auf dieses Zielfeld, um sie als aktuellen Himmel auszuwählen."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Boden
+						</text>
+						<line_editor name="edt_invname_ground">
+							Unbekannt
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Ziehen Sie eine Einstellung aus dem Inventar auf dieses Zielfeld, um sie als aktuellen Himmel auf Bodenhöhe auszuwählen."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Wasser
+						</text>
+						<line_editor name="edt_invname_water">
+							Unbekannt
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Ziehen Sie eine Einstellung aus dem Inventar auf dieses Zielfeld, um sie als aktuelles Wasser auszuwählen."/>
+					</panel>
+					<button label="Zurücksetzen" name="btn_rst_altitudes" tool_tip="Auf Standardhöhen zurücksetzen"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/de/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/de/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f14e3fe47f59b3669a3b79abb107f328656b44db
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmosphäre und Beleuchtung" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/de/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/de/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d78728eed4441428e49a65d9cdb4d286177bdf3
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Wolken" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/de/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7ee6308d83458e27578817c767039b4bf084588
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Dichte" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Rayleigh-Exponentialterm:" name="rayleigh_exponential"/>
+			<slider label="Rayleigh-Exponentialskala:" name="rayleigh_exponential_scale"/>
+			<slider label="Rayleigh-Linearterm:" name="rayleigh_linear"/>
+			<slider label="Rayleigh-Konstantenterm:" name="rayleigh_constant"/>
+			<slider label="Rayleigh-Maximalhöhe:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Mie-Exponentialterm:" name="mie_exponential"/>
+			<slider label="Mie-Exponentialskala:" name="mie_exponential_scale"/>
+			<slider label="Mie-Linearterm:" name="mie_linear"/>
+			<slider label="Mie-Konstantenterm:" name="mie_constant"/>
+			<slider label="Mie-Anisofaktor." name="mie_aniso_factor"/>
+			<slider label="Mie-Maximalhöhe:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Absorptions-Exponentialterm:" name="absorption_exponential"/>
+			<slider label="Absorptions-Exponentialskala:" name="absorption_exponential_scale"/>
+			<slider label="Absorptions-Linearterm:" name="absorption_linear"/>
+			<slider label="Absorptions-Konstantenterm:" name="absorption_constant"/>
+			<slider label="Absorptions-Maximalhöhe:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/de/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9234e22d63827e36a6efa70d1825c69338f4a41b
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sonne und Mond" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Beacon anzeigen" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Beacon anzeigen" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_settings_water.xml b/indra/newview/skins/default/xui/de/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f11f50dcceebe063b5e5e66fde9d68e3a53f2c59
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Wasser" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Fresnel-Versatz:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/panel_tools_texture.xml b/indra/newview/skins/default/xui/de/panel_tools_texture.xml
index e0505ce12869c2fc2f6350a6a935272334b73406..9557f2d6d8f66506199b7f023f0271f2f83e7deb 100644
--- a/indra/newview/skins/default/xui/de/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/de/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Textur" name="Texture">
-	<panel.string name="string repeats per meter">
-		Wiederholungen pro Meter
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Wiederholungen pro Fläche
-	</panel.string>
 	<text name="color label">
 		Farbe
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Horizontaler Versatz" name="shinyOffsetU"/>
 	<spinner label="Vertikaler Versatz" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Planare Flächen ausrichten" name="checkbox planar align" tool_tip="Texturen auf allen ausgewählten Flächen an der zuletzt ausgewählten Fläche ausrichten. Erfordert planares Texture Mapping."/>
+	<button label="Ausrichten" label_selected="Aktuelle Texturebenen ausrichten" name="button align textures" tool_tip="Aktuelle Texturebenen ausrichten"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/de/role_actions.xml b/indra/newview/skins/default/xui/de/role_actions.xml
index 26187678a05039be237f4d1671f086787c4a9e6b..5507fcc04d140ea18affe578c54ffd3d0ac4e573 100644
--- a/indra/newview/skins/default/xui/de/role_actions.xml
+++ b/indra/newview/skins/default/xui/de/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Musik- und Medieneinstellungen ändern" longdescription="Die Einstellungen für Streaming-Musik und Filme finden Sie unter „Land-Info“ &gt; „Medien“." name="land change media" value="20"/>
 		<action description="„Terrain bearbeiten“ ein/aus" longdescription="„Terrain bearbeiten“ ein/aus. *WARNUNG* „Land-Info“ &gt; „Optionen“ &gt; „Terrain bearbeiten“ ermöglicht jedem das Terraformen Ihres Grundbesitzes und das Setzen und Verschieben von Linden-Pflanzen. Überlegen Sie sich, wem Sie diese Fähigkeit verleihen. Diese Einstellung finden Sie unter „Land-Info“ &gt; „Optionen“." name="land edit" value="21"/>
 		<action description="„Land-Info“-Optionen einstellen" longdescription="„Sicher (kein Schaden)“ und „Fliegen“ ein- und ausschalten und Einwohnern folgende Aktionen erlauben: „Terrain bearbeiten“, „Bauen“, „Landmarken erstellen“ und „Skripts ausführen“ auf gruppeneigenem Land in „Land-Info“ &gt; Registerkarte „Optionen“." name="land options" value="22"/>
+		<action description="Ändern Sie die Umgebungseinstellungen und den Tageszyklus." longdescription="Ändern Sie die Umgebungseinstellungen im Reiter &quot;Landinformationen -&gt; Umgebung&quot;." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Diese Fähigkeiten ermöglichen es, Mitgliedern das Umgehen von Restriktionen auf gruppeneigenen Parzellen zu erlauben." name="Parcel Powers">
 		<action description="„Terrain bearbeiten“ zulassen" longdescription="Mitglieder in einer Rolle mit dieser Fähigkeit können auf einer gruppeneigenen Parzelle das Terrain bearbeiten, selbst wenn diese Option unter „Land-Info“ &gt; „Optionen“ deaktiviert ist." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 0fa4ec9affd304cb5318f57e3f464cbadc4538ae..7db76ec552ef103e1f69e1fbc5293b83f559a1c6 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -638,6 +638,15 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.
 	<string name="BUTTON_HELP">
 		Hilfe anzeigen
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Objekte dieses Typs können nicht an Notizkarten 
+für diese Region angehängt werden.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		An Notizkarten können nur Objekte ohne 
+Berechtigungseinschränkungen für den 
+nächsten Eigentümer angehängt werden.
+	</string>
 	<string name="Searching">
 		Suchen...
 	</string>
@@ -717,6 +726,18 @@ Warten Sie kurz und versuchen Sie dann noch einmal, sich anzumelden.
 		Fehler bei der Upload-Anforderung. Um das Problem zu lösen, 
 besuchen Sie bitte http://secondlife.com/support
 	</string>
+	<string name="SettingValidationError">
+		Validierung für das Importieren der Einstellungen [NAME] fehlgeschlagen
+	</string>
+	<string name="SettingImportFileError">
+		[FILE] konnte nicht geöffnet werden
+	</string>
+	<string name="SettingParseFileError">
+		[FILE] konnte nicht geöffnet werden
+	</string>
+	<string name="SettingTranslateError">
+		Altes Windlight [NAME] konnte nicht übernommen werden
+	</string>
 	<string name="texture">
 		Textur
 	</string>
@@ -792,6 +813,9 @@ besuchen Sie bitte http://secondlife.com/support
 	<string name="symbolic folder link">
 		Link zu Ordner
 	</string>
+	<string name="settings blob">
+		Einstellungen
+	</string>
 	<string name="mesh">
 		mesh
 	</string>
@@ -1122,6 +1146,9 @@ besuchen Sie bitte http://secondlife.com/support
 	<string name="ForceSitAvatar">
 		Ihren Avatar zwingen, sich zu setzen
 	</string>
+	<string name="ChangeEnvSettings">
+		Umgebungseinstellungen ändern
+	</string>
 	<string name="NotConnected">
 		Nicht verbunden
 	</string>
@@ -1273,6 +1300,9 @@ besuchen Sie bitte http://secondlife.com/support
 	<string name="tattoo">
 		Tätowierung
 	</string>
+	<string name="universal">
+		Universal
+	</string>
 	<string name="physics">
 		Physik
 	</string>
@@ -1315,6 +1345,9 @@ besuchen Sie bitte http://secondlife.com/support
 	<string name="tattoo_not_worn">
 		Tätowierung nicht getragen
 	</string>
+	<string name="universal_not_worn">
+		Universal nicht getragen
+	</string>
 	<string name="physics_not_worn">
 		Physik nicht getragen
 	</string>
@@ -1366,6 +1399,9 @@ besuchen Sie bitte http://secondlife.com/support
 	<string name="create_new_tattoo">
 		Neue Tätowierung erstellen
 	</string>
+	<string name="create_new_universal">
+		Neues Universal erstellen
+	</string>
 	<string name="create_new_physics">
 		Neue Physik erstellen
 	</string>
@@ -2513,6 +2549,27 @@ Falls diese Meldung weiterhin angezeigt wird, wenden Sie sich unter http://suppo
 	<string name="RegionSettings">
 		Regionseinstellungen
 	</string>
+	<string name="NoEnvironmentSettings">
+		Diese Region unterstützt keine Umgebungseinstellungen.
+	</string>
+	<string name="EnvironmentSun">
+		Sonne
+	</string>
+	<string name="EnvironmentMoon">
+		Mond
+	</string>
+	<string name="EnvironmentBloom">
+		Bloom
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Wolkenrauschen
+	</string>
+	<string name="EnvironmentNormalMap">
+		Normal-Map
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparent
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Klicks: [TELEPORT] teleportieren, [MAP] Karte, [PROFILE] Profil
 	</string>
@@ -4729,6 +4786,9 @@ Missbrauchsbericht
 	<string name="New Tattoo">
 		Neue Tätowierung
 	</string>
+	<string name="New Universal">
+		Neues Universal
+	</string>
 	<string name="New Physics">
 		Neue Physik
 	</string>
@@ -4855,6 +4915,15 @@ Missbrauchsbericht
 	<string name="Female - Wow">
 		Weiblich - Wow
 	</string>
+	<string name="New Daycycle">
+		Neuer Tageszyklus
+	</string>
+	<string name="New Water">
+		Neues Wasser
+	</string>
+	<string name="New Sky">
+		Neuer Himmel
+	</string>
 	<string name="/bow">
 		/verbeugen
 	</string>
@@ -5383,6 +5452,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="BeaconMedia">
 		Medien-Beacons werden angezeigt (weiß)
 	</string>
+	<string name="BeaconSun">
+		Sonnenrichtungs-Beacon ansehen (orange)
+	</string>
+	<string name="BeaconMoon">
+		Mondrichtungs-Beacon ansehen (lila)
+	</string>
 	<string name="ParticleHiding">
 		Partikel werden ausgeblendet
 	</string>
@@ -5410,6 +5485,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="Command_Destinations_Label">
 		Ziele
 	</string>
+	<string name="Command_Environments_Label">
+		Meine Umgebungen
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5503,6 +5584,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="Command_Destinations_Tooltip">
 		Ziele von Interesse
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Meine Umgebungen
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Auf Facebook posten
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Auf Flickr hochladen
 	</string>
@@ -5698,6 +5785,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="ExperiencePermission12">
 		automatisch Erlebnisberechtigungen akzeptieren
 	</string>
+	<string name="ExperiencePermission16">
+		ihren Avatar zwingen, sich zu setzen
+	</string>
+	<string name="ExperiencePermission17">
+		Ändern Ihrer Umgebungseinstellungen
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		unbekannten Vorgang durchführen: [Permission]
 	</string>
@@ -5722,6 +5815,12 @@ Setzen Sie den Editorpfad in Anführungszeichen
 	<string name="ExperiencePermissionShort12">
 		Berechtigung
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Sitzen
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Umgebung
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		Unterhaltungen werden nicht protokolliert. Um ein Protokoll zu starten, wählen Sie „Speichern: nur Protokoll“ oder „Speichern: Protokoll und Transkripte“ unter „Einstellungen“ &gt; „Chat“.
 	</string>
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index a143adfa0633dacff99563e04d2ab849941fa685..a1dd179765208b873bf54df78be62776b9871fc6 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -2140,5 +2140,17 @@ Only large parcels can be listed in search.
             class="land_experiences_panel"
           filename="panel_region_experiences.xml">
        </panel>
+    <panel
+          border="true"
+          follows="all"
+          label="ENVIRONMENT"
+          layout="topleft"
+          left="0"
+          top="0"
+          help_topic="land_environment_tab"
+          name="land_environment_panel"
+          class="land_environment_panel"
+          filename="panel_region_environment.xml">
+       </panel>
     </tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_adjust_environment.xml b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..59589e3665e10cfa54a0f5cac7048e6a6a6ae8fe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_adjust_environment.xml
@@ -0,0 +1,401 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater layout="topleft"
+         name="env_adjust_snapshot"
+         help_topic="day_presets"
+         save_rect="false"
+         title="Personal Lighting"
+         width="845"
+         height="240"
+         min_width="500"
+         min_height="235"
+         single_instance="true"
+         can_resize="false">
+    <layout_stack name="outer_stack"
+                  width="845"
+                  height="230"
+                  follows="all"
+                  animate="false"
+                  top="0"
+                  orientation="vertical">
+        <!-- If I put in a timeline it would go here -->
+        <layout_panel name="env_controls"
+                      border="false"
+                      bevel_style="in"
+                      auto_resize="true"
+                      user_resize="true"
+                      height="150"
+                      min_height="0"
+                      visible="true">
+            <layout_stack name="settings_stack"
+                          width="855"
+                          height="150"
+                          follows="all"
+                          animate="false"
+                          orientation="horizontal">
+                <layout_panel border="false"
+                              bevel_style="in"
+                              auto_resize="false"
+                              user_resize="false"
+                              visible="true"
+                              width="160"
+                              height="150">
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left="10"
+                          top="5"
+                          width="80">Ambient:</text>
+                    <color_swatch can_apply_immediately="true"
+                                  follows="left|top"
+                                  height="40"
+                                  label_height="0"
+                                  layout="topleft"
+                                  left_delta="0"
+                                  name="ambient_light"
+                                  top_pad="5"
+                                  width="60"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="0"
+                          top_pad="10"
+                          width="80">Blue Horizon:</text>
+                    <color_swatch can_apply_immediately="true"
+                                  follows="left|top"
+                                  height="40"
+                                  label_height="0"
+                                  layout="topleft"
+                                  left_delta="0"
+                                  name="blue_horizon"
+                                  top_pad="5"
+                                  width="60"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="0"
+                          top_pad="10"
+                          width="80">Blue Density:</text>
+                    <color_swatch can_apply_immediately="true"
+                                  follows="left|top"
+                                  height="40"
+                                  label_height="0"
+                                  layout="topleft"
+                                  left_delta="0"
+                                  name="blue_density"
+                                  top_pad="5"
+                                  width="60"/>
+                    <button
+                      follows="left|top"
+                      height="23"
+                      label="Reset"
+                      tool_tip="Close and reset to Shared Environment"
+                      layout="topleft"
+                      name="btn_reset"
+                      left_delta="-2"
+                      top_pad="10"
+                      width="100"/>
+                    <text follows="right|top"
+                          height="10"
+                          layout="topleft"
+                          right="-12"
+                          top="5"
+                          width="60">Sun Color:</text>
+                    <color_swatch can_apply_immediately="true"
+                                  follows="left|top"
+                                  height="10"
+                                  label_height="0"
+                                  layout="topleft"
+                                  left_delta="0"
+                                  name="sun_color"
+                                  top_pad="5"
+                                  width="60"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="0"
+                          top_pad="5"
+                          width="80">Cloud Color:</text>
+                    <color_swatch can_apply_immediately="true"
+                                  follows="left|top"
+                                  height="10"
+                                  label_height="0"
+                                  layout="topleft"
+                                  left_delta="0"
+                                  name="cloud_color"
+                                  top_pad="5"
+                                  width="60"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="0"
+                          top_pad="10"
+                          name="cloud_map_label"
+                          width="80">Cloud Image:</text>
+                    <texture_picker height="63"
+                                    layout="topleft"
+                                    left_delta="0"
+                                    name="cloud_map"
+                                    top_pad="5"
+                                    width="60"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="0"
+                          top_pad="-13"
+                          name="cloud_map_label"
+                          width="80">Water Image:</text>
+                    <texture_picker height="63"
+                                    layout="topleft"
+                                    left_delta="0"
+                                    name="water_normal_map"
+                                    top_pad="5"
+                                    width="60"/>
+                </layout_panel>
+                <layout_panel border="false"
+                              bevel_style="in"
+                              auto_resize="false"
+                              user_resize="false"
+                              visible="true"
+                              width="200"
+                              height="150">
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="5"
+                          top_pad="5"
+                          width="80">Haze Horizon:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="5"
+                            name="haze_horizon"
+                            top_pad="5"
+                            width="185"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="5"
+                          width="80">Haze Density:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="5"
+                            name="haze_density"
+                            top_pad="5"
+                            width="185"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="5"
+                          width="185">Cloud Coverage:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="1"
+                            name="cloud_coverage"
+                            top_pad="5"
+                            width="185"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="5"
+                          width="185">Cloud Scale:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.01"
+                            max_val="3"
+                            name="cloud_scale"
+                            top_pad="5"
+                            width="185"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="15"
+                          width="80">Scene Gamma:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            max_val="20"
+                            name="scene_gamma"
+                            top_pad="5"
+                            width="185"
+                            can_edit_text="true"/>
+                </layout_panel>
+                <layout_panel border="false"
+                              bevel_style="in"
+                              auto_resize="false"
+                              user_resize="false"
+                              height="150"
+                              width="310"
+                              min_height="0"
+                              visible="true">
+                    <text follows="top|left"
+                          font="SansSerifBold"
+                          height="10"
+                          layout="topleft"
+                          name="label"
+                          left="5"
+                          top="5"
+                          width="105">Sun:</text>
+                    <sun_moon_trackball name="sun_rotation"
+                                        follows="left|top"
+                                        left_delta="0"
+                                        top_delta="20"
+                                        height="150"
+                                        width="150"
+                                        thumb_mode="sun"/>
+                    <check_box control_name="sunbeacon"
+                               width="60"
+                               height="16"
+                               label="Show Beacon"
+                               layout="topleft"
+                               name="sunbeacon"
+                               left_delta="55"
+                               bottom="-20"
+                               follows="bottom|right"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_pad="40"
+                          top="25"
+                          width="80">Scale:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.25"
+                            max_val="20"
+                            name="sun_scale"
+                            top_delta="15"
+                            width="130"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="5"
+                          width="100">Glow Focus:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="-2"
+                            max_val="2"
+                            name="glow_focus"
+                            top_pad="5"
+                            width="130"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="5"
+                          width="200">Glow Size:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="1.99"
+                            name="glow_size"
+                            top_pad="5"
+                            width="130"
+                            can_edit_text="true"/>
+                    <text follows="left|top"
+                          height="10"
+                          layout="topleft"
+                          left_delta="-5"
+                          top_pad="10"
+                          width="200">Star Brightness:</text>
+                    <slider decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="500"
+                            name="star_brightness"
+                            top_pad="5"
+                            width="130"
+                            can_edit_text="true"/>
+                </layout_panel>
+                <layout_panel border="false"
+                              bevel_style="in"
+                              auto_resize="false"
+                              user_resize="false"
+                              height="150"
+                              width="160"
+                              min_height="0"
+                              visible="true">
+                    <text follows="top|left"
+                          font="SansSerifBold"
+                          height="10"
+                          layout="topleft"
+                          name="label"
+                          left="5"
+                          top="5"
+                          width="105">Moon:</text>
+                    <sun_moon_trackball name="moon_rotation"
+                                        follows="left|top"
+                                        left_delta="0"
+                                        top_delta="20"
+                                        height="150"
+                                        width="150"
+                                        thumb_mode="moon"/>
+                    <check_box control_name="moonbeacon"
+                               width="60"
+                               height="16"
+                               label="Show Beacon"
+                               layout="topleft"
+                               name="moonbeacon"
+                               right="-50"
+                               bottom="-20"
+                               follows="bottom|right"/>
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
+    </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml
index 3d29356b2256a4de0d43e2a3e4406c00c375d1c1..d5947fc0af8b016eeccb091ef6716df2e5f9d582 100644
--- a/indra/newview/skins/default/xui/en/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/en/floater_beacons.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
  legacy_header_height="18"
- height="245"
+ height="310"
  layout="topleft"
  name="beacons"
  help_topic="beacons"
@@ -12,7 +12,7 @@
  width="240">
     <panel
      follows="left|top|right|bottom"
-     height="240"
+     height="305"
      layout="topleft"
      left="10"
      name="beacons_panel"
@@ -143,6 +143,43 @@
           <check_box.commit_callback
            function="Beacons.UICheck" />
         </check_box>
+        <view_border
+         bevel_style="in"
+         height="0"
+         layout="topleft"
+         left="0"
+         name="cost_text_border"
+         top_pad="5"
+         width="220"/>
+        <text
+         follows="all"
+         height="16"
+         font="SansSerif"
+         left="0"
+         top_pad="7"
+         name="label_objects"
+         text_color="White"
+         type="string">
+           Show direction to:
+         </text>
+        <check_box
+         control_name="sunbeacon"
+         height="16"
+         label="Sun"
+         layout="topleft"
+         name="sun" >
+          <check_box.commit_callback
+           function="Beacons.UICheck" />
+        </check_box>
+        <check_box
+         control_name="moonbeacon"
+         height="16"
+         label="Moon"
+         layout="topleft"
+         name="moon" >
+          <check_box.commit_callback
+           function="Beacons.UICheck" />
+        </check_box>
 
     </panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
index 9fa93b640fe9ef0db451c9a6b190d50af8113ebe..431c33a3393279299cc9c02a33d18edaad5f6f9a 100644
--- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -156,7 +156,20 @@
      name="icon_texture"
      tool_tip="Textures"
      left_pad="2" />
-
+  <check_box
+    control_name="BulkChangeIncludeSettings"
+    height="16"
+    name="check_settings"
+    left="245"
+    top="25"
+    width="16" />
+  <icon
+    height="16"
+    image_name="Inv_Settings"
+    mouse_opaque="true"
+    name="icon_setting"
+    tool_tip="Environment settings"
+    left_pad="2" />
     <button
       height="23"
     layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/en/floater_delete_env_preset.xml
deleted file mode 100644
index b5de4166f62ed44ddd924aa45aac50fd944ad0f6..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,59 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<floater
- legacy_header_height="18"
- height="130"
- help_topic=""
- layout="topleft"
- name="Delete Env Preset"
- save_rect="true"
- title="DELETE ENV PRESET"
- width="550">
-
-    <string name="title_water">Delete Water Preset</string>
-    <string name="title_sky">Delete Sky Preset</string>
-    <string name="title_day_cycle">Delete Day Cycle</string>
-
-    <string name="label_water">Preset:</string>
-    <string name="label_sky">Preset:</string>
-    <string name="label_day_cycle">Day cycle:</string>
-   
-    <string name="msg_confirm_deletion">Are you sure you want to delete the selected preset?</string>
-    <string name="msg_sky_is_referenced">Cannot remove a preset that is referenced by some day cycle(s).</string>
-
-    <string name="combo_label">-Select a preset-</string>
-
-    <text
-     follows="top|left|right"
-     font="SansSerif"
-     height="10"
-     layout="topleft"
-     left="50"
-     name="label"
-     top="60"
-     width="60">
-     Preset:
-    </text>
-    <combo_box
-     follows="top|left"
-     layout="topleft"
-     left_pad="10"
-     name="preset_combo"
-     top_delta="-5"
-     width="200"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Delete"
-     layout="topleft"
-     left_pad="15"
-     name="delete"
-     width="70"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Cancel"
-     layout="topleft"
-     left_pad="5"
-     name="cancel"
-     width="70"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_edit_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_day_cycle.xml
deleted file mode 100644
index d9a3ad0c4b1af36f4ed671aee5ca02d0fb7e24a2..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_edit_day_cycle.xml
+++ /dev/null
@@ -1,485 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- height="381"
- layout="topleft"
- name="Edit Day cycle"
- help_topic="day_presets"
- save_rect="true"
- title="Edit Day Cycle"
- width="705">
-
-    <string name="title_new">Create a New Day Cycle</string>
-    <string name="title_edit">Edit Day Cycle</string>
-    <string name="hint_new">Name your day cycle, adjust the controls to create it, and click "Save".</string>
-    <string name="hint_edit">To edit your day cycle, adjust the controls below and click "Save".</string>
-    <string name="combo_label">-Select a preset-</string>
-
-    <text
-     follows="top|left|right"
-     height="10"
-     layout="topleft"
-     left="10"
-     name="hint"
-     top="25"
-     width="685" />
-    <text
-     follows="top|left|right"
-     font="SansSerif"
-     height="10"
-     layout="topleft"
-     left="10"
-     name="label"
-     top_pad="25"
-     width="120">
-     Preset Name:
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     follows="top|left"
-     layout="topleft"
-     left_pad="10"
-     max_chars="100"
-     name="day_cycle_combo"
-     top_delta="-5"
-     width="200" />
-    <line_editor
-     height="20"
-     left_delta="0"
-     name="day_cycle_name"
-     top_delta="0"
-     visible="true"
-     width="200" />
-    <text
-     follows="top|left|right"
-     height="95"
-     layout="topleft"
-     left_pad="10"
-     name="note"
-     top_delta="0"
-     width="345"
-     wrap="true">
-     Note: if you change the name of your preset, you will be creating a new preset and the existing preset will not be changed.
-    </text>
- <!--======== Controls panel ========-->
-    <text
-     follows="left|top|right"
-     height="10"
-     layout="topleft"
-     left="10"    
-     name="hint_item1"
-     top="100"
-     width="300">
-     - Click on a tab to edit the specific sky settings and time.
-    </text>
-    <text
-     follows="left|top|right"
-     height="10"
-     layout="topleft"    
-     name="hint_item2"
-     top_pad="10"
-     width="300">
-     - Click and drag the tabs to set the transition times.
-    </text>
-    <text
-     follows="left|top|right"
-     height="10"
-     layout="topleft"
-     name="hint_item3"
-     top_pad="10"
-     width="300">
-     - Use the scrubber to preview your day cycle.
-    </text>
-    <panel
-     follows="top|left"
-     height="100"
-     name="day_cycle_slider_panel"
-     layout="topleft"
-     left_delta="25"
-     top_pad="15"
-     width="660">
-        <multi_slider
-         can_edit_text="true"
-         control_name="WLTimeSlider"
-         decimal_digits="0"
-         draw_track="false"
-         follows="bottom"
-         height="10"
-         increment="0.0833333"
-         initial_value="0"
-         layout="topleft"
-         left="20"
-         max_sliders="20"
-         max_val="24"
-         name="WLTimeSlider"
-         show_text="false"
-         top_pad="0"
-         use_triangle="true"
-         width="525" />
-        <multi_slider
-         can_edit_text="true"
-         control_name="WLDayCycleKeys"
-         decimal_digits="0"
-         follows="bottom"
-         height="10"
-         increment="0.0833333"
-         initial_value="0"
-         layout="topleft"
-         left_delta="0"
-         max_sliders="20"
-         max_val="24"
-         name="WLDayCycleKeys"
-         show_text="false"
-         top_pad="15"
-         width="525" />
-        <button
-         height="20"
-         label="Add Key"
-         label_selected="Add Key"
-         layout="topleft"
-         left_pad="20"
-         name="WLAddKey"
-         top_delta="-18"
-         width="96" />
-        <button
-         height="20"
-         label="Delete Key"
-         label_selected="Delete Key"
-         layout="topleft"
-         name="WLDeleteKey"
-         top_pad="5"
-         width="96" />
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left="8"
-         name="WL12am"
-         top="74"
-         width="55">
-         12am
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL3am"
-         top_delta="0"
-         width="55">
-            3am
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL6am"
-         top_delta="0"
-         width="55">
-            6am
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL9amHash"
-         top_delta="0"
-         width="55">
-            9am
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL12pmHash"
-         top_delta="0"
-         width="55">
-            12pm
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL3pm"
-         top_delta="0"
-         width="55">
-            3pm
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL6pm"
-         top_delta="0"
-         width="55">
-            6pm
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL9pm"
-         top_delta="0"
-         width="55">
-            9pm
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         height="16"
-         layout="topleft"
-         left_pad="10"
-         name="WL12am2"
-         top_delta="0"
-         width="55">
-            12am
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="14"
-         layout="topleft"
-         left="20"
-         name="WL12amHash"
-         top="54"
-         width="6">
-            |
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="11"
-         layout="topleft"
-         left_pad="59"
-         name="WL3amHash"
-         top_delta="3"
-         width="6">
-            I
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="14"
-         layout="topleft"
-         left_pad="59"
-         name="WL6amHash"
-         top_delta="-3"
-         width="6">
-            |
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="11"
-         layout="topleft"
-         left_pad="59"
-         name="WL9amHash2"
-         top_delta="3"
-         width="6">
-            I
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="14"
-         layout="topleft"
-         left_pad="59"
-         name="WL12pmHash2"
-         top_delta="-3"
-         width="6">
-            |
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="11"
-         layout="topleft"
-         left_pad="59"
-         name="WL3pmHash"
-         top_delta="3"
-         width="6">
-            I
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="14"
-         layout="topleft"
-         left_pad="59"
-         name="WL6pmHash"
-         top_delta="-3"
-         width="6">
-            |
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="11"
-         layout="topleft"
-         left_pad="59"
-         name="WL9pmHash"
-         top_delta="3"
-         width="6">
-            I
-        </text>
-        <text
-         type="string"
-         length="1"
-         border_visible="true"
-         follows="left|top|right"
-         font="SansSerif"
-         height="14"
-         layout="topleft"
-         left_pad="59"
-         name="WL12amHash2"
-         top_delta="-3"
-         width="6">
-         |
-        </text>
-    </panel>
-    <text
-     type="string"
-     length="1"
-     border_visible="true"
-     follows="left|top|right"
-     font="SansSerif"
-     height="16"
-     layout="topleft"
-     left_delta="192"
-     name="WLCurKeyPresetText"
-     top_pad="10"
-     width="80">
-        Sky Setting:
-    </text>
-    <combo_box
-     height="18"
-     label="Preset"
-     layout="topleft"
-     left_pad="5"
-     name="WLSkyPresets"
-     width="205" />
-        <text
-     type="string"
-     length="1"
-     border_visible="true"
-     follows="left|top|right"
-     font="SansSerif"
-     height="16"
-     layout="topleft"
-     left_delta="-40"
-     name="WLCurKeyTimeText"
-     top_pad="15"
-     width="35">
-        Time:
-    </text>
-    <time
-     follows="left|top"
-     height="16"
-     label_width="0"
-     layout="topleft"
-     left_pad="3"
-     name="time"
-     top_delta="-1"
-     value="6:00 AM"
-     width="75"/> 
-    <view_border
-     bevel_style="none"
-     follows="top|left"
-     height="0"
-     layout="topleft"
-     left="10"
-     name="horiz_separator"
-     top_pad="20"
-     width="685"/>
-    <loading_indicator
-     height="23"
-     layout="topleft"
-     left="25"
-     name="progress_indicator"
-     top="350"
-     visible="false"
-     width="23" />
-    <check_box
-     follows="top|left"
-     height="10"
-     label="Make this my new day cycle"
-     layout="topleft"
-     left="310"
-     name="make_default_cb"
-     top_delta="13"
-     width="230"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Save"
-     layout="topleft"
-     left_pad="0"
-     name="save"
-     top_delta="-13"
-     width="70"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Cancel"
-     layout="topleft"
-     left_pad="15"
-     name="cancel"
-     top_delta="0"
-     width="70"/>
- </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..30e9002230d9e799d72e8a0c34f02462ebca51d1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,651 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+        layout="topleft"
+        name="env_edit_extdaycycle"
+        help_topic="day_presets"
+        save_rect="false"
+        title="Edit Day Cycle"
+        width="705"
+        height="700"
+        min_width="705"
+        min_height="700"
+        single_instance="true" 
+        can_resize="false">
+
+    <!-- obsolete?, add as hint for 'save' button? -->
+    <string name="title_new">Create a New Day Cycle</string>
+    <string name="title_edit">Edit Day Cycle</string>
+    <string name="hint_new">Name your day cycle, adjust the controls to create it, and click "Save".</string>
+    <string name="hint_edit">To edit your day cycle, adjust the controls below and click "Save".</string>
+
+    <!-- Substitutions -->
+    <string name="time_label">([HH]:[MM])</string>
+    <string name="sky_track_label">Sky [ALT]</string>
+    <string name="sky_label">Sky</string>
+    <string name="water_label">Water</string>
+
+    <string name="commit_parcel">Apply To Parcel</string>
+    <string name="commit_region">Apply To Region</string>
+
+    <!-- Layout -->
+    <layout_stack name="outer_stack"
+            width="705"
+            height="700"
+            follows="all"
+            animate="false"
+            top="0"
+            orientation="vertical">
+        <layout_panel name="name_and_import"
+                border="false"
+                auto_resize="false"
+                user_resize="false"
+                height="29"
+                min_height="29"
+                background_visible="false">
+            <!-- This layout_panel is for loading legacy presets -->
+            <text
+                    follows="top|left"
+                    font="SansSerif"
+                    height="10"
+                    layout="topleft"
+                    name="label"
+                    left="15"
+                    top="5"
+                    width="105">
+                Day Cycle Name:
+            </text>
+            <line_editor
+                    follows="top|left"
+                    layout="topleft"
+                    left_pad="10"
+                    max_length_bytes="100"
+                    name="day_cycle_name"
+                    prevalidate_callback="ascii"
+                    top="5"
+                    width="200"
+                    height="21" />
+            <button
+                    height="23"
+                    label="Import"
+                    follows="right|top"
+                    right="-10"
+                    font="SansSerif"
+                    top_delta="0"
+                    name="btn_import"
+                    tool_tip="Import legacy settings from disk." 
+                    width="96" />
+        </layout_panel>
+        <layout_panel name="content"
+                border="false"
+                auto_resize="true"
+                user_resize="false"
+                background_visible="false">
+            <layout_stack name="content_stack"
+                    width="705"
+                    follows="all"
+                    animate="false"
+                    top="0"
+                    orientation="vertical">
+                <layout_panel name="timeline_track_selection"
+                        border="false"
+                        bevel_style="in"
+                        auto_resize="false"
+                        user_resize="false"
+                        height="150"
+                        min_height="0"
+                        visible="true">
+                    <panel name="timeline_layers"
+                            border="false"
+                            follows="left|top"
+                            height="150"
+                            width="110"
+                            top_pad="0"
+                            min_height="0"
+                            visible="true">
+                        <button
+                                follows="left|top"
+                                height="23"
+                                label="Sky 4"
+                                layout="topleft"
+                                top_pad="5"
+                                left="10"
+                                name="sky4_track"
+                                width="100"> 
+                            <button.commit_callback
+                                    function="DayCycle.Track"
+                                    parameter="4" />
+                        </button>
+                        <button
+                                follows="left|top"
+                                height="23"
+                                label="Sky 3"
+                                layout="topleft"
+                                top_pad="0"
+                                left="10"
+                                name="sky3_track"
+                                width="100"> 
+                            <button.commit_callback
+                                    function="DayCycle.Track"
+                                    parameter="3" />
+                        </button>
+                        <button
+                                follows="left|top"
+                                height="23"
+                                label="Sky 2"
+                                layout="topleft"
+                                top_pad="0"
+                                left="10"
+                                name="sky2_track"
+                                width="100"> 
+                            <button.commit_callback
+                                    function="DayCycle.Track"
+                                    parameter="2" />
+                        </button>
+                        <button
+                                follows="left|top"
+                                height="23"
+                                label="Ground Level"
+                                layout="topleft"
+                                top_pad="0"
+                                left="10"
+                                name="sky1_track"
+                                width="100"> 
+                            <button.commit_callback
+                                    function="DayCycle.Track"
+                                    parameter="1" />
+                        </button>
+                        <button
+                                follows="left|top"
+                                height="23"
+                                label="Water"
+                                layout="topleft"
+                                top_pad="0"
+                                left="10"
+                                name="water_track"
+                                width="100"> 
+                            <button.commit_callback
+                                    function="DayCycle.Track"
+                                    parameter="0" />
+                        </button>
+                    </panel>
+                    <panel name="timeline"
+                            border="true"
+                            follows="left|top"
+                            height="150"
+                            min_height="0"
+                            width="595"
+                            min_width="595"
+                            left_pad="0"
+                            visible="true">              
+                        <!-- Todo: These 5 tests might be subjected to a change to be dynamically generated, consider using layout_stack to get dynamic width adjustment-->
+                        <text
+                                follows="left|top"
+                                height="15"
+                                layout="topleft"
+                                left="10"
+                                name="p0"
+                                top_pad="5"
+                                value="0% [DSC]"
+                                width="90" />
+                        <text
+                                follows="left|top|right"
+                                height="15"
+                                layout="topleft"
+                                left_delta="117"
+                                name="p1"
+                                top_delta="0"
+                                value="25% [DSC]"
+                                width="90" />
+                        <text
+                                follows="left|top|right"
+                                height="15"
+                                layout="topleft"
+                                left_delta="122"
+                                name="p2"
+                                top_delta="0"
+                                value="50% [DSC]"
+                                width="90" />
+                        <text
+                                follows="left|top|right"
+                                height="15"
+                                layout="topleft"
+                                left_delta="122"
+                                name="p3"
+                                top_delta="0"
+                                value="75% [DSC]"
+                                width="90" />
+                        <text
+                                follows="left|top|right"
+                                height="15"
+                                layout="topleft"
+                                left_delta="122"
+                                name="p4"
+                                top_delta="0"
+                                value="100% [DSC]"
+                                width="90" />
+                        <multi_slider
+                                decimal_digits="0"
+                                draw_track="false"
+                                follows="bottom"
+                                height="10"
+                                increment="0.005"
+                                overlap_threshold="0.026"
+                                initial_value="0"
+                                layout="topleft"
+                                left="10"
+                                max_sliders="1"
+                                max_val="1"
+                                name="WLTimeSlider"
+                                show_text="false"
+                                top_pad="0"
+                                use_triangle="true"
+                                width="525" />
+
+                        <multi_slider
+                                decimal_digits="0"
+                                follows="bottom"
+                                height="10"
+                                increment="0.005"
+                                overlap_threshold="0.026"
+                                loop_overlap="true"
+                                initial_value="0"
+                                layout="topleft"
+                                left="10"
+                                max_sliders="20"
+                                max_val="1"
+                                name="WLDayCycleFrames"
+                                show_text="false"
+                                top_pad="15"
+                                width="525" />
+
+                        <text
+                                follows="left|bottom"
+                                height="25"
+                                layout="topleft"
+                                left_pad="0"
+                                name="current_time"
+                                value="[PRCNT]% [DSC]"
+                                top_delta="-5"
+                                width="56"
+                                word_wrap="true"/>
+
+                        <layout_stack
+                                follows="all"
+                                height="200"
+                                animate="false"
+                                top_pad="0"
+                                left="0"
+                                orientation="horizontal">
+                            <layout_panel
+                                    border="false"
+                                    bevel_style="in"
+                                    auto_resize="false"
+                                    user_resize="false"
+                                    height="150"
+                                    width="200"
+                                    min_height="0"
+                                    visible="true">
+                                <button
+                                        follows="top|left"
+                                        height="23"
+                                        width="110"
+                                        label="Clone Track From"
+                                        left="10"
+                                        top_pad="10"
+                                        name="copy_track" />
+                                <button
+                                        follows="top|left"
+                                        height="23"
+                                        width="110"
+                                        label="Load Track From"
+                                        top_pad="0"
+                                        left_delta="0"
+                                        name="load_track" />
+                                <button
+                                        follows="top|left"
+                                        height="23"
+                                        width="110"
+                                        label="Clear Track"
+                                        top_pad="0"
+                                        left_delta="0"
+                                        name="clear_track" />
+                                    
+                            </layout_panel>
+                            <layout_panel
+                                    border="false"
+                                    bevel_style="in"
+                                    auto_resize="false"
+                                    user_resize="false"
+                                    height="150"
+                                    width="200"
+                                    min_height="0"
+                                    visible="true">
+                                <layout_stack
+                                        name="progress_control"
+                                        follows="top|left"
+                                        height="25"
+                                        width="83"
+                                        layout="topleft"
+                                        animate="false"
+                                        left="31"
+                                        top="40"
+                                        orientation="horizontal">
+
+                                    <layout_panel
+                                            name="skip_back"
+                                            mouse_opaque="false"
+                                            auto_resize="false"
+                                            layout="topleft"
+                                            top="0"
+                                            height="25"
+                                            min_width="25"
+                                            width="25">
+                                        <button
+                                                name="skip_back_btn"
+                                                follows="top"
+                                                image_overlay="SkipBackward_Off"
+                                                image_disabled="PushButton_Disabled"
+                                                image_disabled_selected="PushButton_Disabled"
+                                                image_selected="PushButton_Selected"
+                                                image_unselected="PushButton_Off"
+                                                hover_glow_amount="0.15"
+                                                auto_resize="false"
+                                                width="25"
+                                                height="25"
+                                                layout="topleft"
+                                                tool_tip="Step back"
+                                                top="0"
+                                                left="0">
+                                            <button.commit_callback
+                                                    function="DayCycle.PlayActions"
+                                                    parameter="back" />
+                                        </button>
+                                    </layout_panel>
+
+                                    <layout_panel
+                                            name="play_layout"
+                                            mouse_opaque="false"
+                                            auto_resize="false"
+                                            layout="topleft"
+                                            top="0"
+                                            height="25"
+                                            min_width="25"
+                                            width="25">
+                                        <button
+                                                name="play_btn"
+                                                follows="top"
+                                                image_overlay="Play_Off"
+                                                image_disabled="PushButton_Disabled"
+                                                image_disabled_selected="PushButton_Disabled"
+                                                image_selected="PushButton_Selected"
+                                                image_unselected="PushButton_Off"
+                                                hover_glow_amount="0.15"
+                                                auto_resize="false"
+                                                layout="topleft"
+                                                height="25"
+                                                width="25"
+                                                left="0"
+                                                top="0">
+                                            <button.commit_callback
+                                                    function="DayCycle.PlayActions"
+                                                    parameter="play" />
+                                        </button>
+                                    </layout_panel>
+
+                                    <layout_panel
+                                            name="pause_layout"
+                                            mouse_opaque="false"
+                                            auto_resize="false"
+                                            layout="topleft"
+                                            top="0"
+                                            height="25"
+                                            min_width="25"
+                                            width="25"
+                                            visible="false">
+                                        <button
+                                                name="pause_btn"
+                                                follows="top"
+                                                image_overlay="Pause_Off"
+                                                image_disabled="PushButton_Disabled"
+                                                image_disabled_selected="PushButton_Disabled"
+                                                image_selected="PushButton_Selected"
+                                                image_unselected="PushButton_Off"
+                                                hover_glow_amount="0.15"
+                                                auto_resize="false"
+                                                layout="topleft"
+                                                height="25"
+                                                width="25"
+                                                left="0"
+                                                top="0">
+                                            <button.commit_callback
+                                                    function="DayCycle.PlayActions"
+                                                    parameter="pause" />
+                                        </button>
+                                    </layout_panel>
+
+                                    <layout_panel
+                                            name="skip_forward"
+                                            mouse_opaque="false"
+                                            auto_resize="false"
+                                            layout="topleft"
+                                            top="0"
+                                            height="25"
+                                            min_width="25"
+                                            width="25">
+                                        <button
+                                                name="skip_forward_btn"
+                                                follows="top"
+                                                image_overlay="SkipForward_Off"
+                                                image_disabled="PushButton_Disabled"
+                                                image_disabled_selected="PushButton_Disabled"
+                                                image_selected="PushButton_Selected"
+                                                image_unselected="PushButton_Off"
+                                                hover_glow_amount="0.15"
+                                                width="25"
+                                                height="25"
+                                                layout="topleft"
+                                                tool_tip="Step forward"
+                                                top="0">
+                                            <button.commit_callback
+                                                    function="DayCycle.PlayActions"
+                                                    parameter="forward" />
+                                        </button>
+                                    </layout_panel>
+                                </layout_stack>
+                            </layout_panel>
+                            <layout_panel
+                                    border="false"
+                                    bevel_style="in"
+                                    auto_resize="false"
+                                    user_resize="false"
+                                    width="190"
+                                    height="150"
+                                    min_height="0"
+                                    visible="true">
+                                <button
+
+                                        follows="top|right"
+                                        height="23"
+                                        width="90"
+                                        right="-10"
+                                        top_pad="10"
+                                        label="Add [FRAME]"
+                                        name="add_frame" />
+                                <button
+                                        follows="top|left"
+                                        height="23"
+                                        width="90"
+                                        label="Load [FRAME]"
+                                        top_pad="0"
+                                        left_delta="0"
+                                        name="btn_load_frame" />
+                                <button
+                                        follows="left|top"
+                                        height="23"
+                                        width="90"
+                                        label="Delete [FRAME]"
+                                        top_pad="0"
+                                        left_delta="0"
+                                        name="delete_frame" />
+                            </layout_panel>
+                        </layout_stack>
+                    </panel>
+                </layout_panel>
+                <layout_panel name="frame_edit_controls"
+                        auto_resize="false"
+                        user_resize="false"
+                        height="30"
+                        width="700"
+                        min_height="30"
+                        visible="true">
+                    <!--bg_alpha_color="blue"
+                background_visible="true" -->
+                    <text
+                            name="icn_lock_edit"
+                            follows="bottom"
+                            height="10"
+                            layout="bottomleft"
+                            left_delta="15"
+                            top_pad="15"
+                            font="SansSerif"
+                            text_color="Yellow"
+                            width="500">
+                        Select a key frame from the timeline above to edit settings.
+                    </text>
+                </layout_panel>
+                <layout_panel name="frame_settings_water"
+                        auto_resize="true"
+                        user_resize="false"
+                        height="420"
+                        width="700"
+                        min_height="0"
+                        visible="false">
+                    <tab_container
+                            follows="all"
+                            halign="left"
+                            height="420"
+                            layout="topleft"
+                            left="0"
+                            name="water_tabs"
+                            tab_position="top"
+                            tab_width="140"
+                            tab_padding_right="3"
+                            top_pad="0"
+                            width="700">
+                        <panel
+                                border="true"
+                                class="panel_settings_water"
+                                filename="panel_settings_water.xml"
+                                label="Water"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="water_panel"/>
+                    </tab_container>
+                </layout_panel>
+                <layout_panel name="frame_settings_sky"
+                        auto_resize="true"
+                        user_resize="false"
+                        height="420"
+                        width="700"
+                        min_height="0"
+                        visible="true">
+                    <tab_container
+                            follows="all"
+                            halign="left"
+                            height="420"
+                            visible="true"
+                            layout="topleft"
+                            left="0"
+                            name="sky_tabs"
+                            tab_position="top"
+                            tab_width="140"
+                            tab_padding_right="3"
+                            top_pad="0"
+                            width="700">
+                        <panel
+                                border="true"
+                                class="panel_settings_atmos"
+                                filename="panel_settings_sky_atmos.xml"
+                                label="Atmosphere &amp; Lighting"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="atmosphere_panel" />
+                        <panel
+                                border="true"
+                                class="panel_settings_cloud"
+                                filename="panel_settings_sky_clouds.xml"
+                                label="Clouds"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="clouds_panel" />
+                        <panel
+                                border="true"
+                                class="panel_settings_sunmoon"
+                                filename="panel_settings_sky_sunmoon.xml"
+                                label="Sun &amp; Moon"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="moon_panel" />
+                        <!-- added programatically so it doesn't show up whether we want it or not
+                        <panel
+                                border="true"
+                                class="panel_settings_density"
+                                filename="panel_settings_sky_density.xml"
+                                label="Density"
+                                layout="topleft"
+                                left_delta="0"
+                                top_pad="5"
+                                name="density_panel" />
+                         -->
+                    </tab_container>
+                </layout_panel>        
+            </layout_stack>
+        </layout_panel>
+        <layout_panel name="buttons"
+                auto_resize="false"
+                user_resize="false"
+                height="26"
+                min_height="26"
+                visible="true"
+                width="700">
+            <button
+                    follows="top|left"
+                    height="23"
+                    label="Save"
+                    left="5"
+                    top_pad="0"
+                    name="save_btn"
+                    width="156" />
+
+            <button
+                    follows="top|left"
+                    height="23"
+                    name="btn_flyout"
+                    label=""
+                    layout="topleft"
+                    left_pad="-20"
+                    top="0"
+                    image_selected="SegmentedBtn_Right_Selected_Press"
+                    image_unselected="SegmentedBtn_Right_Off"
+                    image_pressed="SegmentedBtn_Right_Press"
+                    image_pressed_selected="SegmentedBtn_Right_Selected_Press"
+                    image_overlay="Arrow_Small_Up"
+                    width="20"/>
+
+            <button
+                    follows="top|left"
+                    height="23"
+                    label="Cancel"
+                    layout="topleft"
+                    left_pad="10"
+                    name="cancel_btn"
+                    width="150" /> 
+
+        </layout_panel>
+    </layout_stack>
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_edit_sky_preset.xml b/indra/newview/skins/default/xui/en/floater_edit_sky_preset.xml
deleted file mode 100644
index 56233d91eed3f14230335ebbf657719238620052..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_edit_sky_preset.xml
+++ /dev/null
@@ -1,953 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- height="375"
- layout="topleft"
- name="Edit Sky Preset"
- help_topic="sky_preset"
- save_rect="true"
- title="Edit Sky Preset"
- width="840">
-
-    <string name="title_new">Create a New Sky Preset</string>
-    <string name="title_edit">Edit Sky Preset</string>
-    <string name="hint_new">Name your preset, adjust the controls to create it, and click "Save".</string>
-    <string name="hint_edit">To edit your sky preset, adjust the controls and click "Save".</string>
-    <string name="combo_label">-Select a preset-</string>
-
-    <text
-     follows="top|left|right"
-     height="10"
-     layout="topleft"
-     left="30"
-     name="hint"
-     top="25"
-     width="700">
-     To edit your preset, adjust the controls then click "Save"
-     </text>
-    <text
-     follows="top|left|right"
-     font="SansSerif"
-     height="10"
-     layout="topleft"
-     left="30"
-     name="label"
-     top_pad="25"
-     width="120">
-        Preset Name:
-    </text>
-    <combo_box
-     allow_text_entry="true"
-     follows="top|left"
-     layout="topleft"
-     left_pad="10"
-     max_chars="100"
-     name="sky_preset_combo"
-     top_delta="-5"
-     width="200"/>
-    <line_editor
-     height="20"
-     left_delta="0"
-     name="sky_preset_name"
-     top_delta="0"
-     width="200" />
-    <text
-     follows="top|left|right"
-     height="40"
-     layout="topleft"
-     left_pad="10"
-     name="note"
-     top_delta="0"
-     width="405"
-     wrap="true">
-     Note: if you change the name of your preset, you will be creating a new preset and the existing preset will not be changed.
-    </text>
- <!--======== Controls panel ========-->
-    <view_border
-     bevel_style="none"
-     follows="top|left"
-     height="203"
-     layout="topleft"
-     left="25"
-     name="panel_water_preset"
-     top="122"
-     visible="true"
-     width="790"/>
-    <tab_container
-     follows="left|top"
-     height="225"
-     halign="center"
-     layout="topleft"
-     left="22"
-     name="WindLight Tabs"
-     tab_position="top"
-     top="101"
-     width="794">
-    <panel
-     border="true"
-     bevel_style="none"
-     follows="left|top|right|bottom"
-     height="196"
-     label="ATMOSPHERE"
-     layout="topleft"
-     left="1"
-     help_topic="sky_preset_atmosphere"
-     mouse_opaque="false"
-     name="Atmosphere"
-     top="60"
-     width="698">
-
-         <!--======== Tab Panel I. I conlumn of controls ========--> 
-
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         font="SansSerif"
-         height="16"
-         layout="topleft"
-         left="40"
-         name="BHText"
-         top="25"
-         width="200">
-           Blue Horizon
-        </text>
-        <color_swatch
-         can_apply_immediately="true"
-         follows="left|top"
-         height="37"
-         label_height="0"
-         layout="topleft"
-         left_delta="0"
-         name="WLBlueHorizon"
-         top_pad="6"
-         width="60" />
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         font="SansSerif"
-         height="16"
-         layout="topleft"
-         left_delta="0"
-         top_pad="20"
-         name="BDensText"
-         width="200">
-            Haze Horizon
-        </text>
-        <slider
-         control_name="WLHazeHorizon"
-         decimal_digits="2"
-         follows="left|top"
-         height="10"
-         increment="0.01"
-         initial_value="0.25"
-         layout="topleft"
-         left_delta="0"
-         top_pad="6"
-         name="WLHazeHorizon"
-         width="200" />
-
-         <!--======== Tab Panel I. II conlumn of controls ========-->
-
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         font="SansSerif"
-         height="16"
-         layout="topleft"
-         left_pad="55"
-         name="BDensText2"
-         top="25"
-         width="200">
-            Blue Density
-        </text>
-        <color_swatch
-         can_apply_immediately="true"
-         follows="left|top"
-         height="37"
-         label_height="0"
-         layout="topleft"
-         left_delta="0"
-         name="WLBlueDensity"
-         top_pad="6"
-         width="60" />
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         font="SansSerif"
-         height="16"
-         layout="topleft"
-         left_delta="0"
-         name="HDText"
-         top_pad="20"
-         width="200">
-            Haze Density
-        </text>
-        <slider
-         control_name="WLHazeDensity"
-         decimal_digits="2"
-         follows="left|top"
-         height="10"
-         increment="0.01"
-         initial_value="0.7"
-         layout="topleft"
-         left_delta="0"
-         max_val="4"
-         name="WLHazeDensity"
-         top_pad="6"
-         width="200" />
-
-             <!--======== Tab Panel I. III conlumn of controls ========-->
-
-        <text
-         type="string"
-         length="1"
-         follows="left|top"
-         font="SansSerif"
-         height="16"
-         layout="topleft"
-         left_pad="55"
-         name="DensMultText"
-         top="25"
-         width="200">
-           Density Multiplier
-        </text>
-            <slider
-             control_name="WLDensityMult"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.1"
-             layout="topleft"
-             left_delta="15"
-             max_val="0.9"
-             name="WLDensityMult"
-             top_pad="6"
-             width="200" />
-            
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-15"
-             name="WLDistanceMultText"
-             top_pad="20"
-             width="200">
-                Distance Multiplier
-            </text>
-            <slider
-             control_name="WLDistancMult"
-             decimal_digits="1"
-             follows="left|top"
-             height="10"
-             initial_value="1.0"
-             layout="topleft"
-             left_delta="15"
-             max_val="100"
-             name="WLDistanceMult"
-             top_pad="6"
-             width="200" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-15"
-             name="MaxAltText"
-             top_pad="20"
-             width="200">
-                Max Altitude
-            </text>
-            <slider
-             control_name="WLMaxAltitude"
-             decimal_digits="0"
-             follows="left|top"
-             height="10"
-             increment="1"
-             initial_value="500"
-             layout="topleft"
-             left_delta="15"
-             max_val="4000"
-             name="WLMaxAltitude"
-             top_pad="6"
-             width="200" />
-        </panel>
-        <panel
-         border="true"
-         bevel_style="none"
-         follows="left|top|right|bottom"
-         height="196"
-         label="LIGHTING"
-         layout="topleft"
-         left_delta="0"
-         help_topic="sky_preset_lighting"
-         name="Lighting"
-         top_delta="4"
-         width="698">
-
-         <!--======== Tab Panel II. I conlumn of controls ========-->
-
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left="20"
-             name="SLCText"
-             top="25"
-             width="150">
-                Sun/Moon Color
-            </text>
-            <color_swatch
-             can_apply_immediately="true"
-             follows="left|top"
-             height="37"
-             label_height="0"
-             layout="topleft"
-             left_delta="10"
-             name="WLSunlight"
-             top_pad="6"
-             width="60" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-10"
-             name="WLAmbientText"
-             top_pad="20"
-             width="150">
-                Ambient
-            </text>
-            <color_swatch
-             can_apply_immediately="true"
-             follows="left|top"
-             height="37"
-             label_height="0"
-             layout="topleft"
-             left_delta="10"
-             name="WLAmbient"
-             top_pad="6"
-             width="60" />
-
-            <!--======== Tab Panel II. II conlumn of controls ========-->
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_pad="100"
-             name="SunGlowText"
-             top="25"
-             width="200">
-                Sun Glow
-            </text>
-            <slider
-             control_name="WLGlowB"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.1"
-             label="Focus "
-             layout="topleft"
-             left_delta="10"
-             max_val="0.5"
-             name="WLGlowB"
-             top_pad="6"
-             width="200" />
-            <slider
-             control_name="WLGlowR"
-             decimal_digits="2"
-             follows="top|left"
-             height="10"
-             increment="0.01"
-             initial_value="0.25"
-             label="Size    "
-             layout="topleft"
-             left_delta="0"
-             max_val="1.99"
-             min_val="1"
-             name="WLGlowR"
-             top_pad="6"
-             width="200" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-10"
-             name="WLStarText"
-             top_pad="20"
-             width="200">
-                Star Brightness
-            </text>
-            <slider
-             control_name="WLStarAlpha"
-             decimal_digits="2"
-             follows="top|left"
-             height="10"
-             increment="0.01"
-             initial_value="0"
-             layout="topleft"
-             left_delta="10"
-             max_val="2"
-             name="WLStarAlpha"
-             top_pad="6"
-             width="200" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-10"
-             name="SceneGammaText"
-             top_pad="20"
-             width="200">
-                Scene Gamma
-            </text>
-            <slider
-             control_name="WLGamma"
-             decimal_digits="2"
-             follows="top|left"
-             height="10"
-             increment="0.01"
-             initial_value="2.0"
-             layout="topleft"
-             left_delta="10"
-             max_val="10"
-             name="WLGamma"
-             top_pad="6"
-             width="200" />
-
-            <!--======== Tab Panel II. III conlumn of controls ========-->
-
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_pad="60"
-             name="TODText"
-             top="25"
-             width="200">
-                Sun/Moon Position
-            </text>
-            <multi_slider
-             can_edit_text="true"
-             control_name="WLSunPos"
-             decimal_digits="0"
-             follows="bottom"
-             height="10"
-             increment="0.0833333"
-             initial_value="0"
-             layout="topleft"
-             left_delta="0"
-             max_sliders="1"
-             max_val="24"
-             name="WLSunPos"
-             show_text="false"
-             top_pad="0"
-             width="300" />
-
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             font="SansSerif"
-             height="14"
-             layout="topleft"
-             left_delta="2"
-             name="WL12amHash"
-             top_pad="6"
-             width="6">
-                |
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             font="SansSerif"
-             height="14"
-             layout="topleft"
-             left_pad="66"
-             name="WL6amHash"
-             top_delta="0"
-             width="6">
-                |
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             font="SansSerif"
-             height="14"
-             layout="topleft"
-             left_pad="67"
-             name="WL12pmHash2"
-             top_delta="0"
-             width="6">
-                |
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             font="SansSerif"
-             height="14"
-             layout="topleft"
-             left_pad="67"
-             name="WL6pmHash"
-             top_delta="0"
-             width="6">
-                |
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             font="SansSerif"
-             height="14"
-             layout="topleft"
-             left_pad="67"
-             name="WL12amHash2"
-             top_delta="0"
-             width="6">
-             |
-            </text>
-
-
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             height="16"
-             layout="topleft"
-             left_delta="-300"
-             name="WL12am"
-             top="74"
-             width="55">
-             12am
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             height="16"
-             layout="topleft"
-             left_pad="20"
-             name="WL6am"
-             top_delta="0"
-             width="55">
-                6am
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             height="16"
-             layout="topleft"
-             left_pad="15"
-             name="WL12pmHash"
-             top_delta="0"
-             width="55">
-                12pm
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             height="16"
-             layout="topleft"
-             left_pad="18"
-             name="WL6pm"
-             top_delta="0"
-             width="55">
-                6pm
-            </text>
-            <text
-             type="string"
-             length="1"
-             border_visible="true"
-             follows="left|top|right"
-             height="16"
-             layout="topleft"
-             left_pad="15"
-             name="WL12am2"
-             top_delta="0"
-             width="55">
-                12am
-            </text>
-
-            <time
-             follows="left|top"
-             height="16"
-             label_width="0"
-             layout="topleft"
-             left_delta="-175"
-             name="WLDayTime"
-             top_pad="15"
-             value="6:00 AM"
-             width="75"/> 
-
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-106"
-             name="WLEastAngleText"
-             top_pad="24"
-             width="200">
-                East Angle
-            </text>
-            <slider
-             control_name="WLEastAngle"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.0"
-             layout="topleft"
-             left_delta="10"
-             name="WLEastAngle"
-             top_pad="6"
-             width="200" />
-
-        </panel>
-        <panel
-         border="true"
-         bevel_style="none"
-         follows="left|top|right|bottom"
-         height="196"
-         label="CLOUDS"
-         layout="topleft"
-         left_delta="0"
-         mouse_opaque="false"
-         help_topic="sky_preset_clouds"
-         name="Clouds"
-         top_delta="4"
-         width="698">
-
-            <!--======== Tab Panel III. I conlumn of controls ========-->
-
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left="40"
-             name="WLCloudColorText"
-             top="25"
-             width="200">
-                Cloud Color
-            </text>
-            <color_swatch
-             can_apply_immediately="true"
-             follows="left|top"
-             height="37"
-             label_height="0"
-             layout="topleft"
-             left_delta="0"
-             name="WLCloudColor"
-             top_pad="6"
-             width="60" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="0"
-             name="WLCloudColorText2"
-             top_pad="20"
-             width="200">
-                Cloud XY/Density
-            </text>
-            <slider
-             control_name="WLCloudX"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             label="X"
-             layout="topleft"
-             left_delta="0"
-             top_pad="6"
-             name="WLCloudX"
-             width="200" />
-            <slider
-             control_name="WLCloudY"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             label="Y"
-             layout="topleft"
-             left_delta="0"
-             top_pad="6"
-             name="WLCloudY"
-             width="200" />
-            <slider
-             control_name="WLCloudDensity"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="1.0"
-             label="D"
-             layout="topleft"
-             left_delta="0"
-             name="WLCloudDensity"
-             top_pad="6"
-             width="200" />
-            
-            <!--======== Tab Panel III. II conlumn of controls ========-->
-            
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_pad="55"
-             name="WLCloudCoverageText"
-             top="15"
-             width="200">
-                Cloud Coverage
-            </text>
-            <slider
-             control_name="WLCloudCoverage"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             layout="topleft"
-             left_delta="15"
-             name="WLCloudCoverage"
-             top_pad="6"
-             width="200" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-15"
-             name="WLCloudScaleText"
-             top_pad="20"
-             width="200">
-                Cloud Scale
-            </text>
-            <slider
-             control_name="WLCloudScale"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="1.0"
-             layout="topleft"
-             left_delta="15"
-             min_val="0.01"
-             name="WLCloudScale"
-             top_pad="6"
-             width="200" />
-            
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-13"
-             name="WLCloudDetailText"
-             top_pad="20"
-             width="200">
-                Cloud Detail (XY/Density)
-            </text>
-            <slider
-             control_name="WLCloudDetailX"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             label="X"
-             layout="topleft"
-             left_delta="0"
-             top_pad="6"
-             name="WLCloudDetailX"
-             width="200" />
-            <slider
-             control_name="WLCloudDetailY"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             label="Y"
-             layout="topleft"
-             left_delta="0"
-             name="WLCloudDetailY"
-             top_pad="6"
-             width="200" />
-            <slider
-             control_name="WLCloudDetailDensity"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="1.0"
-             label="D"
-             layout="topleft"
-             left_delta="0"
-             name="WLCloudDetailDensity"
-             top_pad="6"
-             width="200" />
-            
-            <!--======== Tab Panel III. III conlumn of controls ========-->
-            
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_pad="55"
-             name="WLCloudScrollXText"
-             top="15"
-             width="150">
-                Cloud Scroll X
-            </text>
-            <check_box
-             control_name="WLCloudLockX"
-             follows="left|top"
-             height="16"
-             label="Lock"
-             layout="topleft"
-             left_delta="150"
-             name="WLCloudLockX"
-             top_delta="0"
-             width="200" />
-            <slider
-             control_name="WLCloudScrollX"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             layout="topleft"
-             left_delta="-135"
-             max_val="10"
-             min_val="-10"
-             name="WLCloudScrollX"
-             top_pad="6"
-             width="200" />
-            <text
-             type="string"
-             length="1"
-             follows="left|top"
-             font="SansSerif"
-             height="16"
-             layout="topleft"
-             left_delta="-15"
-             name="WLCloudScrollYText"
-             top_pad="20"
-             width="150">
-                Cloud Scroll Y
-            </text>
-            <check_box
-             control_name="WLCloudLockY"
-             follows="left|top"
-             height="16"
-             label="Lock"
-             layout="topleft"
-             left_delta="150"
-             name="WLCloudLockY"
-             width="200" />
-            <slider
-             control_name="WLCloudScrollY"
-             decimal_digits="2"
-             follows="left|top"
-             height="10"
-             increment="0.01"
-             initial_value="0.5"
-             layout="topleft"
-             left_delta="-135"
-             max_val="10"
-             min_val="-10"
-             name="WLCloudScrollY"
-             top_pad="6"
-             width="200" />
-        </panel>
-    </tab_container>
-<!--======== End of Controls panel ========-->
-
-    <check_box
-     follows="top|left"
-     height="10"
-     label="Make this preset my new sky setting"
-     layout="topleft"
-     left="380"
-     name="make_default_cb"
-     top_pad="30"
-     width="280"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Save"
-     layout="topleft"
-     left_pad="0"
-     name="save"
-     width="70"/>
-    <button
-     follows="bottom|right"
-     height="23"
-     label="Cancel"
-     layout="topleft"
-     left_pad="15"
-     name="cancel"
-     width="70"/>
- </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_edit_water_preset.xml b/indra/newview/skins/default/xui/en/floater_edit_water_preset.xml
deleted file mode 100644
index 905983e7fa2b2b07007b34c4fd3501583428a765..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_edit_water_preset.xml
+++ /dev/null
@@ -1,448 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- height="375"
- layout="topleft"
- name="Edit Water Preset"
- help_topic="water_preset"
- save_rect="true"
- title="Edit Water Preset"
- width="725">
-
-  <string name="title_new">Create a New Water Preset</string>
-  <string name="title_edit">Edit a Water Preset</string>
-  <string name="hint_new">Name your preset, adjust the controls to create it, and click "Save".</string>
-  <string name="hint_edit">To edit your water preset, adjust the controls and click "Save".</string>
-  <string name="combo_label">-Select a preset-</string>
-
-  <text
-   follows="top|left|right"
-   height="10"
-   layout="topleft"
-   left="30"
-   name="hint"
-   top="25"
-   width="680">
-   	To edit your preset, adjust the controls then click "Save"
-   </text>
-   
-   <text
-   follows="top|left|right"
-   font="SansSerif"
-   height="10"
-   layout="topleft"
-   left="30"
-   name="label"
-   top_pad="25"
-   width="120">
-   	Preset Name:
-   </text>
-   
-   <combo_box
-   	allow_text_entry="true"
-   	follows="top|left"
-   	layout="topleft"
-   	left_pad="10"
-   	max_chars="100"
-   	name="water_preset_combo"
-   	top_delta="-5"
-   	width="200"/>
-
-   <line_editor
-    height="20"
-    left_delta="0"
-    name="water_preset_name"
-    top_delta="0"
-    width="200" />
-   
-   <text
-   follows="top|left|right"
-   height="40"
-   layout="topleft"
-   left_pad="10"
-   name="note"
-   top_delta="0"
-   width="340"
-   wrap="true">
-   	Note: if you change the name of your preset, you will be creating a new preset and the existing preset will not be changed.
-   </text>
- 
- <!--======== Controls panel ========-->
- <panel
-  border="false"
-  bevel_style="none"
-  follows="top|left"
-  height="230"
-  layout="topleft"
-  left="10"
-  name="panel_water_preset"
-  top="100"
-  width="700">
- 
-<!--======== I conlumn of controls ========-->   
-   <text
-    follows="left|top|right"
-    height="10"
-    font="SansSerif"
-    layout="topleft"
-    left="10"    
-    name="water_color_label"
-    top="5"
-    width="215">
-       Water Fog Color
-   </text>
-   <color_swatch
-    can_apply_immediately="true"
-    follows="left|top"
-    height="37"
-    label_height="0"
-    layout="topleft"
-    left_delta="15"
-    name="WaterFogColor"
-    top_pad="8"
-    width="60" />
-    
-    
-   <text
-    follows="left|top|right"
-    font="SansSerif"
-    layout="topleft"
-    left_delta="-15"
-    top_pad="10"
-    name="water_fog_density_label"
-    width="215">
-    	Fog Density Exponent
-   </text>
-   <slider
-    decimal_digits="1"
-    follows="left|top"
-    height="10"
-    initial_value="0"
-    layout="topleft"
-    left_delta="15"
-    max_val="10"
-    name="WaterFogDensity"
-    top_pad="10"
-    width="200"/>
-    
-    
-   <text
-    follows="left|top|right"
-    font="SansSerif"
-    layout="topleft"
-    left_delta="-15"
-    top_pad="15"
-    name="underwater_fog_modifier_label"
-    width="215">
-    	Underwater Fog Modifier
-   </text>
-   <slider
-    decimal_digits="1"
-    follows="left|top"
-    height="10"
-    initial_value="0"
-    layout="topleft"
-    left_delta="15"
-    max_val="10"
-    name="WaterUnderWaterFogMod"
-    top_pad="10"
-    width="200"/>
-    
-    
-    <text
-     follows="left|top|right"
-     font="SansSerif"
-     layout="topleft"
-     left_delta="-15"
-     name="BHText"
-     top_pad="15"
-     width="215">
-        Big Wave Direction
-    </text>    
-    <slider
-     control_name="WaterWave1DirX"
-     decimal_digits="2"
-     follows="left|top"
-     increment="0.01"
-     initial_value="0.7"
-     label="X"
-     layout="topleft"             
-     max_val="4"
-     min_val="-4"
-     name="WaterWave1DirX"
-     top_pad="10"
-     width="216"/>    
-    <slider
-     control_name="WaterWave1DirY"
-     decimal_digits="2"
-     follows="left|top"
-     increment="0.01"
-     initial_value="0.7"
-     label="Y"
-     layout="topleft"
-     max_val="4"
-     min_val="-4"
-     name="WaterWave1DirY"
-     top_pad="5"
-     width="216"/>
-    
-<!--======== II conlumn of controls ========-->    
-    
-    <text
-     follows="left|top|right"
-     font="SansSerif"
-     height="10"
-     layout="topleft"
-     left_pad="20"
-     name="BDensText"
-     top="5"
-     width="215">
-        Reflection Wavelet Scale
-    </text>
-    <slider
-     control_name="WaterNormalScaleX"
-     decimal_digits="1"
-     follows="left|top"
-     initial_value="0.7"
-     layout="topleft"
-     left_delta="15"
-     max_val="10"
-     name="WaterNormalScaleX"
-     top_pad="10"
-     width="200"/>
-    <slider
-     control_name="WaterNormalScaleY"
-     decimal_digits="1"
-     follows="left|top"
-     initial_value="0.7"
-     layout="topleft"
-     max_val="10"
-     name="WaterNormalScaleY"
-     top_pad="6"
-     width="200"/>
-    <slider
-     control_name="WaterNormalScaleZ"
-     decimal_digits="1"
-     follows="left|top"
-     initial_value="0.7"
-     layout="topleft"
-     max_val="10"
-     name="WaterNormalScaleZ"
-     top_pad="6"
-     width="200"/>
-    
-    
-    <text
-     follows="left|top|right"
-     font="SansSerif"
-     layout="topleft"
-     left_delta="-15"
-     name="HDText"
-     top_pad="16"
-     width="215">
-        Fresnel Scale
-    </text>
-    <slider
-     control_name="WaterFresnelScale"
-     decimal_digits="2"
-     follows="left|top"
-     height="10"
-     increment="0.01"
-     initial_value="0.7"
-     layout="topleft"
-     left_delta="15"
-     name="WaterFresnelScale"
-     top_pad="10"
-     width="200"/>
-    <text
-     follows="left|top|right"
-     font="SansSerif"
-     layout="topleft"
-     left_delta="-15"
-     name="FresnelOffsetText"
-     top_pad="15"
-     width="215">
-        Fresnel Offset
-    </text>
-    <slider
-     control_name="WaterFresnelOffset"
-     decimal_digits="2"
-     follows="left"
-     increment="0.01"
-     initial_value="0.7"
-     layout="topleft"
-     left_delta="15"
-     name="WaterFresnelOffset"
-     top_pad="10"
-     width="200"/>
-     
-     
-     <text
-      follows="left|top|right"
-      font="SansSerif"
-      layout="topleft"
-      left_delta="-15"
-      name="BHText2"
-      top_pad="15"
-      width="215">
-         Little Wave Direction
-     </text>
-     <slider
-      control_name="WaterWave2DirX"
-      decimal_digits="2"
-      follows="left|top"
-      increment="0.01"
-      initial_value="0.7"
-      label="X"
-      layout="topleft"
-      max_val="4"
-      min_val="-4"
-      name="WaterWave2DirX"
-      top_pad="10"
-      width="216" />
-     <slider
-      control_name="WaterWave2DirY"
-      decimal_digits="2"
-      follows="left|top"
-      increment="0.01"
-      initial_value="0.7"
-      label="Y"
-      layout="topleft"
-      max_val="4"
-      min_val="-4"
-      name="WaterWave2DirY"
-      top_pad="6"
-      width="216" />
-
-<!--======== III conlumn of contorls ========-->
-
-	 <text
-      follows="left|top|right"
-      font="SansSerif"
-      height="16"
-      layout="topleft"
-      left_pad="20"
-      name="DensMultText"
-      top="5"
-      width="215">
-         Refract Scale Above
-     </text>
-     <slider
-      control_name="WaterScaleAbove"
-      decimal_digits="2"
-      follows="left|top"
-      increment="0.01"
-      initial_value="0.1"
-      layout="topleft"
-      left_delta="15"
-      name="WaterScaleAbove"
-      top_pad="5"
-      width="200" />
-     
-     <text
-      type="string"
-      length="1"
-      follows="left|top|right"
-      font="SansSerif"
-      height="16"
-      layout="topleft"
-      left_delta="-15"
-      name="WaterScaleBelowText"
-      top_pad="15"
-      width="215">
-         Refract Scale Below
-     </text>
-     <slider
-      control_name="WaterScaleBelow"
-      decimal_digits="2"
-      follows="left|top"
-      height="10"
-      increment="0.01"
-      initial_value="0"
-      layout="topleft"
-      left_delta="15"
-      name="WaterScaleBelow"
-      top_pad="5"
-      width="200"/>
-     
-     <text
-      follows="left|top|right"
-      font="SansSerif"
-      height="16"
-      layout="topleft"
-      left_delta="-15"
-      name="MaxAltText"
-      top_pad="15"
-      width="215">
-         Blur Multiplier
-     </text>
-     <slider
-      control_name="WaterBlurMult"
-      follows="left|top"
-      height="10"
-      increment="0.001"
-      initial_value="0"
-      layout="topleft"
-      left_delta="15"
-      max_val="0.16"
-      name="WaterBlurMult"
-      top_pad="5"
-      width="200"/>
-      
-      <text
-       follows="left|top|right"
-       font="SansSerif"
-       height="16"
-       layout="topleft"
-       left_delta="-15"
-       name="BHText3"
-       top_pad="15"
-       width="215">
-          Normal Map
-      </text>
-      <texture_picker
-       height="80"
-       layout="topleft"
-       left_delta="15"
-       name="WaterNormalMap"
-       top_pad="5"
-       width="100" />
-	</panel>
-<!--======== End of Controls panel ========-->	
-
-    <view_border
-     bevel_style="none"
-     follows="top|left"
-     height="0"
-     layout="topleft"
-     left="10"
-     name="horiz_separator"
-     top_pad="5"
-     width="700"/>
-	<check_box
-	 follows="top|left"
-	 height="10"
-	 label="Make this preset my new water setting"
-	 layout="topleft"
-	 left="275"
-	 name="make_default_cb"
-	 top_pad="20"
-	 width="280"/>
-	<button
-	 follows="bottom|right"
-	 height="23"
-	 label="Save"
-	 layout="topleft"
-	 left_pad="0"
-	 name="save"
-	 width="70"/>	 
-	<button
-	 follows="bottom|right"
-	 height="23"
-	 label="Cancel"
-	 layout="topleft"
-	 left_pad="15"
-	 name="cancel"
-	 width="70"/>
-	
- </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_environment_settings.xml b/indra/newview/skins/default/xui/en/floater_environment_settings.xml
deleted file mode 100644
index 1b1cafaca6444ff1e6f9cc78df189473877dcd17..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/en/floater_environment_settings.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- height="328"
- layout="topleft"
- name="Environment Editor Floater"
- help_topic="environment_editor_floater"
- save_rect="true"
- title="ENVIRONMENT SETTINGS"
- width="540">
-
- <text
-  follows="top|left|right"
-  height="15"
-  layout="topleft"
-  left="20"
-  name="note"
-  top="25"
-  width="510"
-  wrap="true">
-  Use the options below to customize the environment settings for your viewer.
- </text>
-
- <view_border
-  bevel_style="none"  
-  follows="top|left"
-  height="237"
-  layout="topleft"
-  left="20"
-  name="border"
-  top_pad="8"
-  width="500"/>  
- <radio_group
-  follows="top|left"
-  height="45"
-  layout="topleft"
-  left_delta="10"
-  name="region_settings_radio_group"
-  top_delta="20"
-  width="200">
-    <radio_item
-  	 label="Use region settings"
-  	 layout="topleft"
-  	 name="use_region_settings"/>
-    <radio_item
-  	 label="Customize my environment"
-  	 layout="topleft"
-  	 name="use_my_settings"
-  	 top_pad="20"/>
-  </radio_group>
-
- <panel
-  height="170"
-  layout="topleft"
-  left="50"
-  name="user_environment_settings"
-  top_pad="0"
-  width="470">
-
- <text
-  follows="top|left|right"
-  font="SansSerifItalic"
-  height="15"
-  layout="topleft"
-  left_delta="0"
-  name="note"
-  top_pad="0"
-  width="470"
-  wrap="true">
-  Note: your custom settings will not be visible to other users.
- </text>
-
- <!-- Water Setting -->
- <text
-  name="water_settings_title"
-  follows="top|left"
-  height="16"
-  layout="topleft"
-  left="50"
-  top="40"
-  width="200">
-  		Water Setting
-  </text>
-  <combo_box
-   follows="top|left"
-   left_pad="2"
-   name="water_settings_preset_combo"
-   top_delta="-5"
-   width="200">
-      <combo_box.item
-       label="-Select a preset-"
-       name="item0"/>
-  </combo_box>
- 
-
- <!-- Sky/Day Cycle Settings -->  
- <text
-  name="sky_dayc_settings_title"
-  follows="top|left"
-  height="16"
-  layout="topleft"
-  left="50"
-  top_pad="20"
-  width="100">
-  		Sky / Day Cycle
-  </text>
-  <radio_group
-   layout="topleft"
-   left_delta="50"
-   name="sky_dayc_settings_radio_group"
-   top_pad="10"
-   height="50"
-   width="150">
-  	<radio_item
-  	 layout="topleft"
-  	 label="Fixed sky"
-  	 name="my_sky_settings"/>
-  	<radio_item
-  	 layout="topleft"
-  	 label="Day cycle"
-  	 name="my_dayc_settings"
-  	 top_pad="25"/>  	
-  </radio_group>
-  <combo_box
-   follows="top|left"
-   left_pad="2"
-   name="sky_settings_preset_combo"
-   top_delta="-7"
-   width="200">
-      <combo_box.item
-       label="-Select a preset-"
-       name="item0"/>
-  </combo_box>
-  <combo_box
-   follows="top|left"
-   name="dayc_settings_preset_combo"
-   top_delta="36"
-   width="200">
-      <combo_box.item
-       label="-Select a preset-"
-       name="item0"/>
-  </combo_box>
-  </panel>
-
-  <button
-   follows="left|top"
-   height="23"
-   label="OK"
-   layout="topleft"
-   right="-130"
-   name="ok_btn"
-   top_pad="10"
-   width="100" />
-  <button
-   follows="left|top"
-   height="23"
-   label="Cancel"
-   layout="topleft"
-   left_pad="10"
-   name="cancel_btn"
-   width="100" />	
-</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dbf91b0834fc1eb79bccd99cce3038b801c3a699
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_fixedenvironment.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+        can_tear_off="false"
+        can_resize="false"
+        can_drag_on_left="false"
+        can_close="true"
+        can_dock="false"
+        bevel_style="in"
+        height="550"
+        layout="topleft"
+        name="Fixed Environment"
+        save_rect="true"
+        title="Fixed Environment"
+        save_visibility="false"
+        help_topic="fixed_environment"
+        single_instance="true" 
+        width="750">
+    <string name="edit_sky">Edit Sky:</string>
+    <string name="edit_water">Edit Water:</string>
+    <layout_stack name="floater_stack"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            follows="left|top|right|bottom"
+            orientation="vertical">
+        <layout_panel name="info_panel"
+                auto_resize="false"
+                user_resize="false"
+                min_height="60">
+            <text
+                    follows="left|top"
+                    top_delta="30"
+                    left_delta="10"
+                    width="35"
+                    height="20"
+                    font="SansSerif">
+                Name:
+            </text>
+            <line_editor
+                    follows="left|top"
+                    top_delta="-2"
+                    left_delta="45"
+                    width="250"
+                    name="settings_name"
+                    prevalidate_callback="ascii"
+                    max_length_chars="63"
+                    height="20"/>
+            <button
+                    height="23"
+                    label="Load"
+                    follows="left|top"
+                    left_delta="260"
+                    font="SansSerif"
+                    top_delta="-2"
+                    name="btn_load"
+                    tool_tip="Load a settings from inventory" 
+                    width="96" />
+            <button
+                    height="23"
+                    label="Import"
+                    follows="right|top"
+                    right="-10"
+                    font="SansSerif"
+                    top_delta="0"
+                    name="btn_import"
+                    tool_tip="Import legacy settings from disk." 
+                    width="96" />
+        </layout_panel>
+        <layout_panel name="tab_area"
+                auto_resize="true"
+                user_resize="false"
+                height="11"
+                min_height="0"
+                visible="true">
+            <tab_container
+                    follows="all"
+                    halign="left"
+                    layout="topleft"
+                    left="0"
+                    name="tab_settings"
+                    tab_position="top"
+                    tab_width="120"
+                    tab_padding_right="3">
+                <!-- Tabs inserted here in code -->
+            </tab_container>
+        </layout_panel>
+        <layout_panel name="button_panel"
+                follows="left|top|right|bottom"
+                auto_resize="false"
+                user_resize="false"
+                height="40"
+                visible="true">
+            <layout_stack
+                    follows="bottom|left|right"
+                    height="23"
+                    layout="topleft"
+                    mouse_opaque="false"
+                    name="button_bar_ls"
+                    left="0"
+                    orientation="horizontal"
+                    top="0"
+                    width="313">
+                <layout_panel
+                        follows="bottom|left|right"
+                        height="23"
+                        layout="bottomleft"
+                        left="0"
+                        mouse_opaque="false"
+                        name="save_btn_lp"
+                        auto_resize="true"
+                        width="156">
+                    <button
+                            follows="bottom|left|right"
+                            height="23"
+                            label="Save"
+                            left="1"
+                            layout="topleft"
+                            name="btn_commit"
+                            top="0"
+                            width="155" />
+                    <button
+                            follows="bottom|right"
+                            height="23"
+                            name="btn_flyout"
+                            label=""
+                            layout="topleft"
+                            left_pad="-20"
+                            tab_stop="false"
+                            top="0"
+                            image_selected="SegmentedBtn_Right_Selected_Press"
+                            image_unselected="SegmentedBtn_Right_Off"
+                            image_pressed="SegmentedBtn_Right_Press"
+                            image_pressed_selected="SegmentedBtn_Right_Selected_Press"
+                            image_overlay="Arrow_Small_Up"
+                            width="20"/>
+                </layout_panel>
+                <layout_panel
+                        follows="bottom|left|right"
+                        height="23"
+                        layout="bottomleft"
+                        left_pad="3"
+                        mouse_opaque="false"
+                        name="revert_btn_lp"
+                        auto_resize="true"
+                        width="147">
+                    <button
+                            follows="bottom|right"
+                            height="23"
+                            right="-1"
+                            label="Cancel"
+                            layout="topleft"
+                            name="btn_cancel"
+                            top="0"
+                            tool_tip="Revert to last saved version"
+                            width="147" />
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
+    </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
index ca1d299553b81813f363901bc20b8f46697499eb..a8342e723bc28d35ef6dee32b7d92e55514c7354 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -2,7 +2,7 @@
 <floater
  legacy_header_height="18"
  can_minimize="false"
- height="448"
+ height="488"
  layout="topleft"
  name="Inventory Finder"
  help_topic="inventory_finder"
@@ -195,6 +195,23 @@
      name="check_snapshot"
      top_delta="0"
      width="126" />
+    <icon
+     height="16"
+     image_name="Inv_Settings"
+     layout="topleft"
+     left="8"
+     mouse_opaque="true"
+     name="icon_settings"
+     top="262"
+     width="16" />
+    <check_box
+     height="16"
+     label="Settings"
+     layout="topleft"
+     left_pad="2"
+     name="check_settings"
+     top_delta="0"
+     width="126" />
     <button
      follows="left|top"
      height="20"
@@ -203,7 +220,7 @@
      layout="topleft"
      left="8"
      name="All"
-     top="242"
+     top="282"
      width="100" />
     <button
      height="20"
@@ -257,7 +274,7 @@
      width="260"/>
     <check_box
      height="16"
-     top="332"
+     top="352"
      label="Since Logoff"
      layout="topleft"
      left_delta="0"
@@ -273,7 +290,7 @@
      layout="topleft"
      left_delta="0"
      name="- OR -"
-     top="350"
+     top="370"
      width="144">
         - OR -
     </text>
@@ -281,7 +298,7 @@
      height="16"
      layout="topleft"
      name="date_search_direction"
-     top="368"
+     top="388"
      left="8"
      width="270">
      <radio_item
@@ -351,6 +368,6 @@
      layout="topleft"
      name="Close"
      right="-6"
-     top="414"
+     top="454"
      width="76" />
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_my_environments.xml b/indra/newview/skins/default/xui/en/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6aff387dcb1b360630e52d88879f51f9244f37f8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_my_environments.xml
@@ -0,0 +1,200 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<floater
+        positioning="cascading"
+        save_rect="true"
+        single_instance="true"
+        reuse_instance="true"
+        legacy_header_height="18"
+        can_resize="true"
+        height="465"
+        name="my_environments"
+        help_topic="my_environments"
+        title="MY ENVIRONMENTS"
+        background_visible="true"
+        label="Places"
+        layout="topleft"
+        min_height="350"
+        min_width="265"
+        width="313">
+    <layout_stack 
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="20"
+            right="-5"
+            bottom="-5"
+            orientation="vertical">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="false"
+                tab_group="1"
+                height="54"
+                name="filter_panel"
+                label="Filters"
+                font="SansSerifBold">
+            <icon
+                    height="16"
+                    image_name="Inv_SettingsDay"
+                    layout="topleft"
+                    mouse_opaque="true"
+                    name="icon_settingsdays"
+                    left="4"
+                    width="16" />
+            <check_box
+                    height="16"
+                    label="Days"
+                    layout="topleft"
+                    left_pad="2"
+                    name="chk_days"
+                    top_delta="0"
+                    width="60" />
+            <icon
+                    height="16"
+                    image_name="Inv_SettingsSky"
+                    layout="topleft"
+                    mouse_opaque="true"
+                    name="icon_settingsskies"
+                    left_pad="10"
+                    width="16" />
+            <check_box
+                    height="16"
+                    label="Skies"
+                    layout="topleft"
+                    left_pad="2"
+                    name="chk_skies"
+                    top_delta="0"
+                    width="60" />
+            <icon
+                    height="16"
+                    image_name="Inv_SettingsWater"
+                    layout="topleft"
+                    mouse_opaque="true"
+                    name="icon_settingswater"
+                    left_pad="10"
+                    width="16" />
+            <check_box
+                    height="16"
+                    label="Water"
+                    layout="topleft"
+                    left_pad="2"
+                    name="chk_water"
+                    top_delta="0"
+                    width="60" />
+          <filter_editor
+                  follows="left|top|right"
+                  height="23"
+                  label="Filter Environments"
+                  layout="topleft"
+                  left="4"
+                  name="flt_search"
+                  top_pad="6"
+                  right="-4" />
+        </layout_panel>
+        <layout_panel
+                auto_resize="true"
+                user_resize="true"
+                tab_group="1"
+                name="list_panel"
+                label="Environments"
+                font="SansSerifBold">
+            <panel
+                    name="pnl_inv_wrap"
+                    label="pnl_inv_wrap"
+                    follows="all"
+                    layout="topleft"
+                    left="2"
+                    top="2"
+                    right="-2"
+                    bottom="-2"
+                    background_visible="true"
+                    bg_alpha_color="DkGray2"
+                    border="true">
+                <asset_filtered_inv_panel
+                       left="0"
+                       top="0"
+                       right="-1"
+                       bottom="-1"
+                       allow_multi_select="false"
+                       follows="all"
+                       layout="topleft"
+                       name="pnl_settings"
+                       filter_asset_type="settings"/>
+            </panel>
+        </layout_panel>
+        <layout_panel
+                auto_resize="false"
+                user_resize="false"
+                tab_group="1"
+                height="15">
+            <check_box
+                    follows="left|bottom"
+                    height="14"
+                    initial_value="false"
+                    label="Show All Folders"
+                    layout="topleft"
+                    name="chk_showfolders"
+                    top="2"
+                    left_delta="-1"
+                    width="200" />
+        </layout_panel>
+        <layout_panel
+                auto_resize="false"
+                tab_group="1"
+                height="31"
+                name="pnl_control"
+                font="SansSerifBold">
+            <panel
+                    background_visible="true"
+                    bevel_style="none"
+                    top_pad="1"
+                    follows="top|left|right"
+                    height="30"
+                    label="bottom_panel"
+                    layout="topleft"
+                    left="0"
+                    name="pnl_bottom">
+                <menu_button
+                        follows="bottom|left"
+                        height="18"
+                        image_disabled="OptionsMenu_Disabled"
+                        image_selected="OptionsMenu_Press"
+                        image_unselected="OptionsMenu_Off"
+                        layout="topleft"
+                        left="10"
+                        menu_filename="menu_settings_gear.xml"
+                        name="btn_gear"
+                        top="5"
+                        tool_tip="More options"
+                        width="18" />
+                <menu_button
+                        follows="bottom|left"
+                        font="SansSerifBigBold"
+                        height="18"
+                        image_selected="AddItem_Press"
+                        image_unselected="AddItem_Off"
+                        image_disabled="AddItem_Disabled"
+                        layout="topleft"
+                        left_pad="5"
+                        menu_filename="menu_settings_add.xml"
+                        name="btn_newsettings"
+                        tool_tip="Make new setting"
+                        top_delta="0"
+                        width="18" />
+                <button
+                        follows="bottom|right"
+                        font="SansSerifBigBold"
+                        height="18"
+                        image_selected="TrashItem_Press"
+                        image_unselected="TrashItem_Off"
+                        image_disabled="TrashItem_Disabled"
+                        layout="topleft"
+                        name="btn_del"
+                        right="-5"
+                        tool_tip="Remove selected item"
+                        top_delta="0"
+                        width="18" />
+            </panel>
+        </layout_panel>
+    </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_perms_default.xml b/indra/newview/skins/default/xui/en/floater_perms_default.xml
index 1c3af49bfe0c5ef42a4c90923698b6965198194d..49dc719a24f9e78a63297fa7541e6b93d0e888a0 100644
--- a/indra/newview/skins/default/xui/en/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/en/floater_perms_default.xml
@@ -488,6 +488,67 @@
        left_pad="0"
        top_delta="0"
        width="100" />
+      <text
+       name="label_13"
+       type="string"
+       length="1"
+       follows="left|top"
+       height="16"
+       layout="topleft"
+       left="0"
+       tool_tip="Set default permissions for when Environment settings are created"
+       width="100">
+          Settings
+      </text>
+      <icon
+       follows="left|top"
+       height="16"
+       image_name="Inv_Settings"
+       layout="topleft"
+       left_pad="2"
+       width="18"/>
+      <check_box
+       height="16"
+       layout="topleft"
+       name="env_settings_c"
+       left_pad="45"
+       top_delta="0"
+       value="true"
+       enabled="false"
+       width="100">
+      </check_box>
+      <check_box
+       control_name="SettingsNextOwnerModify"
+       height="16"
+       layout="topleft"
+       name="env_settings_m"
+       left_pad="0"
+       top_delta="0"
+       width="100" />
+      <check_box
+       control_name="SettingsNextOwnerTransfer"
+       height="16"
+       layout="topleft"
+       name="env_settings_t"
+       left_pad="0"
+       top_delta="0"
+       width="100" />
+      <check_box
+       enabled="false"
+       height="16"
+       layout="topleft"
+       name="env_settings_s"
+       left_pad="0"
+       top_delta="0"
+       width="120" />
+      <check_box
+       enabled="false"
+       height="16"
+       layout="topleft"
+       name="env_settings_e"
+       left_pad="0"
+       top_delta="0"
+       width="100" />
   </panel>
   <button
    height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_pick_track.xml b/indra/newview/skins/default/xui/en/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d8a9877be23e9dd37ade7f84328ff4c0d5c5c940
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_pick_track.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+
+<floater
+        legacy_header_height="0"
+        can_minimize="false"
+        can_resize="true"
+        height="140"
+        layout="topleft"
+        min_height="140"
+        min_width="225"
+        name="track picker"
+        help_topic="track_picker"
+        title="PICK: TRACK"
+        width="225">
+    <layout_stack name="adjuster"
+            follows="all"
+            animate="false"
+            top="0"
+            left="6"
+            right="-6"
+            bottom="-10"
+            orientation="vertical">
+        <layout_panel name="pnl_desc"
+                border="false"
+                auto_resize="false"
+                user_resize="false"
+                height="11"
+                min_height="10"
+                bg_alpha_color="blue"
+                background_visible="false">
+            <text
+                type="string"
+                length="1"
+                follows="left|top"
+                height="10"
+                layout="topleft"
+                left="5"
+                name="select_description"
+                mouse_opaque="false"
+                top="0"
+                width="300">
+                Select source sky:
+            </text>
+        </layout_panel>
+        <layout_panel name="pnl_traks"
+                border="false"
+                auto_resize="true"
+                user_resize="false"
+                height="29"
+                min_height="29"
+                bg_alpha_color="blue"
+                background_visible="false">
+            <radio_group
+                follows="all"
+                height="60"
+                layout="topleft"
+                top="0"
+                left="3"
+                right="-3"
+                bottom="-3"
+                name="track_selection"
+                width="100">
+                <radio_item
+                    height="20"
+                    label="Sky4 [ALT]"
+                    layout="topleft"
+                    left="0"
+                    name="radio_sky4"
+                    value="4"
+                    top="0"
+                    width="90" />
+                <radio_item
+                    height="20"
+                    label="Sky3 [ALT]"
+                    layout="topleft"
+                    left="0"
+                    name="radio_sky3"
+                    value="3"
+                    top_delta="20"
+                    width="90" />
+                <radio_item
+                    height="20"
+                    label="Sky2 [ALT]"
+                    layout="topleft"
+                    left="0"
+                    name="radio_sky2"
+                    value="2"
+                    top_delta="20"
+                    width="90" />
+                <radio_item
+                    height="20"
+                    label="Ground"
+                    layout="topleft"
+                    left="0"
+                    name="radio_sky1"
+                    value="1"
+                    top_delta="20"
+                    width="90" />
+            </radio_group>
+        </layout_panel>
+        <layout_panel name="pnl_ok_cancel"
+                border="false"
+                auto_resize="false"
+                user_resize="false"
+                height="29"
+                min_height="29">
+            <button
+                    follows="top|left"
+                    height="20"
+                    label="OK"
+                    label_selected="OK"
+                    layout="topleft"
+                    left="2"
+                    top="2"
+                    name="btn_select"
+                    width="100" />
+            <button
+                    follows="top|left"
+                    height="20"
+                    label="Cancel"
+                    label_selected="Cancel"
+                    layout="topleft"
+                    left_delta="110"
+                    top_delta="0"
+                    name="btn_cancel"
+                    width="100" />
+        </layout_panel>
+    </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index bec484a5eaac746c2105036253a1a0e99ef02641..e93568a87e59d11f122ce63948b7c0c487adf52f 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -609,7 +609,7 @@
     top_delta="16"
     width="300">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <check_box
@@ -623,6 +623,7 @@
     top_delta="16"
     width="300" />
 
+  <!-- SL-12594, basic shaders always enabled, no fixed-function GL 
   <check_box
     control_name="VertexShaderEnable"
     height="16"
@@ -637,7 +638,8 @@
     <check_box.commit_callback
       function="Pref.VertexShaderEnable" />
   </check_box>
-
+  -->
+    
   <slider
     control_name="RenderTerrainDetail"
     follows="left|top"
@@ -683,7 +685,7 @@
     top_delta="16"
     width="280">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <check_box
@@ -751,7 +753,7 @@
     top_delta="16"
     width="280">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <slider
@@ -800,7 +802,7 @@
     top_delta="16"
     width="260">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <check_box
@@ -814,7 +816,7 @@
     top_delta="16"
     width="240">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <check_box
@@ -828,8 +830,24 @@
     top_delta="16"
     width="240">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
+  </check_box>
+
+  <!--
+  <check_box
+    control_name="RenderUseAdvancedAtmospherics"
+    height="16"
+    initial_value="true"
+    label="Advanced Atmospherics"
+    layout="topleft"
+    left="480"
+    name="UseAdvancedAtmo"
+    top_delta="16"
+    width="240">
+    <check_box.commit_callback
+      function="Pref.AdvancedAtmosphericsEnable" />
   </check_box>
+  -->
 
   <text
     type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_settings_picker.xml b/indra/newview/skins/default/xui/en/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3a26c3b547c4120bb6cf01a20a6ba933117dd98c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_settings_picker.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+        legacy_header_height="18"
+        can_minimize="false"
+        can_resize="true"
+        height="330"
+        layout="topleft"
+        min_height="330"
+        min_width="225"
+        name="settings picker"
+        help_topic="settings_picker"
+        title="PICK: SETTINGS"
+        width="225">
+
+    <!--  top static -->
+    <floater.string
+            name="pick title">
+        Pick:
+    </floater.string>
+    <floater.string
+            name="pick_track">
+        SELECT TRACK
+    </floater.string>
+    <floater.string
+            name="pick_settings">
+        SELECT SETTINGS
+    </floater.string>
+
+    <floater.string
+            name="track_water">
+        Water
+    </floater.string>
+    <floater.string
+            name="track_ground">
+        Ground
+    </floater.string>
+    <floater.string
+            name="track_sky">
+        Sky[NUM]
+    </floater.string>
+
+    <layout_stack name="test_stack"
+            follows="all"
+            animate="false"
+            top="20"
+            left="6"
+            right="-6"
+            bottom="-10"
+            orientation="vertical">
+        <layout_panel name="inv_list"
+                border="false"
+                auto_resize="true"
+                user_resize="false"
+                height="29"
+                min_height="29"
+                bg_alpha_color="blue"
+                background_visible="false">
+            <filter_editor
+                    follows="left|top|right"
+                    height="23"
+                    label="Filter Settings"
+                    layout="topleft"
+                    left="4"
+                    name="flt_inventory_search"
+                    top="4"
+                    right="-2" />
+            <panel
+              name="pnl_inv_wrap"
+              follows="all"
+              layout="topleft"
+              left="2"
+              top="28"
+              right="-2"
+              bottom="-2"
+              background_visible="true"
+              bg_alpha_color="DkGray2">
+                <asset_filtered_inv_panel
+                    allow_multi_select="false"
+                    allow_drag="false"
+                    accepts_drag_and_drop="false"
+                    suppress_folder_menu="true"
+                    bg_visible="true"
+                    bg_alpha_color="DkGray2"
+                    border="false"
+                    follows="all"
+                    layout="topleft"
+                    left_delta="0"
+                    name="pnl_inventory"
+                    top="1"
+                    right="-4"
+                    bottom="-1"
+                    filter_asset_type="settings" />
+            </panel>
+        </layout_panel>
+        <layout_panel name="pnl_combo"
+                border="false"
+                auto_resize="false"
+                user_resize="false"
+                visible="true"
+                height="29"
+                bg_alpha_color="blue"
+                background_visible="false">
+            <combo_box
+             allow_text_entry="false"
+             follows="left|top"
+             height="23"
+             left="10"
+             max_chars="100"
+             mouse_opaque="true"
+             name="track_selection"
+             enabled="false"
+             top="1"
+             width="190"/>
+        </layout_panel>
+        <layout_panel name="temp"
+                border="false"
+                auto_resize="false"
+                user_resize="false"
+                height="29"
+                min_height="29">
+            <button
+                    follows="top|left"
+                    height="20"
+                    label="OK"
+                    label_selected="OK"
+                    layout="topleft"
+                    left="2"
+                    top="2"
+                    name="btn_select"
+                    width="100" />
+            <button
+                    follows="top|left"
+                    height="20"
+                    label="Cancel"
+                    label_selected="Cancel"
+                    layout="topleft"
+                    left_delta="110"
+                    top_delta="0"
+                    name="btn_cancel"
+                    width="100" />
+        </layout_panel>
+    </layout_stack>
+
+    <!--  middle: inventory mode -->
+    <!--
+
+
+-->     
+    <!-- bottom static -->
+    <!--
+     -->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
index a04050e7eb7987c5b30ccc65c44a66ea999ab07e..a3ed22f42211f15b884f8d1633b77df339558672 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml
@@ -1,226 +1,226 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <floater
- can_resize="true"
- can_close="true"
- bevel_style="in"
- height="300"
- layout="topleft"
- min_height="40"
- min_width="420"
- name="Test Floater"
- title="LAYOUTSTACK TESTS"
- width="420">
-  <layout_stack name="test_stack"
-              left="0"
-              top="0"
-              width="100"
-              height="250"
-              follows="left|top|bottom"
-              orientation="vertical">
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  visible="false"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  visible="true"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-  </layout_stack>
-  <layout_stack name="test_stack"
-              left_pad="5"
-              top="0"
-              width="100"
-              height="250"
-              follows="left|top|bottom"
-              orientation="vertical">
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="100"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  visible="false"
-                  bg_alpha_color="blue"
-                  height="100"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="fixed"
-                  auto_resize="false"
-                  user_resize="true"
-                  height="50"
-                  min_height="10"
-                  bg_alpha_color="green"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="fixed"
+        can_resize="true"
+        can_close="true"
+        bevel_style="in"
+        height="300"
+        layout="topleft"
+        min_height="40"
+        min_width="420"
+        name="Test Floater"
+        title="LAYOUTSTACK TESTS"
+        width="420">
+    <layout_stack name="test_stack"
+            left="0"
+            top="0"
+            width="100"
+            height="250"
+            follows="left|top|bottom"
+            orientation="vertical">
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                visible="false"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                visible="true"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+    </layout_stack>
+    <layout_stack name="test_stack"
+            left_pad="5"
+            top="0"
+            width="100"
+            height="250"
+            follows="left|top|bottom"
+            orientation="vertical">
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="100"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                visible="false"
+                bg_alpha_color="blue"
+                height="100"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="fixed"
+                auto_resize="false"
+                user_resize="true"
+                height="50"
+                min_height="10"
+                bg_alpha_color="green"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="fixed"
                 auto_resize="false"
-                  user_resize="true"
+                user_resize="true"
                 height="50"
                 min_height="10"
                 bg_alpha_color="green"
                 background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="100"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="100"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="100"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="100"
-                  visible="true"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-  </layout_stack>
-  <layout_stack name="test_stack"
-               left_pad="5"
-               top="0"
-               width="100"
-               height="250"
-               follows="left|top|bottom"
-               orientation="vertical">
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  height="11"
-                  bg_alpha_color="blue"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="fixed"
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="100"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="100"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="100"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="100"
+                visible="true"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+    </layout_stack>
+    <layout_stack name="test_stack"
+            left_pad="5"
+            top="0"
+            width="100"
+            height="250"
+            follows="left|top|bottom"
+            orientation="vertical">
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                height="11"
+                bg_alpha_color="blue"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="fixed"
                 auto_resize="false"
-                  user_resize="true"
+                user_resize="true"
                 height="50"
                 bg_alpha_color="green"
                 background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-  </layout_stack>
-  <layout_stack name="test_stack"
-               left_pad="5"
-               top="0"
-               width="100"
-               height="250"
-               follows="left|top|bottom"
-               orientation="vertical">
-    <layout_panel name="fixed"
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+    </layout_stack>
+    <layout_stack name="test_stack"
+            left_pad="5"
+            top="0"
+            width="100"
+            height="250"
+            follows="left|top|bottom"
+            orientation="vertical">
+        <layout_panel name="fixed"
                 auto_resize="false"
-                  user_resize="true"
+                user_resize="true"
                 height="50"
                 bg_alpha_color="green"
                 background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="fixed"
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="fixed"
                 auto_resize="false"
-                  user_resize="true"
+                user_resize="true"
                 height="50"
                 bg_alpha_color="green"
                 background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="fixed"
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="fixed"
                 auto_resize="false"
-                  user_resize="true"
+                user_resize="true"
                 height="50"
                 bg_alpha_color="green"
                 background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="black">fixed</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-    <layout_panel name="flex"
-                  auto_resize="true"
-                  user_resize="true"
-                  bg_alpha_color="blue"
-                  height="11"
-                  min_height="0"
-                  background_visible="true">
-      <text follows="top|left|right" halign="center" text_color="white">flex</text>
-    </layout_panel>
-  </layout_stack>
+            <text follows="top|left|right" halign="center" text_color="black">fixed</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+        <layout_panel name="flex"
+                auto_resize="true"
+                user_resize="true"
+                bg_alpha_color="blue"
+                height="11"
+                min_height="0"
+                background_visible="true">
+            <text follows="top|left|right" halign="center" text_color="white">flex</text>
+        </layout_panel>
+    </layout_stack>
 </floater>
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index d122d7491cfaa83e4d725743afff349054c78623..a52d0a95d600024f32c50d44b19ba028d908379e 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -93,11 +93,22 @@
      height="14"
      layout="topleft"
      left_delta="12"
+     name="size_lbl"
+     top_pad="4">
+        Size:
+    </text>
+
+    <text
+     type="string"
+     length="1"
+     follows="left|top"
+     height="14"
+     layout="topleft"
+     left_delta="0"
      name="unknown"
      top_pad="4">
-        Size: [DIMENSIONS]
+        [DIMENSIONS]
     </text>
-    
 <!--  middle: inventory mode -->
 
     <button
@@ -139,19 +150,20 @@
      image_unselected="eye_button_inactive.tga"
      layout="topleft"
      left_delta="-80"
-     top_delta="-25"
+     top_delta="-10"
      name="Pipette"
      width="28" />
    <text
      follows="left|bottom"
-     height="20"
+     height="40"
      layout="topleft"
      left="8"
      name="preview_disabled"
-     top="266"
+     top="285"
      value="Preview Disabled"
+     word_wrap="true"
      visible="false"
-     width="120" />
+     width="87" />
     <filter_editor
      follows="left|top|right"
      height="23"
@@ -161,7 +173,7 @@
      name="inventory search editor"
      top="20"
      width="231" />
-    <inventory_panel
+    <asset_filtered_inv_panel
      allow_multi_select="false"
      bg_visible="true"
      bg_alpha_color="DkGray2"
@@ -172,7 +184,8 @@
      left_delta="0"
      name="inventory panel"
      top_pad="4"
-     width="231" />
+     width="231"
+     filter_asset_type="texture"/>
      <check_box
      height="14"
      initial_value="false"
@@ -301,7 +314,8 @@
      height="20"
      initial_value="false"
      label="Hide Base Mesh Region"
-     layout="topleft"
+     
+layout="topleft"
      name="hide_base_mesh_region"
      left_delta="0"
      top_pad="10"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 3bdbbb04d78e5646bbc979c32f8f479d4157b003..9aa84c1bac4e5746e0403b234d8ad71d7d8618d0 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -321,6 +321,41 @@
              parameter="eyes" />
         </menu_item_call>
     </menu>
+    <menu
+     label="New Settings"
+     layout="topleft"
+     name="New Settings">
+        <menu_item_call
+         label="New Sky"
+         layout="topleft"
+         name="New Sky">
+            <menu_item_call.on_click
+             function="Inventory.DoCreate"
+             parameter="sky"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+        </menu_item_call>
+        <menu_item_call
+         label="New Water"
+         layout="topleft"
+         name="New Water">
+            <menu_item_call.on_click
+             function="Inventory.DoCreate"
+             parameter="water"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+        </menu_item_call>
+        <menu_item_call
+         label="New Day Cycle"
+         layout="topleft"
+         name="New Day Cycle">
+            <menu_item_call.on_click
+             function="Inventory.DoCreate"
+             parameter="daycycle"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+        </menu_item_call>
+    </menu>
     <menu
      label="Use as default for"
      layout="topleft"
@@ -833,6 +868,25 @@
         <menu_item_call.on_click
          function="Inventory.DoToSelected"
          parameter="take_off" />
+    </menu_item_call>
+    <menu_item_separator
+     layout="topleft" 
+     name="Settings Separator" />
+    <menu_item_call
+            name="Settings Apply Local"
+            layout="topleft"
+            label="Apply Only To Myself">
+        <menu_item_call.on_click 
+                function="Inventory.DoToSelected"
+                parameter="apply_settings_local" />
+    </menu_item_call>
+    <menu_item_call
+            name="Settings Apply Parcel"
+            layout="topleft"
+            label="Apply To Parcel">
+        <menu_item_call.on_click 
+                function="Inventory.DoToSelected"
+                parameter="apply_settings_parcel" />
     </menu_item_call>
 	<menu_item_separator
 	 layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
index 05dd8f827dc958db38c251c3d1847b3710302593..3385a29a6c6260cfee22bf08f869c29c4a78e9c6 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml
@@ -253,4 +253,41 @@
                      parameter="eyes" />
                 </menu_item_call>
             </menu>
-</menu>
+    <menu
+            label="New Settings"
+            layout="topleft"
+            name="New Settings">
+        <menu_item_call
+                label="New Sky"
+                layout="topleft"
+                name="New Sky">
+            <menu_item_call.on_click
+                    function="Inventory.DoCreate"
+                    parameter="sky"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+
+        </menu_item_call>
+        <menu_item_call
+                label="New Water"
+                layout="topleft"
+                name="New Water">
+            <menu_item_call.on_click
+                    function="Inventory.DoCreate"
+                    parameter="water"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+
+        </menu_item_call>
+        <menu_item_call
+                label="New Day Cycle"
+                layout="topleft"
+                name="New Day Cycle">
+            <menu_item_call.on_click
+                    function="Inventory.DoCreate"
+                    parameter="daycycle"/>
+            <menu_item_call.on_enable
+                    function="Inventory.EnvironmentEnabled" />
+        </menu_item_call>
+    </menu>
+</menu>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_save_settings.xml b/indra/newview/skins/default/xui/en/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..84dacaa8b8a535c8c0612b80abb79c5b319963c2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_save_settings.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+        height="602"
+        layout="topleft"
+        mouse_opaque="false"
+        name="save_settings_menu"
+        width="120">
+    <menu_item_check
+            name="save_settings" 
+            label="Save">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="save" />
+        <menu_item_check.on_click
+                function="FlyoutCombo.Button.Action"
+                userdata="save"/>
+    </menu_item_check>
+    <menu_item_check 
+            name="save_as_new_settings" 
+            label="Save As">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="saveas" />
+        <menu_item_check.on_click
+                function="FlyoutCombo.Button.Action"
+                userdata="saveas" />
+    </menu_item_check>
+    <menu_item_check
+            name="commit_changes"
+            label="Commit">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="commit" />
+        <menu_item_check.on_click
+                function="FlyoutCombo.Button.Action"
+                userdata="commit" />
+    </menu_item_check>
+    <menu_item_check
+            name="apply_local"
+            label="Apply Only To Myself">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="local" />
+        <menu_item_check.on_click 
+                function="FlyoutCombo.Button.Action"
+                userdata="local" />
+    </menu_item_check>
+    <menu_item_check
+            name="apply_parcel"
+            label="Apply To Parcel">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="parcel" />
+        <menu_item_check.on_click
+                function="FlyoutCombo.Button.Action"
+                userdata="parcel" />
+    </menu_item_check>
+    <menu_item_check
+            name="apply_region"
+            label="Apply To Region">
+        <menu_item_check.on_check
+                function="FlyoutCombo.Button.Check"
+                userdata="region" />
+        <menu_item_check.on_click
+                function="FlyoutCombo.Button.Action"
+                userdata="region" />
+    </menu_item_check>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_settings_add.xml b/indra/newview/skins/default/xui/en/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4782cfdc351a9409ff68267ddb0f37ae1f8be85
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_settings_add.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+        layout="topleft"
+        mouse_opaque="false"
+        name="menu_settings_add"
+        visible="false">
+    <menu_item_call
+            label="New Sky"
+            layout="topleft"
+            name="New Sky">
+        <menu_item_call.on_click
+                function="MyEnvironments.DoCreate"
+                parameter="sky"/>
+        <menu_item_call.on_enable
+                function="MyEnvironments.EnvironmentEnabled" />
+    </menu_item_call>
+    <menu_item_call
+            label="New Water"
+            layout="topleft"
+            name="New Water">
+        <menu_item_call.on_click
+                function="MyEnvironments.DoCreate"
+                parameter="water"/>
+        <menu_item_call.on_enable
+                function="MyEnvironments.EnvironmentEnabled" />
+    </menu_item_call>
+    <menu_item_call
+            label="New Day Cycle"
+            layout="topleft"
+            name="New Day Cycle">
+        <menu_item_call.on_click
+                function="MyEnvironments.DoCreate"
+                parameter="daycycle"/>
+        <menu_item_call.on_enable
+                function="MyEnvironments.EnvironmentEnabled" />
+    </menu_item_call>
+</toggleable_menu>
\ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/menu_settings_gear.xml b/indra/newview/skins/default/xui/en/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ea8e328407d99cfbe02c1f8e09368be123afb426
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_settings_gear.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<toggleable_menu
+        layout="topleft"
+        mouse_opaque="false"
+        name="menu_settings_gear"
+        visible="false">
+    <menu_item_call
+            label="Edit"
+            layout="topleft"
+            name="edit_settings">
+        <on_click
+                function="MyEnvironments.DoEdit" />
+        <on_enable
+                function="MyEnvironments.EnableAction"
+                parameter="edit" />
+    </menu_item_call>
+    <menu_item_separator
+            layout="topleft" 
+            name="Separator" />
+    <menu_item_call
+            name="Settings Apply Local"
+            layout="topleft"
+            label="Apply Only To Myself">
+        <menu_item_call.on_click 
+                function="MyEnvironments.DoApply"
+                parameter="local" />
+    </menu_item_call>
+    <menu_item_call
+            name="Settings Apply Parcel"
+            layout="topleft"
+            label="Apply To Parcel">
+        <menu_item_call.on_click 
+                function="MyEnvironments.DoApply"
+                parameter="parcel" />
+        <menu_item_call.on_enable
+                function="MyEnvironments.CanApply" 
+                parameter="parcel"/>
+    </menu_item_call>
+    <menu_item_call
+            name="Settings Apply Region"
+            layout="topleft"
+            label="Apply To Region">
+        <menu_item_call.on_click 
+                function="MyEnvironments.DoApply"
+                parameter="region" />
+        <menu_item_call.on_enable
+                function="MyEnvironments.CanApply" 
+                parameter="region"/>
+    </menu_item_call>
+    <menu_item_separator
+            layout="topleft" 
+            name="Separator" />
+    <menu_item_call
+            label="Copy"
+            layout="topleft"
+            name="copy_settings">
+        <on_click
+                function="MyEnvironments.CopyPaste"
+                parameter="copy" />
+        <on_enable
+                function="MyEnvironments.EnableAction"
+                parameter="copy" />
+    </menu_item_call>
+    <menu_item_call
+            label="Paste"
+            layout="topleft"
+            name="paste_settings">
+        <on_click
+                function="MyEnvironments.CopyPaste"
+                parameter="paste" />
+        <on_enable
+                function="MyEnvironments.EnableAction"
+                parameter="paste" />
+    </menu_item_call>
+    <menu_item_call
+            label="Copy UUID"
+            layout="topleft"
+            name="copy_uuid">
+        <on_click
+                function="MyEnvironments.CopyPaste"
+                parameter="copy_uuid" />
+        <on_enable
+                function="MyEnvironments.EnableAction"
+                parameter="copy_uuid" />
+    </menu_item_call>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 2c9bf99fe255f81c89bc38092ba814dd8dda07b5..e228c5bdba3929502ce21fd3f31660c9a645cbc7 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -642,8 +642,8 @@
 
         <menu
          create_jump_keys="true"
-         label="Sun"
-         name="Sun"
+         label="Environment"
+         name="Environment"
          tear_off="true">
             <menu_item_check
              label="Sunrise"
@@ -687,10 +687,9 @@
                  function="World.EnableEnvSettings" 
                  parameter="midnight" />
             </menu_item_check>
-            <menu_item_separator/>
             <menu_item_check
-             label="Use Region Settings"
-             name="Use Region Settings">
+             label="Use Shared Environment"
+             name="Use Shared Environment">
                 <menu_item_check.on_click
                  function="World.EnvSettings"
                  parameter="region" />
@@ -698,113 +697,105 @@
                  function="World.EnableEnvSettings" 
                  parameter="region" />
             </menu_item_check>
-        </menu>
-	    
-   
+        <menu_item_separator/>
+	     	<menu_item_call
+	     	 label="My Environments..."
+	     	 name="my_environs">
+	     	 	<menu_item_call.on_click
+	     	 	 function="World.EnvSettings"
+                 parameter="my_environs" />
+	     	</menu_item_call>
+	     	
+<menu_item_call
+	     	 	 label="Personal Lighting..."
+	     	 	 name="adjustment_tool">
+	     	 	 	<menu_item_call.on_click
+	     	 	 	function="World.EnvSettings"
+	     	 	 	parameter="adjust_tool" />
+	     	 	</menu_item_call>
+	     	 	<menu_item_separator/>
+	     	 	 <menu_item_check
+	     	 	 label="Pause Clouds"
+	     	 	 name="pause_clouds">
+	     	 	 	<menu_item_check.on_click
+	     	 	 	function="World.EnvSettings"
+	     	 	 	parameter="pause_clouds" />
+	     	 	 	<menu_item_check.on_check
+	     	 	 	function="World.EnableEnvSettings" 
+	     	 	 	parameter="pause_clouds" />
+	     	 	</menu_item_check>
+	     	</menu>
+	     	
+<!--   
 	    <menu
 	     create_jump_keys="true"
 	     label="Environment Editor"
 	     name="Environment Editor"
 	     tear_off="true">
-	     	
-	     	<menu_item_call
+	     	 	 		     	<menu_item_call
 	     	 label="Environment Settings..."
 	     	 name="Environment Settings">
-	     	 	<menu_item_call.on_click
+<menu_item_call.on_click
 	     	 	 function="World.EnvSettings"
                  parameter="editor"/>
 	     	</menu_item_call>
-	     	
-	     	<menu_item_separator/>
-	     	
-	     	<menu
+	     		     	<menu_item_separator/>
+<menu
 	     	 name="Water Presets"
 	     	 label="Water Presets">
-	     	 	<menu_item_call
-	     	 	 label="New preset..."
+<menu_item_call
+label="New preset..."
 	     	 	 name="new_water_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="new_water"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Edit preset..."
+</menu_item_call>
+<menu_item_call
+label="Edit preset..."
 	     	 	 name="edit_water_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="edit_water"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Delete preset..."
-	     	 	 name="delete_water_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
-	     	 	 	parameter="delete_water"/>
-	     	 	 	<menu_item_call.on_enable
-	     	 	 	function="World.EnableEnvPreset"
-	     	 	 	parameter="delete_water"/>
-	     	 	</menu_item_call>
-	     	</menu>
-	     	
-	     	<menu
-	     	 name="Sky Presets"
+</menu_item_call>
+</menu>
+	     	 	 <menu
+name="Sky Presets"
 	     	 label="Sky Presets">
-	     	 	<menu_item_call
-	     	 	 label="New preset..."
+<menu_item_call
+label="New preset..."
 	     	 	 name="new_sky_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="new_sky"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Edit preset..."
+</menu_item_call>
+<menu_item_call
+label="Edit preset..."
 	     	 	 name="edit_sky_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="edit_sky"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Delete preset..."
-	     	 	 name="delete_sky_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
-	     	 	 	parameter="delete_sky"/>
-	     	 	 	<menu_item_call.on_enable
-	     	 	 	function="World.EnableEnvPreset"
-	     	 	 	parameter="delete_sky"/>
-	     	 	</menu_item_call>
-	     	</menu>
-	     	
-	     	<menu
-	     	 name="Day Presets"
+</menu_item_call>
+</menu>
+<menu
+name="Day Presets"
 	     	 label="Day Presets">
-	     	 	<menu_item_call
-	     	 	 label="New preset..."
+<menu_item_call
+label="New preset..."
 	     	 	 name="new_day_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="new_day_cycle"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Edit preset..."
+</menu_item_call>
+<menu_item_call
+label="Edit preset..."
 	     	 	 name="edit_day_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
+<menu_item_call.on_click
+function="World.EnvPreset"
 	     	 	 	parameter="edit_day_cycle"/>
-	     	 	</menu_item_call>
-	     	 	<menu_item_call
-	     	 	 label="Delete preset..."
-	     	 	 name="delete_day_preset">
-	     	 	 	<menu_item_call.on_click
-	     	 	 	function="World.EnvPreset"
-	     	 	 	parameter="delete_day_cycle"/>
-	     	 	 	<menu_item_call.on_enable
-	     	 	 	function="World.EnableEnvPreset"
-	     	 	 	parameter="delete_day_cycle"/>
-	     	 	</menu_item_call>
-	     	</menu>
-	    </menu>
-    
+</menu_item_call>
+</menu>
+</menu>
+-->    
     
     </menu>
     <menu
@@ -1034,8 +1025,7 @@
            shortcut="control|D">
             <menu_item_call.on_click
                function="Object.Duplicate" />
-
-          </menu_item_call>
+                      </menu_item_call>
 		</menu>
         <menu
            create_jump_keys="true"
@@ -2941,6 +2931,36 @@
                  function="ToggleControl"
                  parameter="TextureDisable" />
             </menu_item_check>
+            <menu_item_check
+              label="Disable Ambient"
+             name="Disable Ambient">
+            <menu_item_check.on_check
+             function="CheckControl"
+             parameter="AmbientDisable" />
+            <menu_item_check.on_click
+             function="ToggleShaderControl"
+             parameter="AmbientDisable" />
+          </menu_item_check>
+          <menu_item_check
+             label="Disable Sunlight"
+             name="Disable Sunlight">
+            <menu_item_check.on_check
+             function="CheckControl"
+             parameter="SunlightDisable" />
+            <menu_item_check.on_click
+             function="ToggleShaderControl"
+             parameter="SunlightDisable" />
+          </menu_item_check>
+          <menu_item_check
+             label="Disable Local Lights"
+             name="Disable Local Lights">
+            <menu_item_check.on_check
+             function="CheckControl"
+             parameter="LocalLightDisable" />
+            <menu_item_check.on_click
+             function="ToggleShaderControl"
+             parameter="LocalLightDisable" />
+          </menu_item_check>
             <menu_item_check
               label="Full Res Textures"
              name="Rull Res Textures">
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 2ae3d76d08cc4dc5c9959243790035246f7ec198..98bb77d9e0aa79cc902c6f29363c6b32d56856cb 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5016,6 +5016,20 @@ Unchecking this option may remove restrictions that parcel owners have added to
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="alertmodal.tga"
+   name="EstateParcelEnvironmentOverride"
+   type="alertmodal">
+(Estate-wide change: [ESTATENAME]) Unchecking this option will remove any custom environments that parcel owners have added to their parcels. Please discuss with your parcel owners as needed.
+Do you wish to proceed?
+    <tag>confirm</tag>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="Cancel"
+     yestext="OK"/>
+  </notification>
+  
+  
   <notification
    icon="alertmodal.tga"
    name="RegionEntryAccessBlocked"
@@ -6317,7 +6331,23 @@ This day cycle file references a missing sky file: [SKY].
    icon="alertmodal.tga"
    name="WLRegionApplyFail"
    type="alertmodal">
-Sorry, the settings couldn't be applied to the region.  Leaving the region and then returning may help rectify the problem.  The reason given was: [FAIL_REASON]
+Sorry, the settings couldn't be applied to the region. Reason: [FAIL_REASON]
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="WLLocalTextureDayBlock"
+   type="alertmodal">
+A Local texture is in use on track [TRACK], frame #[FRAMENO] ([FRAME]%) in field [FIELD].
+Settings may not be saved using local textures.
+  </notification>
+    
+  <notification
+   icon="alertmodal.tga"
+   name="WLLocalTextureFixedBlock"
+   type="alertmodal">
+A local texture is in use in field [FIELD].
+Settings may not be saved using local textures.
   </notification>
 
   <notification
@@ -11434,4 +11464,190 @@ Cannot create large prims that intersect other residents.  Please re-try when ot
      yestext="OK"/>
   </notification>
 
+  <notification
+   icon="notify.tga"
+   name="FailedToFindSettings"
+   persist="true"
+   type="alertmodal">
+Could not load the settings for [NAME] from the database.
+  <tag>fail</tag>
+  </notification>
+  
+  <notification
+   icon="notify.tga"
+   name="FailedToLoadSettingsApply"
+   persist="true"
+   type="alertmodal">
+Unable to apply those settings to the environment.
+  <tag>fail</tag>
+  </notification>
+  
+  <notification
+   icon="notify.tga"
+   name="FailedToBuildSettingsDay"
+   persist="true"
+   type="alertmodal">
+Unable to apply those settings to the environment.
+  <tag>fail</tag>
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="NoEnvironmentSettings"
+   persist="true"
+   type="alertmodal">
+This Region does not support environmental settings.
+  <tag>fail</tag>
+  </notification>
+ 
+  <notification
+   icon="alertmodal.tga"
+   label="Save Outfit"
+   name="SaveSettingAs"
+   type="alertmodal">
+    <unique/>
+    Save current environmental settings as:
+    <tag>confirm</tag>
+    <form name="form">
+      <input name="message" type="text">
+        [DESC] (new)
+      </input>
+      <button
+       default="true"
+       index="0"
+       name="OK"
+       text="OK"/>
+      <button
+       index="1"
+       name="Cancel"
+       text="Cancel"/>
+    </form>
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="WLImportFail"
+   persist="true"
+   type="alertmodal">
+Unable to import legacy Windlight settings [NAME] from 
+[FILE].
+
+[REASONS]
+  <tag>fail</tag>
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="WLParcelApplyFail"
+   persist="true"
+   type="alertmodal">
+Unable to set the environment for this parcel.
+Please enter or select a parcel that you have rights to modify.
+  <tag>fail</tag>
+  </notification>
+
+  <notification
+   icon="notify.tga"
+   name="SettingsUnsuported"
+   persist="true"
+   type="alertmodal">
+Settings are not supported on this region. 
+Please move to a settings enabled region and retry your action.
+  <tag>fail</tag>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SettingsConfirmLoss"
+   type="alertmodal">
+You are about to lose the changes you have made to this [TYPE] named "[NAME]".
+Are you sure you want to continue?
+    <tag>confirm</tag>
+    <usetemplate
+     ignoretext="Are you sure you want to lose changes?"
+     name="okcancelignore"
+     notext="No"
+     yestext="Yes"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SettingsConfirmReset"
+   type="alertmodal">
+You are about to remove all applied settings.
+Are you sure you want to continue?
+    <tag>confirm</tag>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="No"
+     yestext="Yes"/>
+  </notification>
+
+  <notification
+ icon="alertmodal.tga"
+ name="PersonalSettingsConfirmReset"
+ type="alertmodal">
+You are about to remove all applied Personal lighting settings.
+Are you sure you want to continue?
+    <tag>confirm</tag>
+    <usetemplate
+     name="okcancelbuttons"
+     notext="No"
+     yestext="Yes"/>
+  </notification>
+
+  <notification
+   icon="alertmodal.tga"
+   name="SettingsMakeNoTrans"
+   type="alertmodal">
+You are about to import non-transferable settings into this daycycle. Continuing will cause the settings you are editing to become non-transferable also. 
+
+This change can not be undone.
+
+Are you sure you want to continue?
+    <tag>confirm</tag>
+    <usetemplate
+     ignoretext="Are you sure you want to make settings non-transferable?"
+     name="okcancelignore"
+     notext="No"
+     yestext="Yes"/>
+  </notification>
+  
+  <notification
+   icon="notify.tga"
+   name="NoEditFromLibrary"
+   persist="true"
+   type="alertmodal">
+You may not edit settings directly from the libary.  
+Please copy to your own inventory and try again.
+  <tag>fail</tag>
+  </notification>
+
+    <notification
+   icon="notify.tga"
+   name="EnvironmentApplyFailed"
+   persist="true"
+   type="alertmodal">
+We have encountered an issue with these settings.  They can not be saved or applied at this time.
+  <tag>fail</tag>
+  </notification>
+
+    <notification
+   icon="notify.tga"
+   name="TrackLoadFailed"
+   persist="true"
+   type="alertmodal">
+Unable to load the track into [TRACK].
+  <tag>fail</tag>
+  </notification>
+
+    <notification
+   icon="notify.tga"
+   name="TrackLoadMismatch"
+   persist="true"
+   type="alertmodal">
+Unable to load the track from [TRACK1] into [TRACK2].
+  <tag>fail</tag>
+  </notification>
+  
 </notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
index 3f13cea58e8d4639df0b7e11c80b1ad317c372b7..afce9f6eb56632cb8fcf4e800d6742de6e2dd031 100644
--- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml
@@ -1,556 +1,556 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 <!-- Side tray Outfit Edit panel -->
 <panel
- background_visible="true"
- border="false"
- height="600"
- follows="all"
- layout="topleft"
- help_topic="edit_outfit"
- left="0"
- min_height="350"
- name="outfit_edit"
- top="0"
- width="320">
-	<string
-	 name="No Outfit"
-	 value="No Outfit"/>
-	<string
-	 name="unsaved_changes"
-	 value="Unsaved Changes"/>
-	<string
-	 name="now_editing"
-	 value="Now Editing"/>
-	<string
-	 name="folder_view_off"
-	 value="Hierarchy_View_Disabled"
-	 translate="false"/>
-	<string
-	 name="folder_view_on"
-	 value="Hierarchy_View_On"
-	 translate="false"/>
-	<string
-	 name="list_view_off"
-	 value="List_View_Disabled"
-	 translate="false"/>
-	<string
-	 name="list_view_on"
-	 value="List_View_On"
-	 translate="false"/>
+        background_visible="true"
+        border="false"
+        height="600"
+        follows="all"
+        layout="topleft"
+        help_topic="edit_outfit"
+        left="0"
+        min_height="350"
+        name="outfit_edit"
+        top="0"
+        width="320">
+    <string
+            name="No Outfit"
+            value="No Outfit"/>
+    <string
+            name="unsaved_changes"
+            value="Unsaved Changes"/>
+    <string
+            name="now_editing"
+            value="Now Editing"/>
+    <string
+            name="folder_view_off"
+            value="Hierarchy_View_Disabled"
+            translate="false"/>
+    <string
+            name="folder_view_on"
+            value="Hierarchy_View_On"
+            translate="false"/>
+    <string
+            name="list_view_off"
+            value="List_View_Disabled"
+            translate="false"/>
+    <string
+            name="list_view_on"
+            value="List_View_On"
+            translate="false"/>
 
-	<panel.string
-		name="not_available">
-		(N\A)
-	</panel.string>
-	<panel.string
-		name="unknown">
-		(unknown)
-	</panel.string>
+    <panel.string
+            name="not_available">
+        (N\A)
+    </panel.string>
+    <panel.string
+            name="unknown">
+        (unknown)
+    </panel.string>
 
-	<!-- Wearables filtering strings -->
-	<string name="Filter.All" value="All"/>
-	<string name="Filter.Clothes/Body" value="Clothes/Body"/>
-	<string name="Filter.Objects" value="Objects"/>
-	<string name="Filter.Clothing" value="Clothing"/>
-	<string name="Filter.Bodyparts" value="Body parts"/>
+    <!-- Wearables filtering strings -->
+    <string name="Filter.All" value="All"/>
+    <string name="Filter.Clothes/Body" value="Clothes/Body"/>
+    <string name="Filter.Objects" value="Objects"/>
+    <string name="Filter.Clothing" value="Clothing"/>
+    <string name="Filter.Bodyparts" value="Body parts"/>
 
-	<string
-	 name="replace_body_part"
-	 value="Click to replace your existing shape"/>
+    <string
+            name="replace_body_part"
+            value="Click to replace your existing shape"/>
 
 
-	<button
-	 follows="top|left"
-	 height="24"
-	 image_hover_unselected="BackButton_Over"
-	 image_pressed="BackButton_Press"
-	 image_unselected="BackButton_Off"
-	 layout="topleft"
-	 name="back_btn"
-	 left="5"
-	 tab_stop="false"
-	 top="1"
-	 width="30"
-	 use_draw_context_alpha="false" />
-	<text
-	 follows="top|left|right"
-	 font="SansSerifHugeBold"
-	 height="26"
-	 layout="topleft"
-	 left_pad="10"
-	 name="title"
-	 text_color="LtGray"
-	 top="0"
-	 value="Edit Outfit"
-	 use_ellipses="true"
-	 width="275" />
+    <button
+            follows="top|left"
+            height="24"
+            image_hover_unselected="BackButton_Over"
+            image_pressed="BackButton_Press"
+            image_unselected="BackButton_Off"
+            layout="topleft"
+            name="back_btn"
+            left="5"
+            tab_stop="false"
+            top="1"
+            width="30"
+            use_draw_context_alpha="false" />
+    <text
+            follows="top|left|right"
+            font="SansSerifHugeBold"
+            height="26"
+            layout="topleft"
+            left_pad="10"
+            name="title"
+            text_color="LtGray"
+            top="0"
+            value="Edit Outfit"
+            use_ellipses="true"
+            width="275" />
 
-	<!-- "HEADER WITH ICON, STATUS TEXT AND OUTFIT NAME" -->
-	<panel
-	 background_visible="true"
-	 bg_alpha_color="DkGray2"
-	 bevel_style="none"
-	 follows="top|left|right"
-	 height="40"
-	 layout="topleft"
-	 left="6"
-	 name="header_panel"
-	 top_pad="5"
-	 width="311">
-		<icon
-		 follows="left|top"
-		 height="31"
-		 image_name="Shirt_Large"
-		 left="2"
-		 mouse_opaque="false"
-		 name="outfit_icon"
-		 top="2"
-		 scale_image="true"
-		 visible="true"
-		 width="31" />
-		<panel
-		 bevel_style="none"
-		 follows="top|left|right"
-		 height="37"
-		 layout="topleft"
-		 left_pad="5"
-		 name="outfit_name_and_status"
-		 top="2"
-		 width="270">
-			<text
-			 follows="top|left|right"
-			 font="SansSerifSmallBold"
-			 height="13"
-			 layout="topleft"
-			 name="status"
-			 text_color="EmphasisColor"
-			 top="2"
-			 value="Now editing..."
-			 use_ellipses="true"
-			 width="245" />
-			<text
-			 follows="bottom|left|right"
-			 font="SansSerifLargeBold"
-			 height="18"
-			 layout="topleft"
-			 name="curr_outfit_name"
-			 parse_urls="false"
-			 text_color="LtGray"
-			 top_pad="2"
-			 value="[Current Outfit]"
-			 use_ellipses="true"
-			 width="245" />
-			<loading_indicator
-			 follows="right|top"
-			 height="24"
-			 layout="topleft"
-			 right="-2"
-			 name="edit_outfit_loading_indicator"
-			 top="6"
-			 width="24" />
-		</panel>
-	</panel>
+    <!-- "HEADER WITH ICON, STATUS TEXT AND OUTFIT NAME" -->
+    <panel
+            background_visible="true"
+            bg_alpha_color="DkGray2"
+            bevel_style="none"
+            follows="top|left|right"
+            height="40"
+            layout="topleft"
+            left="6"
+            name="header_panel"
+            top_pad="5"
+            width="311">
+        <icon
+                follows="left|top"
+                height="31"
+                image_name="Shirt_Large"
+                left="2"
+                mouse_opaque="false"
+                name="outfit_icon"
+                top="2"
+                scale_image="true"
+                visible="true"
+                width="31" />
+        <panel
+                bevel_style="none"
+                follows="top|left|right"
+                height="37"
+                layout="topleft"
+                left_pad="5"
+                name="outfit_name_and_status"
+                top="2"
+                width="270">
+            <text
+                    follows="top|left|right"
+                    font="SansSerifSmallBold"
+                    height="13"
+                    layout="topleft"
+                    name="status"
+                    text_color="EmphasisColor"
+                    top="2"
+                    value="Now editing..."
+                    use_ellipses="true"
+                    width="245" />
+            <text
+                    follows="bottom|left|right"
+                    font="SansSerifLargeBold"
+                    height="18"
+                    layout="topleft"
+                    name="curr_outfit_name"
+                    parse_urls="false"
+                    text_color="LtGray"
+                    top_pad="2"
+                    value="[Current Outfit]"
+                    use_ellipses="true"
+                    width="245" />
+            <loading_indicator
+                    follows="right|top"
+                    height="24"
+                    layout="topleft"
+                    right="-2"
+                    name="edit_outfit_loading_indicator"
+                    top="6"
+                    width="24" />
+        </panel>
+    </panel>
 
 
-	<!-- LIST OF WEARABLES (CURRENT OUTFIT/ WEARABLES TO ADD) -->
-	<!-- *NOTE: border_size is used to calculate space between layout panels and also to calculate resize bar's height.
+    <!-- LIST OF WEARABLES (CURRENT OUTFIT/ WEARABLES TO ADD) -->
+    <!-- *NOTE: border_size is used to calculate space between layout panels and also to calculate resize bar's height.
 Required height for dragbar (icon in spec) is 10, so resizebar height should be 10 px.
 It is calculated as border_size + 2*UIResizeBarOverlap
 -->
-	<layout_stack
-	 animate="true"
-	 border_size="8"
-	 clip="false"
-	 default_tab_group="2"
-	 follows="all"
-	 height="465"
-	 width="313"
-	 layout="topleft"
-	 orientation="vertical"
-	 name="im_panels"
-	 tab_group="1"
-	 top_pad="5"
-	 left="5">
-		<layout_panel
-		 layout="topleft"
-		 height="187"
-		 min_height="155"
-		 name="outfit_wearables_panel"
-		 width="313"
-		 auto_resize="true"
-		 user_resize="true">
+    <layout_stack
+            animate="true"
+            border_size="8"
+            clip="false"
+            default_tab_group="2"
+            follows="all"
+            height="465"
+            width="313"
+            layout="topleft"
+            orientation="vertical"
+            name="im_panels"
+            tab_group="1"
+            top_pad="5"
+            left="5">
+        <layout_panel
+                layout="topleft"
+                height="187"
+                min_height="155"
+                name="outfit_wearables_panel"
+                width="313"
+                auto_resize="true"
+                user_resize="true">
 
-			<layout_stack
-			 animate="true"
-			 border_size="0"
-			 follows="all"
-			 height="185"
-			 width="313"
-			 orientation="vertical"
-			 layout="topleft"
-			 name="filter_panels"
-			 top="0"
-			 left="0">
-				<layout_panel
-				 auto_resize="true"
-				 background_visible="false"
-				 layout="topleft"
-				 height="154"
-				 name="add_button_and_combobox"
-				 width="311"
-				 visible="true">
+            <layout_stack
+                    animate="true"
+                    border_size="0"
+                    follows="all"
+                    height="185"
+                    width="313"
+                    orientation="vertical"
+                    layout="topleft"
+                    name="filter_panels"
+                    top="0"
+                    left="0">
+                <layout_panel
+                        auto_resize="true"
+                        background_visible="false"
+                        layout="topleft"
+                        height="154"
+                        name="add_button_and_combobox"
+                        width="311"
+                        visible="true">
 
-					<!-- List containing items from the COF and Base outfit -->
-					<panel
-					 background_visible="false"
-					 class="cof_wearables"
-					 filename="panel_cof_wearables.xml"
-									 follows="all"
-									 height="129"
-					 layout="topleft"
-					 left="1"
-					 name="cof_wearables_list"
-					 top="0"
-					 width="311" />
+                    <!-- List containing items from the COF and Base outfit -->
+                    <panel
+                            background_visible="false"
+                            class="cof_wearables"
+                            filename="panel_cof_wearables.xml"
+                            follows="all"
+                            height="129"
+                            layout="topleft"
+                            left="1"
+                            name="cof_wearables_list"
+                            top="0"
+                            width="311" />
 
-					<button
-					 follows="left|bottom"
-					 height="22"
-					 image_pressed="PushButton_Press"
-					 image_pressed_selected="PushButton_Selected_Press"
-					 image_selected="PushButton_Selected_Press"
-					 is_toggle="true"
-					 label="Add More..."
-					 layout="topleft"
-					 left="2"
-					 name="show_add_wearables_btn"
-					 top_pad="2"
-					 tool_tip="Open/Close"
-					 width="125" />
+                    <button
+                            follows="left|bottom"
+                            height="22"
+                            image_pressed="PushButton_Press"
+                            image_pressed_selected="PushButton_Selected_Press"
+                            image_selected="PushButton_Selected_Press"
+                            is_toggle="true"
+                            label="Add More..."
+                            layout="topleft"
+                            left="2"
+                            name="show_add_wearables_btn"
+                            top_pad="2"
+                            tool_tip="Open/Close"
+                            width="125" />
 
-					<combo_box
-					 follows="left|right|bottom"
-					 height="22"
-	 layout="topleft"
-					 left_pad="5"
-					 name="list_view_filter_combobox"
-					 top_delta="0"
-					 visible="false"
-					 width="152"/>
-					<combo_box
-					 follows="left|right|bottom"
-					 height="22"
-					 layout="topleft"
-					 left_delta="0"
-					 name="folder_view_filter_combobox"
-					 top_delta="0"
-					 visible="false"
-					 width="152"/>
+                    <combo_box
+                            follows="left|right|bottom"
+                            height="22"
+                            layout="topleft"
+                            left_pad="5"
+                            name="list_view_filter_combobox"
+                            top_delta="0"
+                            visible="false"
+                            width="152"/>
+                    <combo_box
+                            follows="left|right|bottom"
+                            height="22"
+                            layout="topleft"
+                            left_delta="0"
+                            name="folder_view_filter_combobox"
+                            top_delta="0"
+                            visible="false"
+                            width="152"/>
 
-					<button
-									 follows="bottom|right"
-									 height="22"
-					 image_overlay="Search_Icon"
-									 image_pressed="PushButton_Press"
-									 image_pressed_selected="PushButton_Selected_Press"
-									 image_selected="PushButton_Selected_Press"
-					 is_toggle="true"
-					 layout="topleft"
-					 name="filter_button"
-									 right="-5"
-					 top_delta="0"
-									 visible="false"
-					 width="20" />
-				</layout_panel>
+                    <button
+                            follows="bottom|right"
+                            height="22"
+                            image_overlay="Search_Icon"
+                            image_pressed="PushButton_Press"
+                            image_pressed_selected="PushButton_Selected_Press"
+                            image_selected="PushButton_Selected_Press"
+                            is_toggle="true"
+                            layout="topleft"
+                            name="filter_button"
+                            right="-5"
+                            top_delta="0"
+                            visible="false"
+                            width="20" />
+                </layout_panel>
 
-				<layout_panel
-				 auto_resize="false"
-				 background_visible="true"
-				 bg_alpha_color="DkGray2"
-				 height="30"
-				 name="filter_panel"
-				 width="311"
-				 visible="false">
+                <layout_panel
+                        auto_resize="false"
+                        background_visible="true"
+                        bg_alpha_color="DkGray2"
+                        height="30"
+                        name="filter_panel"
+                        width="311"
+                        visible="false">
 
-					<filter_editor
-			 background_image="TextField_Search_Off"
-			 enabled="true"
-			 follows="left|right|top"
-			 label="Filter Inventory Wearables"
-			 layout="topleft"
-			 left="5"
-			 width="290"
-			 height="25"
-			 name="look_item_filter"
-			 search_button_visible="true"
-			 text_color="black"
-			 visible="true"/>
+                    <filter_editor
+                            background_image="TextField_Search_Off"
+                            enabled="true"
+                            follows="left|right|top"
+                            label="Filter Inventory Wearables"
+                            layout="topleft"
+                            left="5"
+                            width="290"
+                            height="25"
+                            name="look_item_filter"
+                            search_button_visible="true"
+                            text_color="black"
+                            visible="true"/>
 
-				</layout_panel>
-			</layout_stack>
-		</layout_panel>
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
 
 
-		<layout_panel background_visible="false"
-									bg_alpha_color="DkGray2"
-									auto_resize="true"
-									height="450"
-									min_height="80"
-									name="add_wearables_panel"
-									width="313"
-									tab_group="2"
-									user_resize="true"
-									visible="false">
+        <layout_panel background_visible="false"
+                bg_alpha_color="DkGray2"
+                auto_resize="true"
+                height="450"
+                min_height="80"
+                name="add_wearables_panel"
+                width="313"
+                tab_group="2"
+                user_resize="true"
+                visible="false">
 
-			<!-- this icon represent dragbar between layout panels.
+            <!-- this icon represent dragbar between layout panels.
           	 This is a workaround implemented in EXT-7255 becouse of an issue with layout stack (EXT-7471) -->
-			<icon follows="left|top|right"
-						height="10"
-						image_name="Dragbar"
-						left="0"
-						top_pad="-9"
-						width="313" />
-			<inventory_panel allow_multi_select="true"
-											 background_visible="false"
-											 border="false"
-											 follows="left|top|right|bottom"
-											 height="418"
-											 layout="topleft"
-											 left="0"
-											 mouse_opaque="false"
-											 name="folder_view"
-											 top_pad="0"
-											 width="313"
-											 visible="false"/>
-			<panel name="filtered_wearables_panel"
-						 background_opaque="true"
-						 background_visible="false"
-						 layout="topleft"
-						 follows="left|top|right|bottom"
-						 border="false"
-						 height="418"
-						 left="0"
-						 mouse_opaque="false"
-						 width="310"
-						 top_delta="0"
-						 visible="true">
-				<wearable_items_list color="0.107 0.107 0.107 1"
-														 name="list_view"
-														 allow_select="true"
-														 layout="topleft"
-														 follows="all"
-														 multi_select="true"
-														 width="313"
-														 height="418"
-														 left="0"
-														 top="0"/>
-			</panel>
-			<button follows="bottom|left"
-							height="22"
-							left="2"
-							label="Wear Item"
-							layout="topleft"
-							name="plus_btn"
-							top_pad="5"
-							width="130" />
-		</layout_panel>
-	</layout_stack>
+            <icon follows="left|top|right"
+                    height="10"
+                    image_name="Dragbar"
+                    left="0"
+                    top_pad="-9"
+                    width="313" />
+            <inventory_panel allow_multi_select="true"
+                    background_visible="false"
+                    border="false"
+                    follows="left|top|right|bottom"
+                    height="418"
+                    layout="topleft"
+                    left="0"
+                    mouse_opaque="false"
+                    name="folder_view"
+                    top_pad="0"
+                    width="313"
+                    visible="false"/>
+            <panel name="filtered_wearables_panel"
+                    background_opaque="true"
+                    background_visible="false"
+                    layout="topleft"
+                    follows="left|top|right|bottom"
+                    border="false"
+                    height="418"
+                    left="0"
+                    mouse_opaque="false"
+                    width="310"
+                    top_delta="0"
+                    visible="true">
+                <wearable_items_list color="0.107 0.107 0.107 1"
+                        name="list_view"
+                        allow_select="true"
+                        layout="topleft"
+                        follows="all"
+                        multi_select="true"
+                        width="313"
+                        height="418"
+                        left="0"
+                        top="0"/>
+            </panel>
+            <button follows="bottom|left"
+                    height="22"
+                    left="2"
+                    label="Wear Item"
+                    layout="topleft"
+                    name="plus_btn"
+                    top_pad="5"
+                    width="130" />
+        </layout_panel>
+    </layout_stack>
 
 
-	<!-- BUTTON BAR -->
-	<panel
-	 background_visible="true"
-	 bevel_style="none"
-	 follows="bottom|left|right"
-	 height="27"
-	 layout="topleft"
-	 left="5"
-	 name="no_add_wearables_button_bar"
-	 top_pad="0"
-	 width="313">
-		<menu_button
-		 follows="bottom|left"
-		 height="25"
-		 image_hover_unselected="Toolbar_Left_Over"
-		 image_overlay="OptionsMenu_Off"
-		 image_selected="Toolbar_Left_Selected"
-		 image_unselected="Toolbar_Left_Off"
-		 layout="topleft"
-		 left="0"
-		 name="gear_menu_btn"
-		 top="1"
-		 width="31" />
-		<icon
-		 follows="bottom|left|right"
-		 height="25"
-		 image_name="Toolbar_Middle_Off"
-		 layout="topleft"
-		 left_pad="1"
-		 name="dummy_right_icon"
-		 width="250" />
-		<button
-		 follows="bottom|right"
-		 height="25"
-		 image_hover_unselected="Toolbar_Right_Over"
-		 image_overlay="Shop"
-		 image_selected="Toolbar_Right_Selected"
-		 image_unselected="Toolbar_Right_Off"
-		 layout="topleft"
-		 left_pad="1"
-		 name="shop_btn_1"
-		 top="1"
-		 tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
-		 width="31" />
-	</panel>
+    <!-- BUTTON BAR -->
+    <panel
+            background_visible="true"
+            bevel_style="none"
+            follows="bottom|left|right"
+            height="27"
+            layout="topleft"
+            left="5"
+            name="no_add_wearables_button_bar"
+            top_pad="0"
+            width="313">
+        <menu_button
+                follows="bottom|left"
+                height="25"
+                image_hover_unselected="Toolbar_Left_Over"
+                image_overlay="OptionsMenu_Off"
+                image_selected="Toolbar_Left_Selected"
+                image_unselected="Toolbar_Left_Off"
+                layout="topleft"
+                left="0"
+                name="gear_menu_btn"
+                top="1"
+                width="31" />
+        <icon
+                follows="bottom|left|right"
+                height="25"
+                image_name="Toolbar_Middle_Off"
+                layout="topleft"
+                left_pad="1"
+                name="dummy_right_icon"
+                width="250" />
+        <button
+                follows="bottom|right"
+                height="25"
+                image_hover_unselected="Toolbar_Right_Over"
+                image_overlay="Shop"
+                image_selected="Toolbar_Right_Selected"
+                image_unselected="Toolbar_Right_Off"
+                layout="topleft"
+                left_pad="1"
+                name="shop_btn_1"
+                top="1"
+                tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
+                width="31" />
+    </panel>
 
 
-	<!-- BUTTON BAR - WEARABLES ADDING MODE -->
-	<panel
-	 background_visible="true"
-	 bevel_style="none"
-	 follows="left|right|bottom"
-	 height="27"
-	 layout="topleft"
-	 left="5"
-	 name="add_wearables_button_bar"
-	 top_delta="0"
-	 visible="false"
-	 width="313">
-		<menu_button
-		 follows="bottom|left"
-		 height="25"
-		 image_hover_unselected="Toolbar_Left_Over"
-		 image_overlay="OptionsMenu_Off"
-		 image_selected="Toolbar_Left_Selected"
-		 image_unselected="Toolbar_Left_Off"
-		 layout="topleft"
-		 left="0"
-		 name="wearables_gear_menu_btn"
-		 top="1"
-		 width="31" />
-		<button
-		 follows="bottom|left"
-		 height="25"
-		 image_hover_unselected="Toolbar_Middle_Over"
-		 image_overlay="Hierarchy_View_Disabled"
-		 image_selected="Toolbar_Middle_Selected"
-		 image_unselected="Toolbar_Middle_Off"
-		 is_toggle="true"
-		 layout="topleft"
-		 left_pad="1"
-		 name="folder_view_btn"
-		 top="1"
-		 width="31" />
-		<button
-		 follows="bottom|left"
-		 height="25"
-		 image_hover_unselected="Toolbar_Middle_Over"
-		 image_overlay="List_View_On"
-		 image_selected="Toolbar_Middle_Selected"
-		 image_unselected="Toolbar_Middle_Off"
-		 is_toggle="true"
-		 layout="topleft"
-		 left_pad="1"
-		 name="list_view_btn"
-		 top="1"
-		 width="31" />
-		<icon
-		 follows="bottom|left|right"
-		 height="25"
-			image_name="Toolbar_Middle_Off"
-		 layout="topleft"
-		 left_pad="1"
-			name="dummy_right_icon"
-			width="186" >
-		</icon>
-		<button
-		 follows="bottom|right"
-		 height="25"
-		 image_hover_unselected="Toolbar_Right_Over"
-		 image_overlay="Shop"
-		 image_selected="Toolbar_Right_Selected"
-		 image_unselected="Toolbar_Right_Off"
-		 layout="topleft"
-		 left_pad="1"
-		 name="shop_btn_2"
-		 top="1"
-		 tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
-		 width="31" />
-	</panel>
+    <!-- BUTTON BAR - WEARABLES ADDING MODE -->
+    <panel
+            background_visible="true"
+            bevel_style="none"
+            follows="left|right|bottom"
+            height="27"
+            layout="topleft"
+            left="5"
+            name="add_wearables_button_bar"
+            top_delta="0"
+            visible="false"
+            width="313">
+        <menu_button
+                follows="bottom|left"
+                height="25"
+                image_hover_unselected="Toolbar_Left_Over"
+                image_overlay="OptionsMenu_Off"
+                image_selected="Toolbar_Left_Selected"
+                image_unselected="Toolbar_Left_Off"
+                layout="topleft"
+                left="0"
+                name="wearables_gear_menu_btn"
+                top="1"
+                width="31" />
+        <button
+                follows="bottom|left"
+                height="25"
+                image_hover_unselected="Toolbar_Middle_Over"
+                image_overlay="Hierarchy_View_Disabled"
+                image_selected="Toolbar_Middle_Selected"
+                image_unselected="Toolbar_Middle_Off"
+                is_toggle="true"
+                layout="topleft"
+                left_pad="1"
+                name="folder_view_btn"
+                top="1"
+                width="31" />
+        <button
+                follows="bottom|left"
+                height="25"
+                image_hover_unselected="Toolbar_Middle_Over"
+                image_overlay="List_View_On"
+                image_selected="Toolbar_Middle_Selected"
+                image_unselected="Toolbar_Middle_Off"
+                is_toggle="true"
+                layout="topleft"
+                left_pad="1"
+                name="list_view_btn"
+                top="1"
+                width="31" />
+        <icon
+                follows="bottom|left|right"
+                height="25"
+                image_name="Toolbar_Middle_Off"
+                layout="topleft"
+                left_pad="1"
+                name="dummy_right_icon"
+                width="186" >
+        </icon>
+        <button
+                follows="bottom|right"
+                height="25"
+                image_hover_unselected="Toolbar_Right_Over"
+                image_overlay="Shop"
+                image_selected="Toolbar_Right_Selected"
+                image_unselected="Toolbar_Right_Off"
+                layout="topleft"
+                left_pad="1"
+                name="shop_btn_2"
+                top="1"
+                tool_tip="Visit the SL Marketplace. You can also select something you are wearing, then click here to see more things like it"
+                width="31" />
+    </panel>
 
-	<!-- SAVE AND REVERT BUTTONS -->
-	<panel
-	 follows="left|right|bottom"
-	 height="30"
-	 layout="topleft"
-	 left="4"
-	 top_pad="2"
-	 name="save_revert_button_bar"
-	 width="300">
-		<layout_stack
-						 follows="bottom|left|right"
-					 height="23"
-					 layout="topleft"
-					 mouse_opaque="false"
-					 name="button_bar_ls"
-					 left="0"
-					 orientation="horizontal"
-					 top="0"
-					 width="313">
-			<layout_panel
-					 follows="bottom|left|right"
-					 height="23"
-								 layout="bottomleft"
-								 left="0"
-								 mouse_opaque="false"
-								 name="save_btn_lp"
-								 auto_resize="true"
-								 width="156">
-				<button
-                         follows="bottom|left|right"
-         height="23"
-         label="Save"
-                         left="1"
-         layout="topleft"
-         name="save_btn"
-         top="0"
-         width="155" />
-				<button
-                         follows="bottom|right"
-         height="23"
-         name="save_flyout_btn"
-         label=""
-         layout="topleft"
-         left_pad="-20"
-         tab_stop="false"
-         top="0"
-         image_selected="SegmentedBtn_Right_Selected_Press"
-         image_unselected="SegmentedBtn_Right_Off"
-         image_pressed="SegmentedBtn_Right_Press"
-         image_pressed_selected="SegmentedBtn_Right_Selected_Press"
-         image_overlay="Arrow_Small_Up"
-         width="20"/>
-			</layout_panel>
-			<layout_panel
-								 follows="bottom|left|right"
-								 height="23"
-								 layout="bottomleft"
-								 left_pad="3"
-								 mouse_opaque="false"
-								 name="revert_btn_lp"
-								 auto_resize="true"
-								 width="147">
-				<button
-         follows="bottom|left|right"
-         height="23"
-                         left="0"
-         label="Undo Changes"
-         layout="topleft"
-         name="revert_btn"
-         top="0"
-         tool_tip="Revert to last saved version"
-         width="147" />
-			</layout_panel>
-		</layout_stack>
-	</panel>
+    <!-- SAVE AND REVERT BUTTONS -->
+    <panel
+            follows="left|right|bottom"
+            height="30"
+            layout="topleft"
+            left="4"
+            top_pad="2"
+            name="save_revert_button_bar"
+            width="300">
+        <layout_stack
+                follows="bottom|left|right"
+                height="23"
+                layout="topleft"
+                mouse_opaque="false"
+                name="button_bar_ls"
+                left="0"
+                orientation="horizontal"
+                top="0"
+                width="313">
+            <layout_panel
+                    follows="bottom|left|right"
+                    height="23"
+                    layout="bottomleft"
+                    left="0"
+                    mouse_opaque="false"
+                    name="save_btn_lp"
+                    auto_resize="true"
+                    width="156">
+                <button
+                        follows="bottom|left|right"
+                        height="23"
+                        label="Save"
+                        left="1"
+                        layout="topleft"
+                        name="save_btn"
+                        top="0"
+                        width="155" />
+                <button
+                        follows="bottom|right"
+                        height="23"
+                        name="save_flyout_btn"
+                        label=""
+                        layout="topleft"
+                        left_pad="-20"
+                        tab_stop="false"
+                        top="0"
+                        image_selected="SegmentedBtn_Right_Selected_Press"
+                        image_unselected="SegmentedBtn_Right_Off"
+                        image_pressed="SegmentedBtn_Right_Press"
+                        image_pressed_selected="SegmentedBtn_Right_Selected_Press"
+                        image_overlay="Arrow_Small_Up"
+                        width="20"/>
+            </layout_panel>
+            <layout_panel
+                    follows="bottom|left|right"
+                    height="23"
+                    layout="bottomleft"
+                    left_pad="3"
+                    mouse_opaque="false"
+                    name="revert_btn_lp"
+                    auto_resize="true"
+                    width="147">
+                <button
+                        follows="bottom|left|right"
+                        height="23"
+                        left="0"
+                        label="Undo Changes"
+                        layout="topleft"
+                        name="revert_btn"
+                        top="0"
+                        tool_tip="Revert to last saved version"
+                        width="147" />
+            </layout_panel>
+        </layout_stack>
+    </panel>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
index 6badaf8ce24b3fcbfbe4d2c92d24325d9cd4c744..5aff7a512768ab1d69fdf897df8f5c6958598d0b 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -242,7 +242,7 @@
     top_delta="24"
     width="280">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
 
   <check_box
@@ -256,7 +256,7 @@
     top_delta="24"
     width="256">
     <check_box.commit_callback
-      function="Pref.VertexShaderEnable" />
+      function="Pref.RenderOptionUpdate" />
   </check_box>
   
   <slider
diff --git a/indra/newview/skins/default/xui/en/panel_region_environment.xml b/indra/newview/skins/default/xui/en/panel_region_environment.xml
index aa38c49fae13d65d6b297ae0e621cb69ba64666d..edf1e1efd47eec5c32c69e99c257939a3a8c9cd4 100644
--- a/indra/newview/skins/default/xui/en/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_environment.xml
@@ -1,149 +1,903 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
 
 <panel
- border="true"
- follows="top|left"
- height="300"
- label="Environment"
- layout="topleft"
- help_topic="panel_region_environment_tab"
- name="panel_env_info"
- width="530"> 
- <text
-  name="water_settings_title"
-  follows="top|left"
-  height="30"
-  layout="topleft"
-  left="50"
-  top_pad="20"
-  width="430"
-  wrap="true">
-  Select the Water and Sky/Day Cycle Settings you would like all visitors to your region to see.  More info
- </text> 
- <view_border
-  bevel_style="none"
-  follows="top|left"
-  height="237"
-  layout="topleft"
-  left="50"
-  name="border"
-  top="60"
-  width="430"/>
- <radio_group
-  follows="top|left"
-  height="45"
-  layout="topleft"
-  left_delta="10"
-  name="region_settings_radio_group"
-  top_delta="20"
-  width="200">
-  <radio_item
-   label="Use Second Life default"
-   layout="topleft"
-   name="use_sl_default_settings"/>
-  <radio_item
-   label="Use the following settings"
-   layout="topleft"
-   name="use_my_settings"
-   top_pad="20"/>
-  </radio_group>
- <panel
-  follows="top|left"
-  height="150"
-  layout="topleft"
-  left="50"
-  name="user_environment_settings"
-  top_pad="20"
-  width="430">
-   <text
-    name="water_settings_title"
-    follows="top|left"
-    height="16"
-    layout="topleft"
-    left="50"
-    top_pad="0"
-    width="160">
-    Water Setting
-   </text>
-   <combo_box
-    follows="top|left"
-    left_pad="2"
-    name="water_settings_preset_combo"
-    top_delta="-7"
-    width="200">
-    <combo_box.item
-     label="-Select a preset-"
-     name="item0"/>
-   </combo_box>
-   <text
-    name="sky_dayc_settings_title"
-    follows="top|left"
-    height="16"
-    layout="topleft"
-    left="50"
-    top_pad="30"
-    width="100">
-    Sky / Day Cycle
-   </text>
-   <radio_group
-    layout="topleft"
-    left_delta="50"
-    name="sky_dayc_settings_radio_group"
-    top_pad="10"
-    height="50"
-    width="110">
-    <radio_item
-     layout="topleft"
-     label="Fixed sky"
-     name="my_sky_settings"/>
-    <radio_item
-     layout="topleft"
-     label="Day cycle"
-     name="my_dayc_settings"
-     top_pad="25"/>  	
-    </radio_group>
-   <combo_box
-    follows="top|left"
-    left_pad="2"
-    name="sky_settings_preset_combo"
-    top_delta="-7"
-    width="200">
-    <combo_box.item
-     label="-Select a preset-"
-     name="item0"/>
-   </combo_box>
-   <combo_box
-    follows="top|left"
-    name="dayc_settings_preset_combo"
-    top_delta="36"
-    width="200">
-    <combo_box.item
-     label="-Select a preset-"
-     name="item0"/>
-   </combo_box>
- </panel>
- <button
-  follows="left|top"
-  height="23"
-  label="Apply"
-  layout="topleft"
-  right="-160"
-  name="apply_btn"
-  top_pad="10"
-  width="100" />
- <button
-  follows="left|top"
-  height="23"
-  label="Cancel"
-  layout="topleft"
-  left_pad="10"
-  name="cancel_btn"
-  width="100" /> 
- <loading_indicator
-  height="23"
-  left="50"
-  name="progress_indicator"
-  top_delta="0"
-  visible="false"
-  width="23" />
+        border="true"
+        follows="all"
+        height="375"
+        label="Environment"
+        layout="topleft"
+        help_topic="panel_region_environment_tab"
+        name="panel_env_info"
+        width="530"> 
+    <string name="str_label_use_default">Use Default Settings</string>
+    <string name="str_label_use_region">Use Region Settings</string>
+    <string name="str_altitude_desription">Sky [INDEX]([ALTITUDE]m)</string>
+    <string name="str_no_parcel">No parcel is selected. Environmental settings are disabled.</string>
+    <string name="str_cross_region">Environmental settings are not available across region boundries.</string>
+    <string name="str_legacy">Environmental settings are not available on this region.</string>
+    <string name="str_disallowed">The estate manager does not allow changing parcel environments in this region.</string>
+    <string name="str_too_small">The parcel must be at least 128 square meters to support an environment.</string>
+    <string name="str_empty">(empty)</string>
+    <string name="str_region_env">(region environment)</string>
+
+    <layout_stack 
+            width="530"
+            height="400"
+            follows="all"
+            layout="topleft"
+            left="0"
+            animate="false"
+            orientation="vertical">
+        <layout_panel
+                user_resize="false"
+                auto_resize="false"
+                height="20"
+                name="pnl_environment_region_msg"
+                top="0">
+            <text follows="left|top"
+                    font="SansSerif"
+                    height="20"
+                    layout="topleft"
+                    left="10"
+                    name="region_text_lbl"
+                    top="6"
+                    width="100">
+                Region:
+            </text>
+            <text follows="left|top"
+                    font="SansSerif"
+                    height="20"
+                    layout="topleft"
+                    left_delta="50"
+                    name="region_text"
+                    top_delta="0"
+                    width="400">
+                unknown
+            </text>
+        </layout_panel>
+        <layout_panel
+                user_resize="false"
+                name="pnl_environment_disabled"
+                visible="false">
+            <text follows="top|left|bottom|right"
+                    halign="center"
+                    valign="top"
+                    top_pad="40"
+                    name="txt_environment_disabled"
+                    text_color="white">
+                ...
+            </text>
+        </layout_panel>
+        <layout_panel
+                user_resize="false"
+                min_height="0"
+                top="0"
+                name="pnl_environment_config"
+                visible="true">
+            <layout_stack 
+                    follows="all"
+                    layout="topleft"
+                    animate="false"
+                    orientation="horizontal">
+                <layout_panel
+                        user_resize="false"
+                        min_height="0"
+                        top="0"
+                        name="pnl_environment_config"
+                        visible="true">
+                    <layout_stack
+                            follows="all"
+                            layout="topleft"
+                            animate="false"
+                            orientation="vertical">
+                        <layout_panel
+                                min_height="140"
+                                follows="all"
+                                border="true"
+                                bevel_style="in"
+                                name="pnl_environment_current">
+                            <text follows="top|left"
+                                    font="SansSerif"
+                                    halign="left"
+                                    text_color="white"
+                                    left="5"
+                                    top="2">Select Environment</text>
+                            <button
+                                    follows="top|left"
+                                    top_pad="20"
+                                    left_delta="10"
+                                    layout="topleft"
+                                    height="23"
+                                    label="[USEDEFAULT]"
+                                    width="120"
+                                    name="btn_usedefault"/>
+                            <button
+                                    follows="top|left"
+                                    top_pad="5"
+                                    left_delta="0"
+                                    layout="topleft"
+                                    height="23"
+                                    label="Use Inventory"
+                                    width="120"
+                                    name="btn_select_inventory"/>
+                            <button
+                                    follows="top|left"
+                                    top_pad="5"
+                                    left_delta="0"
+                                    layout="topleft"
+                                    height="23"
+                                    label="Customize"
+                                    width="120"
+                                    name="btn_edit"/>
+                            <check_box
+                                    height="20"
+                                    label="Parcel Owners May Override Environment"
+                                    layout="topleft"
+                                    left_delta="0"
+                                    top_pad="10"
+                                    name="chk_allow_override"
+                                    width="200" />
+                        </layout_panel>
+                        <layout_panel
+                                min_height="130"
+                                follows="all"
+                                border="true"
+                                bevel_style="in"
+                                name="pnl_environment_length">
+                            <text 
+                                    font="SansSerif"
+                                    follows="top|left|right"
+                                    halign="left"
+                                    text_color="white"
+                                    left="5"
+                                    top="2">Day Settings</text>
+                            <text
+                                    type="string"
+                                    length="1"
+                                    follows="left|top"
+                                    height="12"
+                                    layout="topleft"
+                                    left_delta="10"
+                                    top_pad="16"
+                                    width="200">
+                                Day Length (hours)
+                            </text>
+                            <slider
+                                    can_edit_text="true"
+                                    decimal_digits="1"
+                                    follows="top|left|right"
+                                    layout="topleft"
+                                    increment="0.5"
+                                    height="20"
+                                    width="237"
+                                    left="10"
+                                    top_pad="0"
+                                    right="-10"
+                                    initial_value="4"
+                                    name="sld_day_length"
+                                    min_val="4"
+                                    max_val="168" />
+                            <text
+                                    type="string"
+                                    length="1"
+                                    follows="left|top"
+                                    height="12"
+                                    layout="topleft"
+                                    left_delta="0"
+                                    top_pad="5"
+                                    width="200">
+                                Day Offset (hours)
+                            </text>
+                            <slider
+                                    can_edit_text="true"
+                                    decimal_digits="1"
+                                    follows="top|left|right"
+                                    layout="topleft"
+                                    height="20"
+                                    width="237"
+                                    increment="0.5"
+                                    initial_value="-8"
+                                    left="10"
+                                    top_pad="0"
+                                    right="-10"
+                                    name="sld_day_offset"
+                                    min_val="-11.5"
+                                    max_val="12" />
+                            <text
+                                    type="string"
+                                    length="1"
+                                    follows="left|top"
+                                    height="12"
+                                    layout="topleft"
+                                    left_delta="0"
+                                    top_pad="5"
+                                    width="200">
+                                Apparent Time of Day:
+                            </text>
+                            <text
+                                    name="lbl_apparent_time"
+                                    type="string"
+                                    length="1"
+                                    follows="left|top"
+                                    height="12"
+                                    layout="topleft"
+                                    left_delta="10"
+                                    top_pad="5"
+                                    width="200">
+                                [HH]:[MM][AP] ([PRC]%)
+                            </text>
+                        </layout_panel>
+                        <layout_panel
+                                follows="bottom"
+                                border="true"
+                                bevel_style="in"
+                                name="pnl_environment_buttons">
+<!-- used to be buttons, but now spacer.
+-->
+                        </layout_panel>
+                    </layout_stack>
+                </layout_panel>
+                <layout_panel
+                        user_resize="false"
+                        min_height="0"
+                        top="0"
+                        name="pnl_environment_altitudes"
+                        visible="true">
+                    <!-- Three movable panels first so that they will be 'below' slider-->
+                    <panel
+                         follows="top|left"
+                         height="26"
+                         width="360"
+                         layout="topleft"
+                         visible="true"
+                         left="1"
+                         top="30"
+                         name="pnl_alt1">
+                        <text
+                                type="string"
+                                length="1"
+                                follows="left|top"
+                                layout="topleft"
+                                height="24"
+                                width="52"
+                                left_delta="2"
+                                top_pad="1"
+                                halign="right"
+                                name="txt_alt1">
+                            Sky [INDEX]
+                            [ALTITUDE]m
+                        </text>
+                        <line_editor
+                                follows="left|top"
+                                enabled="false"
+                                top_delta="3"
+                                left_pad="21"
+                                height="20"
+                                layout="topleft"
+                                name="edt_invname_alt1"
+                                use_bg_color="true"
+                                bg_color="TextBgReadOnlyColor"
+                                width="155">
+                            Unknown
+                        </line_editor>
+                        <settings_drop_target
+                                height="20"
+                                top_delta="0"
+                                left_delta="0"
+                                follows="top|left"
+                                layout="topleft"
+                                name="sdt_alt1"
+                                tool_tip="Drag a setting from Inventory onto this target box to select it as current sky."
+                                width="155" />
+                    </panel>
+                    <panel
+                         follows="top|left"
+                         height="26"
+                         width="360"
+                         layout="topleft"
+                         visible="true"
+                         left="1"
+                         top="60"
+                         name="pnl_alt2">
+                        <text
+                                type="string"
+                                length="1"
+                                follows="left|top"
+                                layout="topleft"
+                                height="24"
+                                width="52"
+                                left_delta="2"
+                                top_pad="1"
+                                halign="right"
+                                name="txt_alt2">
+                            Sky [INDEX]
+                            [ALTITUDE]m
+                        </text>
+                        <line_editor
+                                follows="left|top"
+                                enabled="false"
+                                top_delta="3"
+                                left_pad="21"
+                                height="20"
+                                layout="topleft"
+                                name="edt_invname_alt2"
+                                use_bg_color="true"
+                                bg_color="TextBgReadOnlyColor"
+                                width="155">
+                            Unknown
+                        </line_editor>
+                        <settings_drop_target
+                                height="20"
+                                top_delta="0"
+                                left_delta="0"
+                                follows="top|left"
+                                layout="topleft"
+                                name="sdt_alt2"
+                                tool_tip="Drag a setting from Inventory onto this target box to select it as current sky."
+                                width="155" />
+                    </panel>
+                    <panel
+                         follows="top|left"
+                         height="26"
+                         width="360"
+                         layout="topleft"
+                         visible="true"
+                         left="1"
+                         top="90"
+                         name="pnl_alt3">
+                        <text
+                                type="string"
+                                length="1"
+                                follows="left|top"
+                                layout="topleft"
+                                height="25"
+                                width="52"
+                                left_delta="2"
+                                top_pad="1"
+                                halign="right"
+                                name="txt_alt3">
+                            Sky [INDEX]
+                            [ALTITUDE]m
+                        </text>
+                        <line_editor
+                                follows="left|top"
+                                enabled="false"
+                                top_delta="3"
+                                left_pad="21"
+                                height="20"
+                                layout="topleft"
+                                name="edt_invname_alt3"
+                                use_bg_color="true"
+                                bg_color="TextBgReadOnlyColor"
+                                width="155">
+                            Unknown
+                        </line_editor>
+                        <settings_drop_target
+                                height="20"
+                                top_delta="0"
+                                left_delta="0"
+                                follows="top|left"
+                                layout="topleft"
+                                name="sdt_alt3"
+                                tool_tip="Drag a setting from Inventory onto this target box to select it as current sky."
+                                width="155" />
+                    </panel>
+                    <text follows="top|left"
+                                font="SansSerif"
+                                halign="left"
+                                text_color="white"
+                                left="5"
+                                top="2">Sky Altitudes</text>
+                    <!-- Divider icons also should be under slider to not interfer with clicks-->
+                    <icon
+                        color="LtGray"
+                        height="2"
+                        width="17"
+                        image_name="Rounded_Square"
+                        layout="topleft"
+                        left="57"
+                        top="89"
+                        name="mark0"/>
+                    <icon
+                        color="LtGray"
+                        height="2"
+                        width="17"
+                        image_name="Rounded_Square"
+                        layout="topleft"
+                        left_delta="0"
+                        top_delta="69"
+                        name="mark1"/>
+                    <icon
+                        color="LtGray"
+                        height="2"
+                        width="17"
+                        image_name="Rounded_Square"
+                        layout="topleft"
+                        left_delta="0"
+                        top_delta="69"
+                        name="mark2"/>
+                    <multi_slider
+                            height="270"
+                            follows="top|left"
+                            orientation="vertical"
+                            increment="25"
+                            min_val="100"
+                            max_val="4000"
+                            thumb_image="Inv_SettingsSky"
+                            thumb_width="17"
+                            thumb_highlight_color="white"
+                            decimal_digits="0"
+                            draw_track="true"
+                            overlap_threshold="100"
+                            initial_value="0"
+                            layout="topleft"
+                            left="57"
+                            max_sliders="3"
+                            name="sld_altitudes"
+                            show_text="false"
+                            top="20"
+                            use_triangle="false"
+                            width="17">
+                        <slider name="sld1"
+                                value="1000"/>
+                        <slider name="sld2"
+                                value="2000"/>
+                        <slider name="sld3"
+                                value="3000"/>
+                    </multi_slider>
+                    <panel
+                        follows="top|left"
+                        height="21"
+                        width="360"
+                        layout="topleft"
+                        visible="true"
+                        left="1"
+                        top_pad="10"
+                        name="pnl_ground">
+                        <text
+                           type="string"
+                           length="1"
+                           follows="left|top"
+                           layout="topleft"
+                           height="12"
+                           width="52"
+                           left_delta="2"
+                           top_pad="2"
+                           halign="right"
+                           name="txt_ground">
+                            Ground
+                        </text>
+                        <icon
+                            follows="top|left"
+                            height="17"
+                            width="17"
+                            image_name="Inv_SettingsSky"
+                            layout="topleft"
+                            name="icon_ground"
+                            mouse_opaque="false"
+                            visible="true"
+                           top_delta="-3"
+                           left_pad="2"/>
+                        <line_editor
+                           follows="left|top"
+                           enabled="false"
+                           top_delta="-1"
+                           left_pad="2"
+                           height="20"
+                           layout="topleft"
+                           name="edt_invname_ground"
+                           use_bg_color="true"
+                           bg_color="TextBgReadOnlyColor"
+                           width="155">
+                            Unknown
+                        </line_editor>
+                        <settings_drop_target
+                           height="20"
+                           top_delta="0"
+                           left_delta="0"
+                           follows="top|left"
+                           layout="topleft"
+                           name="sdt_ground"
+                           tool_tip="Drag a setting from Inventory onto this target box to select it as the ground level sky."
+                           width="155" />
+                    </panel>
+                    <panel
+                         follows="top|left"
+                         height="21"
+                         width="360"
+                         layout="topleft"
+                         visible="true"
+                         left="1"
+                         top_pad="10"
+                         name="pnl_water">
+                        <text
+                           type="string"
+                           length="1"
+                           follows="left|top"
+                           layout="topleft"
+                           height="12"
+                           width="52"
+                           left_delta="2"
+                           top_pad="2"
+                           halign="right"
+                           name="txt_water">
+                            Water
+                        </text>
+                        <icon
+                           follows="left|top"
+                           height="17"
+                           width="17"
+                           image_name="Inv_SettingsWater"
+                           layout="topleft"
+                           name="icon_water"
+                           mouse_opaque="false"
+                           visible="true"
+                           top_delta="-3"
+                           left_pad="2"/>
+                        <line_editor
+                                follows="left|top"
+                                enabled="false"
+                                top_delta="-1"
+                                left_pad="2"
+                                height="20"
+                                layout="topleft"
+                                name="edt_invname_water"
+                                use_bg_color="true"
+                                bg_color="TextBgReadOnlyColor"
+                                width="155">
+                            Unknown
+                        </line_editor>
+                        <settings_drop_target
+                                height="20"
+                                top_delta="0"
+                                left_delta="0"
+                                follows="top|left"
+                                layout="topleft"
+                                name="sdt_water"
+                                tool_tip="Drag a setting from Inventory onto this target box to select it as current water."
+                                width="155" />
+                    </panel>
+                    <button
+                            follows="top|right"
+                            layout="topleft"
+                            height="23"
+                            width="100"
+                            label="Reset"
+                            right="-10"
+                            top_pad="4"
+                            tool_tip="Reset to default altitudes"
+                            name="btn_rst_altitudes" />
+                </layout_panel>
+            </layout_stack>        
+        </layout_panel>
+        <!--
+        <layout_panel 
+                user_resize="false"
+                height="155"
+                min_height="0"
+                name="pnl_environment_config"
+                visible="true">
+            <layout_stack 
+                    left="5"
+                    top="0"
+                    right="-5"
+                    bottom="-1"
+                    layout="topleft"
+                    follows="all"
+                    animate="false"
+                    orientation="horizontal">
+                <layout_panel 
+                        background_visible="true"
+                        border="true"
+                        bevel_style="in"
+                        user_resize="false"
+                        width="260"
+                        min_width="260"
+                        name="pnl_environment_current">
+                    <text follows="top|left"
+                            font="SansSerif"
+                            halign="left"
+                            text_color="white"
+                            top="2">Current Environment</text>
+                    <radio_group
+                            height="90"
+                            layout="topleft"
+                            top_pad="8"
+                            left_delta="10"
+                            name="rdg_environment_select">
+                        <radio_item
+                                label="[USEDEFAULT]"
+                                layout="topleft"
+                                name="rdo_use_xxx_setting"
+                                height="20"/>
+                        <radio_item
+                                label="Settings From Inventory"
+                                layout="topleft"
+                                valign="top"
+                                name="rdo_use_inv_setting"
+                                height="20"/>
+                        <radio_item
+                                top_pad="25"
+                                label="Custom Environment"
+                                layout="topleft"
+                                height="20"
+                                name="rdo_use_custom_setting"/>
+                    </radio_group>
+                    <line_editor
+                            follows="top|left"
+                            enabled="false"
+                            left_delta="20"
+                            top_delta="50"
+                            height="20"
+                            layout="topleft"
+                            name="edt_inventory_name"
+                            width="200">
+                        Unknown
+                    </line_editor>
+                    <settings_drop_target
+                            height="20"
+                            top_pad="-20"
+                            follows="top|left"
+                            layout="topleft"
+                            name="sdt_drop_target"
+                            tool_tip="Drag a setting from Inventory onto this target box to select it as current evironment."
+                            width="200" />
+                    <button
+                            name="btn_select_inventory"
+                            follows="top|left"
+                            image_overlay="Command_Inventory_Icon"
+                            layout="topleft"
+                            height="20"
+                            width="20"
+                            left_delta="205"
+                            top_delta="0"/>
+                    <button
+                            follows="top|left"
+                            top_pad="25"
+                            left_delta="-205"
+                            layout="topleft"
+                            height="23"
+                            label="Edit Environment"
+                            width="120"
+                            name="btn_edit"/>
+
+                </layout_panel>
+                <layout_panel 
+                        border="true"
+                        bevel_style="in"
+                        user_resize="false"
+                        width="260"
+                        min_width="260"
+                        background_visible="true"
+                        name="pnl_environment_length">
+                    <text 
+                            font="SansSerif"
+                            follows="top|left|right"
+                            halign="left"
+                            text_color="white"
+                            top="2">Day Settings</text>
+                    <text
+                            type="string"
+                            length="1"
+                            follows="left|top"
+                            height="12"
+                            layout="topleft"
+                            left_delta="10"
+                            top_pad="14"
+                            width="200">
+                        Day Length (hours)
+                    </text>
+                    <slider
+                            can_edit_text="true"
+                            decimal_digits="1"
+                            follows="left|top"
+                            height="20"
+                            increment="0.5"
+                            initial_value="4"
+                            layout="topleft"
+                            left_delta="0"
+                            top_pad="6"
+                            name="sld_day_length"
+                            min_val="4"
+                            max_val="168"
+                            width="180" />
+                    <text
+                            type="string"
+                            length="1"
+                            follows="left|top"
+                            height="12"
+                            layout="topleft"
+                            left_delta="0"
+                            top_pad="10"
+                            width="200">
+                        Day Offset (hours)
+                    </text>
+                    <slider
+                            can_edit_text="true"
+                            decimal_digits="1"
+                            follows="left|top"
+                            height="20"
+                            increment="0.5"
+                            initial_value="-8"
+                            layout="topleft"
+                            left_delta="0"
+                            top_pad="6"
+                            name="sld_day_offset"
+                            min_val="-12"
+                            max_val="12"
+                            width="180" />
+                    <text
+                            type="string"
+                            length="1"
+                            follows="left|top"
+                            height="12"
+                            layout="topleft"
+                            left_delta="0"
+                            top_pad="10"
+                            width="200">
+                        Apparent Time of Day:
+                    </text>
+                    <text
+                            name="lbl_apparent_time"
+                            type="string"
+                            length="1"
+                            follows="left|top"
+                            height="12"
+                            layout="topleft"
+                            left_delta="10"
+                            top_pad="5"
+                            width="200">
+                        [HH]:[MM][AP] ([PRC]%)
+                    </text>
+
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
+        <layout_panel
+                user_resize="false"
+                height="155"
+                min_height="0"
+                name="pnl_environment_altitudes"
+                visible="true">
+            <panel
+                    left="5"
+                    top="0"
+                    bottom="-1"
+                    width="260"
+                    follows="left|top|bottom"
+                    background_visible="true"
+                    border="true"
+                    bevel_style="in"
+                    name="cnt_panel">
+                <text follows="top|left"
+                        font="SansSerif"
+                        halign="left"
+                        text_color="white"
+                        top="2">Sky Altitudes</text>
+                <multi_slider
+                        decimal_digits="0"
+                        follows="bottom"
+                        height="123"
+                        width="17"
+                        orientation="vertical"
+                        increment="10"
+                        overlap_threshold="100"
+                        min_val="100"
+                        max_val="4000"
+                        layout="topleft"
+                        left="15"
+                        top="20"
+                        max_sliders="20"
+                        name="sld_altitudes"
+                        show_text="false"
+                        thumb_image="Inv_SettingsSky"
+                        thumb_width="17"
+                        thumb_highlight_color="white">
+                    <slider name="sld1"
+                            value="200"/>
+                    <slider name="sld2"
+                            value="400"/>
+                    <slider name="sld3"
+                            value="600"/>
+                </multi_slider>
+                <icon
+                        follows="left|top"
+                        height="17"
+                        width="17"
+                        image_name="Inv_SettingsSky"
+                        layout="topleft"
+                        name="icon_ground"
+                        mouse_opaque="false"
+                        visible="true"
+                        left_delta="0"
+                        top_pad="-9"/>
+                <text
+                        type="string"
+                        length="1"
+                        follows="left|top"
+                        height="12"
+                        layout="topleft"
+                        left_pad="3"
+                        top_delta="2"
+                        width="200"
+                        name="ground">
+                    Ground
+                </text>
+                <text
+                        type="string"
+                        length="1"
+                        follows="left"
+                        height="12"
+                        layout="topleft"
+                        left="35"
+                        top="30"
+                        width="200"
+                        name="alt1">
+                    Sky [INDEX]([ALTITUDE]m)
+                </text>
+                <text
+                        type="string"
+                        length="1"
+                        follows="left|top"
+                        height="12"
+                        layout="topleft"
+                        left="35"
+                        top="40"
+                        width="200"
+                        name="alt2">
+                    Sky [INDEX]([ALTITUDE]m)
+                </text>
+                <text
+                        type="string"
+                        length="1"
+                        follows="left|top"
+                        height="12"
+                        layout="topleft"
+                        left="35"
+                        top="50"
+                        width="200"
+                        name="alt3">
+                    Sky [INDEX]([ALTITUDE]m)
+                </text>
+            </panel>
+        </layout_panel>
+        <layout_panel
+                user_resize="false"
+                height="0"
+                min_height="0"
+                name="pnl_auto_adjust"
+                visible="true"/>
+        <layout_panel
+                user_resize="false"
+                height="59"
+                min_height="59"
+                name="pnl_environment_buttons">
+            <check_box
+                    height="20"
+                    label="Parcel Owners May Override Environment"
+                    layout="topleft"
+                    left="10"
+                    top="0"
+                    name="chk_allow_override"
+                    width="200" />
+            <button
+                    follows="top|left"
+                    height="23"
+                    label="Apply"
+                    top_pad="5"
+                    name="btn_apply"
+                    width="100" />
+            <button
+                    follows="top|left"
+                    height="23"
+                    label="Reset"
+                    layout="topleft"
+                    left_pad="10"
+                    top_delta="0"
+                    name="btn_cancel"
+                    width="100" /> 
+
+        </layout_panel>
+-->
+    </layout_stack>
 </panel>
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
new file mode 100644
index 0000000000000000000000000000000000000000..bec793bbeeeff4bd0deef6da4806408b16da47d4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_atmos.xml
@@ -0,0 +1,322 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+        border="true"
+        follows="all"
+        label="Atmosphere &amp; Lighting"
+        layout="topleft"
+        left="0"
+        name="panel_settings_sky_atmos"
+        top="0">
+    <layout_stack
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            orientation="vertical">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="false"
+                user_resize="false"
+                visible="true"
+                height="75">
+
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="15"
+                    top_pad="15"
+                    width="80">
+                Ambient Color:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="0"
+                    name="ambient_light"
+                    top_pad="5"
+                    width="60" />
+            <text
+                    follows="left"
+                    height="10"
+                    layout="topleft"
+                    left_delta="90"
+                    top_delta="-15"
+                    width="80">
+                Blue Horizon:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="0"
+                    name="blue_horizon"
+                    top_pad="5"
+                    width="60" />
+            <text
+                    follows="left"
+                    height="10"
+                    layout="topleft"
+                    left_delta="90"
+                    top_delta="-15"
+                    width="80">
+                Blue Density:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="0"
+                    name="blue_density"
+                    top_pad="5"
+                    width="60" />
+        </layout_panel>
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true">
+            <layout_stack name="atmosphere1"
+                    left="5"
+                    top="5"
+                    right="-5"
+                    bottom="-5"
+                    follows="left|top|right|bottom"
+                    orientation="hoizontal">
+                <layout_panel
+                        border="false"
+                        bevel_style="in"
+                        auto_resize="true"
+                        user_resize="false"
+                        visible="true"
+                        min_width="225">
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="15"
+                            top_pad="15"
+                            width="80">
+                        Haze Horizon:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="5"
+                            name="haze_horizon"
+                            top_delta="20"
+                            width="207"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="80">
+                        Haze Density:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="5"
+                            name="haze_density"
+                            top_delta="20"
+                            width="207"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="80">
+                        Moisture Level:
+                    </text>
+                     <slider
+                            decimal_digits="3"
+                            follows="left|top"
+                            height="14"
+                            increment="0.001"
+                            initial_value="0"
+                            left_delta="5"
+                            top_delta="20"
+                            layout="topleft"
+                            min_val="0"
+                            max_val="1"
+                            name="moisture_level"
+                            width="207"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="80">
+                        Droplet Radius:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="14"
+                            increment="0.01"
+                            initial_value="0"
+                            left_delta="5"
+                            top_delta="20"
+                            layout="topleft"
+                            min_val="5.0"
+                            max_val="1000.0"
+                            name="droplet_radius"
+                            width="207"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="80">
+                        Ice Level:
+                    </text>
+                    <slider
+                            decimal_digits="1"
+                            follows="left|top"
+                            height="14"
+                            increment="0.1"
+                            initial_value="0"
+                            left_delta="5"
+                            top_delta="20"
+                            layout="topleft"
+                            min_val="0"
+                            max_val="1"
+                            name="ice_level"
+                            width="207"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="80">
+                        Scene Gamma:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            max_val="20"
+                            name="scene_gamma"
+                            top_delta="20"
+                            width="207"
+                            can_edit_text="true"/>
+                </layout_panel>            
+                <layout_panel
+                        border="false"
+                        bevel_style="in"
+                        auto_resize="true"
+                        user_resize="false"
+                        visible="true"
+                        min_width="225">
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="15"
+                            top_pad="15"
+                            width="200">
+                        Density Multiplier:
+                    </text>
+                    <slider
+                            decimal_digits="4"
+                            follows="left|top"
+                            height="16"
+                            increment="0.0001"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.0001"
+                            max_val="2"
+                            name="density_multip"
+                            top_delta="20"
+                            width="219"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="200">
+                        Distance Multiplier:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0.8"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.05"
+                            max_val="1000"
+                            name="distance_multip"
+                            top_delta="20"
+                            width="219"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="25"
+                            width="200">
+                        Maximum Altitude:
+                    </text>
+                    <slider
+                            decimal_digits="1"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="10000"
+                            name="max_alt"
+                            top_delta="20"
+                            width="219"
+                            can_edit_text="true"/>
+                </layout_panel>            
+            </layout_stack>                
+        </layout_panel>
+    </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ac3b45d24c3aa6c74c414b7bda6ea247f35fc022
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_clouds.xml
@@ -0,0 +1,271 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+        border="true"
+        follows="all"
+        label="Clouds"
+        layout="topleft"
+        left="0"
+        help_topic="land_general_tab"
+        name="panel_settings_sky_clouds"
+        top="0">
+    <layout_stack 
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            orientation="hoizontal">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="75">
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="15"
+                    top_pad="15"
+                    width="80">
+                Cloud Color:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="0"
+                    name="cloud_color"
+                    top_pad="5"
+                    width="60" />
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="0"
+                    top_delta="47"
+                    width="200">
+                Cloud Coverage:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_coverage"
+                    top_delta="20"
+                    width="214"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="25"
+                    width="200">
+                Cloud Scale:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0.01"
+                    max_val="3"
+                    name="cloud_scale"
+                    top_delta="20"
+                    width="214"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="25"
+                    width="200">
+                Cloud Variance:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1.0"
+                    name="cloud_variance"
+                    top_delta="20"
+                    width="214"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="25"
+                    width="200">
+                Cloud Scroll:
+            </text>
+            <xy_vector
+                    follows="left|top"
+                    name="cloud_scroll_xy"
+                    width="127"
+                    height="145"
+                    visible="true"
+                    left_delta="0"
+                    top_delta="21"
+                    min_val_x="-30"
+                    max_val_x="30"
+                    min_val_y="-30"
+                    max_val_y="30" 
+                    logarithmic="1"/>
+
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="160"
+                    top_delta="-20"
+                    width="200">
+                Cloud Image:
+            </text>
+            <texture_picker
+                    height="123"
+                    layout="topleft"
+                    left_delta="5"
+                    name="cloud_map"
+                    top_pad="10"
+                    width="100"/>
+        </layout_panel>
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="75">
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="15"
+                    top_pad="15"
+                    width="200">
+                Cloud Density:
+            </text>
+            <slider
+                    label="X"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_density_x"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+            <slider
+                    label="Y"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="0"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_density_y"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+            <slider
+                    label="D"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="0"
+                    min_val="0"
+                    max_val="3"
+                    name="cloud_density_d"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="35"
+                    width="200">
+                Cloud Detail:
+            </text>
+            <slider
+                    label="X"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_detail_x"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+            <slider
+                    label="Y"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="0"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_detail_y"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+            <slider
+                    label="D"
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="0"
+                    min_val="0"
+                    max_val="1"
+                    name="cloud_detail_d"
+                    top_delta="20"
+                    width="200"
+                    can_edit_text="true"/>
+        </layout_panel>
+    </layout_stack>
+</panel>                
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b3a33961bcc45a4f99a0a0e0594251ce785f3e9d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_density.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+        border="true"
+        follows="all"
+        label="Density"
+        layout="topleft"
+        left="0"
+        help_topic="sky_density"
+        name="panel_settings_sky_density"
+        top="0">
+    <layout_stack 
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            orientation="vertical">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="12">
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1"
+                    name="rayleigh_exponential"
+                    label="Rayleigh Exponential Term:"
+                    top_pad="12"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="-0.01"
+                    max_val="0.01"
+                    name="rayleigh_exponential_scale"
+                    label="Rayleigh Exponential Scale:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="0.00001"
+                    name="rayleigh_linear"
+                    label="Rayleigh Linear Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="1"
+                    name="rayleigh_constant"
+                    label="Rayleigh Constant Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="1"
+                    follows="left|top"
+                    height="14"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="1000"
+                    max_val="40000"
+                    name="rayleigh_max_altitude"
+                    label="Rayleigh Max Altitude:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+        </layout_panel>
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="14">
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="3.0"
+                    name="mie_exponential"
+                    label="Mie Exponential Term:"
+                    top_pad="12"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="-0.01"
+                    max_val="0.01"
+                    name="mie_exponential_scale"
+                    label="Mie Exponential Scale:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="0.000004"
+                    name="mie_linear"
+                    label="Mie Linear Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="1"
+                    name="mie_constant"
+                    label="Mie Constant Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="14"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0.2"
+                    max_val="1.8"
+                    name="mie_aniso_factor"
+                    label="Mie Aniso Factor:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="1"
+                    follows="left|top"
+                    height="14"
+                    increment="0.1"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="1000"
+                    max_val="30000"
+                    name="mie_max_altitude"
+                    label="Mie Max Altitude:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+        </layout_panel>
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="12">
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1"
+                    name="absorption_exponential"
+                    label="Absorption Exponential Term:"
+                    top_pad="8"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="-1"
+                    max_val="1"
+                    name="absorption_exponential_scale"
+                    label="Absorption Exponential Scale:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="1"
+                    name="absorption_linear"
+                    label="Absorption Linear Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="6"
+                    follows="left|top"
+                    height="14"
+                    increment="0.0000001"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="0"
+                    max_val="1"
+                    name="absorption_constant"
+                    label="Absorption Constant Term:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+            <slider
+                    decimal_digits="1"
+                    follows="left|top"
+                    height="14"
+                    increment="0.1"
+                    initial_value="0"
+                    layout="topleft"
+                    min_val="1000"
+                    max_val="25000"
+                    name="absorption_max_altitude"
+                    label="Absorption Max Altitude:"
+                    width="400"
+                    label_width="160"
+                    can_edit_text="true"/>
+        </layout_panel>
+    </layout_stack>
+</panel> 
diff --git a/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0e3de821d19c8c34aa1f3734b968bcd29ff24897
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,319 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+        border="true"
+        follows="all"
+        label="Sun &amp; Moon"
+        layout="topleft"
+        left="0"
+        name="panel_settings_sky_hbodies"
+        top="0">
+    <layout_stack 
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            orientation="horizontal">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                name="sun_layout"
+                height="400">
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="15"
+                    top_pad="15"
+                    font="SansSerifBold"
+                    width="120">
+                Sun &amp; Stars
+            </text>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="10"
+                    top_delta="30"
+                    width="100">
+                Position:
+            </text>
+            <sun_moon_trackball
+                    name="sun_rotation"
+                    follows="left|top"
+                    left_delta="0"
+                    top_delta="20"
+                    height="150"
+                    width="150"
+                    thumb_mode="sun" />
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="160"
+                    top_delta="-20"
+                    width="200">
+                Image:
+            </text>
+            <texture_picker
+                    height="123"
+                    layout="topleft"
+                    left_delta="5"
+                    name="sun_image"
+                    top_pad="10"
+                    width="100"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="110"
+                    width="80">
+                Scale:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0.25"
+                    max_val="20"
+                    name="sun_scale"
+                    top_delta="15"
+                    width="130"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="20"
+                    width="80">
+                Color:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="5"
+                    name="sun_moon_color"
+                    top_pad="5"
+                    width="60" />
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-160"
+                    top_delta="27"
+                    width="200">
+                Glow Focus:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="-2"
+                    max_val="2"
+                    name="glow_focus"
+                    top_delta="15"
+                    width="250"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="22"
+                    width="200">
+                Glow Size:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="1.99"
+                    name="glow_size"
+                    top_delta="15"
+                    width="250"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="topleft"
+                    left_delta="-5"
+                    top_delta="22"
+                    width="200">
+                Star Brightness:
+            </text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="topleft"
+                    left_delta="5"
+                    min_val="0"
+                    max_val="500"
+                    name="star_brightness"
+                    top_delta="15"
+                    width="250"
+                    can_edit_text="true"/>
+                    
+            <check_box
+                    control_name="sunbeacon"
+                    width="60"
+                    height="16"
+                    label="Show Beacon"
+                    layout="topleft"
+                    name="sunbeacon" 
+                    right="-50"
+                    bottom="-10"
+                    follows="bottom|right"/>
+                    
+        </layout_panel>
+        <layout_panel
+                border="false"
+                bevel_style="in"
+                auto_resize="true"
+                user_resize="false"
+                visible="true"
+                height="400">
+            <layout_stack 
+                    left="5"
+                    top="5"
+                    right="-5"
+                    bottom="-5"
+                    follows="left|top|right|bottom"
+                    orientation="vertical">
+                <layout_panel
+                        border="true"
+                        bevel_style="in"
+                        auto_resize="true"
+                        user_resize="false"
+                        visible="true"
+                        name="moon_layout"
+                        height="220">
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="15"
+                            top_pad="15"
+                            font="SansSerifBold"
+                            width="80">
+                        Moon
+                    </text>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="10"
+                            top_delta="30"
+                            width="100">
+                        Position:
+                    </text>
+                    <sun_moon_trackball
+                            name="moon_rotation"
+                            follows="left|top"
+                            left_delta="0"
+                            top_delta="20"
+                            height="150"
+                            width="150"
+                            thumb_mode="moon" />
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="160"
+                            top_delta="-20"
+                            width="200">
+                        Image:
+                    </text>
+                    <texture_picker
+                            height="123"
+                            layout="topleft"
+                            left_delta="5"
+                            name="moon_image"
+                            top_pad="10"
+                            width="100"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="110"
+                            width="80">
+                        Scale:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.25"
+                            max_val="20"
+                            name="moon_scale"
+                            top_delta="15"
+                            width="130"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top"
+                            height="10"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_delta="22"
+                            width="200">
+                        Brightness:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0.0"
+                            max_val="1.0"
+                            name="moon_brightness"
+                            top_delta="15"
+                            width="130"
+                            can_edit_text="true"/>
+                <check_box
+                        control_name="moonbeacon"
+                        width="60"
+                        height="16"
+                        label="Show Beacon"
+                        layout="topleft"
+                        name="moonbeacon" 
+                        right="-50"
+                        bottom="-10"
+                        follows="bottom|right"/>
+                            
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
+    </layout_stack>
+</panel>                
diff --git a/indra/newview/skins/default/xui/en/panel_settings_water.xml b/indra/newview/skins/default/xui/en/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..991ce25becef969d12d4587312213bd1215775df
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_settings_water.xml
@@ -0,0 +1,374 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+        border="true"
+        follows="all"
+        label="Water"
+        layout="topleft"
+        left="0"
+        help_topic="land_general_tab"
+        name="panel_settings_water"
+        top="0">    
+    <layout_stack name="water_stack1"
+            follows="all"
+            layout="topleft"
+            left="5"
+            top="5"
+            right="-5"
+            bottom="-5"
+            orientation="vertical">
+        <layout_panel
+                border="true"
+                bevel_style="in"
+                auto_resize="false"
+                user_resize="false"
+                visible="true"
+                height="105">
+            <text
+                    follows="left|top"
+                    height="20"
+                    font="SansSerif"
+                    layout="topleft"
+                    left="5"
+                    top="5"
+                    width="215">
+                Water Fog:
+            </text>
+            <text
+                    follows="left|top"
+                    height="10"
+                    layout="left|top"
+                    left_delta="15"
+                    top_delta="0"
+                    width="60">
+                Color:
+            </text>
+            <color_swatch
+                    can_apply_immediately="true"
+                    follows="left|top"
+                    height="37"
+                    label_height="0"
+                    layout="topleft"
+                    left_delta="0"
+                    name="water_fog_color"
+                    top_pad="5"
+                    width="60" />
+            <text
+                    follows="left|top"
+                    height="10"
+                    top_delta="-15"
+                    left_delta="80"
+                    width="150">
+                Density Exponent:
+            </text>
+            <slider
+                    decimal_digits="1"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="top"
+                    left_delta="15"
+                    min_val="-10"
+                    max_val="10"
+                    name="water_fog_density"
+                    top_delta="5"
+                    width="150"
+                    can_edit_text="true"/>
+            <text
+                    follows="left|top"
+                    height="10"
+                    top_delta="25"
+                    left_delta="-15"
+                    width="150">
+                Underwater Modifier:</text>
+            <slider
+                    decimal_digits="2"
+                    follows="left|top"
+                    height="16"
+                    increment="0.01"
+                    initial_value="0"
+                    layout="top"
+                    left_delta="15"
+                    min_val="0.0"
+                    max_val="20.0"
+                    name="water_underwater_mod"
+                    top_delta="20"
+                    width="150"
+                    can_edit_text="true"/>
+                    
+                    <text
+                            follows="left|top|right"
+                            height="10"
+                            layout="topleft"
+                            left_delta="165"
+                            top_delta="-53"
+                            width="150">
+                        Fresnel Scale:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0.7"
+                            layout="topleft"
+                            left_delta="5"
+                            name="water_fresnel_scale"
+                            top_delta="15"
+                            width="150"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top|right"
+                            layout="topleft"
+                            left_delta="-5"
+                            name="FresnelOffsetText"
+                            top_delta="25"
+                            width="150">
+                        Fresnel Offset:
+                    </text>
+                    <slider
+                            decimal_digits="2"
+                            follows="left|top"
+                            increment="0.01"
+                            initial_value="0.7"
+                            height="16"
+                            layout="topleft"
+                            left_delta="5"
+                            name="water_fresnel_offset"
+                            top_pad="5"
+                            width="150"
+                            can_edit_text="true"/>
+                    
+        </layout_panel>
+        <layout_panel
+                auto_resize="true"
+                user_resize="false"
+                visible="true">
+            <layout_stack name="water_stack2"
+                    left="5"
+                    top="5"
+                    right="-5"
+                    bottom="-5"
+                    follows="left|top|right|bottom"
+                    orientation="horizontal">
+                <layout_panel
+                        border="true"
+                        bevel_style="in"
+                        auto_resize="true"
+                        user_resize="false"
+                        visible="true"
+                        min_width="460"
+                        width="50">
+                    <text
+                            follows="left|top|right"
+                            height="16"
+                            layout="topleft"
+                            left="15"
+                            top="5"
+                            width="215">
+                        Normal Map
+                    </text>
+                    <texture_picker
+                            height="84"
+                            layout="topleft"
+                            left_delta="0"
+                            name="water_normal_map"
+                            top_pad="5"
+                            width="61"/>
+
+                    <text
+                            follows="left|top"
+                            height="16"
+                            width="120"
+                            layout="topleft"
+                            top_delta="-20"
+                            left_delta="175">
+                        Large Wave Speed
+                    </text>
+                    <xy_vector
+                        follows="top|left"
+                        name="water_wave1_xy"
+                        width="120"
+                        height="145"
+                        visible="true"
+                        left_delta="0"
+                        top_delta="21"
+                        min_val_x="-20"
+                        max_val_x="20"
+                        increment_x="0.01f"
+                        min_val_y="-20"
+                        max_val_y="20"
+                        increment_y="0.01f"
+                        arrow_color="white"/>
+                    
+                    <text
+                            follows="left|top"
+                            height="16"
+                            layout="topleft"
+                            top_delta="-20"
+                            left_delta="140">
+                        Small Wave Speed
+                    </text>
+                    <xy_vector
+                        follows="top|left"
+                        name="water_wave2_xy"
+                        width="120"
+                        height="145"
+                        visible="true"
+                        left_delta="0"
+                        top_delta="21"
+                        min_val_x="-20"
+                        max_val_x="20"
+                        min_val_y="-20"
+                        max_val_y="20" 
+                        increment_x="0.01f"
+                        increment_y="0.01f"
+                        arrow_color="white"/>
+
+                    <text
+                            follows="left|top|right"
+                            height="16"
+                            layout="topleft"
+                            left="10"
+                            top="90"
+                            width="215">
+                        Reflection Wavelet Scale
+                    </text>
+                    <slider
+                            decimal_digits="1"
+                            follows="left|top"
+                            increment="0.01"
+                            height="16"
+                            initial_value="0.7"
+                            layout="topleft"
+                            label="X:"
+                            left_delta="10"
+                            max_val="10"
+                            name="water_normal_scale_x"
+                            top_pad="5"
+                            width="150"
+                            can_edit_text="true"/>
+                    <slider
+                            decimal_digits="1"
+                            follows="left|top"
+                            increment="0.01"
+                            initial_value="0.7"
+                            height="16"
+                            layout="topleft"
+                            max_val="10"
+                            name="water_normal_scale_y"
+                            top_pad="6"
+                            label="Y:"
+                            width="150"
+                            can_edit_text="true"/>
+                    <slider
+                            decimal_digits="1"
+                            follows="left|top"
+                            increment="0.01"
+                            initial_value="0.7"
+                            height="16"
+                            layout="topleft"
+                            max_val="10"
+                            name="water_normal_scale_z"
+                            top_pad="6"
+                            label="Z:"
+                            width="150"
+                            can_edit_text="true"/>                            
+                        
+                </layout_panel>
+                <layout_panel
+                        border="true"
+                        bevel_style="in"
+                        auto_resize="true"
+                        user_resize="false"
+                        width="50"
+                        visible="true">
+                    <text
+                            follows="left|top"
+                            height="20"
+                            font="SansSerif"
+                            layout="topleft"
+                            left="5"
+                            top="5"
+                            width="215">
+                        Refraction And Blur:
+                    </text>
+                    <text
+                            follows="left|top|right"
+                            height="16"
+                            layout="topleft"
+                            top_delta="25"
+                            left_delta="5"
+                            width="215">
+                        Refraction Scale (Above)
+                    </text>
+                    <slider
+                            control_name="water_scale_above"
+                            decimal_digits="2"
+                            follows="left|top"
+                            increment="0.01"
+                            initial_value="0.1"
+                            height="16"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="3"
+                            name="water_scale_above"
+                            top_pad="5"
+                            width="200"
+                            can_edit_text="true" />
+                    <text
+                            type="string"
+                            length="1"
+                            follows="left|top|right"
+                            height="16"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_pad="5"
+                            width="215">
+                        Refraction Scale (Below)
+                    </text>
+                    <slider
+                            control_name="water_scale_below"
+                            decimal_digits="2"
+                            follows="left|top"
+                            height="16"
+                            increment="0.01"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="0"
+                            max_val="3"
+                            name="water_scale_below"
+                            top_pad="5"
+                            width="200"
+                            can_edit_text="true"/>
+                    <text
+                            follows="left|top|right"
+                            font="SansSerif"
+                            height="16"
+                            layout="topleft"
+                            left_delta="-5"
+                            top_pad="5"
+                            width="215">
+                        Blur Multiplier
+                    </text>
+                    <slider
+                            control_name="water_blur_multip"
+                            follows="left|top"
+                            height="16"
+                            increment="0.001"
+                            initial_value="0"
+                            layout="topleft"
+                            left_delta="5"
+                            min_val="-0.5"
+                            max_val="0.5"
+                            name="water_blur_multip"
+                            top_pad="5"
+                            width="200"
+                            can_edit_text="true"/>
+                </layout_panel>
+            </layout_stack>
+        </layout_panel>
+    </layout_stack>
+</panel>     
diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml
index f79d752fdb10dae0399ef9d42da594a7b46eb891..bda08f34219e220f7cd2c3f5d5316e82cc051cd8 100644
--- a/indra/newview/skins/default/xui/en/role_actions.xml
+++ b/indra/newview/skins/default/xui/en/role_actions.xml
@@ -92,7 +92,10 @@
 		<action description="Toggle various About Land &gt; Options settings"
 		     longdescription="Toggle &apos;Safe (no damage)&apos;, &apos;Fly&apos;, and allow other Residents to: &apos;Edit Terrain&apos;, &apos;Build&apos;, &apos;Create Landmarks&apos;, and &apos;Run Scripts&apos; on group-owned land in About Land &gt; Options tab."
 		     name="land options" value="22" />
-	</action_set>
+    <action description="Modify environment settings and day cycle."
+		     longdescription="Change the environment settings and day cycle from the About Land &gt; Environment tab."
+		     name="land change environment" value="46" />
+  </action_set>
 	<action_set
 	     description="These Abilities include powers which allow Members to bypass restrictions on group-owned parcels."
 	     name="Parcel Powers">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 41ec0f8cfba3493bc7e57e9a4b0768fb92afe3d2..1bfac6aeb7bb0b8a450cf04e7adb2e41daeb2c09 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -300,6 +300,17 @@ Please try logging in again in a minute.</string>
 	<string name="BUTTON_DOCK">Dock</string>
 	<string name="BUTTON_HELP">Show Help</string>
 
+	<!-- ToolTips for notecards -->
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+Items of this type can't be attached
+to notecards on this region.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+Only items with unrestricted
+'next owner' permissions
+can be attached to notecards.
+	</string>
+
 	<!-- searching - generic -->
 	<string name="Searching">Searching...</string>
 	<string name="NoneFound">None found.</string>
@@ -352,6 +363,11 @@ Error in upload request.  Please visit
 http://secondlife.com/support for help fixing this problem.
 </string>
 
+	<!-- Settings errors -->
+	<string name="SettingValidationError">Validation failed for importing settings [NAME]</string>
+	<string name="SettingImportFileError">Could not open file [FILE]</string>
+	<string name="SettingParseFileError">Could not open file [FILE]</string>
+	<string name="SettingTranslateError">Could not translate legacy windlight [NAME]</string>
 	<!-- Asset Type human readable names:  these will replace variable [TYPE] in notification FailedToFindWearable* -->
 	<!-- Will also replace [OBJECTTYPE] in notifications: UserGiveItem, ObjectGiveItem -->
 	<string name="texture">texture</string>
@@ -379,7 +395,8 @@ http://secondlife.com/support for help fixing this problem.
 	<string name="favorite">favorite</string>
 	<string name="symbolic link">link</string>
 	<string name="symbolic folder link">folder link</string>
-  <string name="mesh">mesh</string>
+	<string name="settings blob">settings</string>
+	<string name="mesh">mesh</string>
 
 	<!-- llvoavatar. Displayed in the avatar chat bubble -->
 	<string name="AvatarEditingAppearance">(Editing Appearance)</string>
@@ -504,6 +521,7 @@ http://secondlife.com/support for help fixing this problem.
 	<string name="ManageEstateSilently">Manage your estates silently</string>
 	<string name="ChangeYourDefaultAnimations">Change your default animations</string>
 	<string name="ForceSitAvatar">Force your avatar to sit</string>
+	<string name="ChangeEnvSettings">Change your environment settings</string>
 	
 	<string name="NotConnected">Not Connected</string>
 	<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
@@ -2767,6 +2785,14 @@ If you continue to receive this message, please contact Second Life support for
 	<string name="LocalSettings">Local Settings</string>
 	<string name="RegionSettings">Region Settings</string>
 
+	<string name="NoEnvironmentSettings">This Region does not support environmental settings.</string>
+	<string name="EnvironmentSun">Sun</string>
+	<string name="EnvironmentMoon">Moon</string>
+	<string name="EnvironmentBloom">Bloom</string>
+	<string name="EnvironmentCloudNoise">Cloud Noise</string>
+	<string name="EnvironmentNormalMap">Normal Map</string>
+	<string name="EnvironmentTransparent">Transparent</string>
+
 	<!-- panel classified -->
 	<string name="ClassifiedClicksTxt">Clicks: [TELEPORT] teleport, [MAP] map, [PROFILE] profile</string>
 	<string name="ClassifiedUpdateAfterPublish">(will update after publish)</string>
@@ -3839,6 +3865,12 @@ Abuse Report</string>
   <string name="Female - Stick tougue out">Female - Stick tongue out</string>
   <string name="Female - Wow">Female - Wow</string>
 
+<!-- settings -->
+  <string name="New Daycycle">New Daycycle</string>
+  <string name="New Water">New Water</string>
+  <string name="New Sky">New Sky</string>
+  
+
   <string name="/bow">/bow</string>
   <string name="/clap">/clap</string>
   <string name="/count">/count</string>
@@ -4063,6 +4095,8 @@ Try enclosing path to the editor with double quotes.
   <string name="BeaconScriptedTouch">Viewing scripted object with touch function beacons (red)</string>
   <string name="BeaconSound">Viewing sound beacons (yellow)</string>
   <string name="BeaconMedia">Viewing media beacons (white)</string>
+  <string name="BeaconSun">Viewing sun direction beacon (orange)</string>
+  <string name="BeaconMoon">Viewing moon direction beacon (purple)</string>
   <string name="ParticleHiding">Hiding Particles</string>
 
   <!-- commands -->
@@ -4075,6 +4109,7 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Conversations_Label">Conversations</string>
   <string name="Command_Compass_Label">Compass</string>
   <string name="Command_Destinations_Label">Destinations</string>
+  <string name="Command_Environments_Label">My Environments</string>
   <string name="Command_Gestures_Label">Gestures</string>
   <string name="Command_Grid_Status_Label">Grid status</string>
   <string name="Command_HowTo_Label">How to</string>
@@ -4104,6 +4139,7 @@ Try enclosing path to the editor with double quotes.
   <string name="Command_Conversations_Tooltip">Converse with everyone</string>
   <string name="Command_Compass_Tooltip">Compass</string>
   <string name="Command_Destinations_Tooltip">Destinations of interest</string>
+  <string name="Command_Environments_Tooltip">My Environments</string>
   <string name="Command_Gestures_Tooltip">Gestures for your avatar</string>
   <string name="Command_Grid_Status_Tooltip">Show current Grid status</string>
   <string name="Command_HowTo_Tooltip">How to do common tasks</string>
@@ -4178,6 +4214,8 @@ Try enclosing path to the editor with double quotes.
   <string name="ExperiencePermission10">control your camera</string>
   <string name="ExperiencePermission11">teleport you</string>
   <string name="ExperiencePermission12">automatically accept experience permissions</string>
+  <string name="ExperiencePermission16">force your avatar to sit</string>
+  <string name="ExperiencePermission17">change your environment settings</string>
   <string name="ExperiencePermissionShortUnknown">perform an unknown operation: [Permission]</string>
   <string name="ExperiencePermissionShort1">Take Controls</string>
   <string name="ExperiencePermissionShort3">Trigger Animations</string>
@@ -4186,6 +4224,8 @@ Try enclosing path to the editor with double quotes.
   <string name="ExperiencePermissionShort10">Control Camera</string>
   <string name="ExperiencePermissionShort11">Teleport</string>
   <string name="ExperiencePermissionShort12">Permission</string>
+  <string name="ExperiencePermissionShort16">Sit</string>
+  <string name="ExperiencePermissionShort17">Environment</string>
 
   <!-- Conversation log messages -->
   <string name="logging_calls_disabled_log_empty">
diff --git a/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml b/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0f3f0159db429746423108de61602abb59edbf0d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/density_ctrl.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<densityctrl
+ border="true"
+ follows="all"
+ label="Density"
+ name="density_ctrl"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="320"
+ height="240">
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Exponential Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_exponential"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <view
+     left_pad="15"
+     top="15"
+     name="preview_image"
+     height="140"
+     width="140"
+     follows="left|top"
+    />
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Exponential Scale Factor
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="exponential_scale"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Linear Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_linear"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="-5"
+     width="120">
+Constant Term
+    </text>
+    <slider
+     decimal_digits="2"
+     follows="left|top"
+     height="16"
+     increment="0.01"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="0"
+     max_val="1"
+     name="level_constant"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     left="15"
+     top_pad="15"
+     width="80">
+Max Altitude
+    </text>
+    <slider
+     decimal_digits="0"
+     follows="left|top"
+     height="16"
+     increment="1"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="1000"
+     max_val="40000"
+     name="max_altitude"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+
+    <text
+     follows="left|top"
+     height="11"
+     layout="topleft"
+     name="aniso_factor_label"
+     left="15"
+     top_pad="15"
+     width="80">
+Anisotropy Factor
+    </text>
+    <slider
+     decimal_digits="0"
+     follows="left|top"
+     height="16"
+     increment="1"
+     initial_value="0"
+     layout="topleft"
+     left="15"
+     min_val="1000"
+     max_val="40000"
+     name="aniso_factor"
+     top_delta="15"
+     width="200"
+     can_edit_text="true"/>
+</densityctrl>
diff --git a/indra/newview/skins/default/xui/en/widgets/joystick_quat.xml b/indra/newview/skins/default/xui/en/widgets/joystick_quat.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a190da3909959deb8f77587a2a3654637c85724e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/joystick_quat.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<joystick_rotate
+   image_selected="Cam_Rotate_In"
+   image_unselected="Cam_Rotate_Out"
+   scale_image="false"
+   mouse_opaque="false"
+   held_down_delay.seconds="0"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/joystick_rotate.xml b/indra/newview/skins/default/xui/en/widgets/joystick_rotate.xml
index a190da3909959deb8f77587a2a3654637c85724e..cbf721b346c2b9625c10e3bffd7ca9e15b7d8054 100644
--- a/indra/newview/skins/default/xui/en/widgets/joystick_rotate.xml
+++ b/indra/newview/skins/default/xui/en/widgets/joystick_rotate.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<joystick_rotate
+<joystick_quat
    image_selected="Cam_Rotate_In"
    image_unselected="Cam_Rotate_Out"
-   scale_image="false"
+   scale_image="true"
    mouse_opaque="false"
    held_down_delay.seconds="0"/>
diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
index a054960bf8cc40cbeed3dfdcba5e69ff7f0f1238..f39e0861968c217a33ae6044ae83d19af14daa2f 100644
--- a/indra/newview/skins/default/xui/en/widgets/line_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml
@@ -6,6 +6,7 @@
              commit_on_focus_lost="true"
              ignore_tab="true"
              cursor_color="TextCursorColor"
+             bg_color="White"
              text_color="TextFgColor"
 			 text_pad_left="2"
              text_readonly_color="TextFgReadOnlyColor"
diff --git a/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9fa77855c0db714a353ad1bd61d86c78ed3f4d6f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/sun_moon_trackball.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<sun_moon_trackball
+    name="virtualtrackball"
+    width="150"
+    height="150"
+    user_resize="false"     
+    increment_angle_mouse="1.5f"
+    increment_angle_btn="1.0f"    
+    image_sphere="VirtualTrackball_Sphere"
+    image_moon_back="VirtualTrackball_Moon_Back"
+    image_moon_front="VirtualTrackball_Moon_Front"
+    image_sun_back="VirtualTrackball_Sun_Back"
+    image_sun_front="VirtualTrackball_Sun_Front">
+
+    <sun_moon_trackball.border
+        visible="true"/>
+
+    <sun_moon_trackball.labelN
+        font="SansSerif"
+        name="labelN"
+        valign="bottom"
+        halign="left"
+        label="N"/>
+    <sun_moon_trackball.labelS
+        font="SansSerif"
+        name="labelS"
+        valign="top"
+        halign="left"
+        label="S"/>
+    <sun_moon_trackball.labelW
+        font="SansSerif"
+        name="labelW"
+        valign="top"
+        halign="right"
+        label="W"/>
+    <sun_moon_trackball.labelE
+        font="SansSerif"
+        name="labelE"
+        valign="top"
+        halign="left"
+        label="E"/>
+
+    <sun_moon_trackball.button_rotate_top
+        name="btn_rotate_top"
+        image_unselected="VirtualTrackball_Rotate_Top"
+        image_selected="VirtualTrackball_Rotate_Top_Active"
+        image_disabled="Blank" />
+
+    <sun_moon_trackball.button_rotate_bottom
+        name="btn_rotate_bottom"
+        image_unselected="VirtualTrackball_Rotate_Bottom"
+        image_selected="VirtualTrackball_Rotate_Bottom_Active"
+        image_disabled="Blank" />
+
+    <sun_moon_trackball.button_rotate_left
+        name="btn_rotate_left"
+        image_unselected="VirtualTrackball_Rotate_Left"
+        image_selected="VirtualTrackball_Rotate_Left_Active"
+        image_disabled="Blank" />
+
+    <sun_moon_trackball.button_rotate_right
+        name="btn_rotate_right"
+        image_unselected="VirtualTrackball_Rotate_Right"
+        image_selected="VirtualTrackball_Rotate_Right_Active"
+        image_disabled="Blank" />
+
+</sun_moon_trackball>
+
diff --git a/indra/newview/skins/default/xui/en/widgets/xy_vector.xml b/indra/newview/skins/default/xui/en/widgets/xy_vector.xml
new file mode 100644
index 0000000000000000000000000000000000000000..93ae26a6ad69b022c435cea1f065e6cda7936939
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/xy_vector.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<xy_vector
+    name="xyvector"
+    width="120"
+    height="140"
+    decimal_digits="1"
+    label_width="16"
+    padding="4"
+    edit_bar_height="18"
+    user_resize="false">
+    
+    <xy_vector.border
+        visible="true"/>
+
+    <xy_vector.x_entry
+        name="XEntry"
+        tab_stop="true"
+        label="X:"/>
+    <xy_vector.y_entry
+        name="YEntry"
+        tab_stop="true"
+        label="Y:"/>
+    
+    <xy_vector.touch_area
+        name="TouchArea"
+        bevel_style="in"
+        border_visible="true"/>
+
+</xy_vector>
diff --git a/indra/newview/skins/default/xui/es/floater_about_land.xml b/indra/newview/skins/default/xui/es/floater_about_land.xml
index 57a1b2ec1e466291001489bfa6e70a8f223b04ac..df0edd498f6e5e75a1b4a5c47d86f48d94b1f0da 100644
--- a/indra/newview/skins/default/xui/es/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/es/floater_about_land.xml
@@ -479,5 +479,6 @@ los media:
 			</panel>
 		</panel>
 		<panel label="EXPERIENCIAS" name="land_experiences_panel"/>
+		<panel label="ENTORNO" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/es/floater_adjust_environment.xml b/indra/newview/skins/default/xui/es/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..25b6fad16583e6448bb6654a3a04673d88ca1e33
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Iluminación personal">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Restablecer" name="btn_reset" tool_tip="Cerrar y restablecer Entorno compartido"/>
+					<text name="cloud_map_label">
+						Imagen nube:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Sol:
+					</text>
+					<check_box label="Mostrar baliza" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Mostrar baliza" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_beacons.xml b/indra/newview/skins/default/xui/es/floater_beacons.xml
index 49f990c84d9764783c2dab29d952d436c7a1a907..0eabcc7c276d4be07eab5a2b900e40d4ec646584 100644
--- a/indra/newview/skins/default/xui/es/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/es/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Origen de sonidos" name="sounds"/>
 		<check_box label="Origen de partículas" name="particles"/>
 		<check_box label="Fuentes de media" name="moapbeacon"/>
+		<check_box label="Sol" name="sun"/>
+		<check_box label="Luna" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
index 75e324c7efe354de69adb5fbd2a62e78ac0579cb..5ab13d2b09ab5c0fe12d6f14ff74d33eff314009 100644
--- a/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/es/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="Sonidos"/>
 	<check_box label="Texturas" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="Texturas"/>
+	<icon name="icon_setting" tool_tip="Configuración de entorno"/>
 	<button label="√ Todos" label_selected="Todo" name="check_all"/>
 	<button label="Limpiar" label_selected="Ninguno" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/es/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/es/floater_delete_env_preset.xml
deleted file mode 100644
index bd0910e5d40967354e7448866db236ba1dc1cc5b..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/es/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="ELIMINAR EL ENV PREDEFINIDO">
-	<string name="title_water">
-		Eliminar el agua predefinida
-	</string>
-	<string name="title_sky">
-		Eliminar cielo predefinido
-	</string>
-	<string name="title_day_cycle">
-		Eliminar ciclo del día
-	</string>
-	<string name="label_water">
-		Predefinido:
-	</string>
-	<string name="label_sky">
-		Predefinido:
-	</string>
-	<string name="label_day_cycle">
-		Ciclo del día:
-	</string>
-	<string name="msg_confirm_deletion">
-		¿Estás seguro de que quieres eliminar el valor predefinido seleccionado?
-	</string>
-	<string name="msg_sky_is_referenced">
-		No se puede quitar un valor predefinido al que se hace referencia en otro u otros ciclos del día.
-	</string>
-	<string name="combo_label">
-		-Selecciona un valor predefinido-
-	</string>
-	<text name="label">
-		Predefinido:
-	</text>
-	<button label="Eliminar" name="delete"/>
-	<button label="Cancelar" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/es/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c3273ea64ebe51165d3f9226a1586eb75ca36972
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Editar Ciclo del día">
+	<string name="title_new">
+		Crear un Nuevo ciclo del día
+	</string>
+	<string name="title_edit">
+		Editar Ciclo del día
+	</string>
+	<string name="hint_new">
+		Asigna un nombre al ciclo del día, ajusta los controles para crearlo y selecciona &quot;Guardar&quot;.
+	</string>
+	<string name="hint_edit">
+		Para editar el ciclo del día, ajusta los controles siguientes y selecciona &quot;Guardar&quot;.
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Cielo [ALT]
+	</string>
+	<string name="sky_label">
+		Cielo
+	</string>
+	<string name="water_label">
+		Agua
+	</string>
+	<string name="commit_parcel">
+		Aplicar a la Parcela
+	</string>
+	<string name="commit_region">
+		Aplicar a la Región
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Nombre del Ciclo del día:
+			</text>
+			<button label="Importar" name="btn_import" tool_tip="Importar configuración legado desde disco."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Cielo 4" name="sky4_track"/>
+						<button label="Cielo 3" name="sky3_track"/>
+						<button label="Cielo 2" name="sky2_track"/>
+						<button label="Nivel del terreno" name="sky1_track"/>
+						<button label="Agua" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0 %[DSC]"/>
+						<text name="p1" value="25 %[DSC]"/>
+						<text name="p2" value="50 %[DSC]"/>
+						<text name="p3" value="75 %[DSC]"/>
+						<text name="p4" value="100 %[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Clonar ruta de" name="copy_track"/>
+								<button label="Cargar ruta de" name="load_track"/>
+								<button label="Borrar ruta" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Ir hacia atrás"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Ir hacia adelante"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="Añadir [FRAME]" name="add_frame"/>
+								<button label="Cargar [FRAME]" name="btn_load_frame"/>
+								<button label="Borrar [FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Seleccionar un marco clave de la línea de tiempo indicada arriba para editar los parámetros.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Agua" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmósfera e Iluminación" name="atmosphere_panel"/>
+						<panel label="Nubes" name="clouds_panel"/>
+						<panel label="Sol y Luna" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Guardar" name="save_btn"/>
+			<button label="Cancelar" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/es/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d17dcaad0157c3ac7ce335c92564d9a08ec1c454
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Entorno fijo">
+	<string name="edit_sky">
+		Editar Cielo:
+	</string>
+	<string name="edit_water">
+		Editar Agua:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Cargar" name="btn_load" tool_tip="Cargar una configuración del inventario"/>
+			<button label="Importar" name="btn_import" tool_tip="Importar configuración legado desde disco."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Guardar" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Cancelar" name="btn_cancel" tool_tip="Volver a la última versión guardada"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml
index 5698e39beee0c7b1c94213074b83cdf707353d4e..4f3c177976723d1ae44b7222033f711ea0a003b3 100644
--- a/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Sonidos" name="check_sound"/>
 	<check_box label="Texturas" name="check_texture"/>
 	<check_box label="Fotos" name="check_snapshot"/>
+	<check_box label="Opciones" name="check_settings"/>
 	<button label="Todos" label_selected="Todo" name="All"/>
 	<button label="Ninguno" label_selected="Nada" name="None"/>
 	<check_box label="Mostrar siempre las carpetas" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/es/floater_my_environments.xml b/indra/newview/skins/default/xui/es/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8f636490acc2f0ac015b3a0da8da263b92c1b2dc
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Lugares" name="my_environments" title="MIS ENTORNOS">
+	<layout_stack>
+		<layout_panel label="Filtros" name="filter_panel">
+			<check_box label="Días" name="chk_days"/>
+			<check_box label="Cielos" name="chk_skies"/>
+			<check_box label="Agua" name="chk_water"/>
+			<filter_editor label="Filtrar entornos" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Entornos" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Mostrar todas las carpetas" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Más opciones"/>
+				<menu_button name="btn_newsettings" tool_tip="Crear una opción nueva"/>
+				<button name="btn_del" tool_tip="Quitar el ítem seleccionado"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_perms_default.xml b/indra/newview/skins/default/xui/es/floater_perms_default.xml
index 97e5390931b6a4664ec0fc628a32186c7d257c1d..7238ee7716904e45418fd1ad6302000f85d0b1f1 100644
--- a/indra/newview/skins/default/xui/es/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/es/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Definir los permisos predeterminados para la creación de ropa o partes del cuerpo">
 			Artículos de vestir
 		</text>
+		<text name="label_13" tool_tip="Definir los permisos predeterminados para la creación de parámetros de entorno">
+			Opciones
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Cancelar" label_selected="Cancelar" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/es/floater_pick_track.xml b/indra/newview/skins/default/xui/es/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44c24248a6d9611610cb723431d8fbea466b9289
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="DESTACADO: RUTA">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Seleccionar cielo fuente:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Cielo4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Cielo3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Cielo2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Terreno" name="radio_sky1" value="1."/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Cancelar" label_selected="Cancelar" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/es/floater_preferences_graphics_advanced.xml
index b8d5824fb79c3ab3f74885ad6a858b3825ebd434..2bcec020b2cbdaacbce60b8f6bfc989a973e639c 100644
--- a/indra/newview/skins/default/xui/es/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/es/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Agua transparente" name="TransparentWater"/>
 	<check_box initial_value="true" label="Efecto de relieve y brillo" name="BumpShiny"/>
 	<check_box initial_value="true" label="Puntos de luz locales" name="LocalLights"/>
-	<check_box initial_value="true" label="Shaders básicos" name="BasicShaders" tool_tip="Desactivar esta opción puede evitar que se bloqueen los controladores de algunas tarjetas gráficas"/>
 	<slider label="Nivel de detalle del terreno:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Bajo
diff --git a/indra/newview/skins/default/xui/es/floater_preview_texture.xml b/indra/newview/skins/default/xui/es/floater_preview_texture.xml
index 4012191c78871087ad6691a5c7906ac735704ac7..b0afd44750e7ea9471d3ca3993a15155836353c9 100644
--- a/indra/newview/skins/default/xui/es/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/es/floater_preview_texture.xml
@@ -10,7 +10,7 @@
 		Descripción:
 	</text>
 	<text name="dimensions">
-		[WIDTH] px x [HEIGHT] px
+		[WIDTH]px x [HEIGHT]px
 	</text>
 	<text name="aspect_ratio">
 		Previsualizar la ratio de las proporciones
diff --git a/indra/newview/skins/default/xui/es/floater_settings_picker.xml b/indra/newview/skins/default/xui/es/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73b8de30c36cf0db7e70ac02033ba3637562d56e
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="DESTACADO: CONFIGURACIÓN">
+	<floater.string name="pick title">
+		Destacado:
+	</floater.string>
+	<floater.string name="pick_track">
+		SELECCIONAR RUTA
+	</floater.string>
+	<floater.string name="pick_settings">
+		SELECCIONAR CONFIGURACIÓN
+	</floater.string>
+	<floater.string name="track_water">
+		Agua
+	</floater.string>
+	<floater.string name="track_ground">
+		Terreno
+	</floater.string>
+	<floater.string name="track_sky">
+		Cielo[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Filtrar las texturas" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Cancelar" label_selected="Cancelar" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
index 01b024bc3e40abcf859884d265bb1a9bc2856b7c..2e409ef69c9bb4fa98c26de8613b9c28d504bb38 100644
--- a/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/es/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Inventario" name="inventory" value="0"/>
 		<radio_item label="Local" name="local" value="1"/>
+		<radio_item label="Hornear" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Tamaño: [DIMENSIONS]
@@ -20,7 +21,6 @@
 	<button label="Blanca" label_selected="Blanca" name="Blank"/>
 	<button label="Ninguna" label_selected="Ninguna" left="90" name="None"/>
 	<button label="" label_selected="" name="Pipette"/>
-	<check_box initial_value="true" label="Aplicarlo ahora" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Vista previa inhabilitada"/>
 	<filter_editor label="Filtrar las texturas" name="inventory search editor"/>
 	<check_box initial_value="false" label="Ver las carpetas" name="show_folders_check"/>
@@ -31,6 +31,22 @@
 		<column label="Nombre" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Elegir la textura de horneado">
+		<combo_box.item label="Ninguno" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Esconder Región Malla Base" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
+	<check_box initial_value="true" label="Aplicarlo ahora" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/es/menu_inventory.xml b/indra/newview/skins/default/xui/es/menu_inventory.xml
index c5bc3016083f4e7070183eb6cbf7ad40289664c8..c426158d3e69e8171140451913a258c1e06d3e29 100644
--- a/indra/newview/skins/default/xui/es/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/es/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Activar" name="Marketplace Activate"/>
 	<menu_item_call label="Desactivar" name="Marketplace Deactivate"/>
 	<menu_item_call label="Compartir" name="Share"/>
-	<menu_item_call label="Comprar" name="Task Buy"/>
 	<menu_item_call label="Abrir" name="Task Open"/>
 	<menu_item_call label="Ejecutar" name="Task Play"/>
 	<menu_item_call label="Propiedades" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Ropa interior nueva" name="New Underpants"/>
 		<menu_item_call label="Nueva capa Alpha" name="New Alpha Mask"/>
 		<menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+		<menu_item_call label="Nuevo Universal" name="New Universal"/>
 		<menu_item_call label="Nueva física" name="New Physics"/>
 	</menu>
 	<menu label="Nuevas partes del cuerpo" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Pelo nuevo" name="New Hair"/>
 		<menu_item_call label="Ojos nuevos" name="New Eyes"/>
 	</menu>
+	<menu label="Nueva Configuración" name="New Settings">
+		<menu_item_call label="Nuevo Cielo" name="New Sky"/>
+		<menu_item_call label="Nueva Agua" name="New Water"/>
+		<menu_item_call label="Nuevo Ciclo del día" name="New Day Cycle"/>
+	</menu>
 	<menu label="Usar como valor predeterminado para" name="upload_def">
 		<menu_item_call label="Imágenes subidas" name="Image uploads"/>
 		<menu_item_call label="Sonidos subidos" name="Sound uploads"/>
@@ -102,6 +107,8 @@
 	<menu_item_call label="Editar" name="Wearable Edit"/>
 	<menu_item_call label="Añadir" name="Wearable Add"/>
 	<menu_item_call label="Quitarse" name="Take Off"/>
+	<menu_item_call label="Aplicar sólo a Mi mismo" name="Settings Apply Local"/>
+	<menu_item_call label="Aplicar a la Parcela" name="Settings Apply Parcel"/>
 	<menu_item_call label="Copiar en artículos del Mercado" name="Marketplace Copy"/>
 	<menu_item_call label="Mover a artículos del Mercado" name="Marketplace Move"/>
 	<menu_item_call label="--sin opciones--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/es/menu_inventory_add.xml b/indra/newview/skins/default/xui/es/menu_inventory_add.xml
index f17cfe4ceb8b2801e90f80c04572cadbc2d8234f..f9a9f3a9feedaa12bb64e820afb47e4ceee32841 100644
--- a/indra/newview/skins/default/xui/es/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/es/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Sonido ([COST] L$)..." name="Upload Sound"/>
 		<menu_item_call label="Animación ([COST] L$)..." name="Upload Animation"/>
 		<menu_item_call label="Modelo..." name="Upload Model"/>
-		<menu_item_call label="Asistente de modelo..." name="Upload Model Wizard"/>
 		<menu_item_call label="Masivo ([COST] L$ por archivo)..." name="Bulk Upload"/>
-		<menu_item_call label="Configurar los permisos por defecto de subida" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Carpeta nueva" name="New Folder"/>
 	<menu_item_call label="Script nuevo" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Ropa interior nueva" name="New Underpants"/>
 		<menu_item_call label="Nueva Alfa" name="New Alpha"/>
 		<menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+		<menu_item_call label="Nuevo Universal" name="New Universal"/>
 		<menu_item_call label="Nueva física" name="New Physics"/>
 	</menu>
 	<menu label="Nuevas partes del cuerpo" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Pelo nuevo" name="New Hair"/>
 		<menu_item_call label="Ojos nuevos" name="New Eyes"/>
 	</menu>
+	<menu label="Nueva Configuración" name="New Settings">
+		<menu_item_call label="Nuevo Cielo" name="New Sky"/>
+		<menu_item_call label="Nueva Agua" name="New Water"/>
+		<menu_item_call label="Nuevo Ciclo del día" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/es/menu_outfit_gear.xml b/indra/newview/skins/default/xui/es/menu_outfit_gear.xml
index b3f2b789d78387d47202039ab7898c5e4afcc0e5..0cfab7ffc820eeb3a308762f9861c9e9356d1018 100644
--- a/indra/newview/skins/default/xui/es/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/es/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Nueva Alfa" name="New Alpha"/>
 		<menu_item_call label="Nueva física" name="New Physics"/>
 		<menu_item_call label="Tatuaje nuevo" name="New Tattoo"/>
+		<menu_item_call label="Nuevo Universal" name="New Universal"/>
 	</menu>
 	<menu label="Nuevas partes del cuerpo" name="New Body Parts">
 		<menu_item_call label="Anatomía nueva" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/es/menu_save_settings.xml b/indra/newview/skins/default/xui/es/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..164763427db3156b4ef485f5d0a2ded421c806be
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Guardar" name="save_settings"/>
+	<menu_item_check label="Guardar como" name="save_as_new_settings"/>
+	<menu_item_check label="Asignar" name="commit_changes"/>
+	<menu_item_check label="Aplicar sólo a Mi mismo" name="apply_local"/>
+	<menu_item_check label="Aplicar a la Parcela" name="apply_parcel"/>
+	<menu_item_check label="Aplicar a la Región" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_settings_add.xml b/indra/newview/skins/default/xui/es/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..82bd384ab5cf25e0ec69f67df88493ee09a01d4a
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Nuevo Cielo" name="New Sky"/>
+	<menu_item_call label="Nueva Agua" name="New Water"/>
+	<menu_item_call label="Nuevo Ciclo del día" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_settings_gear.xml b/indra/newview/skins/default/xui/es/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5d1b43933f242393f0b5277331d400701f32105c
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Editar" name="edit_settings"/>
+	<menu_item_call label="Aplicar sólo a Mi mismo" name="Settings Apply Local"/>
+	<menu_item_call label="Aplicar a la Parcela" name="Settings Apply Parcel"/>
+	<menu_item_call label="Aplicar a la Región" name="Settings Apply Region"/>
+	<menu_item_call label="Copiar" name="copy_settings"/>
+	<menu_item_call label="Pegar" name="paste_settings"/>
+	<menu_item_call label="Copiar la UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index 7cc3c0320a7780de114b4cff9caa03690da400cf..10955567ba7b0a173a4f7964335adbcd374cc824 100644
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="Propiedades de la parcela" name="Parcel Properties"/>
 			<menu_item_check label="Menú Avanzado" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Dom" name="Sun">
+		<menu label="Entorno" name="Environment">
 			<menu_item_check label="Amanecer" name="Sunrise"/>
 			<menu_item_check label="Mediodía" name="Noon"/>
 			<menu_item_check label="Atardecer" name="Sunset"/>
 			<menu_item_check label="Medianoche" name="Midnight"/>
-			<menu_item_check label="Usar Configuración de la Región" name="Use Region Settings"/>
-		</menu>
-		<menu label="Editor de entorno" name="Environment Editor">
-			<menu_item_call label="Configuración del entorno..." name="Environment Settings"/>
-			<menu label="Agua predefinida" name="Water Presets">
-				<menu_item_call label="Nuevo predefinido..." name="new_water_preset"/>
-				<menu_item_call label="Editar predefinido..." name="edit_water_preset"/>
-				<menu_item_call label="Eliminar predefinido..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Cielos predefinidos" name="Sky Presets">
-				<menu_item_call label="Nuevo predefinido..." name="new_sky_preset"/>
-				<menu_item_call label="Editar predefinido..." name="edit_sky_preset"/>
-				<menu_item_call label="Eliminar predefinido..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Días predefinidos" name="Day Presets">
-				<menu_item_call label="Nuevo predefinido..." name="new_day_preset"/>
-				<menu_item_call label="Editar predefinido..." name="edit_day_preset"/>
-				<menu_item_call label="Eliminar predefinido..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Usar entorno compartido" name="Use Shared Environment"/>
+			<menu_item_call label="Mis entornos..." name="my_environs"/>
+			<menu_item_call label="Iluminación personal..." name="adjustment_tool"/>
+			<menu_item_check label="Pausar Nubes" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Construir" name="BuildTools">
@@ -323,6 +308,9 @@
 			<menu_item_check label="Capas alfa automáticas (no deferidas)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Animation Textures" name="Animation Textures"/>
 			<menu_item_check label="Disable Textures" name="Disable Textures"/>
+			<menu_item_check label="Desactivar ambiente" name="Disable Ambient"/>
+			<menu_item_check label="Desactivar luz del sol" name="Disable Sunlight"/>
+			<menu_item_check label="Desactivar luces locales" name="Disable Local Lights"/>
 			<menu_item_check label="Render Attached Lights" name="Render Attached Lights"/>
 			<menu_item_check label="Render Attached Particles" name="Render Attached Particles"/>
 			<menu_item_check label="Hover Glow Objects" name="Hover Glow Objects"/>
@@ -406,6 +394,7 @@
 	</menu>
 	<menu label="Admin" name="Deprecated">
 		<menu label="Take Off Clothing" name="Take Off Clothing">
+			<menu_item_call label="Universal" name="Universal"/>
 			<menu_item_call label="Física" name="Physics"/>
 		</menu>
 		<menu label="Ayuda" name="DeprecatedHelp">
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 0a3576b799d26ee9d4edb7f9730e7e4bed80eea4..86e3b5d38b8d38d89d71c93ea13429919b54bed0 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1968,6 +1968,11 @@ Se cambiarán miles de regiones, y se provocará un colapso en el espacio del se
 		Si esta opción no está seleccionada, se anularán las restricciones establecidas por los dueños de parcelas para evitar provocaciones, mantener la privacidad o proteger a los residentes menores de material para adultos. Por favor, consulte con los dueños de parcelas según sea necesario.
 		<usetemplate name="okbutton" yestext="Aceptar"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Si esta opción no está seleccionada, se anularán los entornos personalizados añadidos por los dueños a sus parcelas. Por favor, consulta con los dueños de parcelas según sea necesario. 
+¿Quieres seguir?
+		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		Tus preferencias de contenido actuales te impiden visitar la región que has seleccionado.  Puedes cambiar las preferencias en Yo &gt; Preferencias &gt; General.
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2447,7 +2452,15 @@ Publícala en una página web para que otros puedan acceder fácilmente a esta p
 		Este archivo del ciclo de un día se refiere a un archivo perdido de cielo: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		No se pudo aplicar la configuración a la región. El problema podría solucionarse saliendo de la región y regresando a ella. La razón especificada fue: [FAIL_REASON]
+		No se pudo aplicar la configuración a la región. Motivo: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Una textura local está en uso en la ruta, [TRACK], # cuadro [FRAMENO] ([FRAME]%) en el campo [FIELD]. 
+Los parámetros no pueden guardarse usando texturas locales.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Una textura local está en uso en el campo [FIELD]. 
+Los parámetros no pueden guardarse usando texturas locales.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		No se puede eliminar la última clave de este ciclo del día, ya que no puedes vaciar la caché del día. En lugar de intentar eliminar la última clave restante y después intentar crear una nueva, debes modificarla.
@@ -4387,4 +4400,76 @@ Prueba a seleccionar un terreno más pequeño.
 		[REASON]
 		<usetemplate name="okbutton" yestext="Aceptar"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		No se pudo cargar la configuración para [NAME] a partir de la base de datos.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		No se pudo aplicar esa configuración al entorno.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		No se pudo aplicar esa configuración al entorno.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Esta región no es compatible con las opciones de entorno.
+	</notification>
+	<notification label="Guardar el vestuario" name="SaveSettingAs">
+		Guardar parámetros de entorno actuales como:
+		<form name="form">
+			<input name="message">
+				[DESC] (nuevo)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Cancelar"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		No se pudo importar la configuración de Viento de luz legado [NAME] de 
+[FILE]. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		No se pudo configurar el entorno para esta parcela. 
+Por favor ingresa o selecciona una parcela cuyos derechos puedes modificar.
+	</notification>
+	<notification name="SettingsUnsuported">
+		La configuración de entorno no está disponible en esta región. 
+Por favor accede a una región cuya configuración esté disponible y vuelve a intentar.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Estás a punto de perder los cambios que realizaste en este [TYPE] llamado &quot;[NAME]&quot;. 
+¿Estás seguro de que deseas continuar?
+		<usetemplate ignoretext="¿Estás seguro de que quieres perder los cambios?" name="okcancelignore" notext="No" yestext="Sí"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Estás a punto de eliminar todos los parámetros aplicados. 
+¿Estás seguro de que deseas continuar?
+		<usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Estás a punto de eliminar todos los parámetros aplicados de iluminación personal. 
+¿Estás seguro de que deseas continuar?
+		<usetemplate name="okcancelbuttons" notext="No" yestext="Sí"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Estás a punto de importar parámetros no transferibles a este ciclo del día. Si continúas, las opciones que estás editando pasarán a ser no transferibles también. 
+
+Este cambio no se puede deshacer. 
+
+¿Estás seguro de que deseas continuar?
+		<usetemplate ignoretext="¿Estás seguro de que quieres que esta opción sea no transferible?" name="okcancelignore" notext="No" yestext="Sí"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		No puedes editar parámetros directamente en la librería. 
+Por favor, copia a tu propio inventario y vuelve a intentarlo.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Se produjo un error con estos parámetros. No pueden guardarse o aplicarse por el momento.
+	</notification>
+	<notification name="TrackLoadFailed">
+		No se pudo cargar la ruta en [TRACK].
+	</notification>
+	<notification name="TrackLoadMismatch">
+		No se pudo cargar la ruta de [TRACK1] a [TRACK2].
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/es/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/es/panel_edit_tattoo.xml
index 8776dd6c1030f16bc3c9be9b4f20ff32c7281468..6f6ee41e541b790e6fe1036fa84111f347a1635e 100644
--- a/indra/newview/skins/default/xui/es/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/es/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Tatuaje de la cabeza" name="Head Tattoo" tool_tip="Pulsa para elegir una imagen"/>
-		<texture_picker label="Tatuaje superior" name="Upper Tattoo" tool_tip="Pulsa para elegir una imagen"/>
-		<texture_picker label="Tatuaje inferior" name="Lower Tattoo" tool_tip="Pulsa para elegir una imagen"/>
-		<color_swatch label="Color/Tinte" name="Color/Tint" tool_tip="Pulsa para abrir el selector de color"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Tatuaje en la cabeza" name="Head Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje superior" name="Upper Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje inferior" name="Lower Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<color_swatch label="Color/Tinte" name="Color/Tint" tool_tip="Pulsa para abrir el selector de color"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/panel_edit_universal.xml b/indra/newview/skins/default/xui/es/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5c825b5980db9ef934aaf6152cf8fbfc96ca369d
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Tatuaje de la cabeza" name="Head Universal Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje superior" name="Upper Universal Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje inferior" name="Lower Universal Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje en falda" name="Skirt Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje en cabello" name="Hair Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje en ojos" name="Eyes Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje en brazo izquierdo" name="Left Arm Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje en pierna izquierda" name="Left Leg Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje Aux1" name="Aux1 Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje Aux2" name="Aux2 Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<texture_picker label="Tatuaje Aux3" name="Aux3 Tattoo" tool_tip="Pulsa para elegir una imagen"/>
+			<color_swatch label="Color/Tinte" name="Color/Tint" tool_tip="Pulsa para abrir el selector de color"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_edit_wearable.xml b/indra/newview/skins/default/xui/es/panel_edit_wearable.xml
index 799512968d13c357cce453ec854f45e8f13b3793..c1edf99f876ec597eaf845311fae4f202f027777 100644
--- a/indra/newview/skins/default/xui/es/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/es/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Modificando los tatuajes
 	</string>
+	<string name="edit_universal_title">
+		Modificando Universal
+	</string>
 	<string name="edit_physics_title">
 		Modificar la física
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Tatuaje:
 	</string>
+	<string name="universal_desc_text">
+		Universal:
+	</string>
 	<string name="physics_desc_text">
 		Física:
 	</string>
diff --git a/indra/newview/skins/default/xui/es/panel_region_environment.xml b/indra/newview/skins/default/xui/es/panel_region_environment.xml
index a73f1deed40dbd0a014c210da6fce226b4cf4342..3aa7e12089b1112e459fe5e52816fea1ef7f1eae 100644
--- a/indra/newview/skins/default/xui/es/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Entorno" name="panel_env_info">
-	<text name="water_settings_title">
-		Selecciona la configuración de agua y cielo/ciclo del día que deseas que vean todos los visitantes de tu región. Más información
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Usar los valores predeterminados de Second Life" name="use_sl_default_settings"/>
-		<radio_item label="Usar la configuración siguiente" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Configuración de agua
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Selecciona un valor predefinido-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Cielo/Ciclo del día
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Cielo invariable" name="my_sky_settings"/>
-			<radio_item label="Ciclo del día" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Selecciona un valor predefinido-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Selecciona un valor predefinido-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Aplicar" name="apply_btn"/>
-	<button label="Cancelar" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Usar la configuración predeterminada
+	</string>
+	<string name="str_label_use_region">
+		Usar Configuración de la Región
+	</string>
+	<string name="str_altitude_desription">
+		Cielo [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		No se ha seleccionado ninguna parcela. Las opciones de entorno están desactivadas.
+	</string>
+	<string name="str_cross_region">
+		Las opciones de entorno no están disponibles en las fronteras de regiones.
+	</string>
+	<string name="str_legacy">
+		La configuración de entorno no está disponible en esta región.
+	</string>
+	<string name="str_disallowed">
+		El administrador del estado no permite cambiar los entornos de parcela en esta región.
+	</string>
+	<string name="str_too_small">
+		La parcela debe tener como mínimo 128 metros cuadrados para ser compatible con un entorno.
+	</string>
+	<string name="str_empty">
+		(vacío)
+	</string>
+	<string name="str_region_env">
+		(entorno de la región)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Usar Inventario" name="btn_select_inventory"/>
+							<button label="Personalizar" name="btn_edit"/>
+							<check_box label="Los propietarios de parcelas pueden borrar el entorno" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Desconocido
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Desconocido
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Desconocido
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo actual."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Terreno
+						</text>
+						<line_editor name="edt_invname_ground">
+							Desconocido
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como cielo a nivel del terreno."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Agua
+						</text>
+						<line_editor name="edt_invname_water">
+							Desconocido
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Mover un parámetro desde el Inventario hasta este recuadro para seleccionarlo como agua actual."/>
+					</panel>
+					<button label="Restablecer" name="btn_rst_altitudes" tool_tip="Restablecer altitudes predeterminadas"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/panel_region_estate.xml b/indra/newview/skins/default/xui/es/panel_region_estate.xml
index b3ee34bbfd228ef4c710e1cfddae49b6194c5b77..4cfbffb887b4cab85e26aef37712546166b7863d 100644
--- a/indra/newview/skins/default/xui/es/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/es/panel_region_estate.xml
@@ -26,17 +26,17 @@
 	<check_box label="Permitir el teleporte a cualquier punto" name="allow_direct_teleport"/>
 	<button label="Aplicar" name="apply_btn"/>
 	<text name="estate_manager_label">
-		Administradores del estado:
+		Administradores de estado:
 	</text>
 	<text name="allow_resident_label">
-		Siempre permitido:
+		Siempre autorizado:
 	</text>
 	<button label="Añadir..." name="add_estate_manager_btn"/>
 	<button label="Quitar..." name="remove_estate_manager_btn"/>
 	<button label="Añadir..." name="add_allowed_avatar_btn"/>
 	<button label="Quitar..." name="remove_allowed_avatar_btn"/>
 	<text name="allow_group_label">
-		Grupos siempre permitidos:
+		Grupos siempre autorizados:
 	</text>
 	<text name="ban_resident_label">
 		Siempre prohibido:
diff --git a/indra/newview/skins/default/xui/es/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/es/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bce312dc18902a1242fa4fc3f2052df3297219d0
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmósfera e Iluminación" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/es/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/es/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0aa6f1e41a3fc2d97b29a709352c2b9d2ea047e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Nubes" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/es/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..743f901c7faa897bcafa0427571845e3f8440aa1
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Densidad" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Período exponencial Rayleigh:" name="rayleigh_exponential"/>
+			<slider label="Escala exponencial Rayleigh:" name="rayleigh_exponential_scale"/>
+			<slider label="Período lineal Rayleigh:" name="rayleigh_linear"/>
+			<slider label="Período constante Rayleigh:" name="rayleigh_constant"/>
+			<slider label="Altitud máxima Rayleigh:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Período exponencial Mie:" name="mie_exponential"/>
+			<slider label="Escala exponencial Mie:" name="mie_exponential_scale"/>
+			<slider label="Período lineal Mie:" name="mie_linear"/>
+			<slider label="Período constante Mie:" name="mie_constant"/>
+			<slider label="Factor Aniso Mie:" name="mie_aniso_factor"/>
+			<slider label="Altitud máxima Mie:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Período exponencial de Absorción:" name="absorption_exponential"/>
+			<slider label="Escala exponencial de Absorción:" name="absorption_exponential_scale"/>
+			<slider label="Período lineal de Absorción:" name="absorption_linear"/>
+			<slider label="Período constante de Absorción:" name="absorption_constant"/>
+			<slider label="Altitud máxima de Absorción:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/es/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77db74575561e84a2ee9c57070f6c5ce1272e8c6
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sol y Luna" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Mostrar baliza" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Mostrar baliza" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_settings_water.xml b/indra/newview/skins/default/xui/es/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c0d0cb56362844afc2a18d9b4e6cab86c6ede7a0
--- /dev/null
+++ b/indra/newview/skins/default/xui/es/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Agua" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Compensación Fresnel:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/es/panel_tools_texture.xml b/indra/newview/skins/default/xui/es/panel_tools_texture.xml
index 6ab95b9f5d5bd01af9e572f0a615fa70963b9930..fb1aa5019888219fb8f2d0a871b9e547acb2d0d7 100644
--- a/indra/newview/skins/default/xui/es/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/es/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Textura" name="Texture">
-	<panel.string name="string repeats per meter">
-		Repeticiones por metro
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Repeticiones por cara
-	</panel.string>
 	<text name="color label">
 		Color
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Desplazamiento horizontal" name="shinyOffsetU"/>
 	<spinner label="Desplazamiento vertical" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Alinear caras del plano" name="checkbox planar align" tool_tip="Alinear texturas en todas las caras seleccionadas con la última cara seleccionada. Requiere la representación de texturas en el plano."/>
+	<button label="Centrar" label_selected="Alinear capas de textura actuales" name="button align textures" tool_tip="Alinear capas de textura actuales"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/role_actions.xml b/indra/newview/skins/default/xui/es/role_actions.xml
index 80379da064059a7cf2c57ed5be3af3ff4d6691ca..cfa37432a8e7b17a254a6086275028e8ae6c66e3 100644
--- a/indra/newview/skins/default/xui/es/role_actions.xml
+++ b/indra/newview/skins/default/xui/es/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Cambiar música y configuraciones de los media" longdescription="Cambiar la música en streaming y las configuraciones de vídeo en Acerca del terreno &gt; pestaña Media." name="land change media" value="20"/>
 		<action description="Activar/desactivar &apos;Editar el terreno&apos;" longdescription="Activar/desactivar &apos;Editar el terreno&apos;. *AVISO* Acerca del terreno &gt; pestaña Opciones &gt; Editar el terreno, permite a cualquiera alterar la forma de su terreno y sustituir y mover plantas Linden. Asegúrese de lo que está haciendo antes de otorgar esta capacidad. La edición del terreno se activada/desactiva en Acerca del terreno &gt; pestaña Opciones." name="land edit" value="21"/>
 		<action description="Activar/desactivar varios ítems de Acerca del terreno &gt; Opciones" longdescription="Cambia &apos;Seguro (sin daño)&apos;, &apos;Volar&apos;, y el permitir a otros residentes   en terrenos propiedad del grupo &apos;Modificar el terreno&apos;, &apos;Construir&apos;, &apos;Crear hitos&apos; y &apos;Ejecutat scripts&apos;, como aparece en Acerca del terreno &gt; pestaña Opciones." name="land options" value="22"/>
+		<action description="Modificar configuración del entorno y ciclo del día" longdescription="Cambiar la configuración de entorno y el ciclo del día desde la pestaña Acerca del terreno &gt; Entorno" name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Estas capacidades incluyen poderes que permiten a los miembros rebasar las restricciones de parcelas pertenecientes al grupo." name="Parcel Powers">
 		<action description="Permitir siempre &apos;Editar el terreno&apos;" longdescription="Quien tenga un rol con esta capacidad puede editar el terreno de una parcela perteneciente al grupo aunque eso esté desactivado en Acerca del terreno &gt; pestaña Opciones." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/es/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index c9bfbd6610a30df9af45857ff735aa7cf80dec7e..af66907f8d0ee937a0209184c42938885ef25e9f 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -630,6 +630,15 @@ Intenta iniciar sesión de nuevo en unos instantes.
 	<string name="BUTTON_HELP">
 		Ver la Ayuda
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Los objetos de este tipo no se pueden adjuntar 
+a las notas de esta región.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Sólo los objetos con permisos 
+«próximo propietario» sin restricciones 
+pueden adjuntarse a las notas.
+	</string>
 	<string name="Searching">
 		Buscando...
 	</string>
@@ -706,6 +715,18 @@ Intenta iniciar sesión de nuevo en unos instantes.
 		Error en la solicitud de carga. Por favor, ingresa a 
 http://secondlife.com/support para obtener ayuda sobre cómo solucionar este problema.
 	</string>
+	<string name="SettingValidationError">
+		Error en la validación para importar los parámetros [NAME]
+	</string>
+	<string name="SettingImportFileError">
+		No se pudo abrir el archivo [FILE]
+	</string>
+	<string name="SettingParseFileError">
+		No se pudo abrir el archivo [FILE]
+	</string>
+	<string name="SettingTranslateError">
+		No se pudo traducir el Viento de luz legado [NAME]
+	</string>
 	<string name="texture">
 		la textura
 	</string>
@@ -781,6 +802,9 @@ http://secondlife.com/support para obtener ayuda sobre cómo solucionar este pro
 	<string name="symbolic folder link">
 		enlace de la carpeta
 	</string>
+	<string name="settings blob">
+		opciones
+	</string>
 	<string name="mesh">
 		red
 	</string>
@@ -1108,6 +1132,9 @@ http://secondlife.com/support para obtener ayuda sobre cómo solucionar este pro
 	<string name="ForceSitAvatar">
 		Forzar que el avatar se siente
 	</string>
+	<string name="ChangeEnvSettings">
+		Cambiar tu configuración del entorno
+	</string>
 	<string name="AgentNameSubst">
 		(Tú)
 	</string>
@@ -1256,6 +1283,9 @@ http://secondlife.com/support para obtener ayuda sobre cómo solucionar este pro
 	<string name="tattoo">
 		Tatuaje
 	</string>
+	<string name="universal">
+		Universal
+	</string>
 	<string name="physics">
 		Física
 	</string>
@@ -1298,6 +1328,9 @@ http://secondlife.com/support para obtener ayuda sobre cómo solucionar este pro
 	<string name="tattoo_not_worn">
 		Tatuaje no puesto
 	</string>
+	<string name="universal_not_worn">
+		Universal no puesto
+	</string>
 	<string name="physics_not_worn">
 		Física no puesta
 	</string>
@@ -1349,6 +1382,9 @@ http://secondlife.com/support para obtener ayuda sobre cómo solucionar este pro
 	<string name="create_new_tattoo">
 		Crear un tatuaje nuevo
 	</string>
+	<string name="create_new_universal">
+		Crear unos guantes nuevos
+	</string>
 	<string name="create_new_physics">
 		Crear nueva física
 	</string>
@@ -2484,6 +2520,27 @@ Si sigues recibiendo el mismo mensaje, solicita ayuda al personal de asistencia
 	<string name="RegionSettings">
 		Configuración de la región
 	</string>
+	<string name="NoEnvironmentSettings">
+		Esta región no es compatible con las opciones de entorno.
+	</string>
+	<string name="EnvironmentSun">
+		Sol
+	</string>
+	<string name="EnvironmentMoon">
+		Luna
+	</string>
+	<string name="EnvironmentBloom">
+		Florecimiento
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Ruido de nubes
+	</string>
+	<string name="EnvironmentNormalMap">
+		Vista Normal
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparente
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Clics: [TELEPORT] teleportes, [MAP] mapa, [PROFILE] perfil
 	</string>
@@ -4640,6 +4697,9 @@ Denuncia de infracción
 	<string name="New Tattoo">
 		Tatuaje nuevo
 	</string>
+	<string name="New Universal">
+		Nuevo Universal
+	</string>
 	<string name="New Physics">
 		Nueva física
 	</string>
@@ -4766,6 +4826,15 @@ Denuncia de infracción
 	<string name="Female - Wow">
 		Mujer - Admiración
 	</string>
+	<string name="New Daycycle">
+		Nuevo Ciclo del día
+	</string>
+	<string name="New Water">
+		Nueva Agua
+	</string>
+	<string name="New Sky">
+		Nuevo Cielo
+	</string>
 	<string name="/bow">
 		/reverencia
 	</string>
@@ -5294,6 +5363,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="BeaconMedia">
 		Viendo balizas de medios (blancas)
 	</string>
+	<string name="BeaconSun">
+		Visualización de la baliza de dirección del sol (naranja)
+	</string>
+	<string name="BeaconMoon">
+		Visualización de la baliza de dirección de la luna (violeta)
+	</string>
 	<string name="ParticleHiding">
 		Ocultando las partículas
 	</string>
@@ -5321,6 +5396,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="Command_Destinations_Label">
 		Destinos
 	</string>
+	<string name="Command_Environments_Label">
+		Mis entornos
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5414,6 +5495,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="Command_Destinations_Tooltip">
 		Destinos de interés
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Mis entornos
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Publicar en Facebook
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Subir a Flickr
 	</string>
@@ -5609,6 +5696,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="ExperiencePermission12">
 		aceptar automáticamente permisos de experiencias
 	</string>
+	<string name="ExperiencePermission16">
+		forzar que el avatar se siente
+	</string>
+	<string name="ExperiencePermission17">
+		cambiar tu configuración del entorno
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		realizar una operación desconocida: [Permission]
 	</string>
@@ -5633,6 +5726,12 @@ Inténtalo incluyendo la ruta de acceso al editor entre comillas
 	<string name="ExperiencePermissionShort12">
 		Otorgar permisos
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Sentarte
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Entorno
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		No se están registrando las conversaciones. Para empezar a grabar un registro, elige &quot;Guardar: Solo registro&quot; o &quot;Guardar: Registro y transcripciones&quot; en Preferencias &gt; Chat.
 	</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_about_land.xml b/indra/newview/skins/default/xui/fr/floater_about_land.xml
index fb65e71ee1bbf2e6886f0791b21513002c177b7e..fe863fc565c991e8a48edb6b17a0caffe617e7aa 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -484,5 +484,6 @@ musique :
 			</panel>
 		</panel>
 		<panel label="EXPÉRIENCES" name="land_experiences_panel"/>
+		<panel label="ENVIRONNEMENT" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_adjust_environment.xml b/indra/newview/skins/default/xui/fr/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca5b0ec948358dd74f03a4c072efa6c4f7d66b1f
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Éclairage personnel">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Réinitialiser" name="btn_reset" tool_tip="Fermer et réinitialiser vers l&apos;environnement partagé"/>
+					<text name="cloud_map_label">
+						Image du nuage :
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Soleil :
+					</text>
+					<check_box label="Afficher la balise" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Afficher la balise" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_beacons.xml b/indra/newview/skins/default/xui/fr/floater_beacons.xml
index ebd4dab683ccd2fc13ed814362d58ab987670419..c6adf67bac64a67b9812f870b437559cfd2de729 100644
--- a/indra/newview/skins/default/xui/fr/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/fr/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Sources sonores" name="sounds"/>
 		<check_box label="Sources des particules" name="particles"/>
 		<check_box label="Sources des médias" name="moapbeacon"/>
+		<check_box label="Soleil" name="sun"/>
+		<check_box label="Lune" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
index 02b58f9b36028e6901f86da6258d45631bcbfedf..09186b67770bdf385593c8f32881e346e797db33 100644
--- a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="Sons"/>
 	<check_box label="Textures" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="Textures"/>
+	<icon name="icon_setting" tool_tip="Paramètres d&apos;environnement"/>
 	<button label="√ Tout" label_selected="Tout" name="check_all"/>
 	<button label="Effacer" label_selected="Aucun" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/fr/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/fr/floater_delete_env_preset.xml
deleted file mode 100644
index c666a25c10a1e42425266689c9165e8b74ac825e..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/fr/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="SUPPRIMER PRÉRÉGLAGE ENV.">
-	<string name="title_water">
-		Supprimer un préréglage de l&apos;eau
-	</string>
-	<string name="title_sky">
-		Supprimer un préréglage du ciel
-	</string>
-	<string name="title_day_cycle">
-		Supprimer un cycle du jour
-	</string>
-	<string name="label_water">
-		Préréglage :
-	</string>
-	<string name="label_sky">
-		Préréglage :
-	</string>
-	<string name="label_day_cycle">
-		Cycle du jour :
-	</string>
-	<string name="msg_confirm_deletion">
-		Voulez-vous vraiment supprimer le préréglage sélectionné ?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Impossible de supprimer un préréglage référencé dans un ou plusieurs cycles du jour.
-	</string>
-	<string name="combo_label">
-		-Sélectionner un préréglage-
-	</string>
-	<text name="label">
-		Préréglage :
-	</text>
-	<button label="Supprimer" name="delete"/>
-	<button label="Annuler" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/fr/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e8e76fd5a5607ecf2678729e193b09c736e7aca
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Modifier un cycle du jour">
+	<string name="title_new">
+		Créer un nouveau cycle du jour
+	</string>
+	<string name="title_edit">
+		Modifier un cycle du jour
+	</string>
+	<string name="hint_new">
+		Donner un nom au cycle du jour, ajuster les contrôles afin de le créer, puis cliquez sur « Enregistrer ».
+	</string>
+	<string name="hint_edit">
+		Pour modifier le cycle du jour, ajustez les contrôles ci-dessous, puis cliquez sur « Enregistrer ».
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Ciel [ALT]
+	</string>
+	<string name="sky_label">
+		Ciel
+	</string>
+	<string name="water_label">
+		Eau
+	</string>
+	<string name="commit_parcel">
+		Appliquer à la parcelle
+	</string>
+	<string name="commit_region">
+		Appliquer à la région
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Nom du cycle du jour :
+			</text>
+			<button label="Importer" name="btn_import" tool_tip="Importer les paramètres hérités du disque."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Ciel 4" name="sky4_track"/>
+						<button label="Ciel 3" name="sky3_track"/>
+						<button label="Ciel 2" name="sky2_track"/>
+						<button label="Niveau du sol" name="sky1_track"/>
+						<button label="Eau" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Cloner la piste à partir" name="copy_track"/>
+								<button label="Charger la piste à partir" name="load_track"/>
+								<button label="Effacer la piste" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Reculer"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Avancer"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="Ajouter [FRAME]" name="add_frame"/>
+								<button label="Charger [FRAME]" name="btn_load_frame"/>
+								<button label="Annuler [FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Sélectionnez un cadre clé à partir du calendrier ci-dessus pour modifier les paramètres.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Eau" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmosphère et éclairage" name="atmosphere_panel"/>
+						<panel label="Nuages" name="clouds_panel"/>
+						<panel label="Soleil et lune" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Enregistrer" name="save_btn"/>
+			<button label="Annuler" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/fr/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..515a1d28435103627eb9e0d3bb8f86905b3f167d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Environnement fixe">
+	<string name="edit_sky">
+		Modifier le ciel :
+	</string>
+	<string name="edit_water">
+		Modifier l&apos;eau
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Charger" name="btn_load" tool_tip="Charger des paramètres à partir de l&apos;inventaire"/>
+			<button label="Importer" name="btn_import" tool_tip="Importer les paramètres hérités du disque."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Enregistrer" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Annuler" name="btn_cancel" tool_tip="Rétablir la dernière version enregistrée"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
index 471dddf4487fa7a286e10c8ca09f6013ef7f60d5..4e20431cc4e6410aec209ac4d56ab112ec22fe3c 100644
--- a/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Sons" name="check_sound"/>
 	<check_box label="Textures" name="check_texture"/>
 	<check_box label="Photos" name="check_snapshot"/>
+	<check_box label="Paramètres" name="check_settings"/>
 	<button label="Tout" label_selected="Tout" name="All"/>
 	<button bottom_delta="0" label="Aucun" label_selected="Aucun" name="None"/>
 	<check_box label="Toujours montrer les dossiers" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_my_environments.xml b/indra/newview/skins/default/xui/fr/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5ee6e2d5fd497970913133d47d7c215a7f62fbbf
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Endroits" name="my_environments" title="MES ENVIRONNEMENTS">
+	<layout_stack>
+		<layout_panel label="Filtres" name="filter_panel">
+			<check_box label="Jours" name="chk_days"/>
+			<check_box label="Ciels" name="chk_skies"/>
+			<check_box label="Eau" name="chk_water"/>
+			<filter_editor label="Filtrer les environnements" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Environnements" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Afficher tous les dossiers" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Plus d&apos;options"/>
+				<menu_button name="btn_newsettings" tool_tip="Créer un nouveau paramètre"/>
+				<button name="btn_del" tool_tip="Supprimer l&apos;article sélectionné"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_perms_default.xml b/indra/newview/skins/default/xui/fr/floater_perms_default.xml
index 1cea8e55ccbce9c324b59209cdf735c0261f9b51..ef56ce56639642ed9646296ed5023206fed6a77b 100644
--- a/indra/newview/skins/default/xui/fr/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/fr/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Définir les droits par défaut pour la création d’habits ou de parties de corps">
 			Articles à porter
 		</text>
+		<text name="label_13" tool_tip="Définir les autorisations par défaut pour la création des paramètres environnementaux">
+			Paramètres
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Annuler" label_selected="Annuler" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_pick_track.xml b/indra/newview/skins/default/xui/fr/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..46731bcec7d830ffb2098c3dcae9969ab3905b7e
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="CHOISIR : PISTE">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Sélectionner la source du ciel :
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Ciel4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Ciel3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Ciel2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Sol" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Annuler" label_selected="Annuler" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/fr/floater_preferences_graphics_advanced.xml
index fd47254934a6452814e9e218b33adf76a3a725ad..42af9c526dd351ff0c8a8f6fe6839d4185f29dd4 100644
--- a/indra/newview/skins/default/xui/fr/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Eau transparente" name="TransparentWater"/>
 	<check_box initial_value="true" label="Placage de relief et brillance" name="BumpShiny"/>
 	<check_box initial_value="true" label="Lumières locales" name="LocalLights"/>
-	<check_box initial_value="true" label="Effets de base" name="BasicShaders" tool_tip="La désactivation de cette option peut éviter le plantage de certains pilotes de cartes graphiques"/>
 	<slider label="Rendu du terrain :" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Faible
diff --git a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml
index 9fc9d1402647202b97a381a00423f699771975cd..d63d9903ec301a92098240d7ca2547692ddba4d0 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_texture.xml
@@ -10,12 +10,12 @@
 		Description :
 	</text>
 	<text name="dimensions">
-		[WIDTH] px x [HEIGHT] px
+		[WIDTH]px x [HEIGHT]px
 	</text>
 	<text name="aspect_ratio">
-		Aperçu du rapport hauteur/largeur
+		Rapport d&apos;aspect fixe
 	</text>
-	<combo_box name="combo_aspect_ratio" tool_tip="Aperçu avec un rapport hauteur/largeur fixe">
+	<combo_box name="combo_aspect_ratio" tool_tip="Prévisualiser avec un rapport d&apos;aspect fixe">
 		<combo_item name="Unconstrained">
 			Sans contraintes
 		</combo_item>
diff --git a/indra/newview/skins/default/xui/fr/floater_settings_picker.xml b/indra/newview/skins/default/xui/fr/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b75d8c6b8d22f97aaf63889d47e3d7b02259589d
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="CHOISIR : PARAMÈTRES">
+	<floater.string name="pick title">
+		Choisir :
+	</floater.string>
+	<floater.string name="pick_track">
+		SÉLECTIONNER UNE PISTE
+	</floater.string>
+	<floater.string name="pick_settings">
+		SÉLECTIONNEZ LES PARAMÈTRES
+	</floater.string>
+	<floater.string name="track_water">
+		Eau
+	</floater.string>
+	<floater.string name="track_ground">
+		Sol
+	</floater.string>
+	<floater.string name="track_sky">
+		Ciel[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Filtrer les textures" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Annuler" label_selected="Annuler" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
index eace67026c8dc463e4a6f151463834f8f1040807..2925727b48980670f7867cb047d89c74be7b132c 100644
--- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Inventaire" name="inventory" value="0"/>
 		<radio_item label="Local" name="local" value="1"/>
+		<radio_item label="Figer" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Taille : [DIMENSIONS]
@@ -20,7 +21,6 @@
 	<button label="Vierge" label_selected="Vierge" name="Blank" width="60"/>
 	<button label="Aucune" label_selected="Aucune" left="68" name="None" width="60"/>
 	<button bottom="-240" label="" label_selected="" name="Pipette"/>
-	<check_box initial_value="true" label="Appliquer maintenant" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Aperçu désactivé"/>
 	<filter_editor label="Filtrer les textures" name="inventory search editor"/>
 	<check_box initial_value="false" label="Afficher les dossiers" name="show_folders_check"/>
@@ -31,6 +31,22 @@
 		<column label="Nom" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Choisir la texture mixte">
+		<combo_box.item label="Aucun" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Masquer la région maillée de base" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="Annuler" label_selected="Annuler" name="Cancel"/>
+	<check_box initial_value="true" label="Appliquer maintenant" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory.xml b/indra/newview/skins/default/xui/fr/menu_inventory.xml
index c8bd7dc13013ca3ed96b4c996a3d11f4ec4cc706..f81723e6cf5e1ca1250dcd9c4600a6d982292907 100644
--- a/indra/newview/skins/default/xui/fr/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Activer" name="Marketplace Activate"/>
 	<menu_item_call label="Désactiver" name="Marketplace Deactivate"/>
 	<menu_item_call label="Partager" name="Share"/>
-	<menu_item_call label="Acheter" name="Task Buy"/>
 	<menu_item_call label="Ouvrir" name="Task Open"/>
 	<menu_item_call label="Jouer" name="Task Play"/>
 	<menu_item_call label="Propriétés" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Nouveau caleçon" name="New Underpants"/>
 		<menu_item_call label="Nouveau masque alpha" name="New Alpha Mask"/>
 		<menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+		<menu_item_call label="Nouvel environnement universel" name="New Universal"/>
 		<menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/>
 	</menu>
 	<menu label="Nouvelles parties du corps" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Nouveaux cheveux" name="New Hair"/>
 		<menu_item_call label="Nouveaux yeux" name="New Eyes"/>
 	</menu>
+	<menu label="Nouveaux paramètres" name="New Settings">
+		<menu_item_call label="Nouveau ciel" name="New Sky"/>
+		<menu_item_call label="Nouvelle eau" name="New Water"/>
+		<menu_item_call label="Nouveau cycle du jour" name="New Day Cycle"/>
+	</menu>
 	<menu label="Utiliser comme défaut pour" name="upload_def">
 		<menu_item_call label="Chargements d’images" name="Image uploads"/>
 		<menu_item_call label="Chargements de sons" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Modifier" name="Wearable Edit"/>
 	<menu_item_call label="Ajouter" name="Wearable Add"/>
 	<menu_item_call label="Enlever" name="Take Off"/>
+	<menu_item_call label="Appliquer uniquement à moi-même" name="Settings Apply Local"/>
+	<menu_item_call label="Appliquer à la parcelle" name="Settings Apply Parcel"/>
 	<menu_item_call label="Copier dans les annonces Place du marché" name="Marketplace Copy"/>
 	<menu_item_call label="Déplacer dans les annonces Place du marché" name="Marketplace Move"/>
 	<menu_item_call label="--aucune option--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_inventory_add.xml b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml
index 1076af44d996908324c8771a53649cc444144fc3..de510eaeaa1f1bbc3c7e7543586b642779cb4aa5 100644
--- a/indra/newview/skins/default/xui/fr/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/fr/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Son ([COST] L$)..." name="Upload Sound"/>
 		<menu_item_call label="Animation ([COST] L$)..." name="Upload Animation"/>
 		<menu_item_call label="Modèle..." name="Upload Model"/>
-		<menu_item_call label="Assistant Modèle..." name="Upload Model Wizard"/>
 		<menu_item_call label="Lot ([COST] L$ par fichier)..." name="Bulk Upload"/>
-		<menu_item_call label="Définir les droits de chargement par défaut" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Nouveau dossier" name="New Folder"/>
 	<menu_item_call label="Nouveau script" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Nouveau caleçon" name="New Underpants"/>
 		<menu_item_call label="Nouvel alpha" name="New Alpha"/>
 		<menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+		<menu_item_call label="Nouvel environnement universel" name="New Universal"/>
 		<menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/>
 	</menu>
 	<menu label="Nouvelles parties du corps" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Nouveaux cheveux" name="New Hair"/>
 		<menu_item_call label="Nouveaux yeux" name="New Eyes"/>
 	</menu>
+	<menu label="Nouveaux paramètres" name="New Settings">
+		<menu_item_call label="Nouveau ciel" name="New Sky"/>
+		<menu_item_call label="Nouvelle eau" name="New Water"/>
+		<menu_item_call label="Nouveau cycle du jour" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml b/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml
index 28ae2f74ad38173083439d771b5b80a0b9eb1a9e..3fce2e9f33545ed9aee3f6cb2ef8efe50971687e 100644
--- a/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/fr/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Nouvel alpha" name="New Alpha"/>
 		<menu_item_call label="Nouvelles propriétés physiques" name="New Physics"/>
 		<menu_item_call label="Nouveau tatouage" name="New Tattoo"/>
+		<menu_item_call label="Nouvel environnement universel" name="New Universal"/>
 	</menu>
 	<menu label="Nouvelles parties du corps" name="New Body Parts">
 		<menu_item_call label="Nouvelle silhouette" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/fr/menu_save_settings.xml b/indra/newview/skins/default/xui/fr/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..34a3f009254f2c7151f730bbddf26e0ea97cf6ff
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Enregistrer" name="save_settings"/>
+	<menu_item_check label="Enregistrer sous" name="save_as_new_settings"/>
+	<menu_item_check label="Valider" name="commit_changes"/>
+	<menu_item_check label="Appliquer uniquement à moi-même" name="apply_local"/>
+	<menu_item_check label="Appliquer à la parcelle" name="apply_parcel"/>
+	<menu_item_check label="Appliquer à la région" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_settings_add.xml b/indra/newview/skins/default/xui/fr/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cbd7cba494ae7c73d7ced8aeebd70546b93ca730
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Nouveau ciel" name="New Sky"/>
+	<menu_item_call label="Nouvelle eau" name="New Water"/>
+	<menu_item_call label="Nouveau cycle du jour" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_settings_gear.xml b/indra/newview/skins/default/xui/fr/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4e52d373b6e9fca05d036449e93b2499e312c00
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Modifier" name="edit_settings"/>
+	<menu_item_call label="Appliquer uniquement à moi-même" name="Settings Apply Local"/>
+	<menu_item_call label="Appliquer à la parcelle" name="Settings Apply Parcel"/>
+	<menu_item_call label="Appliquer à la région" name="Settings Apply Region"/>
+	<menu_item_call label="Copier" name="copy_settings"/>
+	<menu_item_call label="Coller" name="paste_settings"/>
+	<menu_item_call label="Copier l’UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/fr/menu_viewer.xml b/indra/newview/skins/default/xui/fr/menu_viewer.xml
index 12c50464da1920c52b03d74ea9c50f700baa087d..2594e9d0bb7a2ce0fd157c178fe89f0df61ba242 100644
--- a/indra/newview/skins/default/xui/fr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/fr/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="Propriétés de la parcelle" name="Parcel Properties"/>
 			<menu_item_check label="Menu Avancé" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Soleil" name="Sun">
+		<menu label="Environnement" name="Environment">
 			<menu_item_check label="Aube" name="Sunrise"/>
 			<menu_item_check label="Midi" name="Noon"/>
 			<menu_item_check label="Coucher de soleil" name="Sunset"/>
 			<menu_item_check label="Minuit" name="Midnight"/>
-			<menu_item_check label="Utiliser les réglages de la région" name="Use Region Settings"/>
-		</menu>
-		<menu label="Éditeur d&apos;environnement" name="Environment Editor">
-			<menu_item_call label="Paramètres d&apos;environnement..." name="Environment Settings"/>
-			<menu label="Préréglages de l&apos;eau" name="Water Presets">
-				<menu_item_call label="Nouveau préréglage..." name="new_water_preset"/>
-				<menu_item_call label="Modifier un préréglage..." name="edit_water_preset"/>
-				<menu_item_call label="Supprimer un préréglage..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Préréglages du ciel" name="Sky Presets">
-				<menu_item_call label="Nouveau préréglage..." name="new_sky_preset"/>
-				<menu_item_call label="Modifier un préréglage..." name="edit_sky_preset"/>
-				<menu_item_call label="Supprimer un préréglage..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Préréglages du jour" name="Day Presets">
-				<menu_item_call label="Nouveau préréglage..." name="new_day_preset"/>
-				<menu_item_call label="Modifier un préréglage..." name="edit_day_preset"/>
-				<menu_item_call label="Supprimer un préréglage..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Utiliser l&apos;environnement partagé" name="Use Shared Environment"/>
+			<menu_item_call label="Mes environnements..." name="my_environs"/>
+			<menu_item_call label="Éclairage personnel..." name="adjustment_tool"/>
+			<menu_item_check label="Pause des nuages" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Construire" name="BuildTools">
@@ -346,6 +331,9 @@
 			<menu_item_check label="Masques alpha automatiques (non différés)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Textures d&apos;animation" name="Animation Textures"/>
 			<menu_item_check label="Désactiver les textures" name="Disable Textures"/>
+			<menu_item_check label="Désactiver l&apos;ambiance" name="Disable Ambient"/>
+			<menu_item_check label="Désactiver la lumière du soleil" name="Disable Sunlight"/>
+			<menu_item_check label="Désactiver les lumières locales" name="Disable Local Lights"/>
 			<menu_item_check label="Textures pleine résolution" name="Rull Res Textures"/>
 			<menu_item_check label="Rendu des lumières jointes" name="Render Attached Lights"/>
 			<menu_item_check label="Rendu des particules jointes" name="Render Attached Particles"/>
@@ -483,6 +471,7 @@
 			<menu_item_call label="Jupe" name="Skirt"/>
 			<menu_item_call label="Alpha" name="Alpha"/>
 			<menu_item_call label="Tatouage" name="Tattoo"/>
+			<menu_item_call label="Universel" name="Universal"/>
 			<menu_item_call label="Propriétés physiques" name="Physics"/>
 			<menu_item_call label="Tous les habits" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index 54f132f68460dce0a1ae6641e5d9ffb84f1a46e7..41e4ad13f9b403e4e94db5616694fdf8ff1dc014 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -1959,6 +1959,11 @@ Cette action modifiera des milliers de régions et sera difficile à digérer po
 		Le fait de décocher cette option est susceptible de lever les restrictions que les propriétaires des parcelles ont ajouté pour éviter tout différend, maintenir la confidentialité ou protéger les jeunes résidents contre tout contenu réservé aux adultes. Veuillez discuter avec les propriétaires du terrain si nécessaire.
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Si vous décochez cette option, tous les environnements personnalisés que les propriétaires de parcelles ont ajoutés à leurs parcelles seront supprimés. Veuillez discuter avec les propriétaires de votre parcelle si nécessaire. 
+Souhaitez-vous continuer ?
+		<usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		La région que vous essayez de visiter comporte du contenu dont le niveau dépasse celui de vos préférences actuelles. Vous pouvez modifier vos préférences en accédant à Moi &gt; Préférences &gt; Général.
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2439,7 +2444,15 @@ Liez-la à partir d&apos;une page web pour permettre aux autres résidents d&apo
 		Une dossier semble manquer au Cycle du jour : [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		Impossible d&apos;appliquer les réglages à la région. Le problème est parfois résolu en quittant la région puis en y revenant. Motif fourni : [FAIL_REASON]
+		Impossible d&apos;appliquer les réglages à la région. Raison : [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Une texture locale est utilisée sur la piste [TRACK], le cadre n° [FRAMENO] ([FRAME]%) dans le champ [FIELD]. 
+Les paramètres ne seront peut-être pas enregistrés en utilisant les textures locales
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Une texture locale est utilisée dans le champ [FIELD]. 
+Les paramètres ne seront peut-être pas enregistrés en utilisant les textures locales
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Impossible de supprimer la dernière clé de ce cycle du jour car ce dernier ne peut pas être vide. Modifiez la dernière clé restante au lieu d&apos;essayer de la supprimer puis d&apos;en créer une nouvelle.
@@ -4389,4 +4402,76 @@ Veuillez sélectionner un terrain plus petit.
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		Impossible de charger les paramètres de [NOM] à partir de la base de données.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Impossible d&apos;appliquer ces paramètres à l&apos;environnement.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Impossible d&apos;appliquer ces paramètres à l&apos;environnement.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Cette région ne prend pas en charge les paramètres environnementaux.
+	</notification>
+	<notification label="Enregistrer la tenue" name="SaveSettingAs">
+		Enregistrer les paramètres environnementaux actuels sous :
+		<form name="form">
+			<input name="message">
+				[DESC] (nouv.)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Annuler"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Impossible d&apos;importer les paramètres Windlight [NAME] hérités de 
+[FILE]. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Impossible de définir l&apos;environnement pour cette parcelle. 
+Veuillez entrer ou sélectionner une parcelle que vous avez le droit de modifier.
+	</notification>
+	<notification name="SettingsUnsuported">
+		Les paramètres ne sont pas pris en charge dans cette région. 
+Veuillez vous déplacer dans une région où les paramètres sont activés et relancer votre action.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Vous êtes sur le point de perdre les modifications que vous avez apportées à ce [TYPE] nommé &quot;[NAME]&quot;. 
+Voulez-vous vraiment continuer ?
+		<usetemplate ignoretext="Voulez-vous vraiment perdre les modifications ?" name="okcancelignore" notext="Non" yestext="Oui"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Vous êtes sur le point de supprimer tous les paramètres appliqués. 
+Voulez-vous vraiment continuer ?
+		<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Vous êtes sur le point de supprimer tous les paramètres d&apos;éclairage personnel appliqués. 
+Voulez-vous vraiment continuer ?
+		<usetemplate name="okcancelbuttons" notext="Non" yestext="Oui"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Vous êtes sur le point d&apos;importer des paramètres non transférables dans ce cycle de jour. Si vous continuez, les paramètres que vous modifiez deviennent également non transférables. 
+
+Cette modification ne peut être être annulée. 
+
+Voulez-vous vraiment continuer ?
+		<usetemplate ignoretext="Voulez-vous vraiment que ces paramètres soient non transférables ?" name="okcancelignore" notext="Non" yestext="Oui"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Vous ne pouvez pas modifier les paramètres directement à partir de la bibliothèque. 
+Veuillez copier vers votre inventaire puis réessayer
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Nous avons rencontré un problème avec ces paramètres. Ils ne peuvent pas être enregistres ou appliqués pour l&apos;instant.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Impossible de charger la piste dans [TRACK].
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Impossible de charger la piste de [TRACK1] dans [TRACK2].
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml
index 086542dee29297ed980218ade4278326aba8f235..24b4fc212a72c8677f3414fe22df26e238c62c9e 100644
--- a/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/fr/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Tatouage tête" name="Head Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
-		<texture_picker label="Tatouage haut" name="Upper Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
-		<texture_picker label="Tatouage bas" name="Lower Tattoo" tool_tip="Cliquez pour sélectionner une image"/>
-		<color_swatch label="Coul./Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Tatouage tête" name="Head Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage haut" name="Upper Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage bas" name="Lower Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<color_swatch label="Coul./Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_universal.xml b/indra/newview/skins/default/xui/fr/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a4626123f975dcfadd52b65ca0fc2611409f70ad
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Tatouage tête" name="Head Universal Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage haut" name="Upper Universal Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage bas" name="Lower Universal Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage jupe" name="Skirt Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage cheveux" name="Hair Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage yeux" name="Eyes Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage bras gauche" name="Left Arm Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Tatouage jambe gauche" name="Left Leg Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Aux1 Tattoo" name="Aux1 Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Aux2 Tattoo" name="Aux2 Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<texture_picker label="Aux3 Tattoo" name="Aux3 Tattoo" tool_tip="Cliquer pour sélectionner une image."/>
+			<color_swatch label="Coul./Teinte" name="Color/Tint" tool_tip="Cliquez pour ouvrir le sélecteur de couleurs"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml
index def158cf68446090f05a2fa0afdfb56af91111c3..d8851bb42cbfa889a5a5c75fa83ba9712b1049c0 100644
--- a/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/fr/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Modification du tatouage
 	</string>
+	<string name="edit_universal_title">
+		Modifier l&apos;universel
+	</string>
 	<string name="edit_physics_title">
 		Modification des propriétés physiques
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Tatouage :
 	</string>
+	<string name="universal_desc_text">
+		Universel :
+	</string>
 	<string name="physics_desc_text">
 		Propriétés physiques :
 	</string>
diff --git a/indra/newview/skins/default/xui/fr/panel_region_environment.xml b/indra/newview/skins/default/xui/fr/panel_region_environment.xml
index a5be812ee5761bd2408e65c60c0b4dbb0db7b989..5212c3a9ce865dd9de58bd2d3ec467d7875ce2b6 100644
--- a/indra/newview/skins/default/xui/fr/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/fr/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Environnement" name="panel_env_info">
-	<text name="water_settings_title">
-		Sélectionnez les réglages d&apos;eau et de ciel/cycle du jour que vous souhaitez afficher pour tous les résidents visitant votre région. En savoir plus
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Utiliser les réglages par défaut de Second Life" name="use_sl_default_settings"/>
-		<radio_item label="Utiliser les réglages suivants" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Réglage de l&apos;eau
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Sélectionner un préréglage-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Ciel / Cycle du jour
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Ciel fixe" name="my_sky_settings"/>
-			<radio_item label="Cycle du jour" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Sélectionner un préréglage-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Sélectionner un préréglage-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Appliquer" name="apply_btn"/>
-	<button label="Annuler" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Utiliser les réglages par défaut
+	</string>
+	<string name="str_label_use_region">
+		Utiliser les réglages de la région
+	</string>
+	<string name="str_altitude_desription">
+		Ciel [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		Aucune parcelle n&apos;est sélectionnée. Les paramètres environnementaux sont désactivés..
+	</string>
+	<string name="str_cross_region">
+		Les paramètres environnementaux ne sont pas disponibles dans les limites des régions.
+	</string>
+	<string name="str_legacy">
+		Les paramètres environnementaux ne sont pas disponibles dans cette région.
+	</string>
+	<string name="str_disallowed">
+		Le gérant du domaine n&apos;autorise pas la modification de l&apos;environnement des parcelles dans cette région.
+	</string>
+	<string name="str_too_small">
+		La parcelle doit faire au moins 128 mètres carrés pour supporter un environnement.
+	</string>
+	<string name="str_empty">
+		(vide)
+	</string>
+	<string name="str_region_env">
+		(environnement de la région)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Utiliser l&apos;inventaire" name="btn_select_inventory"/>
+							<button label="Personnaliser" name="btn_edit"/>
+							<check_box label="Les propriétaires de parcelle peuvent neutraliser l&apos;environnement" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Ciel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Inconnu
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Faites glisser un paramètre de l&apos;inventaire vers cette zone cible pour le sélectionner comme ciel actuel."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Ciel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Inconnu
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Faites glisser un paramètre de l&apos;inventaire vers cette zone cible pour le sélectionner comme ciel actuel."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Ciel [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Inconnu
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Faites glisser un paramètre de l&apos;inventaire vers cette zone cible pour le sélectionner comme ciel actuel."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Sol
+						</text>
+						<line_editor name="edt_invname_ground">
+							Inconnu
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Faites glisser un paramètre de l&apos;inventaire vers cette zone cible pour le sélectionner comme ciel au niveau du sol."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Eau
+						</text>
+						<line_editor name="edt_invname_water">
+							Inconnu
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Faites glisser un paramètre de l&apos;inventaire vers cette zone cible pour le sélectionner comme eau actuelle."/>
+					</panel>
+					<button label="Réinitialiser" name="btn_rst_altitudes" tool_tip="Rétablir les altitudes par défaut."/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/fr/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d6491c7e7913c8a5534088b5197b73bcc3c4d11
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmosphère et éclairage" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/fr/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/fr/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..180f09653eda868d42969a5a68a89bf980fbe3bf
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Nuages" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/fr/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..107858dc208f92bf476d060b425384cf1ed869bc
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Densité" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Terme exponentiel de Rayleigh :" name="rayleigh_exponential"/>
+			<slider label="Échelle exponentielle de Rayleigh :" name="rayleigh_exponential_scale"/>
+			<slider label="Terme linéaire de Rayleigh :" name="rayleigh_linear"/>
+			<slider label="Terme constant de Rayleigh :" name="rayleigh_constant"/>
+			<slider label="Altitude maximum de Rayleigh :" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Terme exponentiel de mie :" name="mie_exponential"/>
+			<slider label="Échelle exponentielle de mie :" name="mie_exponential_scale"/>
+			<slider label="Terme linéaire de mie :" name="mie_linear"/>
+			<slider label="Terme constant de mie :" name="mie_constant"/>
+			<slider label="Facteur aniso de mie :" name="mie_aniso_factor"/>
+			<slider label="Altitude maximum de mie :" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Terme exponentiel d&apos;absorption :" name="absorption_exponential"/>
+			<slider label="Échelle exponentielle d&apos;absorption :" name="absorption_exponential_scale"/>
+			<slider label="Terme linéaire d&apos;absorption :" name="absorption_linear"/>
+			<slider label="Terme constant d&apos;absorption :" name="absorption_constant"/>
+			<slider label="Altitude maximale d&apos;absorption :" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/fr/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..39d87c9727526559c41e11ca4b18711dff1c0ac3
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Soleil et lune" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Afficher la balise" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Afficher la balise" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_settings_water.xml b/indra/newview/skins/default/xui/fr/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..203075f9871b62ab885308b0c99eadf0ef97da34
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Eau" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Décalage Fresnel :
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X :" name="water_normal_scale_x"/>
+					<slider label="Y :" name="water_normal_scale_y"/>
+					<slider label="Z :" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_tools_texture.xml b/indra/newview/skins/default/xui/fr/panel_tools_texture.xml
index 72c456aa6d4ddb6bde2e53a1b638b903742a116f..d028336ac74d3af9b514fea03200f4f9cd0e1676 100644
--- a/indra/newview/skins/default/xui/fr/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/fr/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Texture" name="Texture">
-	<panel.string name="string repeats per meter">
-		Répétitions au mètre
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Répétitions par face
-	</panel.string>
 	<text name="color label">
 		Couleur
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Décalage horizontal" name="shinyOffsetU"/>
 	<spinner label="Décalage vertical" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Aligner les faces Plan" name="checkbox planar align" tool_tip="Aligner les textures sur toutes les faces sélectionnées avec la dernière face sélectionnée. Application de la texture Plan requise."/>
+	<button label="Aligner" label_selected="Aligner les couches de texture actuelles" name="button align textures" tool_tip="Aligner les couches de texture actuelles"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/role_actions.xml b/indra/newview/skins/default/xui/fr/role_actions.xml
index d10de3843772d7f4b1025ea04ceec33373c52b17..95e4799ce43e8a94d2ebbb7fe422ef65174a34fc 100644
--- a/indra/newview/skins/default/xui/fr/role_actions.xml
+++ b/indra/newview/skins/default/xui/fr/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Modifier la musique et les médias" longdescription="Changez la musique et les médias à partir du menu À propos du terrain &gt; Médias." name="land change media" value="20"/>
 		<action description="Changer l&apos;option Modifier le terrain" longdescription="Changez l&apos;option Modifier le terrain à partir du menu À propos du terrain &gt; Options. Attention : ce pouvoir permet de terraformer votre terrain et de placer ou déplacer des plantes Linden. Assurez-vous de bien comprendre ce pouvoir avant de l&apos;attribuer. " name="land edit" value="21"/>
 		<action description="Changer diverses options du terrain" longdescription="Activez Sécurisé (pas de dégâts), Voler, et autorisez les autres résidents à : modifier le terrain, construire, créer des repères et exécuter des scripts sur les terrains appartenant au groupe dans l&apos;onglet propos du terrain &gt; Options." name="land options" value="22"/>
+		<action description="Modifier les paramètres environnementaux et le cycle du jour." longdescription="Charger les paramètres environnementaux et le cycle du jour à partir de l&apos;onglet A propos du terrain &gt; Environnement." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Ces pouvoirs permettent aux membres d&apos;outrepasser les restrictions sur les parcelles du groupe." name="Parcel Powers">
 		<action description="Toujours autoriser Modifier le terrain" longdescription="Vous pouvez modifier le relief d&apos;une parcelle du groupe, même si l&apos;option est désactivée à partir du menu À propos du terrain &gt; Options." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 959494545a251338ce604e01114e1d2dd3625bea..6d40ab4bc999d7e42237066f9eb61869876cf8e5 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -639,6 +639,15 @@ Veuillez réessayer de vous connecter dans une minute.
 	<string name="BUTTON_HELP">
 		Afficher l&apos;aide
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Les éléments de ce type ne peuvent pas être attachés 
+aux notes de cette région.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Seuls des éléments avec des autorisation 
+illimitées pour le &apos;prochain propriétaire&apos; 
+peuvent être joints aux notes.
+	</string>
 	<string name="Searching">
 		Recherche...
 	</string>
@@ -718,6 +727,18 @@ Veuillez réessayer de vous connecter dans une minute.
 		Erreur dans la demande de chargement. Veuillez consulter le site : 
 http://secondlife.com/support pour vous aider à résoudre ce problème.
 	</string>
+	<string name="SettingValidationError">
+		Échec de la validation pour l&apos;importation des paramètres [NAME]
+	</string>
+	<string name="SettingImportFileError">
+		Impossible d&apos;ouvre le fichier [FILE]
+	</string>
+	<string name="SettingParseFileError">
+		Impossible d&apos;ouvre le fichier [FILE]
+	</string>
+	<string name="SettingTranslateError">
+		Impossible de traduit les paramètres windlight hérités [NAME]
+	</string>
 	<string name="texture">
 		texture
 	</string>
@@ -793,6 +814,9 @@ http://secondlife.com/support pour vous aider à résoudre ce problème.
 	<string name="symbolic folder link">
 		lien du dossier
 	</string>
+	<string name="settings blob">
+		paramètres
+	</string>
 	<string name="mesh">
 		maillage
 	</string>
@@ -1123,6 +1147,9 @@ http://secondlife.com/support pour vous aider à résoudre ce problème.
 	<string name="ForceSitAvatar">
 		Forcez votre avatar à s’asseoir
 	</string>
+	<string name="ChangeEnvSettings">
+		Changer vos paramètres d&apos;environnement
+	</string>
 	<string name="NotConnected">
 		Pas connecté(e)
 	</string>
@@ -1274,6 +1301,9 @@ http://secondlife.com/support pour vous aider à résoudre ce problème.
 	<string name="tattoo">
 		Tatouage
 	</string>
+	<string name="universal">
+		Universel
+	</string>
 	<string name="physics">
 		Propriétés physiques
 	</string>
@@ -1316,6 +1346,9 @@ http://secondlife.com/support pour vous aider à résoudre ce problème.
 	<string name="tattoo_not_worn">
 		Tatouage non porté
 	</string>
+	<string name="universal_not_worn">
+		Universel non porté
+	</string>
 	<string name="physics_not_worn">
 		Propriétés physiques non portées
 	</string>
@@ -1367,6 +1400,9 @@ http://secondlife.com/support pour vous aider à résoudre ce problème.
 	<string name="create_new_tattoo">
 		Créer un nouveau tatouage
 	</string>
+	<string name="create_new_universal">
+		Créer un nouvel environnement universel
+	</string>
 	<string name="create_new_physics">
 		Créer de nouvelles propriétés physiques
 	</string>
@@ -2514,6 +2550,27 @@ Si vous continuez de recevoir ce message, contactez l’assistance Second Life 
 	<string name="RegionSettings">
 		Réglages de la région
 	</string>
+	<string name="NoEnvironmentSettings">
+		Cette région ne prend pas en charge les paramètres environnementaux.
+	</string>
+	<string name="EnvironmentSun">
+		Soleil
+	</string>
+	<string name="EnvironmentMoon">
+		Lune
+	</string>
+	<string name="EnvironmentBloom">
+		Éclat
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Bruit du nuage
+	</string>
+	<string name="EnvironmentNormalMap">
+		Carte normale
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparent
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Clics : [TELEPORT] téléportation, [MAP] carte, [PROFILE] profil
 	</string>
@@ -4730,6 +4787,9 @@ du rapport d&apos;infraction
 	<string name="New Tattoo">
 		Nouveau tatouage
 	</string>
+	<string name="New Universal">
+		Nouvel environnement universel
+	</string>
 	<string name="New Physics">
 		Nouvelles propriétés physiques
 	</string>
@@ -4856,6 +4916,15 @@ du rapport d&apos;infraction
 	<string name="Female - Wow">
 		Femme - Ouah !
 	</string>
+	<string name="New Daycycle">
+		Nouveau cycle du jour
+	</string>
+	<string name="New Water">
+		Nouvelle eau
+	</string>
+	<string name="New Sky">
+		Nouveau ciel
+	</string>
 	<string name="/bow">
 		/s&apos;incliner
 	</string>
@@ -5384,6 +5453,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="BeaconMedia">
 		Affichage des balises de média (blanc)
 	</string>
+	<string name="BeaconSun">
+		Balise de visibilité du soleil (orange)
+	</string>
+	<string name="BeaconMoon">
+		Observation de la balise de direction de la lune (violet)
+	</string>
 	<string name="ParticleHiding">
 		Masquage des particules
 	</string>
@@ -5411,6 +5486,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="Command_Destinations_Label">
 		Destinations
 	</string>
+	<string name="Command_Environments_Label">
+		Mes environnements
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5504,6 +5585,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="Command_Destinations_Tooltip">
 		Destinations intéressantes
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Mes environnements
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Publier sur Facebook
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Charger sur Flickr
 	</string>
@@ -5699,6 +5786,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="ExperiencePermission12">
 		accepter automatiquement les permissions d’expérience
 	</string>
+	<string name="ExperiencePermission16">
+		forcez votre avatar à s’asseoir
+	</string>
+	<string name="ExperiencePermission17">
+		changer vos paramètres d&apos;environnement
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		a effectué une opération inconnue : [Permission]
 	</string>
@@ -5723,6 +5816,12 @@ Essayez avec le chemin d&apos;accès à l&apos;éditeur entre guillemets doubles
 	<string name="ExperiencePermissionShort12">
 		Permission
 	</string>
+	<string name="ExperiencePermissionShort16">
+		M&apos;asseoir
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Environnement
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		Les conversations ne sont pas archivées. Pour commencer à tenir un journal, choisissez Enregistrer : Journal seul ou Enregistrer : Journal et transcriptions sous Préférences &gt; Chat.
 	</string>
diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml
index 70909b1f7c49b6318dcb4d7c7a0dc078a3d4c1dd..03e03095d6313099f2cf12785c1e2432944af392 100644
--- a/indra/newview/skins/default/xui/it/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/it/floater_about_land.xml
@@ -484,5 +484,6 @@ Media:
 			</panel>
 		</panel>
 		<panel label="ESPERIENZE" name="land_experiences_panel"/>
+		<panel label="AMBIENTE" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_adjust_environment.xml b/indra/newview/skins/default/xui/it/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..948e2d03aa7870fe7c20910d86abce5eb9cb5f80
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Illuminazione personale">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Reimposta" name="btn_reset" tool_tip="Chiudi e reimposta a Ambiente Condiviso"/>
+					<text name="cloud_map_label">
+						Immagine nuvola:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Sole:
+					</text>
+					<check_box label="Mostra marcatore" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Mostra marcatore" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_beacons.xml b/indra/newview/skins/default/xui/it/floater_beacons.xml
index b7ab265cc23f442061d50543bf0f768c4a5a76b6..303c2fdd6cc1017105f91b57004c5396469803c0 100644
--- a/indra/newview/skins/default/xui/it/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/it/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Fonti sonore" name="sounds"/>
 		<check_box label="Fonti delle particelle" name="particles"/>
 		<check_box label="Fonti multimedia" name="moapbeacon"/>
+		<check_box label="Sole" name="sun"/>
+		<check_box label="Luna" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
index 10bbe933e33e0c1d19911c080c989bd86ab23912..b7572f17763e2e3d582bb049f79868309ae3afde 100644
--- a/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/it/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="Suoni"/>
 	<check_box label="Texture" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="Texture"/>
+	<icon name="icon_setting" tool_tip="Impostazioni ambiente"/>
 	<button label="√ Tutti" label_selected="Tutti" name="check_all"/>
 	<button label="Cancella" label_selected="Nessuno" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/it/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/it/floater_delete_env_preset.xml
deleted file mode 100644
index 31cf01fc7bee11dceba6a8abbc920a1769d13f05..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/it/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="CANCELLA VALORE PREDEFINITO AMB">
-	<string name="title_water">
-		Cancella valore predefinito acqua
-	</string>
-	<string name="title_sky">
-		Cancella valore predefinito cielo
-	</string>
-	<string name="title_day_cycle">
-		Cancella ciclo giornata
-	</string>
-	<string name="label_water">
-		Valore predefinito:
-	</string>
-	<string name="label_sky">
-		Valore predefinito:
-	</string>
-	<string name="label_day_cycle">
-		Ciclo giornata:
-	</string>
-	<string name="msg_confirm_deletion">
-		Sei sicuro di volere eliminare il valore predefinito selezionato?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Impossibile rimuovere un valore predefinito che viene utilizzato in uno o più cicli di giornata.
-	</string>
-	<string name="combo_label">
-		-Seleziona un valore predefinito-
-	</string>
-	<text name="label">
-		Valore predefinito:
-	</text>
-	<button label="Elimina" name="delete"/>
-	<button label="Annulla" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/it/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12efdb81b5234851b7ebc173c139706859957c19
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Modifica ciclo giornata">
+	<string name="title_new">
+		Crea un nuovo ciclo giornata
+	</string>
+	<string name="title_edit">
+		Modifica ciclo giornata
+	</string>
+	<string name="hint_new">
+		Dai un nome al ciclo della giornata, regola i comandi per crearlo e fai clic su &quot;Salva&quot;.
+	</string>
+	<string name="hint_edit">
+		Per modificare il ciclo della giornata, regola i comandi seguenti e fai clic su &quot;Salva&quot;.
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Cielo [ALT]
+	</string>
+	<string name="sky_label">
+		Cielo
+	</string>
+	<string name="water_label">
+		Acqua
+	</string>
+	<string name="commit_parcel">
+		Applica al lotto
+	</string>
+	<string name="commit_region">
+		Applica alla regione
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Nome ciclo giornata:
+			</text>
+			<button label="Importa" name="btn_import" tool_tip="Importa impostazioni legacy dal disco."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Cielo 4:" name="sky4_track"/>
+						<button label="Cielo 3:" name="sky3_track"/>
+						<button label="Cielo 2:" name="sky2_track"/>
+						<button label="Suolo" name="sky1_track"/>
+						<button label="Acqua" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Clona Percorso Da" name="copy_track"/>
+								<button label="Carica Percorso Da" name="load_track"/>
+								<button label="Cancella Percorso" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Passo indietro"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Passo avanti"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="Aggiungi [FRAME]" name="add_frame"/>
+								<button label="Carica [FRAME]" name="btn_load_frame"/>
+								<button label="Elimina [FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Seleziona un fotogramma chiave dalla cronologia degli eventi qui sopra per modificare le impostazioni.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Acqua" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmosfera e illuminazione" name="atmosphere_panel"/>
+						<panel label="Nuvole" name="clouds_panel"/>
+						<panel label="Sole e Luna" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Salva" name="save_btn"/>
+			<button label="Annulla" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/it/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4ca13a5891765a4f794eccc9d67998532308e376
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Ambiente stabilito">
+	<string name="edit_sky">
+		Modifica cielo:
+	</string>
+	<string name="edit_water">
+		Modifica acqua:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Carica" name="btn_load" tool_tip="Carica impostazioni dall’inventario"/>
+			<button label="Importa" name="btn_import" tool_tip="Importa impostazioni legacy dal disco."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Salva" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Annulla" name="btn_cancel" tool_tip="Ripristina l&apos;ultima versione salvata"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
index fe41b8ca655b42261f7c49d8020ff3559636b699..c12c031198fc8b454675f200000658b6c271387b 100644
--- a/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/it/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Suoni" name="check_sound"/>
 	<check_box label="Texture" name="check_texture"/>
 	<check_box label="Fotografie" name="check_snapshot"/>
+	<check_box label="Impostazioni" name="check_settings"/>
 	<button label="Tutto" label_selected="Tutto" name="All"/>
 	<button label="Nulla" label_selected="Nulla" name="None"/>
 	<check_box label="Mostra sempre le cartelle" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/it/floater_my_environments.xml b/indra/newview/skins/default/xui/it/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bcbf4613f37c65bb3029181b54c63925535508e4
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Luoghi" name="my_environments" title="I MIEI AMBIENTI">
+	<layout_stack>
+		<layout_panel label="Filtri" name="filter_panel">
+			<check_box label="Giorni" name="chk_days"/>
+			<check_box label="Cieli" name="chk_skies"/>
+			<check_box label="Acqua" name="chk_water"/>
+			<filter_editor label="Filtra Ambienti" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Ambienti" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Mostra tutte le cartelle" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Altre opzioni"/>
+				<menu_button name="btn_newsettings" tool_tip="Crea nuova impostazione"/>
+				<button name="btn_del" tool_tip="Rimuovi l&apos;articolo selezionato"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_perms_default.xml b/indra/newview/skins/default/xui/it/floater_perms_default.xml
index 9a88f53d47187de1820aebe110225e4a6b0fa3c1..bdfea6d0ad8a49788cadc2529f864110e2d610e6 100644
--- a/indra/newview/skins/default/xui/it/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/it/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Imposta autorizzazioni predefinite per la creazione di vestiti o parti del corpo">
 			Indossabili
 		</text>
+		<text name="label_13" tool_tip="Imposta autorizzazioni predefinite per la creazione delle impostazioni dell’Ambiente">
+			Impostazioni
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Annulla" label_selected="Annulla" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/it/floater_pick_track.xml b/indra/newview/skins/default/xui/it/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8e1f3d70650fb39acf91c3c8576368084664fc0a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="PREFERITO: PERCORSO">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Seleziona fonte cielo:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Cielo4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Cielo3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Cielo2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Suolo" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Annulla" label_selected="Annulla" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/it/floater_preferences_graphics_advanced.xml
index 3773ef371163f1c8020190e9a95f15684554b1bb..53f9ebc6fd2d0709c9fccaf2c857d3e34d63f2cf 100644
--- a/indra/newview/skins/default/xui/it/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/it/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Acqua trasparente" name="TransparentWater"/>
 	<check_box initial_value="true" label="Mappatura urti e brillantezza" name="BumpShiny"/>
 	<check_box initial_value="true" label="Luci locali" name="LocalLights"/>
-	<check_box initial_value="true" label="Shader di base" name="BasicShaders" tool_tip="Se si disattiva questa opzione, si possono evitare interruzioni nei driver di alcune schede grafiche"/>
 	<slider label="Dettagli terreno:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Basso
diff --git a/indra/newview/skins/default/xui/it/floater_preview_texture.xml b/indra/newview/skins/default/xui/it/floater_preview_texture.xml
index 5b4054514e3663232160211b72b137a6d243cbcd..8e8d020067b5ee86346ebeeecb0d190a239008c9 100644
--- a/indra/newview/skins/default/xui/it/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/it/floater_preview_texture.xml
@@ -10,7 +10,7 @@
 		Descrizione:
 	</text>
 	<text name="dimensions">
-		[WIDTH] px x [HEIGHT] px
+		[WIDTH]px x [HEIGHT]px
 	</text>
 	<text name="aspect_ratio">
 		Antreprima rapporto di visualizzazione
diff --git a/indra/newview/skins/default/xui/it/floater_settings_picker.xml b/indra/newview/skins/default/xui/it/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..31dfb6ef19eef31ba3b1ad819e6025408343d12a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="PREFERITO: IMPOSTAZIONI">
+	<floater.string name="pick title">
+		Preferito:
+	</floater.string>
+	<floater.string name="pick_track">
+		SELEZIONA PERCORSO
+	</floater.string>
+	<floater.string name="pick_settings">
+		SELEZIONA IMPOSTAZIONI
+	</floater.string>
+	<floater.string name="track_water">
+		Acqua
+	</floater.string>
+	<floater.string name="track_ground">
+		Suolo
+	</floater.string>
+	<floater.string name="track_sky">
+		Cielo[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Filtro texture" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Annulla" label_selected="Annulla" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
index 27a17868a76712ec55b5ecfbbf33cf05623cf1f6..2e4644cef3efd25d0730d303005434385eb08e0a 100644
--- a/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/it/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Inventario" name="inventory" value="0"/>
 		<radio_item label="Locale" name="local" value="1"/>
+		<radio_item label="Effettua il bake" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Dimensioni: [DIMENSIONS]
@@ -19,7 +20,6 @@
 	<button label="Default" label_selected="Default" name="Default"/>
 	<button label="Vuoto" label_selected="Vuoto" name="Blank"/>
 	<button label="Niente" label_selected="Niente" name="None"/>
-	<check_box initial_value="true" label="Applica adesso" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Anteprima disattivata"/>
 	<filter_editor label="Filtro texture" name="inventory search editor"/>
 	<check_box initial_value="false" label="Mostra cartelle" name="show_folders_check"/>
@@ -30,6 +30,22 @@
 		<column label="Nome" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Scegli la bake della texture">
+		<combo_box.item label="Nessuna" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Nascondi regione mesh base" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="Annulla" label_selected="Annulla" name="Cancel"/>
+	<check_box initial_value="true" label="Applica adesso" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml
index de6855ca970234fb9b29f36555437417c3bb1492..84ec7c4bd4e0a9208f2de1becfd9cf46e106fac5 100644
--- a/indra/newview/skins/default/xui/it/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/it/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Attiva" name="Marketplace Activate"/>
 	<menu_item_call label="Disattiva" name="Marketplace Deactivate"/>
 	<menu_item_call label="Condividi" name="Share"/>
-	<menu_item_call label="Compra" name="Task Buy"/>
 	<menu_item_call label="Apri" name="Task Open"/>
 	<menu_item_call label="Esegui" name="Task Play"/>
 	<menu_item_call label="Proprietà" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Nuove mutande" name="New Underpants"/>
 		<menu_item_call label="Nuovo Alfa Mask" name="New Alpha Mask"/>
 		<menu_item_call label="Nuovo tatuaggio" name="New Tattoo"/>
+		<menu_item_call label="Nuovo Universale" name="New Universal"/>
 		<menu_item_call label="Nuova fisica" name="New Physics"/>
 	</menu>
 	<menu label="Nuove parti del corpo" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Nuovi capelli" name="New Hair"/>
 		<menu_item_call label="Nuovi occhi" name="New Eyes"/>
 	</menu>
+	<menu label="Nuove impostazioni" name="New Settings">
+		<menu_item_call label="Nuovo cielo" name="New Sky"/>
+		<menu_item_call label="Nuova acqua" name="New Water"/>
+		<menu_item_call label="Nuovo ciclo giornata" name="New Day Cycle"/>
+	</menu>
 	<menu label="Usa come impostazione predefinita per" name="upload_def">
 		<menu_item_call label="Caricamenti immagini" name="Image uploads"/>
 		<menu_item_call label="Caricamenti suoni" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Modifica" name="Wearable Edit"/>
 	<menu_item_call label="Aggiungi" name="Wearable Add"/>
 	<menu_item_call label="Togli" name="Take Off"/>
+	<menu_item_call label="Applica solo a me stesso" name="Settings Apply Local"/>
+	<menu_item_call label="Applica al lotto" name="Settings Apply Parcel"/>
 	<menu_item_call label="Copia negli annunci Marketplace" name="Marketplace Copy"/>
 	<menu_item_call label="Sposta negli annunci Marketplace" name="Marketplace Move"/>
 	<menu_item_call label="--nessuna opzione--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/it/menu_inventory_add.xml b/indra/newview/skins/default/xui/it/menu_inventory_add.xml
index e31f0ebb6987a24bc1812c0274ebcf1568a95dca..6f9212f56b9de11cf15f8c8b94b0ce5725c8565e 100644
--- a/indra/newview/skins/default/xui/it/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/it/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Suono ([COST]L$)..." name="Upload Sound"/>
 		<menu_item_call label="Animazione ([COST]L$)..." name="Upload Animation"/>
 		<menu_item_call label="Modella..." name="Upload Model"/>
-		<menu_item_call label="Procedura guidata modellazione..." name="Upload Model Wizard"/>
 		<menu_item_call label="In blocco..." name="Bulk Upload"/>
-		<menu_item_call label="Definisci diritti di caricamento predefiniti" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Nuova cartella" name="New Folder"/>
 	<menu_item_call label="Nuovo script" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Nuovi slip" name="New Underpants"/>
 		<menu_item_call label="Nuovo Alfa (trasparenza)" name="New Alpha"/>
 		<menu_item_call label="Nuovo tatuaggio" name="New Tattoo"/>
+		<menu_item_call label="Nuovo Universale" name="New Universal"/>
 		<menu_item_call label="Nuova fisica" name="New Physics"/>
 	</menu>
 	<menu label="Nuove parti del corpo" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Nuovi capelli" name="New Hair"/>
 		<menu_item_call label="Nuovi occhi" name="New Eyes"/>
 	</menu>
+	<menu label="Nuove impostazioni" name="New Settings">
+		<menu_item_call label="Nuovo cielo" name="New Sky"/>
+		<menu_item_call label="Nuova acqua" name="New Water"/>
+		<menu_item_call label="Nuovo ciclo giornata" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/it/menu_outfit_gear.xml b/indra/newview/skins/default/xui/it/menu_outfit_gear.xml
index 62c6d53e1c6aec40382a54562a1594bc595eb7e9..cf45fec09eff337d26b3ee50a4c18a05443fc8d9 100644
--- a/indra/newview/skins/default/xui/it/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/it/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Nuovo Alpha (trasparenza)" name="New Alpha"/>
 		<menu_item_call label="Nuova fisica" name="New Physics"/>
 		<menu_item_call label="Nuovo tatuaggio" name="New Tattoo"/>
+		<menu_item_call label="Nuovo Universale" name="New Universal"/>
 	</menu>
 	<menu label="Nuove parti del corpo" name="New Body Parts">
 		<menu_item_call label="Nuova figura corporea" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/it/menu_save_settings.xml b/indra/newview/skins/default/xui/it/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..80c0ef90a6fe9078f581d09bfb7b8798e7f2d61f
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Salva" name="save_settings"/>
+	<menu_item_check label="Salva con nome" name="save_as_new_settings"/>
+	<menu_item_check label="Esegui" name="commit_changes"/>
+	<menu_item_check label="Applica solo a me stesso" name="apply_local"/>
+	<menu_item_check label="Applica al lotto" name="apply_parcel"/>
+	<menu_item_check label="Applica alla regione" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_settings_add.xml b/indra/newview/skins/default/xui/it/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..69fcacc3748cf6907e9a51b4b416700526b05a1a
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Nuovo cielo" name="New Sky"/>
+	<menu_item_call label="Nuova acqua" name="New Water"/>
+	<menu_item_call label="Nuovo ciclo giornata" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_settings_gear.xml b/indra/newview/skins/default/xui/it/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6a879814fc1eb76d6d1f02e19e5da0bfa73f059e
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Modifica" name="edit_settings"/>
+	<menu_item_call label="Applica solo a me stesso" name="Settings Apply Local"/>
+	<menu_item_call label="Applica al lotto" name="Settings Apply Parcel"/>
+	<menu_item_call label="Applica alla regione" name="Settings Apply Region"/>
+	<menu_item_call label="Copia" name="copy_settings"/>
+	<menu_item_call label="Incolla" name="paste_settings"/>
+	<menu_item_call label="Copia UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 795a23ca9bca7616a44f5cd1dc25c3b54b095df6..c7a10df91032d0c5705cf86e736bc589829bce16 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="Proprietà del lotto" name="Parcel Properties"/>
 			<menu_item_check label="Menu Avanzato" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Dom" name="Sun">
+		<menu label="Ambiente" name="Environment">
 			<menu_item_check label="Alba" name="Sunrise"/>
 			<menu_item_check label="Mezzogiorno" name="Noon"/>
 			<menu_item_check label="Tramonto" name="Sunset"/>
 			<menu_item_check label="Mezzanotte" name="Midnight"/>
-			<menu_item_check label="Usa impostazioni regione" name="Use Region Settings"/>
-		</menu>
-		<menu label="Editor ambiente" name="Environment Editor">
-			<menu_item_call label="Impostazioni ambiente..." name="Environment Settings"/>
-			<menu label="Valori predefiniti acqua" name="Water Presets">
-				<menu_item_call label="Nuovo valore predefinito..." name="new_water_preset"/>
-				<menu_item_call label="Modifica valore predefinito..." name="edit_water_preset"/>
-				<menu_item_call label="Elimina valore predefinito..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Valori predefiniti cielo" name="Sky Presets">
-				<menu_item_call label="Nuovo valore predefinito..." name="new_sky_preset"/>
-				<menu_item_call label="Modifica valore predefinito..." name="edit_sky_preset"/>
-				<menu_item_call label="Elimina valore predefinito..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Valori predefiniti giorno" name="Day Presets">
-				<menu_item_call label="Nuovo valore predefinito..." name="new_day_preset"/>
-				<menu_item_call label="Modifica valore predefinito..." name="edit_day_preset"/>
-				<menu_item_call label="Elimina valore predefinito..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Utilizza ambienti condivisi" name="Use Shared Environment"/>
+			<menu_item_call label="I miei ambienti..." name="my_environs"/>
+			<menu_item_call label="Illuminazione personale..." name="adjustment_tool"/>
+			<menu_item_check label="Ferma nuvole" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Costruisci" name="BuildTools">
@@ -323,6 +308,9 @@
 			<menu_item_check label="Maschera alfa automatica (non differita)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Texture delle animazioni" name="Animation Textures"/>
 			<menu_item_check label="Disabilita texture" name="Disable Textures"/>
+			<menu_item_check label="Disattiva Ambiente" name="Disable Ambient"/>
+			<menu_item_check label="Disattiva luce del sole" name="Disable Sunlight"/>
+			<menu_item_check label="Disattiva Luci locali" name="Disable Local Lights"/>
 			<menu_item_check label="Rendering delle luci unite" name="Render Attached Lights"/>
 			<menu_item_check label="Rendering particelle unite" name="Render Attached Particles"/>
 			<menu_item_check label="Gli oggetti brillano quando sono sotto il cursore" name="Hover Glow Objects"/>
@@ -413,6 +401,7 @@
 	</menu>
 	<menu label="Admin" name="Deprecated">
 		<menu label="Take Off Clothing" name="Take Off Clothing">
+			<menu_item_call label="Universale" name="Universal"/>
 			<menu_item_call label="Fisica" name="Physics"/>
 		</menu>
 		<menu label="Guida" name="DeprecatedHelp">
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index d7be208c51d94d39332f34248890aab46b253e16..a63b0273495bd7b71f07aa0e555ec03c8daf1aa1 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -1963,6 +1963,10 @@ Cambierà migliaia di regioni e produrrà seri problemi ai vari server.
 		Togliendo la spunta a questa opzione potrebbero essere rimosse le restrizioni che i proprietari di lotti hanno aggiunto per tenere lontani disturbatori, mantenere la privacy, o evitare che minorenni abbiano accesso a materiale per adulti. Parla con i proprietari del tuo lotto se ce n’è bisogno.
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Togliendo la spunta a questa opzione potrebbero essere rimossi gli ambienti personalizzati che i proprietari hanno aggiunto ai loro lotti. Parlane con i proprietari del tuo lotto se ce n’è bisogno. Vuoi continuare?
+		<usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		La regione che cerchi di visitare include contenuti che non corripondono al livello selezionato nelle preferenze.  Per cambiare le preferenze seleziona Io &gt; Preferenze &gt; Generale.
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2443,7 +2447,15 @@ Inseriscilo in una pagina web per dare ad altri un accesso facile a questa ubica
 		Questo file di ciclo giornaliero fa riferimento ad un file di cielo mancante: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		Queste impostazioni non possono essere applicare alla regione.  Uscendo dalla regione e ritornandoci potrebbe risolvere il problema.  Il motivo fornito: [FAIL_REASON]
+		Siamo spiacenti, queste impostazioni non possono essere applicate alla regione. Motivo: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Una texture Locale è in uso nel percorso [TRACK], fotogramma #[FRAMENO] ([FRAME%]) nel campo [FIELD]. 
+Utilizzando texture locali potrebbero non venire salvate le impostazioni.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Una texture Locale è in uso nel campo [FIELD]. 
+Utilizzando texture locali potrebbero non venire salvate le impostazioni.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Impossibile cancellare l&apos;ultima chiave in questo ciclo giornata. Il ciclo giornata non può essere vuoto.  Invece di cancellare la chiave restante, modificala e quindi creane una nuova.
@@ -4388,4 +4400,75 @@ Prova a selezionare un pezzo di terreno più piccolo.
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		Non abbiamo potuto caricare le impostazioni per [NAME] dal database.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Impossibile applicare le impostazioni all’ambiente.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Impossibile applicare le impostazioni all’ambiente.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Questa regione non supporta le impostazioni per l’ambiente.
+	</notification>
+	<notification label="Salva Outfit" name="SaveSettingAs">
+		Salva con nome le impostazioni attuali dell’ambiente:
+		<form name="form">
+			<input name="message">
+				[DESC] (nuovo)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Annulla"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Impossibile importare le impostazioni legacy vento e luce [NAME] da 
+[FILE]. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Impossibile impostare l’ambiente per questo lotto. 
+Inserisci o seleziona un lotto che hai il permesso di modificare.
+	</notification>
+	<notification name="SettingsUnsuported">
+		Questa regione non supporta le impostazioni. 
+Spostati in una regione che abbia le impostazioni abilitate e riprova.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Stai per perdere le modifiche che hai fatto a questo [TYPE] chiamato &quot;[NAME]&quot;. 
+Vuoi continuare?
+		<usetemplate ignoretext="Sei sicuro di voler perdere le modifiche apportate?" name="okcancelignore" notext="No" yestext="Sì"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Stai per rimuovere tutte le impostazioni applicate. 
+Vuoi continuare?
+		<usetemplate name="okcancelbuttons" notext="No" yestext="Sì"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Stai per rimuovere tutte le Impostazioni personali illuminazione. Vuoi continuare?
+		<usetemplate name="okcancelbuttons" notext="No" yestext="Sì"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Stai per importare impostazioni non trasferibili in questo ciclo giornata. Continuando, anche le impostazioni che stai modificando diventeranno non trasferibili. 
+
+Questo cambiamento non può essere annullato. 
+
+Vuoi continuare?
+		<usetemplate ignoretext="Sei sicuro di voler rendere le impostazioni non trasferibili?" name="okcancelignore" notext="No" yestext="Sì"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Non puoi modificare le impostazioni direttamente dalla raccolta. 
+Copia nell’inventario e prova ancora.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Abbiamo riscontrato un problema con queste impostazioni. Non possono essere salvate o applicate in questo momento.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Impossibile caricare il percorso in [TRACK].
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Impossibile caricare il percorso da [TRACK1] a [TRACK2].
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml
index d76fb62c5333624e246eff927b8fe26ca8e4e531..79938b79dc20d501af87587575b8a293bb85af76 100644
--- a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Tatuaggio della testa" name="Head Tattoo" tool_tip="Clicca per scegliere una fotografia"/>
-		<texture_picker label="Tatuaggio superiore" name="Upper Tattoo" tool_tip="Clicca per scegliere una fotografia"/>
-		<texture_picker label="Tattuaggio inferiore" name="Lower Tattoo" tool_tip="Clicca per scegliere una fotografia"/>
-		<color_swatch label="Colore/Tinta" name="Color/Tint" tool_tip="Clicca per aprire il selettore dei colori"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Tatuaggio testa" name="Head Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio parte alta" name="Upper Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio parte bassa" name="Lower Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<color_swatch label="Colore/Tinta" name="Color/Tint" tool_tip="Fai clic per aprire il selettore dei colori"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/it/panel_edit_universal.xml b/indra/newview/skins/default/xui/it/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..10fab0e8bea1310fcd12ebf5c56cde99151e8402
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Tatuaggio testa" name="Head Universal Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio parte alta" name="Upper Universal Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio parte bassa" name="Lower Universal Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio gonna" name="Skirt Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio capelli" name="Hair Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio occhi" name="Eyes Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio braccio sinistro" name="Left Arm Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio gamba sinistra" name="Left Leg Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio Aux1" name="Aux1 Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio Aux2" name="Aux2 Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<texture_picker label="Tatuaggio Aux3" name="Aux3 Tattoo" tool_tip="Fai clic per scegliere un’immagine"/>
+			<color_swatch label="Colore/Tinta" name="Color/Tint" tool_tip="Fai clic per aprire il selettore dei colori"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml
index e54dc26d05a5c6922c045f579783abe1246a1db9..83824591d6230b0512922bd357c8f9bd6fd1ce02 100644
--- a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Modifica del tatuaggio
 	</string>
+	<string name="edit_universal_title">
+		Modifica Universale:
+	</string>
 	<string name="edit_physics_title">
 		Modifica fisica
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Tatuaggio:
 	</string>
+	<string name="universal_desc_text">
+		Universale:
+	</string>
 	<string name="physics_desc_text">
 		Fisica:
 	</string>
diff --git a/indra/newview/skins/default/xui/it/panel_region_environment.xml b/indra/newview/skins/default/xui/it/panel_region_environment.xml
index d7d9658e263fedb478ac33b6e9cb3a69232cca10..467bcdb005e7c1606baa87cf36ec625a739d6d7d 100644
--- a/indra/newview/skins/default/xui/it/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/it/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Ambiente" name="panel_env_info">
-	<text name="water_settings_title">
-		Seleziona le impostazioni del ciclo dell&apos;acqua e del cielo/giornata che vuoi che vedano tutti coloro che visitano la tua regione. Maggiori informazioni
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Usa valori predefiniti di Second Life" name="use_sl_default_settings"/>
-		<radio_item label="Usa le impostazioni seguenti" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Impostazione Acqua
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Seleziona un valore predefinito-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Ciclo cielo / giornata
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Cielo fisso" name="my_sky_settings"/>
-			<radio_item label="Ciclo giornata" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Seleziona un valore predefinito-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Seleziona un valore predefinito-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Applica" name="apply_btn"/>
-	<button label="Annulla" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Usa impostazioni predefinite
+	</string>
+	<string name="str_label_use_region">
+		Usa impostazioni regione
+	</string>
+	<string name="str_altitude_desription">
+		Cielo [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		Non è stato selezionato alcun lotto. Le impostazioni ambientali sono disabilitate.
+	</string>
+	<string name="str_cross_region">
+		Le impostazioni ambientali non sono disponibili oltre i confini della regione.
+	</string>
+	<string name="str_legacy">
+		Le impostazioni ambientali non sono disponibili per questa regione.
+	</string>
+	<string name="str_disallowed">
+		Il gestore della proprietà immobiliare non permette di cambiare gli ambienti del lotto in questa regione.
+	</string>
+	<string name="str_too_small">
+		Il lotto deve essere di almeno 128 metri quadri per supportare un ambiente.
+	</string>
+	<string name="str_empty">
+		(vuoto)
+	</string>
+	<string name="str_region_env">
+		(ambiente regione)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Utilizza Inventario" name="btn_select_inventory"/>
+							<button label="Personalizza" name="btn_edit"/>
+							<check_box label="I proprietari del lotto possono ignorare l’ambiente" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Sconosciuto
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Trascina un’impostazione dall’Inventario a questa casella per selezionarla come cielo corrente."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Sconosciuto
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Trascina un’impostazione dall’Inventario a questa casella per selezionarla come cielo corrente."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Cielo [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Sconosciuto
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Trascina un’impostazione dall’Inventario a questa casella per selezionarla come cielo corrente."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Suolo
+						</text>
+						<line_editor name="edt_invname_ground">
+							Sconosciuto
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Trascina un’impostazione dall’Inventario a questa casella per selezionarla come suolo."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Acqua
+						</text>
+						<line_editor name="edt_invname_water">
+							Sconosciuto
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Trascina un’impostazione dall’Inventario a questa casella per selezionarla come acqua."/>
+					</panel>
+					<button label="Reimposta" name="btn_rst_altitudes" tool_tip="Reimposta alle altitudini predefinite"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/it/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/it/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b2d27b93fc95e5547c7bc37c6f977eaaa2e21e48
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmosfera e illuminazione" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/it/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/it/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e4dd5e00c066379d9af4bef97055b6641c39cbe8
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Nuvole" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/it/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3142d1442a7061870ce93dde1524138662a0967d
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Densità" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Termine esponenziale Rayleigh:" name="rayleigh_exponential"/>
+			<slider label="Scala esponenziale Rayleigh:" name="rayleigh_exponential_scale"/>
+			<slider label="Termine lineare Rayleigh:" name="rayleigh_linear"/>
+			<slider label="Termine costante Rayleigh:" name="rayleigh_constant"/>
+			<slider label="Altitudine massima Rayleigh:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Termine esponenziale Mie:" name="mie_exponential"/>
+			<slider label="Scala esponenziale Mie:" name="mie_exponential_scale"/>
+			<slider label="Termine lineare Mie:" name="mie_linear"/>
+			<slider label="Termine costante Mie:" name="mie_constant"/>
+			<slider label="Fattore diverso Mie:" name="mie_aniso_factor"/>
+			<slider label="Altitudine massima Mie:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Termine esponenziale di assorbimento:" name="absorption_exponential"/>
+			<slider label="Scala esponenziale di assorbimento:" name="absorption_exponential_scale"/>
+			<slider label="Termine lineare di assorbimento:" name="absorption_linear"/>
+			<slider label="Termine costante di assorbimento:" name="absorption_constant"/>
+			<slider label="Altitudine massima di assorbimento:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/it/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a167b0aea397d434176c2d3569afbb9bf9d9d9d
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sole e Luna" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Mostra marcatore" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Mostra marcatore" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_settings_water.xml b/indra/newview/skins/default/xui/it/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0d123a62499823a1f960808323747f7d97466d36
--- /dev/null
+++ b/indra/newview/skins/default/xui/it/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Acqua" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Spostamento Fresnel:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/it/panel_tools_texture.xml b/indra/newview/skins/default/xui/it/panel_tools_texture.xml
index 46e2717647a401bf250f8b692a39cfedd709c3fe..5b4cb5868f28f893bc91f2c66884c62459d0f6de 100644
--- a/indra/newview/skins/default/xui/it/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/it/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Texture" name="Texture">
-	<panel.string name="string repeats per meter">
-		Ripetizioni al metro
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Ripetizioni per faccia
-	</panel.string>
 	<text name="color label">
 		Colore
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Spostamento orizzontale" name="shinyOffsetU"/>
 	<spinner label="Spostamento verticale" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Allinea facce planari" name="checkbox planar align" tool_tip="Allinea le texture su tutte le facce selezionate con l’ultima faccia selezionata. È richiesta la mappatura planare delle texture."/>
+	<button label="Alllinea" label_selected="Alllinea livelli di texture attuali" name="button align textures" tool_tip="Alllinea livelli di texture attuali"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/it/role_actions.xml b/indra/newview/skins/default/xui/it/role_actions.xml
index 2bfaea89631d657c14e9fd1a9fc6ecc9ff3f1d68..0e0016522797b844c76070f17ff10f07ddc77b65 100644
--- a/indra/newview/skins/default/xui/it/role_actions.xml
+++ b/indra/newview/skins/default/xui/it/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Cambiare impostazioni musica e multimediali" longdescription="Cambia le impostazioni per lo streaming della musica e dei video in Informazioni sul terreno &gt; Media." name="land change media" value="20"/>
 		<action description="Attiva &apos;Modifica terreno&apos;" longdescription="Attiva &apos;Modifica terreno&apos;. *ATTENZIONE* Informazioni sul terreno &gt; Opzioni &gt; Modifica terreno consente a chiunque di modificare la forma del tuo terreno e di collocare e spostare le piante Linden. Pertanto sii sicuro della scelta prima di assegnare questa Abilità. La funzione di modifica del terreno è attivata in Informazioni sul terreno &gt; Opzioni." name="land edit" value="21"/>
 		<action description="Attivazione di parametri per Informazioni sul terreno &gt; Opzioni" longdescription="Premi Sicuro (nessun danno), Vola e consenti agli altri residenti di: modificare il terreno, costruire, creare punti di riferimento ed eseguire script nel terreno appartenente ad un gruppo in Informazioni sul terreno &gt; scheda Opzioni." name="land options" value="22"/>
+		<action description="Modifica le impostazioni dell’ambiente e del ciclo giornata." longdescription="Cambia le impostazioni dell’ambiente e del ciclo giornata dalla scheda Informazioni sul terreno &gt; Ambiente." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Queste abilità permettono ai membri di non avere restrizioni in un lotto appartenente ad un gruppo." name="Parcel Powers">
 		<action description="Consenti sempre la modifica del terreno" longdescription="I membri con questo ruolo e abilità possono modificare il terreno appartenente ad un gruppo, anche se la funzionalità è disattivata in Informazioni sul terreno &gt; Opzioni." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 9265ce9ec6a2720321ee34fe1c0761af39cd2a4b..ca486f832e50da75e6b3c3e460db18dd69d1d229 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -635,6 +635,15 @@ Prova ad accedere nuovamente tra un minuto.
 	<string name="BUTTON_HELP">
 		Mostra Aiuto
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Oggetti di questo tipo non possono essere allegati ai 
+biglietti in questa regione.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Solamente gli oggetti con autorizzazioni 
+illimitate al “proprietario successivo” 
+possono essere allegati ai biglietti.
+	</string>
 	<string name="Searching">
 		Ricerca in corso...
 	</string>
@@ -711,6 +720,18 @@ Prova ad accedere nuovamente tra un minuto.
 		Errore nella richiesta di caricamento. Vai alla pagina 
 http://secondlife.com/support per risolvere il problema.
 	</string>
+	<string name="SettingValidationError">
+		Impossibile convalidare le impostazioni importate [NAME]
+	</string>
+	<string name="SettingImportFileError">
+		Impossibile aprire il file [FILE]
+	</string>
+	<string name="SettingParseFileError">
+		Impossibile aprire il file [FILE]
+	</string>
+	<string name="SettingTranslateError">
+		Impossibile tradurre la legacy vento e luce [NAME]
+	</string>
 	<string name="texture">
 		texture
 	</string>
@@ -786,6 +807,9 @@ http://secondlife.com/support per risolvere il problema.
 	<string name="symbolic folder link">
 		link alla cartella
 	</string>
+	<string name="settings blob">
+		impostazioni
+	</string>
 	<string name="mesh">
 		reticolo
 	</string>
@@ -1116,6 +1140,9 @@ http://secondlife.com/support per risolvere il problema.
 	<string name="ForceSitAvatar">
 		Forza l&apos;avatar a sedersi
 	</string>
+	<string name="ChangeEnvSettings">
+		Cambia le impostazioni dell’ambiente
+	</string>
 	<string name="AgentNameSubst">
 		(Tu)
 	</string>
@@ -1264,6 +1291,9 @@ http://secondlife.com/support per risolvere il problema.
 	<string name="tattoo">
 		Tatuaggio
 	</string>
+	<string name="universal">
+		Universale
+	</string>
 	<string name="physics">
 		Fisica
 	</string>
@@ -1306,6 +1336,9 @@ http://secondlife.com/support per risolvere il problema.
 	<string name="tattoo_not_worn">
 		Tatuaggio non portato
 	</string>
+	<string name="universal_not_worn">
+		Universale non indossato
+	</string>
 	<string name="physics_not_worn">
 		Fisica non indossata
 	</string>
@@ -1357,6 +1390,9 @@ http://secondlife.com/support per risolvere il problema.
 	<string name="create_new_tattoo">
 		Crea un nuovo tatuaggio
 	</string>
+	<string name="create_new_universal">
+		Crea nuovo universale
+	</string>
 	<string name="create_new_physics">
 		Crea nuova fisica
 	</string>
@@ -2492,6 +2528,27 @@ Se continui a ricevere questo messaggio, contatta l&apos;assistenza Second Life
 	<string name="RegionSettings">
 		Impostazioni regione
 	</string>
+	<string name="NoEnvironmentSettings">
+		Questa regione non supporta le impostazioni per l’ambiente.
+	</string>
+	<string name="EnvironmentSun">
+		Sole
+	</string>
+	<string name="EnvironmentMoon">
+		Luna
+	</string>
+	<string name="EnvironmentBloom">
+		Fioritura
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Rumore nuvole
+	</string>
+	<string name="EnvironmentNormalMap">
+		Mappa normale
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparent
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Clicca: [TELEPORT] teleport, [MAP] mappa, [PROFILE] profilo
 	</string>
@@ -4645,6 +4702,9 @@ Segnala abuso
 	<string name="New Tattoo">
 		Nuovo tatuaggio
 	</string>
+	<string name="New Universal">
+		Nuovo Universale
+	</string>
 	<string name="New Physics">
 		Nuova fisica
 	</string>
@@ -4771,6 +4831,15 @@ Segnala abuso
 	<string name="Female - Wow">
 		Femmina - Accipicchia
 	</string>
+	<string name="New Daycycle">
+		Nuovo ciclo giornata
+	</string>
+	<string name="New Water">
+		Nuova acqua
+	</string>
+	<string name="New Sky">
+		Nuovo cielo
+	</string>
 	<string name="/bow">
 		/inchino
 	</string>
@@ -5299,6 +5368,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="BeaconMedia">
 		Visualizzazione marcatori multimedia (bianco)
 	</string>
+	<string name="BeaconSun">
+		Marcatore visualizza direzione sole (arancione)
+	</string>
+	<string name="BeaconMoon">
+		Marcatore visualizza direzione luna (viola)
+	</string>
 	<string name="ParticleHiding">
 		Particelle nascoste
 	</string>
@@ -5326,6 +5401,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="Command_Destinations_Label">
 		Destinazioni
 	</string>
+	<string name="Command_Environments_Label">
+		I miei ambienti
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5419,6 +5500,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="Command_Destinations_Tooltip">
 		Destinazioni interessanti
 	</string>
+	<string name="Command_Environments_Tooltip">
+		I miei ambienti
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Pubblica su Facebook
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Carica su Flickr
 	</string>
@@ -5614,6 +5701,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="ExperiencePermission12">
 		accettazione automatica delle autorizzazioni per le esperienze
 	</string>
+	<string name="ExperiencePermission16">
+		obbliga l&apos;avatar a sedersi
+	</string>
+	<string name="ExperiencePermission17">
+		cambia le impostazioni dell’ambiente
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		ha eseguito un&apos;operazione sconosciuta: [Permission]
 	</string>
@@ -5638,6 +5731,12 @@ Prova a racchiudere il percorso dell&apos;editor in doppie virgolette.
 	<string name="ExperiencePermissionShort12">
 		Autorizzazione
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Siediti
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Ambiente
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		Le conversazioni non vengono registrate. Per iniziare a registrare, seleziona &quot;Salva: Solo registro&quot; oppure &quot;Salva: Registri e trascrizioni&quot; in Preferenze &gt; Chat.
 	</string>
diff --git a/indra/newview/skins/default/xui/ja/floater_about_land.xml b/indra/newview/skins/default/xui/ja/floater_about_land.xml
index d26a1b34d5791a86f2013fda2ad1a8af8a1ed376..4703dfaa34ad46282e55e2db3477befc780a82b7 100644
--- a/indra/newview/skins/default/xui/ja/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about_land.xml
@@ -478,5 +478,6 @@
 			</panel>
 		</panel>
 		<panel label="体験" name="land_experiences_panel"/>
+		<panel label="環境" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_adjust_environment.xml b/indra/newview/skins/default/xui/ja/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6736dad336d5471a1b640645368f199b97691d46
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="個人的な照明">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="リセット" name="btn_reset" tool_tip="閉じて共有された環境にリセットする"/>
+					<text name="cloud_map_label">
+						雲の画像:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						太陽:
+					</text>
+					<check_box label="ビーコンを表示" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="ビーコンを表示" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_beacons.xml b/indra/newview/skins/default/xui/ja/floater_beacons.xml
index a55698e3d030417f556bab2ddaba3a6d8bfb749e..cb3dae06444ac6d8a4f7bd366f1b020822603927 100644
--- a/indra/newview/skins/default/xui/ja/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/ja/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="音源" name="sounds"/>
 		<check_box label="パーティクル源" name="particles"/>
 		<check_box label="メディア源" name="moapbeacon"/>
+		<check_box label="太陽" name="sun"/>
+		<check_box label="月" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
index b34fd192a926750e455feacfcb25b6009a28497f..fc9b35a34d46169f3da2d81b87920da18f7e36b5 100644
--- a/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/ja/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="サウンド"/>
 	<check_box label="テクスチャ" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="テクスチャ"/>
+	<icon name="icon_setting" tool_tip="自然環境の設定"/>
 	<button label="すべてに √" label_selected="全て" name="check_all"/>
 	<button label="クリア" label_selected="なし" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/ja/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/ja/floater_delete_env_preset.xml
deleted file mode 100644
index 6467a69956ea37137d159f0bb6f4efc3956a6c4d..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/ja/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="環境の事前設定を削除">
-	<string name="title_water">
-		水の事前設定を削除
-	</string>
-	<string name="title_sky">
-		空の事前設定を削除
-	</string>
-	<string name="title_day_cycle">
-		デイサイクルを削除
-	</string>
-	<string name="label_water">
-		事前設定:
-	</string>
-	<string name="label_sky">
-		事前設定:
-	</string>
-	<string name="label_day_cycle">
-		デイサイクル:
-	</string>
-	<string name="msg_confirm_deletion">
-		選択された事前設定を削除しますか?
-	</string>
-	<string name="msg_sky_is_referenced">
-		デイサイクルの参照先として使われている事前設定は削除できません。
-	</string>
-	<string name="combo_label">
-		- 事前設定を選択 -
-	</string>
-	<text name="label">
-		事前設定:
-	</text>
-	<button label="削除" name="delete"/>
-	<button label="キャンセル" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/ja/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..79c97472df051cbececa936cac583ee209f93b1f
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="デイサイクルを編集">
+	<string name="title_new">
+		新しいデイサイクルを作成
+	</string>
+	<string name="title_edit">
+		デイサイクルを編集
+	</string>
+	<string name="hint_new">
+		新しいデイサイクルに名前をつけ、希望の設定に調節して、「保存」をクリックします。
+	</string>
+	<string name="hint_edit">
+		自分で作成したデイサイクルを編集するには、希望の設定に調節して、「保存」をクリックします。
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		空 [ALT]
+	</string>
+	<string name="sky_label">
+		空
+	</string>
+	<string name="water_label">
+		æ°´
+	</string>
+	<string name="commit_parcel">
+		区画に適用
+	</string>
+	<string name="commit_region">
+		リージョンに適用
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				デイサイクル名:
+			</text>
+			<button label="インポート" name="btn_import" tool_tip="ディスクから過去の設定をインポートする。"/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="空 4" name="sky4_track"/>
+						<button label="空 3" name="sky3_track"/>
+						<button label="空 2" name="sky2_track"/>
+						<button label="地表レベル" name="sky1_track"/>
+						<button label="æ°´" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="トラックを以下からクローン" name="copy_track"/>
+								<button label="トラックを以下からロード" name="load_track"/>
+								<button label="トラックをクリア" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="後ろに移動"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="前に移動"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="[FRAME] を追加" name="add_frame"/>
+								<button label="[FRAME] をロード" name="btn_load_frame"/>
+								<button label="[FRAME] を削除" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						上部のタイムラインからキーフレームを選択し、設定を編集します。
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="æ°´" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="大気&光" name="atmosphere_panel"/>
+						<panel label="雲" name="clouds_panel"/>
+						<panel label="太陽&月" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="保存" name="save_btn"/>
+			<button label="キャンセル" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/ja/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a00b87b990585dff99b17fe72c6252a6dd3d2f63
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="固定された環境">
+	<string name="edit_sky">
+		空を編集:
+	</string>
+	<string name="edit_water">
+		水を編集:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="ロード" name="btn_load" tool_tip="持ち物から設定をロードする"/>
+			<button label="インポート" name="btn_import" tool_tip="ディスクから過去の設定をインポートする。"/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="保存" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="キャンセル" name="btn_cancel" tool_tip="最後に保存された状態に戻す"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
index da63b54eababde3fa4c22f1f1b85b2f0def979c6..425cb7ad8199743b23128b8e2a58e51f164a2240 100644
--- a/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="サウンド" name="check_sound"/>
 	<check_box label="テクスチャ" name="check_texture"/>
 	<check_box label="スナップショット" name="check_snapshot"/>
+	<check_box label="設定" name="check_settings"/>
 	<button label="すべて" label_selected="すべて" name="All"/>
 	<button label="なし" label_selected="なし" name="None"/>
 	<check_box label="常にフォルダを表示" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_my_environments.xml b/indra/newview/skins/default/xui/ja/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d697a9f32152fbbe1fd7e4166f262b6b06751f94
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="場所" name="my_environments" title="私の環境">
+	<layout_stack>
+		<layout_panel label="フィルター" name="filter_panel">
+			<check_box label="日間" name="chk_days"/>
+			<check_box label="空" name="chk_skies"/>
+			<check_box label="æ°´" name="chk_water"/>
+			<filter_editor label="環境の絞り込み" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="環境" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="すべてのフォルダを表示" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="その他のオプションを表示"/>
+				<menu_button name="btn_newsettings" tool_tip="新規設定を作成"/>
+				<button name="btn_del" tool_tip="選択したアイテムを削除"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_perms_default.xml b/indra/newview/skins/default/xui/ja/floater_perms_default.xml
index 0dfc75014e8241dad71f367c81e085e13c00e1e8..33551a57068dfbbff0a5ec3f3600d55b73af298b 100644
--- a/indra/newview/skins/default/xui/ja/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/ja/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="衣服またはボディパーツを作成するときにデフォルトの権限を設定する">
 			着用物
 		</text>
+		<text name="label_13" tool_tip="自然環境の設定を作成するときにデフォルトの権限を設定する">
+			設定
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="取り消し" label_selected="取り消し" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_pick_track.xml b/indra/newview/skins/default/xui/ja/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e5773e1ec80680bdf201db8fcacd7fa7877fcfac
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="選択:トラック">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				空のソースを選択:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="空 4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="空 3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="空 2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="地面" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="キャンセル" label_selected="キャンセル" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/ja/floater_preferences_graphics_advanced.xml
index c28afa4c98c99ea66e3e37001f09469c9feb1057..8ba537faa23ffa30c81afc772e0cd38102c7c82f 100644
--- a/indra/newview/skins/default/xui/ja/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/ja/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="透明な水" name="TransparentWater"/>
 	<check_box initial_value="true" label="バンプマッピングと光沢" name="BumpShiny"/>
 	<check_box initial_value="true" label="近くの光" name="LocalLights"/>
-	<check_box initial_value="true" label="基本シェーダー" name="BasicShaders" tool_tip="このオプションを無効にすると、グラフィックカードのドライバの種類によっては、クラッシュするのを防ぎます。"/>
 	<slider label="地形詳細:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		低
diff --git a/indra/newview/skins/default/xui/ja/floater_settings_picker.xml b/indra/newview/skins/default/xui/ja/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b8b1699f03839043088dad0e516b35a328cc8951
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="選択:設定">
+	<floater.string name="pick title">
+		選択:
+	</floater.string>
+	<floater.string name="pick_track">
+		トラックを選択
+	</floater.string>
+	<floater.string name="pick_settings">
+		設定を選択
+	</floater.string>
+	<floater.string name="track_water">
+		æ°´
+	</floater.string>
+	<floater.string name="track_ground">
+		地面
+	</floater.string>
+	<floater.string name="track_sky">
+		空 [NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="テクスチャをフィルター" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="キャンセル" label_selected="キャンセル" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
index 37233d3e6869fb272e6e22cc74fa8f17c76e93d8..05e7bfefd2ee7cb07f25cc616433c071efd19184 100644
--- a/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/ja/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="インベントリ" name="inventory" value="0"/>
 		<radio_item label="ローカル" name="local" value="1"/>
+		<radio_item label="構築(ベーク)" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		サイズ: [DIMENSIONS]
@@ -20,7 +21,6 @@
 	<button label="ブランク" label_selected="ブランク" name="Blank"/>
 	<button label="なし" label_selected="なし" name="None"/>
 	<button label="" label_selected="" name="Pipette"/>
-	<check_box initial_value="true" label="今すぐ適用" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="プレビュー無効"/>
 	<filter_editor label="テクスチャをフィルター" name="inventory search editor"/>
 	<check_box initial_value="false" label="フォルダを表示" name="show_folders_check"/>
@@ -31,6 +31,22 @@
 		<column label="名前" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="構築(ベーク)するテクスチャを選択">
+		<combo_box.item label="なし" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="基本となるメッシュリージョンを隠す" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="取り消し" label_selected="取り消し" name="Cancel"/>
+	<check_box initial_value="true" label="今すぐ適用" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory.xml b/indra/newview/skins/default/xui/ja/menu_inventory.xml
index 0b06b77901da880eef74acb75876389235bb24d0..ec16f1cf1727ba0eb64977e12b071de87dfd7d1c 100644
--- a/indra/newview/skins/default/xui/ja/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/ja/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="有効にする" name="Marketplace Activate"/>
 	<menu_item_call label="無効にする" name="Marketplace Deactivate"/>
 	<menu_item_call label="共有" name="Share"/>
-	<menu_item_call label="購入" name="Task Buy"/>
 	<menu_item_call label="開く" name="Task Open"/>
 	<menu_item_call label="再生" name="Task Play"/>
 	<menu_item_call label="プロパティ" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="新しいパンツ" name="New Underpants"/>
 		<menu_item_call label="新しいアルファマスク" name="New Alpha Mask"/>
 		<menu_item_call label="新しいタトゥ" name="New Tattoo"/>
+		<menu_item_call label="新しいユニバーサル" name="New Universal"/>
 		<menu_item_call label="新規の物理作用" name="New Physics"/>
 	</menu>
 	<menu label="新しい身体部位" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="新しい髪" name="New Hair"/>
 		<menu_item_call label="新しい眼" name="New Eyes"/>
 	</menu>
+	<menu label="新しい設定" name="New Settings">
+		<menu_item_call label="新しい空" name="New Sky"/>
+		<menu_item_call label="新しい水" name="New Water"/>
+		<menu_item_call label="新しいデイサイクル" name="New Day Cycle"/>
+	</menu>
 	<menu label="次のデフォルトとして使用" name="upload_def">
 		<menu_item_call label="画像のアップロード" name="Image uploads"/>
 		<menu_item_call label="サウンドのアップロード" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="編集" name="Wearable Edit"/>
 	<menu_item_call label="追加" name="Wearable Add"/>
 	<menu_item_call label="取り外す" name="Take Off"/>
+	<menu_item_call label="自分にのみ適用" name="Settings Apply Local"/>
+	<menu_item_call label="区画に適用" name="Settings Apply Parcel"/>
 	<menu_item_call label="マーケットプレイスのリストにコピー" name="Marketplace Copy"/>
 	<menu_item_call label="マーケットプレイスのリストに移動" name="Marketplace Move"/>
 	<menu_item_call label="--オプションなし--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_inventory_add.xml b/indra/newview/skins/default/xui/ja/menu_inventory_add.xml
index ae5ddbb78f1b3302c771151c1f266ed40b4dbd7f..eecf166a7077ce263e5e5cbb6034374855c412b6 100644
--- a/indra/newview/skins/default/xui/ja/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/ja/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="サウンド (L$[COST] )..." name="Upload Sound"/>
 		<menu_item_call label="アニメーション (L$ [COST] )..." name="Upload Animation"/>
 		<menu_item_call label="モデル" name="Upload Model"/>
-		<menu_item_call label="モデルウィザード" name="Upload Model Wizard"/>
 		<menu_item_call label="一括 (ファイルにつき L$[COST] )..." name="Bulk Upload"/>
-		<menu_item_call label="デフォルトのアップロード権限を設定" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="新規フォルダ" name="New Folder"/>
 	<menu_item_call label="新規スクリプト" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="新しい下着(下)" name="New Underpants"/>
 		<menu_item_call label="新しいアルファ" name="New Alpha"/>
 		<menu_item_call label="新しいタトゥー" name="New Tattoo"/>
+		<menu_item_call label="新しいユニバーサル" name="New Universal"/>
 		<menu_item_call label="新規の物理作用" name="New Physics"/>
 	</menu>
 	<menu label="新しい身体部位" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="新しい髪" name="New Hair"/>
 		<menu_item_call label="新しい目" name="New Eyes"/>
 	</menu>
+	<menu label="新しい設定" name="New Settings">
+		<menu_item_call label="新しい空" name="New Sky"/>
+		<menu_item_call label="新しい水" name="New Water"/>
+		<menu_item_call label="新しいデイサイクル" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_outfit_gear.xml b/indra/newview/skins/default/xui/ja/menu_outfit_gear.xml
index 5e02fd3b8f39ade54572ca4509daf729dee8a9d3..4946d58fd84a0faeda0ce25f2121ee53997d6b23 100644
--- a/indra/newview/skins/default/xui/ja/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/ja/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="アルファ" name="New Alpha"/>
 		<menu_item_call label="新規の物理作用" name="New Physics"/>
 		<menu_item_call label="新しいタトゥ" name="New Tattoo"/>
+		<menu_item_call label="新しいユニバーサル" name="New Universal"/>
 	</menu>
 	<menu label="新しい身体部位" name="New Body Parts">
 		<menu_item_call label="新しいシェイプ" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/ja/menu_save_settings.xml b/indra/newview/skins/default/xui/ja/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44fb1fb30b6c544b8987ddad088b311b6a18b929
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="保存" name="save_settings"/>
+	<menu_item_check label="別名で保存" name="save_as_new_settings"/>
+	<menu_item_check label="約束する" name="commit_changes"/>
+	<menu_item_check label="自分にのみ適用" name="apply_local"/>
+	<menu_item_check label="区画に適用" name="apply_parcel"/>
+	<menu_item_check label="リージョンに適用" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_settings_add.xml b/indra/newview/skins/default/xui/ja/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..814ad9c1a6b2c57b638b3c5f8c0b75eaee5de8ff
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="新しい空" name="New Sky"/>
+	<menu_item_call label="新しい水" name="New Water"/>
+	<menu_item_call label="新しいデイサイクル" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_settings_gear.xml b/indra/newview/skins/default/xui/ja/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..064eae95bfbab2c644d4a6a9a92501dd98d05cd9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="編集" name="edit_settings"/>
+	<menu_item_call label="自分にのみ適用" name="Settings Apply Local"/>
+	<menu_item_call label="区画に適用" name="Settings Apply Parcel"/>
+	<menu_item_call label="リージョンに適用" name="Settings Apply Region"/>
+	<menu_item_call label="コピー" name="copy_settings"/>
+	<menu_item_call label="貼り付け" name="paste_settings"/>
+	<menu_item_call label="UUID をコピー" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index 7810094823014ab7fb42043430632a857cd7ccf2..ba8d8e49556a3aad4ed747ca990d2493b765eb31 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="区画プロパティ" name="Parcel Properties"/>
 			<menu_item_check label="アドバンスメニュー" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="æ—¥" name="Sun">
+		<menu label="環境" name="Environment">
 			<menu_item_check label="日の出" name="Sunrise"/>
 			<menu_item_check label="正午" name="Noon"/>
 			<menu_item_check label="日没" name="Sunset"/>
 			<menu_item_check label="深夜" name="Midnight"/>
-			<menu_item_check label="リージョンの設定を使用" name="Use Region Settings"/>
-		</menu>
-		<menu label="自然環境エディター" name="Environment Editor">
-			<menu_item_call label="自然環境の設定..." name="Environment Settings"/>
-			<menu label="水の事前設定" name="Water Presets">
-				<menu_item_call label="新しい事前設定..." name="new_water_preset"/>
-				<menu_item_call label="事前設定を編集..." name="edit_water_preset"/>
-				<menu_item_call label="事前設定を削除..." name="delete_water_preset"/>
-			</menu>
-			<menu label="空の事前設定" name="Sky Presets">
-				<menu_item_call label="新しい事前設定..." name="new_sky_preset"/>
-				<menu_item_call label="事前設定を編集..." name="edit_sky_preset"/>
-				<menu_item_call label="事前設定を削除..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="デイの事前設定" name="Day Presets">
-				<menu_item_call label="新しい事前設定..." name="new_day_preset"/>
-				<menu_item_call label="事前設定を編集..." name="edit_day_preset"/>
-				<menu_item_call label="事前設定を削除..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="共有された環境を使用" name="Use Shared Environment"/>
+			<menu_item_call label="私の環境…" name="my_environs"/>
+			<menu_item_call label="個人的な照明…" name="adjustment_tool"/>
+			<menu_item_check label="雲を一時停止" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="制作" name="BuildTools">
@@ -346,6 +331,9 @@
 			<menu_item_check label="自動アルファマスク(遅延なし)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="アニメーションテクスチャ" name="Animation Textures"/>
 			<menu_item_check label="テクスチャを無効にする" name="Disable Textures"/>
+			<menu_item_check label="アンビエントを無効にする" name="Disable Ambient"/>
+			<menu_item_check label="日の出を無効にする" name="Disable Sunlight"/>
+			<menu_item_check label="近くの光を無効にする" name="Disable Local Lights"/>
 			<menu_item_check label="フル解像度テクスチャ" name="Rull Res Textures"/>
 			<menu_item_check label="装着された光源を描画する" name="Render Attached Lights"/>
 			<menu_item_check label="取り付けられたパーティクルを描画する" name="Render Attached Particles"/>
@@ -483,6 +471,7 @@
 			<menu_item_call label="スカート" name="Skirt"/>
 			<menu_item_call label="アルファ" name="Alpha"/>
 			<menu_item_call label="タトゥ" name="Tattoo"/>
+			<menu_item_call label="ユニバーサル" name="Universal"/>
 			<menu_item_call label="物理作用" name="Physics"/>
 			<menu_item_call label="すべての衣類" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 16aeb4dcd7ece1fe6fb63c4f635aac79b6f1cbae..96a5cb741a7c5ae898b3311ba89f43085aadda53 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -1996,6 +1996,11 @@ http://wiki.secondlife.com/wiki/Setting_your_display_name を参照してくだ
 		このオプションをオフにすると、嫌がらせの防止やプライバシーの維持、18 才以下の住人を Adult コンテンツから守るために区画所有者が加えた制限が解除される可能性があります。必要に応じて区画所有者と相談してください。
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		このオプションをオフにすると、区画所有者がその区画に加えたカスタム環境が削除されます。必要に応じて区画所有者と相談してください。
+続けますか?
+		<usetemplate name="okcancelbuttons" notext="キャンセル" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		訪問しようとしている地域(リージョン)には現在の環境設定を超えるコンテンツが含まれています。「ミー」 &gt; 「環境設定」 &gt; 「一般」を選択して、環境設定を変更できます。
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2483,7 +2488,14 @@ Web ページにリンクすると、他人がこの場所に簡単にアクセ
 		このデイサイクルのファイルは次の存在しない「空」ファイルを参照しています: [SKY]。
 	</notification>
 	<notification name="WLRegionApplyFail">
-		申し訳ございませんが、設定をリージョンに適用できませんでした。一度リージョンを出てから戻ると、問題が解決されるかもしれません。問題の発生した理由:[FAIL_REASON]
+		申し訳ございませんが、設定をリージョンに適用できませんでした。理由: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		ローカルテクスチャは、フィールド [FIELD] 内のトラック [TRACK]、フレーム #[FRAMENO] ([FRAME]%) で使用されています。ローカルテクスチャを使った設定は保存されない可能性があります。
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		ローカルテクスチャは、フィールド [FIELD] で使用されています。
+ローカルテクスチャを使った設定は保存されない可能性があります。
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		デイサイクルを空にはできないので、このデイサイクルの最後のキーを削除することはできません。最後のキーを削除して新しいキーを作成するのではなく、最後のキーを変更してください。
@@ -4429,4 +4441,75 @@ M キーを押して変更します。
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		データベースから [NAME] の設定の読み込みができませんでした。
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		環境にこれらの設定を適用することができません。
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		環境にこれらの設定を適用することができません。
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		このリージョンは環境設定をサポートしていません。
+	</notification>
+	<notification label="アウトフィットを保存する" name="SaveSettingAs">
+		現在の環境設定を次の内容で保存する:
+		<form name="form">
+			<input name="message">
+				[DESC] (新)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="キャンセル"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		[FILE] から過去のウインドライトの設定 [NAME] をインポートできません。 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		この区画で環境を設定することはできません。
+変更する権限のある区画を入力または選択してください。
+	</notification>
+	<notification name="SettingsUnsuported">
+		このリージョンでは設定をサポートしていません。
+設定に対応しているリージョンに移動し、アクションを再試行してください。
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		&quot;[NAME]&quot;と名付けられたこの [TYPE] に加えられた変更が失われます。
+続けますか?
+		<usetemplate ignoretext="変更を失いますがよろしいですか?" name="okcancelignore" notext="いいえ" yestext="はい"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		適用されたすべての設定を削除しようとしています。
+続けますか?
+		<usetemplate name="okcancelbuttons" notext="いいえ" yestext="はい"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		適用されたすべての個人的な照明の設定を削除しようとしています。
+続けますか?
+		<usetemplate name="okcancelbuttons" notext="いいえ" yestext="はい"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		このデイサイクルに移行不可の設定をインポートしようとしています。このまま続けると、編集中の設定も移行不可になります。
+
+この変更は元に戻すことができません。
+
+続けますか?
+		<usetemplate ignoretext="設定を移行不可にしますか?" name="okcancelignore" notext="いいえ" yestext="はい"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		ライブラリから直接設定を変更することはできません。
+自分の持ち物からコピーしてやり直してください。
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		この設定で問題が発生しました。この設定は現在保存または適用ができません。
+	</notification>
+	<notification name="TrackLoadFailed">
+		トラックを [TRACK] にロードできません。
+	</notification>
+	<notification name="TrackLoadMismatch">
+		トラックを [TRACK1] から [TRACK2] にロードできません。
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml
index b556b68e0290a80226c781695d583e9185ed61a4..cf5f2489f1ad4dae8d7f58aa744377e0fb37245a 100644
--- a/indra/newview/skins/default/xui/ja/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/ja/panel_edit_classified.xml
@@ -47,7 +47,7 @@
 				<button label="[LABEL]" name="save_changes_btn"/>
 			</layout_panel>
 			<layout_panel name="show_on_map_btn_lp">
-				<button label="取り消し" name="cancel_btn"/>
+				<button label="キャンセル" name="cancel_btn"/>
 			</layout_panel>
 		</layout_stack>
 	</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml
index f4cfe6d83f769b24479b5889dc8c7b63d3bb61c9..5729cb7552322049b0f5996d34f95dfd478a7d89 100644
--- a/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/ja/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="頭部のタトゥー" name="Head Tattoo" tool_tip="クリックして写真を選択"/>
-		<texture_picker label="上部のタトゥー" name="Upper Tattoo" tool_tip="クリックして写真を選択"/>
-		<texture_picker label="下部のタトゥー" name="Lower Tattoo" tool_tip="クリックして写真を選択"/>
-		<color_swatch label="色・色彩配合" name="Color/Tint" tool_tip="クリックしてカラーピッカーを開きます"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="頭部のタトゥー" name="Head Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="上部のタトゥー" name="Upper Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="下部のタトゥー" name="Lower Tattoo" tool_tip="クリックして写真を選択する"/>
+			<color_swatch label="色/明暗" name="Color/Tint" tool_tip="クリックしてカラーピッカーを開きます"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_universal.xml b/indra/newview/skins/default/xui/ja/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..614fd1059fab82ce51056778743054ef37169e25
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="頭部のタトゥー" name="Head Universal Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="上部のタトゥー" name="Upper Universal Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="下部のタトゥー" name="Lower Universal Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="スカートのタトゥー" name="Skirt Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="髪の毛のタトゥー" name="Hair Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="目のタトゥー" name="Eyes Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="左腕のタトゥー" name="Left Arm Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="左脚のタトゥー" name="Left Leg Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="Aux1 のタトゥー" name="Aux1 Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="Aux2 のタトゥー" name="Aux2 Tattoo" tool_tip="クリックして写真を選択する"/>
+			<texture_picker label="Aux3 のタトゥー" name="Aux3 Tattoo" tool_tip="クリックして写真を選択する"/>
+			<color_swatch label="色/明暗" name="Color/Tint" tool_tip="クリックしてカラーピッカーを開きます"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml b/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml
index 000dac7b5b90d8e4bbcc867df18115232a2f9a11..9101920f1b9d13388a7448293308a55def639e2d 100644
--- a/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/ja/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		タトゥーを編集中
 	</string>
+	<string name="edit_universal_title">
+		ユニバーサルを編集中
+	</string>
 	<string name="edit_physics_title">
 		物理作用の編集中
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		タトゥ:
 	</string>
+	<string name="universal_desc_text">
+		ユニバーサル:
+	</string>
 	<string name="physics_desc_text">
 		物理作用:
 	</string>
diff --git a/indra/newview/skins/default/xui/ja/panel_me.xml b/indra/newview/skins/default/xui/ja/panel_me.xml
index 3df1ae804870c69914a595f59e64e364394e524e..9b1cf1c8a4d6e9ac01580888a54071372ce7ed32 100644
--- a/indra/newview/skins/default/xui/ja/panel_me.xml
+++ b/indra/newview/skins/default/xui/ja/panel_me.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<panel label="マイ プロフィール" name="panel_me">
-	<panel label="マイ-ピック" name="panel_picks"/>
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="プロフィール" name="panel_me">
+	<panel label="マイ ピック" name="panel_picks"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_region_environment.xml b/indra/newview/skins/default/xui/ja/panel_region_environment.xml
index a2981012dc72be911a717106fe82259f42f629f5..444f8bae91494c8f9d2de5f68df0e16e887b6b2d 100644
--- a/indra/newview/skins/default/xui/ja/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/ja/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="環境" name="panel_env_info">
-	<text name="water_settings_title">
-		あなたのリージョンを訪れるユーザーに見せたい、水と空/デイサイクルの設定を選択します。詳細
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Second Life のデフォルト設定を使用" name="use_sl_default_settings"/>
-		<radio_item label="次の設定を使用" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			水の設定
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="- 事前設定を選択 -" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			空 / デイサイクル
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="空の固定" name="my_sky_settings"/>
-			<radio_item label="デイサイクル" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="- 事前設定を選択 -" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="- 事前設定を選択 -" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="適用" name="apply_btn"/>
-	<button label="キャンセル" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		既定の設定を使用
+	</string>
+	<string name="str_label_use_region">
+		リージョンの設定を使用
+	</string>
+	<string name="str_altitude_desription">
+		空 [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		区画が選択されていません。環境設定が無効になっています。
+	</string>
+	<string name="str_cross_region">
+		リージョンの境界では環境設定ができません。
+	</string>
+	<string name="str_legacy">
+		このリージョンで環境設定はできません。
+	</string>
+	<string name="str_disallowed">
+		不動産マネージャーが、このリージョンで区画の環境を変更することを許可していません。
+	</string>
+	<string name="str_too_small">
+		環境をサポートするには、最低でも 128 平方メートルの区画が必要です。
+	</string>
+	<string name="str_empty">
+		(空)
+	</string>
+	<string name="str_region_env">
+		(リージョンの環境)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="持ち物を使う" name="btn_select_inventory"/>
+							<button label="カスタマイズ" name="btn_edit"/>
+							<check_box label="区画所有者が環境を上書きすることがあります" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							空 [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							不明
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="持ち物から設定をこのターゲットボックスにドラッグし、現在の空として選択する"/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							空 [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							不明
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="持ち物から設定をこのターゲットボックスにドラッグし、現在の空として選択する"/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							空 [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							不明
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="持ち物から設定をこのターゲットボックスにドラッグし、現在の空として選択する"/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							地面
+						</text>
+						<line_editor name="edt_invname_ground">
+							不明
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="持ち物から設定をこのターゲットボックスにドラッグし、地表レベルの空として選択します。"/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							æ°´
+						</text>
+						<line_editor name="edt_invname_water">
+							不明
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="持ち物から設定をこのターゲットボックスにドラッグし、現在の水として選択する"/>
+					</panel>
+					<button label="リセット" name="btn_rst_altitudes" tool_tip="デフォルトの高度にリセット"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/ja/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..56fab14f7cf994660202d56c1d2b916850975ce4
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="大気&光" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/ja/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..232530c5f86c0a92b1cd975261e28e5adf57cdc9
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="雲" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/ja/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb746d8792dc29f93ed24e1a2fc7e27500f1d958
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="密度" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="レイリー指数項:" name="rayleigh_exponential"/>
+			<slider label="レイリー指数スケール:" name="rayleigh_exponential_scale"/>
+			<slider label="レイリー線形項:" name="rayleigh_linear"/>
+			<slider label="レイリー定数項:" name="rayleigh_constant"/>
+			<slider label="レイリー最大高度:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="レイリー指数項:" name="mie_exponential"/>
+			<slider label="Mie 指数スケール:" name="mie_exponential_scale"/>
+			<slider label="Mie 線形項:" name="mie_linear"/>
+			<slider label="Mie 定数項:" name="mie_constant"/>
+			<slider label="Mie 不等要素:" name="mie_aniso_factor"/>
+			<slider label="Mie 最大高度:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="吸収指数項:" name="absorption_exponential"/>
+			<slider label="吸収指数スケール:" name="absorption_exponential_scale"/>
+			<slider label="吸収線形項:" name="absorption_linear"/>
+			<slider label="吸収定数項:" name="absorption_constant"/>
+			<slider label="吸収最大高度:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/ja/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e5026dc9fd2db196536c819f3c135e5afb950234
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="太陽&月" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="ビーコンを表示" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="ビーコンを表示" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_settings_water.xml b/indra/newview/skins/default/xui/ja/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..20341fcb8d5d372d278c29012be97154770c5758
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="æ°´" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				フレネル・オフセット:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_tools_texture.xml b/indra/newview/skins/default/xui/ja/panel_tools_texture.xml
index 1821a6fad6e1b479f3f283d5214cfc6212968440..75bc8eb86f35645cf83f417d622de7ebf966e27e 100644
--- a/indra/newview/skins/default/xui/ja/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/ja/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="テクスチャ" name="Texture">
-	<panel.string name="string repeats per meter">
-		メーターごとに繰り返す
-	</panel.string>
-	<panel.string name="string repeats per face">
-		面ごとに繰り返す
-	</panel.string>
 	<text name="color label">
 		色
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="水平オフセット" name="shinyOffsetU"/>
 	<spinner label="垂直オフセット" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="平面を揃える" name="checkbox planar align" tool_tip="選択面全てのテクスチャを、最後に選択された面に揃えます。平面テクスチャのマッピングが必要です。"/>
+	<button label="揃える" label_selected="現在のテクスチャレイヤーを揃える" name="button align textures" tool_tip="現在のテクスチャレイヤーを揃える"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/role_actions.xml b/indra/newview/skins/default/xui/ja/role_actions.xml
index fe90da89c7eea3964f032f33aa69c5ed830df2bd..05eca2cca39e7eb380950b160df8edae740b2482 100644
--- a/indra/newview/skins/default/xui/ja/role_actions.xml
+++ b/indra/newview/skins/default/xui/ja/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="音楽とメディアの設定を変更" longdescription="ストリーミングミュージックと動画の設定を変更するには、「土地情報」 > 「メディア」タブを使います。" name="land change media" value="20"/>
 		<action description="「地形を編集」に切り替え" longdescription="「地形を編集」に切り替えます。 *警告* 「土地情報」>「オプション」>「地形を編集」の順で進むと、誰でもあなたの土地の形の整備や、リンデン製の樹木の設置、移動ができます。  この能力を割り振る前に、このことをよく理解しておいてください。 「土地情報」>「オプション」タブから「地形を編集」に切り替えられます。" name="land edit" value="21"/>
 		<action description="「土地情報」>「オプション」タブ内のさまざまな設定を切り替え" longdescription="「安全(ダメージなし)」、「飛行」を切り替え、住人に以下を許可します: グループ所有地の「土地情報」 &gt; 「オプション」タブ内の、「地形を編集」、「制作」、「ランドマークの作成」、「スクリプトの実行」。" name="land options" value="22"/>
+		<action description="自然環境の設定とデイサイクルを修正する。" longdescription="「土地について」 &gt; 「環境」タブから自然環境の設定とデイサイクルを変更する。" name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="これらの能力には、グループ所有の区画に関する規制を迂回することを、メンバーに許可する権限が含まれます。" name="Parcel Powers">
 		<action description="常に「地形を編集」を許可" longdescription="この能力を持つ役割のメンバーは、グループ所有の区画上で地形を編集することができます。その区画が「土地情報」>「オプション」タブでオフになっていても、地形の編集が可能です。" name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 1e123eb61977212516ed1914c222434b6e319c75..3f463765957eafd4ac7b146b0d0b16e89c725016 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -638,6 +638,15 @@ support@secondlife.com にお問い合わせください。
 	<string name="BUTTON_HELP">
 		ヘルプを表示
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		このタイプのアイテムは、このリージョンのノートカード
+に添付することができません。
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		制限のない「次の所有者」の
+許可のみノートカードに
+添付できます。
+	</string>
 	<string name="Searching">
 		検索中...
 	</string>
@@ -717,6 +726,18 @@ support@secondlife.com にお問い合わせください。
 		アップロードリクエスト中にエラーが発生しました。問題を解決するには、サポート
 (http://secondlife.com/support)にお問い合わせください。
 	</string>
+	<string name="SettingValidationError">
+		インポートする設定 [NAME] の検証に失敗しました。
+	</string>
+	<string name="SettingImportFileError">
+		ファイル [FILE] を開くことができません
+	</string>
+	<string name="SettingParseFileError">
+		ファイル [FILE] を開くことができません
+	</string>
+	<string name="SettingTranslateError">
+		過去のウインドライト [NAME] を変換できません
+	</string>
 	<string name="texture">
 		テクスチャ
 	</string>
@@ -792,6 +813,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="symbolic folder link">
 		フォルダのリンク
 	</string>
+	<string name="settings blob">
+		設定
+	</string>
 	<string name="mesh">
 		メッシュ
 	</string>
@@ -1122,6 +1146,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="ForceSitAvatar">
 		アバターを強制的に座らせる
 	</string>
+	<string name="ChangeEnvSettings">
+		自然環境の設定を変更する
+	</string>
 	<string name="NotConnected">
 		接続されていません
 	</string>
@@ -1273,6 +1300,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="tattoo">
 		タトゥ
 	</string>
+	<string name="universal">
+		ユニバーサル
+	</string>
 	<string name="physics">
 		物理作用
 	</string>
@@ -1315,6 +1345,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="tattoo_not_worn">
 		タトゥー未着用
 	</string>
+	<string name="universal_not_worn">
+		ユニバーサルなし
+	</string>
 	<string name="physics_not_worn">
 		物理作用なし
 	</string>
@@ -1366,6 +1399,9 @@ support@secondlife.com にお問い合わせください。
 	<string name="create_new_tattoo">
 		新しいタトゥを作成
 	</string>
+	<string name="create_new_universal">
+		新しいユニバーサルを作成
+	</string>
 	<string name="create_new_physics">
 		新しい物理作用を作成
 	</string>
@@ -2512,6 +2548,27 @@ support@secondlife.com にお問い合わせください。
 	<string name="RegionSettings">
 		リージョン(地域)の設定
 	</string>
+	<string name="NoEnvironmentSettings">
+		このリージョンは環境設定をサポートしていません。
+	</string>
+	<string name="EnvironmentSun">
+		太陽
+	</string>
+	<string name="EnvironmentMoon">
+		月
+	</string>
+	<string name="EnvironmentBloom">
+		花
+	</string>
+	<string name="EnvironmentCloudNoise">
+		雲の音
+	</string>
+	<string name="EnvironmentNormalMap">
+		ノーマル・マップ
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparent
+	</string>
 	<string name="ClassifiedClicksTxt">
 		クリック数: [TELEPORT] テレポート、 [MAP] 地図、 [PROFILE] プロフィール
 	</string>
@@ -4728,6 +4785,9 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="New Tattoo">
 		新しいタトゥ
 	</string>
+	<string name="New Universal">
+		新しいユニバーサル
+	</string>
 	<string name="New Physics">
 		新規の物理作用
 	</string>
@@ -4854,6 +4914,15 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Female - Wow">
 		女性 - Wow
 	</string>
+	<string name="New Daycycle">
+		新しいデイサイクル
+	</string>
+	<string name="New Water">
+		新しい水
+	</string>
+	<string name="New Sky">
+		新しい空
+	</string>
 	<string name="/bow">
 		/おじぎする
 	</string>
@@ -5382,6 +5451,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="BeaconMedia">
 		メディアビーコン(白)を表示中
 	</string>
+	<string name="BeaconSun">
+		太陽の方角ビーコン(オレンジ)を表示中
+	</string>
+	<string name="BeaconMoon">
+		月の方角ビーコン(紫)を表示中
+	</string>
 	<string name="ParticleHiding">
 		パーティクルを非表示
 	</string>
@@ -5409,6 +5484,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Command_Destinations_Label">
 		行き先
 	</string>
+	<string name="Command_Environments_Label">
+		私の環境
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5502,6 +5583,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="Command_Destinations_Tooltip">
 		行ってみたい場所
 	</string>
+	<string name="Command_Environments_Tooltip">
+		私の環境
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Facebook へ投稿
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Flickr にアップロード
 	</string>
@@ -5697,6 +5784,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="ExperiencePermission12">
 		体験の権限を自動的に承諾
 	</string>
+	<string name="ExperiencePermission16">
+		あなたのアバターを強制的に座らせる
+	</string>
+	<string name="ExperiencePermission17">
+		自然環境の設定を変更する
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		が不明な操作を実行しました: [Permission]
 	</string>
@@ -5721,6 +5814,12 @@ www.secondlife.com から最新バージョンをダウンロードしてくだ
 	<string name="ExperiencePermissionShort12">
 		権限
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Sit
+	</string>
+	<string name="ExperiencePermissionShort17">
+		環境
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		会話はログに記録されていません。ログの記録を開始するには、「環境設定」&gt;「チャット」で「保存: ログのみ」または「保存: ログと会話のテキスト」を選択します。
 	</string>
diff --git a/indra/newview/skins/default/xui/pl/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/pl/floater_delete_env_preset.xml
deleted file mode 100644
index fc750715c616f38dad7b5d941e5a61d4ee443159..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/pl/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<floater name="Delete Env Preset" title="USUŃ UST. OTOCZENIA">
-	<string name="title_water">
-		Usuń Ustawienie wody
-	</string>
-	<string name="title_sky">
-		Usuń Ustawienie nieba
-	</string>
-	<string name="title_day_cycle">
-		Usuń cykl dnia
-	</string>
-	<string name="label_water">
-		Wybierz:
-	</string>
-	<string name="label_sky">
-		Wybierz:
-	</string>
-	<string name="label_day_cycle">
-		Cykl dnia:
-	</string>
-	<string name="msg_confirm_deletion">
-		Masz absolutną pewność, że chcesz usunąć wybrane Ustawienie?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Nie można usunąć Ustawienia odwołującego się do jakiegoś cyklu dnia.
-	</string>
-	<string name="combo_label">
-		-Wybierz Ustawienie-
-	</string>
-	<text name="label">
-		Wybierz:
-	</text>
-	<button label="Usuń" name="delete" />
-	<button label="Anuluj" name="cancel" />
-</floater>
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index 2dfafff7f5aca848e41b80c0c48aeb64ed6fd7cb..4d03e7c78069ea001684dcd3c65b541fde5985e2 100644
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -84,17 +84,14 @@
 			<menu name="Water Presets" label="Ustawienia wody">
 				<menu_item_call label="Nowe Ustawienie..." name="new_water_preset" />
 				<menu_item_call label="Edytuj Ustawienie..." name="edit_water_preset" />
-				<menu_item_call label="Usuń Ustawienie..." name="delete_water_preset" />
 			</menu>
 			<menu name="Sky Presets" label="Ustawienia nieba">
 				<menu_item_call label="Nowe Ustawienie..." name="new_sky_preset" />
 				<menu_item_call label="Edytuj Ustawienie..." name="edit_sky_preset" />
-				<menu_item_call label="Usuń Ustawienie..." name="delete_sky_preset" />
 			</menu>
 			<menu name="Day Presets" label="Ustawienia pory dnia">
 				<menu_item_call label="Nowe Ustawienie..." name="new_day_preset" />
 				<menu_item_call label="Edytuj Ustawienie..." name="edit_day_preset" />
-				<menu_item_call label="Usuń Ustawienie..." name="delete_day_preset" />
 			</menu>
 		</menu>
 	</menu>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
index 738805d8000ad2db240e37a1c246acde24605c90..e8c400dbd14ea302898a4bc47739816275766d3a 100644
--- a/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_graphics1.xml
@@ -28,7 +28,6 @@
 		<check_box label="Przezroczysta woda" name="TransparentWater" />
 		<check_box label="Mapping wypukłości i połysk" name="BumpShiny" />
 		<check_box label="Lokalne światła" name="LocalLights" />
-		<check_box label="Podstawowe shadery" name="BasicShaders" tool_tip="Wyłączenie tej opcji może naprawić błędy niektórych sterowników graficznych" />
 		<check_box label="Shadery atmosfery" name="WindLightUseAtmosShaders" />
 		<check_box label="Zaawansowane oświetlenie" name="UseLightShaders" />
 		<check_box label="Okluzja otoczenia" name="UseSSAO" />
diff --git a/indra/newview/skins/default/xui/pl/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index 9aece1221d781a95cf99182997d37ec4dfdad929..91fea234d2a1ffd2a8810c7ae63fe28be7ee6b5e 100644
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -710,6 +710,9 @@ Spróbuj zalogować się ponownie za minutę.
 	<string name="mesh">
 		mesz
 	</string>
+    <string name="settings">
+        ustawień
+    </string>
 	<string name="AvatarEditingAppearance">
 		(Edycja wyglÄ…du)
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/floater_about_land.xml b/indra/newview/skins/default/xui/pt/floater_about_land.xml
index 0e7d0798c79d5cbc3119a0b58cbd27a3d0b6c47b..d7741fa90219bf6c0464a9f46cb66e0fbbbcd7e1 100644
--- a/indra/newview/skins/default/xui/pt/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about_land.xml
@@ -479,5 +479,6 @@ Mídia:
 			</panel>
 		</panel>
 		<panel label="EXPERIÊNCIAS" name="land_experiences_panel"/>
+		<panel label="AMBIENTE" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_adjust_environment.xml b/indra/newview/skins/default/xui/pt/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4e2e96c54b52c7baf613014f58000767bd966a2d
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Iluminação pessoal">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Redefinir" name="btn_reset" tool_tip="Feche e redefina e Compartilhe o Ambiente"/>
+					<text name="cloud_map_label">
+						Imagem de nuvem:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Dom:
+					</text>
+					<check_box label="Exibir baliza" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Exibir baliza" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_beacons.xml b/indra/newview/skins/default/xui/pt/floater_beacons.xml
index f8ae3cd2d8c33341610471aea29fa6663505e587..bcd6ae0400244af8217a80e54b71193900218344 100644
--- a/indra/newview/skins/default/xui/pt/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/pt/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Fontes de som" name="sounds"/>
 		<check_box label="Fontes de partículas" name="particles"/>
 		<check_box label="Fontes de mídia" name="moapbeacon"/>
+		<check_box label="Dom" name="sun"/>
+		<check_box label="Lua" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
index a31b049345c5ca186333fa19bd063c9fd3c7e345..554865b3a6ab78c15045457de84d297491ebb60e 100644
--- a/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/pt/floater_bulk_perms.xml
@@ -30,6 +30,7 @@
 	<icon name="icon_sound" tool_tip="Sons"/>
 	<check_box label="Texturas" name="check_texture"/>
 	<icon name="icon_texture" tool_tip="Texturas"/>
+	<icon name="icon_setting" tool_tip="Configurações de ambiente"/>
 	<button label="Tudo" label_selected="Todas" name="check_all"/>
 	<button label="Limpar" label_selected="Nenhuma" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/pt/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/pt/floater_delete_env_preset.xml
deleted file mode 100644
index 2434f67d6c714c469bb11a18f6ba0414910fdfb7..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/pt/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="EXCLUIR PREDEFINIÇÃO ENV">
-	<string name="title_water">
-		Excluir predefinição da água
-	</string>
-	<string name="title_sky">
-		Excluir predefinição de céu
-	</string>
-	<string name="title_day_cycle">
-		Excluir ciclo de dias
-	</string>
-	<string name="label_water">
-		Predefinição:
-	</string>
-	<string name="label_sky">
-		Predefinição:
-	</string>
-	<string name="label_day_cycle">
-		Ciclos de dias:
-	</string>
-	<string name="msg_confirm_deletion">
-		Tem certeza de que quer excluir a predefinição selecionada?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Não é possível remover uma predefinição que está referenciada por algum(ns) ciclo(s) de dias.
-	</string>
-	<string name="combo_label">
-		-Selecionar uma prefefinição-
-	</string>
-	<text name="label">
-		Predefinição:
-	</text>
-	<button label="Excluir" name="delete"/>
-	<button label="Cancelar" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/pt/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f58af73e55f1b92b322b6ba4176336e9a808e02f
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Editar ciclo de dias">
+	<string name="title_new">
+		Criar um ciclo de dias
+	</string>
+	<string name="title_edit">
+		Editar ciclo de dia
+	</string>
+	<string name="hint_new">
+		Nomeie o seu ciclo de dias, ajustar os controles para criá-lo e clique em “Salvar”.
+	</string>
+	<string name="hint_edit">
+		Editar o seu ciclo de dias, ajustar os controles para criá-lo e clique em “Salvar”.
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Céu [ALT]
+	</string>
+	<string name="sky_label">
+		Céu
+	</string>
+	<string name="water_label">
+		Água
+	</string>
+	<string name="commit_parcel">
+		Aplicar ao lote
+	</string>
+	<string name="commit_region">
+		Aplicar para a região
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Nome do ciclo de dias:
+			</text>
+			<button label="Importar" name="btn_import" tool_tip="Importar configurações do legado do disco."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Céu 4" name="sky4_track"/>
+						<button label="Céu 3" name="sky3_track"/>
+						<button label="Céu 2" name="sky2_track"/>
+						<button label="A nível do chão" name="sky1_track"/>
+						<button label="Água" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Clonar Rastreio de" name="copy_track"/>
+								<button label="Carregar rastreio de" name="load_track"/>
+								<button label="Limpar rastreio" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Passo para trás"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Passo para frente"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="Adicionar [FRAME]" name="add_frame"/>
+								<button label="Carregar [FRAME]" name="btn_load_frame"/>
+								<button label="Excluir [FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Selecionar uma estrutura chave da linha do tempo acima para editar as configurações.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Água" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmosfera e Claridade" name="atmosphere_panel"/>
+						<panel label="Nuvens" name="clouds_panel"/>
+						<panel label="Sol e Lua" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Salvar" name="save_btn"/>
+			<button label="Cancelar" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/pt/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c969aac74e29e8fe6b4cfe36800682c1b4137505
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Ambiente consertado">
+	<string name="edit_sky">
+		Editar céu:
+	</string>
+	<string name="edit_water">
+		Editar água:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Carregar" name="btn_load" tool_tip="Carregar as configurações de inventário"/>
+			<button label="Importar" name="btn_import" tool_tip="Importar configurações do legado do disco."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Salvar" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Cancelar" name="btn_cancel" tool_tip="Voltar à última versão salva"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml
index 3f66fd07b963e470d2597fe77a132fe4df90717c..c50d7dcda0d48962f76f1f3e339a5abbb3e9f4ea 100644
--- a/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Sons" name="check_sound"/>
 	<check_box label="Texturas" name="check_texture"/>
 	<check_box label="Fotos" name="check_snapshot"/>
+	<check_box label="Configurações" name="check_settings"/>
 	<button label="Tudo" label_selected="Tudo" name="All"/>
 	<button label="Nenhum" label_selected="Nenhum" name="None"/>
 	<check_box label="Sempre mostrar as pastas" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_my_environments.xml b/indra/newview/skins/default/xui/pt/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..71c1a33f58bf51401e0e226da1cc78f47ecdb57e
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Lugares" name="my_environments" title="MEUS AMBIENTES">
+	<layout_stack>
+		<layout_panel label="Filtros" name="filter_panel">
+			<check_box label="Dias" name="chk_days"/>
+			<check_box label="Céus" name="chk_skies"/>
+			<check_box label="Água" name="chk_water"/>
+			<filter_editor label="Filtrar Ambientes" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Ambientes" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Exibir todas as pastas" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Mais opções"/>
+				<menu_button name="btn_newsettings" tool_tip="Criar nova configuração"/>
+				<button name="btn_del" tool_tip="Remover item selecionado"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_perms_default.xml b/indra/newview/skins/default/xui/pt/floater_perms_default.xml
index 40659a353add5f0ed3ae1e5f2e1de9a2d89c892a..0b8914b4dd171ac44371295642a32572c02556e2 100644
--- a/indra/newview/skins/default/xui/pt/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/pt/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Definir permissões padrão para roupas ou partes do corpo criadas">
 			Itens de vestuário
 		</text>
+		<text name="label_13" tool_tip="Definir permissões padrão para quando as configurações do Ambiente forem criadas">
+			Configurações
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Cancelar" label_selected="Cancelar" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_pick_track.xml b/indra/newview/skins/default/xui/pt/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dc09f262c044174791e4936d90616e68f0d1474f
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="ESCOLHER: RASTREAR">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Selecionar o céu de origem:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Céu4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Céu3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Céu2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Chão" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Cancelar" label_selected="Cancelar" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/pt/floater_preferences_graphics_advanced.xml
index c5039267caf5b81c3a60aa82f0e94e0dab602fd5..bbe36e3e03e9c84c014722d697cb1a3b4edbd68d 100644
--- a/indra/newview/skins/default/xui/pt/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Água transparente" name="TransparentWater"/>
 	<check_box initial_value="true" label="Mapeamento de relevo e brilho" name="BumpShiny"/>
 	<check_box initial_value="true" label="Luzes locais" name="LocalLights"/>
-	<check_box initial_value="true" label="Sombreamento simples" name="BasicShaders" tool_tip="Desativar essa opção pode evitar o travamento de alguns drivers de placas gráficas"/>
 	<slider label="Detalhes do terreno:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Baixo
diff --git a/indra/newview/skins/default/xui/pt/floater_settings_picker.xml b/indra/newview/skins/default/xui/pt/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0dc80989be527814115e70798f4542600080ef35
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="ESCOLHER: CONFIGURAÇÕES">
+	<floater.string name="pick title">
+		Escolher:
+	</floater.string>
+	<floater.string name="pick_track">
+		SELECIONE RASTREIO
+	</floater.string>
+	<floater.string name="pick_settings">
+		SELECIONAR CONFIGURAÇÕES
+	</floater.string>
+	<floater.string name="track_water">
+		Água
+	</floater.string>
+	<floater.string name="track_ground">
+		Chão
+	</floater.string>
+	<floater.string name="track_sky">
+		Céu[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Filtrar texturas" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Cancelar" label_selected="Cancelar" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
index ba4ef0afdefb476bace1aec51220305be833edd6..d06c16d8c8a6b724657ccd571c06d3bc9dafe29b 100644
--- a/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Inventário" name="inventory" value="0"/>
 		<radio_item label="Local" name="local" value="1"/>
+		<radio_item label="Assar" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Tamanho: [DIMENSÕES]
@@ -19,7 +20,6 @@
 	<button label="Padrão" label_selected="Padrão" name="Default"/>
 	<button label="Branco" label_selected="Branco" name="Blank"/>
 	<button label="Nenhum" label_selected="Nenhum" name="None"/>
-	<check_box initial_value="true" label="Inscrever-se agora" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Visualização desativada"/>
 	<filter_editor label="Filtrar texturas" name="inventory search editor"/>
 	<check_box initial_value="false" label="Exibir pastas" name="show_folders_check"/>
@@ -30,6 +30,22 @@
 		<column label="Nome" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Escolha a textura de assar">
+		<combo_box.item label="Nenhum" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Ocultar região da mesh de base" name="hide_base_mesh_region"/>
 	<button label="OK" label_selected="OK" name="Select"/>
 	<button label="Cancelar" label_selected="Cancelar" name="Cancel"/>
+	<check_box initial_value="true" label="Inscrever-se agora" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/pt/menu_inventory.xml b/indra/newview/skins/default/xui/pt/menu_inventory.xml
index b99ddc67d2fcf37d364d62fd76e6f17af664a0db..78a0482deea2b07fc6b6726f3a14e0ef1f952d6e 100644
--- a/indra/newview/skins/default/xui/pt/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/pt/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Ativar" name="Marketplace Activate"/>
 	<menu_item_call label="Desativar" name="Marketplace Deactivate"/>
 	<menu_item_call label="Compartilhar" name="Share"/>
-	<menu_item_call label="Comprar" name="Task Buy"/>
 	<menu_item_call label="Abrir" name="Task Open"/>
 	<menu_item_call label="Executar" name="Task Play"/>
 	<menu_item_call label="Propriedades" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Nova roupa de baixo" name="New Underpants"/>
 		<menu_item_call label="Nova máscara alfa" name="New Alpha Mask"/>
 		<menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+		<menu_item_call label="Novo universal" name="New Universal"/>
 		<menu_item_call label="Novo físico" name="New Physics"/>
 	</menu>
 	<menu label="Nova parte do corpo" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Novo cabelo" name="New Hair"/>
 		<menu_item_call label="Novos olhos" name="New Eyes"/>
 	</menu>
+	<menu label="Novas configurações" name="New Settings">
+		<menu_item_call label="Novo céu" name="New Sky"/>
+		<menu_item_call label="Nova água" name="New Water"/>
+		<menu_item_call label="Novo ciclo de dias" name="New Day Cycle"/>
+	</menu>
 	<menu label="Usar como padrão para" name="upload_def">
 		<menu_item_call label="Envios de imagem" name="Image uploads"/>
 		<menu_item_call label="Envios de som" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Editar" name="Wearable Edit"/>
 	<menu_item_call label="Adicionar" name="Wearable Add"/>
 	<menu_item_call label="Tirar" name="Take Off"/>
+	<menu_item_call label="Aplicar somente a mim" name="Settings Apply Local"/>
+	<menu_item_call label="Aplicar ao lote" name="Settings Apply Parcel"/>
 	<menu_item_call label="Copiar para Listagens do Marketplace" name="Marketplace Copy"/>
 	<menu_item_call label="Mover para Listagens do Marketplace" name="Marketplace Move"/>
 	<menu_item_call label="--Sem opções--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
index 92621e8493404aa37b73f97c5b6b9f3a35a71b5c..0eaf3c7c5fb7f1a0a02aaaf282933aaa36e3799a 100644
--- a/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/pt/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Som (L$[COST])..." name="Upload Sound"/>
 		<menu_item_call label="Animação (L$[COST])..." name="Upload Animation"/>
 		<menu_item_call label="Modelar..." name="Upload Model"/>
-		<menu_item_call label="Assistente de modelagem..." name="Upload Model Wizard"/>
 		<menu_item_call label="Volume..." name="Bulk Upload"/>
-		<menu_item_call label="Autorizações de upload padrão" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Nova pasta" name="New Folder"/>
 	<menu_item_call label="Novo script" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Novas roupa de baixo" name="New Underpants"/>
 		<menu_item_call label="Novo alpha" name="New Alpha"/>
 		<menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+		<menu_item_call label="Novo universal" name="New Universal"/>
 		<menu_item_call label="Novo físico" name="New Physics"/>
 	</menu>
 	<menu label="Nova parte do corpo" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Novo cabelo" name="New Hair"/>
 		<menu_item_call label="Novos olhos" name="New Eyes"/>
 	</menu>
+	<menu label="Novas configurações" name="New Settings">
+		<menu_item_call label="Novo céu" name="New Sky"/>
+		<menu_item_call label="Nova água" name="New Water"/>
+		<menu_item_call label="Novo ciclo de dias" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml b/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml
index ccf65ae5664e49c8abc742b6b8ac56d28ee16578..1de8fd939bb59d48f0e9b8624b6556e59405e4da 100644
--- a/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/pt/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Novo alpha" name="New Alpha"/>
 		<menu_item_call label="Novo físico" name="New Physics"/>
 		<menu_item_call label="Nova tatuagem" name="New Tattoo"/>
+		<menu_item_call label="Novo universal" name="New Universal"/>
 	</menu>
 	<menu label="Nova parte do corpo" name="New Body Parts">
 		<menu_item_call label="Nova silhueta" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/pt/menu_save_settings.xml b/indra/newview/skins/default/xui/pt/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9af5d016294287c87dea1c278b90d01b980e7971
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Salvar" name="save_settings"/>
+	<menu_item_check label="Salvar como" name="save_as_new_settings"/>
+	<menu_item_check label="Enviar" name="commit_changes"/>
+	<menu_item_check label="Aplicar somente a mim" name="apply_local"/>
+	<menu_item_check label="Aplicar ao lote" name="apply_parcel"/>
+	<menu_item_check label="Aplicar para a região" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_settings_add.xml b/indra/newview/skins/default/xui/pt/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3bd87e6c12b1f6a4a44715cd10b3b34c98ccf5fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Novo céu" name="New Sky"/>
+	<menu_item_call label="Nova água" name="New Water"/>
+	<menu_item_call label="Novo ciclo de dias" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_settings_gear.xml b/indra/newview/skins/default/xui/pt/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..55817b22e064f41f2ab09460c310dd2610445072
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Editar" name="edit_settings"/>
+	<menu_item_call label="Aplicar somente a mim" name="Settings Apply Local"/>
+	<menu_item_call label="Aplicar ao lote" name="Settings Apply Parcel"/>
+	<menu_item_call label="Aplicar para a região" name="Settings Apply Region"/>
+	<menu_item_call label="Copiar" name="copy_settings"/>
+	<menu_item_call label="Colar" name="paste_settings"/>
+	<menu_item_call label="Copiar UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index e82b7bc62a58a5c614ab8f08b211502b4bcd59b3..8b144390faf379a637a3ee24e8f3d27cde5ea4ab 100644
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -79,30 +79,15 @@
 			<menu_item_check label="Propriedades do lote" name="Parcel Properties"/>
 			<menu_item_check label="Menu avançado" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Dom" name="Sun">
+		<menu label="Ambiente" name="Environment">
 			<menu_item_check label="Nascer do sol" name="Sunrise"/>
 			<menu_item_check label="Meio-dia" name="Noon"/>
 			<menu_item_check label="Pôr do sol" name="Sunset"/>
 			<menu_item_check label="Meia-noite" name="Midnight"/>
-			<menu_item_check label="Usar as configurações da região" name="Use Region Settings"/>
-		</menu>
-		<menu label="Editor de ambientes" name="Environment Editor">
-			<menu_item_call label="Configurações do ambiente..." name="Environment Settings"/>
-			<menu label="Predefinições da água" name="Water Presets">
-				<menu_item_call label="Nova predefinição..." name="new_water_preset"/>
-				<menu_item_call label="Editar predefinição..." name="edit_water_preset"/>
-				<menu_item_call label="Excluir predefinição..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Predefinições de céu" name="Sky Presets">
-				<menu_item_call label="Nova predefinição..." name="new_sky_preset"/>
-				<menu_item_call label="Editar predefinição..." name="edit_sky_preset"/>
-				<menu_item_call label="Excluir predefinição..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Predefinições do dia" name="Day Presets">
-				<menu_item_call label="Nova predefinição..." name="new_day_preset"/>
-				<menu_item_call label="Editar predefinição..." name="edit_day_preset"/>
-				<menu_item_call label="Excluir predefinição..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Use o ambiente compartilhado" name="Use Shared Environment"/>
+			<menu_item_call label="Meu ambiente..." name="my_environs"/>
+			<menu_item_call label="Iluminação pessoal..." name="adjustment_tool"/>
+			<menu_item_check label="Pausar as nuvens" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Construir" name="BuildTools">
@@ -323,6 +308,9 @@
 			<menu_item_check label="Máscaras alpha automáticas (sem adiar)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Texturas de animação" name="Animation Textures"/>
 			<menu_item_check label="Desativar texturas" name="Disable Textures"/>
+			<menu_item_check label="Desativar ambiente" name="Disable Ambient"/>
+			<menu_item_check label="Desabilitar a luz solar" name="Disable Sunlight"/>
+			<menu_item_check label="Desativar Luzes locais" name="Disable Local Lights"/>
 			<menu_item_check label="Render Attached Lights" name="Render Attached Lights"/>
 			<menu_item_check label="Render Attached Particles" name="Render Attached Particles"/>
 			<menu_item_check label="Objetos iridescentes" name="Hover Glow Objects"/>
@@ -413,6 +401,7 @@
 	</menu>
 	<menu label="Admin" name="Deprecated">
 		<menu label="Take Off Clothing" name="Take Off Clothing">
+			<menu_item_call label="Universal" name="Universal"/>
 			<menu_item_call label="Físico" name="Physics"/>
 		</menu>
 		<menu label="Ajuda" name="DeprecatedHelp">
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index 530a272dbbb482355ef4d4956c5ef388325ff8aa..35f65a59bc584c697851a2ea726a645d18ded200 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -1951,6 +1951,11 @@ Isto mudará milhares de regiões e fará o spaceserver soluçar.
 		Ao desselecionar esta opção, você pode remover as restrições que os proprietários dos terrenos adicionaram para evitar problemas, manter a privacidade ou proteger residentes menores de idade contra conteúdo adulto. Por favor, discuta com os seus proprietários de terreno conforme necessário.
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Desmarcando esta opção pode remover quaisquer ambientes personalizados que os proprietários tenham adicionado aos seus lotes.. 
+Por favor, discuta com os seus proprietários de terreno conforme necessário. Deseja continuar?
+		<usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		A região que você está tentando visitar tem conteúdo que excede suas preferências atuais.  Você pode alterar suas preferências acessando Eu &gt; Preferências &gt; Geral.
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2431,7 +2436,15 @@ Inclua um link para facilitar o acesso para visitantes. Teste o link na barra de
 		Este arquivo de ciclo de dia se refere a um arquivo de céu faltando: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		As configurações não podem ser aplicadas à região.   Talvez sair e votlar à região resolva.   Motivo:  [FAIL_REASON]
+		As configurações não puderam ser aplicadas para a região. Motivo: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Uma textura local está em uso no rastreio [TRACK], moldura #[FRAMENO] ([FRAME]%) no campo [FIELD]. 
+As definições não puderam ser salvas usando as texturas locais.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Uma textura local está em uso no campo [FIELD]. 
+As definições não puderam ser salvas usando as texturas locais.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Impossível excluir a última chave do ciclo pois um ciclo não pode ficar vazio.   Modifique a última chave em vez de tentar apagá-la, depois crie uma chave nova.
@@ -4376,4 +4389,76 @@ Tente selecionar uma quantidade menor de terreno.
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		Não pode carregar as configurações para [NAME] da base de dados.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Não foi possível aplicar aquelas configurações para o ambiente.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Não foi possível aplicar aquelas configurações para o ambiente.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Esta Região não suporta as configurações do ambiente.
+	</notification>
+	<notification label="Salvar visual" name="SaveSettingAs">
+		Salve as configurações do ambiente atual como:
+		<form name="form">
+			<input name="message">
+				[DESC] (novo)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Cancelar"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Não foi possível imporar as configurações do vento antigo [NAME] de 
+[FILE]. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Não é possível definir o ambiente para este lote. 
+Inserir ou selecionar um lote que você tem direitos para modificar.
+	</notification>
+	<notification name="SettingsUnsuported">
+		As configurações não são suportadas para esta região. 
+Mude para uma configuração permitida para a região ou tente novamente realizar a ação.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Você está prestes a perder as alterações que você fez para este [TYPE] com o nome &quot;[NAME]&quot;. 
+Tem certeza de que deseja continuar?
+		<usetemplate ignoretext="Tem certeza de que deseja perder as alterações?" name="okcancelignore" notext="Não" yestext="Sim"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Você está prestes a remover todas as configurações aplicadas. 
+Tem certeza de que deseja continuar?
+		<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Você está prestes a remover todas as configurações de Iluminação pessoal aplicadas. 
+Tem certeza de que deseja continuar?
+		<usetemplate name="okcancelbuttons" notext="Não" yestext="Sim"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Você está prestes a importar configurações não transferíveis para este ciclo de dias. Caso continue, transformará as configurações que você está editando não transferível também. 
+
+Esta alteração não pode ser desfeita. 
+
+Tem certeza de que deseja continuar?
+		<usetemplate ignoretext="Tem certeza de que deseja tornar as configurações não transferível?" name="okcancelignore" notext="Não" yestext="Sim"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Você não pode editar as configurações diretamente da biblioteca. 
+Copie para o seu próprio inventário e tente novamente.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Encontramos problemas com essas configurações. Eles não podem ser salvos ou aplicados desta vez.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Não foi possível carregar o rastreio para [TRACK].
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Não foi possível carregar rastreio de [TRACK1] em [TRACK2].
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml
index f85bb3c49993f9219c21e659e7143bd4a4638b8e..f5d513e2f6b90541b3fc3020706a977f3fc319f5 100644
--- a/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/pt/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Tatuagem de cabeça" name="Head Tattoo" tool_tip="Clique para escolher uma foto"/>
-		<texture_picker label="Tatuagem superior" name="Upper Tattoo" tool_tip="Selecione uma foto"/>
-		<texture_picker label="Tatuagem inferior" name="Lower Tattoo" tool_tip="Selecione uma foto"/>
-		<color_swatch label="Cor/Tonalidade" name="Color/Tint" tool_tip="Selecionar a cor"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Tatuagem na cabeça" name="Head Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem parte de cima" name="Upper Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem de baixo" name="Lower Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<color_swatch label="Cor/Tonalidade" name="Color/Tint" tool_tip="Selecionar a cor"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_edit_universal.xml b/indra/newview/skins/default/xui/pt/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0bcaa36f1db6ee8f242a2734d75cc96f52d30382
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Tatuagem na cabeça" name="Head Universal Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem parte de cima" name="Upper Universal Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem de baixo" name="Lower Universal Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem de saia" name="Skirt Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem de cabelo" name="Hair Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem de olhos" name="Eyes Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem no Braço esquerdo" name="Left Arm Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Tatuagem na perna esquerdo" name="Left Leg Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Aux1 Tatuagem" name="Aux1 Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Aux2 Tatuagem" name="Aux2 Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<texture_picker label="Aux3 Tatuagem" name="Aux3 Tattoo" tool_tip="Clique para selecionar uma imagem"/>
+			<color_swatch label="Cor/Tonalidade" name="Color/Tint" tool_tip="Selecionar a cor"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml
index 2e3e3d63058b417c39999911e566e9212768a246..e8d9063206dd15f1734e5b348125d43685e2b39a 100644
--- a/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/pt/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Editando tatuagem
 	</string>
+	<string name="edit_universal_title">
+		Edição Universal
+	</string>
 	<string name="edit_physics_title">
 		Editando o físico
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Tatuagem:
 	</string>
+	<string name="universal_desc_text">
+		Universal:
+	</string>
 	<string name="physics_desc_text">
 		Físico:
 	</string>
diff --git a/indra/newview/skins/default/xui/pt/panel_region_environment.xml b/indra/newview/skins/default/xui/pt/panel_region_environment.xml
index 7593c50941390c6addbdfcf7984ee1f4f92b598c..f99a75d699ef41ed289f82cdf6edba8bfa77041f 100644
--- a/indra/newview/skins/default/xui/pt/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/pt/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Ambiente" name="panel_env_info">
-	<text name="water_settings_title">
-		Selecionar a Água e o Céu/Configurações de Ciclo de Dias que você gostaria que todos os visitantes da sua região visse. Mais informações
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Use o padrão Second Life" name="use_sl_default_settings"/>
-		<radio_item label="Use as seguintes configurações" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Configurações da água
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Selecionar uma prefefinição-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Céu / Ciclo de dias
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Céu fixo" name="my_sky_settings"/>
-			<radio_item label="Ciclos de dias" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Selecionar uma prefefinição-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Selecionar uma prefefinição-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Aplicar" name="apply_btn"/>
-	<button label="Cancelar" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Usar as configurações padrões
+	</string>
+	<string name="str_label_use_region">
+		Usar as configurações da região
+	</string>
+	<string name="str_altitude_desription">
+		Céu [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		Nenhum lote está selecionado. As configurações do ambiente estão desativadas.
+	</string>
+	<string name="str_cross_region">
+		As configurações do ambiente não estão disponíveis além das fronteiras da região.
+	</string>
+	<string name="str_legacy">
+		As configurações do ambiente não estão disponíveis nesta região.
+	</string>
+	<string name="str_disallowed">
+		O gerente do estado não permite alteração dos ambientes dos lotes nesta região.
+	</string>
+	<string name="str_too_small">
+		O lote deve ter no mínimo 128 metros quadrados para suportar um ambiente.
+	</string>
+	<string name="str_empty">
+		(vazio)
+	</string>
+	<string name="str_region_env">
+		(região ambiente)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Usar inventário" name="btn_select_inventory"/>
+							<button label="Customizar" name="btn_edit"/>
+							<check_box label="Os proprietários do lote podem desconsiderar o ambiente" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Céu [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Desconhecido
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Céu [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Desconhecido
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Céu [INDEX]
+                            [ALTITUDE]m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Desconhecido
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o céu atual."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Chão
+						</text>
+						<line_editor name="edt_invname_ground">
+							Desconhecido
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como o nível do chão do céu."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Água
+						</text>
+						<line_editor name="edt_invname_water">
+							Desconhecido
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Arraste uma configuração do Inventário para a caixa alvo para selecionar como a água atual."/>
+					</panel>
+					<button label="Redefinir" name="btn_rst_altitudes" tool_tip="Redefinir para padrão de altitudes"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/pt/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..25c27cd6e61657f2ab5ae651ad08e9ba96fe40e5
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmosfera e Claridade" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/pt/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/pt/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..70f814138a41d0df6c3dc14cf21087b5b284043b
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Nuvens" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/pt/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14143a928a5f5c0961831af9c93b052efd761e75
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Densidade" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Espelhar termo exponencial:" name="rayleigh_exponential"/>
+			<slider label="Espelhar escala exponencial:" name="rayleigh_exponential_scale"/>
+			<slider label="Espelhar termo linear:" name="rayleigh_linear"/>
+			<slider label="Espelhar termo constante:" name="rayleigh_constant"/>
+			<slider label="Espelhar altitude máxima:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Mie termo exponencial:" name="mie_exponential"/>
+			<slider label="Mie escala exponencial:" name="mie_exponential_scale"/>
+			<slider label="Mie termo linear:" name="mie_linear"/>
+			<slider label="Mie termo constante:" name="mie_constant"/>
+			<slider label="Mie fator aniso:" name="mie_aniso_factor"/>
+			<slider label="Mie altitude máxima:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Absorção termo exponencial:" name="absorption_exponential"/>
+			<slider label="Absorção escala exponencial:" name="absorption_exponential_scale"/>
+			<slider label="Absorção termo linear:" name="absorption_linear"/>
+			<slider label="Absorção termo constante:" name="absorption_constant"/>
+			<slider label="Absorção altitude máxima:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/pt/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe6672b2617be1b1e300c677d4533d95aa8a1598
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Sol e Lua" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Exibir baliza" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Exibir baliza" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_settings_water.xml b/indra/newview/skins/default/xui/pt/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a6e6462bdc777c986dbf15c204bb0f5f03cbee0
--- /dev/null
+++ b/indra/newview/skins/default/xui/pt/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Água" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Offset fresnel:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_tools_texture.xml b/indra/newview/skins/default/xui/pt/panel_tools_texture.xml
index 5e97eca605995cbaa1edfef8f53839cc62da98cf..4f484c5fce6217dab068b8c9aa14e9343f1eeea9 100644
--- a/indra/newview/skins/default/xui/pt/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/pt/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Textura" name="Texture">
-	<panel.string name="string repeats per meter">
-		Repetições por metro
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Repetições por face
-	</panel.string>
 	<text name="color label">
 		Cor
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Offset horizontal" name="shinyOffsetU"/>
 	<spinner label="Offset vertical" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Alinhar planos planares" name="checkbox planar align" tool_tip="Alinhar texturas de todos os planos selecionados com o plano selecionado por último. Requer mapeamento de textura planar."/>
+	<button label="Alinhar" label_selected="Alinhar camadas de textura atual" name="button align textures" tool_tip="Alinhar camadas de textura atual"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/pt/role_actions.xml b/indra/newview/skins/default/xui/pt/role_actions.xml
index 67ecfa0be3e047db9eafeedecbf1eb67b740db44..e09476a83ee16667b039de7e3b52c310c9894518 100644
--- a/indra/newview/skins/default/xui/pt/role_actions.xml
+++ b/indra/newview/skins/default/xui/pt/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Mudar música &amp; configurações de mídia" longdescription="Mude streaming de música e configurações de vídeo em Sobre o terreno &gt; aba Mídia." name="land change media" value="20"/>
 		<action description="Ativar/desativar &apos;Editar terreno&apos;" longdescription="Ative/desative &apos;Editar terreno&apos;. *AVISO* Sobre o terreno &gt; aba Opções &gt; Editar terreno permite a qualquer um alterar as formas de seu terreno, substituir e mover plantas Linden. Certifique-se de saber o que está fazendo antes de desginar esta habilidade. A edição de terreno é ativada/desativada em Sobre o terreno &gt; aba Opções." name="land edit" value="21"/>
 		<action description="Ativar/desativar variados Sobre o Terreno &gt; Opções de configuração" longdescription="Alterna as opções &apos;Seguro (zero danos)&apos;, &apos;Voar&apos; e autorizar outros residentes a:  &apos;Editar terreno&apos;, &apos;Contruir&apos;, &apos;Criar marcos&apos; e &apos;Executar scripts&apos; nos terrenos do grupo. Clique em Sobre o terreno &gt; guia Opções." name="land options" value="22"/>
+		<action description="Modificar configurações do ambiente e ciclos de dia." longdescription="Mude as configurações de ambiente e ciclos de dia em Sobre terrenos &gt; Aba Ambiente." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Estas habilidades incluem poderes que permitem a membros ultrapassar restrições em parcelas pertencentes ao grupo." name="Parcel Powers">
 		<action description="Sempre permitir &apos;Editar terreno&apos;" longdescription="Membros em uma função com esta habilidade podem editar terreno em uma parcela pertencente ao grupo, mesmo se estiver desativada em Sobre o terreno &gt; aba Opções." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/pt/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index cccc70a92a82a2f567f1850d0113c326ec340bd5..6b86c4330c62165fa20165237fc366464d87a923 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -595,6 +595,15 @@ Aguarde um minuto antes que tentar logar-se novamente.
 	<string name="BUTTON_HELP">
 		Mostrar ajuda
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Os itens deste tipo não podem ser anexados 
+às anotações desta região.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Somente itens com permissões irrestritas 
+do &apos;próximo proprietário’ pode 
+ser anexado às anotações.
+	</string>
 	<string name="Searching">
 		Buscando...
 	</string>
@@ -671,6 +680,18 @@ Aguarde um minuto antes que tentar logar-se novamente.
 		Erro na solicitação de upload. Acesso 
 http://secondlife.com/support para ajuda ao resolver este problema.
 	</string>
+	<string name="SettingValidationError">
+		Falha na validação para importação das configurações [NAME]
+	</string>
+	<string name="SettingImportFileError">
+		Não foi possível abrir o arquivo [FILE]
+	</string>
+	<string name="SettingParseFileError">
+		Não foi possível abrir o arquivo [FILE]
+	</string>
+	<string name="SettingTranslateError">
+		Não foi possível traduzir o vento antigo [NAME]
+	</string>
 	<string name="texture">
 		textura
 	</string>
@@ -746,6 +767,9 @@ http://secondlife.com/support para ajuda ao resolver este problema.
 	<string name="symbolic folder link">
 		link da pasta
 	</string>
+	<string name="settings blob">
+		configurações
+	</string>
 	<string name="mesh">
 		mesh
 	</string>
@@ -1076,6 +1100,9 @@ http://secondlife.com/support para ajuda ao resolver este problema.
 	<string name="ForceSitAvatar">
 		Forçar o avatar a sentar
 	</string>
+	<string name="ChangeEnvSettings">
+		Alterar sua configurações de ambiente
+	</string>
 	<string name="AgentNameSubst">
 		(Você)
 	</string>
@@ -1224,6 +1251,9 @@ http://secondlife.com/support para ajuda ao resolver este problema.
 	<string name="tattoo">
 		Tatuagem
 	</string>
+	<string name="universal">
+		Universal
+	</string>
 	<string name="physics">
 		Físico
 	</string>
@@ -1266,6 +1296,9 @@ http://secondlife.com/support para ajuda ao resolver este problema.
 	<string name="tattoo_not_worn">
 		Tatuagem não usada
 	</string>
+	<string name="universal_not_worn">
+		Universal não usado
+	</string>
 	<string name="physics_not_worn">
 		Físico não usado
 	</string>
@@ -1317,6 +1350,9 @@ http://secondlife.com/support para ajuda ao resolver este problema.
 	<string name="create_new_tattoo">
 		Criar nova tatuagem
 	</string>
+	<string name="create_new_universal">
+		Criar um novo universal
+	</string>
 	<string name="create_new_physics">
 		Criar novo físico
 	</string>
@@ -2452,6 +2488,27 @@ Se você continuar a receber essa mensagem, entre em contato com o suporte do Se
 	<string name="RegionSettings">
 		Configurações da região
 	</string>
+	<string name="NoEnvironmentSettings">
+		Esta Região não suporta as configurações do ambiente.
+	</string>
+	<string name="EnvironmentSun">
+		Dom
+	</string>
+	<string name="EnvironmentMoon">
+		Lua
+	</string>
+	<string name="EnvironmentBloom">
+		Florescer
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Ruído na nuvem
+	</string>
+	<string name="EnvironmentNormalMap">
+		Mapa normal
+	</string>
+	<string name="EnvironmentTransparent">
+		Transparente
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Cliques: [TELEPORT] teletransporte, [MAP] mapa, [PROFILE] perfil
 	</string>
@@ -4604,6 +4661,9 @@ Denunciar abuso
 	<string name="New Tattoo">
 		Nova tatuagem
 	</string>
+	<string name="New Universal">
+		Novo universal
+	</string>
 	<string name="New Physics">
 		Novo físico
 	</string>
@@ -4730,6 +4790,15 @@ Denunciar abuso
 	<string name="Female - Wow">
 		Wow - feminino
 	</string>
+	<string name="New Daycycle">
+		Novo ciclo de dias
+	</string>
+	<string name="New Water">
+		Nova água
+	</string>
+	<string name="New Sky">
+		Novo céu
+	</string>
 	<string name="/bow">
 		/reverência
 	</string>
@@ -5258,6 +5327,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="BeaconMedia">
 		Vendo balizas de mídia (branco)
 	</string>
+	<string name="BeaconSun">
+		Visualizando farol de direção do sol (alaranjado)
+	</string>
+	<string name="BeaconMoon">
+		Visualizando farol de direção da lua (roxo)
+	</string>
 	<string name="ParticleHiding">
 		Ocultar partículas
 	</string>
@@ -5285,6 +5360,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="Command_Destinations_Label">
 		Destinos
 	</string>
+	<string name="Command_Environments_Label">
+		Meus ambientes
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5378,6 +5459,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="Command_Destinations_Tooltip">
 		Destinos de interesse
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Meus ambientes
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Publicar no Facebook
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Carregar no Flickr
 	</string>
@@ -5573,6 +5660,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="ExperiencePermission12">
 		aceitar automaticamente permissões de experiência
 	</string>
+	<string name="ExperiencePermission16">
+		forçar o avatar a sentar
+	</string>
+	<string name="ExperiencePermission17">
+		alterar sua configurações de ambiente
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		realizar uma operação desconhecida: [Permission]
 	</string>
@@ -5597,6 +5690,12 @@ Tente colocar o caminho do editor entre aspas.
 	<string name="ExperiencePermissionShort12">
 		Autorização
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Sentar
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Ambiente
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		As conversas não estão sendo registradas. Para começar a manter um registro, selecione &quot;Salvar: apenas registro&quot; ou &quot;Salvar: registro e transcrições&quot; em Preferências&gt; Bate-papo.
 	</string>
diff --git a/indra/newview/skins/default/xui/ru/floater_about_land.xml b/indra/newview/skins/default/xui/ru/floater_about_land.xml
index fb17896551c075dfc6dccbd9b28e68d7815e981b..4848f2f7e75b824208cc411ce3d0e8c29513f374 100644
--- a/indra/newview/skins/default/xui/ru/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about_land.xml
@@ -474,5 +474,6 @@
 			</panel>
 		</panel>
 		<panel label="ПРИКЛЮЧЕНИЯ" name="land_experiences_panel"/>
+		<panel label="ОКРУЖАЮЩАЯ СРЕДА" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_adjust_environment.xml b/indra/newview/skins/default/xui/ru/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..85809966e49483a259bf8af0dcc6ec5eaecf8763
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Личное освещение">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Сброс" name="btn_reset" tool_tip="Закрыть и сбросить в общую среду"/>
+					<text name="cloud_map_label">
+						Изображение облака:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Солнце:
+					</text>
+					<check_box label="Показать метку" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="Показать метку" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_beacons.xml b/indra/newview/skins/default/xui/ru/floater_beacons.xml
index 38d257ff8187a0b647914da41954282e35b09a57..9d706a7c5d450e20134f37d70ba09df746f2b197 100644
--- a/indra/newview/skins/default/xui/ru/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/ru/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Источники звука" name="sounds"/>
 		<check_box label="Источники частиц" name="particles"/>
 		<check_box label="Источники медиа" name="moapbeacon"/>
+		<check_box label="Солнце" name="sun"/>
+		<check_box label="Луна" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml b/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml
index 55b0e0c3bd6bdd240659e5fb8b087387091451f2..f5115a161dec70e62077ca15199f4974b49c40a3 100644
--- a/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/ru/floater_bulk_perms.xml
@@ -21,6 +21,7 @@
 	<icon name="icon_script" tool_tip="Скрипты"/>
 	<icon name="icon_sound" tool_tip="Звуки"/>
 	<icon name="icon_texture" tool_tip="Текстуры"/>
+	<icon name="icon_setting" tool_tip="Настройки окружающей среды"/>
 	<button label="√ Все" name="check_all"/>
 	<button label="Очистить" label_selected="Нет" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/ru/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/ru/floater_delete_env_preset.xml
deleted file mode 100644
index 1ae278f03b4b325d2de928355f8a2eb1d240ee09..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/ru/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="УДАЛЕНИЕ НАСТРОЙКИ СРЕДЫ">
-	<string name="title_water">
-		Удалить настройку воды
-	</string>
-	<string name="title_sky">
-		Удалить настройку неба
-	</string>
-	<string name="title_day_cycle">
-		Удалить суточный цикл
-	</string>
-	<string name="label_water">
-		Настройка:
-	</string>
-	<string name="label_sky">
-		Настройка:
-	</string>
-	<string name="label_day_cycle">
-		Суточный цикл:
-	</string>
-	<string name="msg_confirm_deletion">
-		Действительно удалить выбранную настройку?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Нельзя удалить настройку, которая используется в некоторых суточных циклах.
-	</string>
-	<string name="combo_label">
-		-Выбор настройки-
-	</string>
-	<text name="label">
-		Настройка:
-	</text>
-	<button label="Удалить" name="delete"/>
-	<button label="Отмена" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/ru/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ba01b13a82284263b2f30d2f79ad04ec69cd7f23
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Изменить суточный цикл">
+	<string name="title_new">
+		Создать новый суточный цикл
+	</string>
+	<string name="title_edit">
+		Изменить суточный цикл
+	</string>
+	<string name="hint_new">
+		Введите имя суточного цикла, задайте его параметры с помощью элементов управления и нажмите кнопку «Сохранить».
+	</string>
+	<string name="hint_edit">
+		Чтобы изменить суточный цикл, задайте его параметры с помощью элементов управления ниже и нажмите кнопку «Сохранить».
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Небо [ALT]
+	</string>
+	<string name="sky_label">
+		Небо
+	</string>
+	<string name="water_label">
+		Вода
+	</string>
+	<string name="commit_parcel">
+		Применить к участку
+	</string>
+	<string name="commit_region">
+		Применить к региону
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Название суточного цикла:
+			</text>
+			<button label="Импортировать" name="btn_import" tool_tip="Импортировать устаревшие настройки с диска."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Небо 4" name="sky4_track"/>
+						<button label="Небо 3" name="sky3_track"/>
+						<button label="Небо 2" name="sky2_track"/>
+						<button label="Уровень земли" name="sky1_track"/>
+						<button label="Вода" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Клонировать режим редактирования из" name="copy_track"/>
+								<button label="Загрузить режим редактирования из" name="load_track"/>
+								<button label="Очистить режим редактирования" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Шаг назад"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="Шаг вперед"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="Добавить [FRAME]" name="add_frame"/>
+								<button label="Загрузить [FRAME]" name="btn_load_frame"/>
+								<button label="Удалить [FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Выбрать ключевой фрейм на временной шкале выше для изменения настроек.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Вода" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Атмосфера и освещение" name="atmosphere_panel"/>
+						<panel label="Облака" name="clouds_panel"/>
+						<panel label="Солнце и луна" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Сохранить" name="save_btn"/>
+			<button label="Отмена" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/ru/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b5f1a1ced25c775bbf8d82052a5a52c64c2f26fa
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Фиксированная среда">
+	<string name="edit_sky">
+		Редактировать настройки неба:
+	</string>
+	<string name="edit_water">
+		Редактировать настройки воды:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Загрузить" name="btn_load" tool_tip="Загрузить настройки из инвентарного списка"/>
+			<button label="Импортировать" name="btn_import" tool_tip="Импортировать устаревшие настройки с диска."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Сохранить" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="Отмена" name="btn_cancel" tool_tip="Вернуться к последней сохраненной версии"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml
index ce6b89cb82d66b5294951b4fd372df5424c1f3d5..7c1d3b52c5f22fbcb9b1c18c71cc60f972a06863 100644
--- a/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/ru/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Звуки" name="check_sound"/>
 	<check_box label="Текстуры" name="check_texture"/>
 	<check_box label="Снимки" name="check_snapshot"/>
+	<check_box label="Настройки" name="check_settings"/>
 	<button label="Все" label_selected="Все" name="All"/>
 	<button label="Нет" label_selected="Нет" name="None"/>
 	<check_box label="Всегда показывать папки" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/ru/floater_my_environments.xml b/indra/newview/skins/default/xui/ru/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ba31600df77a5afcea716e2a46d22e2c1809a406
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Места" name="my_environments" title="МОЯ ОКРУЖАЮЩАЯ СРЕДА">
+	<layout_stack>
+		<layout_panel label="Фильтры" name="filter_panel">
+			<check_box label="Дни" name="chk_days"/>
+			<check_box label="Небеса" name="chk_skies"/>
+			<check_box label="Вода" name="chk_water"/>
+			<filter_editor label="Фильтр окружающей среды" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Окружающая среда" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Показать все папки" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Дополнительные параметры"/>
+				<menu_button name="btn_newsettings" tool_tip="Создать новую настройку"/>
+				<button name="btn_del" tool_tip="Удалить выбранную вещь"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_perms_default.xml b/indra/newview/skins/default/xui/ru/floater_perms_default.xml
index a33c6b40b60b46e74506936f25a9fd4a8b00794a..2a239c07c49aa4f78394ec77dcdb87db4ae6b2a7 100644
--- a/indra/newview/skins/default/xui/ru/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/ru/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Задайте стандартные разрешения для создания одежды или частей тела">
 			Носимые вещи
 		</text>
+		<text name="label_13" tool_tip="Задать стандартные разрешения, когда будут созданы настройки среды">
+			Настройки
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="OK" label_selected="OK" name="ok"/>
 	<button label="Отмена" label_selected="Отмена" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/ru/floater_pick_track.xml b/indra/newview/skins/default/xui/ru/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7588e1759c965826391b712052c596c25e3fa76e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="ВЫБРАТЬ: РЕЖИМ РЕДАКТИРОВАНИЯ">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Выбрать источник неба:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Небо4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Небо3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Небо2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Земля" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Отмена" label_selected="Отмена" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/ru/floater_preferences_graphics_advanced.xml
index fc6b6a173ea6b0018543ce985ff2e9a5b195623f..84e1ff15a01986ca418f0aa14b4fe8753100ee54 100644
--- a/indra/newview/skins/default/xui/ru/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/ru/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Прозрачность воды" name="TransparentWater"/>
 	<check_box initial_value="true" label="Рельефность и сияние" name="BumpShiny"/>
 	<check_box initial_value="true" label="Локальный свет" name="LocalLights"/>
-	<check_box initial_value="true" label="Базовые шейдеры" name="BasicShaders" tool_tip="Отключение этого параметра может предотвратить зависание некоторых видеокарт"/>
 	<slider label="Ландшафт:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Низкая
diff --git a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml
index c9cb87282a032e856f132543a3bef76b28fbadba..46d2a37503f399e58352f8b0ef6a5be4437fc8f2 100644
--- a/indra/newview/skins/default/xui/ru/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/ru/floater_preview_texture.xml
@@ -10,12 +10,12 @@
 		Описание:
 	</text>
 	<text name="dimensions">
-		[WIDTH]x[HEIGHT] пикселей
+		[WIDTH]пикселей x [HEIGHT]пикселей
 	</text>
 	<text name="aspect_ratio">
-		Соотношение сторон
+		Просмотр изображения с соотношением сторон
 	</text>
-	<combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с другим соотношением сторон">
+	<combo_box name="combo_aspect_ratio" tool_tip="Просмотр изображения с фиксированным соотношением сторон">
 		<combo_item name="Unconstrained">
 			Без ограничения
 		</combo_item>
@@ -42,6 +42,6 @@
 		</combo_item>
 	</combo_box>
 	<button label="OK" name="Keep"/>
-	<button label="Удалить" name="Discard"/>
+	<button label="Отменить" name="Discard"/>
 	<button label="Сохранить как" name="save_tex_btn"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_settings_picker.xml b/indra/newview/skins/default/xui/ru/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..84f0e303fc4b3fcf9f12bffc0186b360bef34ea0
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="ВЫБРАТЬ: НАСТРОЙКИ">
+	<floater.string name="pick title">
+		Выбрать:
+	</floater.string>
+	<floater.string name="pick_track">
+		ВЫБРАТЬ РЕЖИМ РЕДАКТИРОВАНИЯ
+	</floater.string>
+	<floater.string name="pick_settings">
+		ВЫБРАТЬ НАСТРОЙКИ
+	</floater.string>
+	<floater.string name="track_water">
+		Вода
+	</floater.string>
+	<floater.string name="track_ground">
+		Земля
+	</floater.string>
+	<floater.string name="track_sky">
+		Небо[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Фильтровать текстуры" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="OK" label_selected="OK" name="btn_select"/>
+			<button label="Отмена" label_selected="Отмена" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
index c9e117362f9226b2b219a142a4fc1986310483b4..c56657b86bc109c0130b9e55151f1ea8fee0e091 100644
--- a/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/ru/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Инвентарь" name="inventory" value="0"/>
 		<radio_item label="Локально" name="local" value="1"/>
+		<radio_item label="Зафиксировать" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Размер: [DIMENSIONS]
@@ -19,7 +20,6 @@
 	<button label="По умолчанию" label_selected="По умолчанию" name="Default"/>
 	<button label="Очистить" label_selected="Очистить" name="Blank"/>
 	<button label="Нет" label_selected="Нет" name="None"/>
-	<check_box initial_value="true" label="Применить сейчас" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Просмотр отключен"/>
 	<filter_editor label="Фильтровать текстуры" name="inventory search editor"/>
 	<check_box initial_value="false" label="Показывать папки" name="show_folders_check"/>
@@ -30,6 +30,22 @@
 		<column label="Имя" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Выбрать фиксированную текстуру">
+		<combo_box.item label="Никакой" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Скрыть регион базовой сетки" name="hide_base_mesh_region"/>
 	<button label="ОК" label_selected="ОК" name="Select"/>
 	<button label="Отмена" label_selected="Отмена" name="Cancel"/>
+	<check_box initial_value="true" label="Применить сейчас" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/ru/menu_inventory.xml b/indra/newview/skins/default/xui/ru/menu_inventory.xml
index 3404ae29a3803ff33c95b54d9e0f1e84590d3337..05cccebafc79ad172b0c0511fbaba82744945824 100644
--- a/indra/newview/skins/default/xui/ru/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/ru/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="Активировать" name="Marketplace Activate"/>
 	<menu_item_call label="Деактивировать" name="Marketplace Deactivate"/>
 	<menu_item_call label="Поделиться" name="Share"/>
-	<menu_item_call label="Купить" name="Task Buy"/>
 	<menu_item_call label="Открыть" name="Task Open"/>
 	<menu_item_call label="Воспроизвести" name="Task Play"/>
 	<menu_item_call label="Свойства" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Новые трусы" name="New Underpants"/>
 		<menu_item_call label="Новая альфа-маска" name="New Alpha Mask"/>
 		<menu_item_call label="Новое тату" name="New Tattoo"/>
+		<menu_item_call label="Новые универсальные" name="New Universal"/>
 		<menu_item_call label="Новая физика" name="New Physics"/>
 	</menu>
 	<menu label="Новые части тела" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Новые волосы" name="New Hair"/>
 		<menu_item_call label="Новые глаза" name="New Eyes"/>
 	</menu>
+	<menu label="Новые настройки" name="New Settings">
+		<menu_item_call label="Новое небо" name="New Sky"/>
+		<menu_item_call label="Новая вода" name="New Water"/>
+		<menu_item_call label="Новый суточный цикл" name="New Day Cycle"/>
+	</menu>
 	<menu label="Использовать по умолчанию для" name="upload_def">
 		<menu_item_call label="Переданные изображения" name="Image uploads"/>
 		<menu_item_call label="Переданные звуки" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Изменить" name="Wearable Edit"/>
 	<menu_item_call label="Добавить" name="Wearable Add"/>
 	<menu_item_call label="Снять" name="Take Off"/>
+	<menu_item_call label="Применить только к себе" name="Settings Apply Local"/>
+	<menu_item_call label="Применить к участку" name="Settings Apply Parcel"/>
 	<menu_item_call label="Копировать в списки товаров торгового центра" name="Marketplace Copy"/>
 	<menu_item_call label="Переместить в списки товаров торгового центра" name="Marketplace Move"/>
 	<menu_item_call label="- нет действий -" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_inventory_add.xml b/indra/newview/skins/default/xui/ru/menu_inventory_add.xml
index 9a240c653e60bee7e77a033bc9ec7dcba5b61d38..94ec61af90d987644bcfa2dfb3b4cec35fc51180 100644
--- a/indra/newview/skins/default/xui/ru/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/ru/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Звук (L$[COST])..." name="Upload Sound"/>
 		<menu_item_call label="Анимация (L$[COST])..." name="Upload Animation"/>
 		<menu_item_call label="Модель..." name="Upload Model"/>
-		<menu_item_call label="Мастер моделирования..." name="Upload Model Wizard"/>
 		<menu_item_call label="Все сразу (L$[COST] за файл)..." name="Bulk Upload"/>
-		<menu_item_call label="Установить разрешения на передачу по умолчанию" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Новая папка" name="New Folder"/>
 	<menu_item_call label="Новый скрипт" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Новые трусы" name="New Underpants"/>
 		<menu_item_call label="Новая альфа-маска" name="New Alpha"/>
 		<menu_item_call label="Новое тату" name="New Tattoo"/>
+		<menu_item_call label="Новые универсальные" name="New Universal"/>
 		<menu_item_call label="Новая физика" name="New Physics"/>
 	</menu>
 	<menu label="Новые части тела" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Новые волосы" name="New Hair"/>
 		<menu_item_call label="Новые глаза" name="New Eyes"/>
 	</menu>
+	<menu label="Новые настройки" name="New Settings">
+		<menu_item_call label="Новое небо" name="New Sky"/>
+		<menu_item_call label="Новая вода" name="New Water"/>
+		<menu_item_call label="Новый суточный цикл" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_outfit_gear.xml b/indra/newview/skins/default/xui/ru/menu_outfit_gear.xml
index 24d780ba1c625422d1bea682bd253d5e0e05afeb..1d883220e81670ef13ded7e90e3157b042e35c15 100644
--- a/indra/newview/skins/default/xui/ru/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/ru/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Новая альфа-маска" name="New Alpha"/>
 		<menu_item_call label="Новая физика" name="New Physics"/>
 		<menu_item_call label="Новое тату" name="New Tattoo"/>
+		<menu_item_call label="Новые универсальные" name="New Universal"/>
 	</menu>
 	<menu label="Новые части тела" name="New Body Parts">
 		<menu_item_call label="Новая фигура" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/ru/menu_save_settings.xml b/indra/newview/skins/default/xui/ru/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a9c796cf6757c2a0f625f37c96f391f6578479b
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Сохранить" name="save_settings"/>
+	<menu_item_check label="Сохранить как" name="save_as_new_settings"/>
+	<menu_item_check label="Подтвердить" name="commit_changes"/>
+	<menu_item_check label="Применить только к себе" name="apply_local"/>
+	<menu_item_check label="Применить к участку" name="apply_parcel"/>
+	<menu_item_check label="Применить к региону" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_settings_add.xml b/indra/newview/skins/default/xui/ru/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a3ef9764242f34dadfcb2396a45925e5aff4dc96
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Новое небо" name="New Sky"/>
+	<menu_item_call label="Новая вода" name="New Water"/>
+	<menu_item_call label="Новый суточный цикл" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_settings_gear.xml b/indra/newview/skins/default/xui/ru/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d17424b85d7e044a5a7aeaf7cfd4b6893aa39ce
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Редактировать" name="edit_settings"/>
+	<menu_item_call label="Применить только к себе" name="Settings Apply Local"/>
+	<menu_item_call label="Применить к участку" name="Settings Apply Parcel"/>
+	<menu_item_call label="Применить к региону" name="Settings Apply Region"/>
+	<menu_item_call label="Копировать" name="copy_settings"/>
+	<menu_item_call label="Вставить" name="paste_settings"/>
+	<menu_item_call label="Копировать UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml
index 876972ba2444e26592a48aacdf09a1c7ee6f7a52..8361464f4c1c9f1918c776c3f76077ee3fb53fd7 100644
--- a/indra/newview/skins/default/xui/ru/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml
@@ -77,30 +77,15 @@
 			<menu_item_check label="Свойства участка" name="Parcel Properties"/>
 			<menu_item_check label="Меню «Дополнительно»" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Солнце" name="Sun">
+		<menu label="Окружающая среда" name="Environment">
 			<menu_item_check label="Восход" name="Sunrise"/>
 			<menu_item_check label="Полдень" name="Noon"/>
 			<menu_item_check label="Закат" name="Sunset"/>
 			<menu_item_check label="Полночь" name="Midnight"/>
-			<menu_item_check label="Использовать настройки региона" name="Use Region Settings"/>
-		</menu>
-		<menu label="Редактор среды" name="Environment Editor">
-			<menu_item_call label="Настройки среды..." name="Environment Settings"/>
-			<menu label="Настройки воды" name="Water Presets">
-				<menu_item_call label="Новая настройка..." name="new_water_preset"/>
-				<menu_item_call label="Изменить настройку..." name="edit_water_preset"/>
-				<menu_item_call label="Удалить настройку..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Настройки неба" name="Sky Presets">
-				<menu_item_call label="Новая настройка..." name="new_sky_preset"/>
-				<menu_item_call label="Изменить настройку..." name="edit_sky_preset"/>
-				<menu_item_call label="Удалить настройку..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Суточные настройки" name="Day Presets">
-				<menu_item_call label="Новая настройка..." name="new_day_preset"/>
-				<menu_item_call label="Изменить настройку..." name="edit_day_preset"/>
-				<menu_item_call label="Удалить настройку..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Использование окружающей среды" name="Use Shared Environment"/>
+			<menu_item_call label="Моя среда…" name="my_environs"/>
+			<menu_item_call label="Личное освещение..." name="adjustment_tool"/>
+			<menu_item_check label="Приостановить движение облаков" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Строительство" name="BuildTools">
@@ -343,6 +328,9 @@
 			<menu_item_check label="Автоматические альфа-маски (не отложенные)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Текстуры анимаций" name="Animation Textures"/>
 			<menu_item_check label="Отключить текстуры" name="Disable Textures"/>
+			<menu_item_check label="Отключить окружающую среду" name="Disable Ambient"/>
+			<menu_item_check label="Отключить солнечный свет" name="Disable Sunlight"/>
+			<menu_item_check label="Отключить локальный свет" name="Disable Local Lights"/>
 			<menu_item_check label="Текстуры в полном разрешении" name="Rull Res Textures"/>
 			<menu_item_check label="Визуализация присоединенных источников света" name="Render Attached Lights"/>
 			<menu_item_check label="Визуализация присоединенных частиц" name="Render Attached Particles"/>
@@ -480,6 +468,7 @@
 			<menu_item_call label="Юбка" name="Skirt"/>
 			<menu_item_call label="Альфа" name="Alpha"/>
 			<menu_item_call label="Тату" name="Tattoo"/>
+			<menu_item_call label="Универсальные" name="Universal"/>
 			<menu_item_call label="Физика" name="Physics"/>
 			<menu_item_call label="Вся одежда" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml
index 1e4f9e9abbb35c997a359ac813dfaa809e03dc81..517c4db278206e561ba122ff3cebdaacb10476f8 100644
--- a/indra/newview/skins/default/xui/ru/notifications.xml
+++ b/indra/newview/skins/default/xui/ru/notifications.xml
@@ -1959,6 +1959,11 @@
 		При снятии этой опции вы можете удалить ограничения, которые владельцы участка добавили для предотвращения провокационных сообщений, сохранения конфиденциальности и защиты несовершеннолетных жителей от материала для взрослых. При необходимости обсудите со своими владельцами участков.
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		При снятии этой опции вы можете удалить пользовательскую среду, которую владельцы участка добавили для своих участков. При необходимости обсудите со своими владельцами участков. 
+Вы хотите продолжить?
+		<usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		Вы пытаетесь посетить регион, контент в котором не соответствует вашим настройкам.  Попробуйте изменить настройки в меню «Я &gt; Настройки &gt; Общие».
 		<usetemplate name="okbutton" yestext="OK"/>
@@ -2438,7 +2443,15 @@
 		Этот файл суточного цикла ссылается на отсутствующий файл неба: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		Не удалось применить настройки к региону.  Попробуйте покинуть регион, а затем вернуться в него.  Причина неполадки: [FAIL_REASON]
+		К сожалению настройки не применимы к этому региону. Причина: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Местная текстура используется в режиме редактирования [TRACK], № фрейма [FRAMENO] ([FRAMENO]%) на поле [FIELD]. 
+Настройки невозможно сохранить с использованием местных текстур.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Местная текстура используется на поле [FIELD]. 
+Настройки невозможно сохранить с использованием местных текстур.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Невозможно удалить последний ключ в этом суточном цикле: пустой суточный цикл не разрешен.  Следует изменить последний оставшийся ключ, а не удалять его и создавать новый.
@@ -4389,4 +4402,76 @@
 		[REASON]
 		<usetemplate name="okbutton" yestext="OK"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		Не удалось загрузить настройки для [NAME] из базы данных.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Невозможно применить эти настройки для этой среды.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Невозможно применить эти настройки для этой среды.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Этот регион не поддерживает настройки окружающей среды.
+	</notification>
+	<notification label="Сохранить костюм" name="SaveSettingAs">
+		Сохранить текущие настройки как:
+		<form name="form">
+			<input name="message">
+				[DESC] (новый)
+			</input>
+			<button name="OK" text="OK"/>
+			<button name="Cancel" text="Отмена"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Невозможно импортировать устаревшие установки [NAME] для эффекта Windlight из 
+[FILE]. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Невозможно установить настройки среды для этого участка. 
+Ввести или выбрать участок, который вы можете модифицировать.
+	</notification>
+	<notification name="SettingsUnsuported">
+		Настройки окружающей среды не поддерживаются в этом регионе. 
+Перейдите в регион с поддерживаемыми настройками и повторите действие.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		Вы потеряете изменения, внесенные в этот [TYPE] под именем &quot;[NAME]&quot;. 
+Вы уверены, что хотите продолжить?
+		<usetemplate ignoretext="Вы уверены, что хотите сделать настройки непереносимыми?" name="okcancelignore" notext="Нет" yestext="Да"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Вы собираетесь удалить все примененные настройки. 
+Вы уверены, что хотите продолжить?
+		<usetemplate name="okcancelbuttons" notext="Нет" yestext="Да"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Вы собираетесь удалить все примененные настройки для личного освещения. 
+Вы уверены, что хотите продолжить?
+		<usetemplate name="okcancelbuttons" notext="Нет" yestext="Да"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Вы собираетесь импортировать непереносимые настройки в этот суточный цикл. В случае дальнейшего изменения в этих параметрах они также станут непереносимыми. 
+
+Это изменение не подлежит отмене. 
+
+Вы уверены, что хотите продолжить?
+		<usetemplate ignoretext="Вы уверены, что хотите сделать настройки непереносимыми?" name="okcancelignore" notext="Нет" yestext="Да"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Вы не можете редактировать настройки непосредственно из библиотеки. 
+Скопировать в свой собственный инвентарь и повторить попытку.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Мы столкнулись с проблемой с этими настройками. Их невозможно сохранить или применить в данный момент.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Невозможно загрузить режим редактирования в [TRACK].
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Невозможно загрузить режим редактирования из [TRACK1] в [TRACK2].
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/ru/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/ru/panel_edit_tattoo.xml
index 874d5f8bc4a8ed0ee7d10e1a96281693293bff6d..ed5312b7239551211abf77e8a6468b8562d36ca5 100644
--- a/indra/newview/skins/default/xui/ru/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/ru/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Тату на голове" name="Head Tattoo" tool_tip="Щелкните картинку, чтобы выбрать ее"/>
-		<texture_picker label="Тату вверху" name="Upper Tattoo" tool_tip="Щелкните картинку, чтобы выбрать ее"/>
-		<texture_picker label="Тату внизу" name="Lower Tattoo" tool_tip="Щелкните картинку, чтобы выбрать ее"/>
-		<color_swatch label="Цвет/оттенок" name="Color/Tint" tool_tip="Щелкните для выбора цвета"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Тату на голове" name="Head Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на верхних частях тела" name="Upper Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на нижних частях тела" name="Lower Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<color_swatch label="Цвет/оттенок" name="Color/Tint" tool_tip="Щелкнуть для появления палитры цветов"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_edit_universal.xml b/indra/newview/skins/default/xui/ru/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..647d1aa9e7023d7b2ae731171660a252515c321e
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Тату на голове" name="Head Universal Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на верхних частях тела" name="Upper Universal Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на нижних частях тела" name="Lower Universal Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на юбке" name="Skirt Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату волос" name="Hair Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату глаз" name="Eyes Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на левой руке" name="Left Arm Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату на левой ноге" name="Left Leg Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату Aux1" name="Aux1 Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату Aux2" name="Aux2 Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<texture_picker label="Тату Aux3" name="Aux3 Tattoo" tool_tip="Щелкнуть для выбора изображения"/>
+			<color_swatch label="Цвет/оттенок" name="Color/Tint" tool_tip="Щелкнуть для появления палитры цветов"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_edit_wearable.xml b/indra/newview/skins/default/xui/ru/panel_edit_wearable.xml
index 79130a9c80e350ff5bd9b908ec36051d7fc6303d..cede43f859d7bd7c425c2ed3a9e54565fdf0c6b6 100644
--- a/indra/newview/skins/default/xui/ru/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/ru/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Изменение тату
 	</string>
+	<string name="edit_universal_title">
+		Редактирование универсальных
+	</string>
 	<string name="edit_physics_title">
 		Изменение физики
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Тату:
 	</string>
+	<string name="universal_desc_text">
+		Универсальные:
+	</string>
 	<string name="physics_desc_text">
 		Физика:
 	</string>
diff --git a/indra/newview/skins/default/xui/ru/panel_region_environment.xml b/indra/newview/skins/default/xui/ru/panel_region_environment.xml
index 8057176cfb5ee215ca2962596ec39d450e5bab0c..fcf1548ae5b86616a54e97bdaf0a1eaf61ad5439 100644
--- a/indra/newview/skins/default/xui/ru/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/ru/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Среда" name="panel_env_info">
-	<text name="water_settings_title">
-		Настройки воды и неба/суточного цикла определяют, каким посетители увидят ваш регион. Дополнительная информация
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Использовать настройки Second Life по умолчанию" name="use_sl_default_settings"/>
-		<radio_item label="Использовать следующие настройки" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Настройка воды
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Выбор настройки-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Небо/суточный цикл
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Зафиксированное небо" name="my_sky_settings"/>
-			<radio_item label="Суточный цикл" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Выбор настройки-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Выбор настройки-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Применить" name="apply_btn"/>
-	<button label="Отмена" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Использовать настройки по умолчанию
+	</string>
+	<string name="str_label_use_region">
+		Использовать настройки региона
+	</string>
+	<string name="str_altitude_desription">
+		Небо [INDEX]([ALTITUDE]м)
+	</string>
+	<string name="str_no_parcel">
+		Не выбрано ни одного участка. Настройки среды отключены.
+	</string>
+	<string name="str_cross_region">
+		Настройки окружающей среды недоступны в рамках этого региона.
+	</string>
+	<string name="str_legacy">
+		Настройки среды недоступны для этого региона.
+	</string>
+	<string name="str_disallowed">
+		Управляющий недвижимостью не разрешает менять среду вокруг участка в этом регионе.
+	</string>
+	<string name="str_too_small">
+		Чтобы поддерживать настройки окружающей среды участок должен быть не менее 128 кв. метров.
+	</string>
+	<string name="str_empty">
+		(пусто)
+	</string>
+	<string name="str_region_env">
+		(среда региона)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Использовать инвентарь" name="btn_select_inventory"/>
+							<button label="Настроить" name="btn_edit"/>
+							<check_box label="Владельцы участков могут менять окружающую среду" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Небо [INDEX]
+                            [ALTITUDE]м
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Неизвестно
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Перетащить настройки из инвентаря на это целевое поле, чтобы выбрать его в качестве неба на настоящий момент."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Небо [INDEX] 
+                            [ALTITUDE]м
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Неизвестно
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Перетащить настройки из инвентаря на это целевое поле, чтобы выбрать его в качестве неба на настоящий момент."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Небо [INDEX]
+                            [ALTITUDE]м
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Неизвестно
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Перетащить настройки из инвентаря на это целевое поле, чтобы выбрать его в качестве неба на настоящий момент."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Земля
+						</text>
+						<line_editor name="edt_invname_ground">
+							Неизвестно
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Перетащить настройки из инвентаря на это целевое поле для выбора его в качестве неба на уровне земли."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Вода
+						</text>
+						<line_editor name="edt_invname_water">
+							Неизвестно
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Перетащить настройки из инвентаря на это целевое поле для выбора его в качестве воды на настоящий момент."/>
+					</panel>
+					<button label="Сброс" name="btn_rst_altitudes" tool_tip="Сбросить настройки по умолчанию"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/ru/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9c4c502694d895caeccf30234c11caa5b55dfeec
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Атмосфера и освещение" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/ru/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/ru/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..46b4b101258c899a9e1f342599b40b0b2ba92652
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Облака" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/ru/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8886ceb539118dd845e3345443cb9e6c3c311309
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Плотность" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Экспоненциальный член Рэлея:" name="rayleigh_exponential"/>
+			<slider label="Экспоненциальная шкала Рэлея:" name="rayleigh_exponential_scale"/>
+			<slider label="Линейный член Рэлея:" name="rayleigh_linear"/>
+			<slider label="Постоянный член Рэлея:" name="rayleigh_constant"/>
+			<slider label="Максимальная высота Рэлея:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Экспоненциальный член Мие:" name="mie_exponential"/>
+			<slider label="Экспоненциальная шкала Мие:" name="mie_exponential_scale"/>
+			<slider label="Линейный член Мие:" name="mie_linear"/>
+			<slider label="Постоянный член Мие:" name="mie_constant"/>
+			<slider label="Анизо-фактор Мие:" name="mie_aniso_factor"/>
+			<slider label="Максимальная высота Мие:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Экспоненциальный член абсорбции:" name="absorption_exponential"/>
+			<slider label="Экспоненциальная шкала абсорбции:" name="absorption_exponential_scale"/>
+			<slider label="Линейный член абсорбции:" name="absorption_linear"/>
+			<slider label="Постоянный член абсорбции:" name="absorption_constant"/>
+			<slider label="Максимальная высота абсорбции:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/ru/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a494bbbe0e84c0bf9750a5ef49fcff48ffb0b349
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Солнце и луна" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="Показать метку" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="Показать метку" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_settings_water.xml b/indra/newview/skins/default/xui/ru/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de8b15ac19473018424a4cb551c4e447ff9d203a
--- /dev/null
+++ b/indra/newview/skins/default/xui/ru/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Вода" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Угловая зависимость:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/ru/panel_tools_texture.xml b/indra/newview/skins/default/xui/ru/panel_tools_texture.xml
index 707578cd07418171ef6b3d3f8751bc30dd1603cf..5cd83c712fcbe1ed6c131eb1eb4bf66250888fce 100644
--- a/indra/newview/skins/default/xui/ru/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/ru/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Текстура" name="Texture">
-	<panel.string name="string repeats per meter">
-		Повторений на метр
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Повторений на грань
-	</panel.string>
 	<text name="color label">
 		Цвет
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Смещение по горизонтали" name="shinyOffsetU"/>
 	<spinner label="Смещение по вертикали" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Согласование" name="checkbox planar align" tool_tip="Согласование текстур на всех выбранных гранях по последней выбранной грани. Должно быть выбрано наложение по плоскостям."/>
+	<button label="Выровнять" label_selected="Выровнять текущие слои текстуры" name="button align textures" tool_tip="Выровнять текущие слои текстуры"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/ru/role_actions.xml b/indra/newview/skins/default/xui/ru/role_actions.xml
index 1d526b90e46537a94380f4b67a06f7e2a6ecf763..314f6b9cb534b0fcf11295d965de0eec7de1f8a8 100644
--- a/indra/newview/skins/default/xui/ru/role_actions.xml
+++ b/indra/newview/skins/default/xui/ru/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Изменение настроек музыки и медиа" longdescription="Измените настройки потоковой музыки и фильмов в окне «О земле» на вкладке «Медиа»." name="land change media" value="20"/>
 		<action description="Включение-отключение изменения ландшафта" longdescription="Включение-отключение изменения ландшафта. *ПРЕДУПРЕЖДЕНИЕ* Выбрав параметры «О земле» &gt; вкладка «Параметры» &gt; «Изменить ландшафт», любой пользователь может изменить форму земли, а также размещать или перемещать растения Linden. Прежде чем назначить эту способность, убедитесь в целесообразности этого. Изменить ландшафт можно в окне «О земле» на вкладке «Параметры»." name="land edit" value="21"/>
 		<action description="Включение-отключение различных настроек «О земле &gt; Параметры»" longdescription="В окне «О земле» на вкладке «Параметры» можно включить-отключить параметр «Безопасно (нет повреждений)», «Полет» и разрешить другим жителям изменять ландшафт, строительство, создавать закладки и запускать скрипты для земли группы." name="land options" value="22"/>
+		<action description="Изменить установки окружающей среды и суточного цикла." longdescription="Изменить установки окружающей среды и суточного цикла от «О земле» &gt; Вкладка окружающей среды." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="К этим способностям относится разрешение участникам обходить ограничения на участках группы." name="Parcel Powers">
 		<action description="Всегда разрешено изменение ландшафта" longdescription="Участники роли с этой способностью могут изменять ландшафт участка группы, даже если это отключено в окне «О земле» на вкладке «Параметры»." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/ru/strings.xml b/indra/newview/skins/default/xui/ru/strings.xml
index 9c01de2f1bbde269a4b23f7206ce9fc832095a32..edcf9d3e0061116158a99d1a156a02ffa4c46fe3 100644
--- a/indra/newview/skins/default/xui/ru/strings.xml
+++ b/indra/newview/skins/default/xui/ru/strings.xml
@@ -639,6 +639,15 @@ support@secondlife.com.
 	<string name="BUTTON_HELP">
 		Показать справку
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Элементы этого типа не могут быть занесены в 
+карточку для комментариев в этом регионе.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Только элементы с безусловным разрешением 
+‘следующего владельца’ можно внести 
+в карточки для комментариев.
+	</string>
 	<string name="Searching">
 		Поиск...
 	</string>
@@ -715,6 +724,18 @@ support@secondlife.com.
 		Ошибка при запросе на передачу. Для получения помощи в 
 решении этой проблемы пройдите по ссылке http://secondlife.com/support.
 	</string>
+	<string name="SettingValidationError">
+		Не удалось выполнить проверку для импорта настроек [NAME]
+	</string>
+	<string name="SettingImportFileError">
+		Не удалось открыть файл [FILE]
+	</string>
+	<string name="SettingParseFileError">
+		Не удалось открыть файл [FILE]
+	</string>
+	<string name="SettingTranslateError">
+		Не удалось применить устаревший эффект windlight \[NAME]
+	</string>
 	<string name="texture">
 		текстуру
 	</string>
@@ -790,6 +811,9 @@ support@secondlife.com.
 	<string name="symbolic folder link">
 		ссылку на папку
 	</string>
+	<string name="settings blob">
+		настройки
+	</string>
 	<string name="mesh">
 		сетка
 	</string>
@@ -1120,6 +1144,9 @@ support@secondlife.com.
 	<string name="ForceSitAvatar">
 		Заставьте аватар сесть
 	</string>
+	<string name="ChangeEnvSettings">
+		Изменить свои настройки окружающей среды
+	</string>
 	<string name="NotConnected">
 		Нет подключения
 	</string>
@@ -1271,6 +1298,9 @@ support@secondlife.com.
 	<string name="tattoo">
 		Тату
 	</string>
+	<string name="universal">
+		Универсальные
+	</string>
 	<string name="physics">
 		Физические данные
 	</string>
@@ -1313,6 +1343,9 @@ support@secondlife.com.
 	<string name="tattoo_not_worn">
 		Тату не надето
 	</string>
+	<string name="universal_not_worn">
+		Универсальный наряд не надет
+	</string>
 	<string name="physics_not_worn">
 		Физика не учитывается
 	</string>
@@ -1364,6 +1397,9 @@ support@secondlife.com.
 	<string name="create_new_tattoo">
 		Создать тату
 	</string>
+	<string name="create_new_universal">
+		Создать новые универсальные
+	</string>
 	<string name="create_new_physics">
 		Создать физику
 	</string>
@@ -2511,6 +2547,27 @@ support@secondlife.com.
 	<string name="RegionSettings">
 		Региональные настройки
 	</string>
+	<string name="NoEnvironmentSettings">
+		Этот регион не поддерживает настройки окружающей среды.
+	</string>
+	<string name="EnvironmentSun">
+		Солнце
+	</string>
+	<string name="EnvironmentMoon">
+		Луна
+	</string>
+	<string name="EnvironmentBloom">
+		Ореол
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Шум облака
+	</string>
+	<string name="EnvironmentNormalMap">
+		Карта Нормалей
+	</string>
+	<string name="EnvironmentTransparent">
+		Прозрачный
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Щелчки: телепорт [TELEPORT], карта [MAP], профиль [PROFILE]
 	</string>
@@ -4724,6 +4781,9 @@ support@secondlife.com.
 	<string name="New Tattoo">
 		Новое тату
 	</string>
+	<string name="New Universal">
+		Новые универсальные
+	</string>
 	<string name="New Physics">
 		Новая физика
 	</string>
@@ -4850,6 +4910,15 @@ support@secondlife.com.
 	<string name="Female - Wow">
 		Женщина – ух ты!
 	</string>
+	<string name="New Daycycle">
+		Новый суточный цикл
+	</string>
+	<string name="New Water">
+		Новая вода
+	</string>
+	<string name="New Sky">
+		Новое небо
+	</string>
 	<string name="/bow">
 		/поклониться
 	</string>
@@ -5390,6 +5459,12 @@ support@secondlife.com.
 	<string name="BeaconMedia">
 		Просмотр медийных меток (белые)
 	</string>
+	<string name="BeaconSun">
+		Просмотр метки направления солнца (оранжевый)
+	</string>
+	<string name="BeaconMoon">
+		Просмотр метки направления луны (багровый)
+	</string>
 	<string name="ParticleHiding">
 		Частицы скрыты
 	</string>
@@ -5417,6 +5492,12 @@ support@secondlife.com.
 	<string name="Command_Destinations_Label">
 		Пункты
 	</string>
+	<string name="Command_Environments_Label">
+		Моя окружающая среда
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5510,6 +5591,12 @@ support@secondlife.com.
 	<string name="Command_Destinations_Tooltip">
 		Интересные места
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Моя окружающая среда
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Опубликовать в Facebook
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Загрузить на Flickr
 	</string>
@@ -5705,6 +5792,12 @@ support@secondlife.com.
 	<string name="ExperiencePermission12">
 		автоматически принимать разрешения для приключения
 	</string>
+	<string name="ExperiencePermission16">
+		посадить аватара
+	</string>
+	<string name="ExperiencePermission17">
+		изменить свои настройки окружающей среды
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		выполнил неизвестную операцию: [Permission]
 	</string>
@@ -5729,6 +5822,12 @@ support@secondlife.com.
 	<string name="ExperiencePermissionShort12">
 		Разрешение
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Сесть
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Окружающая среда
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		Разговоры не записываются. Чтобы начать запись разговора, в меню «Настройки &gt; Чат» выберите «Сохранять: только журнал» или «Сохранять: журнал и записи».
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/floater_about_land.xml b/indra/newview/skins/default/xui/tr/floater_about_land.xml
index 1101e5055a95101328a65de736007ee51f879aa1..f9dbda03782ece5e6755ae2170abddac2760e95d 100644
--- a/indra/newview/skins/default/xui/tr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about_land.xml
@@ -474,5 +474,6 @@ Sadece büyük parseller aramada görünür.
 			</panel>
 		</panel>
 		<panel label="DENEYÄ°MLER" name="land_experiences_panel"/>
+		<panel label="ORTAM" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_adjust_environment.xml b/indra/newview/skins/default/xui/tr/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..763845c54d9e97434090d861d78abf41a6a03d7b
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="Kişisel Aydınlatma">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="Sıfırla" name="btn_reset" tool_tip="Kapat ve Ortak Ortama sıfırla"/>
+					<text name="cloud_map_label">
+						Bulut Görüntüsü:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						Güneş:
+					</text>
+					<check_box label="İşareti Göster" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="İşareti Göster" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_beacons.xml b/indra/newview/skins/default/xui/tr/floater_beacons.xml
index 08ebf36be51df518ea20a8531ddd2eb512dc2fc9..e5b598ee619dce0dc024e3c04cb3b1be22f65c08 100644
--- a/indra/newview/skins/default/xui/tr/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/tr/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="Ses kaynakları" name="sounds"/>
 		<check_box label="Parçacık kaynakları" name="particles"/>
 		<check_box label="Ortam kaynakları" name="moapbeacon"/>
+		<check_box label="Güneş" name="sun"/>
+		<check_box label="Ay" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_bulk_perms.xml b/indra/newview/skins/default/xui/tr/floater_bulk_perms.xml
index a7708b58827a2f0d348026f61b1b1ed311828ef2..4eee1b81a2fd0b94191f229c40ffb7449271a221 100644
--- a/indra/newview/skins/default/xui/tr/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/tr/floater_bulk_perms.xml
@@ -21,6 +21,7 @@
 	<icon name="icon_script" tool_tip="Komut Dosyaları"/>
 	<icon name="icon_sound" tool_tip="Sesler"/>
 	<icon name="icon_texture" tool_tip="Dokular"/>
+	<icon name="icon_setting" tool_tip="Ortam ayarları"/>
 	<button label="√ Tümü" name="check_all"/>
 	<button label="Temizle" label_selected="Hiçbiri" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/tr/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/tr/floater_delete_env_preset.xml
deleted file mode 100644
index 7634bea642bafe84132264a217a4a5fd32d9c97d..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/tr/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="ORTAM ÖN AYARINI SİL">
-	<string name="title_water">
-		Su Ön Ayarını Sil
-	</string>
-	<string name="title_sky">
-		Gökyüzü Ön Ayarını Sil
-	</string>
-	<string name="title_day_cycle">
-		Gün Döngüsünü Sil
-	</string>
-	<string name="label_water">
-		Ön Ayar:
-	</string>
-	<string name="label_sky">
-		Ön Ayar:
-	</string>
-	<string name="label_day_cycle">
-		Gün döngüsü:
-	</string>
-	<string name="msg_confirm_deletion">
-		Seçili ön ayarı silmek istediğinizden emin misiniz?
-	</string>
-	<string name="msg_sky_is_referenced">
-		Bazı gün döngüleri tarafından referans alınan bir ön ayar kaldırılamaz.
-	</string>
-	<string name="combo_label">
-		-Bir ön ayar seçin-
-	</string>
-	<text name="label">
-		Ön Ayar:
-	</text>
-	<button label="Sil" name="delete"/>
-	<button label="Ä°ptal Et" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/tr/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7ebbafa9bc306c0ed167b3f996827d75a99d446c
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="Gün Döngüsünü Düzenle">
+	<string name="title_new">
+		Yeni bir Gün Döngüsü Oluştur
+	</string>
+	<string name="title_edit">
+		Gün Döngüsünü Düzenle
+	</string>
+	<string name="hint_new">
+		Gün döngünüze ad verin, bunu oluşturmak için denetimleri ayarlayın ve &quot;Kaydet&quot; düğmesine tıklayın.
+	</string>
+	<string name="hint_edit">
+		Gün döngünüzü düzenlemek için, alttaki denetimleri ayarlayın ve &quot;Kaydet&quot; düğmesine tıklayın.
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		Gökyüzü [ALT]
+	</string>
+	<string name="sky_label">
+		Gökyüzü
+	</string>
+	<string name="water_label">
+		Su
+	</string>
+	<string name="commit_parcel">
+		Parsele Uygula
+	</string>
+	<string name="commit_region">
+		Bölgeye Uygula
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				Gün Döngüsü Adı:
+			</text>
+			<button label="İçeri Aktar" name="btn_import" tool_tip="Eski ayarları diskten içeri aktarın."/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="Gökyüzü 4" name="sky4_track"/>
+						<button label="Gökyüzü 3" name="sky3_track"/>
+						<button label="Gökyüzü 2" name="sky2_track"/>
+						<button label="Zemin Seviyesi" name="sky1_track"/>
+						<button label="Su" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="%0 [DSC]"/>
+						<text name="p1" value="%25 [DSC]"/>
+						<text name="p2" value="%50 [DSC]"/>
+						<text name="p3" value="%75 [DSC]"/>
+						<text name="p4" value="%100 [DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="%[PRCNT] [DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="Buradan Rota Kopyala:" name="copy_track"/>
+								<button label="Buradan Rota Yükle:" name="load_track"/>
+								<button label="Rotayı Temizle" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="Geri çekil"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="İleri çık"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="[FRAME] Ekle" name="add_frame"/>
+								<button label="[FRAME] Yükle" name="btn_load_frame"/>
+								<button label="[FRAME] Sil" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						Ayarları düzenlemek için yukarıdaki zaman çizelgesinden bir anahtar çerçeve seçin.
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="Su" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="Atmosfer ve Aydınlatma" name="atmosphere_panel"/>
+						<panel label="Bulutlar" name="clouds_panel"/>
+						<panel label="Güneş ve Ay" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="Kaydet" name="save_btn"/>
+			<button label="Ä°ptal Et" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/tr/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8a8757c86cd6d3933fdb9e43bd43436e20652112
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="Sabit Ortam">
+	<string name="edit_sky">
+		Gökyüzünü Düzenle:
+	</string>
+	<string name="edit_water">
+		Suyu Düzenle:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="Yükle" name="btn_load" tool_tip="Envanterden bir ayar yükle"/>
+			<button label="İçeri Aktar" name="btn_import" tool_tip="Eski ayarları diskten içeri aktarın."/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="Kaydet" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="İptal Et" name="btn_cancel" tool_tip="Son kaydedilen sürüme dön"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml
index 6c04b64275d4ed0c17b112818a4c143ba43aaec2..accb1ed71c097a1868b7cfd34e949025680cd695 100644
--- a/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/tr/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="Sesler" name="check_sound"/>
 	<check_box label="Dokular" name="check_texture"/>
 	<check_box label="Anlık Görüntüler" name="check_snapshot"/>
+	<check_box label="Ayarlar" name="check_settings"/>
 	<button label="Tümü" label_selected="Tümü" name="All"/>
 	<button label="Hiçbiri" label_selected="Hiçbiri" name="None"/>
 	<check_box label="Klasörleri her zaman göster" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_my_environments.xml b/indra/newview/skins/default/xui/tr/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b91f48c50040f414bd169522e96523f93b22d5f0
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="Yerler" name="my_environments" title="ORTAMLARIM">
+	<layout_stack>
+		<layout_panel label="Filtreler" name="filter_panel">
+			<check_box label="Günler" name="chk_days"/>
+			<check_box label="Gökler" name="chk_skies"/>
+			<check_box label="Su" name="chk_water"/>
+			<filter_editor label="Ortamları Filtrele" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="Ortamlar" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="Tüm Klasörleri Göster" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="Diğer seçenekler"/>
+				<menu_button name="btn_newsettings" tool_tip="Yeni ayar oluÅŸtur"/>
+				<button name="btn_del" tool_tip="Seçilen öğeyi kaldır"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_perms_default.xml b/indra/newview/skins/default/xui/tr/floater_perms_default.xml
index 9691b678f2470e60f8d852985b995f4f6a223d82..9263d4e1c697d90194231a8cf8e614ae3250013f 100644
--- a/indra/newview/skins/default/xui/tr/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/tr/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="Giysi ya da Vücut Parçaları oluşturulduğunda varsayılan izinleri ayarla">
 			Giyilebilir öğeler
 		</text>
+		<text name="label_13" tool_tip="Ortam ayarları oluşturulduğunda varsayılan izinleri ayarla">
+			Ayarlar
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="Tamam" label_selected="Tamam" name="ok"/>
 	<button label="Ä°ptal" label_selected="Ä°ptal" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_pick_track.xml b/indra/newview/skins/default/xui/tr/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..83cfa8b652e7b0fd659daa5ab03ce2d1fe2e55ad
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="SEÇİM: ROTA">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				Kaynak gökyüzünü seç
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="Gökyüzü 4 [ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="Gökyüzü 3 [ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="Gökyüzü 2 [ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="Zemin" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="Tamam" label_selected="Tamam" name="btn_select"/>
+			<button label="Ä°ptal Et" label_selected="Ä°ptal Et" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_picks.xml b/indra/newview/skins/default/xui/tr/floater_picks.xml
index 513a2e319ad3bb89d6e7ecc11f31aa91afb56873..5aee6ae09110fcb6934e1bdd609bc363cb6eb95c 100644
--- a/indra/newview/skins/default/xui/tr/floater_picks.xml
+++ b/indra/newview/skins/default/xui/tr/floater_picks.xml
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_picks" title="Seçmeler"/>
+<floater name="floater_picks" title="Seçimler"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/tr/floater_preferences_graphics_advanced.xml
index 01ada1354c5cf7cab3faa302ff12973914c820f8..c5ca9973367d04548272a08044b51b46e0cf960c 100644
--- a/indra/newview/skins/default/xui/tr/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/tr/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="Saydam Su" name="TransparentWater"/>
 	<check_box initial_value="true" label="Tümsek eşleme ve parlaklık" name="BumpShiny"/>
 	<check_box initial_value="true" label="Yerel Işıklar" name="LocalLights"/>
-	<check_box initial_value="true" label="Temel gölgeleyiciler" name="BasicShaders" tool_tip="Bu seçeneğin devre dışı bırakılması bazı grafik kartlarının sürücülerinin kilitlenmesini önleyebilir"/>
 	<slider label="Yüzey Ayrıntısı:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		Düşük
diff --git a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml
index 79e184130a2734f6ed4a1a0738ca2bafe3309318..8302c62070568fcf60da27d57a5d06ae38588fd1 100644
--- a/indra/newview/skins/default/xui/tr/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/tr/floater_preview_texture.xml
@@ -10,7 +10,7 @@
 		Açıklama:
 	</text>
 	<text name="dimensions">
-		[WIDTH]px x [HEIGHT]px
+		[WIDTH] pks x [HEIGHT] pks
 	</text>
 	<text name="aspect_ratio">
 		En boy oranını önizle
diff --git a/indra/newview/skins/default/xui/tr/floater_settings_picker.xml b/indra/newview/skins/default/xui/tr/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0ef3aad5eee86188aa24ff26038986b93fcacac6
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="SEÇİM: AYARLAR">
+	<floater.string name="pick title">
+		Seçim:
+	</floater.string>
+	<floater.string name="pick_track">
+		ROTA SEÇ
+	</floater.string>
+	<floater.string name="pick_settings">
+		AYARLARI SEÇ
+	</floater.string>
+	<floater.string name="track_water">
+		Su
+	</floater.string>
+	<floater.string name="track_ground">
+		Zemin
+	</floater.string>
+	<floater.string name="track_sky">
+		Gökyüzü [NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="Dokuları Filtrele" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="Tamam" label_selected="Tamam" name="btn_select"/>
+			<button label="Ä°ptal Et" label_selected="Ä°ptal Et" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
index 42483c09e189b8d1ca2fc18ca12e7df3c0f30b88..1a1670912728bc4a04be98721a8c9a00a65c0dfe 100644
--- a/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/tr/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="Envanter" name="inventory" value="0"/>
 		<radio_item label="Yerel" name="local" value="1"/>
+		<radio_item label="Kurut" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		Büyüklük: [DIMENSIONS]
@@ -19,7 +20,6 @@
 	<button label="Varsayılan" label_selected="Varsayılan" name="Default"/>
 	<button label="BoÅŸ" label_selected="BoÅŸ" name="Blank"/>
 	<button label="Hiçbiri" label_selected="Hiçbiri" name="None"/>
-	<check_box initial_value="true" label="Åžimdi uygula" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="Önizleme Devre Dışı"/>
 	<filter_editor label="Dokuları Filtrele" name="inventory search editor"/>
 	<check_box initial_value="false" label="Klasörleri göster" name="show_folders_check"/>
@@ -30,6 +30,22 @@
 		<column label="Ad" name="unit_name"/>
 		<column label="Kimlik" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="Kurutma dokusunu seçin">
+		<combo_box.item label="Yok" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="Temel Ağ Bölgesini Gizle" name="hide_base_mesh_region"/>
 	<button label="Tamam" label_selected="Tamam" name="Select"/>
 	<button label="Ä°ptal" label_selected="Ä°ptal" name="Cancel"/>
+	<check_box initial_value="true" label="Åžimdi uygula" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/tr/menu_inventory.xml b/indra/newview/skins/default/xui/tr/menu_inventory.xml
index 1e8dfc7d68a1adf43890da00149b0bcb8c807601..d5e4113febf98309926870d7f80dc2467f84000d 100644
--- a/indra/newview/skins/default/xui/tr/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/tr/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="EtkinleÅŸtir" name="Marketplace Activate"/>
 	<menu_item_call label="Devre Dışı Bırak" name="Marketplace Deactivate"/>
 	<menu_item_call label="PaylaÅŸ" name="Share"/>
-	<menu_item_call label="Satın Al" name="Task Buy"/>
 	<menu_item_call label="Aç" name="Task Open"/>
 	<menu_item_call label="Oyna" name="Task Play"/>
 	<menu_item_call label="Özellikler" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="Yeni Külot" name="New Underpants"/>
 		<menu_item_call label="Yeni Alfa Maskesi" name="New Alpha Mask"/>
 		<menu_item_call label="Yeni Dövme" name="New Tattoo"/>
+		<menu_item_call label="Yeni Evrensel" name="New Universal"/>
 		<menu_item_call label="Yeni Fizik" name="New Physics"/>
 	</menu>
 	<menu label="Yeni Vücut Bölümleri" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="Yeni Saç" name="New Hair"/>
 		<menu_item_call label="Yeni Gözler" name="New Eyes"/>
 	</menu>
+	<menu label="Yeni Ayarlar" name="New Settings">
+		<menu_item_call label="Yeni Gökyüzü" name="New Sky"/>
+		<menu_item_call label="Yeni Su" name="New Water"/>
+		<menu_item_call label="Yeni Gün Döngüsü" name="New Day Cycle"/>
+	</menu>
 	<menu label="Şunun için varsayılan olarak kullan" name="upload_def">
 		<menu_item_call label="Karşıya yüklenen görüntüler" name="Image uploads"/>
 		<menu_item_call label="Karşıya yüklenen sesler" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="Düzenle" name="Wearable Edit"/>
 	<menu_item_call label="Ekle" name="Wearable Add"/>
 	<menu_item_call label="Çıkar" name="Take Off"/>
+	<menu_item_call label="Sadece Kendime Uygula" name="Settings Apply Local"/>
+	<menu_item_call label="Parsele Uygula" name="Settings Apply Parcel"/>
 	<menu_item_call label="Pazaryeri İlanlarına Kopyala" name="Marketplace Copy"/>
 	<menu_item_call label="Pazaryeri İlanlarına Taşı" name="Marketplace Move"/>
 	<menu_item_call label="--seçenek yok--" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/tr/menu_inventory_add.xml b/indra/newview/skins/default/xui/tr/menu_inventory_add.xml
index db2a9a2c8c584d6ee9b25b7238c5fd75922eb2cf..118081e3a3d224af4dcb5be9535e88133c1ddacf 100644
--- a/indra/newview/skins/default/xui/tr/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/tr/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="Ses (L$[COST])..." name="Upload Sound"/>
 		<menu_item_call label="Animasyon (L$[COST])..." name="Upload Animation"/>
 		<menu_item_call label="Model..." name="Upload Model"/>
-		<menu_item_call label="Model Sihirbazı..." name="Upload Model Wizard"/>
 		<menu_item_call label="Toplu (dosya başına L$[COST])..." name="Bulk Upload"/>
-		<menu_item_call label="Varsayılan Karşıya Yükleme İzinlerini Ayarla" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="Yeni Klasör" name="New Folder"/>
 	<menu_item_call label="Yeni Komut Dosyası" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="Yeni Külot" name="New Underpants"/>
 		<menu_item_call label="Yeni Alfa" name="New Alpha"/>
 		<menu_item_call label="Yeni Dövme" name="New Tattoo"/>
+		<menu_item_call label="Yeni Evrensel" name="New Universal"/>
 		<menu_item_call label="Yeni Fizik" name="New Physics"/>
 	</menu>
 	<menu label="Yeni Vücut Bölümleri" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="Yeni Saç" name="New Hair"/>
 		<menu_item_call label="Yeni Gözler" name="New Eyes"/>
 	</menu>
+	<menu label="Yeni Ayarlar" name="New Settings">
+		<menu_item_call label="Yeni Gökyüzü" name="New Sky"/>
+		<menu_item_call label="Yeni Su" name="New Water"/>
+		<menu_item_call label="Yeni Gün Döngüsü" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_outfit_gear.xml b/indra/newview/skins/default/xui/tr/menu_outfit_gear.xml
index 1b73032a5d3b0f999d52cea805036e2ebe5ceab5..7590ee28de3ca79a310f5d87dffdb8407f1e5b61 100644
--- a/indra/newview/skins/default/xui/tr/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/tr/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="Yeni Alfa" name="New Alpha"/>
 		<menu_item_call label="Yeni Fizik" name="New Physics"/>
 		<menu_item_call label="Yeni Dövme" name="New Tattoo"/>
+		<menu_item_call label="Yeni Evrensel" name="New Universal"/>
 	</menu>
 	<menu label="Yeni Vücut Bölümleri" name="New Body Parts">
 		<menu_item_call label="Yeni Åžekil" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/tr/menu_save_settings.xml b/indra/newview/skins/default/xui/tr/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dad150a54bdfa93695185bad2679f063af858eff
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="Kaydet" name="save_settings"/>
+	<menu_item_check label="Farklı Kaydet" name="save_as_new_settings"/>
+	<menu_item_check label="Yürüt" name="commit_changes"/>
+	<menu_item_check label="Sadece Kendime Uygula" name="apply_local"/>
+	<menu_item_check label="Parsele Uygula" name="apply_parcel"/>
+	<menu_item_check label="Bölgeye Uygula" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_settings_add.xml b/indra/newview/skins/default/xui/tr/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0afd8a78931d9e9c86861fd760081b71553bd1e2
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="Yeni Gökyüzü" name="New Sky"/>
+	<menu_item_call label="Yeni Su" name="New Water"/>
+	<menu_item_call label="Yeni Gün Döngüsü" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_settings_gear.xml b/indra/newview/skins/default/xui/tr/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f0d04a9e68d12228230b390c639fc6422e1a6ebe
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="Düzenle" name="edit_settings"/>
+	<menu_item_call label="Sadece Kendime Uygula" name="Settings Apply Local"/>
+	<menu_item_call label="Parsele Uygula" name="Settings Apply Parcel"/>
+	<menu_item_call label="Bölgeye Uygula" name="Settings Apply Region"/>
+	<menu_item_call label="Kopyala" name="copy_settings"/>
+	<menu_item_call label="Yapıştır" name="paste_settings"/>
+	<menu_item_call label="UUID&apos;yi Kopyala" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml
index b83847a013e2e9a9484ce531da6fd7e516c499fb..1c977ba5cee54852577c10555d8556ba5761d46d 100644
--- a/indra/newview/skins/default/xui/tr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml
@@ -77,30 +77,15 @@
 			<menu_item_check label="Parsel Özellikleri" name="Parcel Properties"/>
 			<menu_item_check label="Gelişmiş Menü" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="Güneş" name="Sun">
+		<menu label="Ortam" name="Environment">
 			<menu_item_check label="Gün doğumu" name="Sunrise"/>
 			<menu_item_check label="Öğle" name="Noon"/>
 			<menu_item_check label="Gün batımı" name="Sunset"/>
 			<menu_item_check label="Gece yarısı" name="Midnight"/>
-			<menu_item_check label="Bölge Ayarlarını Kullan" name="Use Region Settings"/>
-		</menu>
-		<menu label="Ortam Düzenleyici" name="Environment Editor">
-			<menu_item_call label="Ortam Ayarları..." name="Environment Settings"/>
-			<menu label="Su Ön Ayarları" name="Water Presets">
-				<menu_item_call label="Yeni ön ayar..." name="new_water_preset"/>
-				<menu_item_call label="Ön ayarı düzenle..." name="edit_water_preset"/>
-				<menu_item_call label="Ön ayarı sil..." name="delete_water_preset"/>
-			</menu>
-			<menu label="Gökyüzü Ön Ayarları" name="Sky Presets">
-				<menu_item_call label="Yeni ön ayar..." name="new_sky_preset"/>
-				<menu_item_call label="Ön ayarı düzenle..." name="edit_sky_preset"/>
-				<menu_item_call label="Ön ayarı sil..." name="delete_sky_preset"/>
-			</menu>
-			<menu label="Gün Ön Ayarları" name="Day Presets">
-				<menu_item_call label="Yeni ön ayar..." name="new_day_preset"/>
-				<menu_item_call label="Ön ayarı düzenle..." name="edit_day_preset"/>
-				<menu_item_call label="Ön ayarı sil..." name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="Ortak Ortam Kullan" name="Use Shared Environment"/>
+			<menu_item_call label="Ortamlarım..." name="my_environs"/>
+			<menu_item_call label="Kişisel Aydınlatma..." name="adjustment_tool"/>
+			<menu_item_check label="Bulutları Duraklat" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="Ä°nÅŸa Et" name="BuildTools">
@@ -344,6 +329,9 @@
 			<menu_item_check label="Otomatik Alfa Maskeleri (ertelenmemiÅŸ)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="Animasyon Dokuları" name="Animation Textures"/>
 			<menu_item_check label="Dokuları Devre Dışı Bırak" name="Disable Textures"/>
+			<menu_item_check label="Ortamı Devre Dışı Bırak" name="Disable Ambient"/>
+			<menu_item_check label="Güneş Işığını Devre Dışı Bırak" name="Disable Sunlight"/>
+			<menu_item_check label="Yerel Işıkları Devre Dışı Bırak" name="Disable Local Lights"/>
 			<menu_item_check label="Tam Çöz. Dokular" name="Rull Res Textures"/>
 			<menu_item_check label="Eklenmiş Işıkları İşle" name="Render Attached Lights"/>
 			<menu_item_check label="Eklenmiş Parçacıkları İşle" name="Render Attached Particles"/>
@@ -481,6 +469,7 @@
 			<menu_item_call label="Etek" name="Skirt"/>
 			<menu_item_call label="Alfa" name="Alpha"/>
 			<menu_item_call label="Dövme" name="Tattoo"/>
+			<menu_item_call label="Evrensel" name="Universal"/>
 			<menu_item_call label="Fizik" name="Physics"/>
 			<menu_item_call label="Tüm Giysiler" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml
index 13867cf5b8e6774e8287bb9c3227febbf92d62b6..b7593322e32758dbef8c74cb1cbc5e78f9308180 100644
--- a/indra/newview/skins/default/xui/tr/notifications.xml
+++ b/indra/newview/skins/default/xui/tr/notifications.xml
@@ -1960,6 +1960,11 @@ Binlerce bölgeyi değiştirecek ve alan sunucusunu kesintiye uğratacaktır.
 		Bu seçeneğin onay işaretini kaldırmak, parsel sahiplerinin rahatsızlık veren oyuncuları bunu yapmasını engellemek, gizliliği sürdürmek ve yaşı tutmayan sakinleri yetişkin içeriklerden korumak için ekledikleri kısıtlamaları kaldırabilir. Lütfen gerekli olduğunda parsel sahiplerinizle tartışın.
 		<usetemplate name="okbutton" yestext="Tamam"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		Bu seçeneğin onay işaretinin kaldırılması, parsel sahiplerinin kendi parsellerine eklemiş oldukları tüm özel ortamları kaldırır. Lütfen gerektiğinde parsel sahiplerinizle görüşün. 
+Devam etmek istiyor musunuz?
+		<usetemplate name="okcancelbuttons" notext="Ä°ptal Et" yestext="Tamam"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		Ziyaret etmeye çalıştığınız bölge, mevcut tercihlerinizi aşan içeriğe sahip.  Ben &gt; Tercihler &gt; Genel sekmesini kullanarak tercihlerinizi değiştirebilirsiniz.
 		<usetemplate name="okbutton" yestext="Tamam"/>
@@ -2438,7 +2443,15 @@ Diğer kişilerin bu konuma kolayca erişmesini sağlamak için bu adrese bir we
 		Bu gün döngüsü dosyası kayıp bir gökyüzü dosyasına başvuruda bulunuyor: [SKY].
 	</notification>
 	<notification name="WLRegionApplyFail">
-		Üzgünüz, bu ayarlar bölgeye uygulanamadı.  Bölgeden ayrılmak ve sonra geri dönmek sorunu çözebilir.  Gösterilen neden şuydu: [FAIL_REASON]
+		Üzgünüz, ayarlar bölgeye uygulanamadı. Neden: [FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		Bir Yerel doku [FIELD] alanındaki [TRACK] rotasında, #[FRAMENO] ([FRAME]%) çerçevesinde kullanılıyor. 
+Ayarlar yerel dokular kullanılarak kaydedilemez.
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		Bir yerel doku [FIELD] alanında kullanılıyor. 
+Ayarlar yerel dokular kullanılarak kaydedilemez.
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		Bu gün döngüsündeki son anahtar silinemedi çünkü boş bir gün döngünüz olamaz.  Son kalan anahtarı silmek ve yenisini oluşturmaya kalkışmak yerine bunu değiştirmelisiniz.
@@ -4382,4 +4395,75 @@ Daha küçük bir arazi parçası seçmeyi deneyin.
 		[REASON]
 		<usetemplate name="okbutton" yestext="Tamam"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		[NAME] ile ilgili ayarlar veritabanından yüklenemedi.
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		Bu değişiklikler ortama uygulanamıyor.
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		Bu değişiklikler ortama uygulanamıyor.
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		Bu Bölge ortam ayarlarını desteklemiyor.
+	</notification>
+	<notification label="Dış Görünümü Kaydet" name="SaveSettingAs">
+		Geçerli ortam ayarlarını farklı kaydet:
+		<form name="form">
+			<input name="message">
+				[DESC] (yeni)
+			</input>
+			<button name="OK" text="Tamam"/>
+			<button name="Cancel" text="Ä°ptal Et"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		Eski Windlight ayarları [NAME], [FILE] kaynağından içeri aktarılamıyor. 
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		Bu parsele ait ortam ayarlanamıyor. 
+Lütfen değişiklik yapma hakkına sahip olduğunuz bir parsel girin veya seçin.
+	</notification>
+	<notification name="SettingsUnsuported">
+		Ayarlar bu bölgede desteklenmiyor. 
+Lütfen ayarların etkin olduğu bir bölgeye gidin ve eyleminizi yeniden deneyin.
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		&quot;[NAME]&quot; adlı bu [TYPE] öğesinde yaptığınız değişiklikleri kaybetmek üzeresiniz. 
+Devam etmek istediÄŸinizden emin misiniz?
+		<usetemplate ignoretext="Değişiklikleri kaybetmek istediğinizden emin misiniz?" name="okcancelignore" notext="Hayır" yestext="Evet"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		Uygulanan ayarlarınızın tümünü kaldırmak üzeresiniz. 
+Devam etmek istediÄŸinizden emin misiniz?
+		<usetemplate name="okcancelbuttons" notext="Hayır" yestext="Evet"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		Uygulanan Kişisel aydınlatma ayarlarınızın tümünü kaldırmak üzeresiniz. 
+Devam etmek istediÄŸinizden emin misiniz?
+		<usetemplate name="okcancelbuttons" notext="Hayır" yestext="Evet"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		Aktarılamayan ayarları bu gün döngüsüne aktarmak üzeresiniz. Bu işleme devam etmeniz düzenlemekte olduğunuz ayarların da aktarılamaz olmasına neden olacaktır. 
+
+Bu değişiklik geri alınamaz. 
+
+Devam etmek istediÄŸinizden emin misiniz?
+		<usetemplate ignoretext="Ayarları aktarılamaz hale getirmek istediğinizden emin misiniz?" name="okcancelignore" notext="Hayır" yestext="Evet"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		Ayarları doğrudan kütüphaneden düzenleyemezsiniz. 
+Lütfen kendi envanterinize kopyalayın ve yeniden deneyin.
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		Bu ayarlarla ilgili bir sorunla karşılaştık. Bu ayarlar şu anda kaydedilemiyor veya uygulanamıyor.
+	</notification>
+	<notification name="TrackLoadFailed">
+		Rota [TRACK] hedefine yüklenemiyor.
+	</notification>
+	<notification name="TrackLoadMismatch">
+		Rota [TRACK1] kaynağından [TRACK2] hedefine yüklenemiyor.
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml
index 7584b754f1328a7f9662f5719232a08e5d70958b..fc444f21f6711b281e438fff36d9b43199ec3f23 100644
--- a/indra/newview/skins/default/xui/tr/panel_edit_classified.xml
+++ b/indra/newview/skins/default/xui/tr/panel_edit_classified.xml
@@ -47,7 +47,7 @@
 				<button label="[LABEL]" name="save_changes_btn"/>
 			</layout_panel>
 			<layout_panel name="show_on_map_btn_lp">
-				<button label="Ä°ptal" name="cancel_btn"/>
+				<button label="Ä°ptal Et" name="cancel_btn"/>
 			</layout_panel>
 		</layout_stack>
 	</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/tr/panel_edit_tattoo.xml
index 7f5590a485a25f4113b780e32c4d42c7df6f8b25..fb97f1e1ced5d6801d0908d2e0928790a0d75f02 100644
--- a/indra/newview/skins/default/xui/tr/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/tr/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="Baş Dövmesi" name="Head Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
-		<texture_picker label="Üst Gövde Dövmesi" name="Upper Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
-		<texture_picker label="Alt Gövde Dövmesi" name="Lower Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
-		<color_swatch label="Renk/Ton" name="Color/Tint" tool_tip="Renk seçiciyi açmak için tıklayın"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="Baş Dövmesi" name="Head Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Üst Gövde Dövmesi" name="Upper Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Alt Gövde Dövmesi" name="Lower Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<color_swatch label="Renk/Ton" name="Color/Tint" tool_tip="Renk seçiciyi açmak için tıklayın"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_edit_universal.xml b/indra/newview/skins/default/xui/tr/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ef10307d119292eb1a7ea667c19911071524a343
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="Baş Dövmesi" name="Head Universal Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Üst Gövde Dövmesi" name="Upper Universal Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Alt Gövde Dövmesi" name="Lower Universal Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Etek Dövmesi" name="Skirt Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Saç Dövmesi" name="Hair Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Göz Dövmesi" name="Eyes Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Sol Kol Dövmesi" name="Left Arm Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Sol Bacak Dövmesi" name="Left Leg Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Yedek 1 Dövme" name="Aux1 Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Yedek 2 Dövme" name="Aux2 Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<texture_picker label="Yedek 3 Dövme" name="Aux3 Tattoo" tool_tip="Bir resim seçmek için tıklayın"/>
+			<color_swatch label="Renk/Ton" name="Color/Tint" tool_tip="Renk seçiciyi açmak için tıklayın"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_edit_wearable.xml b/indra/newview/skins/default/xui/tr/panel_edit_wearable.xml
index 7a4a09aaedc623ea68b77fb00e760029bf0a5ae2..7880de8e7db152ba534595591e09d96bbd09bf42 100644
--- a/indra/newview/skins/default/xui/tr/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/tr/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		Dövme Düzenleniyor
 	</string>
+	<string name="edit_universal_title">
+		Evrensel Düzenleniyor
+	</string>
 	<string name="edit_physics_title">
 		Fizik Düzenleniyor
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		Dövme:
 	</string>
+	<string name="universal_desc_text">
+		Evrensel:
+	</string>
 	<string name="physics_desc_text">
 		Fizik:
 	</string>
diff --git a/indra/newview/skins/default/xui/tr/panel_me.xml b/indra/newview/skins/default/xui/tr/panel_me.xml
index 4b911c9ce6acf469a473c6a3c1062c72cf35be10..d9e79d171cd8bed00d9f0162656d7f3b2aecf3e9 100644
--- a/indra/newview/skins/default/xui/tr/panel_me.xml
+++ b/indra/newview/skins/default/xui/tr/panel_me.xml
@@ -1,4 +1,4 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Profilim" name="panel_me">
-	<panel label="SEÇMELERİM" name="panel_picks"/>
+	<panel label="SEÇTİKLERİM" name="panel_picks"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_region_environment.xml b/indra/newview/skins/default/xui/tr/panel_region_environment.xml
index b5f505f25fd197c8180f9440d30dae54d933143f..d375203cf623a0975bd9b346ff2c07062081409a 100644
--- a/indra/newview/skins/default/xui/tr/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/tr/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Ortam" name="panel_env_info">
-	<text name="water_settings_title">
-		Bölgenize gelen tüm ziyaretçilerin görmesini istediğiniz Su ve Gökyüzü/Gündüz Döngüsü Ayarlarını seçin. Ek bilgi
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="Second Life varsayılanını kullan" name="use_sl_default_settings"/>
-		<radio_item label="Aşağıdaki ayarları kullan" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			Su Ayarı
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-Bir ön ayar seçin-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			Gökyüzü / Gün Döngüsü
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="Sabit gökyüzü" name="my_sky_settings"/>
-			<radio_item label="Gün döngüsü" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-Bir ön ayar seçin-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-Bir ön ayar seçin-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="Uygula" name="apply_btn"/>
-	<button label="Ä°ptal Et" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		Varsayılan Ayarları Kullan
+	</string>
+	<string name="str_label_use_region">
+		Bölge Ayarlarını Kullan
+	</string>
+	<string name="str_altitude_desription">
+		Gökyüzü [INDEX]([ALTITUDE] m)
+	</string>
+	<string name="str_no_parcel">
+		Parsel seçilmedi. Ortam ayarları devre dışı.
+	</string>
+	<string name="str_cross_region">
+		Ortam ayarları bölge sınırları dahilinde kullanılamıyor.
+	</string>
+	<string name="str_legacy">
+		Ortam ayarları bu bölgede kullanılamıyor.
+	</string>
+	<string name="str_disallowed">
+		Gayrimenkul yöneticisi bu bölgede parsel ortamlarını değiştirmeye izin vermiyor.
+	</string>
+	<string name="str_too_small">
+		Parselin bir ortamı desteklemesi için en az 128 metrekare olması gerekir.
+	</string>
+	<string name="str_empty">
+		(boÅŸ)
+	</string>
+	<string name="str_region_env">
+		(bölge ortamı)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="Envanteri Kullan" name="btn_select_inventory"/>
+							<button label="Özelleştir" name="btn_edit"/>
+							<check_box label="Parsel Sahipleri Ortamı Geçersiz Kılabilir" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] (% [PRC])
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							Gökyüzü [INDEX]
+                            [ALTITUDE] m
+						</text>
+						<line_editor name="edt_invname_alt1">
+							Bilinmiyor
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="Geçerli gökyüzü olarak seçmek için Envanterden bir ayarı bu hedef kutuya sürükleyin."/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							Gökyüzü [INDEX]
+                            [ALTITUDE] m
+						</text>
+						<line_editor name="edt_invname_alt2">
+							Bilinmiyor
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="Geçerli gökyüzü olarak seçmek için Envanterden bir ayarı bu hedef kutuya sürükleyin."/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							Gökyüzü [INDEX]
+                            [ALTITUDE] m
+						</text>
+						<line_editor name="edt_invname_alt3">
+							Bilinmiyor
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="Geçerli gökyüzü olarak seçmek için Envanterden bir ayarı bu hedef kutuya sürükleyin."/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							Zemin
+						</text>
+						<line_editor name="edt_invname_ground">
+							Bilinmiyor
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="Zemin seviyesinde gökyüzü olarak seçmek için Envanterden bir ayarı bu hedef kutuya sürükleyin."/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							Su
+						</text>
+						<line_editor name="edt_invname_water">
+							Bilinmiyor
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="Geçerli su olarak seçmek için Envanterden bir ayarı bu hedef kutuya sürükleyin."/>
+					</panel>
+					<button label="Sıfırla" name="btn_rst_altitudes" tool_tip="Varsayılan irtifalara sıfırla"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/tr/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9bc23a550761f138bcdf0f51048593b09a7268ef
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Atmosfer ve Aydınlatma" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/tr/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/tr/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5dd31546cd279f9cbf52bded4e1e3f25619d12bc
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Bulutlar" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/tr/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d2aa3092165b4c703359964fb59ce93248c168d
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="YoÄŸunluk" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Rayleigh Ãœstel Terim:" name="rayleigh_exponential"/>
+			<slider label="Rayleigh Ãœstel Skala:" name="rayleigh_exponential_scale"/>
+			<slider label="Rayleigh Lineer Terim:" name="rayleigh_linear"/>
+			<slider label="Rayleigh Sabit Terim:" name="rayleigh_constant"/>
+			<slider label="Rayleigh Maks. Ä°rtifa:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Mie Ãœstel Terim:" name="mie_exponential"/>
+			<slider label="Mie Ãœstel Skala:" name="mie_exponential_scale"/>
+			<slider label="Mie Lineer Terim:" name="mie_linear"/>
+			<slider label="Mie Sabit Terim:" name="mie_constant"/>
+			<slider label="Mie Anizotropi Faktörü:" name="mie_aniso_factor"/>
+			<slider label="Mie Maks. Ä°rtifa:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Absorpsiyon Ãœstel Terim:" name="absorption_exponential"/>
+			<slider label="Absorpsiyon Ãœstel Skala:" name="absorption_exponential_scale"/>
+			<slider label="Absorpsiyon Lineer Terim:" name="absorption_linear"/>
+			<slider label="Absorpsiyon Sabit Terim:" name="absorption_constant"/>
+			<slider label="Absorpsiyon Maks. Ä°rtifa:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/tr/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44fccb594d79388b9ffdd40125e3c223b9fd7c22
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Güneş ve Ay" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="İşareti Göster" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="İşareti Göster" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_settings_water.xml b/indra/newview/skins/default/xui/tr/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9537a2b4942d08cd741bdaedec6035dcd511cec7
--- /dev/null
+++ b/indra/newview/skins/default/xui/tr/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Su" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				Fresnel Dengeleme:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/tr/panel_tools_texture.xml b/indra/newview/skins/default/xui/tr/panel_tools_texture.xml
index 1324e2cc36ca44b200378d28a4a3fea61cda13c4..baf53a7af421212bb7028beef40527983e25d0e3 100644
--- a/indra/newview/skins/default/xui/tr/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/tr/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="Doku" name="Texture">
-	<panel.string name="string repeats per meter">
-		Metrede Kaç Kez Tekrarlandığı
-	</panel.string>
-	<panel.string name="string repeats per face">
-		Bir Yüzde Kaç Kez Tekrarlandığı
-	</panel.string>
 	<text name="color label">
 		Renk
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="Yatay ofset" name="shinyOffsetU"/>
 	<spinner label="Dikey ofset" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="Planar yüzleri hizala" name="checkbox planar align" tool_tip="Tüm seçili yüzeylerdeki dokuları son seçili yüzdekiyle hizalar. Planar doku eşleştirmesi gerektirir."/>
+	<button label="Hizala" label_selected="Geçerli doku katmanlarına hizala" name="button align textures" tool_tip="Geçerli doku katmanlarına hizala"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/tr/role_actions.xml b/indra/newview/skins/default/xui/tr/role_actions.xml
index 5e830bddd56f71d90a81b0898a6a5c04e9b765e9..3ac4a7b19fc1d931dcd0e8fc145e9b006f7508d1 100644
--- a/indra/newview/skins/default/xui/tr/role_actions.xml
+++ b/indra/newview/skins/default/xui/tr/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="Müziği &amp; ortam ayarlarını değiştir" longdescription="Akış müziğini ve film ayarlarını Arazi Hakkında &gt; Ortam sekmesinden değiştirin." name="land change media" value="20"/>
 		<action description="&apos;Yüzeyi Düzenle&apos; seçeneğini Aç/Kapa" longdescription="&apos;Yüzeyi Düzenle&apos; seçeneğini açın/kapatın. *UYARI* Arazi Hakkında &gt; Seçenekler sekmesi &gt; Yüzeyi Düzenle seçeneği, herhangi bir kişinin arazinizin şeklini değiştirmesine, Linden bitkileri yerleştirmesine ve bu bitkilerin yerlerini değiştirmesine izin verir. Bu Yeteneği atamadan önce ne yaptığınızı bildiğinizden emin olun. Yüzey düzenleme seçeneği Arazi Hakkında &gt; Seçenekler sekmesinden açılıp kapanır." name="land edit" value="21"/>
 		<action description="Arazi Hakkında &gt; Seçenekler sekmesindeki çeşitli ayarları Aç/Kapa" longdescription="&apos;Güvenli (hasar yok)&apos;, &apos;Uç&apos; ve diğer Second Life Sakinlerinin &apos;Yüzeyi Düzenle&apos;, &apos;İnşa Et&apos;, &apos;Yer İmleri Oluştur&apos; ve &apos;Komut Dosyalarını Çalıştır&apos; yeteneklerini grubun sahip olduğu arazi üzerinde kullanmalarına izin verme tercihini Arazi Hakkında &gt; Seçenekler sekmesinden açın/kapayın." name="land options" value="22"/>
+		<action description="Ortam ayarlarını ve gün döngüsünü değiştirin." longdescription="Arazi Hakkında &gt; Ortam sekmesinden ortam ayarlarını ve gün döngüsünü değiştirin." name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="Bu Yeteneklere Üyelerin grubun sahip olduğu parseller üzerindeki kısıtlamaları geçmesine izin veren güçler de dahildir." name="Parcel Powers">
 		<action description="&apos;Yüzeyi Düzenle&apos; yeteneğine her zaman izin ver" longdescription="Bu Yeteneğe sahip olan bir Roldeki Üyeler, Arazi Hakkında &gt; Seçenekler sekmesinde kapalı olsa da grubun sahip olduğu parsel üzerinde yüzey düzenleme yapabilir." name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/tr/strings.xml b/indra/newview/skins/default/xui/tr/strings.xml
index 27f3c4d4d98c587fbbfe18e8fa1115cd33fe45ae..3fd466d71cd11f486ceac7772727c963b2d2da1c 100644
--- a/indra/newview/skins/default/xui/tr/strings.xml
+++ b/indra/newview/skins/default/xui/tr/strings.xml
@@ -639,6 +639,15 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.
 	<string name="BUTTON_HELP">
 		Yardımı Göster
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		Bu türe ait öğeler bu bölgedeki 
+not kartlarına eklenemez.
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		Sadece kısıtlamasız &apos;sonraki sahip&apos; 
+izinlerini içeren öğeler not 
+kartlarına eklenebilir.
+	</string>
 	<string name="Searching">
 		Arıyor...
 	</string>
@@ -715,6 +724,18 @@ Lütfen bir dakika içerisinde tekrar oturum açmayı deneyin.
 		Karşıya yükleme talebinde hata. Bu sorunu çözmek için lütfen 
 http://secondlife.com/support adresini ziyaret edin.
 	</string>
+	<string name="SettingValidationError">
+		[NAME] ayarlarının içeri aktarılması için doğrulama başarısız oldu
+	</string>
+	<string name="SettingImportFileError">
+		[FILE] dosyası açılamadı
+	</string>
+	<string name="SettingParseFileError">
+		[FILE] dosyası açılamadı
+	</string>
+	<string name="SettingTranslateError">
+		Eski Windlight [NAME] çevrilemedi
+	</string>
 	<string name="texture">
 		doku
 	</string>
@@ -790,6 +811,9 @@ http://secondlife.com/support adresini ziyaret edin.
 	<string name="symbolic folder link">
 		klasör bağlantısı
 	</string>
+	<string name="settings blob">
+		ayarlar
+	</string>
 	<string name="mesh">
 		örgü
 	</string>
@@ -1120,6 +1144,9 @@ http://secondlife.com/support adresini ziyaret edin.
 	<string name="ForceSitAvatar">
 		Avatarınızı oturmaya zorlayın
 	</string>
+	<string name="ChangeEnvSettings">
+		Ortam ayarlarınızı değiştirin
+	</string>
 	<string name="NotConnected">
 		Bağlı Değil
 	</string>
@@ -1271,6 +1298,9 @@ http://secondlife.com/support adresini ziyaret edin.
 	<string name="tattoo">
 		Dövme
 	</string>
+	<string name="universal">
+		Evrensel
+	</string>
 	<string name="physics">
 		Fizik
 	</string>
@@ -1313,6 +1343,9 @@ http://secondlife.com/support adresini ziyaret edin.
 	<string name="tattoo_not_worn">
 		Giyilmemiş dövme
 	</string>
+	<string name="universal_not_worn">
+		Evrensel giyilmiyor
+	</string>
 	<string name="physics_not_worn">
 		GiyilmemiÅŸ fizik
 	</string>
@@ -1364,6 +1397,9 @@ http://secondlife.com/support adresini ziyaret edin.
 	<string name="create_new_tattoo">
 		Yeni dövme oluştur
 	</string>
+	<string name="create_new_universal">
+		Yeni evrensel oluÅŸtur
+	</string>
 	<string name="create_new_physics">
 		Yeni fizik oluÅŸtur
 	</string>
@@ -2511,6 +2547,27 @@ Bu mesaj size gelmeye devam ederse lütfen http://support.secondlife.com adresin
 	<string name="RegionSettings">
 		Bölge Ayarları
 	</string>
+	<string name="NoEnvironmentSettings">
+		Bu Bölge ortam ayarlarını desteklemiyor.
+	</string>
+	<string name="EnvironmentSun">
+		Güneş
+	</string>
+	<string name="EnvironmentMoon">
+		Ay
+	</string>
+	<string name="EnvironmentBloom">
+		Bahar
+	</string>
+	<string name="EnvironmentCloudNoise">
+		Bulut Gürültüsü
+	</string>
+	<string name="EnvironmentNormalMap">
+		Normal Harita
+	</string>
+	<string name="EnvironmentTransparent">
+		Saydam
+	</string>
 	<string name="ClassifiedClicksTxt">
 		Tıklamalar: [TELEPORT] ışınlama, [MAP] harita, [PROFILE] profil
 	</string>
@@ -4725,6 +4782,9 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
 	<string name="New Tattoo">
 		Yeni Dövme
 	</string>
+	<string name="New Universal">
+		Yeni Evrensel
+	</string>
 	<string name="New Physics">
 		Yeni Fizik
 	</string>
@@ -4851,6 +4911,15 @@ Bu iletiyi almaya devam ederseniz, lütfen [SUPPORT_SITE] bölümüne başvurun.
 	<string name="Female - Wow">
 		Kadın - Vay be
 	</string>
+	<string name="New Daycycle">
+		Yeni Gün döngüsü
+	</string>
+	<string name="New Water">
+		Yeni Su
+	</string>
+	<string name="New Sky">
+		Yeni Gökyüzü
+	</string>
 	<string name="/bow">
 		/selamlama
 	</string>
@@ -5391,6 +5460,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="BeaconMedia">
 		Ortam işaretleri gösteriliyor (beyaz)
 	</string>
+	<string name="BeaconSun">
+		Güneş yönü işareti (turuncu) görüntüleniyor
+	</string>
+	<string name="BeaconMoon">
+		Ay yönü işareti (mor) görüntüleniyor
+	</string>
 	<string name="ParticleHiding">
 		Parçacıklar Gizleniyor
 	</string>
@@ -5418,6 +5493,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="Command_Destinations_Label">
 		Hedef Konum
 	</string>
+	<string name="Command_Environments_Label">
+		Ortamlarım
+	</string>
+	<string name="Command_Facebook_Label">
+		Facebook
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5511,6 +5592,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="Command_Destinations_Tooltip">
 		Ä°lgilendiÄŸiniz hedef konumlar
 	</string>
+	<string name="Command_Environments_Tooltip">
+		Ortamlarım
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		Facebook&apos;ta Yayınla
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		Flickr&apos;a yükle
 	</string>
@@ -5706,6 +5793,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="ExperiencePermission12">
 		deneyim izinlerini otomatik olarak kabul et
 	</string>
+	<string name="ExperiencePermission16">
+		avatarınızı oturmaya zorlayın
+	</string>
+	<string name="ExperiencePermission17">
+		ortam ayarlarınızı değiştirin
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		bilinmeyen bir işlem gerçekleştirdi: [Permission]
 	</string>
@@ -5730,6 +5823,12 @@ Düzenleyici yolunu çift tırnakla çevrelemeyi deneyin.
 	<string name="ExperiencePermissionShort12">
 		Ä°zin
 	</string>
+	<string name="ExperiencePermissionShort16">
+		Otur
+	</string>
+	<string name="ExperiencePermissionShort17">
+		Ortam
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		Sohbetlerin günlüğü tutulmuyor. Bir günlük tutmaya başlamak için, Tercihler &gt; Sohbet altında &quot;Kaydet: Sadece günlük&quot; veya &quot;Kaydet: Günlük ve dökümler&quot; seçimini yapın.
 	</string>
diff --git a/indra/newview/skins/default/xui/zh/floater_about_land.xml b/indra/newview/skins/default/xui/zh/floater_about_land.xml
index 1164722abf62189dae5331b11f0f77ba19e4d419..bb680f822e36b6e649becc61d0720fe7e94e816b 100644
--- a/indra/newview/skins/default/xui/zh/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/zh/floater_about_land.xml
@@ -474,5 +474,6 @@
 			</panel>
 		</panel>
 		<panel label="體驗" name="land_experiences_panel"/>
+		<panel label="環境" name="land_environment_panel"/>
 	</tab_container>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_adjust_environment.xml b/indra/newview/skins/default/xui/zh/floater_adjust_environment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..192c429430939b04a08f21a67c784d824616b906
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_adjust_environment.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_adjust_snapshot" title="個人照明">
+	<layout_stack name="outer_stack">
+		<layout_panel name="env_controls">
+			<layout_stack name="settings_stack">
+				<layout_panel>
+					<button label="重設" name="btn_reset" tool_tip="關閉並重設爲共享環境"/>
+					<text name="cloud_map_label">
+						雲彩圖像:
+					</text>
+				</layout_panel>
+				<layout_panel>
+					<text name="label">
+						太陽:
+					</text>
+					<check_box label="顯示指標" name="sunbeacon"/>
+				</layout_panel>
+				<layout_panel>
+					<check_box label="顯示指標" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_beacons.xml b/indra/newview/skins/default/xui/zh/floater_beacons.xml
index 83e10804d6e721d01b08afa417dec7d3239181a8..4df8c8f14bbb2dbbda08d18767b01aec755e6904 100644
--- a/indra/newview/skins/default/xui/zh/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/zh/floater_beacons.xml
@@ -18,5 +18,7 @@
 		<check_box label="聲音來源" name="sounds"/>
 		<check_box label="例子來源" name="particles"/>
 		<check_box label="媒體來源" name="moapbeacon"/>
+		<check_box label="太陽" name="sun"/>
+		<check_box label="月亮" name="moon"/>
 	</panel>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml b/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml
index dbf4a21416b978cb46b418fcfd403a354d0c1122..3729aa7620b90406987d4a129507487ee7adc097 100644
--- a/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/zh/floater_bulk_perms.xml
@@ -21,6 +21,7 @@
 	<icon name="icon_script" tool_tip="腳本"/>
 	<icon name="icon_sound" tool_tip="聲音"/>
 	<icon name="icon_texture" tool_tip="材質"/>
+	<icon name="icon_setting" tool_tip="環境設定"/>
 	<button label="√ 全部" name="check_all"/>
 	<button label="清除" label_selected="無" name="check_none"/>
 	<text name="newperms">
diff --git a/indra/newview/skins/default/xui/zh/floater_delete_env_preset.xml b/indra/newview/skins/default/xui/zh/floater_delete_env_preset.xml
deleted file mode 100644
index 4aafb319521455a5f1c6ed36c2ce5d42494ddab2..0000000000000000000000000000000000000000
--- a/indra/newview/skins/default/xui/zh/floater_delete_env_preset.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<floater name="Delete Env Preset" title="刪除環境自訂配置">
-	<string name="title_water">
-		刪除水的自訂配置
-	</string>
-	<string name="title_sky">
-		刪除天空自訂配置
-	</string>
-	<string name="title_day_cycle">
-		刪除日循環
-	</string>
-	<string name="label_water">
-		自訂配置:
-	</string>
-	<string name="label_sky">
-		自訂配置:
-	</string>
-	<string name="label_day_cycle">
-		日循環:
-	</string>
-	<string name="msg_confirm_deletion">
-		確定要刪除所選自訂配置?
-	</string>
-	<string name="msg_sky_is_referenced">
-		無法刪除日循環有所指涉的自訂配置。
-	</string>
-	<string name="combo_label">
-		-選擇一個自訂配置-
-	</string>
-	<text name="label">
-		自訂配置:
-	</text>
-	<button label="刪除" name="delete"/>
-	<button label="取消" name="cancel"/>
-</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_edit_ext_day_cycle.xml b/indra/newview/skins/default/xui/zh/floater_edit_ext_day_cycle.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cdcf0a685ed77499a441ae001bba91b3d2fe3e43
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_edit_ext_day_cycle.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="env_edit_extdaycycle" title="編輯日循環">
+	<string name="title_new">
+		新建一個日循環
+	</string>
+	<string name="title_edit">
+		編輯日循環
+	</string>
+	<string name="hint_new">
+		為日循環定名,調整各項控制確定細節,再點按「儲存」。
+	</string>
+	<string name="hint_edit">
+		若要編輯你的日循環,請調整下方各項控制,再點按「儲存」。
+	</string>
+	<string name="time_label">
+		([HH]:[MM])
+	</string>
+	<string name="sky_track_label">
+		天空[ALT]
+	</string>
+	<string name="sky_label">
+		天空
+	</string>
+	<string name="water_label">
+		æ°´æ–‡
+	</string>
+	<string name="commit_parcel">
+		套用到地段
+	</string>
+	<string name="commit_region">
+		套用到地區
+	</string>
+	<layout_stack name="outer_stack">
+		<layout_panel name="name_and_import">
+			<text name="label">
+				日循環名稱:
+			</text>
+			<button label="匯入" name="btn_import" tool_tip="從磁碟匯入舊設定。"/>
+		</layout_panel>
+		<layout_panel name="content">
+			<layout_stack name="content_stack">
+				<layout_panel name="timeline_track_selection">
+					<panel name="timeline_layers">
+						<button label="天空 4" name="sky4_track"/>
+						<button label="天空 3" name="sky3_track"/>
+						<button label="天空 2" name="sky2_track"/>
+						<button label="地面水平" name="sky1_track"/>
+						<button label="æ°´æ–‡" name="water_track"/>
+					</panel>
+					<panel name="timeline">
+						<text name="p0" value="0%[DSC]"/>
+						<text name="p1" value="25%[DSC]"/>
+						<text name="p2" value="50%[DSC]"/>
+						<text name="p3" value="75%[DSC]"/>
+						<text name="p4" value="100%[DSC]"/>
+						<multi_slider initial_value="0" name="WLTimeSlider"/>
+						<multi_slider initial_value="0" name="WLDayCycleFrames"/>
+						<text name="current_time" value="[PRCNT]%[DSC]"/>
+						<layout_stack>
+							<layout_panel>
+								<button label="複製軌跡來源:" name="copy_track"/>
+								<button label="載入軌跡來源:" name="load_track"/>
+								<button label="清除軌跡" name="clear_track"/>
+							</layout_panel>
+							<layout_panel>
+								<layout_stack name="progress_control">
+									<layout_panel name="skip_back">
+										<button name="skip_back_btn" tool_tip="逐步後退"/>
+									</layout_panel>
+									<layout_panel name="skip_forward">
+										<button name="skip_forward_btn" tool_tip="逐步前進"/>
+									</layout_panel>
+								</layout_stack>
+							</layout_panel>
+							<layout_panel>
+								<button label="新增[FRAME]" name="add_frame"/>
+								<button label="載入[FRAME]" name="btn_load_frame"/>
+								<button label="刪除[FRAME]" name="delete_frame"/>
+							</layout_panel>
+						</layout_stack>
+					</panel>
+				</layout_panel>
+				<layout_panel name="frame_edit_controls">
+					<text name="icn_lock_edit">
+						從上方的時間線選擇一個關鍵幀以編輯設定。
+					</text>
+				</layout_panel>
+				<layout_panel name="frame_settings_water">
+					<tab_container name="water_tabs">
+						<panel label="æ°´æ–‡" name="water_panel"/>
+					</tab_container>
+				</layout_panel>
+				<layout_panel name="frame_settings_sky">
+					<tab_container name="sky_tabs">
+						<panel label="大氣與照明" name="atmosphere_panel"/>
+						<panel label="雲彩" name="clouds_panel"/>
+						<panel label="日與月" name="moon_panel"/>
+					</tab_container>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+		<layout_panel name="buttons">
+			<button label="儲存" name="save_btn"/>
+			<button label="取消" name="cancel_btn"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_fixedenvironment.xml b/indra/newview/skins/default/xui/zh/floater_fixedenvironment.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b47b8937641c11831efb7e000034e970146c8ddc
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_fixedenvironment.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="Fixed Environment" title="固定環境">
+	<string name="edit_sky">
+		編輯天空:
+	</string>
+	<string name="edit_water">
+		編輯水文:
+	</string>
+	<layout_stack name="floater_stack">
+		<layout_panel name="info_panel">
+			<button label="載入" name="btn_load" tool_tip="從收納區載入一個設定"/>
+			<button label="匯入" name="btn_import" tool_tip="從磁碟匯入舊設定。"/>
+		</layout_panel>
+		<layout_panel name="button_panel">
+			<layout_stack name="button_bar_ls">
+				<layout_panel name="save_btn_lp">
+					<button label="儲存" name="btn_commit"/>
+				</layout_panel>
+				<layout_panel name="revert_btn_lp">
+					<button label="取消" name="btn_cancel" tool_tip="恢復上一個已儲存版本"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml b/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml
index 9001615d89e537436e23ede884e67785798ed126..ae05396cc5e2e4f00231b5136672a37db71a3459 100644
--- a/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/zh/floater_inventory_view_finder.xml
@@ -12,6 +12,7 @@
 	<check_box label="聲音" name="check_sound"/>
 	<check_box label="材質" name="check_texture"/>
 	<check_box label="å¿«ç…§" name="check_snapshot"/>
+	<check_box label="設定" name="check_settings"/>
 	<button label="全部" label_selected="全部" name="All"/>
 	<button label="ç„¡" label_selected="ç„¡" name="None"/>
 	<check_box label="固定顯示資料夾" name="check_show_empty"/>
diff --git a/indra/newview/skins/default/xui/zh/floater_my_environments.xml b/indra/newview/skins/default/xui/zh/floater_my_environments.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2184455dc9f43e4875fff4b15ac086d279c45d4b
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_my_environments.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater label="地點" name="my_environments" title="我的環境">
+	<layout_stack>
+		<layout_panel label="過濾器" name="filter_panel">
+			<check_box label="æ—¥" name="chk_days"/>
+			<check_box label="天空" name="chk_skies"/>
+			<check_box label="æ°´æ–‡" name="chk_water"/>
+			<filter_editor label="過濾環境" name="flt_search"/>
+		</layout_panel>
+		<layout_panel label="環境" name="list_panel">
+			<panel label="pnl_inv_wrap" name="pnl_inv_wrap"/>
+		</layout_panel>
+		<layout_panel>
+			<check_box initial_value="false" label="顯示所有資料夾" name="chk_showfolders"/>
+		</layout_panel>
+		<layout_panel name="pnl_control">
+			<panel label="bottom_panel" name="pnl_bottom">
+				<menu_button name="btn_gear" tool_tip="更多選項"/>
+				<menu_button name="btn_newsettings" tool_tip="製作新的設定"/>
+				<button name="btn_del" tool_tip="移除所選擇的物品"/>
+			</panel>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_perms_default.xml b/indra/newview/skins/default/xui/zh/floater_perms_default.xml
index d4706d8d87a9ea91808dfc94383c73c9a9845996..eb432a8bcd95dad883ce30155650f1119aad5401 100644
--- a/indra/newview/skins/default/xui/zh/floater_perms_default.xml
+++ b/indra/newview/skins/default/xui/zh/floater_perms_default.xml
@@ -37,6 +37,10 @@
 		<text name="label_12" tool_tip="設定預設權限決定何時建立服裝或身體部位">
 			可穿裝扮
 		</text>
+		<text name="label_13" tool_tip="設定預設權限決定何時建立環境設定">
+			設定
+		</text>
+		<check_box name="env_settings_c" value="true"/>
 	</panel>
 	<button label="確定" label_selected="確定" name="ok"/>
 	<button label="取消" label_selected="取消" name="cancel"/>
diff --git a/indra/newview/skins/default/xui/zh/floater_pick_track.xml b/indra/newview/skins/default/xui/zh/floater_pick_track.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f86132a423e999fe197ae6f762f8a278f5cc7139
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_pick_track.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="track picker" title="選擇:軌跡">
+	<layout_stack name="adjuster">
+		<layout_panel name="pnl_desc">
+			<text name="select_description">
+				選擇來源天空:
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_traks">
+			<radio_group name="track_selection">
+				<radio_item label="天空4[ALT]" name="radio_sky4" value="4"/>
+				<radio_item label="天空3[ALT]" name="radio_sky3" value="3"/>
+				<radio_item label="天空2[ALT]" name="radio_sky2" value="2"/>
+				<radio_item label="地面" name="radio_sky1" value="1"/>
+			</radio_group>
+		</layout_panel>
+		<layout_panel name="pnl_ok_cancel">
+			<button label="確定" label_selected="確定" name="btn_select"/>
+			<button label="取消" label_selected="取消" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/zh/floater_preferences_graphics_advanced.xml
index 7b127acd71d6a4cae1844714806e02d7019ee2f4..58314efeedd209dac92bbf0fb6132d9de1e2b18d 100644
--- a/indra/newview/skins/default/xui/zh/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/zh/floater_preferences_graphics_advanced.xml
@@ -82,7 +82,6 @@
 	<check_box initial_value="true" label="清澈透明的水" name="TransparentWater"/>
 	<check_box initial_value="true" label="凹凸映射與光澤效果" name="BumpShiny"/>
 	<check_box initial_value="true" label="本地光線" name="LocalLights"/>
-	<check_box initial_value="true" label="基本著色" name="BasicShaders" tool_tip="關閉此一選項可能避免部分顯示卡驅動程式損毀當機"/>
 	<slider label="地形細節:" name="TerrainDetail"/>
 	<text name="TerrainDetailText">
 		低
diff --git a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml
index c56b1c298742216354e05a7798220fc1c4b962c2..2b6eac48b34dc458e493a5824bc965c9e0790d80 100644
--- a/indra/newview/skins/default/xui/zh/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/zh/floater_preview_texture.xml
@@ -10,7 +10,7 @@
 		描述:
 	</text>
 	<text name="dimensions">
-		[WIDTH] 像素 X [HEIGHT] 像素
+		[WIDTH]像素 x [HEIGHT]像素
 	</text>
 	<text name="aspect_ratio">
 		預覽長寬比
diff --git a/indra/newview/skins/default/xui/zh/floater_settings_picker.xml b/indra/newview/skins/default/xui/zh/floater_settings_picker.xml
new file mode 100644
index 0000000000000000000000000000000000000000..36e32777fb056313e6e8f6fe4173391abc23c6ca
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/floater_settings_picker.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<floater name="settings picker" title="選擇:設定">
+	<floater.string name="pick title">
+		精選地點:
+	</floater.string>
+	<floater.string name="pick_track">
+		選取軌跡
+	</floater.string>
+	<floater.string name="pick_settings">
+		選取設定
+	</floater.string>
+	<floater.string name="track_water">
+		æ°´æ–‡
+	</floater.string>
+	<floater.string name="track_ground">
+		地面
+	</floater.string>
+	<floater.string name="track_sky">
+		天空[NUM]
+	</floater.string>
+	<layout_stack name="test_stack">
+		<layout_panel name="inv_list">
+			<filter_editor label="材質過濾器" name="flt_inventory_search"/>
+		</layout_panel>
+		<layout_panel name="temp">
+			<button label="確定" label_selected="確定" name="btn_select"/>
+			<button label="取消" label_selected="取消" name="btn_cancel"/>
+		</layout_panel>
+	</layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
index 02d06323d47d3721db1ddecbcefedde002438c73..881ca4033837961519b6648da6e00905f7be0b4e 100644
--- a/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/zh/floater_texture_ctrl.xml
@@ -12,6 +12,7 @@
 	<radio_group name="mode_selection">
 		<radio_item label="收納區" name="inventory" value="0"/>
 		<radio_item label="本地" name="local" value="1"/>
+		<radio_item label="確定產出" name="bake" value="2"/>
 	</radio_group>
 	<text name="unknown">
 		尺寸:[DIMENSIONS]
@@ -19,7 +20,6 @@
 	<button label="預設" label_selected="預設" name="Default"/>
 	<button label="空白" label_selected="空白" name="Blank"/>
 	<button label="ç„¡" label_selected="ç„¡" name="None"/>
-	<check_box initial_value="true" label="立即套用" name="apply_immediate_check"/>
 	<text name="preview_disabled" value="已停用預覽"/>
 	<filter_editor label="材質過濾器" name="inventory search editor"/>
 	<check_box initial_value="false" label="顯示資料夾" name="show_folders_check"/>
@@ -30,6 +30,22 @@
 		<column label="名稱" name="unit_name"/>
 		<column label="ID" name="unit_id_HIDDEN"/>
 	</scroll_list>
+	<combo_box name="l_bake_use_texture_combo_box" tool_tip="選擇定貌材質">
+		<combo_box.item label="ç„¡" name="None"/>
+		<combo_box.item label="BAKED_HEAD" name="BAKED_HEAD"/>
+		<combo_box.item label="BAKED_UPPER" name="BAKED_UPPER"/>
+		<combo_box.item label="BAKED_LOWER" name="BAKED_LOWER"/>
+		<combo_box.item label="BAKED_EYES" name="BAKED_EYES"/>
+		<combo_box.item label="BAKED_SKIRT" name="BAKED_SKIRT"/>
+		<combo_box.item label="BAKED_HAIR" name="BAKED_HAIR"/>
+		<combo_box.item label="BAKED_LEFTARM" name="BAKED_LEFTARM"/>
+		<combo_box.item label="BAKED_LEFTLEG" name="BAKED_LEFTLEG"/>
+		<combo_box.item label="BAKED_AUX1" name="BAKED_AUX1"/>
+		<combo_box.item label="BAKED_AUX2" name="BAKED_AUX2"/>
+		<combo_box.item label="BAKED_AUX3" name="BAKED_AUX3"/>
+	</combo_box>
+	<check_box initial_value="false" label="隱藏基底網面區域" name="hide_base_mesh_region"/>
 	<button label="確定" label_selected="確定" name="Select"/>
 	<button label="取消" label_selected="取消" name="Cancel"/>
+	<check_box initial_value="true" label="立即套用" name="apply_immediate_check"/>
 </floater>
diff --git a/indra/newview/skins/default/xui/zh/menu_inventory.xml b/indra/newview/skins/default/xui/zh/menu_inventory.xml
index 2ed078841ef262ae0d1b4cfe5ba573c9340673da..8b65b5c8dee04b79e1c0d084b5d17556e5824f52 100644
--- a/indra/newview/skins/default/xui/zh/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inventory.xml
@@ -10,7 +10,6 @@
 	<menu_item_call label="啟用" name="Marketplace Activate"/>
 	<menu_item_call label="停用" name="Marketplace Deactivate"/>
 	<menu_item_call label="分享" name="Share"/>
-	<menu_item_call label="購買" name="Task Buy"/>
 	<menu_item_call label="打開" name="Task Open"/>
 	<menu_item_call label="播放" name="Task Play"/>
 	<menu_item_call label="屬性" name="Task Properties"/>
@@ -34,6 +33,7 @@
 		<menu_item_call label="新內褲" name="New Underpants"/>
 		<menu_item_call label="新半透明遮罩" name="New Alpha Mask"/>
 		<menu_item_call label="新刺青" name="New Tattoo"/>
+		<menu_item_call label="新通用值" name="New Universal"/>
 		<menu_item_call label="新身體物理" name="New Physics"/>
 	</menu>
 	<menu label="新身體部位" name="New Body Parts">
@@ -42,6 +42,11 @@
 		<menu_item_call label="æ–°é ­é«®" name="New Hair"/>
 		<menu_item_call label="新眼睛" name="New Eyes"/>
 	</menu>
+	<menu label="新的設定" name="New Settings">
+		<menu_item_call label="新的天空" name="New Sky"/>
+		<menu_item_call label="æ–°çš„æ°´æ–‡" name="New Water"/>
+		<menu_item_call label="新的日循環" name="New Day Cycle"/>
+	</menu>
 	<menu label="作這一用途的預設值:" name="upload_def">
 		<menu_item_call label="圖像上傳" name="Image uploads"/>
 		<menu_item_call label="聲音上傳" name="Sound uploads"/>
@@ -103,6 +108,8 @@
 	<menu_item_call label="編輯" name="Wearable Edit"/>
 	<menu_item_call label="添加" name="Wearable Add"/>
 	<menu_item_call label="脫下" name="Take Off"/>
+	<menu_item_call label="僅套用到我自己" name="Settings Apply Local"/>
+	<menu_item_call label="套用到地段" name="Settings Apply Parcel"/>
 	<menu_item_call label="複製到 Marketplace 刊登" name="Marketplace Copy"/>
 	<menu_item_call label="移到 Marketplace 刊登" name="Marketplace Move"/>
 	<menu_item_call label="-- 無選項 --" name="--no options--"/>
diff --git a/indra/newview/skins/default/xui/zh/menu_inventory_add.xml b/indra/newview/skins/default/xui/zh/menu_inventory_add.xml
index 30bf5a7e75b3ac970171f4abd88bdc3dfb4dd3b4..c64b3996300846c720bf91811cc6e8245971a951 100644
--- a/indra/newview/skins/default/xui/zh/menu_inventory_add.xml
+++ b/indra/newview/skins/default/xui/zh/menu_inventory_add.xml
@@ -5,9 +5,7 @@
 		<menu_item_call label="聲音(L$[COST])..." name="Upload Sound"/>
 		<menu_item_call label="動作(L$[COST])..." name="Upload Animation"/>
 		<menu_item_call label="模型…" name="Upload Model"/>
-		<menu_item_call label="模型精靈…" name="Upload Model Wizard"/>
 		<menu_item_call label="批量(每檔案 L$[COST] )..." name="Bulk Upload"/>
-		<menu_item_call label="設定預設上傳權限" name="perm prefs"/>
 	</menu>
 	<menu_item_call label="新資料夾" name="New Folder"/>
 	<menu_item_call label="新腳本" name="New Script"/>
@@ -25,6 +23,7 @@
 		<menu_item_call label="新內褲" name="New Underpants"/>
 		<menu_item_call label="新半透明" name="New Alpha"/>
 		<menu_item_call label="新刺青" name="New Tattoo"/>
+		<menu_item_call label="新通用值" name="New Universal"/>
 		<menu_item_call label="新身體物理" name="New Physics"/>
 	</menu>
 	<menu label="新身體部位" name="New Body Parts">
@@ -33,4 +32,9 @@
 		<menu_item_call label="æ–°é ­é«®" name="New Hair"/>
 		<menu_item_call label="新眼睛" name="New Eyes"/>
 	</menu>
+	<menu label="新的設定" name="New Settings">
+		<menu_item_call label="新的天空" name="New Sky"/>
+		<menu_item_call label="æ–°çš„æ°´æ–‡" name="New Water"/>
+		<menu_item_call label="新的日循環" name="New Day Cycle"/>
+	</menu>
 </menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
index 124598a09828cf61af89b0837867561f0d8da156..460adf99188e461570825fb82ac6dff23b9b62a0 100644
--- a/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
+++ b/indra/newview/skins/default/xui/zh/menu_outfit_gear.xml
@@ -20,6 +20,7 @@
 		<menu_item_call label="新半透明" name="New Alpha"/>
 		<menu_item_call label="新身體物理" name="New Physics"/>
 		<menu_item_call label="新刺青" name="New Tattoo"/>
+		<menu_item_call label="新通用值" name="New Universal"/>
 	</menu>
 	<menu label="新身體部位" name="New Body Parts">
 		<menu_item_call label="新體形" name="New Shape"/>
diff --git a/indra/newview/skins/default/xui/zh/menu_save_settings.xml b/indra/newview/skins/default/xui/zh/menu_save_settings.xml
new file mode 100644
index 0000000000000000000000000000000000000000..05ec0d97e27e6b254352caf78852c3cf6c639e46
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/menu_save_settings.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="save_settings_menu">
+	<menu_item_check label="儲存" name="save_settings"/>
+	<menu_item_check label="另存為" name="save_as_new_settings"/>
+	<menu_item_check label="確定" name="commit_changes"/>
+	<menu_item_check label="僅套用到我自己" name="apply_local"/>
+	<menu_item_check label="套用到地段" name="apply_parcel"/>
+	<menu_item_check label="套用到地區" name="apply_region"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_settings_add.xml b/indra/newview/skins/default/xui/zh/menu_settings_add.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4e1174124107e4ffa37715f47b02e5422af10ca1
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/menu_settings_add.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_add">
+	<menu_item_call label="新的天空" name="New Sky"/>
+	<menu_item_call label="æ–°çš„æ°´æ–‡" name="New Water"/>
+	<menu_item_call label="新的日循環" name="New Day Cycle"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_settings_gear.xml b/indra/newview/skins/default/xui/zh/menu_settings_gear.xml
new file mode 100644
index 0000000000000000000000000000000000000000..342f9d50b46458419d1866922733f1959193ddc3
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/menu_settings_gear.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<toggleable_menu name="menu_settings_gear">
+	<menu_item_call label="編輯" name="edit_settings"/>
+	<menu_item_call label="僅套用到我自己" name="Settings Apply Local"/>
+	<menu_item_call label="套用到地段" name="Settings Apply Parcel"/>
+	<menu_item_call label="套用到地區" name="Settings Apply Region"/>
+	<menu_item_call label="複製" name="copy_settings"/>
+	<menu_item_call label="貼上" name="paste_settings"/>
+	<menu_item_call label="覆製 UUID" name="copy_uuid"/>
+</toggleable_menu>
diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml
index a5c96849737f9f981836fd9cdf0d8c151238e381..972434dfc5254279fd03b8a23b8b4e697606533b 100644
--- a/indra/newview/skins/default/xui/zh/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml
@@ -77,30 +77,15 @@
 			<menu_item_check label="地段屬性" name="Parcel Properties"/>
 			<menu_item_check label="進階選單" name="Show Advanced Menu"/>
 		</menu>
-		<menu label="太陽" name="Sun">
+		<menu label="環境" name="Environment">
 			<menu_item_check label="日出" name="Sunrise"/>
 			<menu_item_check label="中午" name="Noon"/>
 			<menu_item_check label="日落" name="Sunset"/>
 			<menu_item_check label="午夜" name="Midnight"/>
-			<menu_item_check label="使用地區設定" name="Use Region Settings"/>
-		</menu>
-		<menu label="環境編輯器" name="Environment Editor">
-			<menu_item_call label="環境設定…" name="Environment Settings"/>
-			<menu label="水的自訂配置" name="Water Presets">
-				<menu_item_call label="新的自訂配置…" name="new_water_preset"/>
-				<menu_item_call label="編輯自訂配置…" name="edit_water_preset"/>
-				<menu_item_call label="刪除自訂配置…" name="delete_water_preset"/>
-			</menu>
-			<menu label="天空自訂配置" name="Sky Presets">
-				<menu_item_call label="新的自訂配置…" name="new_sky_preset"/>
-				<menu_item_call label="編輯自訂配置…" name="edit_sky_preset"/>
-				<menu_item_call label="刪除自訂配置…" name="delete_sky_preset"/>
-			</menu>
-			<menu label="日的自訂配置" name="Day Presets">
-				<menu_item_call label="新的自訂配置…" name="new_day_preset"/>
-				<menu_item_call label="編輯自訂配置…" name="edit_day_preset"/>
-				<menu_item_call label="刪除自訂配置…" name="delete_day_preset"/>
-			</menu>
+			<menu_item_check label="使用共享環境" name="Use Shared Environment"/>
+			<menu_item_call label="我的環境…" name="my_environs"/>
+			<menu_item_call label="個人照明⋯" name="adjustment_tool"/>
+			<menu_item_check label="暫停雲彩" name="pause_clouds"/>
 		</menu>
 	</menu>
 	<menu label="建造" name="BuildTools">
@@ -344,6 +329,9 @@
 			<menu_item_check label="自動半透明遮罩(非遞延)" name="Automatic Alpha Masks (non-deferred)"/>
 			<menu_item_check label="動作材質" name="Animation Textures"/>
 			<menu_item_check label="關閉材質" name="Disable Textures"/>
+			<menu_item_check label="停用環境光" name="Disable Ambient"/>
+			<menu_item_check label="停用日光" name="Disable Sunlight"/>
+			<menu_item_check label="停用本地光線" name="Disable Local Lights"/>
 			<menu_item_check label="全解析度材質" name="Rull Res Textures"/>
 			<menu_item_check label="使附著燈光呈像" name="Render Attached Lights"/>
 			<menu_item_check label="使附著例子效果呈像" name="Render Attached Particles"/>
@@ -481,6 +469,7 @@
 			<menu_item_call label="裙子" name="Skirt"/>
 			<menu_item_call label="半透明" name="Alpha"/>
 			<menu_item_call label="刺青" name="Tattoo"/>
+			<menu_item_call label="通用值" name="Universal"/>
 			<menu_item_call label="身體物理" name="Physics"/>
 			<menu_item_call label="全部衣服" name="All Clothes"/>
 		</menu>
diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml
index d304e95b09d7fff15253aabddff4ee85fc895c4b..cfde824349bb841f52536312912872a1aab76cd9 100644
--- a/indra/newview/skins/default/xui/zh/notifications.xml
+++ b/indra/newview/skins/default/xui/zh/notifications.xml
@@ -1954,6 +1954,11 @@ SHA1 指紋:[MD5_DIGEST]
 		若不勾選這選項,可能會移除地段所有人為防止惡意騷擾及為維護隱私、保護幼未成年居民不接觸成年限制級內容的限制措施。 若有必要請與地段所有人溝通。
 		<usetemplate name="okbutton" yestext="確定"/>
 	</notification>
+	<notification name="EstateParcelEnvironmentOverride">
+		取消勾選這選項會移除地段擁有人增設於地段的任何自訂環境設定。 若有必要請與地段所有人溝通。
+你確定要繼續嗎?
+		<usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/>
+	</notification>
 	<notification name="RegionEntryAccessBlocked">
 		你所欲前往的地區含有超過你目前偏好的分級的內容。  你可以到「我自己 &gt; 偏好設定 &gt; 一般設定」變更你的偏好設定。
 		<usetemplate name="okbutton" yestext="確定"/>
@@ -2433,7 +2438,15 @@ SHA1 指紋:[MD5_DIGEST]
 		這個「一日循環」檔案參考了一個不存在的天空檔案:[SKY]。
 	</notification>
 	<notification name="WLRegionApplyFail">
-		抱歉,設定無法套用到地區。  離開地區再返回也許可以解決這個問題。  所得的原因為:[FAIL_REASON]
+		抱歉,設定無法套用到地區。 原因:[FAIL_REASON]
+	</notification>
+	<notification name="WLLocalTextureDayBlock">
+		一個本地材質正在使用中:軌跡[TRACK],幀#[FRAMENO]([FRAME]%),欄位[FIELD]。
+無法儲存使用本地材質的設定。
+	</notification>
+	<notification name="WLLocalTextureFixedBlock">
+		一個本地材質正在欄位[FIELD]使用中。
+無法儲存使用本地材質的設定。
 	</notification>
 	<notification name="EnvCannotDeleteLastDayCycleKey">
 		無法刪除此日循環的最後一組設定,日循環不得為空白。  你應該修改最後一組資料,不要試圖刪除,然後再建立新的。
@@ -4380,4 +4393,76 @@ SHA1 指紋:[MD5_DIGEST]
 		[REASON]
 		<usetemplate name="okbutton" yestext="確定"/>
 	</notification>
+	<notification name="FailedToFindSettings">
+		無法從資料庫載入[NAME]的設定。
+	</notification>
+	<notification name="FailedToLoadSettingsApply">
+		無法將設定套用到環境。
+	</notification>
+	<notification name="FailedToBuildSettingsDay">
+		無法將設定套用到環境。
+	</notification>
+	<notification name="NoEnvironmentSettings">
+		這區域不支援環境設定。
+	</notification>
+	<notification label="儲存裝扮" name="SaveSettingAs">
+		把目前的環境設定儲存為:
+		<form name="form">
+			<input name="message">
+				[DESC](新)
+			</input>
+			<button name="OK" text="確定"/>
+			<button name="Cancel" text="取消"/>
+		</form>
+	</notification>
+	<notification name="WLImportFail">
+		無法匯入舊的風光(Windlight)設定[NAME],來源: 
+[FILE]。
+
+[REASONS]
+	</notification>
+	<notification name="WLParcelApplyFail">
+		無法設定此地段的環境。
+請輸入或選擇一個你有權修改的地段。
+	</notification>
+	<notification name="SettingsUnsuported">
+		這地區不支援設定。 
+請移位到支援設定的地區,再試一次。
+	</notification>
+	<notification name="SettingsConfirmLoss">
+		你即將針對名爲&quot;[NAME]&quot;的[TYPE]放棄變更。
+確定繼續?
+		<usetemplate ignoretext="確定放棄變更?" name="okcancelignore" notext="取消" yestext="確定"/>
+	</notification>
+	<notification name="SettingsConfirmReset">
+		你即將移除所有已用的設定。
+確定繼續?
+		<usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/>
+	</notification>
+	<notification name="PersonalSettingsConfirmReset">
+		你即將移除所有已用的個人照明設定。
+確定繼續?
+		<usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/>
+	</notification>
+	<notification name="SettingsMakeNoTrans">
+		你即將把無法轉移的設定匯入這個日循環。 如果繼續,將使得你正在編輯的設定也變成無法轉移。 
+
+這個改變無法取消復原。
+
+確定繼續?
+		<usetemplate ignoretext="確定要把設定變成無法轉移?" name="okcancelignore" notext="取消" yestext="確定"/>
+	</notification>
+	<notification name="NoEditFromLibrary">
+		你不得直接從資源庫編輯設定。  
+請複製到你自己的收納區,然後再試一次。
+	</notification>
+	<notification name="EnvironmentApplyFailed">
+		這些設定發生一個問題。  它們此時無法儲存或套用。
+	</notification>
+	<notification name="TrackLoadFailed">
+		無法把軌跡載入[TRACK]。
+	</notification>
+	<notification name="TrackLoadMismatch">
+		無法把軌跡從[TRACK1]載入[TRACK2]。
+	</notification>
 </notifications>
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
index f5111d629a68802b75733591d000cc44e0371b36..10ed653472aa65193b13dfe665dc1421ed54d44d 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_tattoo.xml
@@ -1,9 +1,11 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel name="edit_tattoo_panel">
-	<panel name="avatar_tattoo_color_panel">
-		<texture_picker label="頭部刺青" name="Head Tattoo" tool_tip="點按以挑選圖片"/>
-		<texture_picker label="上半身刺青" name="Upper Tattoo" tool_tip="點按以挑選圖片"/>
-		<texture_picker label="下半身刺青" name="Lower Tattoo" tool_tip="點按以挑選圖片"/>
-		<color_swatch label="顏色/色調" name="Color/Tint" tool_tip="點按以開啟顏色挑選器"/>
-	</panel>
+	<scroll_container name="avatar_tattoo_scroll">
+		<panel name="avatar_tattoo_color_panel">
+			<texture_picker label="頭部刺青" name="Head Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="上半身刺青" name="Upper Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="下半身刺青" name="Lower Tattoo" tool_tip="點按以挑選圖片"/>
+			<color_swatch label="顏色/色調" name="Color/Tint" tool_tip="點按以開啟顏色挑選器"/>
+		</panel>
+	</scroll_container>
 </panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_universal.xml b/indra/newview/skins/default/xui/zh/panel_edit_universal.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6974efcc8959fe32398d9350cecf22feb2bfb16c
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_edit_universal.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel name="edit_universal_panel">
+	<scroll_container name="avatar_universal_scroll">
+		<panel name="avatar_universal_color_panel">
+			<texture_picker label="頭部刺青" name="Head Universal Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="上半身刺青" name="Upper Universal Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="下半身刺青" name="Lower Universal Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="裙子刺青" name="Skirt Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="頭髮刺青" name="Hair Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="眼睛刺青" name="Eyes Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="左臂刺青" name="Left Arm Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="左腿刺青" name="Left Leg Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="Aux1刺青" name="Aux1 Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="Aux2刺青" name="Aux2 Tattoo" tool_tip="點按以挑選圖片"/>
+			<texture_picker label="Aux3刺青" name="Aux3 Tattoo" tool_tip="點按以挑選圖片"/>
+			<color_swatch label="顏色/色調" name="Color/Tint" tool_tip="點按以開啟顏色挑選器"/>
+		</panel>
+	</scroll_container>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
index 4dd7ea6d93c5ecb4b05da29adeda4e331861c9e7..d41785858a17fe479814479aa8b9435170464bf8 100644
--- a/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
+++ b/indra/newview/skins/default/xui/zh/panel_edit_wearable.xml
@@ -45,6 +45,9 @@
 	<string name="edit_tattoo_title">
 		刺青編輯中
 	</string>
+	<string name="edit_universal_title">
+		編輯通用值
+	</string>
 	<string name="edit_physics_title">
 		身體物理編輯中
 	</string>
@@ -93,6 +96,9 @@
 	<string name="tattoo_desc_text">
 		刺青:
 	</string>
+	<string name="universal_desc_text">
+		通用值:
+	</string>
 	<string name="physics_desc_text">
 		身體物理:
 	</string>
diff --git a/indra/newview/skins/default/xui/zh/panel_region_environment.xml b/indra/newview/skins/default/xui/zh/panel_region_environment.xml
index afea391ddafcf03a288d00d02f8318c45eff6ec3..8caadf50ae01fe540b497cd9cbe51d8284ec6e69 100644
--- a/indra/newview/skins/default/xui/zh/panel_region_environment.xml
+++ b/indra/newview/skins/default/xui/zh/panel_region_environment.xml
@@ -1,33 +1,116 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="環境" name="panel_env_info">
-	<text name="water_settings_title">
-		選擇你希望到你地區的訪客所能看到的水和天空 / 日循環設定。  詳情
-	</text>
-	<radio_group name="region_settings_radio_group">
-		<radio_item label="使用第二人生預設值" name="use_sl_default_settings"/>
-		<radio_item label="使用以下設定" name="use_my_settings"/>
-	</radio_group>
-	<panel name="user_environment_settings">
-		<text name="water_settings_title">
-			水的設定
-		</text>
-		<combo_box name="water_settings_preset_combo">
-			<combo_box.item label="-選擇一個自訂配置-" name="item0"/>
-		</combo_box>
-		<text name="sky_dayc_settings_title">
-			天空/日循環
-		</text>
-		<radio_group name="sky_dayc_settings_radio_group">
-			<radio_item label="固定天空" name="my_sky_settings"/>
-			<radio_item label="日循環" name="my_dayc_settings"/>
-		</radio_group>
-		<combo_box name="sky_settings_preset_combo">
-			<combo_box.item label="-選擇一個自訂配置-" name="item0"/>
-		</combo_box>
-		<combo_box name="dayc_settings_preset_combo">
-			<combo_box.item label="-選擇一個自訂配置-" name="item0"/>
-		</combo_box>
-	</panel>
-	<button label="套用" name="apply_btn"/>
-	<button label="取消" name="cancel_btn"/>
+	<string name="str_label_use_default">
+		使用預設設定
+	</string>
+	<string name="str_label_use_region">
+		使用地區設定
+	</string>
+	<string name="str_altitude_desription">
+		天空 [INDEX]([ALTITUDE]m)
+	</string>
+	<string name="str_no_parcel">
+		未選擇地段。 環境設定已停用。
+	</string>
+	<string name="str_cross_region">
+		跨越地區不提供環境設定。
+	</string>
+	<string name="str_legacy">
+		這地區不提供環境設定。
+	</string>
+	<string name="str_disallowed">
+		領地管理人不允許改變此區域的地段環境。
+	</string>
+	<string name="str_too_small">
+		地段必須至少128平方公尺才可支撐環境。
+	</string>
+	<string name="str_empty">
+		(空白)
+	</string>
+	<string name="str_region_env">
+		(地區環境)
+	</string>
+	<layout_stack>
+		<layout_panel name="pnl_environment_disabled">
+			<text name="txt_environment_disabled">
+				...
+			</text>
+		</layout_panel>
+		<layout_panel name="pnl_environment_config">
+			<layout_stack>
+				<layout_panel name="pnl_environment_config">
+					<layout_stack>
+						<layout_panel name="pnl_environment_current">
+							<button label="[USEDEFAULT]" name="btn_usedefault"/>
+							<button label="使用收納區" name="btn_select_inventory"/>
+							<button label="自訂" name="btn_edit"/>
+							<check_box label="地段所有人可強制設定環境" name="chk_allow_override"/>
+						</layout_panel>
+						<layout_panel name="pnl_environment_length">
+							<text name="lbl_apparent_time">
+								[HH]:[MM][AP] ([PRC]%)
+							</text>
+						</layout_panel>
+						<layout_panel name="pnl_environment_buttons"/>
+					</layout_stack>
+				</layout_panel>
+				<layout_panel name="pnl_environment_altitudes">
+					<panel name="pnl_alt1">
+						<text name="txt_alt1">
+							天空[INDEX]
+                            [ALTITUDE]公尺
+						</text>
+						<line_editor name="edt_invname_alt1">
+							未知
+						</line_editor>
+						<settings_drop_target name="sdt_alt1" tool_tip="將一個設定從收納區拖曳到這個目標箱框,便可把它選定為目前的天空。"/>
+					</panel>
+					<panel name="pnl_alt2">
+						<text name="txt_alt2">
+							天空[INDEX]
+                            [ALTITUDE]公尺
+						</text>
+						<line_editor name="edt_invname_alt2">
+							未知
+						</line_editor>
+						<settings_drop_target name="sdt_alt2" tool_tip="將一個設定從收納區拖曳到這個目標箱框,便可把它選定為目前的天空。"/>
+					</panel>
+					<panel name="pnl_alt3">
+						<text name="txt_alt3">
+							天空[INDEX]
+                            [ALTITUDE]公尺
+						</text>
+						<line_editor name="edt_invname_alt3">
+							未知
+						</line_editor>
+						<settings_drop_target name="sdt_alt3" tool_tip="將一個設定從收納區拖曳到這個目標箱框,便可把它選定為目前的天空。"/>
+					</panel>
+					<multi_slider initial_value="0" name="sld_altitudes">
+						<slider name="sld1" value="1000"/>
+						<slider name="sld2" value="2000"/>
+						<slider name="sld3" value="3000"/>
+					</multi_slider>
+					<panel name="pnl_ground">
+						<text name="txt_ground">
+							地面
+						</text>
+						<line_editor name="edt_invname_ground">
+							未知
+						</line_editor>
+						<settings_drop_target name="sdt_ground" tool_tip="將一個設定從收納區拖曳到這個目標箱框,便可把它選定為地面水平的天空。"/>
+					</panel>
+					<panel name="pnl_water">
+						<text name="txt_water">
+							æ°´æ–‡
+						</text>
+						<line_editor name="edt_invname_water">
+							未知
+						</line_editor>
+						<settings_drop_target name="sdt_water" tool_tip="將一個設定從收納區拖曳到這個目標箱框,便可把它選定為目前的水文。"/>
+					</panel>
+					<button label="重設" name="btn_rst_altitudes" tool_tip="重設為預設高度"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
 </panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_settings_sky_atmos.xml b/indra/newview/skins/default/xui/zh/panel_settings_sky_atmos.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a352055d6df6ec55bdbaca5bc8fdf6dadc08d040
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_settings_sky_atmos.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="大氣與照明" name="panel_settings_sky_atmos"/>
diff --git a/indra/newview/skins/default/xui/zh/panel_settings_sky_clouds.xml b/indra/newview/skins/default/xui/zh/panel_settings_sky_clouds.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e27e2278df7ecfae1b2ea0094e83179c723a38da
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_settings_sky_clouds.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="雲彩" name="panel_settings_sky_clouds">
+	<layout_stack>
+		<layout_panel>
+			<slider label="X" name="cloud_density_x"/>
+			<slider label="Y" name="cloud_density_y"/>
+			<slider label="D" name="cloud_density_d"/>
+			<slider label="X" name="cloud_detail_x"/>
+			<slider label="Y" name="cloud_detail_y"/>
+			<slider label="D" name="cloud_detail_d"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_settings_sky_density.xml b/indra/newview/skins/default/xui/zh/panel_settings_sky_density.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ddd5ecfe494ab9eab279c946ccd6248227775553
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_settings_sky_density.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="密度" name="panel_settings_sky_density">
+	<layout_stack>
+		<layout_panel>
+			<slider label="Rayleigh指數項:" name="rayleigh_exponential"/>
+			<slider label="Rayleigh指數比例尺:" name="rayleigh_exponential_scale"/>
+			<slider label="Rayleigh線性項:" name="rayleigh_linear"/>
+			<slider label="Rayleigh常數項:" name="rayleigh_constant"/>
+			<slider label="Rayleigh最大高度:" name="rayleigh_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="Mie指數項:" name="mie_exponential"/>
+			<slider label="Mie指數比例尺:" name="mie_exponential_scale"/>
+			<slider label="Mie線性項:" name="mie_linear"/>
+			<slider label="Mie常數項:" name="mie_constant"/>
+			<slider label="Mie Aniso因數:" name="mie_aniso_factor"/>
+			<slider label="Mie最大高度:" name="mie_max_altitude"/>
+		</layout_panel>
+		<layout_panel>
+			<slider label="吸收指數項:" name="absorption_exponential"/>
+			<slider label="吸收指數比例尺:" name="absorption_exponential_scale"/>
+			<slider label="吸收線性項:" name="absorption_linear"/>
+			<slider label="吸收常數項:" name="absorption_constant"/>
+			<slider label="吸收最大高度:" name="absorption_max_altitude"/>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_settings_sky_sunmoon.xml b/indra/newview/skins/default/xui/zh/panel_settings_sky_sunmoon.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7d1d433cbc049e9095563eca76a3777ac9a85193
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_settings_sky_sunmoon.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="日與月" name="panel_settings_sky_hbodies">
+	<layout_stack>
+		<layout_panel name="sun_layout">
+			<check_box label="顯示指標" name="sunbeacon"/>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack>
+				<layout_panel name="moon_layout">
+					<check_box label="顯示指標" name="moonbeacon"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_settings_water.xml b/indra/newview/skins/default/xui/zh/panel_settings_water.xml
new file mode 100644
index 0000000000000000000000000000000000000000..59687c001ba6a4740d3bf87ef56d2eda227bd09e
--- /dev/null
+++ b/indra/newview/skins/default/xui/zh/panel_settings_water.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="æ°´æ–‡" name="panel_settings_water">
+	<layout_stack name="water_stack1">
+		<layout_panel>
+			<text name="FresnelOffsetText">
+				菲涅耳偏距:
+			</text>
+		</layout_panel>
+		<layout_panel>
+			<layout_stack name="water_stack2">
+				<layout_panel>
+					<slider label="X:" name="water_normal_scale_x"/>
+					<slider label="Y:" name="water_normal_scale_y"/>
+					<slider label="Z:" name="water_normal_scale_z"/>
+				</layout_panel>
+			</layout_stack>
+		</layout_panel>
+	</layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/zh/panel_tools_texture.xml b/indra/newview/skins/default/xui/zh/panel_tools_texture.xml
index 9a4e2f68a8f6593a2058f5efcf385282f9ba6c24..f7868ff8550758b9f3fe0007f9b1699ff7e923bc 100644
--- a/indra/newview/skins/default/xui/zh/panel_tools_texture.xml
+++ b/indra/newview/skins/default/xui/zh/panel_tools_texture.xml
@@ -1,11 +1,5 @@
 <?xml version="1.0" encoding="utf-8" standalone="yes"?>
 <panel label="材質" name="Texture">
-	<panel.string name="string repeats per meter">
-		每公尺重覆次數
-	</panel.string>
-	<panel.string name="string repeats per face">
-		每一面重覆次數
-	</panel.string>
 	<text name="color label">
 		顏色
 	</text>
@@ -114,4 +108,5 @@
 	<spinner label="水平偏距" name="shinyOffsetU"/>
 	<spinner label="垂直偏距" name="shinyOffsetV"/>
 	<check_box initial_value="false" label="對齊平面" name="checkbox planar align" tool_tip="以最後所選擇的面為基準,對齊全部所選擇的面上的材質。 這必須使用平面材質映射方式。"/>
+	<button label="對齊" label_selected="對齊目前的材質層次" name="button align textures" tool_tip="對齊目前的材質層次"/>
 </panel>
diff --git a/indra/newview/skins/default/xui/zh/role_actions.xml b/indra/newview/skins/default/xui/zh/role_actions.xml
index e3b0eb1261c8088bf4c188a75e58c320f6252e9f..e7865b60567150f72d96ef1d5c53abfc3fa1638f 100644
--- a/indra/newview/skins/default/xui/zh/role_actions.xml
+++ b/indra/newview/skins/default/xui/zh/role_actions.xml
@@ -33,6 +33,7 @@
 		<action description="更改音樂和媒體設定" longdescription="在「土地資料」&gt; 媒體頁籤更改串流音樂和影片設定。" name="land change media" value="20"/>
 		<action description="切換「編輯地形」設定" longdescription="切換「編輯地形」設定。 *警告* 「土地資料」&gt; 「選項」頁籤 &gt;「編輯地形」可允許任何人變更你的土地形狀,放置或移動 Linden 植物。 賦予這項能力之前,敬請慎重考慮。 編輯地形可在「土地資料」&gt; 選項頁籤做切換。" name="land edit" value="21"/>
 		<action description="切換各項「土地資料」&gt; 選項設定" longdescription="在「土地資料」&gt; 選項頁籤切換「安全(無傷害)」設定,並允許其他居民在群組所有土地上「編輯地形」、「建製」、「建立地標」、「執行腳本」。" name="land options" value="22"/>
+		<action description="修改環境設定和日循環。" longdescription="從「土地資料」&gt;「環境頁籤」變更環境設定和日循環。" name="land change environment" value="46"/>
 	</action_set>
 	<action_set description="這些能力包括可允許成員在群組所有地段上規避限制。" name="Parcel Powers">
 		<action description="固定允許「編輯地形」" longdescription="身負具此能力的角色的成員可以在群組所有地段上編輯地形,無論這功能在「土地資料」&gt; 選項頁籤裡是否被禁止。" name="land allow edit land" value="23"/>
diff --git a/indra/newview/skins/default/xui/zh/strings.xml b/indra/newview/skins/default/xui/zh/strings.xml
index bbbaf57501adc13137d779a7301b80a40429826a..e6c61a5d9458911e020893ecc0e42a8e21d770a5 100644
--- a/indra/newview/skins/default/xui/zh/strings.xml
+++ b/indra/newview/skins/default/xui/zh/strings.xml
@@ -635,6 +635,15 @@ http://secondlife.com/viewer-access-faq
 	<string name="BUTTON_HELP">
 		顯示幫助
 	</string>
+	<string name="TooltipNotecardNotAllowedTypeDrop">
+		這種類型的物項不能附著
+到這一區域的記事卡。
+	</string>
+	<string name="TooltipNotecardOwnerRestrictedDrop">
+		唯有「下一所有人」權限
+不受限制的物項才可
+附著到記事卡。
+	</string>
 	<string name="Searching">
 		搜尋中...
 	</string>
@@ -711,6 +720,18 @@ http://secondlife.com/viewer-access-faq
 		上傳要求發生錯誤。  請參見: 
 http://secondlife.com/support 求助解決問題。
 	</string>
+	<string name="SettingValidationError">
+		匯入設定[NAME]時驗證失敗
+	</string>
+	<string name="SettingImportFileError">
+		無法開啟檔案[FILE]
+	</string>
+	<string name="SettingParseFileError">
+		無法開啟檔案[FILE]
+	</string>
+	<string name="SettingTranslateError">
+		無法轉譯舊的風光(windlight)[NAME]
+	</string>
 	<string name="texture">
 		材質
 	</string>
@@ -786,6 +807,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="symbolic folder link">
 		資料夾聯結
 	</string>
+	<string name="settings blob">
+		設定
+	</string>
 	<string name="mesh">
 		網面
 	</string>
@@ -1116,6 +1140,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="ForceSitAvatar">
 		強迫你的化身坐下
 	</string>
+	<string name="ChangeEnvSettings">
+		改變你的環境設定
+	</string>
 	<string name="NotConnected">
 		未聯接
 	</string>
@@ -1267,6 +1294,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="tattoo">
 		刺青
 	</string>
+	<string name="universal">
+		通用值
+	</string>
 	<string name="physics">
 		身體物理
 	</string>
@@ -1309,6 +1339,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="tattoo_not_worn">
 		刺青未穿
 	</string>
+	<string name="universal_not_worn">
+		未穿戴通用值
+	</string>
 	<string name="physics_not_worn">
 		身體物理未穿
 	</string>
@@ -1360,6 +1393,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="create_new_tattoo">
 		創造新刺青
 	</string>
+	<string name="create_new_universal">
+		創立新的通用值
+	</string>
 	<string name="create_new_physics">
 		創造新身體物理
 	</string>
@@ -2507,6 +2543,27 @@ http://secondlife.com/support 求助解決問題。
 	<string name="RegionSettings">
 		地區設定
 	</string>
+	<string name="NoEnvironmentSettings">
+		這區域不支援環境設定。
+	</string>
+	<string name="EnvironmentSun">
+		太陽
+	</string>
+	<string name="EnvironmentMoon">
+		月亮
+	</string>
+	<string name="EnvironmentBloom">
+		開花
+	</string>
+	<string name="EnvironmentCloudNoise">
+		雲彩噪度
+	</string>
+	<string name="EnvironmentNormalMap">
+		正常地圖
+	</string>
+	<string name="EnvironmentTransparent">
+		透明
+	</string>
 	<string name="ClassifiedClicksTxt">
 		點按:[TELEPORT] 瞬間傳送,[MAP] 地圖,[PROFILE] 檔案
 	</string>
@@ -4723,6 +4780,9 @@ http://secondlife.com/support 求助解決問題。
 	<string name="New Tattoo">
 		新刺青
 	</string>
+	<string name="New Universal">
+		新通用值
+	</string>
 	<string name="New Physics">
 		新身體物理
 	</string>
@@ -4849,6 +4909,15 @@ http://secondlife.com/support 求助解決問題。
 	<string name="Female - Wow">
 		女性 - 哇塞
 	</string>
+	<string name="New Daycycle">
+		新的日循環
+	</string>
+	<string name="New Water">
+		æ–°çš„æ°´æ–‡
+	</string>
+	<string name="New Sky">
+		新的天空
+	</string>
 	<string name="/bow">
 		/彎腰點頭
 	</string>
@@ -5389,6 +5458,12 @@ http://secondlife.com/support 求助解決問題。
 	<string name="BeaconMedia">
 		檢視媒體的導引(白色)
 	</string>
+	<string name="BeaconSun">
+		檢視太陽方向指標(橘色)
+	</string>
+	<string name="BeaconMoon">
+		檢視月亮方向指標(紫色)
+	</string>
 	<string name="ParticleHiding">
 		隱藏粒子效果
 	</string>
@@ -5416,6 +5491,12 @@ http://secondlife.com/support 求助解決問題。
 	<string name="Command_Destinations_Label">
 		目的地
 	</string>
+	<string name="Command_Environments_Label">
+		我的環境
+	</string>
+	<string name="Command_Facebook_Label">
+		臉書
+	</string>
 	<string name="Command_Flickr_Label">
 		Flickr
 	</string>
@@ -5509,6 +5590,12 @@ http://secondlife.com/support 求助解決問題。
 	<string name="Command_Destinations_Tooltip">
 		你可能感興趣的目的地
 	</string>
+	<string name="Command_Environments_Tooltip">
+		我的環境
+	</string>
+	<string name="Command_Facebook_Tooltip">
+		發佈到臉書
+	</string>
 	<string name="Command_Flickr_Tooltip">
 		上傳到 Flickr
 	</string>
@@ -5704,6 +5791,12 @@ http://secondlife.com/support 求助解決問題。
 	<string name="ExperiencePermission12">
 		自動接受各種體驗權限
 	</string>
+	<string name="ExperiencePermission16">
+		強迫你的化身坐下
+	</string>
+	<string name="ExperiencePermission17">
+		改變你的環境設定
+	</string>
 	<string name="ExperiencePermissionShortUnknown">
 		進行了未知的操作:[Permission]
 	</string>
@@ -5728,6 +5821,12 @@ http://secondlife.com/support 求助解決問題。
 	<string name="ExperiencePermissionShort12">
 		權限
 	</string>
+	<string name="ExperiencePermissionShort16">
+		坐下
+	</string>
+	<string name="ExperiencePermissionShort17">
+		環境
+	</string>
 	<string name="logging_calls_disabled_log_empty">
 		交談未留記錄。 若想開始留記錄,請到「偏好設定 &gt; 聊天」,選擇「儲存:只留歷史記錄」或「儲存:歷史記錄兼交談內容」。
 	</string>
diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp
index bb28abead3256bebdbcf5a11ff2b1ed3c49da722..fe81fd63ea17cc5ecd72660d879d2ad9e234610a 100644
--- a/indra/newview/tests/llviewernetwork_test.cpp
+++ b/indra/newview/tests/llviewernetwork_test.cpp
@@ -258,7 +258,7 @@ namespace tut
 					  std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi"));
 		ensure_equals("Aditi helper uri",
 					  LLGridManager::getInstance()->getHelperURI("util.aditi.lindenlab.com"),
-					  std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
+                      std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
 		ensure_equals("Aditi login page",
 					  LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
 					  std::string("https://viewer-splash.secondlife.com/"));
@@ -330,7 +330,7 @@ namespace tut
 					  std::string("https://login.aditi.lindenlab.com/cgi-bin/login.cgi"));
 		ensure_equals("Aditi helper uri",
 					  LLGridManager::getInstance()->getHelperURI("util.aditi.lindenlab.com"),
-					  std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
+                      std::string("https://secondlife.aditi.lindenlab.com/helpers/"));
 		ensure_equals("Aditi login page",
 					  LLGridManager::getInstance()->getLoginPage("util.aditi.lindenlab.com"),
 					  std::string("https://viewer-splash.secondlife.com/"));
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index b7283f53a6bd3041e21378787e69da88a5bfa09b..b65a3fefd50c605596e91a56ca7d3bec663b7ed5 100644
--- a/indra/test/llsdmessagebuilder_tut.cpp
+++ b/indra/test/llsdmessagebuilder_tut.cpp
@@ -272,7 +272,7 @@ namespace tut
 	void LLSDMessageBuilderTestObject::test<14>()
 		 // Quaternion
 	{
-	  LLQuaternion outValue, inValue = LLQuaternion(1,2,3,4);
+	  LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
 	  LLSDMessageBuilder builder = defaultBuilder();
 	  builder.addQuat("var", inValue);
 	  LLSDMessageReader reader = setReader(builder);
diff --git a/indra/test/llsdmessagereader_tut.cpp b/indra/test/llsdmessagereader_tut.cpp
index 6dc5cf593eb85aaea78c42afcf31c895c94b7e18..3c402765d813482663fded694d6cc9089fb3ae80 100644
--- a/indra/test/llsdmessagereader_tut.cpp
+++ b/indra/test/llsdmessagereader_tut.cpp
@@ -274,7 +274,7 @@ namespace tut
 	void LLSDMessageReaderTestObject::test<17>()
 		// Quaternion
 	{
-		 LLQuaternion outValue, inValue = LLQuaternion(1,2,3,4);
+		LLQuaternion outValue, inValue = LLQuaternion(1,LLVector3(2,3,4));
 		LLSD sdValue = ll_sd_from_quaternion(inValue);
 		LLSDMessageReader msg = testType(sdValue);
 		msg.getQuat("block", "var", outValue);
diff --git a/indra/test/llsdutil_tut.cpp b/indra/test/llsdutil_tut.cpp
index 140f4b832b295cbe133ef7c8f77086f01004e45a..6fce53f335143b5e57eec287a14dbed3684aa716 100644
--- a/indra/test/llsdutil_tut.cpp
+++ b/indra/test/llsdutil_tut.cpp
@@ -386,4 +386,49 @@ namespace tut
         lmap["Seattle"] = 72;
         ensure("llsd_equals(superset left map)", ! llsd_equals(lmap, rmap));
     }
+
+    template<> template<> 
+    void llsdutil_object::test<10>()
+    {
+        set_test_name("llsd_hashing");
+
+        {
+            LLSD data_s1 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
+            LLSD data_s2 = LLSD::String("The quick brown aardvark jumped over the lazy lemming.");
+
+            ensure("hash: Identical string hashes match.", boost::hash<LLSD>{}(data_s1) == boost::hash<LLSD>{}(data_s2));
+        }
+        {
+            LLSD data_r1 = LLSD::Real(3.0f);
+            LLSD data_i1 = LLSD::Integer(3);
+            ensure("hash: equivalent values but different types do not match.", boost::hash<LLSD>{}(data_r1) != boost::hash<LLSD>{}(data_i1));
+        }
+        {
+            LLSD data_a1 = LLSDArray("A")("B")("C");
+            LLSD data_a2 = LLSDArray("A")("B")("C");
+
+            ensure("hash: identical arrays produce identical results", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
+
+            data_a2.append(LLSDArray(1)(2));
+
+            ensure("hash: changing the array changes the hash.", boost::hash<LLSD>{}(data_a1) != boost::hash<LLSD>{}(data_a2));
+
+            data_a1.append(LLSDArray(1)(2));
+            ensure("hash: identical arrays produce identical results with nested arrays", boost::hash<LLSD>{}(data_a1) == boost::hash<LLSD>{}(data_a2));
+        }
+        {
+            LLSD data_m1 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            LLSD data_m2 = LLSDMap("key1", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+
+            ensure("hash: identical maps produce identical results", boost::hash<LLSD>{}(data_m1) == boost::hash<LLSD>{}(data_m2));
+
+            LLSD data_m3 = LLSDMap("key1", LLSD::Real(5.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            ensure("hash: Different values in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m3));
+
+            LLSD data_m4 = LLSDMap("keyA", LLSD::Real(3.0))("key2", "value2")("key3", LLSDArray(1)(2)(3));
+            ensure("hash: Different keys in the map produce different hashes.", boost::hash<LLSD>{}(data_m1) != boost::hash<LLSD>{}(data_m4));
+
+        }
+    }
+
 }
diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp
index 7b4b6a8b70c969ee4e9ba30af9e25324e3c81b3e..10564ad7b3974a9eb952641384771ed254426ec2 100644
--- a/indra/test/lltemplatemessagebuilder_tut.cpp
+++ b/indra/test/lltemplatemessagebuilder_tut.cpp
@@ -319,7 +319,8 @@ namespace tut
 	{
 		LLMessageTemplate messageTemplate = defaultTemplate();
 		messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
-		LLQuaternion outValue, inValue = LLQuaternion(0.3713907f, 0.5570861f, 0.7427813f,0.0f);
+        LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
+
 		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
 		builder->addQuat(_PREHASH_Test0, inValue);
 		LLTemplateMessageReader* reader = setReader(messageTemplate, builder);
@@ -786,7 +787,7 @@ namespace tut
 	{
 		LLMessageTemplate messageTemplate = defaultTemplate();
 		messageTemplate.addBlock(defaultBlock(MVT_LLQuaternion, 12));
-		LLQuaternion outValue, inValue = LLQuaternion(0.3713907f, 0.5570861f, 0.7427813f,0.0f);
+		LLQuaternion outValue, inValue = LLQuaternion(0.0f, LLVector3(0.3713907f, 0.5570861f, 0.7427813f));
 		LLTemplateMessageBuilder* builder = defaultBuilder(messageTemplate);
 		builder->addQuat(_PREHASH_Test0, inValue);
 		LLTemplateMessageReader* reader = setReader(
diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg
index 18264ee59c8d1f0351bcaf8ae38b9aab0a41aa35..635227ccf39624172b596bb85e4e7282df14a657 100755
--- a/scripts/messages/message_template.msg
+++ b/scripts/messages/message_template.msg
@@ -6,7 +6,7 @@ version 2.0
 // numbers. Each message must be numbered relative to the
 // other messages of that type. The current highest number 
 // for each type is listed below:
-// Low: 423
+// Low: 430
 // Medium: 18
 // High: 30
 // PLEASE UPDATE THIS WHEN YOU ADD A NEW MESSAGE!
@@ -4502,6 +4502,11 @@ version 2.0
         RegionAllowAccessBlock Single
         {   RegionAllowAccessOverride BOOL  }  
     }
+    {
+        ParcelEnvironmentBlock Single
+        {   ParcelEnvironmentVersion        S32  }
+        {   RegionAllowEnvironmentOverride  BOOL }
+    }
 }
 
 // ParcelPropertiesUpdate
@@ -5775,6 +5780,28 @@ version 2.0
 	}
 }
 
+// LargeGenericMessage
+// Similar to the above messages, but can handle larger payloads and serialized 
+// LLSD.  Uses HTTP transport 
+{
+    LargeGenericMessage Low 430 NotTrusted Unencoded UDPDeprecated
+    {
+		AgentData 		Single
+		{   AgentID     LLUUID  	}
+		{	SessionID	LLUUID		}
+		{	TransactionID	LLUUID	}
+    }
+    {
+        MethodData Single
+		{	Method		Variable 1 }
+		{	Invoice		LLUUID	}
+    }
+    {
+		ParamList		Variable
+		{	Parameter	Variable 2 }
+    }
+}
+
 // ***************************************************************************
 // Requests for possessions, acquisition, money, etc
 // ***************************************************************************
diff --git a/scripts/messages/message_template.msg.sha1 b/scripts/messages/message_template.msg.sha1
index db87ad5e777c31e9f49e4ff1a2364abf81a2a286..bf45b08f93c574626ba509ce98e75a169ffc3180 100755
--- a/scripts/messages/message_template.msg.sha1
+++ b/scripts/messages/message_template.msg.sha1
@@ -1 +1 @@
-55df2c7135733c5da64ef8f01859b83a433a3a09
\ No newline at end of file
+be964beb7a2cd060a438c89fd5cb25e2f687d45e
\ No newline at end of file