diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
index 8c8bd6d0d5cbd506b10dcfb7aad8851002de69cb..ad105c616c5b24c0d47c844c825a537967ece626 100644
--- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl
@@ -23,55 +23,10 @@
  * $/LicenseInfo$
  */
  
-#ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform sampler2D diffuseMap;
-uniform sampler2D bumpMap;   
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-uniform sampler2D screenDepth;
-
-uniform vec4 fogCol;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform vec2 fbScale;
-uniform float refScale;
-uniform float znear;
-uniform float zfar;
-uniform float kd;
-uniform vec4 waterPlane;
-uniform vec3 eyeVec;
-uniform vec4 waterFogColor;
-uniform float waterFogKS;
-uniform vec2 screenRes;
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-vec4 applyWaterFogView(vec3 pos, vec4 color);
 
+// debug stub
 void main() 
 {
-	vec4 color;
-	    
-	//get detail normals
-	vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
-	vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
-	vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;    
-	vec3 wavef = normalize(wave1+wave2+wave3);
-	
-	//figure out distortion vector (ripply)   
-	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-	distort = distort+wavef.xy*refScale;
-		
-	vec4 fb = texture2D(screenTex, distort);
-	
-	frag_color = applyWaterFogView(view.xyz, fb);
+    frag_color = vec4(0, 1, 1, 0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
index 7dbba1250250a67160c1e520de3207f3401d76ba..011b3c86438a7dddb6a139ac9b03146d1a4a5bc7 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl
@@ -75,10 +75,16 @@ vec4 applyWaterFogView(vec3 pos, vec4 color)
 
 vec4 applyWaterFogViewLinear(vec3 pos, vec4 color)
 {
+    if (dot(pos, waterPlane.xyz) + waterPlane.w > 0.0)
+    {
+        return color;
+    }
+
     vec3 view = normalize(pos);
     //normalize view vector
     float es = -(dot(view, waterPlane.xyz));
 
+    
     //find intersection point with water plane and eye vector
 
     //get eye depth
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
index b51583de26f6b1a8d83af4bc4d598a1f0588807e..d485379a560bc256f041e4aa3ab61c74a3c41f61 100644
--- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -22,40 +22,22 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
+
+//class2/environment/waterF.glsl
+
 #ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
 #else
 #define frag_color gl_FragColor
 #endif
 
-vec3 scaleSoftClipFragLinear(vec3 l);
-vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
-void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
-vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
-
-// PBR interface
-vec3 pbrIbl(vec3 diffuseColor,
-    vec3 specularColor,
-    vec3 radiance, // radiance map sample
-    vec3 irradiance, // irradiance map sample
-    float ao,       // ambient occlusion factor
-    float nv,       // normal dot view vector
-    float perceptualRoughness);
-
-vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
-    float perceptualRoughness,
-    float metallic,
-    vec3 n, // normal
-    vec3 v, // surface point to camera
-    vec3 l); //surface point to light
+vec3 scaleSoftClip(vec3 inColor);
+vec3 atmosTransport(vec3 inColor);
 
 uniform sampler2D bumpMap;
 uniform sampler2D bumpMap2;
 uniform float     blend_factor;
 uniform sampler2D screenTex;
-uniform sampler2D screenDepth;
-
 uniform sampler2D refTex;
 
 uniform float sunAngle;
@@ -70,17 +52,12 @@ uniform vec3 normScale;
 uniform float fresnelScale;
 uniform float fresnelOffset;
 uniform float blurMultiplier;
-uniform vec4 waterFogColor;
 
 
 //bigWave is (refCoord.w, view.w);
 VARYING vec4 refCoord;
 VARYING vec4 littleWave;
 VARYING vec4 view;
-in vec3 vary_position;
-in vec3 vary_normal;
-in vec3 vary_tangent;
-in vec3 vary_light_dir;
 
 vec3 BlendNormal(vec3 bump1, vec3 bump2)
 {
@@ -88,37 +65,15 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2)
     return n;
 }
 
-vec3 srgb_to_linear(vec3 col);
-
-void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
-    vec3 pos, vec3 norm, float glossiness, float envIntensity);
-
-vec3 vN, vT, vB;
-
-vec3 transform_normal(vec3 vNt)
-{
-    return normalize(vNt.x * vT + vNt.y * vB + vNt.z * vN);
-}
-
-void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
-    vec3 pos, vec3 norm, float glossiness);
-
-vec3 getPositionWithNDC(vec3 ndc);
 
 void main() 
 {
 	vec4 color;
-
-    vN = vary_normal;
-    vT = vary_tangent;
-    vB = cross(vN, vT);
-
-    vec3 pos = vary_position.xyz;
-
-	float dist = length(pos.xyz);
+	
+	float dist = length(view.xy);
 	
 	//normalize view vector
-	vec3 viewVec = normalize(pos.xyz);
+	vec3 viewVec = normalize(view.xyz);
 	
 	//get wave normals
     vec2 bigwave = vec2(refCoord.w, view.w);
@@ -126,6 +81,7 @@ void main()
     vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
     vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
 
+
     vec3 wave1_b = texture2D(bumpMap2, bigwave      ).xyz*2.0-1.0;
     vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
     vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
@@ -134,15 +90,6 @@ void main()
     vec3 wave2 = BlendNormal(wave2_a, wave2_b);
     vec3 wave3 = BlendNormal(wave3_a, wave3_b);
 
-    wave1 = transform_normal(wave1);
-    wave2 = transform_normal(wave2);
-    wave3 = transform_normal(wave3);
-
-    vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
-
-    wavef.z *= max(-viewVec.z, 0.1);
-
-    wavef = normalize(wavef);
 
 	//get base fresnel components	
 	
@@ -151,6 +98,7 @@ void main()
 					dot(viewVec, (wave2 + wave3) * 0.5),
 					dot(viewVec, wave3)
 				 ) * fresnelScale + fresnelOffset;
