diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 35bd9a2254c2e813f57df8849e9bbe1211e491df..9bbeb00efe4326d589c8940fc62fc8c395ded651 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -1051,6 +1051,19 @@ LLColor3 LLSettingsSky::getAmbientColor() const
     return getColor(SETTING_AMBIENT, LLColor3(0.25f, 0.25f, 0.25f));
 }
 
+LLColor3 LLSettingsSky::getAmbientColorClamped() const
+{
+    LLColor3 ambient = getAmbientColor();
+
+    F32 max_color = llmax(ambient.mV[0], ambient.mV[1], ambient.mV[2]);
+    if (max_color > 1.0f)
+    {
+        ambient *= 1.0f/max_color;
+    }
+
+    return ambient;
+}
+
 LLColor3 LLSettingsSky::getBlueDensity() const
 {
     return getColor(SETTING_BLUE_DENSITY, LLColor3(0.2447f, 0.4487f, 0.7599f));
@@ -1313,10 +1326,23 @@ void LLSettingsSky::calculateLightSettings() const
     componentMultBy(sunlight, componentExp((light_atten * -1.f) * lighty));
     componentMultBy(sunlight, light_transmittance);
 
+    //F32 max_color = llmax(sunlight.mV[0], sunlight.mV[1], sunlight.mV[2]);
+    //if (max_color > 1.0f)
+    //{
+    //    sunlight *= 1.0f/max_color;
+    //}
+
     //increase ambient when there are more clouds
     LLColor3 tmpAmbient = ambient + (smear(1.f) - ambient) * cloud_shadow * 0.5;
     componentMultBy(tmpAmbient, light_transmittance);
 
+    //tmpAmbient = LLColor3::clamp(tmpAmbient, getGamma(), 1.0f);
+    //max_color = llmax(tmpAmbient.mV[0], tmpAmbient.mV[1], tmpAmbient.mV[2]);
+    //if (max_color > 1.0f)
+    //{
+    //    tmpAmbient *= 1.0f/max_color;
+    //}
+
     //brightness of surface both sunlight and ambient
     mSunDiffuse = sunlight;
     mSunAmbient = tmpAmbient;
@@ -1334,6 +1360,7 @@ void LLSettingsSky::calculateLightSettings() const
     LLColor3 moonlight_b(0.66, 0.66, 1.2); // scotopic ambient value
 
     componentMultBy(moonlight, componentExp((light_atten * -1.f) * lighty));
+    //clampColor(moonlight, getGamma(), 1.0f);
 
     mMoonDiffuse  = componentMult(moonlight, light_transmittance) * moon_brightness;
     mMoonAmbient  = componentMult(moonlight_b, light_transmittance) * 0.0125f;
@@ -1676,6 +1703,20 @@ LLColor3 LLSettingsSky::getSunlightColor() const
     return LLColor3(mSettings[SETTING_SUNLIGHT_COLOR]);
 }
 
