From 30fc38603a6031f1f9ed1b4f33beca9e469b5ed3 Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Thu, 3 Jan 2019 11:22:46 -0800
Subject: [PATCH] Fix two files stomped my merging VR before a downstream
 branch.

---
 indra/newview/lldrawpoolwater.cpp |  314 ++--
 indra/newview/llvosky.cpp         | 2248 +++++++++++------------------
 2 files changed, 981 insertions(+), 1581 deletions(-)

diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 93168901565..ee37f36cbd5 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -46,14 +46,9 @@
 #include "llworld.h"
 #include "pipeline.h"
 #include "llviewershadermgr.h"
-#include "llwaterparammanager.h"
-
-#if LL_WINDOWS
-#pragma optimize("", off)
-#endif
-
-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;
 
@@ -62,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()
@@ -109,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()
@@ -182,7 +179,7 @@ void LLDrawPoolWater::render(S32 pass)
 
 	LLGLEnable blend(GL_BLEND);
 
-	if ((mVertexShaderLevel > 0) && !sSkipScreenCopy)
+	if ((mShaderLevel > 0) && !sSkipScreenCopy)
 	{
 		shade();
 		return;
@@ -207,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;
@@ -267,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(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
 
@@ -366,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();
@@ -465,7 +471,7 @@ 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();
@@ -490,30 +496,32 @@ void LLDrawPoolWater::shade()
 	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); 	 
+
+    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;
@@ -522,20 +530,22 @@ void LLDrawPoolWater::shade()
 	light_exp *= 256.f;
 	light_exp = light_exp > 32.f ? light_exp : 32.f;
 
+    light_diffuse *= 6.f;
+
 	LLGLSLShader* shader;
 
-	F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - gAgent.getRegion()->getWaterHeight();
+	F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight();
 	
 	if (eyedepth < 0.f && LLPipeline::sWaterReflections)
 	{
-	if (deferred_render)
-	{
-			shader = &gDeferredUnderWaterProgram;
-	}
+	    if (deferred_render)
+	    {
+            shader = &gDeferredUnderWaterProgram;
+	    }
 		else
-	{
-		shader = &gUnderWaterProgram;
-	}
+        {
+	        shader = &gUnderWaterProgram;
+        }
 	}
 	else if (deferred_render)
 	{
@@ -546,16 +556,18 @@ void LLDrawPoolWater::shade()
 		shader = &gWaterProgram;
 	}
 
+    shader->bind();
+
 	if (deferred_render)
 	{
-		gPipeline.bindDeferredShader(*shader);
-	}
-	else
-	{
-		shader->bind();
+        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);
+	    }
 	}
 
-	sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f;
+	sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f;
 	
 	S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
 		
@@ -569,43 +581,48 @@ void LLDrawPoolWater::shade()
 	//bind normal map
 	S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
 
-	LLWaterParamManager * param_mgr = &LLWaterParamManager::instance();
+    if (mWaterNormp[0])
+    {
+	    gGL.getTexUnit(bumpTex)->bind(mWaterNormp[0]) ;
 
-	// change mWaterNormp if needed
-	if (mWaterNormp->getID() != param_mgr->getNormalMapID())
-	{
-		mWaterNormp = LLViewerTextureManager::getFetchedTexture(param_mgr->getNormalMapID());
+	    if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
+	    {
+		    mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+	    }
+	    else 
+	    {
+		    mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT);
+	    }
 	}
 
-	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);
+    if (mWaterNormp[1])
+    {
+        bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
+
+        gGL.getTexUnit(bumpTex)->bind(mWaterNormp[1]) ;
+
+	    if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
+	    {
+            mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
+	    }
+	    else 
+	    {
+            mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT);
+	    }
 	}
+
+    shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR, 1, pwater->getWaterFogColor().mV);
+    shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, pwater->getWaterFogDensity());
 	
-	stop_glerror();
-	
+    // bind reflection texture from RenderTarget
+	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
 	gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);	
 
-	if (mVertexShaderLevel == 1)
+	if (mShaderLevel == 1)
 	{
-		sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue;
-		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);
+        LLColor4 fog_color(pwater->getWaterFogColor(), 0.f);
+        fog_color[3] = pwater->getWaterFogDensity();
+        shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
 	}
 
 	F32 screenRes[] = 
@@ -619,25 +636,30 @@ void LLDrawPoolWater::shade()
 	S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
 	stop_glerror();
 	
-	light_dir.normVec();
-	sLightDir = light_dir;
-	
-	light_diffuse *= 6.f;
-
 	//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
 	shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
 	shader->uniform1f(LLShaderMgr::WATER_TIME, sTime);
 	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 scaledAngle = 1.f - sunAngle;
@@ -652,12 +674,12 @@ void LLDrawPoolWater::shade()
 	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)
@@ -665,40 +687,19 @@ void LLDrawPoolWater::shade()
 		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;
-			}
+        sNeedsReflectionUpdate = TRUE;			
+        sNeedsDistortionUpdate = TRUE;
 
-			LLVOWater* water = (LLVOWater*) face->getViewerObject();
+        for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++)
+		{
+			LLFace *face = *iter;
 			gGL.getTexUnit(diffTex)->bind(face->getTexture());
-
-			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();
-			}
+            face->renderIndexed();
 		}
-	}
+    }
 	
 	shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
 	shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);	
@@ -707,14 +708,7 @@ void LLDrawPoolWater::shade()
 	shader->disableTexture(LLShaderMgr::WATER_REFTEX);
 	shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
 
