From 5efee00a835a30f09637b2459134d458a9efa6cd Mon Sep 17 00:00:00 2001
From: Graham Linden <graham@lindenlab.com>
Date: Fri, 12 Jul 2013 13:01:31 -0700
Subject: [PATCH] NORSPEC-291 WIP added underwater deferred program and more
 reflection pass work

---
 .../shaders/class1/deferred/underWaterF.glsl  | 120 ++++++++++
 indra/newview/lldrawpoolwater.cpp             |   9 +-
 indra/newview/llviewershadermgr.cpp           |  17 ++
 indra/newview/llviewershadermgr.h             |   1 +
 indra/newview/pipeline.cpp                    | 220 +++++++++++++-----
 indra/newview/pipeline.h                      |   3 +-
 6 files changed, 315 insertions(+), 55 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl

diff --git a/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
new file mode 100644
index 00000000000..c160b38cfed
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/underWaterF.glsl
@@ -0,0 +1,120 @@
+/**
+ * @file 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$
+ */
+ 
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_data[3];
+#else
+#define frag_data gl_FragData
+#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 waterFogDensity;
+uniform float waterFogKS;
+uniform vec2 screenRes;
+
+//bigWave is (refCoord.w, view.w);
+VARYING vec4 refCoord;
+VARYING vec4 littleWave;
+VARYING vec4 view;
+
+vec2 encode_normal(vec3 n)
+{
+	float f = sqrt(8 * n.z + 8);
+	return n.xy / f + 0.5;
+}
+
+vec4 applyWaterFog(vec4 color, vec3 viewVec)
+{
+	//normalize view vector
+	vec3 view = normalize(viewVec);
+	float es = -view.z;
+
+	//find intersection point with water plane and eye vector
+	
+	//get eye depth
+	float e0 = max(-waterPlane.w, 0.0);
+	
+	//get object depth
+	float depth = length(viewVec);
+		
+	//get "thickness" of water
+	float l = max(depth, 0.1);
+
+	float kd = waterFogDensity;
+	float ks = waterFogKS;
+	vec4 kc = waterFogColor;
+	
+	float F = 0.98;
+	
+	float t1 = -kd * pow(F, ks * e0);
+	float t2 = kd + ks * es;
+	float t3 = pow(F, t2*l) - 1.0;
+	
+	float L = min(t1/t2*t3, 1.0);
+	
+	float D = pow(0.98, l*kd);
+	//return vec4(1.0, 0.0, 1.0, 1.0);
+	return color * D + kc * L;
+	//depth /= 10.0;
+	//return vec4(depth,depth,depth,0.0);
+}
+
+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_data[0] = vec4(fb.rgb, 0.5); // diffuse
+	frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec
+	frag_data[2] = vec4(encode_normal(wavef), 0.0, 0.0); // normalxyz, displace
+}
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 5b0b173926b..6774926f62a 100755
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -524,7 +524,14 @@ void LLDrawPoolWater::shade()
 	
 	if (eyedepth < 0.f && LLPipeline::sWaterReflections)
 	{
-		shader = &gUnderWaterProgram;
+		if (deferred_render)
+		{
+			shader = &gDeferredUnderWaterProgram;
+		}
+		else
+		{
+			shader = &gUnderWaterProgram;
+		}		
 	}
 	else if (deferred_render)
 	{
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 3df81154026..e9c3990e9ab 100755
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -168,6 +168,7 @@ LLGLSLShader			gPostNightVisionProgram;
 // Deferred rendering shaders
 LLGLSLShader			gDeferredImpostorProgram;
 LLGLSLShader			gDeferredWaterProgram;
+LLGLSLShader			gDeferredUnderWaterProgram;
 LLGLSLShader			gDeferredDiffuseProgram;
 LLGLSLShader			gDeferredDiffuseAlphaMaskProgram;
 LLGLSLShader			gDeferredNonIndexedDiffuseProgram;
@@ -309,6 +310,7 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
 	mShaderList.push_back(&gDeferredEmissiveProgram);
 	mShaderList.push_back(&gDeferredAvatarEyesProgram);
 	mShaderList.push_back(&gDeferredWaterProgram);
+	mShaderList.push_back(&gDeferredUnderWaterProgram);	
 	mShaderList.push_back(&gDeferredAvatarAlphaProgram);
 	mShaderList.push_back(&gDeferredWLSkyProgram);
 	mShaderList.push_back(&gDeferredWLCloudProgram);
@@ -1153,6 +1155,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredPostGammaCorrectProgram.unload();
 		gFXAAProgram.unload();
 		gDeferredWaterProgram.unload();
+		gDeferredUnderWaterProgram.unload();
 		gDeferredWLSkyProgram.unload();
 		gDeferredWLCloudProgram.unload();
 		gDeferredStarProgram.unload();
@@ -1640,6 +1643,20 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredWaterProgram.createShader(NULL, &mWaterUniforms);
 	}
 