+LLColor3 LLSettingsSky::getSunlightColorClamped() const
+{
+    LLColor3 sunlight = getSunlightColor();
+    //clampColor(sunlight, getGamma(), 3.0f);
+
+    F32 max_color = llmax(sunlight.mV[0], sunlight.mV[1], sunlight.mV[2]);
+    if (max_color > 1.0f)
+    {
+        sunlight *= 1.0f/max_color;
+    }
+
+    return sunlight;
+}
+
 void LLSettingsSky::setSunlightColor(const LLColor3 &val)
 {
     setValue(SETTING_SUNLIGHT_COLOR, val);
diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h
index e562fe38ff3e79716f50b6b1f3b28c81b4f87723..412791164327d9e7c3dcebfa5fca437f9a069b6a 100644
--- a/indra/llinventory/llsettingssky.h
+++ b/indra/llinventory/llsettingssky.h
@@ -292,6 +292,9 @@ class LLSettingsSky: public LLSettingsBase
     LLColor4  getTotalAmbient() const;
     LLColor4  getHazeColor() const;
 
+    LLColor3 getSunlightColorClamped() const;
+    LLColor3 getAmbientColorClamped() const;
+
     virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
 
     static LLUUID GetDefaultAssetId();
diff --git a/indra/newview/lllegacyatmospherics.cpp b/indra/newview/lllegacyatmospherics.cpp
index 720c7e238854bdf7be6c6c3111d40ba686dbde92..a1093df7e1e958dda721219f25c5a788753041af 100644
--- a/indra/newview/lllegacyatmospherics.cpp
+++ b/indra/newview/lllegacyatmospherics.cpp
@@ -242,8 +242,10 @@ LLColor4 LLAtmospherics::calcSkyColorInDir(AtmosphericsVars& vars, const LLVecto
 
 	calcSkyColorWLVert(Pn, vars);
 
+    bool low_end = !gPipeline.canUseWindLightShaders();
+
 	LLColor3 sky_color =  isShiny ? vars.hazeColor : 
-                          !gPipeline.canUseWindLightShaders() ? vars.hazeColor * 2.0f : psky->gammaCorrect(vars.hazeColor * 2.0f);
+                          low_end ? vars.hazeColor * 2.0f : psky->gammaCorrect(vars.hazeColor * 2.0f);
 
 	if (isShiny)
 	{
@@ -443,8 +445,8 @@ void LLAtmospherics::updateFog(const F32 distance, const LLVector3& tosun_in)
     vars.distance_multiplier = psky->getDistanceMultiplier();
     vars.max_y = psky->getMaxY();
     vars.sun_norm = LLEnvironment::instance().getSunDirectionCFR();
-    vars.sunlight = psky->getSunlightColor();
-    vars.ambient = psky->getAmbientColor();    
+    vars.sunlight = psky->getSunlightColorClamped();
+    vars.ambient = psky->getAmbientColorClamped();
     vars.glow = psky->getGlow();
     vars.cloud_shadow = psky->getCloudShadow();
     vars.dome_radius = psky->getDomeRadius();
@@ -605,3 +607,112 @@ F32 azimuth(const LLVector3 &v)
 	}	
 	return azimuth;
 }
+
+bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b)
+{
+    if (a.hazeColor != b.hazeColor)
+    {
+        return false;
+    }
+
+    if (a.hazeColorBelowCloud != b.hazeColorBelowCloud)
+    {
+        return false;
+    }
+
+    if (a.cloudColorSun != b.cloudColorSun)
+    {
+        return false;
+    }
+
+    if (a.cloudColorAmbient != b.cloudColorAmbient)
+    {
+        return false;
+    }
+
+    if (a.cloudDensity != b.cloudDensity)
+    {
+        return false;
+    }
+
+    if (a.density_multiplier != b.density_multiplier)
+    {
+        return false;
+    }
+
+    if (a.haze_horizon != b.haze_horizon)
+    {
+        return false;
+    }
+
+    if (a.haze_density != b.haze_density)
+    {
+        return false;
+    }
+
+    if (a.blue_horizon != b.blue_horizon)
+    {
+        return false;
+    }
+
+    if (a.blue_density != b.blue_density)
+    {
+        return false;
+    }
+
+    if (a.dome_offset != b.dome_offset)
+    {
+        return false;
+    }
+
+    if (a.dome_radius != b.dome_radius)
+    {
+        return false;
+    }
+
+    if (a.cloud_shadow != b.cloud_shadow)
+    {
+        return false;
+    }
+
+    if (a.glow != b.glow)
+    {
+        return false;
+    }
+
+    if (a.ambient != b.ambient)
+    {
+        return false;
+    }
+
+    if (a.sunlight != b.sunlight)
+    {
+        return false;
+    }
+
+    if (a.sun_norm != b.sun_norm)
+    {
+        return false;
+    }
+
+    if (a.gamma != b.gamma)
+    {
+        return false;
+    }
+
+    if (a.max_y != b.max_y)
+    {
+        return false;
+    }
+
+    if (a.distance_multiplier != b.distance_multiplier)
+    {
+        return false;
+    }
+
+    // light_atten, light_transmittance, total_density
+    // are ignored as they always change when the values above do
+    // they're just shared calc across the sky map generation to save cycles
+
+    return true;
+}
diff --git a/indra/newview/lllegacyatmospherics.h b/indra/newview/lllegacyatmospherics.h
index 95700227f94fac8ca49a5a413c603861c8b55c0e..cdfcead7a4026f0e5b85f33c3c1edd27e02e6e91 100644
--- a/indra/newview/lllegacyatmospherics.h
+++ b/indra/newview/lllegacyatmospherics.h
@@ -206,7 +206,7 @@ class AtmosphericsVars
     {
     }
 