-	if (deferred_render)
-	{
-		gPipeline.unbindDeferredShader(*shader);
-	}
-	else
-	{
-		shader->unbind();
-	}
+	shader->unbind();
 
 	gGL.getTexUnit(0)->activate();
 	gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 54ec238fdef..af078251b30 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -48,156 +48,42 @@
 #include "llworld.h"
 #include "pipeline.h"
 #include "lldrawpoolwlsky.h"
-#include "llwlparammanager.h"
-#include "llwaterparammanager.h"
+#include "v3colorutil.h"
 
-#undef min
-#undef max
-
-#if LL_WINDOWS
-#pragma optimize("", off)
-#endif
-
-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;
+#include "llsettingssky.h"
+#include "llenvironment.h"
 
-// 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;
+#include "lltrace.h"
+#include "llfasttimer.h"
 
-// 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;
+#undef min
+#undef max
 
-class LLFastLn
+namespace
 {
-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;
-
+    const S32 NUM_TILES_X = 8;
+    const S32 NUM_TILES_Y = 4;
+    const S32 NUM_TILES = NUM_TILES_X * NUM_TILES_Y;
 
-// Functions used a lot.
+    // Heavenly body constants
+    const F32 SUN_DISK_RADIUS	= 0.5f;
+    const F32 MOON_DISK_RADIUS	= SUN_DISK_RADIUS * 0.9f;
+    const F32 SUN_INTENSITY = 1e5;
 
-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);
-}
+    // Texture coordinates:
+    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);
 
-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);
-}
+    const F32 LIGHT_DIRECTION_THRESHOLD = (F32) cosf(DEG_TO_RAD * 1.f);
+    const F32 COLOR_CHANGE_THRESHOLD = 0.01f;
 
-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);
-	}
-}
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATETIMER("VOSky Update Timer Tick");
+    LLTrace::BlockTimerStatHandle FTM_VOSKY_UPDATEFORCED("VOSky Update Forced");
 
-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 );
+    F32Seconds UPDATE_EXPRY(2.0f);
 }
-
-// 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
 ***************************************/
@@ -253,6 +139,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)
 {
@@ -293,9 +205,6 @@ void LLSkyTex::create(const F32 brightness)
 	createGLImage(sCurrent);
 }
 
-
-
-
 void LLSkyTex::createGLImage(S32 which)
 {	
 	mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL);
@@ -304,15 +213,176 @@ void LLSkyTex::createGLImage(S32 which)
 
 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 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;
@@ -330,32 +400,15 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 	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();
 
+    mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
+    mForceUpdateThrottle.reset();
+
 	for (S32 i = 0; i < 6; i++)
 	{
 		mSkyTex[i].init();
@@ -370,33 +423,13 @@ 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;
+	mInterpVal = 0.f;    
 }
 
 
@@ -410,11 +443,32 @@ 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->getSunlightColor();
+    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.gamma = psky->getGamma();
 
 	// Initialize the cached normalized direction vectors
 	for (S32 side = 0; side < 6; ++side)
@@ -422,7 +476,7 @@ void LLVOSky::init()
 		for (S32 tile = 0; tile < NUM_TILES; ++tile)
 		{
 			initSkyTextureDirs(side, tile);
-			createSkyTexture(side, tile);
+			createSkyTexture(m_atmosphericsVars, side, tile, false);
 		}
 	}
 
@@ -433,9 +487,107 @@ void LLVOSky::init()
 	}
 
 	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.max_y = psky->getMaxY();
