diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 8807433d8064ac43249c54021daa90f4e58eea4a..a363eac59e777fff389d9970d89adda80ecd620d 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -214,7 +214,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
 	}
 
     // we want this BEFORE shadows and AO because those facilities use pos/norm access
-    if (features->isDeferred)
+    if (features->isDeferred || features->hasReflectionProbes)
 	{
         if (!shader->attachFragmentObject("deferred/deferredUtil.glsl"))
 		{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 39baa23778fbfb0e62ade4053648d808f178726e..bfc41e315304ab11729c8ff56ea7e1c23249ab0e 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -1688,6 +1688,14 @@ set_source_files_properties(${viewer_XUI_FILES}
 
 list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES})
 
+file(GLOB_RECURSE viewer_SHADER_FILES LIST_DIRECTORIES TRUE
+    ${CMAKE_CURRENT_SOURCE_DIR}/app_settings/shaders/*.glsl)
+source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/app_settings/shaders PREFIX "Shaders" FILES ${viewer_SHADER_FILES})
+set_source_files_properties(${viewer_SHADER_FILES} 
+                            PROPERTIES HEADER_FILE_ONLY TRUE)
+list(APPEND viewer_SOURCE_FILES ${viewer_SHADER_FILES})
+
+
 set(viewer_APPSETTINGS_FILES
     app_settings/anim.ini
     app_settings/cmd_line.xml
diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
index 58a444a76337d759239017d5cb97f74cada54fe2..876422f86b39cd5ba41208d851bfb53145903a7d 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl
@@ -22,170 +22,15 @@
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
-#extension GL_ARB_texture_rectangle : enable
 
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
+// debug stub
 out vec4 frag_data[4];
-#else
-#define frag_data gl_FragData
-#endif
-
-vec3 scaleSoftClip(vec3 inColor);
-vec3 atmosTransport(vec3 inColor);
-
-uniform sampler2D bumpMap;   
-uniform sampler2D bumpMap2;
-uniform float blend_factor;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-uniform float sunAngle;
-uniform float sunAngle2;
-uniform vec3 lightDir;
-uniform vec3 specular;
-uniform float lightExp;
-uniform float refScale;
-uniform float kd;
-uniform vec2 screenRes;
-uniform vec3 normScale;
-uniform float fresnelScale;
-uniform float fresnelOffset;
-uniform float blurMultiplier;
-uniform vec2 screen_res;
-uniform mat4 norm_mat; //region space to screen space
-uniform int water_edge;
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-VARYING vec4 vary_position;
-
-vec2 encode_normal(vec3 n);
-vec3 scaleSoftClip(vec3 l);
-vec3 srgb_to_linear(vec3 c);
-vec3 linear_to_srgb(vec3 c);
 
-vec3 BlendNormal(vec3 bump1, vec3 bump2)
+void main()
 {
-    vec3 n = mix(bump1, bump2, blend_factor);
-    return n;
-}
-
-void main() 
-{
-    vec4 color;
-    float dist = length(view.xyz);
-    
-    //normalize view vector
-    vec3 viewVec = normalize(view.xyz);
-    
-    //get wave normals
-    vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
-    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
-    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-
-
-    vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
-    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
-    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
-
-    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
-    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
-    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
-
-    //get base fresnel components   
-    
-    vec3 df = vec3(
-                    dot(viewVec, wave1),
-                    dot(viewVec, (wave2 + wave3) * 0.5),
-                    dot(viewVec, wave3)
-                 ) * fresnelScale + fresnelOffset;
-    df *= df;
-            
-    vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-    
-    float dist2 = dist;
-    dist = max(dist, 5.0);
-    
-    float dmod = sqrt(dist);
-    
-    vec2 dmod_scale = vec2(dmod*dmod, dmod);
-    
-    //get reflected color
-    vec2 refdistort1 = wave1.xy*normScale.x;
-    vec2 refvec1 = distort+refdistort1/dmod_scale;
-    vec4 refcol1 = texture2D(refTex, refvec1);
-    
-    vec2 refdistort2 = wave2.xy*normScale.y;
-    vec2 refvec2 = distort+refdistort2/dmod_scale;
-    vec4 refcol2 = texture2D(refTex, refvec2);
-    
-    vec2 refdistort3 = wave3.xy*normScale.z;
-    vec2 refvec3 = distort+refdistort3/dmod_scale;
-    vec4 refcol3 = texture2D(refTex, refvec3);
-
-    vec4 refcol = refcol1 + refcol2 + refcol3;
-    float df1 = df.x + df.y + df.z;
-	refcol *= df1 * 0.333;
-    
-    vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
-    wavef.z *= max(-viewVec.z, 0.1);
-    wavef = normalize(wavef);
-    
-    float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-    
-    vec2 refdistort4 = wavef.xy*0.125;
-    refdistort4.y -= abs(refdistort4.y);
-    vec2 refvec4 = distort+refdistort4/dmod;
-    float dweight = min(dist2*blurMultiplier, 1.0);
-    vec4 baseCol = texture2D(refTex, refvec4);
-
-    refcol = mix(baseCol*df2, refcol, dweight);
-
-    //get specular component
-	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
-		
-	//harden specular
-	spec = pow(spec, 128.0);
-
-	//figure out distortion vector (ripply)   
-	vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
-		
-	vec4 fb = texture2D(screenTex, distort2);
-	
-	//mix with reflection
-	// Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
-	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999f);
-	
-	vec4 pos = vary_position;
-	
-	//color.rgb += spec * specular;
-
-	//color.rgb = atmosTransport(color.rgb);
-	//color.rgb = scaleSoftClip(color.rgb);
-    
-    //color.rgb = refcol.rgb;
-    color.rgb = vec3(0.0);
-	color.a   = spec * sunAngle2;
-    
-	vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
-
-	//frag_data[0] = color;
-
-    // TODO: The non-obvious assignment below is copied from the pre-EEP WL shader code
-    //       Unfortunately, fixing it causes a mismatch for EEP, and so it remains...  for now
-    //       SL-12975 (unfix pre-EEP broken alpha)
-    frag_data[0] = vec4(srgb_to_linear(color.rgb), 0.0);
-    
-    frag_data[1] = vec4(1.0, 0.1, 0.0, 0.0);		// occlusion, roughness, metalness
-	frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.0, GBUFFER_FLAG_HAS_PBR);// normalxy, env intens, flags (atmo kill)
-    frag_data[3] = vec4(srgb_to_linear(refcol.rgb),0);
-
-    
-    //frag_data[0] = vec4(0.0,0,0,0);
-    //frag_data[1] = vec4(0, 1.0, 0.0, 0.0);
-    //frag_data[3] = vec4(0);
+    // emissive blue PBR material
+    frag_data[0] = vec4(0, 0, 0, 0);
+    frag_data[1] = vec4(0, 0, 0, 0);
+    frag_data[2] = vec4(1, 0, 0, GBUFFER_FLAG_HAS_PBR);
+    frag_data[3] = vec4(0, 0, 1, 0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
index d37099712354ccb98865ac4b14bf28d7e9fe410a..46a6c2021d9def0b97ab7a1f2be9dc135ed44e04 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl
@@ -23,146 +23,9 @@
  * $/LicenseInfo$
  */
  
-#ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
 
-vec3 scaleSoftClip(vec3 inColor);
-vec3 atmosTransport(vec3 inColor);
-
-uniform sampler2D bumpMap;
-uniform sampler2D bumpMap2;
-uniform float     blend_factor;
-uniform sampler2D screenTex;
-uniform sampler2D refTex;
-
-uniform 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;
-
-
-//bigWave is (refCoord.w, view.w);
-VARYING vec4 refCoord;
-VARYING vec4 littleWave;
-VARYING vec4 view;
-
-vec3 BlendNormal(vec3 bump1, vec3 bump2)
+void main()
 {
-    vec3 n = mix(bump1, bump2, blend_factor);
-    return n;
+    frag_color = vec4(0, 0, 1, 0);
 }
-
-
-void main() 
-{
-	vec4 color;
-	
-	float dist = length(view.xy);
-	
-	//normalize view vector
-	vec3 viewVec = normalize(view.xyz);
-	
-	//get wave normals
-    vec2 bigwave = vec2(refCoord.w, view.w);
-    vec3 wave1_a = texture2D(bumpMap, bigwave      ).xyz*2.0-1.0;
-    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
-    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
-
-
-    vec3 wave1_b = texture2D(bumpMap2, bigwave      ).xyz*2.0-1.0;
-    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
-    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
-
-    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
-    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
-    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
-
-
-	//get base fresnel components	
-	
-	vec3 df = vec3(
-					dot(viewVec, wave1),
-					dot(viewVec, (wave2 + wave3) * 0.5),
-					dot(viewVec, wave3)
-				 ) * fresnelScale + fresnelOffset;
-	df *= df;
-		    
-	vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
-	
-	float dist2 = dist;
-	dist = max(dist, 5.0);
-	
-	float dmod = sqrt(dist);
-	
-	vec2 dmod_scale = vec2(dmod*dmod, dmod);
-	
-	//get reflected color
-	vec2 refdistort1 = wave1.xy*normScale.x;
-	vec2 refvec1 = distort+refdistort1/dmod_scale;
-	vec4 refcol1 = texture2D(refTex, refvec1);
-	
-	vec2 refdistort2 = wave2.xy*normScale.y;
-	vec2 refvec2 = distort+refdistort2/dmod_scale;
-	vec4 refcol2 = texture2D(refTex, refvec2);
-	
-	vec2 refdistort3 = wave3.xy*normScale.z;
-	vec2 refvec3 = distort+refdistort3/dmod_scale;
-	vec4 refcol3 = texture2D(refTex, refvec3);
-
-	vec4 refcol = refcol1 + refcol2 + refcol3;
-	float df1 = df.x + df.y + df.z;
-	refcol *= df1 * 0.333;
-	
-	vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
-	
-	wavef.z *= max(-viewVec.z, 0.1);
-	wavef = normalize(wavef);
-	
-	float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
-	
-	vec2 refdistort4 = wavef.xy*0.125;
-	refdistort4.y -= abs(refdistort4.y);
-	vec2 refvec4 = distort+refdistort4/dmod;
-	float dweight = min(dist2*blurMultiplier, 1.0);
-	vec4 baseCol = texture2D(refTex, refvec4);
-	refcol = mix(baseCol*df2, refcol, dweight);
-
-	//get specular component
-	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
-		
-	//harden specular
-	spec = pow(spec, 128.0);
-
-	//figure out distortion vector (ripply)   
-	vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
-		
-	vec4 fb = texture2D(screenTex, distort2);
-	
-	//mix with reflection
-	// Note we actually want to use just df1, but multiplying by 0.999999 gets around 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)
-    gl_FragDepth = 0.9999847f;
-#endif
-	
-}
-
diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
index cc41e3f740df6d9076d8de788ad30c8240b6acd9..e95f268681dfb97ffa9608e8552e52751a83c7df 100644
--- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl
@@ -24,6 +24,7 @@
  */
 
 uniform mat4 modelview_matrix;
+uniform mat3 normal_matrix;
 uniform mat4 modelview_projection_matrix;
 
 ATTRIBUTE vec3 position;
@@ -36,10 +37,15 @@ uniform vec2 waveDir2;
 uniform float time;
 uniform vec3 eyeVec;
 uniform float waterHeight;
+uniform vec3 lightDir;
 
 VARYING vec4 refCoord;
 VARYING vec4 littleWave;
 VARYING vec4 view;
+out vec3 vary_position;
+out vec3 vary_light_dir;
+out vec3 vary_tangent;
+out vec3 vary_normal;
 
 float wave(vec2 v, float t, float f, vec2 d, float s) 
 {
@@ -52,6 +58,11 @@ void main()
 	vec4 pos = vec4(position.xyz, 1.0);
 	mat4 modelViewProj = modelview_projection_matrix;
 	
+    vary_position = (modelview_matrix * pos).xyz;
+    vary_light_dir = normal_matrix * lightDir;
+    vary_normal = normal_matrix * vec3(0, 0, 1);
+    vary_tangent = normal_matrix * vec3(1, 0, 0);
+
 	vec4 oPosition;
 		    
 	//get view vector
@@ -63,12 +74,13 @@ void main()
 	
 	pos.xy = eyeVec.xy + oEyeVec.xy/d*ld;
 	view.xyz = oEyeVec;
-		
+
 	d = clamp(ld/1536.0-0.5, 0.0, 1.0);	
 	d *= d;
 		
 	oPosition = vec4(position, 1.0);
 	oPosition.z = mix(oPosition.z, max(eyeVec.z*0.75, 0.0), d);
+
 	oPosition = modelViewProj * oPosition;
 	
 	refCoord.xyz = oPosition.xyz + vec3(0,0,0.2);
@@ -83,8 +95,7 @@ void main()
 	pos = modelview_matrix*pos;
 	
 	calcAtmospherics(pos.xyz);
-	
-	
+		
 	//pass wave parameters to pixel shader
 	vec2 bigWave =  (v.xy) * vec2(0.04,0.04)  + waveDir1 * time * 0.055;
 	//get two normal map (detail map) texture coordinates
diff --git a/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..96739d91d7856b54bf4695ed073ad5d1d43d1476
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/deferred/waterF.glsl
@@ -0,0 +1,192 @@
+/** 
+ * @file class1/deferred/waterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+ 
+#extension GL_ARB_texture_rectangle : enable
+
+/*[EXTRA_CODE_HERE]*/
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[4];
+#else
+#define frag_data gl_FragData
+#endif
+
+vec3 scaleSoftClip(vec3 inColor);
+vec3 atmosTransport(vec3 inColor);
+
+uniform sampler2D bumpMap;   
+uniform sampler2D bumpMap2;
+uniform float blend_factor;
+uniform sampler2D screenTex;
+uniform sampler2D refTex;
+uniform float sunAngle;
+uniform float sunAngle2;
+uniform vec3 lightDir;
+uniform vec3 specular;
+uniform float lightExp;
+uniform float refScale;
+uniform float kd;
+uniform vec2 screenRes;
+uniform vec3 normScale;
+uniform float fresnelScale;
+uniform float fresnelOffset;
+uniform float blurMultiplier;
+uniform vec2 screen_res;
+uniform mat4 norm_mat; //region space to screen space
+uniform int water_edge;
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+VARYING vec4 vary_position;
+
+vec2 encode_normal(vec3 n);
+vec3 scaleSoftClip(vec3 l);
+vec3 srgb_to_linear(vec3 c);
+vec3 linear_to_srgb(vec3 c);
+
+vec3 BlendNormal(vec3 bump1, vec3 bump2)
+{
+    vec3 n = mix(bump1, bump2, blend_factor);
+    return n;
+}
+
+void main() 
+{
+    vec4 color;
+    float dist = length(view.xyz);
+    
+    //normalize view vector
+    vec3 viewVec = normalize(view.xyz);
+    
+    //get wave normals
+    vec3 wave1_a = texture2D(bumpMap, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+    vec3 wave1_b = texture2D(bumpMap2, vec2(refCoord.w, view.w)).xyz*2.0-1.0;
+    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+    //get base fresnel components   
+    
+    vec3 df = vec3(
+                    dot(viewVec, wave1),
+                    dot(viewVec, (wave2 + wave3) * 0.5),
+                    dot(viewVec, wave3)
+                 ) * fresnelScale + fresnelOffset;
+    df *= df;
+            
+    vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5;
+    
+    float dist2 = dist;
+    dist = max(dist, 5.0);
+    
+    float dmod = sqrt(dist);
+    
+    vec2 dmod_scale = vec2(dmod*dmod, dmod);
+    
+    //get reflected color
+    vec2 refdistort1 = wave1.xy*normScale.x;
+    vec2 refvec1 = distort+refdistort1/dmod_scale;
+    vec4 refcol1 = texture2D(refTex, refvec1);
+    
+    vec2 refdistort2 = wave2.xy*normScale.y;
+    vec2 refvec2 = distort+refdistort2/dmod_scale;
+    vec4 refcol2 = texture2D(refTex, refvec2);
+    
+    vec2 refdistort3 = wave3.xy*normScale.z;
+    vec2 refvec3 = distort+refdistort3/dmod_scale;
+    vec4 refcol3 = texture2D(refTex, refvec3);
+
+    vec4 refcol = refcol1 + refcol2 + refcol3;
+    float df1 = df.x + df.y + df.z;
+	refcol *= df1 * 0.333;
+    
+    vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5;
+    wavef.z *= max(-viewVec.z, 0.1);
+    wavef = normalize(wavef);
+    
+    float df2 = dot(viewVec, wavef) * fresnelScale+fresnelOffset;
+    
+    vec2 refdistort4 = wavef.xy*0.125;
+    refdistort4.y -= abs(refdistort4.y);
+    vec2 refvec4 = distort+refdistort4/dmod;
+    float dweight = min(dist2*blurMultiplier, 1.0);
+    vec4 baseCol = texture2D(refTex, refvec4);
+
+    refcol = mix(baseCol*df2, refcol, dweight);
+
+    //get specular component
+	float spec = clamp(dot(lightDir, (reflect(viewVec,wavef))),0.0,1.0);
+		
+	//harden specular
+	spec = pow(spec, 128.0);
+
+	//figure out distortion vector (ripply)   
+	vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+		
+	vec4 fb = texture2D(screenTex, distort2);
+	
+	//mix with reflection
+	// Note we actually want to use just df1, but multiplying by 0.999999 gets around an nvidia compiler bug
+	color.rgb = mix(fb.rgb, refcol.rgb, df1 * 0.99999f);
+	
+	vec4 pos = vary_position;
+	
+	//color.rgb += spec * specular;
+
+	//color.rgb = atmosTransport(color.rgb);
+	//color.rgb = scaleSoftClip(color.rgb);
+    
+    //color.rgb = refcol.rgb;
+    color.rgb = vec3(0.0);
+	color.a   = spec * sunAngle2;
+    
+	vec3 screenspacewavef = normalize((norm_mat*vec4(wavef, 1.0)).xyz);
+
+	//frag_data[0] = color;
+
+    // TODO: The non-obvious assignment below is copied from the pre-EEP WL shader code
+    //       Unfortunately, fixing it causes a mismatch for EEP, and so it remains...  for now
+    //       SL-12975 (unfix pre-EEP broken alpha)
+    frag_data[0] = vec4(srgb_to_linear(color.rgb), 0.0);
+    
+    frag_data[1] = vec4(1.0, 0.1, 0.0, 0.0);		// occlusion, roughness, metalness
+	frag_data[2] = vec4(encode_normal(screenspacewavef.xyz), 0.0, GBUFFER_FLAG_HAS_PBR);// normalxy, env intens, flags (atmo kill)
+    //frag_data[3] = vec4(srgb_to_linear(refcol.rgb),0);
+    frag_data[3] = vec4(0, 0, 0, 0);
+
+    
+    //frag_data[0] = vec4(0.0,0,0,0);
+    //frag_data[1] = vec4(0, 1.0, 0.0, 0.0);
+    //frag_data[3] = vec4(0);
+}
diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
new file mode 100644
index 0000000000000000000000000000000000000000..2e7efa9b2a8dfb15ece9124d0500d2356a2d70fe
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl
@@ -0,0 +1,237 @@
+/** 
+ * @file waterF.glsl
+ *
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2007, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+ 
+#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);
+
+// 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 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);
+
+void main() 
+{
+	vec4 color;
+
+    vN = vary_normal;
+    vT = vary_tangent;
+    vB = cross(vN, vT);
+
+    vec3 pos = vary_position.xyz;
+
+	float dist = length(view.xy);
+	
+	//normalize view vector
+	vec3 viewVec = normalize(pos.xyz);
+	
+	//get wave normals
+    vec2 bigwave = vec2(refCoord.w, view.w);
+    vec3 wave1_a = texture2D(bumpMap, bigwave      ).xyz*2.0-1.0;
+    vec3 wave2_a = texture2D(bumpMap, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_a = texture2D(bumpMap, littleWave.zw).xyz*2.0-1.0;
+
+
+    vec3 wave1_b = texture2D(bumpMap2, bigwave      ).xyz*2.0-1.0;
+    vec3 wave2_b = texture2D(bumpMap2, littleWave.xy).xyz*2.0-1.0;
+    vec3 wave3_b = texture2D(bumpMap2, littleWave.zw).xyz*2.0-1.0;
+
+    vec3 wave1 = BlendNormal(wave1_a, wave1_b);
+    vec3 wave2 = BlendNormal(wave2_a, wave2_b);
+    vec3 wave3 = BlendNormal(wave3_a, wave3_b);
+
+    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;
+
+    vec4 refcol = vec4(0, 0, 0, 0);
+
+	//get specular component
+	float spec = clamp(dot(vary_light_dir, (reflect(viewVec,wavef))),0.0,1.0);
+		
+	//harden specular
+	spec = pow(spec, 128.0);
+
+	//figure out distortion vector (ripply)   
+	//vec2 distort2 = distort+wavef.xy*refScale/max(dmod*df1, 1.0);
+		
+	//vec4 fb = texture2D(screenTex, distort2);
+
+    vec3 sunlit;
+    vec3 amblit;
+    vec3 additive;
+    vec3 atten;
+
+    calcAtmosphericVarsLinear(pos.xyz, wavef, lightDir, sunlit, amblit, additive, atten);
+    
+    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.08;
+    float gloss = 1.0 - roughness;
+
+    vec3 baseColor = vec3(0);
+    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 irradiance = vec3(0);
+    vec3 radiance = vec3(0);
+    sampleReflectionProbes(irradiance, radiance, pos, refnorm, gloss);
+    
+    // fudge -- use refracted color as irradiance
+    irradiance = srgb_to_linear(waterFogColor.rgb);
+
+    color.rgb = pbrIbl(diffuseColor, specularColor, radiance, irradiance, gloss, NdotV, 0.0);
+
+    //vec4 fb = waterFogColor;
+    //fb.rgb = srgb_to_linear(fb.rgb);
+	
+    //refcol.rgb = vec3(0, 1, 0);
+
+	//mix with reflection
+	//color.rgb = mix(fb.rgb, refcol.rgb, df1);
+	
+    //color.rgb += spec * specular;
+
+    // fudge -- for punctual lighting, pretend water is metallic
+    diffuseColor = vec3(0);
+    specularColor = vec3(1);
+    roughness = 0.1;
+    color.rgb += pbrPunctual(diffuseColor, specularColor, roughness, metallic, wavef, v, vary_light_dir);
+	color.rgb = atmosFragLightingLinear(color.rgb, additive, atten);
+	color.rgb = scaleSoftClipFragLinear(color.rgb);
+
+    color.a = 0.f;
+
+	//color.a = spec * sunAngle2;
+
+    frag_color = color;
+
+#if defined(WATER_EDGE)
+    gl_FragDepth = 0.9999847f;
+#endif
+	
+}
+
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 576024ead3aa3474d7145c7145d45f2439ce4936..23de00e3a4371beadf900bce6ea89f95f2991e37 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -117,16 +117,20 @@ S32 LLDrawPoolWater::getNumPasses()
 	return 0;
 }
 
-void LLDrawPoolWater::beginPostDeferredPass(S32 pass)
+S32 LLDrawPoolWater::getNumPostDeferredPasses()
 {
-	beginRenderPass(pass);
-	deferred_render = TRUE;
+    return 1;
 }
 
-void LLDrawPoolWater::endPostDeferredPass(S32 pass)
+void LLDrawPoolWater::renderPostDeferred(S32 pass) 
 {
-	endRenderPass(pass);
-	deferred_render = FALSE;
+    renderWater();
+}
+
+
+S32 LLDrawPoolWater::getNumDeferredPasses() 
+{ 
+    return 0;
 }
 
 //===============================
@@ -152,6 +156,7 @@ void LLDrawPoolWater::renderDeferred(S32 pass)
 
 void LLDrawPoolWater::render(S32 pass)
 {
+#if 0
 	LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; //LL_RECORD_BLOCK_TIME(FTM_RENDER_WATER);
 	if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1)
 	{
@@ -323,11 +328,13 @@ void LLDrawPoolWater::render(S32 pass)
 		glStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF);
 		renderReflection(refl_face);
 	}
+#endif
 }
 
 // for low end hardware
 void LLDrawPoolWater::renderOpaqueLegacyWater()
 {
+#if 0
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
     LLVOSky *voskyp = gSky.mVOSkyp;
 
@@ -432,11 +439,13 @@ void LLDrawPoolWater::renderOpaqueLegacyWater()
 	}
 
 	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+#endif
 }
 
 
 void LLDrawPoolWater::renderReflection(LLFace* face)
 {
+#if 0
     LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
 	LLVOSky *voskyp = gSky.mVOSkyp;
 
@@ -462,6 +471,7 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
 
 	LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV));
 	face->renderIndexed();
+#endif
 }
 
 void LLDrawPoolWater::renderWater()
@@ -535,7 +545,8 @@ void LLDrawPoolWater::renderWater()
                 shader = deferred_render ? &gDeferredWaterProgram : &gWaterProgram;
             }
         }
-        shader->bind();
+
+        gPipeline.bindDeferredShader(*shader);
 
         // bind textures for water rendering
         S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
@@ -683,7 +694,8 @@ void LLDrawPoolWater::renderWater()
         shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
 
         // clean up
-        shader->unbind();
+        gPipeline.unbindDeferredShader(*shader);
+
         gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
         gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
     }
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index 6f2fc3271dd2fbfa5414a30e750d773083a8479f..e3073018c338efd5747ab76736a99c51902f2826 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -35,7 +35,7 @@ class LLHeavenBody;
 class LLWaterSurface;
 class LLGLSLShader;
 
-class LLDrawPoolWater: public LLFacePool
+class LLDrawPoolWater final: public LLFacePool
 {
 protected:
 	LLPointer<LLViewerTexture> mWaterImagep[2];	
@@ -63,19 +63,17 @@ class LLDrawPoolWater: public LLFacePool
 
 	static void restoreGL();
 	
-	/*virtual*/ S32 getNumPostDeferredPasses() { return 0; } //getNumPasses(); }
-	/*virtual*/ void beginPostDeferredPass(S32 pass);
-	/*virtual*/ void endPostDeferredPass(S32 pass);
-	/*virtual*/ void renderPostDeferred(S32 pass) { render(pass); }
-	/*virtual*/ S32 getNumDeferredPasses() { return 1; }
-	/*virtual*/ void renderDeferred(S32 pass = 0);
-
-	/*virtual*/ S32 getNumPasses();
-	/*virtual*/ void render(S32 pass = 0);
-	/*virtual*/ void prerender();
-
-	/*virtual*/ LLViewerTexture *getDebugTexture();
-	/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
+    S32 getNumPostDeferredPasses() override;
+    void renderPostDeferred(S32 pass) override;
+    S32 getNumDeferredPasses() override;
+	void renderDeferred(S32 pass = 0) override;
+
+	S32 getNumPasses() override;
+	void render(S32 pass = 0) override;
+	void prerender() override;
+
+	LLViewerTexture *getDebugTexture();
+	LLColor3 getDebugColor() const; // For AGP debug display
 
 	void renderReflection(LLFace* face);
 	void renderWater();
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 4b2a2a382a5d3c16cfe9b34fbd2594d9bf00092f..cbefb93ca9d659de115af91fc3e8c209e2576713 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -34,6 +34,7 @@
 #include "llviewershadermgr.h"
 #include "llviewercontrol.h"
 #include "llenvironment.h"
+#include "llstartup.h"
 
 extern BOOL gCubeSnapshot;
 extern BOOL gTeleportDisplay;
@@ -63,7 +64,7 @@ struct CompareProbeDistance
 // helper class to seed octree with probes
 void LLReflectionMapManager::update()
 {
-    if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay)
+    if (!LLPipeline::sReflectionProbesEnabled || gTeleportDisplay || LLStartUp::getStartupState() < STATE_PRECACHE)
     {
         return;
     }
@@ -212,7 +213,11 @@ LLReflectionMap* LLReflectionMapManager::addProbe(LLSpatialGroup* group)
 {
     LLReflectionMap* probe = new LLReflectionMap();
     probe->mGroup = group;
-    probe->mOrigin = group->getOctreeNode()->getCenter();
+
+    if (group)
+    {
+        probe->mOrigin = group->getOctreeNode()->getCenter();
+    }
 
     if (gCubeSnapshot)
     { //snapshot is in progress, mProbes is being iterated over, defer insertion until next update
@@ -272,7 +277,9 @@ LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* gr
             return addProbe(group);
         }
     }
-    
+#endif
+
+#if 0
     if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN)
     {
         OctreeNode* node = group->getOctreeNode();
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 493f53efb82d989baef8b5c56a556146a165c3cd..4dcd822677819108ae48df02efc585606cfac688 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -62,7 +62,7 @@ class alignas(16) LLReflectionMapManager
     void update();
 
     // add a probe for the given spatial group
-    LLReflectionMap* addProbe(LLSpatialGroup* group);
+    LLReflectionMap* addProbe(LLSpatialGroup* group = nullptr);
     
     // Populate "maps" with the N most relevant Reflection Maps where N is no more than maps.size()
     // If less than maps.size() ReflectionMaps are available, will assign trailing elements to nullptr.
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 7e1f8db9a882bceca579e4f6b643c7639e99cab8..65f1170eb43f513e3bfc01702831aaf83c6fa175 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1062,11 +1062,9 @@ void display_cube_face()
 
     llassert(!gSnapshot);
     llassert(!gTeleportDisplay);
-    llassert(LLPipeline::sRenderDeferred);
     llassert(LLStartUp::getStartupState() >= STATE_PRECACHE);
     llassert(!LLAppViewer::instance()->logoutRequestSent());
     llassert(!gRestoreGL);
-    llassert(!gUseWireframe);
 
     bool rebuild = false;
 
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 8f56f6110fe4e0decc9fb0526616bf52fcf859be..19f8cc105ea7f142a93e8eb3c5b8266f7526a33f 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -830,6 +830,9 @@ void LLViewerRegion::sendReliableMessage()
 void LLViewerRegion::setWaterHeight(F32 water_level)
 {
 	mImpl->mLandp->setWaterHeight(water_level);
+
+    // reflection probes move with the water height
+    updateReflectionProbes();
 }
 
 F32 LLViewerRegion::getWaterHeight() const
@@ -1233,6 +1236,45 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
 	return mImpl ? mImpl->mVisibleGroups.size() : 0;
 }
 
+void LLViewerRegion::updateReflectionProbes()
+{
+    const F32 probe_spacing = 32.f;
+    const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f);
+    const F32 hover_height = 2.f;
+
+    F32 start = probe_spacing * 0.5f;
+
+    U32 grid_width = REGION_WIDTH_METERS / probe_spacing;
+
+    mReflectionMaps.resize(grid_width * grid_width);
+
+    F32 water_height = getWaterHeight();
+    LLVector3 origin = getOriginAgent();
+
+    for (U32 i = 0; i < grid_width; ++i)
+    {
+        F32 x = i * probe_spacing + start;
+        for (U32 j = 0; j < grid_width; ++j)
+        {
+            F32 y = j * probe_spacing + start;
+
+            U32 idx = i * grid_width + j;
+
+            if (mReflectionMaps[idx].isNull())
+            {
+                mReflectionMaps[idx] = gPipeline.mReflectionMapManager.addProbe();
+            }
+
+            LLVector3 probe_origin = LLVector3(x,y, llmax(water_height, mImpl->mLandp->resolveHeightRegion(x,y)));
+            probe_origin.mV[2] += hover_height;
+            probe_origin += origin;
+
+            mReflectionMaps[idx]->mOrigin.load3(probe_origin.mV);
+            mReflectionMaps[idx]->mRadius = probe_radius;
+        }
+    }
+}
+
 void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry)
 {
 	if(!sVOCacheCullingEnabled)
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index d0fa9fea01423eba16b9f819c67858ce01189f64..250e0236e4579bbb81e02ffcd1f4d1699e8434b7 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -41,6 +41,7 @@
 #include "llcapabilityprovider.h"
 #include "m4math.h"					// LLMatrix4
 #include "llframetimer.h"
+#include "llreflectionmap.h"
 
 // Surface id's
 #define LAND  1
@@ -399,6 +400,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	static BOOL isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;}
 
+    // rebuild reflection probe list
+    void updateReflectionProbes();
+
 private:
 	void addToVOCacheTree(LLVOCacheEntry* entry);
 	LLViewerObject* addNewObject(LLVOCacheEntry* entry);
@@ -572,6 +576,10 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 	LLFrameTimer mMaterialsCapThrottleTimer;
 	LLFrameTimer mRenderInfoRequestTimer;
 	LLFrameTimer mRenderInfoReportTimer;
+
+    // list of reflection maps being managed by this llviewer region
+    std::vector<LLPointer<LLReflectionMap> > mReflectionMaps;
+
 };
 
 inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 67838751611890e3a8b645f3e79016d405bca84c..f2b01808a5685008a06926e2bd3bece017f8659a 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -1020,9 +1020,11 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 		// load water shader
 		gWaterProgram.mName = "Water Shader";
 		gWaterProgram.mFeatures.calculatesAtmospherics = true;
