From 785dcfe6d496bd44730b6ba0004614b2c6d04c6a Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Fri, 4 Nov 2011 16:42:00 -0500
Subject: [PATCH] SH-2652 Even faster depth of field

---
 .../shaders/class1/deferred/dofCombineF.glsl  |  49 +++++++
 .../class1/deferred/postDeferredF.glsl        |   5 -
 indra/newview/llviewershadermgr.cpp           |  12 ++
 indra/newview/llviewershadermgr.h             |   1 +
 indra/newview/pipeline.cpp                    | 120 +++++++++++-------
 5 files changed, 139 insertions(+), 48 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl

diff --git a/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
new file mode 100644
index 00000000000..de0c70cfe91
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/deferred/dofCombineF.glsl
@@ -0,0 +1,49 @@
+/** 
+ * @file dofCombineF.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
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 gl_FragColor;
+#endif
+
+uniform sampler2DRect diffuseRect;
+uniform sampler2DRect lightMap;
+
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
+VARYING vec2 vary_fragcoord;
+
+void main() 
+{
+	vec2 tc = vary_fragcoord.xy;
+	
+	vec4 dof = texture2DRect(diffuseRect, vary_fragcoord.xy*0.5);
+	
+	vec4 diff = texture2DRect(lightMap, vary_fragcoord.xy);
+
+	gl_FragColor = mix(diff, dof, diff.a);
+}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index f684e25df8f..1db638b943e 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -31,11 +31,6 @@ out vec4 gl_FragColor;
 
 uniform sampler2DRect diffuseRect;
 
-uniform float focal_distance;
-uniform float blur_constant;
-uniform float tan_pixel_angle;
-uniform float magnification;
-
 uniform mat4 inv_proj;
 uniform vec2 screen_res;
 
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 8118d32dc41..32978a0d04d 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -187,6 +187,7 @@ LLGLSLShader			gDeferredFullbrightProgram;
 LLGLSLShader			gDeferredEmissiveProgram;
 LLGLSLShader			gDeferredPostProgram;
 LLGLSLShader			gDeferredCoFProgram;
+LLGLSLShader			gDeferredDoFCombineProgram;
 LLGLSLShader			gFXAAProgram;
 LLGLSLShader			gDeferredPostNoDoFProgram;
 LLGLSLShader			gDeferredWLSkyProgram;
@@ -1015,6 +1016,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		gDeferredAvatarEyesProgram.unload();
 		gDeferredPostProgram.unload();		
 		gDeferredCoFProgram.unload();		
+		gDeferredDoFCombineProgram.unload();
 		gFXAAProgram.unload();
 		gDeferredWaterProgram.unload();
 		gDeferredWLSkyProgram.unload();
@@ -1437,6 +1439,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
 		success = gDeferredCoFProgram.createShader(NULL, NULL);
 	}
 
+	if (success)
+	{
+		gDeferredDoFCombineProgram.mName = "Deferred DoFCombine Shader";
+		gDeferredDoFCombineProgram.mShaderFiles.clear();
+		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
+		gDeferredDoFCombineProgram.mShaderFiles.push_back(make_pair("deferred/dofCombineF.glsl", GL_FRAGMENT_SHADER_ARB));
+		gDeferredDoFCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+		success = gDeferredDoFCombineProgram.createShader(NULL, NULL);
+	}
+
 	if (success)
 	{
 		gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index f746d3f1152..95eb551bf1b 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -331,6 +331,7 @@ extern LLGLSLShader			gDeferredShadowProgram;
 extern LLGLSLShader			gDeferredShadowAlphaMaskProgram;
 extern LLGLSLShader			gDeferredPostProgram;
 extern LLGLSLShader			gDeferredCoFProgram;
+extern LLGLSLShader			gDeferredDoFCombineProgram;
 extern LLGLSLShader			gFXAAProgram;
 extern LLGLSLShader			gDeferredPostNoDoFProgram;
 extern LLGLSLShader			gDeferredAvatarShadowProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 85899b5ad67..8ae7e97f4a0 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6595,68 +6595,102 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
 				blur_constant /= 1000.f; //convert to meters for shader
 				F32 magnification = focal_length/(subject_distance-focal_length);
 
-				mDeferredLight.bindTarget();
-				shader = &gDeferredCoFProgram;
+				{ //build diffuse+bloom+CoF
+					mDeferredLight.bindTarget();
+					shader = &gDeferredCoFProgram;
 
-				bindDeferredShader(*shader);
-
-				S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
-				if (channel > -1)
-				{
-					mScreen.bindTexture(0, channel);
-				}
+					bindDeferredShader(*shader);
 
-				if (multisample)
-				{ //bloom has already been added, bind black
-					channel = shader->enableTexture(LLShaderMgr::DEFERRED_BLOOM);
+					S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
 					if (channel > -1)
 					{
-						gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sBlackImagep);
+						mScreen.bindTexture(0, channel);
+					}
+
+					if (multisample)
+					{ //bloom has already been added, bind black
+						channel = shader->enableTexture(LLShaderMgr::DEFERRED_BLOOM);
+						if (channel > -1)
+						{
+							gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sBlackImagep);
+						}
 					}
-				}
 				
-				shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
-				shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
-				shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
-				shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
+					shader->uniform1f(LLShaderMgr::DOF_FOCAL_DISTANCE, -subject_distance/1000.f);
+					shader->uniform1f(LLShaderMgr::DOF_BLUR_CONSTANT, blur_constant);
+					shader->uniform1f(LLShaderMgr::DOF_TAN_PIXEL_ANGLE, tanf(1.f/LLDrawable::sCurPixelAngle));
+					shader->uniform1f(LLShaderMgr::DOF_MAGNIFICATION, magnification);
 
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
+					gGL.begin(LLRender::TRIANGLE_STRIP);
+					gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+					gGL.vertex2f(-1,-1);
 		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
+					gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+					gGL.vertex2f(-1,3);
 		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
+					gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+					gGL.vertex2f(3,-1);
 		
-				gGL.end();
+					gGL.end();
 
-				unbindDeferredShader(*shader);
-				mDeferredLight.flush();
+					unbindDeferredShader(*shader);
+					mDeferredLight.flush();
+				}
 
+				{ //perform DoF sampling at half-res (preserve alpha channel)
+					mScreen.bindTarget();
+					glViewport(0,0,mScreen.getWidth()/2, mScreen.getHeight()/2);
+					gGL.setColorMask(true, false);
 
-				shader = &gDeferredPostProgram;
-				bindDeferredShader(*shader);
-				channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
-				if (channel > -1)
-				{
-					mDeferredLight.bindTexture(0, channel);
+					shader = &gDeferredPostProgram;
+					bindDeferredShader(*shader);
+					S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mDeferredLight.getUsage());
+					if (channel > -1)
+					{
+						mDeferredLight.bindTexture(0, channel);
+					}
+
+					gGL.begin(LLRender::TRIANGLE_STRIP);
+					gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+					gGL.vertex2f(-1,-1);
+		
+					gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+					gGL.vertex2f(-1,3);
+		
+					gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+					gGL.vertex2f(3,-1);
+		
+					gGL.end();
+
+					unbindDeferredShader(*shader);
+					mScreen.flush();
+					gGL.setColorMask(true, true);
 				}
 
-				gGL.begin(LLRender::TRIANGLE_STRIP);
-				gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
-				gGL.vertex2f(-1,-1);
+				{ //combine result based on alpha
+					shader = &gDeferredDoFCombineProgram;
+					bindDeferredShader(*shader);
+					glViewport(0, 0, mDeferredScreen.getWidth(), mDeferredScreen.getHeight());
+					S32 channel = shader->enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage());
+					if (channel > -1)
+					{
+						mScreen.bindTexture(0, channel);
+					}
+
+					gGL.begin(LLRender::TRIANGLE_STRIP);
+					gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
+					gGL.vertex2f(-1,-1);
 		
-				gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
-				gGL.vertex2f(-1,3);
+					gGL.texCoord2f(tc1.mV[0], tc2.mV[1]);
+					gGL.vertex2f(-1,3);
 		
-				gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
-				gGL.vertex2f(3,-1);
+					gGL.texCoord2f(tc2.mV[0], tc1.mV[1]);
+					gGL.vertex2f(3,-1);
 		
-				gGL.end();
+					gGL.end();
 
-				unbindDeferredShader(*shader);
+					unbindDeferredShader(*shader);
+				}
 			}
 			else
 			{
-- 
GitLab