-    LL_FORCE_INLINE friend bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b);
+    friend bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b);
 
     LLColor3  hazeColor;
     LLColor3  hazeColorBelowCloud;
@@ -233,115 +233,6 @@ class AtmosphericsVars
     LLColor3 total_density;
 };
 
-bool operator==(const AtmosphericsVars& a, const AtmosphericsVars& b)
-{
-    if (a.hazeColor != b.hazeColor)
-    {
-        return false;
-    }
-
-    if (a.hazeColorBelowCloud != b.hazeColorBelowCloud)
-    {
-        return false;
-    }
-
-    if (a.cloudColorSun != b.cloudColorSun)
-    {
-        return false;
-    }
-
-    if (a.cloudColorAmbient != b.cloudColorAmbient)
-    {
-        return false;
-    }
-
-    if (a.cloudDensity != b.cloudDensity)
-    {
-        return false;
-    }
-
-    if (a.density_multiplier != b.density_multiplier)
-    {
-        return false;
-    }
-
-    if (a.haze_horizon != b.haze_horizon)
-    {
-        return false;
-    }
-
-    if (a.haze_density != b.haze_density)
-    {
-        return false;
-    }
-
-    if (a.blue_horizon != b.blue_horizon)
-    {
-        return false;
-    }
-
-    if (a.blue_density != b.blue_density)
-    {
-        return false;
-    }
-
-    if (a.dome_offset != b.dome_offset)
-    {
-        return false;
-    }
-
-    if (a.dome_radius != b.dome_radius)
-    {
-        return false;
-    }
-
-    if (a.cloud_shadow != b.cloud_shadow)
-    {
-        return false;
-    }
-
-    if (a.glow != b.glow)
-    {
-        return false;
-    }
-
-    if (a.ambient != b.ambient)
-    {
-        return false;
-    }
-
-    if (a.sunlight != b.sunlight)
-    {
-        return false;
-    }
-
-    if (a.sun_norm != b.sun_norm)
-    {
-        return false;
-    }
-
-    if (a.gamma != b.gamma)
-    {
-        return false;
-    }
-
-    if (a.max_y != b.max_y)
-    {
-        return false;
-    }
-
-    if (a.distance_multiplier != b.distance_multiplier)
-    {
-        return false;
-    }
-
-    // light_atten, light_transmittance, total_density
-    // are ignored as they always change when the values above do
-    // they're just shared calc across the sky map generation to save cycles
-
-    return true;
-}
-
 class LLAtmospherics
 {
 public:    
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index c874b3cf59c0204e1c41e9ebb019a6fc5f198f70..aca236cdfd221d8ec3c71555883f9a454fb743a1 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -528,7 +528,7 @@ void LLViewerShaderMgr::setShaders()
         }
 
 		// Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders
-		if (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull())
+		if (!wl_class || (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull()))
 		{
 			gSky.mVOSkyp->forceSkyUpdate();
 		}
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 78c782eb5f79eca23345ff1b32908baea0e197af..ae63a9921cd97dd17d982b5bea90e12d8a537516 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -416,6 +416,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
 	mCloudDensity(0.2f),
 	mWind(0.f),
 	mForceUpdate(FALSE),
+    mNeedUpdate(TRUE),
 	mWorldScale(1.f),
 	mBumpSunDir(0.f, 0.f, 1.f)
 {
@@ -608,7 +609,7 @@ void LLVOSky::restoreGL()
 		initCubeMap();
 	}
 