+        gWaterProgram.mFeatures.hasAtmospherics = true;
 		gWaterProgram.mFeatures.hasGamma = true;
 		gWaterProgram.mFeatures.hasTransport = true;
         gWaterProgram.mFeatures.hasSrgb = true;
+        gWaterProgram.mFeatures.hasReflectionProbes = true;
 		gWaterProgram.mShaderFiles.clear();
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
 		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER));
@@ -1037,9 +1039,11 @@ BOOL LLViewerShaderMgr::loadShadersWater()
 	// load water shader
 		gWaterEdgeProgram.mName = "Water Edge Shader";
 		gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true;
+        gWaterEdgeProgram.mFeatures.hasAtmospherics = true;
 		gWaterEdgeProgram.mFeatures.hasGamma = true;
 		gWaterEdgeProgram.mFeatures.hasTransport = true;
         gWaterEdgeProgram.mFeatures.hasSrgb = true;
+        gWaterEdgeProgram.mFeatures.hasReflectionProbes = true;
 		gWaterEdgeProgram.mShaderFiles.clear();
 		gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
 		gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER));
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 92cca190fde5a51ed08ff2190b7ca2de77828731..0da2faae29396d7a092d45f1dc785f442f6f7caf 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -1032,7 +1032,6 @@ void LLPipeline::updateRenderBump()
 // static
 void LLPipeline::updateRenderDeferred()
 {
-    sRenderDeferred = !gUseWireframe;
     sRenderPBR = sRenderDeferred;
     static LLCachedControl<S32> sProbeDetail(gSavedSettings, "RenderReflectionProbeDetail", -1);
     sReflectionProbesEnabled = sProbeDetail >= 0 && gGLManager.mGLVersion > 3.99f;
@@ -4326,6 +4325,7 @@ U32 LLPipeline::sCurRenderPoolType = 0 ;
 
 void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
 {
+#if 0
 	LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_RENDER_GEOMETRY);
     LL_PROFILE_GPU_ZONE("renderGeom");
 	assertInitialized();
@@ -4575,6 +4575,7 @@ void LLPipeline::renderGeom(LLCamera& camera, bool forceVBOUpdate)
 	LLGLState::checkStates();
 //	LLGLState::checkTextureChannels();
 //	LLGLState::checkClientArrays();
+#endif
 }
 
 void LLPipeline::renderGeomDeferred(LLCamera& camera)