+	if (success)
+	{
+		// load water shader
+		gDeferredUnderWaterProgram.mName = "Deferred Under Water Shader";
+		gDeferredUnderWaterProgram.mFeatures.calculatesAtmospherics = true;
+		gDeferredUnderWaterProgram.mFeatures.hasGamma = true;
+		gDeferredUnderWaterProgram.mFeatures.hasTransport = true;
+		gDeferredUnderWaterProgram.mShaderFiles.clear();
+		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredUnderWaterProgram.mShaderFiles.push_back(make_pair("deferred/underWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredUnderWaterProgram.createShader(NULL, &mWaterUniforms);
+	}
+
 	if (success)
 	{
 		gDeferredSoftenProgram.mName = "Deferred Soften Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 53100760137..f14180d957b 100755
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -330,6 +330,7 @@ extern LLGLSLShader			gPostNightVisionProgram;
 // Deferred rendering shaders
 extern LLGLSLShader			gDeferredImpostorProgram;
 extern LLGLSLShader			gDeferredWaterProgram;
+extern LLGLSLShader			gDeferredUnderWaterProgram;
 extern LLGLSLShader			gDeferredDiffuseProgram;
 extern LLGLSLShader			gDeferredDiffuseAlphaMaskProgram;
 extern LLGLSLShader			gDeferredNonIndexedDiffuseAlphaMaskProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index cac347b3a5f..4e1eb4d8ad8 100755
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -122,6 +122,10 @@
 //#define DEBUG_INDICES
 #endif
 
+// Expensive and currently broken...
+//
+#define MATERIALS_IN_REFLECTIONS 0
+
 bool gShiftFrame = false;
 
 //cached settings
@@ -4647,6 +4651,103 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera)
 	gGL.setColorMask(true, false);
 }
 
+void LLPipeline::renderGeomDeferredToRT(LLCamera& camera)
+{
+	LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomDeferred");
+
+	LLFastTimer t(FTM_RENDER_GEOMETRY);
+	LLFastTimer t2(FTM_DEFERRED_POOLS);
+
+	LLGLEnable cull(GL_CULL_FACE);
+
+	LLGLEnable stencil(GL_STENCIL_TEST);
+	glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF);
+	stop_glerror();
+	glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+	stop_glerror();
+
+	for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter)
+	{
+		LLDrawPool *poolp = *iter;
+		if (hasRenderType(poolp->getType()))
+		{
+			poolp->prerender();
+		}
+	}
+
+	LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
+
+	LLVertexBuffer::unbind();
+
+	LLGLState::checkStates();
+	LLGLState::checkTextureChannels();
+	LLGLState::checkClientArrays();
+
+	U32 cur_type = 0;
+
+	gGL.setColorMask(true, true);
+
+	pool_set_t::iterator iter1 = mPools.begin();
+
+	while ( iter1 != mPools.end() )
+	{
+		LLDrawPool *poolp = *iter1;
+
+		cur_type = poolp->getType();
+
+		pool_set_t::iterator iter2 = iter1;
+		if (hasRenderType(poolp->getType()) && poolp->getNumDeferredPasses() > 0)
+		{
+			LLFastTimer t(FTM_DEFERRED_POOLRENDER);
+
+			gGLLastMatrix = NULL;
+			gGL.loadMatrix(gGLModelView);
+
+			for( S32 i = 0; i < poolp->getNumDeferredPasses(); i++ )
+			{
+				LLVertexBuffer::unbind();
+				poolp->beginDeferredPass(i);
+				for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+				{
+					LLDrawPool *p = *iter2;
+					if (p->getType() != cur_type)
+					{
+						break;
+					}
+
+					if ( !p->getSkipRenderFlag() ) { p->renderDeferred(i); }
+				}
+				poolp->endDeferredPass(i);
+				LLVertexBuffer::unbind();
+
+				if (gDebugGL || gDebugPipeline)
+				{
+					LLGLState::checkStates();
+				}
+			}
+		}
+		else
+		{
+			// Skip all pools of this type
+			for (iter2 = iter1; iter2 != mPools.end(); iter2++)
+			{
+				LLDrawPool *p = *iter2;
+				if (p->getType() != cur_type)
+				{
+					break;
+				}
+			}
+		}
+		iter1 = iter2;
+		stop_glerror();
+	}
+
+	gGLLastMatrix = NULL;
+	gGL.loadMatrix(gGLModelView);
+
+	gGL.setColorMask(true, false);
+}
+
 void LLPipeline::renderGeomPostDeferred(LLCamera& camera, bool do_occlusion)
 {
 	LLFastTimer t(FTM_POST_DEFERRED_POOLS);
@@ -8047,10 +8148,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 
 static LLFastTimer::DeclareTimer FTM_BIND_DEFERRED("Bind Deferred");
 
-void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 noise_map)
+void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* alternative_target, U32 noise_map)
 {
 	LLFastTimer t(FTM_BIND_DEFERRED);
 
+	LLRenderTarget* render_target = alternative_target ? alternative_target : &mScreen;
+
 	if (noise_map == 0xFFFFFFFF)
 	{
 		noise_map = mNoiseMap;
@@ -8120,7 +8223,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n
 	{
 		if (light_index > 0)
 		{
-			mScreen.bindTexture(0, channel);
+			render_target->bindTexture(0, channel);
 		}
 		else
 		{
@@ -8903,11 +9006,11 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 
 		LLViewerCamera* camera = LLViewerCamera::getInstance();
 
-		/*{
+		{
 			LLGLDepthTest depth(GL_TRUE);
 			mDeferredDepth.copyContents(mDeferredScreen, 0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight(),
 							0, 0, mDeferredDepth.getWidth(), mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);	
-		}*/
+		}
 
 		LLGLEnable multisample(RenderFSAASamples > 0 ? GL_MULTISAMPLE_ARB : 0);
 
@@ -8957,7 +9060,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 			mDeferredLight.bindTarget();
 			{ //paint shadow/SSAO light map (direct lighting lightmap)
 				LLFastTimer ftm(FTM_SUN_SHADOW);
-				bindDeferredShader(gDeferredSunProgram, 0);
+				bindDeferredShader(gDeferredSunProgram, 0, target);
 				mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 				glClearColor(1,1,1,1);
 				mDeferredLight.clear(GL_COLOR_BUFFER_BIT);
@@ -9006,17 +9109,16 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		gGL.popMatrix();
 		stop_glerror();
 
-		// Done by callers...
-		//
-		//target->bindTarget();
-		// clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
-		//glClearColor(0,0,0,0);
+		target->bindTarget();
+
+		//clear color buffer here - zeroing alpha (glow) is important or it will accumulate against sky
+		//glClearColor(0,1,0,0);
 		//target->clear(GL_COLOR_BUFFER_BIT);
 		
 		if (RenderDeferredAtmospheric)
 		{ //apply sunlight contribution 
 			LLFastTimer ftm(FTM_ATMOSPHERICS);
-			bindDeferredShader(gDeferredSoftenProgram);	
+			bindDeferredShader(gDeferredSoftenProgram,0,target);	
 			{
 				LLGLDepthTest depth(GL_FALSE);
 				LLGLDisable blend(GL_BLEND);
@@ -9077,7 +9179,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 			LLVertexBuffer::unbind();
 
 			{
-				bindDeferredShader(gDeferredLightProgram);
+				bindDeferredShader(gDeferredLightProgram, 0, target);
 				
 				if (mCubeVB.isNull())
 				{
@@ -9185,7 +9287,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 			if (!spot_lights.empty())
 			{
 				LLGLDepthTest depth(GL_TRUE, GL_FALSE);
-				bindDeferredShader(gDeferredSpotLightProgram);
+				bindDeferredShader(gDeferredSpotLightProgram,0, target);
 
 				mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
 
@@ -9266,7 +9368,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 					if (count == max_count || fullscreen_lights.empty())
 					{
 						U32 idx = count-1;
-						bindDeferredShader(gDeferredMultiLightProgram[idx]);
+						bindDeferredShader(gDeferredMultiLightProgram[idx],0, target);
 						gDeferredMultiLightProgram[idx].uniform1i(LLShaderMgr::MULTI_LIGHT_COUNT, count);
 						gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT, count, (GLfloat*) light);
 						gDeferredMultiLightProgram[idx].uniform4fv(LLShaderMgr::MULTI_LIGHT_COL, count, (GLfloat*) col);
@@ -9280,7 +9382,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 				
 				unbindDeferredShader(gDeferredMultiLightProgram[0]);
 
-				bindDeferredShader(gDeferredMultiSpotLightProgram);
+				bindDeferredShader(gDeferredMultiSpotLightProgram, 0, target);
 
 				gDeferredMultiSpotLightProgram.enableTexture(LLShaderMgr::DEFERRED_PROJECTION);
 
@@ -9420,8 +9522,7 @@ void LLPipeline::renderDeferredLightingToRT(LLRenderTarget* target)
 		popRenderTypeMask();
 	}
 
-	// Done by callers for flexibility
-	//target->flush();				
+	target->flush();				
 }
 
 void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
@@ -9733,17 +9834,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 					if (LLPipeline::sRenderDeferred)
 					{
 						gGL.setColorMask(true, true);
-						renderGeomDeferred(camera);
-						gPipeline.mDeferredScreen.flush();
-						if(LLRenderTarget::sUseFBO)
-						{
-							LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
-								gPipeline.mDeferredScreen.getHeight(), 0, 0, 
-								gPipeline.mDeferredScreen.getWidth(), 
-								gPipeline.mDeferredScreen.getHeight(), 
-								GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-						}
-						renderDeferredLightingToRT(&mWaterRef);
+						gPipeline.mDeferredScreen.bindTarget();
+						glClearColor(0,0,0,0);
+						gPipeline.mDeferredScreen.clear();
+
+						LLGLDepthTest d(GL_FALSE,GL_FALSE);
+						renderGeomDeferred(camera);						
 					}
 					else
 #endif
@@ -9754,6 +9850,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 					gPipeline.popRenderTypeMask();
 				}					
 
+				gGL.setColorMask(true, false);
 				gPipeline.pushRenderTypeMask();
 
 				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
@@ -9795,26 +9892,30 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 #if MATERIALS_IN_REFLECTIONS
 						if (LLPipeline::sRenderDeferred)
 						{
+							LLGLDepthTest d(GL_FALSE,GL_FALSE);
 							renderGeomDeferred(camera);
-							gPipeline.mDeferredScreen.flush();
-							if(LLRenderTarget::sUseFBO)
-							{
-								LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
-									gPipeline.mDeferredScreen.getHeight(), 0, 0, 
-									gPipeline.mDeferredScreen.getWidth(), 
-									gPipeline.mDeferredScreen.getHeight(), 
-									GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-							}
-							renderDeferredLightingToRT(&mWaterRef);
 						}
 						else
 #endif
 						{
 							renderGeom(camera);
-						}						
+						}
 					}
 				}	
 
+#if MATERIALS_IN_REFLECTIONS
+				if (LLPipeline::sRenderDeferred)
+				{
+					gPipeline.mDeferredScreen.flush();
+					gPipeline.mWaterRef.copyContents(gPipeline.mDeferredScreen,
+						0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
+						0, 0, gPipeline.mWaterRef.getWidth(),		  gPipeline.mWaterRef.getHeight(), 
+						0, GL_NEAREST);
+					mWaterRef.flush();
+					renderDeferredLightingToRT(&mWaterRef);
+				}
+#endif
+
 				gPipeline.popRenderTypeMask();
 			}	
 			glCullFace(GL_BACK);
@@ -9849,10 +9950,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			LLViewerCamera::updateFrustumPlanes(camera);
 
 			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+			
 			LLColor4& col = LLDrawPoolWater::sWaterFogColor;
 			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
 			mWaterDis.bindTarget();
 			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
+			
 			mWaterDis.getViewport(gGLViewport);
 
 			if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
@@ -9868,33 +9971,44 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 			
 				gGL.setColorMask(true, true);
 				mWaterDis.clear();
+				gGL.setColorMask(true, false);
 
 #if MATERIALS_IN_REFLECTIONS
 				if (LLPipeline::sRenderDeferred)
-				{
+				{					
+					
+					gPipeline.mDeferredScreen.bindTarget();
+					gGL.setColorMask(true, true);
+					glClearColor(1,0,1,0);
+					gPipeline.mDeferredScreen.clear();
+
 					renderGeomDeferred(camera);
+
 					gPipeline.mDeferredScreen.flush();
-					if(LLRenderTarget::sUseFBO)
-					{
-						LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), 
-							gPipeline.mDeferredScreen.getHeight(), 0, 0, 
-							gPipeline.mDeferredScreen.getWidth(), 
-							gPipeline.mDeferredScreen.getHeight(), 
-							GL_DEPTH_BUFFER_BIT, GL_NEAREST);
-					}
-					renderDeferredLightingToRT(&mWaterDis);
+
+					mWaterDis.copyContents(gPipeline.mDeferredScreen,
+							0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(),
+							0, 0, gPipeline.mWaterDis.getWidth(), gPipeline.mWaterDis.getHeight(), 
+							0, GL_NEAREST);
+					mWaterDis.flush();					
 				}
 				else
 #endif
 				{
-					gGL.setColorMask(true, false);
-					renderGeom(camera);
+					renderGeom(camera);					
 				}
-
+				
+#if MATERIALS_IN_REFLECTIONS
+				if (LLPipeline::sRenderDeferred)
+				{	
+					renderDeferredLightingToRT(&mWaterDis);
+				}
+#endif
 			}
 
-			LLPipeline::sUnderWaterRender = FALSE;
 			mWaterDis.flush();
+			LLPipeline::sUnderWaterRender = FALSE;
+			
 		}
 		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
 
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 36b293b9986..8764616fba9 100755
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -281,9 +281,10 @@ class LLPipeline
 
 	void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE);
 	void renderGeomDeferred(LLCamera& camera);
+	void renderGeomDeferredToRT(LLCamera& camera);
 	void renderGeomPostDeferred(LLCamera& camera, bool do_occlusion=true);
 	void renderGeomShadow(LLCamera& camera);
-	void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, U32 noise_map = 0xFFFFFFFF);
+	void bindDeferredShader(LLGLSLShader& shader, U32 light_index = 0, LLRenderTarget* alternative_target = NULL, U32 noise_map = 0xFFFFFFFF);
 	void setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep);
 
 	void unbindDeferredShader(LLGLSLShader& shader);
-- 
GitLab