+    m_atmosphericsVars.sun_norm = LLEnvironment::instance().getClampedSunNorm();
+    m_atmosphericsVars.sunlight = psky->getSunlightColor();
+    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.gamma = psky->getGamma();
+
+	LLColor3 vary_HazeColor;
+	LLColor3 vary_SunlightColor;
+	LLColor3 vary_AmbientColor;
+	{
+		// Initialize temp variables
+		LLColor3 sunlight = m_atmosphericsVars.sunlight;
+
+		// Sunlight attenuation effect (hue and brightness) due to atmosphere
+		// this is used later for sunlight modulation at various altitudes
+		LLColor3 light_atten =
+			(m_atmosphericsVars.blue_density * 1.0 + smear(m_atmosphericsVars.haze_density * 0.25f)) * (m_atmosphericsVars.density_multiplier * m_atmosphericsVars.max_y);
+
+		// Calculate relative weights
+		LLColor3 temp2(0.f, 0.f, 0.f);
+		LLColor3 temp1 = m_atmosphericsVars.blue_density + smear(m_atmosphericsVars.haze_density);
+		LLColor3 blue_weight = componentDiv(m_atmosphericsVars.blue_density, temp1);
+		LLColor3 haze_weight = componentDiv(smear(m_atmosphericsVars.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] );
+		F32 lighty = getSun().getDirection().mV[2];
+		temp2.mV[1] = llmax(0.f, lighty);
+		if(temp2.mV[1] > 0.f)
+		{
+			temp2.mV[1] = 1.f / temp2.mV[1];
+		}
+		componentMultBy(sunlight, componentExp((light_atten * -1.f) * temp2.mV[1]));
+
+		// Distance
+		temp2.mV[2] = m_atmosphericsVars.density_multiplier;
+
+		// Transparency (-> temp1)
+		temp1 = componentExp((temp1 * -1.f) * temp2.mV[2]);
+
+		// vary_AtmosAttenuation = temp1; 
+
+		//increase ambient when there are more clouds
+		LLColor3 tmpAmbient = m_atmosphericsVars.ambient + (smear(1.f) - m_atmosphericsVars.ambient) * m_atmosphericsVars.cloud_shadow * 0.5f;
+
+		//haze color
+		vary_HazeColor =
+			(m_atmosphericsVars.blue_horizon * blue_weight * (sunlight * (1.f - m_atmosphericsVars.cloud_shadow) + tmpAmbient)	
+			+ componentMult(m_atmosphericsVars.haze_horizon * haze_weight, sunlight * (1.f - m_atmosphericsVars.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, m_atmosphericsVars.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, m_atmosphericsVars.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));
+
+	mSun.renewDirection();
+	mSun.renewColor();
+	mMoon.renewDirection();
+	mMoon.renewColor();
 }
 
 void LLVOSky::initCubeMap() 
@@ -478,15 +630,16 @@ void LLVOSky::restoreGL()
 	{
 		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();	
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    if (psky)
+    {
+        setSunTextures(psky->getSunTextureId(), psky->getNextSunTextureId());
+        setMoonTextures(psky->getMoonTextureId(), psky->getNextMoonTextureId());
+    }
+
+	updateDirections();
 
 	if (gSavedSettings.getBOOL("RenderWater") && gGLManager.mHasCubeMap
 	    && LLCubeMap::sUseCubeMaps)
@@ -502,10 +655,11 @@ void LLVOSky::restoreGL()
 		if(cube_map)
 		{
 			cube_map->init(images);
-			mForceUpdate = TRUE;
 		}
 	}
 
+    mForceUpdate = TRUE;
+
 	if (mDrawable)
 	{
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
@@ -545,7 +699,7 @@ 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, bool skip_sky_tex)
 {
 	S32 tile_x = tile % NUM_TILES_X;
 	S32 tile_y = tile / NUM_TILES_X;
@@ -554,495 +708,55 @@ void LLVOSky::createSkyTexture(const S32 side, const S32 tile)
 	S32 tile_y_pos = tile_y * sTileResY;
 
 	S32 x, y;
+    if (!skip_sky_tex)
+    {
+        for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
+	    {
+		    for (x = tile_x_pos; x < (tile_x_pos + sTileResX); ++x)
+		    {
+                mSkyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(vars, mSkyTex[side].getDir(x, y)), x, y);
+		    }
+	    }
+    }
+
 	for (y = tile_y_pos; y < (tile_y_pos + sTileResY); ++y)
 	{
 		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);
+			mShinyTex[side].setPixel(m_legacyAtmospherics.calcSkyColorInDir(vars, mSkyTex[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();
 
+    mLastSunLightingDirection  = mSun.getDirection();
+    mLastMoonLightingDirection = mMoon.getDirection();
 
-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]);
-}
+    mSun.setDirection(psky->getSunDirection());
+	mMoon.setDirection(psky->getMoonDirection());
 
-
-static inline LLColor3 componentExp(LLColor3 const &v)
-{
-	return LLColor3(exp(v.mV[0]),
-					 exp(v.mV[1]),
-					 exp(v.mV[2]));
-}
-
-static 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));
-}
-
-static 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));
-}
-
-
-static inline LLColor3 componentSqrt(LLColor3 const &v)
-{
-	return LLColor3(sqrt(v.mV[0]),
-					 sqrt(v.mV[1]),
-					 sqrt(v.mV[2]));
-}
-
-static 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];
-}
-
-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)
-	{
-		lightnorm.mV[1] = -0.1f;
-	}
-	
-}
-
-LLColor4 LLVOSky::calcSkyColorInDir(const LLVector3 &dir, bool isShiny)
-{
-	F32 saturation = 0.3f;
-	if (dir.mV[VZ] < -0.02f)
-	{
-		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;
-	}
-
-	// 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)
-	{
-		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;
-	}
-
-	F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA;
-
-	Pn *= Plen;
-
-	vary_HorizontalProjection[0] = LLVector2(Pn[0], Pn[2]);
-	vary_HorizontalProjection[0] /= - 2.f * 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 = 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]));
-
-	// 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
-	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)
-		{
-			vary_HazeColor = colorMix(LLColor3::white * haze_brightness, vary_HazeColor, fabs((Pn[1] + 0.05f) * -20.f));
-		}
-	}
-}
-
-#if LL_MSVC && __MSVC_VER__ < 8
-#pragma optimize("p", off)
-#endif
-
-LLColor3 LLVOSky::calcSkyColorWLFrag(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLColor3 & vary_CloudColorSun, 
-							LLColor3 & vary_CloudColorAmbient, F32 & vary_CloudDensity, 
-							LLVector2 vary_HorizontalProjection[2])
-{
-	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 
-	{
-		res = color0;
-	}
-
-#	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) 
-	{
-		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;
-}
-
-LLColor3 LLVOSky::createDiffuseFromWL(LLColor3 diffuse, LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
-{
-	return componentMult(diffuse, sundiffuse) * 4.0f +
-			componentMult(ambient, sundiffuse) * 2.0f + sunambient;
-}
-
-LLColor3 LLVOSky::createAmbientFromWL(LLColor3 ambient, LLColor3 sundiffuse, LLColor3 sunambient)
-{
-	return (componentMult(ambient, sundiffuse) + sunambient) * 0.8f;
-}
-
-
-void LLVOSky::calcAtmospherics(void)
-{
-	initAtmospherics();
-
-	LLColor3 vary_HazeColor;
-	LLColor3 vary_SunlightColor;
-	LLColor3 vary_AmbientColor;
-	{
-		// 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;
-		}
-
-		temp2.mV[1] = llmax(0.f, lighty);
-		if(temp2.mV[1] > 0.f)
-		{
-			temp2.mV[1] = 1.f / temp2.mV[1];
-		}
-		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));
+    mSun.setColor(psky->getSunlightColor());
+	mMoon.setColor(psky->getMoonDiffuse());
 
 	mSun.renewDirection();
 	mSun.renewColor();
 	mMoon.renewDirection();
 	mMoon.renewColor();
-
-	float dp = getToSunLast() * LLVector3(0,0,1.f);
-	if (dp < 0)
-	{
-		dp = 0;
-	}
-
-	// 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);
-
-	mSunDiffuse = vary_SunlightColor;
-	mSunAmbient = vary_AmbientColor;
-	mMoonDiffuse = vary_SunlightColor;
-	mMoonAmbient = vary_AmbientColor;
-
-	mTotalAmbient = vary_AmbientColor;
-	mTotalAmbient.setAlpha(1);
-	
-	mFadeColor = mTotalAmbient + (mSunDiffuse + mMoonDiffuse) * 0.5f;
-	mFadeColor.setAlpha(0);
 }
 
 void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time)
 {
 }
 