@@ -4774,6 +4775,16 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
 		gGL.matrixMode(LLRender::MM_MODELVIEW);
 		gGL.loadMatrix(gGLModelView);
 	}
+
+    if (!gCubeSnapshot)
+    {
+        // debug displays
+        renderHighlights();
+        mHighlightFaces.clear();
+
+        renderDebug();
+    }
+
 }
 
 void LLPipeline::renderGeomShadow(LLCamera& camera)
@@ -8692,6 +8703,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
             unbindDeferredShader(LLPipeline::sUnderWaterRender ? gDeferredSoftenWaterProgram : gDeferredSoftenProgram);
         }
 
+#if 0
         {  // render non-deferred geometry (fullbright, alpha, etc)
             LLGLDisable blend(GL_BLEND);
             LLGLDisable stencil(GL_STENCIL_TEST);
@@ -8707,6 +8719,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
             renderGeomPostDeferred(*LLViewerCamera::getInstance(), false);
             gPipeline.popRenderTypeMask();
         }
+#endif
 
         bool render_local = RenderLocalLights; // && !gCubeSnapshot;
 
@@ -8970,10 +8983,6 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
         gGL.setColorMask(true, true);
     }
 
-    screen_target->flush();
-
-    screen_target->bindTarget();
-
     {  // render non-deferred geometry (alpha, fullbright, glow)
         LLGLDisable blend(GL_BLEND);
         LLGLDisable stencil(GL_STENCIL_TEST);
@@ -9001,6 +9010,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
                           LLPipeline::RENDER_TYPE_CONTROL_AV,
                           LLPipeline::RENDER_TYPE_ALPHA_MASK,
                           LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
+                          LLPipeline::RENDER_TYPE_WATER,
                           END_RENDER_TYPES);
 
         renderGeomPostDeferred(*LLViewerCamera::getInstance());
@@ -9065,16 +9075,7 @@ void LLPipeline::renderDeferredLighting(LLRenderTarget *screen_target)
         gGL.popMatrix();
         gGL.matrixMode(LLRender::MM_MODELVIEW);
         gGL.popMatrix();
-    }
-
-    if (!gCubeSnapshot)
-    {
-        // render highlights, etc.
-        renderHighlights();
-        mHighlightFaces.clear();
-
-        renderDebug();
-
+    
         LLVertexBuffer::unbind();
 
         if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
@@ -9346,6 +9347,7 @@ inline float sgn(float a)
 
 void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 {
+#if 0
     LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
     LL_PROFILE_GPU_ZONE("generateWaterReflection");
 
@@ -9684,6 +9686,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
             gPipeline.popRenderTypeMask();
         }
     }
+#endif
 }
 
 glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)