From e5e94b5fa832c62dc0df239fdb4aefc23e559c0c Mon Sep 17 00:00:00 2001
From: Dave Parks <davep@lindenlab.com>
Date: Thu, 23 Feb 2023 11:47:24 -0600
Subject: [PATCH] DRTVWR-559 Fix for irradiance maps going black at 128x128
 radiance map resolution.  Improve radiance map anti-aliasing and default to
 128x128 everywhere.

---
 indra/newview/app_settings/settings.xml       |  2 +-
 .../shaders/class1/interface/gaussianF.glsl   | 53 +++++++++++++++
 .../class1/interface/reflectionmipF.glsl      | 52 +--------------
 .../class1/interface/splattexturerectV.glsl   | 11 ++--
 .../class2/interface/irradianceGenF.glsl      |  3 +-
 indra/newview/featuretable.txt                | 10 +--
 indra/newview/llreflectionmapmanager.cpp      | 66 +++++++++++--------
 indra/newview/llviewershadermgr.cpp           | 21 ++++--
 indra/newview/llviewershadermgr.h             |  1 +
 indra/newview/pipeline.cpp                    |  2 +-
 10 files changed, 120 insertions(+), 101 deletions(-)
 create mode 100644 indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl

diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 304932dd1aa..5217e88a592 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10391,7 +10391,7 @@
     <key>Type</key>
     <string>U32</string>
     <key>Value</key>
-    <integer>256</integer>
+    <integer>128</integer>
   </map>
   <key>RenderReflectionProbeAmbianceScale</key>
   <map>
diff --git a/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl
new file mode 100644
index 00000000000..8e341503f5a
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl
@@ -0,0 +1,53 @@
+/** 
+ * @file gaussianF.glsl
+ *
+ * $LicenseInfo:firstyear=2023&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2023, 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 diffuseRect;
+
+uniform float resScale;
+
+// texture direction, will be <1, 0> or <0, 1>
+uniform vec2 direction;
+
+in vec2 vary_texcoord0;
+
+// get linear depth value given a depth buffer sample d and znear and zfar values
+float linearDepth(float d, float znear, float zfar);
+
+void main() 
+{
+    vec3 col = vec3(0,0,0);
+
+    float w[] = { 0.0002, 0.0060, 0.0606, 0.2417, 0.3829, 0.2417, 0.0606, 0.0060, 0.0002 };
+    
+    for (int i = 0; i < 9; ++i)
+    {
+        vec2 tc = vary_texcoord0 + (i-4)*direction*resScale;
+        col += texture(diffuseRect, tc).rgb * w[i];
+    }
+
+    frag_color = vec4(col, 0.0);
+}
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
index a9c28b2974c..9f7706fe365 100644
--- a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
@@ -23,18 +23,8 @@
  * $/LicenseInfo$
  */
  
-#extension GL_ARB_texture_rectangle : enable
-
-/*[EXTRA_CODE_HERE]*/
-
-#ifdef DEFINE_GL_FRAGCOLOR
 out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
 
-// NOTE screenMap should always be texture channel 0 and 
-// depthmap should always be channel 1
 uniform sampler2D diffuseRect;
 uniform sampler2D depthMap;
 
@@ -42,48 +32,13 @@ uniform float resScale;
 uniform float znear;
 uniform float zfar;
 
-VARYING vec2 vary_texcoord0;
+in vec2 vary_texcoord0;
 
 // get linear depth value given a depth buffer sample d and znear and zfar values
 float linearDepth(float d, float znear, float zfar);
 
 void main() 
 {
-#if 0
-    float w[9];
-
-    float c = 1.0/16.0;  //corner weight
-    float e = 1.0/8.0; //edge weight
-    float m = 1.0/4.0; //middle weight
-
-    //float wsum = c*4+e*4+m;
-
-    w[0] = c;   w[1] = e;    w[2] = c;
-    w[3] = e;    w[4] = m;     w[5] = e;
-    w[6] = c;   w[7] = e;    w[8] = c;
-    
-    vec2 tc[9];
-
-    float ed = 1;
-    float cd = 1;
-
-
-    tc[0] = vec2(-cd, cd);    tc[1] = vec2(0, ed);    tc[2] = vec2(cd, cd);
-    tc[3] = vec2(-ed, 0);    tc[4] = vec2(0, 0);    tc[5] = vec2(ed, 0);
-    tc[6] = vec2(-cd, -cd);    tc[7] = vec2(0, -ed);   tc[8] = vec2(cd, -1);
-
-    vec3 color = vec3(0,0,0);
-
-    for (int i = 0; i < 9; ++i)
-    {
-        color += texture2D(screenMap, vary_texcoord0.xy+tc[i]).rgb * w[i];
-        //color += texture2D(screenMap, vary_texcoord0.xy+tc[i]*2.0).rgb * w[i]*0.5;
-    }
-
-    //color /= wsum;
-
-    frag_color = vec4(color, 1.0);
-#else
     float depth = texture(depthMap, vary_texcoord0.xy).r;
     float dist = linearDepth(depth, znear, zfar);
 
@@ -94,7 +49,6 @@ void main()
     v = normalize(v);
     dist /= v.z;
 
-    vec3 col = texture2D(diffuseRect, vary_texcoord0.xy).rgb;
-    frag_color = vec4(col, dist/256.0); 
-#endif
+    vec3 col = texture(diffuseRect, vary_texcoord0.xy).rgb;
+    frag_color = vec4(col, dist/256.0);
 }
