diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index 4a6dbc03132b9d5518d81a61dc68f0e77aa745dc..c81d0f97da8c0430365aaa74f7992faf7c44a5f5 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -153,7 +153,7 @@ vec3 post_diffuse = color.rgb;
  vec3 post_spec = color.rgb;
  
 #ifndef WATER_FOG
-        color.rgb += diffuse_srgb.a * diffuse_srgb.rgb;
+        color.rgb = mix(color.rgb, diffuse_srgb.rgb, diffuse_srgb.a);
 #endif
 
         if (envIntensity > 0.0)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 180f38b1e1d24902c04bc5aa4b6a63370176e248..914e17beedacf1718bba2fc288ddb2604a2c0979 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -64,7 +64,9 @@ VARYING vec4 view;
 VARYING vec4 vary_position;
 
 vec2 encode_normal(vec3 n);
-vec3 scaleSoftClipFrag(vec3 l);
+vec3 scaleSoftClip(vec3 l);
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
 
 vec3 BlendNormal(vec3 bump1, vec3 bump2)
 {
@@ -75,7 +77,7 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
 void main() 
 {
     vec4 color;
-    float dist = length(view.xy);
+    float dist = length(view.xyz);
     
     //normalize view vector
     vec3 viewVec = normalize(view.xyz);
@@ -127,7 +129,8 @@ void main()
 
     vec4 refcol = refcol1 + refcol2 + refcol3;
     float df1 = df.x + df.y + df.z;
-    refcol *= df1 * 0.333;
+    df1 *= 0.333;
+    refcol *= df1;
     
     vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
     wavef.z *= max(-viewVec.z, 0.1);
@@ -142,16 +145,18 @@ void main()
     vec4 baseCol = texture2D(refTex, refvec4);
 
     refcol = mix(baseCol*df2, refcol, dweight);
-    
+
     //figure out distortion vector (ripply)   
     vec2 distort2 = distort+wavef.xy*(refScale * 0.01)/max(dmod*df1, 1.0);
         
     vec4 fb = texture2D(screenTex, distort2);
-
+ 
     //mix with reflection
     // Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
-    color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
- 
+    color.rgb = mix(fb.rgb, refcol.rgb, df1 + 0.6);
+    color.rgb *= 2.0f;
+    color.rgb = scaleSoftClip(color.rgb);
+
     vec4 pos = vary_position;
     
     vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index a4e3f94816a2b9eb614284a4af5388decb9149a3..043815c82481b57d541531e50980a657d5cb56fb 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -121,7 +121,8 @@ void main()
 
     vec4 refcol = refcol1 + refcol2 + refcol3;
     float df1 = df.x + df.y + df.z;
-    refcol *= df1 * 0.333;
+    df1 *= 0.3333;
+    refcol *= df1;
     
     vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
     
@@ -144,13 +145,13 @@ void main()
     spec = pow(spec, 128.0);
 
     //figure out distortion vector (ripply)   
-    vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+    vec2 distort2 = distort+wavef.xy*(refScale*0.01)/max(dmod*df1, 1.0);
         
     vec4 fb = texture2D(screenTex, distort2);
     
     //mix with reflection
     // Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug
-    color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
+    color.rgb = mix(fb.rgb, refcol.rgb, df1 + 0.6);
     color.rgb += spec * specular;
     
     color.rgb = atmosTransport(color.rgb);
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 4c95fb0a0fd18861045a2a819feb80809fd4c901..2c9418ca19ffb00bf61cff0786df8ec4b800ef5b 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -479,7 +479,10 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
 
 void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp)
 {
-    F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight();
+    F32  water_height  = LLEnvironment::instance().getWaterHeight(); 
+    F32  camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
+    F32  eyedepth      = camera_height - water_height;
+    bool underwater    = eyedepth <= 0.0f;
 
     LLEnvironment& environment = LLEnvironment::instance();
     LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
@@ -487,6 +490,7 @@ void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& li
 
     shader->bind();
 
+// bind textures for water rendering
 	if (deferred_render)
 	{
         if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
@@ -516,16 +520,17 @@ void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& li
 
     F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor();
 	
+    gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+    gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
+
     if (tex_a && (!tex_b || (tex_a == tex_b)))
     {
 		gGL.getTexUnit(bumpTex)->bind(tex_a);
-        gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
         blend_factor = 0; // only one tex provided, no blending
     }
     else if (tex_b && !tex_a)
     {
         gGL.getTexUnit(bumpTex)->bind(tex_b);
-        gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
         blend_factor = 0; // only one tex provided, no blending
     }
     else if (tex_b != tex_a)
@@ -533,37 +538,40 @@ void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& li
         gGL.getTexUnit(bumpTex)->bind(tex_a);
         gGL.getTexUnit(bumpTex2)->bind(tex_b);
     }
-
-    shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
-
-    shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR, 1, pwater->getWaterFogColor().mV);
-
-    F32 fog_density = pwater->getModifiedWaterFogDensity(LLPipeline::sUnderWaterRender || (eyedepth <= 0.0f));
-
-    shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
 	
     // bind reflection texture from RenderTarget
 	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
-	gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);	
-
-	if (mShaderLevel == 1)
-	{
-        LLColor4 fog_color(pwater->getWaterFogColor(), 0.f);
-        fog_color[3] = fog_density;
-        shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
-	}
-
 	F32 screenRes[] = 
 	{
 		1.f/gGLViewport[2],
 		1.f/gGLViewport[3]
 	};