-BOOL LLVOSky::updateSky()
-{
+bool LLVOSky::updateSky()
+{    
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    LLColor4 total_ambient = psky->getTotalAmbient();
+
 	if (mDead || !(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)))
 	{
 		return TRUE;
@@ -1062,11 +776,13 @@ BOOL LLVOSky::updateSky()
 	const S32 total_no_tiles = 6 * NUM_TILES;
 	const S32 cycle_frame_no = total_no_tiles + 1;
 
-	if (mUpdateTimer.getElapsedTimeF32() > 0.001f)
+	if (mUpdateTimer.getElapsedTimeF32() > 0.025f)
 	{
-		mUpdateTimer.reset();
+        mUpdateTimer.reset();
 		const S32 frame = next_frame;
 
+        mForceUpdate = mForceUpdate || (total_no_tiles == frame);
+
 		++next_frame;
 		next_frame = next_frame % cycle_frame_no;
 
@@ -1074,117 +790,150 @@ BOOL LLVOSky::updateSky()
 		// sInterpVal = (F32)next_frame / cycle_frame_no;
 		LLSkyTex::setInterpVal( mInterpVal );
 		LLHeavenBody::setInterpVal( mInterpVal );
-		calcAtmospherics();
+		updateDirections();
 
-		if (mForceUpdate || total_no_tiles == frame)
+        LLVector3 direction = mSun.getDirection();
+		direction.normalize();
+		const F32 dot_sun  = direction * mLastSunLightingDirection;
+        const F32 dot_moon = direction * mLastMoonLightingDirection;
+
+		LLColor3 delta_color;
+		delta_color.setVec(mLastTotalAmbient.mV[0] - total_ambient.mV[0],
+							mLastTotalAmbient.mV[1] - total_ambient.mV[1],
+                            mLastTotalAmbient.mV[2] - total_ambient.mV[2]);
+
+        bool sun_direction_changed  = (dot_sun < LIGHT_DIRECTION_THRESHOLD);
+        bool moon_direction_changed = (dot_moon < LIGHT_DIRECTION_THRESHOLD);
+        bool color_changed          = (delta_color.length() >= COLOR_CHANGE_THRESHOLD);
+
+        mForceUpdate = mForceUpdate || sun_direction_changed;
+        mForceUpdate = mForceUpdate || moon_direction_changed;
+        mForceUpdate = mForceUpdate || color_changed;
+        mForceUpdate = mForceUpdate || !mInitialized;
+
+        bool is_alm_wl_sky = gPipeline.canUseWindLightShaders();
+
+        calc();
+
+        if (mForceUpdate && mForceUpdateThrottle.hasExpired())
 		{
+            LL_RECORD_BLOCK_TIME(FTM_VOSKY_UPDATEFORCED);
+
+            mForceUpdateThrottle.setTimerExpirySec(UPDATE_EXPRY);
+
 			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 (!direction.isExactlyZero())
 			{
-				mLastLightingDirection = direction;
-				mLastTotalAmbient = mTotalAmbient;
+                mLastTotalAmbient = total_ambient;
 				mInitialized = TRUE;
 
 				if (mCubeMap)
 				{
-                    if (mForceUpdate)
-					{
-						updateFog(LLViewerCamera::getInstance()->getFar());
-						for (int side = 0; side < 6; side++) 
-						{
-							for (int tile = 0; tile < NUM_TILES; tile++) 
-							{
-								createSkyTexture(side, tile);
-							}
-						}
-
-						calcAtmospherics();
+					updateFog(LLViewerCamera::getInstance()->getFar());
 
-						for (int side = 0; side < 6; side++) 
+					for (int side = 0; side < 6; side++) 
+					{
+						for (int tile = 0; tile < NUM_TILES; tile++) 
 						{
-							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));
+							createSkyTexture(m_atmosphericsVars, side, tile, is_alm_wl_sky);
 						}
-						next_frame = 0;	
 					}
-				}
-			}
 
-			/// *TODO really, sky texture and env map should be shared on a single texture
-			/// I'll let Brad take this at some point
+                    int tex = mSkyTex[0].getWhich(TRUE);
 
-			// update the sky texture
-			for (S32 i = 0; i < 6; ++i)
-			{
-				mSkyTex[i].create(1.0f);
-				mShinyTex[i].create(1.0f);
-			}
-			
-			// 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));
+					for (int side = 0; side < 6; 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 < 6; ++i)
+			            {
+                            mSkyTex[i].create(1.0f);
+			            }
+                    }
+
+                    for (S32 i = 0; i < 6; ++i)
+			        {
+				        mShinyTex[i].create(1.0f);
+			        }
+
+			        // 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();
+			        }                    
 				}
-				mCubeMap->init(images);
-				gGL.getTexUnit(0)->disable();
-			}
+            }
 
 			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);