diff --git a/indra/newview/app_settings/shaders/class1/interface/splattexturerectV.glsl b/indra/newview/app_settings/shaders/class1/interface/splattexturerectV.glsl
index 641d670c267..edc0a9628b1 100644
--- a/indra/newview/app_settings/shaders/class1/interface/splattexturerectV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/splattexturerectV.glsl
@@ -25,17 +25,16 @@
 
 uniform mat4 modelview_projection_matrix;
 
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec2 texcoord0;
-ATTRIBUTE vec4 diffuse_color;
+in vec3 position;
+in vec4 diffuse_color;
 
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
+out vec4 vertex_color;
+out vec2 vary_texcoord0;
 
 void main()
 {
 	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
-	vary_texcoord0 = texcoord0;
+	vary_texcoord0 = position.xy*0.5+0.5;
 	vertex_color = diffuse_color;
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
index c7da23fb00c..baf68e11f42 100644
--- a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
+++ b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
@@ -176,7 +176,6 @@ float computeLod(float pdf)
 
 vec4 filterColor(vec3 N)
 {
-    //return  textureLod(uCubeMap, N, 3.0).rgb;
     vec4 color = vec4(0.f);
     
     for(int i = 0; i < u_sampleCount; ++i)
@@ -192,7 +191,7 @@ vec4 filterColor(vec3 N)
         // apply the bias to the lod
         lod += u_lodBias;
 
-        lod = clamp(lod, 0, 7);
+        lod = clamp(lod, 0, max_probe_lod);
         // sample lambertian at a lower resolution to avoid fireflies
         vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod);
 
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 0f8dcf7f73d..af72d48db98 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 48
+version 49
 // The version number above should be incremented IF AND ONLY IF some
 // change has been made that is sufficiently important to justify
 // resetting the graphics preferences of all users to the recommended
@@ -71,7 +71,7 @@ RenderFSAASamples			1	16
 RenderMaxTextureIndex		1	16
 RenderGLContextCoreProfile         1   1
 RenderGLMultiThreaded       1   0
-RenderReflectionProbeResolution 1 256
+RenderReflectionProbeResolution 1 128
 RenderScreenSpaceReflections 1  1
 
 
@@ -279,12 +279,6 @@ RenderUseAdvancedAtmospherics 1 0
 list VRAMGT512
 RenderCompressTextures		1	0
 
-//
-// VRAM < 2GB
-//
-list VRAMLT2GB
-RenderReflectionProbeResolution 1 128
-
 //
 // "Default" setups for safe, low, medium, high
 //
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 608585acf51..acb36124164 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -95,7 +95,7 @@ void LLReflectionMapManager::update()
     if (!mRenderTarget.isComplete())
     {
         U32 color_fmt = GL_RGB16;
-        U32 targetRes = mProbeResolution * 2; // super sample
+        U32 targetRes = mProbeResolution * 4; // super sample
         mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
     }
 
@@ -502,8 +502,6 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
 
     // downsample to placeholder map
     {
-        gReflectionMipProgram.bind();
-
         gGL.matrixMode(gGL.MM_MODELVIEW);
         gGL.pushMatrix();
         gGL.loadIdentity();
@@ -515,21 +513,50 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
         gGL.flush();
         U32 res = mProbeResolution * 2;
 
+        static LLStaticHashedString resScale("resScale");
+        static LLStaticHashedString direction("direction");
+        static LLStaticHashedString znear("znear");
+        static LLStaticHashedString zfar("zfar");
+
+        LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen;
+        LLRenderTarget* depth_rt = &gPipeline.mAuxillaryRT.deferredScreen;
+
+        // perform a gaussian blur on the super sampled render before downsampling
+        {
+            gGaussianProgram.bind();
+            gGaussianProgram.uniform1f(resScale, 1.f / (mProbeResolution * 2));
+            S32 diffuseChannel = gGaussianProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
+
+            // horizontal
+            gGaussianProgram.uniform2f(direction, 1.f, 0.f);
+            gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
+            mRenderTarget.bindTarget();
+            gPipeline.mScreenTriangleVB->setBuffer();
+            gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+            mRenderTarget.flush();
+
+            // vertical
+            gGaussianProgram.uniform2f(direction, 0.f, 1.f);
+            gGL.getTexUnit(diffuseChannel)->bind(&mRenderTarget);
+            screen_rt->bindTarget();
+            gPipeline.mScreenTriangleVB->setBuffer();
+            gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+            screen_rt->flush();
+        }
+
+
         S32 mips = log2((F32)mProbeResolution) + 0.5f;
 
+        gReflectionMipProgram.bind();
         S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
         S32 depthChannel   = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE);
 
-        LLRenderTarget* screen_rt = &gPipeline.mAuxillaryRT.screen;
-        LLRenderTarget* depth_rt = &gPipeline.mAuxillaryRT.deferredScreen;
-
         for (int i = 0; i < mMipChain.size(); ++i)
         {
             LL_PROFILE_GPU_ZONE("probe mip");
             mMipChain[i].bindTarget();
             if (i == 0)
             {
-                
                 gGL.getTexUnit(diffuseChannel)->bind(screen_rt);
             }
             else
@@ -539,30 +566,13 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
 
             gGL.getTexUnit(depthChannel)->bind(depth_rt, true);
 
-            static LLStaticHashedString resScale("resScale");
-            static LLStaticHashedString znear("znear");
-            static LLStaticHashedString zfar("zfar");
-            
-            gReflectionMipProgram.uniform1f(resScale, (F32) (1 << i));
+            gReflectionMipProgram.uniform1f(resScale, 1.f/(mProbeResolution*2));
             gReflectionMipProgram.uniform1f(znear, probe->getNearClip());
             gReflectionMipProgram.uniform1f(zfar, MAX_FAR_CLIP);
 
-            gGL.begin(gGL.QUADS);
-
-            gGL.texCoord2f(0, 0);
-            gGL.vertex2f(-1, -1);
-
-            gGL.texCoord2f(1.f, 0);
-            gGL.vertex2f(1, -1);
-
-            gGL.texCoord2f(1.f, 1.f);
-            gGL.vertex2f(1, 1);
-
-            gGL.texCoord2f(0, 1.f);
-            gGL.vertex2f(-1, 1);
-            gGL.end();
-            gGL.flush();
-
+            gPipeline.mScreenTriangleVB->setBuffer();
+            gPipeline.mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3);
+            
             res /= 2;
 
             S32 mip = i - (mMipChain.size() - mips);
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 5d3da554992..bddce2d6d92 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -73,6 +73,7 @@ LLGLSLShader    gSkinnedOcclusionProgram;
 LLGLSLShader	gOcclusionCubeProgram;
 LLGLSLShader	gGlowCombineProgram;
 LLGLSLShader	gReflectionMipProgram;
+LLGLSLShader    gGaussianProgram;
 LLGLSLShader	gRadianceGenProgram;
 LLGLSLShader	gIrradianceGenProgram;
 LLGLSLShader	gGlowCombineFXAAProgram;
@@ -3185,12 +3186,20 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
         gReflectionMipProgram.mShaderFiles.push_back(make_pair("interface/reflectionmipF.glsl", GL_FRAGMENT_SHADER));
         gReflectionMipProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
         success = gReflectionMipProgram.createShader(NULL, NULL);
-        if (success)
-        {
-            gReflectionMipProgram.bind();
-            gReflectionMipProgram.uniform1i(sScreenMap, 0);
-            gReflectionMipProgram.unbind();
-        }
+    }
+
+    if (success)
+    {
+        gGaussianProgram.mName = "Reflection Mip Shader";
+        gGaussianProgram.mFeatures.isDeferred = true;
+        gGaussianProgram.mFeatures.hasGamma = true;
+        gGaussianProgram.mFeatures.hasAtmospherics = true;
+        gGaussianProgram.mFeatures.calculatesAtmospherics = true;
+        gGaussianProgram.mShaderFiles.clear();
+        gGaussianProgram.mShaderFiles.push_back(make_pair("interface/splattexturerectV.glsl", GL_VERTEX_SHADER));
+        gGaussianProgram.mShaderFiles.push_back(make_pair("interface/gaussianF.glsl", GL_FRAGMENT_SHADER));
+        gGaussianProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+        success = gGaussianProgram.createShader(NULL, NULL);
     }
 
     if (success && gGLManager.mHasCubeMapArray)
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 9bd01dbdf50..867413b6c96 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -151,6 +151,7 @@ extern LLGLSLShader			gOcclusionProgram;
 extern LLGLSLShader			gOcclusionCubeProgram;
 extern LLGLSLShader			gGlowCombineProgram;
 extern LLGLSLShader			gReflectionMipProgram;
+extern LLGLSLShader         gGaussianProgram;
 extern LLGLSLShader         gRadianceGenProgram;
 extern LLGLSLShader         gIrradianceGenProgram;
 extern LLGLSLShader			gGlowCombineFXAAProgram;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index a4578c0e98b..0ef89afe611 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -802,7 +802,7 @@ bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
         gCubeSnapshot = TRUE;
         mReflectionMapManager.initReflectionMaps();
         mRT = &mAuxillaryRT;
-        U32 res = mReflectionMapManager.mProbeResolution * 2;  //multiply by 2 because probes will be super sampled
+        U32 res = mReflectionMapManager.mProbeResolution * 4;  //multiply by 4 because probes will be 16x super sampled
         allocateScreenBuffer(res, res, samples);
         mRT = &mMainRT;
         gCubeSnapshot = FALSE;
-- 
GitLab