+	df *= df;
 		    
 	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
 	
@@ -161,85 +109,57 @@ void main()
 	
 	vec2 dmod_scale = vec2(dmod*dmod, dmod);
 	
-    float df1 = df.x + df.y + df.z;
-
-    //wavef = normalize(wavef - vary_normal);
-    //wavef = vary_normal;
+	//get reflected color
+	vec2 refdistort1 = wave1.xy*normScale.x;
+	vec2 refvec1 = distort+refdistort1/dmod_scale;
+	vec4 refcol1 = texture2D(refTex, refvec1);
+	
+	vec2 refdistort2 = wave2.xy*normScale.y;
+	vec2 refvec2 = distort+refdistort2/dmod_scale;
+	vec4 refcol2 = texture2D(refTex, refvec2);
+	
+	vec2 refdistort3 = wave3.xy*normScale.z;
+	vec2 refvec3 = distort+refdistort3/dmod_scale;
+	vec4 refcol3 = texture2D(refTex, refvec3);
 
-    vec3 waver = reflect(viewVec, -wavef)*3;
+	vec4 refcol = refcol1 + refcol2 + refcol3;
+	float df1 = df.x + df.y + df.z;
+	refcol *= df1 * 0.333;
+	
+	vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+	
+	wavef.z *= max(-viewVec.z, 0.1);
+	wavef = normalize(wavef);
+	
+	float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
+	
+	vec2 refdistort4 = wavef.xy*0.125;
+	refdistort4.y -= abs(refdistort4.y);
+	vec2 refvec4 = distort+refdistort4/dmod;
+	float dweight = min(dist2*blurMultiplier, 1.0);
+	vec4 baseCol = texture2D(refTex, refvec4);
+	refcol = mix(baseCol*df2, refcol, dweight);
+
+	//get specular component
+	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+		
+	//harden specular
+	spec = pow(spec, 128.0);
 
 	//figure out distortion vector (ripply)   