-	shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
-	stop_glerror();
-	
+		
 	S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
 	stop_glerror();
-	
+
+// set uniforms for water rendering
+    shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
+    shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
+
+    LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f);
+    F32      fog_density = pwater->getModifiedWaterFogDensity(underwater);
+
+    if (screentex > -1)
+	{
+		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
+		gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
+	}
+    
+    if (mShaderLevel == 1)
+    {
+        //F32 fog_density_slider_value = param_mgr->mDensitySliderValue;
+		//sWaterFogColor.mV[3] = fog_density_slider_value;
+        fog_color.mV[VW] = log(fog_density) / log(2);
+	}
+
+    shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
+
 	//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
 	shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
 	shader->uniform1f(LLShaderMgr::WATER_TIME, sTime);
@@ -592,30 +600,21 @@ void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& li
 	F32 sunAngle = llmax(0.f, light_dir.mV[2]);
 	F32 scaledAngle = 1.f - sunAngle;
 
+    shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
 	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
 	shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
 	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle);
     shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
 
-	LLColor4 water_color;
-	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis();
-	F32 up_dot = camera_up * LLVector3::z_axis;
 	if (LLViewerCamera::getInstance()->cameraUnderWater())
 	{
-		water_color.setVec(1.f, 1.f, 1.f, 0.4f);
 		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
 	}
 	else
 	{
-		water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot));
 		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
 	}
 
-	if (water_color.mV[3] > 0.9f)
-	{
-		water_color.mV[3] = 0.9f;
-	}
-
 	{		
 		LLGLDisable cullface(GL_CULL_FACE);
 
@@ -666,6 +665,9 @@ void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& li
         }
     }
 
+    gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+    gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
+
 	shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
 	shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);	
 	shader->disableTexture(LLShaderMgr::BUMP_MAP);
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 7e0ec23a06ef34ac9b8b883da4bc5853f48cb86f..387644fa575ce03db11e6c4a88c9e3a41ea9cc09 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -936,10 +936,14 @@ void LLSettingsVOWater::applySpecial(void *ptarget)
         shader->uniform1f(LLShaderMgr::WATER_FOGKS, waterFogKS);
 
         F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - water_height;
+        bool underwater = LLPipeline::sUnderWaterRender || (eyedepth <= 0.0f);
 
-        F32 waterFogDensity = env.getCurrentWater()->getModifiedWaterFogDensity(LLPipeline::sUnderWaterRender || (eyedepth <= 0.0f));
+        F32 waterFogDensity = env.getCurrentWater()->getModifiedWaterFogDensity(underwater);
         shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, waterFogDensity);
 
+        LLColor4 fog_color(env.getCurrentWater()->getWaterFogColor(), 0.0f);
+        shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
+
         F32 blend_factor = env.getCurrentWater()->getBlendFactor();
         shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
 
@@ -970,9 +974,8 @@ LLSettingsWater::parammapping_t LLSettingsVOWater::getParameterMap() const
 
     if (param_map.empty())
     {
-        LLSD water_defaults = LLSettingsWater::defaults();
-        param_map[SETTING_FOG_COLOR] = DefaultParam(LLShaderMgr::WATER_FOGCOLOR, water_defaults[SETTING_FOG_COLOR]);
-
+        //LLSD water_defaults = LLSettingsWater::defaults();
+        //param_map[SETTING_FOG_COLOR] = DefaultParam(LLShaderMgr::WATER_FOGCOLOR, water_defaults[SETTING_FOG_COLOR]);
         // let this get set by LLSettingsVOWater::applySpecial so that it can properly reflect the underwater modifier
         //param_map[SETTING_FOG_DENSITY] = DefaultParam(LLShaderMgr::WATER_FOGDENSITY, water_defaults[SETTING_FOG_DENSITY]);
     }
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 406d147792c1eb6a0d4175d5d4b8b24b46b208b0..e0253c8a5cfb9465bf4925a81b0947a1a9c01f41 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -2084,6 +2084,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredWaterProgram.mFeatures.hasGamma = true;
 		gDeferredWaterProgram.mFeatures.hasTransport = true;
 		gDeferredWaterProgram.mFeatures.encodesNormal = true;
+        gDeferredWaterProgram.mFeatures.hasSrgb = true;
 
 		gDeferredWaterProgram.mShaderFiles.clear();
 		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));