-
 			mForceUpdate = FALSE;
 		}
-		else
-		{
-			const S32 side = frame / NUM_TILES;
-			const S32 tile = frame % NUM_TILES;
-			createSkyTexture(side, tile);
-		}
 	}
 
 	if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
 	{
 		gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
 	}
+
 	return TRUE;
 }
 
 void LLVOSky::updateTextures()
 {
-	if (mSunTexturep)
+	if (mSunTexturep[0])
 	{
-		mSunTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
-		mMoonTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
-		mBloomTexturep->addTextureStats( (F32)MAX_IMAGE_AREA );
+		mSunTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
+    }
+
+    if (mSunTexturep[1])
+	{
+		mSunTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
+    }
+
+    if (mMoonTexturep[0])
+	{
+		mMoonTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
+    }
+
+    if (mMoonTexturep[1])
+	{
+		mMoonTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
+    }   
+
+    if (mBloomTexturep[0])
+    {
+		mBloomTexturep[0]->addTextureStats( (F32)MAX_IMAGE_AREA );
+	}
+
+    if (mBloomTexturep[1])
+    {
+		mBloomTexturep[1]->addTextureStats( (F32)MAX_IMAGE_AREA );
 	}
 }
 
@@ -1202,60 +951,121 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline)
 		mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL);
 	}
 
-	mFace[FACE_SUN] = mDrawable->addFace(poolp, mSunTexturep);
-	mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep);
-	mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep);
+	mFace[FACE_SUN]   = mDrawable->addFace(poolp, nullptr);
+	mFace[FACE_MOON]  = mDrawable->addFace(poolp, nullptr);
+	mFace[FACE_BLOOM] = mDrawable->addFace(poolp, nullptr);
 
 	return mDrawable;
 }
 
-//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::setSunScale(F32 sun_scale)
 {
-	if(!mFace[FACE_DUMMY])
-	{
-		LLDrawPoolSky *poolp = (LLDrawPoolSky*) gPipeline.getPool(LLDrawPool::POOL_SKY);
-		mFace[FACE_DUMMY] = mDrawable->addFace(poolp, NULL);
-	}
+    mSunScale  = sun_scale;
+}
 
-	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);
-	}
+void LLVOSky::setMoonScale(F32 moon_scale)
+{
+    mMoonScale = moon_scale;
 }
 
-static LLTrace::BlockTimerStatHandle FTM_RENDER_FAKE_VBO_UPDATE("Fake VBO Update");
+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);
+
+    if (mFace[FACE_SUN])
+    {
+        if (mSunTexturep[0])
+        {
+	        mSunTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+        }
+
+        LLViewerTexture* current_tex0 = mFace[FACE_SUN]->getTexture(LLRender::DIFFUSE_MAP);
+        LLViewerTexture* current_tex1 = mFace[FACE_SUN]->getTexture(LLRender::ALTERNATE_DIFFUSE_MAP);
+
+        if (current_tex0 && (mSunTexturep[0] != current_tex0) && current_tex0->isViewerMediaTexture())
+        {
+            static_cast<LLViewerMediaTexture*>(current_tex0)->removeMediaFromFace(mFace[FACE_SUN]);
+        }
+
+        if (current_tex1 && (mSunTexturep[1] != current_tex1) && current_tex1->isViewerMediaTexture())
+        {
+            static_cast<LLViewerMediaTexture*>(current_tex1)->removeMediaFromFace(mFace[FACE_SUN]);
+        }
+
+        mFace[FACE_SUN]->setTexture(LLRender::DIFFUSE_MAP, mSunTexturep[0]);
+
+        if (mSunTexturep[1])
+        {
+	        mSunTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);            
+        }
+        mFace[FACE_SUN]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mSunTexturep[1]);
+    }
+}
 
-void LLVOSky::updateDummyVertexBuffer()
-{	
-	if(!LLVertexBuffer::sEnableVBOs)
-		return ;
+void LLVOSky::setMoonTextures(const LLUUID& moon_texture, const LLUUID& moon_texture_next)
+{
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    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);
+
+    if (mFace[FACE_MOON])
+    {
+        if (mMoonTexturep[0])
+        {
+	        mMoonTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+        }
+        mFace[FACE_MOON]->setTexture(LLRender::DIFFUSE_MAP, mMoonTexturep[0]);
+    
+        if (mMoonTexturep[1])
+        {
+	        mMoonTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
+            mFace[FACE_MOON]->setTexture(LLRender::ALTERNATE_DIFFUSE_MAP, mMoonTexturep[1]);
+        }
+    }
+}
 
-	if(mHeavenlyBodyUpdated)
-	{
-		mHeavenlyBodyUpdated = FALSE ;
-		return ;
-	}
+void LLVOSky::setCloudNoiseTextures(const LLUUID& cloud_noise_texture, const LLUUID& cloud_noise_texture_next)
+{
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    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);
+
+    if (mCloudNoiseTexturep[0])
+    {
+	    mCloudNoiseTexturep[0]->setAddressMode(LLTexUnit::TAM_WRAP);
+    }
+
+    if (mCloudNoiseTexturep[1])
+    {
+	    mCloudNoiseTexturep[1]->setAddressMode(LLTexUnit::TAM_WRAP);
+    }
+}
+
+void LLVOSky::setBloomTextures(const LLUUID& bloom_texture, const LLUUID& bloom_texture_next)
+{
+    LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
+
+    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;
 
-	LL_RECORD_BLOCK_TIME(FTM_RENDER_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);
 
-	if(!mFace[FACE_DUMMY] || !mFace[FACE_DUMMY]->getVertexBuffer())
-		createDummyVertexBuffer() ;
+    if (mBloomTexturep[0])
+    {
+	    mBloomTexturep[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
+    }
 
-	LLStrider<LLVector3> vertices ;
-	mFace[FACE_DUMMY]->getVertexBuffer()->getVertexStrider(vertices,  0);
-	*vertices = mCameraPosAgent ;
-	mFace[FACE_DUMMY]->getVertexBuffer()->flush();
+    if (mBloomTexturep[1])
+    {
+	    mBloomTexturep[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
+    }
 }
-//----------------------------------
-//end of fake vertex buffer updating
-//----------------------------------
+
 static LLTrace::BlockTimerStatHandle FTM_GEO_SKY("Sky Geometry");
 
 BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
@@ -1264,13 +1074,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];
 
@@ -1344,64 +1155,40 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable)
 	LLVector3 up = right % look_at;
 	right.normalize();
 	up.normalize();