-    mForceUpdate = TRUE;
+    forceSkyUpdate();
 
 	if (mDrawable)
 	{
@@ -690,6 +691,13 @@ void LLVOSky::idleUpdate(LLAgent &agent, const F64 &time)
 {
 }
 
+void LLVOSky::forceSkyUpdate()
+{
+    mForceUpdate = TRUE;
+
+    memset(&m_lastAtmosphericsVars, 0x00, sizeof(AtmosphericsVars));
+}
+
 bool LLVOSky::updateSky()
 {    
     LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky();
@@ -718,7 +726,7 @@ bool LLVOSky::updateSky()
 
 	const S32 frame = next_frame;
 
-    mForceUpdate = mForceUpdate || (total_no_tiles == frame);
+    mNeedUpdate = mForceUpdate || (total_no_tiles == frame);
 
 	++next_frame;
 	next_frame = next_frame % cycle_frame_no;
@@ -727,10 +735,13 @@ bool LLVOSky::updateSky()
 	LLHeavenBody::setInterpVal( mInterpVal );
 	updateDirections();
 
-    LLVector3 direction = mSun.getDirection();
-	direction.normalize();
-	const F32 dot_sun  = direction * mLastSunLightingDirection;
-    const F32 dot_moon = direction * mLastMoonLightingDirection;
+    LLVector3 sun_dir = mSun.getDirection();
+	sun_dir.normalize();
+    LLVector3 moon_dir = mMoon.getDirection();
+	moon_dir.normalize();
+
+	const F32 dot_sun  = sun_dir  * mLastSunLightingDirection;
+    const F32 dot_moon = moon_dir * mLastMoonLightingDirection;
 
 	LLColor3 delta_color;
 	delta_color.setVec(mLastTotalAmbient.mV[0] - total_ambient.mV[0],
@@ -741,10 +752,10 @@ bool LLVOSky::updateSky()
     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;
+    mNeedUpdate = mNeedUpdate || sun_direction_changed;
+    mNeedUpdate = mNeedUpdate || moon_direction_changed;
+    mNeedUpdate = mNeedUpdate || color_changed;
+    mNeedUpdate = mNeedUpdate || !mInitialized;
 
     bool is_alm_wl_sky = gPipeline.canUseWindLightShaders();
 
@@ -752,7 +763,7 @@ bool LLVOSky::updateSky()
 
     bool same_atmospherics = m_lastAtmosphericsVars == m_atmosphericsVars;
 
-    if (mForceUpdate && mForceUpdateThrottle.hasExpired() && !same_atmospherics)
+    if (mNeedUpdate && mForceUpdateThrottle.hasExpired() && (mForceUpdate || !same_atmospherics))
 	{
         LL_RECORD_BLOCK_TIME(FTM_VOSKY_UPDATEFORCED);
 
@@ -762,77 +773,76 @@ bool LLVOSky::updateSky()
 		
         m_lastAtmosphericsVars = m_atmosphericsVars;
 
-		if (!direction.isExactlyZero())
+        mLastTotalAmbient = total_ambient;
+		mInitialized = TRUE;
+
+		if (mCubeMap)
 		{
-            mLastTotalAmbient = total_ambient;
-			mInitialized = TRUE;
+			updateFog(LLViewerCamera::getInstance()->getFar());
 
-			if (mCubeMap)
+			for (int side = 0; side < 6; side++) 
 			{
-				updateFog(LLViewerCamera::getInstance()->getFar());
-
-				for (int side = 0; side < 6; side++) 
+				for (int tile = 0; tile < NUM_TILES; tile++) 
 				{
-					for (int tile = 0; tile < NUM_TILES; tile++) 
-					{
-						createSkyTexture(m_atmosphericsVars, side, tile, mSkyTex);
-                        createSkyTexture(m_atmosphericsVars, side, tile, mShinyTex, true);
-					}
+					createSkyTexture(m_atmosphericsVars, side, tile, mSkyTex);
+                    createSkyTexture(m_atmosphericsVars, side, tile, mShinyTex, true);
 				}
 			}
+		}
 
-            int tex = mSkyTex[0].getWhich(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);
-                }
+        int tex = mSkyTex[0].getWhich(TRUE);
 
-				raw1 = mShinyTex[side].getImageRaw(TRUE);
-				raw2 = mShinyTex[side].getImageRaw(FALSE);
-				raw2->copy(raw1);
-				mShinyTex[side].createGLImage(tex);
-			}
-			next_frame = 0;	
+		for (int side = 0; side < 6; side++) 
+		{
+            LLImageRaw* raw1 = nullptr;
+            LLImageRaw* raw2 = nullptr;
 
-			// update the sky texture
             if (!is_alm_wl_sky)
             {
-			    for (S32 i = 0; i < 6; ++i)
-			    {
-                    mSkyTex[i].create(1.0f);
-			    }
+				raw1 = mSkyTex[side].getImageRaw(TRUE);
+				raw2 = mSkyTex[side].getImageRaw(FALSE);
+				raw2->copy(raw1);
+				mSkyTex[side].createGLImage(tex);
             }
 
-            for (S32 i = 0; i < 6; ++i)
+			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)
 			{
-				mShinyTex[i].create(1.0f);
+                mSkyTex[i].create(1.0f);
 			}
+        }
+
+        for (S32 i = 0; i < 6; ++i)
+		{
+			mShinyTex[i].create(1.0f);
+		}
 
-			// update the environment map
-			if (mCubeMap)
+		// update the environment map
+		if (mCubeMap)
+		{
+			std::vector<LLPointer<LLImageRaw> > images;
+			images.reserve(6);
+			for (S32 side = 0; side < 6; side++)
 			{
-				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();
-			}                    
+				images.push_back(mShinyTex[side].getImageRaw(TRUE));
+			}
+			mCubeMap->init(images);
+			gGL.getTexUnit(0)->disable();
 		}
 
 		gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE);
