summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/app_settings/settings.xml2
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl5
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl118
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/gaussianF.glsl53
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl52
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/splattexturerectV.glsl11
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl8
-rw-r--r--indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl3
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl174
-rw-r--r--indra/newview/app_settings/shaders/class3/environment/waterF.glsl4
-rw-r--r--indra/newview/featuretable.txt10
-rw-r--r--indra/newview/lldrawpool.cpp8
-rw-r--r--indra/newview/lldrawpool.h5
-rw-r--r--indra/newview/lldrawpoolpbropaque.cpp33
-rw-r--r--indra/newview/lldrawpoolpbropaque.h16
-rw-r--r--indra/newview/llmaterialeditor.cpp15
-rw-r--r--indra/newview/llpanelvolume.cpp8
-rw-r--r--indra/newview/llreflectionmap.cpp83
-rw-r--r--indra/newview/llreflectionmap.h18
-rw-r--r--indra/newview/llreflectionmapmanager.cpp132
-rw-r--r--indra/newview/llreflectionmapmanager.h3
-rw-r--r--indra/newview/lltexturectrl.cpp12
-rw-r--r--indra/newview/llviewershadermgr.cpp21
-rw-r--r--indra/newview/llviewershadermgr.h1
-rw-r--r--indra/newview/pipeline.cpp98
-rw-r--r--indra/newview/pipeline.h2
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml2
29 files changed, 664 insertions, 270 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 304932dd1a..5217e88a59 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/deferred/pbralphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
index ddb53ff852..24faf1763f 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pbralphaV.glsl
@@ -49,10 +49,9 @@ uniform mat3 texture_normal_matrix;
uniform mat3 texture_metallic_roughness_matrix;
uniform mat3 texture_emissive_matrix;
-#ifdef HAS_SUN_SHADOW
out vec3 vary_fragcoord;
+
uniform float near_clip;
-#endif
in vec3 position;
in vec4 diffuse_color;
@@ -88,9 +87,7 @@ void main()
#endif
gl_Position = vert;
-#ifdef HAS_SUN_SHADOW
vary_fragcoord.xyz = vert.xyz + vec3(0,0,near_clip);
-#endif
basecolor_texcoord = texture_transform(texcoord0, texture_basecolor_matrix, texture_matrix0);
normal_texcoord = texture_transform(texcoord0, texture_normal_matrix, texture_matrix0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
index 987b2d1fe8..e0e975faf0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl
@@ -41,6 +41,122 @@ uniform float display_gamma;
vec3 linear_to_srgb(vec3 cl);
+//===============================================================
+// tone mapping taken from Khronos sample implementation
+//===============================================================
+const float GAMMA = 2.2;
+const float INV_GAMMA = 1.0 / GAMMA;
+
+
+// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
+const mat3 ACESInputMat = mat3
+(
+ 0.59719, 0.07600, 0.02840,
+ 0.35458, 0.90834, 0.13383,
+ 0.04823, 0.01566, 0.83777
+);
+
+
+// ODT_SAT => XYZ => D60_2_D65 => sRGB
+const mat3 ACESOutputMat = mat3
+(
+ 1.60475, -0.10208, -0.00327,
+ -0.53108, 1.10813, -0.07276,
+ -0.07367, -0.00605, 1.07602
+);
+
+
+// linear to sRGB approximation
+// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+vec3 linearTosRGB(vec3 color)
+{
+ return pow(color, vec3(INV_GAMMA));
+}
+
+
+// sRGB to linear approximation
+// see http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
+vec3 sRGBToLinear(vec3 srgbIn)
+{
+ return vec3(pow(srgbIn.xyz, vec3(GAMMA)));
+}
+
+
+vec4 sRGBToLinear(vec4 srgbIn)
+{
+ return vec4(sRGBToLinear(srgbIn.xyz), srgbIn.w);
+}
+
+
+// ACES tone map (faster approximation)
+// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
+vec3 toneMapACES_Narkowicz(vec3 color)
+{
+ const float A = 2.51;
+ const float B = 0.03;
+ const float C = 2.43;
+ const float D = 0.59;
+ const float E = 0.14;
+ return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
+}
+
+
+// ACES filmic tone map approximation
+// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
+vec3 RRTAndODTFit(vec3 color)
+{
+ vec3 a = color * (color + 0.0245786) - 0.000090537;
+ vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
+ return a / b;
+}
+
+
+// tone mapping
+vec3 toneMapACES_Hill(vec3 color)
+{
+ color = ACESInputMat * color;
+
+ // Apply RRT and ODT
+ color = RRTAndODTFit(color);
+
+ color = ACESOutputMat * color;
+
+ // Clamp to [0, 1]
+ color = clamp(color, 0.0, 1.0);
+
+ return color;
+}
+
+
+#define TONEMAP_ACES_NARKOWICZ
+//#define TONEMAP_ACES_HILL_EXPOSURE_BOOST
+float u_Exposure = 1;
+
+vec3 toneMap(vec3 color)
+{
+ color *= u_Exposure;
+
+#ifdef TONEMAP_ACES_NARKOWICZ
+ color = toneMapACES_Narkowicz(color);
+#endif
+
+#ifdef TONEMAP_ACES_HILL
+ color = toneMapACES_Hill(color);
+#endif
+
+#ifdef TONEMAP_ACES_HILL_EXPOSURE_BOOST
+ // boost exposure as discussed in https://github.com/mrdoob/three.js/pull/19621
+ // this factor is based on the exposure correction of Krzysztof Narkowicz in his
+ // implemetation of ACES tone mapping
+ color /= 0.6;
+ color = toneMapACES_Hill(color);
+#endif
+
+ return linearTosRGB(color);
+}
+
+//===============================================================
+
//=================================
// borrowed noise from:
// <https://www.shadertoy.com/view/4dS3Wd>
@@ -83,7 +199,7 @@ void main()
{
//this is the one of the rare spots where diffuseRect contains linear color values (not sRGB)
vec4 diff = texture2D(diffuseRect, vary_fragcoord);
- diff.rgb = linear_to_srgb(diff.rgb);
+ diff.rgb = toneMap(diff.rgb);
vec2 tc = vary_fragcoord.xy*screen_res;
vec3 seed = (diff.rgb+vec3(1.0))*vec3(tc.xy, tc.x+tc.y);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
index fffbdb913e..ee3a5f1f31 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowUtil.glsl
@@ -59,12 +59,12 @@ float pcfShadow(sampler2DShadow shadowMap, vec3 norm, vec4 stc, float bias_mul,
stc.xyz /= stc.w;
stc.z += offset * 2.0;
stc.x = floor(stc.x*shadow_res.x + fract(pos_screen.y*shadow_res.y))/shadow_res.x; // add some chaotic jitter to X sample pos according to Y to disguise the snapping going on here
- float cs = texture(shadowMap, stc.xyz).x;
+ float cs = texture(shadowMap, stc.xyz);
float shadow = cs * 4.0;
- shadow += texture(shadowMap, stc.xyz+vec3( 1.5/shadow_res.x, 0.5/shadow_res.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3( 0.5/shadow_res.x, -1.5/shadow_res.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x, 1.5/shadow_res.y, 0.0)).x;
+ shadow += texture(shadowMap, stc.xyz+vec3( 1.5/shadow_res.x, 0.5/shadow_res.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3( 0.5/shadow_res.x, -1.5/shadow_res.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3(-1.5/shadow_res.x, -0.5/shadow_res.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3(-0.5/shadow_res.x, 1.5/shadow_res.y, 0.0));
return clamp(shadow * 0.125, 0.0, 1.0);
#else
return 1.0;
@@ -78,16 +78,16 @@ float pcfSpotShadow(sampler2DShadow shadowMap, vec4 stc, float bias_scale, vec2
stc.z += spot_shadow_bias * bias_scale;
stc.x = floor(proj_shadow_res.x * stc.x + fract(pos_screen.y*0.666666666)) / proj_shadow_res.x; // snap
- float cs = texture(shadowMap, stc.xyz).x;
+ float cs = texture(shadowMap, stc.xyz);
float shadow = cs;
vec2 off = 1.0/proj_shadow_res;
off.y *= 1.5;
- shadow += texture(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0)).x;
- shadow += texture(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0)).x;
+ shadow += texture(shadowMap, stc.xyz+vec3(off.x*2.0, off.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3(off.x, -off.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3(-off.x, off.y, 0.0));
+ shadow += texture(shadowMap, stc.xyz+vec3(-off.x*2.0, -off.y, 0.0));
return shadow*0.2;
#else
return 1.0;
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 0000000000..8e341503f5
--- /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/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
index e60ddcd569..b6f080739e 100644
--- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
@@ -127,14 +127,11 @@ vec4 prefilterEnvMap(vec3 R)
vec3 V = R;
vec4 color = vec4(0.0);
float totalWeight = 0.0;
- float envMapDim = u_width;
- int numSamples = 4;
-
- float numMips = max_probe_lod;
+ float envMapDim = float(textureSize(reflectionProbes, 0).s);
+ float roughness = mipLevel/max_probe_lod;
+ int numSamples = max(int(32*roughness), 1);
- float roughness = mipLevel/numMips;
-
- numSamples = max(int(numSamples*roughness), 1);
+ float numMips = max_probe_lod+1;
for(uint i = 0u; i < numSamples; i++) {
vec2 Xi = hammersley2d(i, numSamples);
@@ -154,11 +151,9 @@ vec4 prefilterEnvMap(vec3 R)
// Solid angle of 1 pixel across all cube faces
float omegaP = 4.0 * PI / (6.0 * envMapDim * envMapDim);
// Biased (+1.0) mip level for better result
- float mip = roughness == 0.0 ? 0.0 : clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, numMips);
- //float mip = clamp(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f, 7.f);
- color += textureLod(reflectionProbes, vec4(L,sourceIdx), mip) * dotNL;
+ float mipLevel = roughness == 0.0 ? 0.0 : max(0.5 * log2(omegaS / omegaP) + 1.0, 0.0f);
+ color += textureLod(reflectionProbes, vec4(L, sourceIdx), mipLevel) * dotNL;
totalWeight += dotNL;
-
}
}
return (color / totalWeight);
diff --git a/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl b/indra/newview/app_settings/shaders/class1/interface/reflectionmipF.glsl
index a9c28b2974..9f7706fe36 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 641d670c26..edc0a9628b 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/deferred/pbralphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
index 35ccc65a8e..a95feb8e2f 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/pbralphaF.glsl
@@ -46,8 +46,9 @@ uniform vec3 moon_dir;
out vec4 frag_color;
+in vec3 vary_fragcoord;
+
#ifdef HAS_SUN_SHADOW
- in vec3 vary_fragcoord;
uniform vec2 screen_res;
#endif
@@ -191,8 +192,9 @@ void main()
vec3 atten;
calcAtmosphericVarsLinear(pos.xyz, norm, light_dir, sunlit, amblit, additive, atten);
-#ifdef HAS_SUN_SHADOW
vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5;
+
+#ifdef HAS_SUN_SHADOW
scol = sampleDirectionalShadow(pos.xyz, norm.xyz, frag);
#endif
@@ -211,7 +213,7 @@ void main()
float gloss = 1.0 - perceptualRoughness;
vec3 irradiance = vec3(0);
vec3 radiance = vec3(0);
- sampleReflectionProbes(irradiance, radiance, vec2(0), pos.xyz, norm.xyz, gloss);
+ sampleReflectionProbes(irradiance, radiance, vary_position.xy*0.5+0.5, pos.xyz, norm.xyz, gloss);
// Take maximium of legacy ambient vs irradiance sample as irradiance
// NOTE: ao is applied in pbrIbl (see pbrBaseLight), do not apply here
irradiance = max(amblit,irradiance);
diff --git a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
index c7da23fb00..baf68e11f4 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/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 8b1d41776f..24539c3c3a 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -80,7 +80,7 @@ bool isAbove(vec3 pos, vec4 plane)
return (dot(plane.xyz, pos) + plane.w) > 0;
}
-int max_priority = 0;
+bool sample_automatic = true;
// return true if probe at index i influences position pos
bool shouldSampleProbe(int i, vec3 pos)
@@ -95,24 +95,24 @@ bool shouldSampleProbe(int i, vec3 pos)
return false;
}
- max_priority = max(max_priority, -refIndex[i].w);
+ sample_automatic = false;
}
else
{
- if (refSphere[i].w > 0.0) // zero is special indicator to always sample this probe
+ if (refIndex[i].w == 0 && !sample_automatic)
{
- vec3 delta = pos.xyz - refSphere[i].xyz;
- float d = dot(delta, delta);
- float r2 = refSphere[i].w;
- r2 *= r2;
-
- if (d > r2)
- { //outside bounding sphere
- return false;
- }
+ return false;
}
- max_priority = max(max_priority, refIndex[i].w);
+ vec3 delta = pos.xyz - refSphere[i].xyz;
+ float d = dot(delta, delta);
+ float r2 = refSphere[i].w;
+ r2 *= r2;
+
+ if (d > r2)
+ { // outside bounding sphere
+ return false;
+ }
}
return true;
@@ -120,7 +120,6 @@ bool shouldSampleProbe(int i, vec3 pos)
// call before sampleRef
// populate "probeIndex" with N probe indices that influence pos where N is REF_SAMPLE_COUNT
-// overall algorithm --
void preProbeSample(vec3 pos)
{
// TODO: make some sort of structure that reduces the number of distance checks
@@ -210,7 +209,7 @@ void preProbeSample(vec3 pos)
}
}
- if (max_priority <= 1)
+ if (sample_automatic)
{ // probe at index 0 is a special probe for smoothing out automatic probes
probeIndex[probeInfluences++] = 0;
}
@@ -342,7 +341,7 @@ return texCUBE(envMap, ReflDirectionWS);
// d - distance to nearest wall in clip space
vec3 boxIntersect(vec3 origin, vec3 dir, int i, out float d)
{
- // Intersection with OBB convertto unit box space
+ // Intersection with OBB convert to unit box space
// Transform in local unit parallax cube space (scaled and rotated)
mat4 clipToLocal = refBox[i];
@@ -431,18 +430,24 @@ void boxIntersectDebug(vec3 origin, vec3 pos, int i, inout vec4 col)
// origin - center of sphere probe
// r - radius of probe influence volume
// min_da - minimum angular attenuation coefficient
-float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da)
+// i - index of probe in refSphere
+// dw - distance weight
+float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da, int i, out float dw)
{
float r1 = r * 0.5; // 50% of radius (outer sphere to start interpolating down)
vec3 delta = pos.xyz - origin;
float d2 = max(length(delta), 0.001);
+
float r2 = r1; //r1 * r1;
//float atten = 1.0 - max(d2 - r2, 0.0) / max((rr - r2), 0.001);
float atten = 1.0 - max(d2 - r2, 0.0) / max((r - r2), 0.001);
+ float w = 1.0 / d2;
+
+ dw = w * atten * max(r, 1.0)*4;
atten *= max(dot(normalize(-delta), dir), min_da);
- float w = 1.0 / d2;
+
w *= atten;
return w;
@@ -451,13 +456,15 @@ float sphereWeight(vec3 pos, vec3 dir, vec3 origin, float r, float min_da)
// Tap a reflection probe
// pos - position of pixel
// dir - pixel normal
+// w - weight of sample (distance and angular attenuation)
+// dw - weight of sample (distance only)
// vi - return value of intersection point with influence volume
// wi - return value of approximate world space position of sampled pixel
// lod - which mip to bias towards (lower is higher res, sharper reflections)
// c - center of probe
// r2 - radius of probe squared
// i - index of probe
-vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
+vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out float dw, out vec3 vi, out vec3 wi, float lod, vec3 c, int i)
{
//lod = max(lod, 1);
// parallax adjustment
@@ -473,14 +480,15 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float
}
else
{
- float r = refSphere[i].w; // radius of sphere volume
- float rr = r * r; // radius squared
+ float r = refSphere[i].w;
+
+ float rr = r * r;
v = sphereIntersect(pos, dir, c,
- refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
+ refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
- w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25);
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.25, i, dw);
}
vi = v;
@@ -500,10 +508,10 @@ vec3 tapRefMap(vec3 pos, vec3 dir, out float w, out vec3 vi, out vec3 wi, float
// Tap an irradiance map
// pos - position of pixel
// dir - pixel normal
-// c - center of probe
-// r2 - radius of probe squared
+// w - weight of sample (distance and angular attenuation)
+// dw - weight of sample (distance only)
// i - index of probe
-vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
+vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, out float dw, vec3 c, int i)
{
// parallax adjustment
vec3 v;
@@ -516,14 +524,15 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
else
{
float r = refSphere[i].w; // radius of sphere volume
- float p = float(abs(refIndex[i].w)); // priority
- float rr = r * r; // radius squred
+
+ // pad sphere for manual probe extending into automatic probe space
+ float rr = r * r;
v = sphereIntersect(pos, dir, c,
- refIndex[i].w <= 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
+ refIndex[i].w < 1 ? 4096.0*4096.0 : // <== effectively disable parallax correction for automatically placed probes to keep from bombing the world with obvious spheres
rr);
- w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001);
+ w = sphereWeight(pos, dir, refSphere[i].xyz, r, 0.001, i, dw);
}
v -= c;
@@ -535,19 +544,30 @@ vec3 tapIrradianceMap(vec3 pos, vec3 dir, out float w, vec3 c, int i)
vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
{
- float wsum = 0.0;
- vec3 col = vec3(0,0,0);
- float vd2 = dot(pos,pos); // view distance squared
+ float wsum[2];
+ wsum[0] = 0;
+ wsum[1] = 0;
+
+ float dwsum[2];
+ dwsum[0] = 0;
+ dwsum[1] = 0;
+
+ vec3 col[2];
+ col[0] = vec3(0);
+ col[1] = vec3(0);
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
- if (abs(refIndex[i].w) < max_priority)
+ int p = clamp(abs(refIndex[i].w), 0, 1);
+
+ if (p == 0 && !sample_automatic)
{
continue;
}
- float w;
+ float w = 0;
+ float dw = 0;
vec3 vi, wi;
vec3 refcol;
@@ -556,7 +576,7 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
if (errorCorrect && refIndex[i].w >= 0)
{ // error correction is on and this probe is a sphere
//take a sample to get depth value, then error correct
- refcol = tapRefMap(pos, dir, w, vi, wi, abs(lod + 2), refSphere[i].xyz, i);
+ refcol = tapRefMap(pos, dir, w, dw, vi, wi, abs(lod + 2), refSphere[i].xyz, i);
//adjust lookup by distance result
float d = length(vi - wi);
@@ -571,61 +591,96 @@ vec3 sampleProbes(vec3 pos, vec3 dir, float lod, bool errorCorrect)
// weight by vector correctness
vec3 pi = normalize(wi - pos);
w *= max(dot(pi, dir), 0.1);
- //w = pow(w, 32.0);
}
else
{
- refcol = tapRefMap(pos, dir, w, vi, wi, lod, refSphere[i].xyz, i);
+ refcol = tapRefMap(pos, dir, w, dw, vi, wi, lod, refSphere[i].xyz, i);
}
- col += refcol.rgb*w;
-
- wsum += w;
+ col[p] += refcol.rgb*w;
+ wsum[p] += w;
+ dwsum[p] += dw;
}
}
- if (wsum > 0.0)
+ // mix automatic and manual probes
+ if (sample_automatic && wsum[0] > 0.0)
+ { // some automatic probes were sampled
+ col[0] *= 1.0/wsum[0];
+ if (wsum[1] > 0.0)
+ { //some manual probes were sampled, mix between the two
+ col[1] *= 1.0/wsum[1];
+ col[1] = mix(col[0], col[1], min(dwsum[1], 1.0));
+ col[0] = vec3(0);
+ }
+ }
+ else if (wsum[1] > 0.0)
{
- col *= 1.0/wsum;
+ // manual probes were sampled but no automatic probes were
+ col[1] *= 1.0/wsum[1];
+ col[0] = vec3(0);
}
- return col;
+ return col[1]+col[0];
}
vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
{
// modified copy/paste of sampleProbes follows, will likely diverge from sampleProbes further
// as irradiance map mixing is tuned independently of radiance map mixing
- float wsum = 0.0;
- vec3 col = vec3(0,0,0);
- float vd2 = dot(pos,pos); // view distance squared
+ float wsum[2];
+ wsum[0] = 0;
+ wsum[1] = 0;
- float minweight = 1.0;
+ float dwsum[2];
+ dwsum[0] = 0;
+ dwsum[1] = 0;
+
+ vec3 col[2];
+ col[0] = vec3(0);
+ col[1] = vec3(0);
for (int idx = 0; idx < probeInfluences; ++idx)
{
int i = probeIndex[idx];
- if (abs(refIndex[i].w) < max_priority)
+ int p = clamp(abs(refIndex[i].w), 0, 1);
+
+ if (p == 0 && !sample_automatic)
{
continue;
}
{
- float w;
- vec3 refcol = tapIrradianceMap(pos, dir, w, refSphere[i].xyz, i);
+ float w = 0;
+ float dw = 0;
- col += refcol*w;
-
- wsum += w;
+ vec3 refcol = tapIrradianceMap(pos, dir, w, dw, refSphere[i].xyz, i);
+
+ col[p] += refcol*w;
+ wsum[p] += w;
+ dwsum[p] += dw;
}
}
- if (wsum > 0.0)
+ // mix automatic and manual probes
+ if (sample_automatic && wsum[0] > 0.0)
+ { // some automatic probes were sampled
+ col[0] *= 1.0/wsum[0];
+ if (wsum[1] > 0.0)
+ { //some manual probes were sampled, mix between the two
+ col[1] *= 1.0/wsum[1];
+ col[1] = mix(col[0], col[1], min(dwsum[1], 1.0));
+ col[0] = vec3(0);
+ }
+ }
+ else if (wsum[1] > 0.0)
{
- col *= 1.0/wsum;
+ // manual probes were sampled but no automatic probes were
+ col[1] *= 1.0/wsum[1];
+ col[0] = vec3(0);
}
-
- return col;
+
+ return col[1]+col[0];
}
void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
@@ -658,7 +713,7 @@ void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col)
{
vec3 origin = vec3(0,0,0);
- bool manual_probe = abs(refIndex[i].w) > 2;
+ bool manual_probe = abs(refIndex[i].w) > 0;
if (manual_probe)
{
@@ -705,7 +760,6 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
{
- // TODO - don't hard code lods
float reflection_lods = max_probe_lod;
preProbeSample(pos);
diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
index 3d721cd048..631d2c04d0 100644
--- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
+++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl
@@ -232,8 +232,8 @@ void main()
irradiance = vec3(0);
- vec3 diffuseColor;
- vec3 specularColor;
+ vec3 diffuseColor = vec3(0);
+ vec3 specularColor = vec3(0);
calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor);
vec3 v = -normalize(pos.xyz);
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 0f8dcf7f73..af72d48db9 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
@@ -280,12 +280,6 @@ list VRAMGT512
RenderCompressTextures 1 0
//
-// VRAM < 2GB
-//
-list VRAMLT2GB
-RenderReflectionProbeResolution 1 128
-
-//
// "Default" setups for safe, low, medium, high
//
list safe
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 7fe8b02cc5..c61618c056 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -116,6 +116,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0)
break;
case POOL_GLTF_PBR:
poolp = new LLDrawPoolGLTFPBR();
+ break;
+ case POOL_GLTF_PBR_ALPHA_MASK:
+ poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
break;
default:
LL_ERRS() << "Unknown draw pool type!" << LL_ENDL;
@@ -648,11 +651,6 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, bool texture, bool batch_textur
}
}
- //if (params.mGroup) // TOO LATE!
- //{
- // params.mGroup->rebuildMesh();
- //}
-
params.mVertexBuffer->setBuffer();
params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset);
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index 2c5e31f579..5e741b2b95 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -58,8 +58,9 @@ public:
POOL_BUMP,
POOL_TERRAIN,
POOL_MATERIALS,
- POOL_GRASS,
POOL_GLTF_PBR,
+ POOL_GRASS,
+ POOL_GLTF_PBR_ALPHA_MASK,
POOL_TREE,
POOL_ALPHA_MASK,
POOL_FULLBRIGHT_ALPHA_MASK,
@@ -109,7 +110,7 @@ public:
virtual void render(S32 pass = 0) {};
virtual void prerender() {};
- virtual U32 getVertexDataMask() = 0;
+ virtual U32 getVertexDataMask() { return 0; } // DEPRECATED -- draw pool doesn't actually determine vertex data mask any more
virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct!
virtual S32 getShaderLevel() const { return mShaderLevel; }
diff --git a/indra/newview/lldrawpoolpbropaque.cpp b/indra/newview/lldrawpoolpbropaque.cpp
index d30fc22393..86b790e2c5 100644
--- a/indra/newview/lldrawpoolpbropaque.cpp
+++ b/indra/newview/lldrawpoolpbropaque.cpp
@@ -31,11 +31,17 @@
#include "llviewershadermgr.h"
#include "pipeline.h"
-static const U32 gltf_render_types[] = { LLPipeline::RENDER_TYPE_PASS_GLTF_PBR, LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK };
-
-LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR() :
- LLRenderPass(POOL_GLTF_PBR)
+LLDrawPoolGLTFPBR::LLDrawPoolGLTFPBR(U32 type) :
+ LLRenderPass(type)
{
+ if (type == LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK)
+ {
+ mRenderType = LLPipeline::RENDER_TYPE_PASS_GLTF_PBR_ALPHA_MASK;
+ }
+ else
+ {
+ mRenderType = LLPipeline::RENDER_TYPE_PASS_GLTF_PBR;
+ }
}
S32 LLDrawPoolGLTFPBR::getNumDeferredPasses()
@@ -47,14 +53,11 @@ void LLDrawPoolGLTFPBR::renderDeferred(S32 pass)
{
llassert(!LLPipeline::sRenderingHUDs);
- for (U32 type : gltf_render_types)
- {
- gDeferredPBROpaqueProgram.bind();
- pushGLTFBatches(type);
+ gDeferredPBROpaqueProgram.bind();
+ pushGLTFBatches(mRenderType);
- gDeferredPBROpaqueProgram.bind(true);
- pushRiggedGLTFBatches(type + 1);
- }
+ gDeferredPBROpaqueProgram.bind(true);
+ pushRiggedGLTFBatches(mRenderType + 1);
}
S32 LLDrawPoolGLTFPBR::getNumPostDeferredPasses()
@@ -67,12 +70,9 @@ void LLDrawPoolGLTFPBR::renderPostDeferred(S32 pass)
if (LLPipeline::sRenderingHUDs)
{
gHUDPBROpaqueProgram.bind();
- for (U32 type : gltf_render_types)
- {
- pushGLTFBatches(type);
- }
+ pushGLTFBatches(mRenderType);
}
- else
+ else if (mRenderType == LLPipeline::RENDER_TYPE_PASS_GLTF_PBR) // HACK -- don't render glow except for the non-alpha masked implementation
{
gGL.setColorMask(false, true);
gPBRGlowProgram.bind();
@@ -85,4 +85,3 @@ void LLDrawPoolGLTFPBR::renderPostDeferred(S32 pass)
}
}
-
diff --git a/indra/newview/lldrawpoolpbropaque.h b/indra/newview/lldrawpoolpbropaque.h
index 69e063b322..c8a28461fa 100644
--- a/indra/newview/lldrawpoolpbropaque.h
+++ b/indra/newview/lldrawpoolpbropaque.h
@@ -32,21 +32,9 @@
class LLDrawPoolGLTFPBR final : public LLRenderPass
{
public:
- enum
- {
- // See: DEFERRED_VB_MASK
- VERTEX_DATA_MASK = 0
- | LLVertexBuffer::MAP_VERTEX
- | LLVertexBuffer::MAP_NORMAL
- | LLVertexBuffer::MAP_TEXCOORD0 // Diffuse
- | LLVertexBuffer::MAP_TEXCOORD1 // Normal
- | LLVertexBuffer::MAP_TEXCOORD2 // Spec <-- ORM Occlusion Roughness Metal
- | LLVertexBuffer::MAP_TANGENT
- | LLVertexBuffer::MAP_COLOR
- };
- U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
+ LLDrawPoolGLTFPBR(U32 type = LLDrawPool::POOL_GLTF_PBR);
- LLDrawPoolGLTFPBR();
+ U32 mRenderType = 0;
S32 getNumDeferredPasses() override;
void renderDeferred(S32 pass) override;
diff --git a/indra/newview/llmaterialeditor.cpp b/indra/newview/llmaterialeditor.cpp
index 41085afb3d..64ce5fd4d2 100644
--- a/indra/newview/llmaterialeditor.cpp
+++ b/indra/newview/llmaterialeditor.cpp
@@ -420,6 +420,13 @@ BOOL LLMaterialEditor::postBuild()
mEmissiveTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_TEX_DIRTY));
mNormalTextureCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_NORMAL_TEX_DIRTY));
}
+ else
+ {
+ mBaseColorTextureCtrl->setCanApplyImmediately(false);
+ mMetallicTextureCtrl->setCanApplyImmediately(false);
+ mEmissiveTextureCtrl->setCanApplyImmediately(false);
+ mNormalTextureCtrl->setCanApplyImmediately(false);
+ }
if (!mIsOverride)
{
@@ -461,6 +468,10 @@ BOOL LLMaterialEditor::postBuild()
mBaseColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
mBaseColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_BASE_COLOR_DIRTY));
}
+ else
+ {
+ mBaseColorCtrl->setCanApplyImmediately(false);
+ }
// transparency is a part of base color
childSetCommitCallback("transparency", changes_callback, (void*)&MATERIAL_BASE_COLOR_DIRTY);
childSetCommitCallback("alpha mode", changes_callback, (void*)&MATERIAL_ALPHA_MODE_DIRTY);
@@ -477,6 +488,10 @@ BOOL LLMaterialEditor::postBuild()
mEmissiveColorCtrl->setOnCancelCallback(boost::bind(&LLMaterialEditor::onCancelCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
mEmissiveColorCtrl->setOnSelectCallback(boost::bind(&LLMaterialEditor::onSelectCtrl, this, _1, _2, MATERIAL_EMISIVE_COLOR_DIRTY));
}
+ else
+ {
+ mEmissiveColorCtrl->setCanApplyImmediately(false);
+ }
if (!mIsOverride)
{
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 0cbc2b0bad..3c34d6ee65 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -755,6 +755,7 @@ void LLPanelVolume::sendIsReflectionProbe()
if (value && !old_value)
{ // has become a reflection probe, slam to a 10m sphere and pop up a message
// warning people about the pitfalls of reflection probes
+#if 0
auto* select_mgr = LLSelectMgr::getInstance();
mObject->setScale(LLVector3(10.f, 10.f, 10.f));
@@ -768,6 +769,7 @@ void LLPanelVolume::sendIsReflectionProbe()
params.getPathParams().setCurveType(LL_PCODE_PATH_CIRCLE);
params.getProfileParams().setCurveType(LL_PCODE_PROFILE_CIRCLE_HALF);
mObject->updateVolume(params);
+#endif
LLNotificationsUtil::add("ReflectionProbeApplied");
}
@@ -1343,6 +1345,12 @@ void LLPanelVolume::onCommitProbe(LLUICtrl* ctrl, void* userdata)
if (volobjp->setReflectionProbeIsBox(is_box))
{
// make the volume match the probe
+ auto* select_mgr = LLSelectMgr::getInstance();
+
+ select_mgr->selectionUpdatePhantom(true);
+ select_mgr->selectionSetGLTFMaterial(LLUUID::null);
+ select_mgr->selectionSetAlphaOnly(0.f);
+
U8 profile, path;
if (!is_box)
diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp
index ce749a96c7..37ad74e54d 100644
--- a/indra/newview/llreflectionmap.cpp
+++ b/indra/newview/llreflectionmap.cpp
@@ -31,13 +31,24 @@
#include "llviewerwindow.h"
#include "llviewerregion.h"
#include "llworld.h"
+#include "llshadermgr.h"
extern F32SecondsImplicit gFrameTimeSeconds;
+extern U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center);
+
LLReflectionMap::LLReflectionMap()
{
}
+LLReflectionMap::~LLReflectionMap()
+{
+ if (mOcclusionQuery)
+ {
+ glDeleteQueries(1, &mOcclusionQuery);
+ }
+}
+
void LLReflectionMap::update(U32 resolution, U32 face)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
@@ -66,7 +77,7 @@ void LLReflectionMap::autoAdjustOrigin()
if (mGroup->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)
{
- mPriority = 1;
+ mPriority = 0;
// cast a ray towards 8 corners of bounding box
// nudge origin towards center of empty space
@@ -150,7 +161,7 @@ void LLReflectionMap::autoAdjustOrigin()
}
else if (mViewerObject)
{
- mPriority = 64;
+ mPriority = 1;
mOrigin.load3(mViewerObject->getPositionAgent().mV);
mRadius = mViewerObject->getScale().mV[0]*0.5f;
}
@@ -245,3 +256,71 @@ bool LLReflectionMap::getBox(LLMatrix4& box)
return false;
}
+
+bool LLReflectionMap::isActive()
+{
+ return mCubeIndex != -1;
+}
+
+void LLReflectionMap::doOcclusion(const LLVector4a& eye)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
+#if 1
+ // super sloppy, but we're doing an occlusion cull against a bounding cube of
+ // a bounding sphere, pad radius so we assume if the eye is within
+ // the bounding sphere of the bounding cube, the node is not culled
+ F32 dist = mRadius * F_SQRT3 + 1.f;
+
+ LLVector4a o;
+ o.setSub(mOrigin, eye);
+
+ bool do_query = false;
+
+ if (o.getLength3().getF32() < dist)
+ { // eye is inside radius, don't attempt to occlude
+ mOccluded = false;
+ return;
+ }
+
+ if (mOcclusionQuery == 0)
+ { // no query was previously issued, allocate one and issue
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGenQueries");
+ glGenQueries(1, &mOcclusionQuery);
+ do_query = true;
+ }
+ else
+ { // query was previously issued, check it and only issue a new query
+ // if previous query is available
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - glGetQueryObject");
+ GLuint result = 0;
+ glGetQueryObjectuiv(mOcclusionQuery, GL_QUERY_RESULT_AVAILABLE, &result);
+
+ if (result > 0)
+ {
+ do_query = true;
+ glGetQueryObjectuiv(mOcclusionQuery, GL_QUERY_RESULT, &result);
+ mOccluded = result == 0;
+ mOcclusionPendingFrames = 0;
+ }
+ else
+ {
+ mOcclusionPendingFrames++;
+ }
+ }
+
+ if (do_query)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("rmdo - push query");
+ glBeginQuery(GL_ANY_SAMPLES_PASSED, mOcclusionQuery);
+
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+
+ shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mOrigin.getF32ptr());
+ shader->uniform3f(LLShaderMgr::BOX_SIZE, mRadius, mRadius, mRadius);
+
+ gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(LLViewerCamera::getInstance(), mOrigin));
+
+ glEndQuery(GL_ANY_SAMPLES_PASSED);
+ }
+#endif
+}
diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h
index cf0bc2ff27..6eff607ea5 100644
--- a/indra/newview/llreflectionmap.h
+++ b/indra/newview/llreflectionmap.h
@@ -39,6 +39,8 @@ public:
// allocate an environment map of the given resolution
LLReflectionMap();
+ ~LLReflectionMap();
+
// update this environment map
// resolution - size of cube map to generate
void update(U32 resolution, U32 face);
@@ -64,6 +66,12 @@ public:
// return false if no bounding box (treat as sphere influence volume)
bool getBox(LLMatrix4& box);
+ // return true if this probe is active for rendering
+ bool isActive();
+
+ // perform occlusion query/readback
+ void doOcclusion(const LLVector4a& eye);
+
// point at which environment map was last generated from (in agent space)
LLVector4a mOrigin;
@@ -97,6 +105,14 @@ public:
LLViewerObject* mViewerObject = nullptr;
// what priority should this probe have (higher is higher priority)
- U32 mPriority = 1;
+ // currently only 0 or 1
+ // 0 - automatic probe
+ // 1 - manual probe
+ U32 mPriority = 0;
+
+ // occlusion culling state
+ GLuint mOcclusionQuery = 0;
+ bool mOccluded = false;
+ U32 mOcclusionPendingFrames = 0;
};
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index fd2906fa37..acb3612416 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -94,8 +94,8 @@ void LLReflectionMapManager::update()
if (!mRenderTarget.isComplete())
{
- U32 color_fmt = GL_RGB16F;
- U32 targetRes = mProbeResolution * 2; // super sample
+ U32 color_fmt = GL_RGB16;
+ U32 targetRes = mProbeResolution * 4; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
@@ -107,7 +107,7 @@ void LLReflectionMapManager::update()
mMipChain.resize(count);
for (int i = 0; i < count; ++i)
{
- mMipChain[i].allocate(res, res, GL_RGBA16F);
+ mMipChain[i].allocate(res, res, GL_RGBA16);
res /= 2;
}
}
@@ -157,6 +157,7 @@ void LLReflectionMapManager::update()
LLReflectionMap* closestDynamic = nullptr;
LLReflectionMap* oldestProbe = nullptr;
+ LLReflectionMap* oldestOccluded = nullptr;
if (mUpdatingProbe != nullptr)
{
@@ -179,12 +180,27 @@ void LLReflectionMapManager::update()
probe->mProbeIndex = i;
LLVector4a d;
-
- if (!did_update &&
- i < mReflectionProbeCount &&
- (oldestProbe == nullptr || probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
+
+ if (probe->mOccluded)
+ {
+ if (oldestOccluded == nullptr)
+ {
+ oldestOccluded = probe;
+ }
+ else if (probe->mLastUpdateTime < oldestOccluded->mLastUpdateTime)
+ {
+ oldestOccluded = probe;
+ }
+ }
+ else
{
- oldestProbe = probe;
+ if (!did_update &&
+ i < mReflectionProbeCount &&
+ (oldestProbe == nullptr ||
+ probe->mLastUpdateTime < oldestProbe->mLastUpdateTime))
+ {
+ oldestProbe = probe;
+ }
}
if (realtime &&
@@ -240,6 +256,13 @@ void LLReflectionMapManager::update()
doProbeUpdate();
}
+ if (oldestOccluded)
+ {
+ // as far as this occluded probe is concerned, an origin/radius update is as good as a full update
+ oldestOccluded->autoAdjustOrigin();
+ oldestOccluded->mLastUpdateTime = gFrameTimeSeconds;
+ }
+
// update distance to camera for all probes
std::sort(mProbes.begin(), mProbes.end(), CompareProbeDistance());
}
@@ -277,8 +300,11 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma
mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested
if (mProbes[i]->mCubeIndex != -1)
{
- mProbes[i]->mProbeIndex = count;
- maps[count++] = mProbes[i];
+ if (!mProbes[i]->mOccluded)
+ {
+ mProbes[i]->mProbeIndex = count;
+ maps[count++] = mProbes[i];
+ }
}
else
{
@@ -476,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();
@@ -489,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
@@ -513,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);
@@ -799,8 +835,12 @@ void LLReflectionMapManager::updateUniforms()
llassert(refmap->mCubeIndex >= 0); // should always be true, if not, getReflectionMaps is bugged
{
- //LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("rmmsu - refSphere");
+ if (refmap->mViewerObject)
+ { // have active manual probes live-track the object they're associated with
+ refmap->mOrigin.load3(refmap->mViewerObject->getPositionAgent().mV);
+ refmap->mRadius = refmap->mViewerObject->getScale().mV[0] * 0.5f;
+ }
modelview.affineTransform(refmap->mOrigin, oa);
rpd.refSphere[count].set(oa.getF32ptr());
rpd.refSphere[count].mV[3] = refmap->mRadius;
@@ -832,7 +872,7 @@ void LLReflectionMapManager::updateUniforms()
}
GLint idx = neighbor->mProbeIndex;
- if (idx == -1)
+ if (idx == -1 || neighbor->mOccluded)
{
continue;
}
@@ -1034,3 +1074,17 @@ void LLReflectionMapManager::cleanup()
// note: also called on teleport (not just shutdown), so make sure we're in a good "starting" state
initCubeFree();
}
+
+void LLReflectionMapManager::doOcclusion()
+{
+ LLVector4a eye;
+ eye.load3(LLViewerCamera::instance().getOrigin().mV);
+
+ for (auto& probe : mProbes)
+ {
+ if (probe != nullptr)
+ {
+ probe->doOcclusion(eye);
+ }
+ }
+}
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 85f428d75b..fef308541d 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -96,6 +96,9 @@ public:
// True if currently updating a radiance map, false if currently updating an irradiance map
bool isRadiancePass() { return mRadiancePass; }
+ // perform occlusion culling on all active reflection probes
+ void doOcclusion();
+
private:
friend class LLPipeline;
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index 4849015e79..6c38550049 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -251,7 +251,9 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b)
{
mCanApplyImmediately = b;
- getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately);
+ LLUICtrl *apply_checkbox = getChild<LLUICtrl>("apply_immediate_check");
+ apply_checkbox->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
+ apply_checkbox->setEnabled(mCanApplyImmediately);
}
void LLFloaterTexturePicker::stopUsingPipette()
@@ -528,7 +530,7 @@ BOOL LLFloaterTexturePicker::postBuild()
mNoCopyTextureSelected = FALSE;
- getChild<LLUICtrl>("apply_immediate_check")->setValue(gSavedSettings.getBOOL("TextureLivePreview"));
+ getChild<LLUICtrl>("apply_immediate_check")->setValue(mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview"));
childSetCommitCallback("apply_immediate_check", onApplyImmediateCheck, this);
getChildView("apply_immediate_check")->setEnabled(mCanApplyImmediately);
@@ -862,7 +864,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem
if(!mPreviewSettingChanged)
{
- mCanPreview = gSavedSettings.getBOOL("TextureLivePreview");
+ mCanPreview = mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
}
else
{
@@ -1163,7 +1165,7 @@ void LLFloaterTexturePicker::onBakeTextureSelect(LLUICtrl* ctrl, void *user_data
if (!self->mPreviewSettingChanged)
{
- self->mCanPreview = gSavedSettings.getBOOL("TextureLivePreview");
+ self->mCanPreview = self->mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview");
}
else
{
@@ -1184,7 +1186,7 @@ void LLFloaterTexturePicker::setCanApply(bool can_preview, bool can_apply)
getChildRef<LLUICtrl>("apply_immediate_check").setVisible(can_preview);
mCanApply = can_apply;
- mCanPreview = can_preview ? gSavedSettings.getBOOL("TextureLivePreview") : false;
+ mCanPreview = can_preview ? (mCanApplyImmediately && gSavedSettings.getBOOL("TextureLivePreview")) : false;
mPreviewSettingChanged = true;
}
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index f99dac6ed6..584dc5c344 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;
@@ -3187,12 +3188,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 9bd01dbdf5..867413b6c9 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 388dee00db..8d9a2a876e 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -354,7 +354,7 @@ bool addDeferredAttachments(LLRenderTarget& target, bool for_impostor = false)
bool valid = true
&& target.addColorAttachment(GL_RGBA) // frag-data[1] specular OR PBR ORM
&& target.addColorAttachment(GL_RGBA16F) // frag_data[2] normal+z+fogmask, See: class1\deferred\materialF.glsl & softenlight
- && target.addColorAttachment(GL_RGBA); // frag_data[3] PBR emissive
+ && target.addColorAttachment(GL_RGB16); // frag_data[3] PBR emissive
return valid;
}
@@ -432,6 +432,7 @@ void LLPipeline::init()
getPool(LLDrawPool::POOL_MATERIALS);
getPool(LLDrawPool::POOL_GLOW);
getPool(LLDrawPool::POOL_GLTF_PBR);
+ getPool(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK);
resetFrameStats();
@@ -801,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;
@@ -1545,6 +1546,9 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0)
case LLDrawPool::POOL_GLTF_PBR:
poolp = mPBROpaquePool;
break;
+ case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
+ poolp = mPBRAlphaMaskPool;
+ break;
default:
llassert(0);
@@ -2282,7 +2286,7 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result)
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE; //LL_RECORD_BLOCK_TIME(FTM_CULL);
LL_PROFILE_GPU_ZONE("updateCull"); // should always be zero GPU time, but drop a timer to flush stuff out
- bool water_clip = !sRenderTransparentWater;
+ bool water_clip = !sRenderTransparentWater && !sRenderingHUDs;
if (water_clip)
{
@@ -2432,6 +2436,26 @@ void LLPipeline::doOcclusion(LLCamera& camera)
LL_PROFILE_GPU_ZONE("doOcclusion");
llassert(!gCubeSnapshot);
+ if (sReflectionProbesEnabled && sUseOcclusion > 1 && !LLPipeline::sShadowRender && !gCubeSnapshot)
+ {
+ gGL.setColorMask(false, false);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+
+ gOcclusionCubeProgram.bind();
+
+ if (mCubeVB.isNull())
+ { //cube VB will be used for issuing occlusion queries
+ mCubeVB = ll_create_cube_vb(LLVertexBuffer::MAP_VERTEX);
+ }
+ mCubeVB->setBuffer();
+
+ mReflectionMapManager.doOcclusion();
+ gOcclusionCubeProgram.unbind();
+
+ gGL.setColorMask(true, true);
+ }
+
if (LLPipeline::sUseOcclusion > 1 && !LLSpatialPartition::sTeleportRequested &&
(sCull->hasOcclusionGroups() || LLVOCachePartition::sNeedsOcclusionCheck))
{
@@ -4687,7 +4711,7 @@ void LLPipeline::renderDebug()
mReflectionMapManager.renderDebug();
}
- if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes"))
+ if (gSavedSettings.getBOOL("RenderReflectionProbeVolumes") && !hud_only)
{
LL_PROFILE_ZONE_NAMED_CATEGORY_PIPELINE("probe debug display");
@@ -4740,7 +4764,7 @@ void LLPipeline::renderDebug()
}
}
- if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
+ if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !hud_only)
{
LLVertexBuffer::unbind();
@@ -5192,6 +5216,19 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp )
}
break;
+ case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
+ if (mPBRAlphaMaskPool)
+ {
+ llassert(0);
+ LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate PBR Alpha Mask Pool" << LL_ENDL;
+ }
+ else
+ {
+ mPBRAlphaMaskPool = new_poolp;
+ }
+ break;
+
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::addPool()" << LL_ENDL;
@@ -5308,6 +5345,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp )
mPBROpaquePool = NULL;
break;
+ case LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK:
+ llassert(poolp == mPBRAlphaMaskPool);
+ mPBRAlphaMaskPool = NULL;
+ break;
+
default:
llassert(0);
LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL;
@@ -7779,18 +7821,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
stop_glerror();
}
- channel = shader.enableTexture(LLShaderMgr::SCENE_MAP);
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bind(&mSceneMap);
- }
-
- channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH);
- if (channel > -1)
- {
- gGL.getTexUnit(channel)->bind(&mSceneMap, true);
- }
-
if (shader.getUniformLocation(LLShaderMgr::VIEWPORT) != -1)
{
shader.uniform4f(LLShaderMgr::VIEWPORT, (F32) gGLViewport[0],
@@ -8572,10 +8602,13 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
shader.uniform1f(LLShaderMgr::PROJECTOR_SHADOW_FADE, 1.f);
}
- //if (!gCubeSnapshot)
+ // make sure we're not already targeting the same spot light with both shadow maps
+ llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
+
+ if (!gCubeSnapshot)
{
LLDrawable* potential = drawablep;
- //determine if this is a good light for casting shadows
+ //determine if this light is higher priority than one of the existing spot shadows
F32 m_pri = volume->getSpotLightPriority();
for (U32 i = 0; i < 2; i++)
@@ -8584,7 +8617,7 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
if (mTargetShadowSpotLight[i].notNull())
{
- pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
+ pri = mTargetShadowSpotLight[i]->getVOVolume()->getSpotLightPriority();
}
if (m_pri > pri)
@@ -8597,6 +8630,9 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep)
}
}
+ // make sure we didn't end up targeting the same spot light with both shadow maps
+ llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
+
LLViewerTexture* img = volume->getLightTexture();
if (img == NULL)
@@ -8717,6 +8753,21 @@ void LLPipeline::bindReflectionProbes(LLGLSLShader& shader)
setEnvMat(shader);
}
+
+ // reflection probe shaders generally sample the scene map as well for SSR
+ channel = shader.enableTexture(LLShaderMgr::SCENE_MAP);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bind(&mSceneMap);
+ }
+
+ channel = shader.enableTexture(LLShaderMgr::SCENE_DEPTH);
+ if (channel > -1)
+ {
+ gGL.getTexUnit(channel)->bind(&mSceneMap, true);
+ }
+
+
}
void LLPipeline::unbindReflectionProbes(LLGLSLShader& shader)
@@ -9886,7 +9937,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
}
-
//hack to disable projector shadows
bool gen_shadow = RenderShadowDetail > 1;
@@ -9898,6 +9948,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
F32 fade_amt = gFrameIntervalSeconds.value()
* llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0);
+ // should never happen
+ llassert(mTargetShadowSpotLight[0] != mTargetShadowSpotLight[1] || mTargetShadowSpotLight[0].isNull());
+
//update shadow targets
for (U32 i = 0; i < 2; i++)
{ //for each current shadow
@@ -9928,6 +9981,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
}
+ // this should never happen
+ llassert(mShadowSpotLight[0] != mShadowSpotLight[1] || mShadowSpotLight[0].isNull());
+
for (S32 i = 0; i < 2; i++)
{
set_current_modelview(saved_view);
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 85878dd21d..29dd42e4ec 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -895,6 +895,8 @@ protected:
LLDrawPool* mMaterialsPool = nullptr;
LLDrawPool* mWLSkyPool = nullptr;
LLDrawPool* mPBROpaquePool = nullptr;
+ LLDrawPool* mPBRAlphaMaskPool = nullptr;
+
// Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar
public:
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 7cdf4af5c2..711be76764 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -12041,7 +12041,7 @@ Material successfully created. Asset ID: [ASSET_ID]
name="ReflectionProbeApplied"
persist="true"
type="alertmodal">
- Your object has been set to the default Reflection Probe state, which is an invisible, phantom, 5m sphere. To learn more about Reflection Probes and how to use them, see the Knowledge Base.
+ WARNING: You have made your object a Refelction Probe. Continuing to manipulate the object while it is a probe will implicitly change the object to mimic its influence volume and will make irreversible changes to the object. If you don't know what a reflection probe is, uncheck "Reflection Probe" immediately. To learn more about Reflection Probes and how to use them, see https://wiki.secondlife.com/wiki/PBR_Materials#Understanding_and_Assisting_the_New_Reflections_System.
<usetemplate ignoretext="Reflection Probe tips"
name="okignore"
yestext="OK"/>