+    
+    bool draw_sun  = updateHeavenlyBodyGeometry(drawable, mSunScale, FACE_SUN, mSun, up, right);
+    bool draw_moon = updateHeavenlyBodyGeometry(drawable, mMoonScale, FACE_MOON, mMoon, up, right);
 
-	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));
+    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);
-			if (render_ref)
-			{
-				updateReflectionGeometry(drawable, height_above_water, mSun);
-			}
-		}
-		else
-		{
-			setDrawRefl(1);
-			if (render_ref)
-			{
-				updateReflectionGeometry(drawable, height_above_water, mMoon);
-			}
-		}
-	}
-	else
-	{
-		setDrawRefl(-1);
-	}
+    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);
+    }
 
 	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 ;
 
@@ -1412,52 +1199,28 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons
 	S32 index_offset;
 	LLFace *facep;
 
-	LLVector3 to_dir = hb.getDirection();
-
-	if (!is_sun)
-	{
-		to_dir.mV[2] = llmax(to_dir.mV[2]+0.1f, 0.1f);
-	}
+	LLVector3 to_dir   = hb.getDirection();
 	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] );
+    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]; 
@@ -1507,164 +1270,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;
@@ -1726,9 +1334,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;
@@ -1743,22 +1348,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);
@@ -1770,9 +1363,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];
@@ -1861,9 +1451,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
@@ -1874,408 +1463,225 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H,
 
 	LLFace *face = mFace[FACE_REFLECTION]; 
 