-		mForceUpdate = FALSE;
+
+		mNeedUpdate  = FALSE;
+        mForceUpdate = FALSE;
 	}
 
 	if (mDrawable.notNull() && mDrawable->getFace(0) && !mDrawable->getFace(0)->getVertexBuffer())
@@ -1605,8 +1615,6 @@ void LLVOSky::setSunAndMoonDirectionsCFR(const LLVector3 &sun_dir_cfr, const LLV
     }
 
 	updateDirections();
-
-    mForceUpdate = true;
 }
 
 void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr)
@@ -1630,8 +1638,6 @@ void LLVOSky::setSunDirectionCFR(const LLVector3 &sun_dir_cfr)
     }
 
 	updateDirections();
-
-    mForceUpdate = true;
 }
 
 void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr)
@@ -1639,6 +1645,4 @@ void LLVOSky::setMoonDirectionCFR(const LLVector3 &moon_dir_cfr)
 	mMoon.setDirection(moon_dir_cfr);
 
 	updateDirections();
-
-    mForceUpdate = true;
 }
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 5f270855997926ad72b931f54ad2d741db5b64e1..6c9d6dc8be4d06afca6ecc9aed8d0d417c4955c5 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -288,7 +288,7 @@ class LLVOSky : public LLStaticViewerObject
     void setSunScale(F32 sun_scale);
     void setMoonScale(F32 sun_scale);
 
-	void forceSkyUpdate(void)							{ mForceUpdate = TRUE; }
+	void forceSkyUpdate(void);
 
 public:
 	LLFace	*mFace[FACE_COUNT];
@@ -337,6 +337,7 @@ class LLVOSky : public LLStaticViewerObject
 	F32					mWind;
 	
 	bool				mInitialized;
+    bool				mNeedUpdate;				//flag to mark update being necessary (input has changed)
 	bool				mForceUpdate;				//flag to force instantaneous update of cubemap
 	LLVector3			mLastSunLightingDirection;
     LLVector3			mLastMoonLightingDirection;