-    vec2 distort2 = distort + waver.xy * refScale / max(dmod * df1, 1.0);
-    distort2 = clamp(distort2, vec2(0), vec2(0.99));
- 
-    vec4 fb = texture2D(screenTex, distort2);
-    float depth = texture2D(screenDepth, distort2).r;
-    vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0));
-
-#if 1
-    if (refPos.z > pos.z-0.05)
-    {
-        //we sampled an above water sample, don't distort
-        distort2 = distort;
-        fb = texture2D(screenTex, distort2);
-        depth = texture2D(screenDepth, distort2).r;
-        refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
-    }
-#endif
-
-    fb = applyWaterFogViewLinear(refPos, fb);
-
-    vec3 sunlit;
-    vec3 amblit;
-    vec3 additive;
-    vec3 atten;
-
-    calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
-    sunlit = vec3(1); // TODO -- figure out why sunlit is breaking at some view angles
-    vec3 v = -viewVec;
-    float NdotV = clamp(abs(dot(wavef.xyz, v)), 0.001, 1.0);
-
-    float metallic = fresnelOffset * 0.1; // fudge -- use fresnelOffset as metalness
-    float roughness = 0.1;
-    float gloss = 1.0 - roughness;
-
-    vec3 baseColor = vec3(0.25);
-    vec3 f0 = vec3(0.04);
-    vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
-    diffuseColor *= gloss;
-
-    vec3 specularColor = mix(f0, baseColor.rgb, metallic);
-
-    vec3 refnorm = normalize(wavef + vary_normal);
-    //vec3 refnorm = wavef;
-    
-   
-    vec3 irradiance = vec3(0);
-    vec3 radiance = vec3(0);
-    sampleReflectionProbes(irradiance, radiance, pos, refnorm, gloss);
-    radiance *= 0.5;
-    irradiance = fb.rgb;
-
-    color.rgb = pbrIbl(diffuseColor, specularColor, radiance, irradiance, gloss, NdotV, 0.0);
-    
-    // fudge -- for punctual lighting, pretend water is metallic
-    diffuseColor = vec3(0);
-    specularColor = vec3(1);
-    roughness = 0.1;
-    float scol = 1.0; // TODO -- incorporate shadow map
-
-    color.rgb += pbrPunctual(diffuseColor, specularColor, roughness, metallic, wavef, v, vary_light_dir) * sunlit * 2.75 * scol;
-	color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
-	color.rgb = scaleSoftClipFragLinear(color.rgb);
-
-    color.a = 0.f;
-    //color.rgb = fb.rgb;
-    //color.rgb = vec3(depth*depth*depth*depth);
-    //color.rgb = srgb_to_linear(normalize(refPos) * 0.5 + 0.5);
-    //color.rgb = srgb_to_linear(normalize(pos) * 0.5 + 0.5);
-    //color.rgb = srgb_to_linear(wavef * 0.5 + 0.5);
-
-    //color.rgb = radiance;
+	vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+		
+	vec4 fb = texture2D(screenTex, distort2);
+	
+	//mix with reflection
+	// Note we actually want to use just df1, but multiplying by 0.999999 gets around and nvidia compiler bug
+	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999);
+	color.rgb += spec * specular;
+	
+	color.rgb = atmosTransport(color.rgb);
+	color.rgb = scaleSoftClip(color.rgb);
+	color.a = spec * sunAngle2;
+	
 	frag_color = color;
 
 #if defined(WATER_EDGE)
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index e5ffe55163cbafd17bc1d63bbafc7e0e457902fe..eea497bce58b77cc8437dd378511efa2a3692818 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -86,7 +86,7 @@ vec3 linear_to_srgb(vec3 c);
 vec3 srgb_to_linear(vec3 c);
 
 #ifdef WATER_FOG
-vec4 applyWaterFogView(vec3 pos, vec4 color);
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
 #endif
 
 // PBR interface
@@ -236,7 +236,7 @@ void main()
     }
 
     #ifdef WATER_FOG
-        vec4 fogged = applyWaterFogView(pos.xyz, vec4(color, bloom));
+        vec4 fogged = applyWaterFogViewLinear(pos.xyz, vec4(color, bloom));
         color       = fogged.rgb;
     #endif
 
diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..819e6dcf15ab956bbbfc15baaba32bc06f1f8ee4
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl
@@ -0,0 +1,74 @@
+/**
+ * @file class3\environment\underWaterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+ 
+out vec4 frag_color;
+
+uniform sampler2D diffuseMap;
+uniform sampler2D bumpMap;   
+uniform sampler2D screenTex;
+uniform sampler2D refTex;
+uniform sampler2D screenDepth;
+
+uniform vec4 fogCol;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform vec2 fbScale;
+uniform float refScale;
+uniform float znear;
+uniform float zfar;
+uniform float kd;
+uniform vec4 waterPlane;
+uniform vec3 eyeVec;
+uniform vec4 waterFogColor;
+uniform float waterFogKS;
+uniform vec2 screenRes;
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+in vec3 vary_position;
+
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
+
+void main() 
+{
+	vec4 color;
+	    
+	//get detail normals
+	vec3 wave1 = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+	vec3 wave2 = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+	vec3 wave3 = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;    
+	vec3 wavef = normalize(wave1+wave2+wave3);
+	
+	//figure out distortion vector (ripply)   
+	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+	distort = distort+wavef.xy*refScale;
+		
+	vec4 fb = texture2D(screenTex, distort);
+	
+	frag_color = applyWaterFogViewLinear(vary_position, fb);
+}
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..4c361884a5edbdc1e0091aa575a4d8a66d572504
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -0,0 +1,258 @@
+/** 
+ * @file waterF.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+ 
+// class3/environment/waterF.glsl
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+vec3 scaleSoftClipFragLinear(vec3 l);
+vec3 atmosFragLightingLinear(vec3 light, vec3 additive, vec3 atten);
+void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 atten, out vec3 additive);
+vec4 applyWaterFogViewLinear(vec3 pos, vec4 color);
+
+// PBR interface
+vec3 pbrIbl(vec3 diffuseColor,
+    vec3 specularColor,
+    vec3 radiance, // radiance map sample
+    vec3 irradiance, // irradiance map sample
+    float ao,       // ambient occlusion factor
+    float nv,       // normal dot view vector
+    float perceptualRoughness);
+
+vec3 pbrPunctual(vec3 diffuseColor, vec3 specularColor,
+    float perceptualRoughness,
+    float metallic,
+    vec3 n, // normal
+    vec3 v, // surface point to camera
+    vec3 l); //surface point to light
+
+uniform sampler2D bumpMap;
+uniform sampler2D bumpMap2;
+uniform float     blend_factor;
+uniform sampler2D screenTex;
+uniform sampler2D screenDepth;
+
+uniform sampler2D refTex;
+
+uniform float sunAngle;
+uniform float sunAngle2;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform float refScale;
+uniform float kd;
+uniform vec2 screenRes;
+uniform vec3 normScale;
+uniform float fresnelScale;
+uniform float fresnelOffset;
+uniform float blurMultiplier;
+uniform vec4 waterFogColor;
+
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+in vec3 vary_position;
+in vec3 vary_normal;
+in vec3 vary_tangent;
+in vec3 vary_light_dir;
+
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+    vec3 n = mix(bump1, bump2, blend_factor);
+    return n;
+}
+
+vec3 srgb_to_linear(vec3 col);
+
+void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
+    vec3 pos, vec3 norm, float glossiness, float envIntensity);
+
+vec3 vN, vT, vB;
+
+vec3 transform_normal(vec3 vNt)
+{
+    return normalize(vNt.x * vT + vNt.y * vB + vNt.z * vN);
+}
+
+void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
+    vec3 pos, vec3 norm, float glossiness);
+
+vec3 getPositionWithNDC(vec3 ndc);
+
+void main() 
+{
+	vec4 color;
+
+    vN = vary_normal;
+    vT = vary_tangent;
+    vB = cross(vN, vT);
+
+    vec3 pos = vary_position.xyz;
+
+	float dist = length(pos.xyz);
+	
+	//normalize view vector
+	vec3 viewVec = normalize(pos.xyz);
+	
+	//get wave normals
+    vec2 bigwave = vec2(refCoord.w, view.w);
+    vec3 wave1_a = texture(bumpMap, bigwave, -2      ).xyz*2.0-1.0;
+    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1_b = texture(bumpMap2, bigwave      ).xyz*2.0-1.0;
+    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+    wave1 = transform_normal(wave1);
+    wave2 = transform_normal(wave2);
+    wave3 = transform_normal(wave3);
+
+    vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+
+    //wavef.z *= max(-viewVec.z, 0.1);
+
+    wavef = normalize(wavef);
+
+	//get base fresnel components	
+	
+	vec3 df = vec3(
+					dot(viewVec, wave1),
+					dot(viewVec, (wave2 + wave3) * 0.5),
+					dot(viewVec, wave3)
+				 ) * fresnelScale + fresnelOffset;
+		    
+	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+	
+	float dist2 = dist;
+	dist = max(dist, 5.0);
+	
+	float dmod = sqrt(dist);
+	
+	vec2 dmod_scale = vec2(dmod*dmod, dmod);
+	
+    float df1 = df.x + df.y + df.z;
+
+    //wavef = normalize(wavef - vary_normal);
+    //wavef = vary_normal;
+
+    vec3 waver = reflect(viewVec, -wavef)*3;
+
+	//figure out distortion vector (ripply)   
+    vec2 distort2 = distort + waver.xy * refScale / max(dmod * df1, 1.0);
+    distort2 = clamp(distort2, vec2(0), vec2(0.99));
+ 
+    vec4 fb = texture2D(screenTex, distort2);
+    float depth = texture2D(screenDepth, distort2).r;
+    vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0));
+
+    if (refPos.z > pos.z-0.05)
+    {
+        //we sampled an above water sample, don't distort
+        distort2 = distort;
+        fb = texture2D(screenTex, distort2);
+        depth = texture2D(screenDepth, distort2).r;
+        refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0));
+    }
+
+    fb = applyWaterFogViewLinear(refPos, fb);
+
+    vec3 sunlit;
+    vec3 amblit;
+    vec3 additive;
+    vec3 atten;
+
+    calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
+    sunlit = vec3(1); // TODO -- figure out why sunlit is breaking at some view angles
+    vec3 v = -viewVec;
+    float NdotV = clamp(abs(dot(wavef.xyz, v)), 0.001, 1.0);
+
+    float metallic = fresnelOffset * 0.1; // fudge -- use fresnelOffset as metalness
+    float roughness = 0.1;
+    float gloss = 1.0 - roughness;
+
+    vec3 baseColor = vec3(0.25);
+    vec3 f0 = vec3(0.04);
+    vec3 diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
+    diffuseColor *= gloss;
+
+    vec3 specularColor = mix(f0, baseColor.rgb, metallic);
+
+    vec3 refnorm = normalize(wavef + vary_normal);
+    //vec3 refnorm = wavef;
+    
+    vec3 irradiance = vec3(0);
+    vec3 radiance = vec3(0);
+    sampleReflectionProbes(irradiance, radiance, pos, refnorm, gloss);
+    radiance *= 0.5;
+    irradiance = fb.rgb;
+
+    color.rgb = pbrIbl(diffuseColor, specularColor, radiance, irradiance, gloss, NdotV, 0.0);
+    
+    // fudge -- for punctual lighting, pretend water is metallic
+    diffuseColor = vec3(0);
+    specularColor = vec3(1);
+    roughness = 0.1;
+    float scol = 1.0; // TODO -- incorporate shadow map
+
+    //color.rgb += pbrPunctual(diffuseColor, specularColor, roughness, metallic, wavef, v, vary_light_dir) * sunlit * 2.75 * scol;
+
+    //get specular component
+    float spec = clamp(dot(vary_light_dir, (reflect(viewVec, wavef))), 0.0, 1.0);
+
+    //harden specular
+    spec = pow(spec, 128.0);
+
+    color.rgb += spec * specular;
+
+	color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
+	color.rgb = scaleSoftClipFragLinear(color.rgb);
+
+    color.a = 0.f;
+    //color.rgb = fb.rgb;
+    //color.rgb = vec3(depth*depth*depth*depth);
+    //color.rgb = srgb_to_linear(normalize(refPos) * 0.5 + 0.5);
+    //color.rgb = srgb_to_linear(normalize(pos) * 0.5 + 0.5);
+    //color.rgb = srgb_to_linear(wavef * 0.5 + 0.5);
+
+    //color.rgb = radiance;
+	frag_color = color;
+
+#if defined(WATER_EDGE)
+    gl_FragDepth = 0.9999847f;
+#endif
+	
+}
+
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 05978e1144be5735bfe883a85e7431b9d93eed48..d4c93eec06747bd63a487e221b2e7f9dc82ff416 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -505,7 +505,7 @@ void LLViewerShaderMgr::setShaders()
     S32 obj_class = 2;
     S32 effect_class = 2;
     S32 wl_class = 1;
-    S32 water_class = 2;
+    S32 water_class = 3;
     S32 deferred_class = 0;
 
     if (useRenderDeferred)