-	if (!face->getVertexBuffer() || quads*4 != face->getGeomCount())
-	{
-		face->setSize(quads * 4, quads * 6);
-		LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
-		if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE))
-		{
-			LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
-				<< face->getGeomCount() << " vertices and "
-				<< face->getIndicesCount() << " indices" << LL_ENDL;
-		}
-		face->setIndicesIndex(0);
-		face->setGeomIndex(0);
-		face->setVertexBuffer(buff);
-	}
-	
-	LLStrider<LLVector3> verticesp;
-	LLStrider<LLVector3> normalsp;
-	LLStrider<LLVector2> texCoordsp;
-	LLStrider<U16> indicesp;
-	S32 index_offset;
-	
-	index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp);
-	if (-1 == index_offset)
-	{
-		return;
-	}
-
-	LLColor3 hb_col3 = HB.getInterpColor();
-	hb_col3.clamp();
-	const LLColor4 hb_col = LLColor4(hb_col3);
-
-	const F32 min_attenuation = 0.4f;
-	const F32 max_attenuation = 0.7f;
-	const F32 attenuation = min_attenuation
-		+ cos_angle_of_view * (max_attenuation - min_attenuation);
-
-	LLColor4 hb_refl_col = (1-attenuation) * hb_col + attenuation * mFogColor;
-	face->setFaceColor(hb_refl_col);
-	
-	LLVector3 v_far[2];
-	v_far[0] = v_refl_corner[1];
-	v_far[1] = v_refl_corner[3];
-
-	if(dt_clip > 0)
-	{
-		if (dt_clip >= 1)
-		{
-			for (S32 vtx = 0; vtx < 4; ++vtx)
-			{
-				F32 ratio = far_clip / v_refl_corner[vtx].length();
-				*(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
-			}
-			const LLVector3 draw_pos = 0.25 *
-				(v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
-			face->mCenterAgent = draw_pos;
-		}
-		else
-		{
-			F32 ratio = far_clip / v_refl_corner[1].length();
-			v_sprite_corner[1] = v_refl_corner[1] * ratio;
-
-			ratio = far_clip / v_refl_corner[3].length();
-			v_sprite_corner[3] = v_refl_corner[3] * ratio;
-
-			v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
-			v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
-			v_sprite_corner[0] = v_refl_corner[1];
-			v_sprite_corner[2] = v_refl_corner[3];
-
-			for (S32 vtx = 0; vtx < 4; ++vtx)
-			{
-				*(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
-			}
-
-			const LLVector3 draw_pos = 0.25 *
-				(v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
-			face->mCenterAgent = draw_pos;
-		}
-
-		*(texCoordsp++) = TEX0tt;
-		*(texCoordsp++) = TEX0t;
-		*(texCoordsp++) = TEX1tt;
-		*(texCoordsp++) = TEX1t;
-
-		*indicesp++ = index_offset + 0;
-		*indicesp++ = index_offset + 2;
-		*indicesp++ = index_offset + 1;
-
-		*indicesp++ = index_offset + 1;
-		*indicesp++ = index_offset + 2;
-		*indicesp++ = index_offset + 3;
-
-		index_offset += 4;
-	}
-
-	if (dt_clip < 1)
-	{
-		if (dt_clip <= 0)
-		{
-			const LLVector3 draw_pos = 0.25 *
-				(v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
-			face->mCenterAgent = draw_pos;
-		}
-
-		const F32 raws_inv = 1.f/raws;
-		const F32 cols_inv = 1.f/cols;
-		LLVector3 left	= v_refl_corner[0] - v_refl_corner[1];
-		LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
-		left *= raws_inv;
-		right *= raws_inv;
-
-		F32 dt_raw = dt;
-
-		for (S32 raw = 0; raw < raws; ++raw)
-		{
-			F32 dt_v0 = raw * raws_inv;
-			F32 dt_v1 = (raw + 1) * raws_inv;
-			const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
-			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);
-			for (S32 col = 0; col < cols; ++col)
+    if (face)
+    {
+        if (!face->getVertexBuffer() || quads * 4 != face->getGeomCount())
+        {
+            face->setSize(quads * 4, quads * 6);
+            LLVertexBuffer* buff = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB);
+			if (!buff->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE))
 			{
-				F32 dt_h0 = col * cols_inv;
-				*(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
-				*(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
-				F32 dt_h1 = (col + 1) * cols_inv;
-				*(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
-				*(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
-
-				*(texCoordsp++) = LLVector2(dt_h0, dt_v1);
-				*(texCoordsp++) = LLVector2(dt_h0, dt_v0);
-				*(texCoordsp++) = LLVector2(dt_h1, dt_v1);
-				*(texCoordsp++) = LLVector2(dt_h1, dt_v0);
-
-				*indicesp++ = index_offset + 0;
-				*indicesp++ = index_offset + 2;
-				*indicesp++ = index_offset + 1;
-
-				*indicesp++ = index_offset + 1;
-				*indicesp++ = index_offset + 2;
-				*indicesp++ = index_offset + 3;
-
-				index_offset += 4;
+				LL_WARNS() << "Failed to allocate Vertex Buffer for vosky to "
+					<< face->getGeomCount() << " vertices and "
+					<< face->getIndicesCount() << " indices" << LL_ENDL;
 			}
-		}
-	}
-
-	face->getVertexBuffer()->flush();
+            face->setIndicesIndex(0);
+            face->setGeomIndex(0);
+            face->setVertexBuffer(buff);
+        }
+
+        LLStrider<LLVector3> verticesp;
+        LLStrider<LLVector3> normalsp;
+        LLStrider<LLVector2> texCoordsp;
+        LLStrider<U16> indicesp;
+        S32 index_offset;
+
+        index_offset = face->getGeometry(verticesp, normalsp, texCoordsp, indicesp);
+        if (-1 == index_offset)
+        {
+            return;
+        }
+
+        LLColor3 hb_col3 = HB.getInterpColor();
+        hb_col3.clamp();
+        const LLColor4 hb_col = LLColor4(hb_col3);
+
+        const F32 min_attenuation = 0.4f;
+        const F32 max_attenuation = 0.7f;
+        const F32 attenuation = min_attenuation
+            + cos_angle_of_view * (max_attenuation - min_attenuation);
+
+        LLColor4 hb_refl_col = (1 - attenuation) * hb_col + attenuation * getSkyFogColor();
+        face->setFaceColor(hb_refl_col);
+
+        LLVector3 v_far[2];
+        v_far[0] = v_refl_corner[1];
+        v_far[1] = v_refl_corner[3];
+
+        if (dt_clip > 0)
+        {
+            if (dt_clip >= 1)
+            {
+                for (S32 vtx = 0; vtx < 4; ++vtx)
+                {
+                    F32 ratio = far_clip / v_refl_corner[vtx].length();
+                    *(verticesp++) = v_refl_corner[vtx] = ratio * v_refl_corner[vtx] + mCameraPosAgent;
+                }
+                const LLVector3 draw_pos = 0.25 *
+                    (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
+                face->mCenterAgent = draw_pos;
+            }
+            else
+            {
+                F32 ratio = far_clip / v_refl_corner[1].length();
+                v_sprite_corner[1] = v_refl_corner[1] * ratio;
+
+                ratio = far_clip / v_refl_corner[3].length();
+                v_sprite_corner[3] = v_refl_corner[3] * ratio;
+
+                v_refl_corner[1] = (1 - dt_clip) * v_refl_corner[1] + dt_clip * v_refl_corner[0];
+                v_refl_corner[3] = (1 - dt_clip) * v_refl_corner[3] + dt_clip * v_refl_corner[2];
+                v_sprite_corner[0] = v_refl_corner[1];
+                v_sprite_corner[2] = v_refl_corner[3];
+
+                for (S32 vtx = 0; vtx < 4; ++vtx)
+                {
+                    *(verticesp++) = v_sprite_corner[vtx] + mCameraPosAgent;
+                }
+
+                const LLVector3 draw_pos = 0.25 *
+                    (v_refl_corner[0] + v_sprite_corner[1] + v_refl_corner[2] + v_sprite_corner[3]);
+                face->mCenterAgent = draw_pos;
+            }
+
+            *(texCoordsp++) = TEX0tt;
+            *(texCoordsp++) = TEX0t;
+            *(texCoordsp++) = TEX1tt;
+            *(texCoordsp++) = TEX1t;
+
+            *indicesp++ = index_offset + 0;
+            *indicesp++ = index_offset + 2;
+            *indicesp++ = index_offset + 1;
+
+            *indicesp++ = index_offset + 1;
+            *indicesp++ = index_offset + 2;
+            *indicesp++ = index_offset + 3;
+
+            index_offset += 4;
+        }
+
+        if (dt_clip < 1)
+        {
+            if (dt_clip <= 0)
+            {
+                const LLVector3 draw_pos = 0.25 *
+                    (v_refl_corner[0] + v_refl_corner[1] + v_refl_corner[2] + v_refl_corner[3]);
+                face->mCenterAgent = draw_pos;
+            }
+
+            const F32 raws_inv = 1.f / raws;
+            const F32 cols_inv = 1.f / cols;
+            LLVector3 left = v_refl_corner[0] - v_refl_corner[1];
+            LLVector3 right = v_refl_corner[2] - v_refl_corner[3];
+            left *= raws_inv;
+            right *= raws_inv;
+
+            for (S32 raw = 0; raw < raws; ++raw)
+            {
+                F32 dt_v0 = raw * raws_inv;
+                F32 dt_v1 = (raw + 1) * raws_inv;
+                const LLVector3 BL = v_refl_corner[1] + (F32)raw * left;
+                const LLVector3 BR = v_refl_corner[3] + (F32)raw * right;
+                const LLVector3 EL = BL + left;
+                const LLVector3 ER = BR + right;
+                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;
+                    *(verticesp++) = (1 - dt_h0) * EL + dt_h0 * ER + mCameraPosAgent;
+                    *(verticesp++) = (1 - dt_h0) * BL + dt_h0 * BR + mCameraPosAgent;
+                    F32 dt_h1 = (col + 1) * cols_inv;
+                    *(verticesp++) = (1 - dt_h1) * EL + dt_h1 * ER + mCameraPosAgent;
+                    *(verticesp++) = (1 - dt_h1) * BL + dt_h1 * BR + mCameraPosAgent;
+
+                    *(texCoordsp++) = LLVector2(dt_h0, dt_v1);
+                    *(texCoordsp++) = LLVector2(dt_h0, dt_v0);
+                    *(texCoordsp++) = LLVector2(dt_h1, dt_v1);
+                    *(texCoordsp++) = LLVector2(dt_h1, dt_v0);
+
+                    *indicesp++ = index_offset + 0;
+                    *indicesp++ = index_offset + 2;
+                    *indicesp++ = index_offset + 1;
+
+                    *indicesp++ = index_offset + 1;
+                    *indicesp++ = index_offset + 2;
+                    *indicesp++ = index_offset + 3;
+
+                    index_offset += 4;
+                }
+            }
+        }
+
+        face->getVertexBuffer()->flush();
+    }
 }
 
-
-
-
 void LLVOSky::updateFog(const F32 distance)
 {
-	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;
-
-	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++)
-	{
-		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
-	{
-		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);
-		
-		// 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"));
+    LLEnvironment& environment = LLEnvironment::instance();
+    if (environment.getCurrentSky() != nullptr)
+    {
+        LLVector3 light_dir = LLVector3(environment.getClampedLightNorm());
+        m_legacyAtmospherics.updateFog(distance, light_dir);
+    }
+}
 
-		LLColor4 fogCol = water_fog_color * depth_modifier;
-		fogCol.setAlpha(1);
+void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLVector3 &moon_dir_cfr)
+{
+    mSun.setDirection(sun_dir_cfr);	
+	mMoon.setDirection(moon_dir_cfr);
 
-		// set the gl fog color
-		mGLFogCol = fogCol;
+	// Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
+	// on the upward facing faces of cubes.
+    {
+	    // Same as dot product with the up direction + clamp.
+	    F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
+	    sunDot *= sunDot;	
 
-		// set the density based on what the shaders use
-		fog_density = water_fog_density * gSavedSettings.getF32("WaterGLFogDensityScale");
+	    // 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;
 
-		if (!LLGLSLShader::sNoFixedFunction)
-		{
-			glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV);
-			glFogi(GL_FOG_MODE, GL_EXP2);
-		}
-	}
+	    // 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();
+    }
 
-	mFogColor = sky_fog_color;
-	mFogColor.setAlpha(1);
-	LLDrawPoolWater::sWaterFogEnd = fog_distance*2.2f;
+	updateDirections();
 
-	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();
+    mForceUpdate = true;
 }
 
-
-// Functions used a lot.
-F32 color_norm_pow(LLColor3& col, F32 e, BOOL postmultiply)
+void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr)
 {
-	F32 mv = color_max(col);
-	if (0 == mv)
-	{
-		return 0;
-	}
+    mSun.setDirection(sun_dir_cfr);	
 
-	col *= 1.f / mv;
-	color_pow(col, e);
-	if (postmultiply)
-	{
-		col *= mv;
-	}
-	return mv;
-}
+	// Push the sun "South" as it approaches directly overhead so that we can always see bump mapping
+	// on the upward facing faces of cubes.
+    {
+	    // Same as dot product with the up direction + clamp.
+	    F32 sunDot = llmax(0.f, sun_dir_cfr.mV[2]);
+	    sunDot *= sunDot;	
 
-// 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;
-}
+	    // 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;
 
-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();
+	    // 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();
+    }
 
-	calcAtmospherics();
+	updateDirections();
 
-	if ( !mInitialized )
-	{
-		init();
-		LLSkyTex::stepCurrent();
-	}		
+    mForceUpdate = true;
 }
 
-void LLVOSky::setSunDirection(const LLVector3 &sun_dir, const LLVector3 &sun_ang_velocity)
+void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr)
 {
-	LLVector3 sun_direction = (sun_dir.length() == 0) ? LLVector3::x_axis : sun_dir;
-	sun_direction.normalize();
+	mMoon.setDirection(moon_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]);
-	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;
-
-	// 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.normalize();
-
-	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;
-	}
+	updateDirections();
+
+    mForceUpdate = true;
 }
-- 
GitLab