summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorDave Parks <davep@lindenlab.com>2023-01-30 18:56:19 -0600
committerDave Parks <davep@lindenlab.com>2023-01-30 18:56:19 -0600
commit10b8dcc497599042655dcc4037c9ae98d494bd6f (patch)
tree7a3cfb43aad02f032d82d3d2fcbc52ecd0feaac0 /indra/newview
parent3ef31cb9b28f7b026e109eab69d383dddc922850 (diff)
SL-19015 Bump probe resolution back to 256 by default (drop to 128 if vram < 2GB), remove irradiance map feedback loop (one bounce, but but more stable and allows for much brighter first bounce), make sky contribution to irradiance not tint the world blue. Make irradiance that appears in radiance maps match world irradiance.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl198
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl231
-rw-r--r--indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl80
-rw-r--r--indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl7
-rw-r--r--indra/newview/featuretable.txt9
-rw-r--r--indra/newview/llenvironment.cpp51
-rw-r--r--indra/newview/llfeaturemanager.cpp4
-rw-r--r--indra/newview/llreflectionmapmanager.cpp187
-rw-r--r--indra/newview/llreflectionmapmanager.h16
-rw-r--r--indra/newview/llsettingsvo.cpp31
-rw-r--r--indra/newview/llviewerdisplay.cpp6
-rw-r--r--indra/newview/pipeline.cpp13
14 files changed, 461 insertions, 387 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d262a1285f..41afca50f6 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -10382,6 +10382,17 @@
<key>Value</key>
<integer>256</integer>
</map>
+ <key>RenderReflectionProbeResolution</key>
+ <map>
+ <key>Comment</key>
+ <string>Resolution of reflection probe radiance maps (requires restart). Will be set to the next highest power of two clamped to [64, 512]. Note that changing this value may consume a massive amount of video memory.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>256</integer>
+ </map>
<key>RenderReflectionProbeDrawDistance</key>
<map>
diff --git a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
index 3e056aa048..2b1e794b52 100644
--- a/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl
@@ -23,205 +23,11 @@
* $/LicenseInfo$
*/
+// debug stub
-/*[EXTRA_CODE_HERE]*/
-
-
-#ifdef DEFINE_GL_FRAGCOLOR
out vec4 frag_color;
-#else
-#define frag_color gl_FragColor
-#endif
-
-uniform samplerCubeArray reflectionProbes;
-uniform int sourceIdx;
-
-VARYING vec3 vary_dir;
-
-
-// Code below is derived from the Khronos GLTF Sample viewer:
-// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag
-
-
-#define MATH_PI 3.1415926535897932384626433832795
-
-float u_roughness = 1.0;
-int u_sampleCount = 16;
-float u_lodBias = 2.0;
-int u_width = 64;
-
-// Hammersley Points on the Hemisphere
-// CC BY 3.0 (Holger Dammertz)
-// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
-// with adapted interface
-float radicalInverse_VdC(uint bits)
-{
- bits = (bits << 16u) | (bits >> 16u);
- bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
- bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
- bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
- bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
- return float(bits) * 2.3283064365386963e-10; // / 0x100000000
-}
-
-// hammersley2d describes a sequence of points in the 2d unit square [0,1)^2
-// that can be used for quasi Monte Carlo integration
-vec2 hammersley2d(int i, int N) {
- return vec2(float(i)/float(N), radicalInverse_VdC(uint(i)));
-}
-
-// Hemisphere Sample
-
-// TBN generates a tangent bitangent normal coordinate frame from the normal
-// (the normal must be normalized)
-mat3 generateTBN(vec3 normal)
-{
- vec3 bitangent = vec3(0.0, 1.0, 0.0);
-
- float NdotUp = dot(normal, vec3(0.0, 1.0, 0.0));
- float epsilon = 0.0000001;
- /*if (1.0 - abs(NdotUp) <= epsilon)
- {
- // Sampling +Y or -Y, so we need a more robust bitangent.
- if (NdotUp > 0.0)
- {
- bitangent = vec3(0.0, 0.0, 1.0);
- }
- else
- {
- bitangent = vec3(0.0, 0.0, -1.0);
- }
- }*/
-
- vec3 tangent = normalize(cross(bitangent, normal));
- bitangent = cross(normal, tangent);
-
- return mat3(tangent, bitangent, normal);
-}
-
-struct MicrofacetDistributionSample
-{
- float pdf;
- float cosTheta;
- float sinTheta;
- float phi;
-};
-
-MicrofacetDistributionSample Lambertian(vec2 xi, float roughness)
-{
- MicrofacetDistributionSample lambertian;
-
- // Cosine weighted hemisphere sampling
- // http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#Cosine-WeightedHemisphereSampling
- lambertian.cosTheta = sqrt(1.0 - xi.y);
- lambertian.sinTheta = sqrt(xi.y); // equivalent to `sqrt(1.0 - cosTheta*cosTheta)`;
- lambertian.phi = 2.0 * MATH_PI * xi.x;
-
- lambertian.pdf = lambertian.cosTheta / MATH_PI; // evaluation for solid angle, therefore drop the sinTheta
-
- return lambertian;
-}
-
-// getImportanceSample returns an importance sample direction with pdf in the .w component
-vec4 getImportanceSample(int sampleIndex, vec3 N, float roughness)
-{
- // generate a quasi monte carlo point in the unit square [0.1)^2
- vec2 xi = hammersley2d(sampleIndex, u_sampleCount);
-
- MicrofacetDistributionSample importanceSample;
-
- // generate the points on the hemisphere with a fitting mapping for
- // the distribution (e.g. lambertian uses a cosine importance)
- importanceSample = Lambertian(xi, roughness);
-
- // transform the hemisphere sample to the normal coordinate frame
- // i.e. rotate the hemisphere to the normal direction
- vec3 localSpaceDirection = normalize(vec3(
- importanceSample.sinTheta * cos(importanceSample.phi),
- importanceSample.sinTheta * sin(importanceSample.phi),
- importanceSample.cosTheta
- ));
- mat3 TBN = generateTBN(N);
- vec3 direction = TBN * localSpaceDirection;
-
- return vec4(direction, importanceSample.pdf);
-}
-
-// Mipmap Filtered Samples (GPU Gems 3, 20.4)
-// https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-20-gpu-based-importance-sampling
-// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
-float computeLod(float pdf)
-{
- // // Solid angle of current sample -- bigger for less likely samples
- // float omegaS = 1.0 / (float(u_sampleCount) * pdf);
- // // Solid angle of texel
- // // note: the factor of 4.0 * MATH_PI
- // float omegaP = 4.0 * MATH_PI / (6.0 * float(u_width) * float(u_width));
- // // Mip level is determined by the ratio of our sample's solid angle to a texel's solid angle
- // // note that 0.5 * log2 is equivalent to log4
- // float lod = 0.5 * log2(omegaS / omegaP);
-
- // babylon introduces a factor of K (=4) to the solid angle ratio
- // this helps to avoid undersampling the environment map
- // this does not appear in the original formulation by Jaroslav Krivanek and Mark Colbert
- // log4(4) == 1
- // lod += 1.0;
-
- // We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps
-
- // https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
- float lod = 0.5 * log2( 6.0 * float(u_width) * float(u_width) / (float(u_sampleCount) * pdf));
-
-
- return lod;
-}
-
-vec4 filterColor(vec3 N)
-{
- //return textureLod(uCubeMap, N, 3.0).rgb;
- vec4 color = vec4(0.f);
- float weight = 0.0f;
-
- for(int i = 0; i < u_sampleCount; ++i)
- {
- vec4 importanceSample = getImportanceSample(i, N, 1.0);
-
- vec3 H = vec3(importanceSample.xyz);
- float pdf = importanceSample.w;
-
- // mipmap filtered samples (GPU Gems 3, 20.4)
- float lod = computeLod(pdf);
-
- // apply the bias to the lod
- lod += u_lodBias;
-
- lod = clamp(lod, 0, 6);
- // sample lambertian at a lower resolution to avoid fireflies
- vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod);
-
- color += lambertian;
- }
-
- if(weight != 0.0f)
- {
- color /= weight;
- }
- else
- {
- color /= float(u_sampleCount);
- }
-
- return min(color*1.9, vec4(1));
-}
-
-// entry point
void main()
{
- vec4 color = vec4(0);
-
- color = filterColor(vary_dir);
-
- frag_color = color;
+ frag_color = vec4(0.5, 0, 0.5, 0);
}
-
diff --git a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
index 858052281b..e60ddcd569 100644
--- a/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl
@@ -37,6 +37,8 @@ VARYING vec3 vary_dir;
uniform float mipLevel;
uniform int u_width;
+uniform float max_probe_lod;
+
// =============================================================================================================
// Parts of this file are (c) 2018 Sascha Willems
@@ -128,7 +130,7 @@ vec4 prefilterEnvMap(vec3 R)
float envMapDim = u_width;
int numSamples = 4;
- float numMips = 6.0;
+ float numMips = max_probe_lod;
float roughness = mipLevel/numMips;
diff --git a/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
new file mode 100644
index 0000000000..a4aec48c59
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl
@@ -0,0 +1,231 @@
+/**
+ * @file irradianceGenF.glsl
+ *
+ * $LicenseInfo:firstyear=2022&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2022, 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$
+ */
+
+
+/*[EXTRA_CODE_HERE]*/
+
+
+#ifdef DEFINE_GL_FRAGCOLOR
+out vec4 frag_color;
+#else
+#define frag_color gl_FragColor
+#endif
+
+uniform samplerCubeArray reflectionProbes;
+uniform int sourceIdx;
+
+uniform float max_probe_lod;
+
+VARYING vec3 vary_dir;
+
+
+// Code below is derived from the Khronos GLTF Sample viewer:
+// https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/shaders/ibl_filtering.frag
+
+
+#define MATH_PI 3.1415926535897932384626433832795
+
+float u_roughness = 1.0;
+int u_sampleCount = 64;
+float u_lodBias = 2.0;
+int u_width = 64;
+
+// Hammersley Points on the Hemisphere
+// CC BY 3.0 (Holger Dammertz)
+// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
+// with adapted interface
+float radicalInverse_VdC(uint bits)
+{
+ bits = (bits << 16u) | (bits >> 16u);
+ bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
+ bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
+ bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
+ bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
+ return float(bits) * 2.3283064365386963e-10; // / 0x100000000
+}
+
+// hammersley2d describes a sequence of points in the 2d unit square [0,1)^2
+// that can be used for quasi Monte Carlo integration
+vec2 hammersley2d(int i, int N) {
+ return vec2(float(i)/float(N), radicalInverse_VdC(uint(i)));
+}
+
+// Hemisphere Sample
+
+// TBN generates a tangent bitangent normal coordinate frame from the normal
+// (the normal must be normalized)
+mat3 generateTBN(vec3 normal)
+{
+ vec3 bitangent = vec3(0.0, 1.0, 0.0);
+
+ float NdotUp = dot(normal, vec3(0.0, 1.0, 0.0));
+ float epsilon = 0.0000001;
+ /*if (1.0 - abs(NdotUp) <= epsilon)
+ {
+ // Sampling +Y or -Y, so we need a more robust bitangent.
+ if (NdotUp > 0.0)
+ {
+ bitangent = vec3(0.0, 0.0, 1.0);
+ }
+ else
+ {
+ bitangent = vec3(0.0, 0.0, -1.0);
+ }
+ }*/
+
+ vec3 tangent = normalize(cross(bitangent, normal));
+ bitangent = cross(normal, tangent);
+
+ return mat3(tangent, bitangent, normal);
+}
+
+struct MicrofacetDistributionSample
+{
+ float pdf;
+ float cosTheta;
+ float sinTheta;
+ float phi;
+};
+
+MicrofacetDistributionSample Lambertian(vec2 xi, float roughness)
+{
+ MicrofacetDistributionSample lambertian;
+
+ // Cosine weighted hemisphere sampling
+ // http://www.pbr-book.org/3ed-2018/Monte_Carlo_Integration/2D_Sampling_with_Multidimensional_Transformations.html#Cosine-WeightedHemisphereSampling
+ lambertian.cosTheta = sqrt(1.0 - xi.y);
+ lambertian.sinTheta = sqrt(xi.y); // equivalent to `sqrt(1.0 - cosTheta*cosTheta)`;
+ lambertian.phi = 2.0 * MATH_PI * xi.x;
+
+ lambertian.pdf = lambertian.cosTheta / MATH_PI; // evaluation for solid angle, therefore drop the sinTheta
+
+ return lambertian;
+}
+
+
+// getImportanceSample returns an importance sample direction with pdf in the .w component
+vec4 getImportanceSample(int sampleIndex, vec3 N, float roughness)
+{
+ // generate a quasi monte carlo point in the unit square [0.1)^2
+ vec2 xi = hammersley2d(sampleIndex, u_sampleCount);
+
+ MicrofacetDistributionSample importanceSample;
+
+ // generate the points on the hemisphere with a fitting mapping for
+ // the distribution (e.g. lambertian uses a cosine importance)
+ importanceSample = Lambertian(xi, roughness);
+
+ // transform the hemisphere sample to the normal coordinate frame
+ // i.e. rotate the hemisphere to the normal direction
+ vec3 localSpaceDirection = normalize(vec3(
+ importanceSample.sinTheta * cos(importanceSample.phi),
+ importanceSample.sinTheta * sin(importanceSample.phi),
+ importanceSample.cosTheta
+ ));
+ mat3 TBN = generateTBN(N);
+ vec3 direction = TBN * localSpaceDirection;
+
+ return vec4(direction, importanceSample.pdf);
+}
+
+// Mipmap Filtered Samples (GPU Gems 3, 20.4)
+// https://developer.nvidia.com/gpugems/gpugems3/part-iii-rendering/chapter-20-gpu-based-importance-sampling
+// https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
+float computeLod(float pdf)
+{
+ // // Solid angle of current sample -- bigger for less likely samples
+ // float omegaS = 1.0 / (float(u_sampleCount) * pdf);
+ // // Solid angle of texel
+ // // note: the factor of 4.0 * MATH_PI
+ // float omegaP = 4.0 * MATH_PI / (6.0 * float(u_width) * float(u_width));
+ // // Mip level is determined by the ratio of our sample's solid angle to a texel's solid angle
+ // // note that 0.5 * log2 is equivalent to log4
+ // float lod = 0.5 * log2(omegaS / omegaP);
+
+ // babylon introduces a factor of K (=4) to the solid angle ratio
+ // this helps to avoid undersampling the environment map
+ // this does not appear in the original formulation by Jaroslav Krivanek and Mark Colbert
+ // log4(4) == 1
+ // lod += 1.0;
+
+ // We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps
+
+ // https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf
+ float lod = 0.5 * log2( 6.0 * float(u_width) * float(u_width) / (float(u_sampleCount) * pdf));
+
+
+ return lod;
+}
+
+vec4 filterColor(vec3 N)
+{
+ //return textureLod(uCubeMap, N, 3.0).rgb;
+ vec4 color = vec4(0.f);
+ float weight = 0.0f;
+
+ for(int i = 0; i < u_sampleCount; ++i)
+ {
+ vec4 importanceSample = getImportanceSample(i, N, 1.0);
+
+ vec3 H = vec3(importanceSample.xyz);
+ float pdf = importanceSample.w;
+
+ // mipmap filtered samples (GPU Gems 3, 20.4)
+ float lod = computeLod(pdf);
+
+ // apply the bias to the lod
+ lod += u_lodBias;
+
+ lod = clamp(lod, 0, max_probe_lod);
+ // sample lambertian at a lower resolution to avoid fireflies
+ vec4 lambertian = textureLod(reflectionProbes, vec4(H, sourceIdx), lod);
+
+ color += lambertian;
+ }
+
+ if(weight != 0.0f)
+ {
+ color /= weight;
+ }
+ else
+ {
+ color /= float(u_sampleCount);
+ }
+
+ color = min(color*1.9, vec4(1));
+ color = pow(color, vec4(0.5));
+ return color;
+}
+
+// entry point
+void main()
+{
+ vec4 color = vec4(0);
+
+ color = filterColor(vary_dir);
+
+ frag_color = color;
+}
+
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
index c69eba93b6..ba02070e45 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl
@@ -162,90 +162,10 @@ float ambientLighting(vec3 norm, vec3 light_dir)
void calcAtmosphericVarsLinear(vec3 inPositionEye, vec3 norm, vec3 light_dir, out vec3 sunlit, out vec3 amblit, out vec3 additive,
out vec3 atten)
{
-#if 1
calcAtmosphericVars(inPositionEye, light_dir, 1.0, sunlit, amblit, additive, atten, false);
sunlit = srgb_to_linear(sunlit);
additive = srgb_to_linear(additive);
amblit = ambient_linear;
amblit *= ambientLighting(norm, light_dir);
-#else
-
- //EXPERIMENTAL -- attempt to factor out srgb_to_linear conversions above
- vec3 rel_pos = inPositionEye;
-
- //(TERRAIN) limit altitude
- if (abs(rel_pos.y) > max_y) rel_pos *= (max_y / rel_pos.y);
-
- vec3 rel_pos_norm = normalize(rel_pos);
- float rel_pos_len = length(rel_pos);
- vec3 sunlight = (sun_up_factor == 1) ? vec3(sunlight_linear, 0.0) : vec3(moonlight_linear, 0.0);
-
- // sunlight attenuation effect (hue and brightness) due to atmosphere
- // this is used later for sunlight modulation at various altitudes
- vec3 light_atten = (blue_density + vec3(haze_density * 0.25)) * (density_multiplier * max_y);
- // I had thought blue_density and haze_density should have equal weighting,
- // but attenuation due to haze_density tends to seem too strong
-
- vec3 combined_haze = blue_density + vec3(haze_density);
- vec3 blue_weight = blue_density / combined_haze;
- vec3 haze_weight = vec3(haze_density) / combined_haze;
-
- //(TERRAIN) compute sunlight from lightnorm y component. Factor is roughly cosecant(sun elevation) (for short rays like terrain)
- float above_horizon_factor = 1.0 / max(1e-6, lightnorm.y);
- sunlight *= exp(-light_atten * above_horizon_factor); // for sun [horizon..overhead] this maps to an exp curve [0..1]
-
- // main atmospheric scattering line integral
- float density_dist = rel_pos_len * density_multiplier;
-
- // Transparency (-> combined_haze)
- // ATI Bugfix -- can't store combined_haze*density_dist*distance_multiplier in a variable because the ati
- // compiler gets confused.
- combined_haze = exp(-combined_haze * density_dist * distance_multiplier);
-
- // final atmosphere attenuation factor
- atten = combined_haze.rgb;
-
- // compute haze glow
- float haze_glow = dot(rel_pos_norm, lightnorm.xyz);
-
- // dampen sun additive contrib when not facing it...
- // SL-13539: This "if" clause causes an "additive" white artifact at roughly 77 degreees.
- // if (length(light_dir) > 0.01)
- haze_glow *= max(0.0f, dot(light_dir, rel_pos_norm));
-
- haze_glow = 1. - haze_glow;
- // haze_glow is 0 at the sun and increases away from sun
- haze_glow = max(haze_glow, .001); // set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
- haze_glow *= glow.x;
- // higher glow.x gives dimmer glow (because next step is 1 / "angle")
- haze_glow = pow(haze_glow, glow.z);
- // glow.z should be negative, so we're doing a sort of (1 / "angle") function
-
- // add "minimum anti-solar illumination"
- haze_glow += .25;
-
- haze_glow *= sun_moon_glow_factor;
-
- //vec3 amb_color = vec4(ambient_linear, 0.0);
- vec3 amb_color = ambient_color;
-
- // increase ambient when there are more clouds
- vec3 tmpAmbient = amb_color + (vec3(1.) - amb_color) * cloud_shadow * 0.5;
-
- // Similar/Shared Algorithms:
- // indra\llinventory\llsettingssky.cpp -- LLSettingsSky::calculateLightSettings()
- // indra\newview\app_settings\shaders\class1\windlight\atmosphericsFuncs.glsl -- calcAtmosphericVars()
- // haze color
- vec3 cs = sunlight.rgb * (1. - cloud_shadow);
- additive = (blue_horizon.rgb * blue_weight.rgb) * (cs + tmpAmbient.rgb) + (haze_horizon * haze_weight.rgb) * (cs * haze_glow + tmpAmbient.rgb);
-
- // brightness of surface both sunlight and ambient
- sunlit = min(sunlight.rgb, vec3(1));
- amblit = tmpAmbient.rgb;
- additive *= vec3(1.0 - combined_haze);
-
- //sunlit = sunlight_linear;
- amblit = ambient_linear*0.8;
-#endif
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
index 9793ab13de..bb3be7260b 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl
@@ -36,6 +36,7 @@ uniform samplerCubeArray reflectionProbes;
uniform samplerCubeArray irradianceProbes;
uniform sampler2D sceneMap;
uniform int cube_snapshot;
+uniform float max_probe_lod;
layout (std140) uniform ReflectionProbes
{
@@ -623,7 +624,7 @@ vec3 sampleProbeAmbient(vec3 pos, vec3 dir)
{
col *= 1.0/wsum;
}
-
+
return col;
}
@@ -631,7 +632,7 @@ void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv,
vec2 tc, vec3 pos, vec3 norm, float glossiness, bool errorCorrect)
{
// TODO - don't hard code lods
- float reflection_lods = 6;
+ float reflection_lods = max_probe_lod;
preProbeSample(pos);
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
@@ -705,7 +706,7 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout
vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity)
{
// TODO - don't hard code lods
- float reflection_lods = 7;
+ float reflection_lods = max_probe_lod;
preProbeSample(pos);
vec3 refnormpersp = reflect(pos.xyz, norm.xyz);
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index 2821b63391..5bd74fe318 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 46
+version 47
// 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
@@ -72,6 +72,7 @@ RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
RenderGLContextCoreProfile 1 1
RenderGLMultiThreaded 1 0
+RenderReflectionProbeResolution 1 256
//
@@ -272,6 +273,12 @@ 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/llenvironment.cpp b/indra/newview/llenvironment.cpp
index efe4ad2af2..6d600efe37 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -1630,28 +1630,31 @@ LLVector4 LLEnvironment::getRotatedLightNorm() const
return toLightNorm(light_direction);
}
+extern BOOL gCubeSnapshot;
+
//-------------------------------------------------------------------------
void LLEnvironment::update(const LLViewerCamera * cam)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT; //LL_RECORD_BLOCK_TIME(FTM_ENVIRONMENT_UPDATE);
//F32Seconds now(LLDate::now().secondsSinceEpoch());
- static LLFrameTimer timer;
-
- F32Seconds delta(timer.getElapsedTimeAndResetF32());
-
+ if (!gCubeSnapshot)
{
- DayInstance::ptr_t keeper = mCurrentEnvironment;
- // make sure the current environment does not go away until applyTimeDelta is done.
- mCurrentEnvironment->applyTimeDelta(delta);
+ static LLFrameTimer timer;
- }
- // update clouds, sun, and general
- updateCloudScroll();
+ F32Seconds delta(timer.getElapsedTimeAndResetF32());
- // cache this for use in rotating the rotated light vec for shader param updates later...
- mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW;
+ {
+ DayInstance::ptr_t keeper = mCurrentEnvironment;
+ // make sure the current environment does not go away until applyTimeDelta is done.
+ mCurrentEnvironment->applyTimeDelta(delta);
+
+ }
+ // update clouds, sun, and general
+ updateCloudScroll();
- stop_glerror();
+ // cache this for use in rotating the rotated light vec for shader param updates later...
+ mLastCamYaw = cam->getYaw() + SUN_DELTA_YAW;
+ }
updateSettingsUniforms();
@@ -1752,13 +1755,23 @@ void LLEnvironment::updateGLVariablesForSettings(LLShaderUniforms* uniforms, con
{
LLVector4 vect4(value);
- switch (it.second.getShaderKey())
- { // convert to linear color space if this is a color parameter
- case LLShaderMgr::BLUE_HORIZON:
- case LLShaderMgr::BLUE_DENSITY:
- //vect4 = LLVector4(linearColor4(LLColor4(vect4.mV)).mV);
- break;
+ if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass())
+ { // maximize and remove tinting if this is an irradiance map render pass and the parameter feeds into the sky background color
+ auto max_vec = [](LLVector4 col)
+ {
+ col.mV[0] = col.mV[1] = col.mV[2] = llmax(llmax(col.mV[0], col.mV[1]), col.mV[2]);
+ return col;
+ };
+
+ switch (it.second.getShaderKey())
+ {
+ case LLShaderMgr::BLUE_HORIZON:
+ case LLShaderMgr::BLUE_DENSITY:
+ vect4 = max_vec(vect4);
+ break;
+ }
}
+
//_WARNS("RIDER") << "pushing '" << (*it).first << "' as " << vect4 << LL_ENDL;
shader->uniform3fv(it.second.getShaderKey(), LLVector3(vect4.mV) );
break;
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 5817fdbfa0..3b1bee05af 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -651,6 +651,10 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("VRAMGT512");
}
+ if (gGLManager.mVRAM < 2048)
+ {
+ maskFeatures("VRAMLT2GB");
+ }
if (gGLManager.mGLVersion < 3.99f)
{
maskFeatures("GL3");
diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp
index 128aa99ccc..ee05849130 100644
--- a/indra/newview/llreflectionmapmanager.cpp
+++ b/indra/newview/llreflectionmapmanager.cpp
@@ -39,6 +39,10 @@
extern BOOL gCubeSnapshot;
extern BOOL gTeleportDisplay;
+// get the next highest power of two of v (or v if v is already a power of two)
+//defined in llvertexbuffer.cpp
+extern U32 nhpo2(U32 v);
+
static void touch_default_probe(LLReflectionMap* probe)
{
LLVector3 origin = LLViewerCamera::getInstance()->getOrigin();
@@ -91,13 +95,13 @@ void LLReflectionMapManager::update()
if (!mRenderTarget.isComplete())
{
U32 color_fmt = GL_RGB16F;
- U32 targetRes = LL_REFLECTION_PROBE_RESOLUTION * 2; // super sample
+ U32 targetRes = mProbeResolution * 2; // super sample
mRenderTarget.allocate(targetRes, targetRes, color_fmt, true);
}
if (mMipChain.empty())
{
- U32 res = LL_REFLECTION_PROBE_RESOLUTION;
+ U32 res = mProbeResolution;
U32 count = log2((F32)res) + 0.5f;
mMipChain.resize(count);
@@ -401,11 +405,27 @@ void LLReflectionMapManager::doProbeUpdate()
if (++mUpdatingFace == 6)
{
updateNeighbors(mUpdatingProbe);
- mUpdatingProbe = nullptr;
mUpdatingFace = 0;
+ if (mRadiancePass)
+ {
+ mUpdatingProbe = nullptr;
+ mRadiancePass = false;
+ }
+ else
+ {
+ mRadiancePass = true;
+ }
}
}
+// Do the reflection map update render passes.
+// For every 12 calls of this function, one complete reflection probe radiance map and irradiance map is generated
+// First six passes render the scene with direct lighting only into a scratch space cube map at the end of the cube map array and generate
+// a simple mip chain (not convolution filter).
+// At the end of these passes, an irradiance map is generated for this probe and placed into the irradiance cube map array at the index for this probe
+// The next six passes render the scene with both radiance and irradiance into the same scratch space cube map and generate a simple mip chain.
+// At the end of these passes, a radiance map is generated for this probe and placed into the radiance cube map array at the index for this probe.
+// In effect this simulates single-bounce lighting.
void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
{
// hacky hot-swap of camera specific render targets
@@ -432,11 +452,11 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gPipeline.mRT = &gPipeline.mMainRT;
- S32 targetIdx = mReflectionProbeCount;
+ S32 sourceIdx = mReflectionProbeCount;
if (probe != mUpdatingProbe)
{ // this is the "realtime" probe that's updating every frame, use the secondary scratch space channel
- targetIdx += 1;
+ sourceIdx += 1;
}
gGL.setColorMask(true, true);
@@ -457,9 +477,9 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
gGL.loadIdentity();
gGL.flush();
- U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
+ U32 res = mProbeResolution * 2;
- S32 mips = log2((F32)LL_REFLECTION_PROBE_RESOLUTION) + 0.5f;
+ S32 mips = log2((F32)mProbeResolution) + 0.5f;
S32 diffuseChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_TEXTURE);
S32 depthChannel = gReflectionMipProgram.enableTexture(LLShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_TEXTURE);
@@ -516,7 +536,7 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
LL_PROFILE_GPU_ZONE("probe mip copy");
mTexture->bind(0);
//glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, targetIdx * 6 + face, 0, 0, res, res);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, sourceIdx * 6 + face, 0, 0, res, res);
//if (i == 0)
//{
//glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, 0, 0, probe->mCubeIndex * 6 + face, 0, 0, res, res);
@@ -537,89 +557,98 @@ void LLReflectionMapManager::updateProbeFace(LLReflectionMap* probe, U32 face)
if (face == 5)
{
- //generate radiance map
- gRadianceGenProgram.bind();
- mVertexBuffer->setBuffer();
-
- S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
- mTexture->bind(channel);
- static LLStaticHashedString sSourceIdx("sourceIdx");
- gRadianceGenProgram.uniform1i(sSourceIdx, targetIdx);
-
mMipChain[0].bindTarget();
- U32 res = mMipChain[0].getWidth();
+ static LLStaticHashedString sSourceIdx("sourceIdx");
- for (int i = 0; i < mMipChain.size(); ++i)
+ if (mRadiancePass)
{
- LL_PROFILE_GPU_ZONE("probe radiance gen");
- static LLStaticHashedString sMipLevel("mipLevel");
- static LLStaticHashedString sRoughness("roughness");
- static LLStaticHashedString sWidth("u_width");
+ //generate radiance map (even if this is not the irradiance map, we need the mip chain for the irradiance map)
+ gRadianceGenProgram.bind();
+ mVertexBuffer->setBuffer();
- gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
- gRadianceGenProgram.uniform1f(sMipLevel, i);
- gRadianceGenProgram.uniform1i(sWidth, mMipChain[i].getWidth());
+ S32 channel = gRadianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+ gRadianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
+ gRadianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
- for (int cf = 0; cf < 6; ++cf)
- { // for each cube face
- LLCoordFrame frame;
- frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
+ U32 res = mMipChain[0].getWidth();
- F32 mat[16];
- frame.getOpenGLRotation(mat);
- gGL.loadMatrix(mat);
+ for (int i = 0; i < mMipChain.size(); ++i)
+ {
+ LL_PROFILE_GPU_ZONE("probe radiance gen");
+ static LLStaticHashedString sMipLevel("mipLevel");
+ static LLStaticHashedString sRoughness("roughness");
+ static LLStaticHashedString sWidth("u_width");
- mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
-
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
- }
+ gRadianceGenProgram.uniform1f(sRoughness, (F32)i / (F32)(mMipChain.size() - 1));
+ gRadianceGenProgram.uniform1f(sMipLevel, i);
+ gRadianceGenProgram.uniform1i(sWidth, mMipChain[i].getWidth());
- if (i != mMipChain.size() - 1)
- {
- res /= 2;
- glViewport(0, 0, res, res);
- }
- }
+ for (int cf = 0; cf < 6; ++cf)
+ { // for each cube face
+ LLCoordFrame frame;
+ frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
+
+ F32 mat[16];
+ frame.getOpenGLRotation(mat);
+ gGL.loadMatrix(mat);
+
+ mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
- gRadianceGenProgram.unbind();
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
+ }
- //generate irradiance map
- gIrradianceGenProgram.bind();
- channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
- mTexture->bind(channel);
+ if (i != mMipChain.size() - 1)
+ {
+ res /= 2;
+ glViewport(0, 0, res, res);
+ }
+ }
- gIrradianceGenProgram.uniform1i(sSourceIdx, targetIdx);
- mVertexBuffer->setBuffer();
- int start_mip = 0;
- // find the mip target to start with based on irradiance map resolution
- for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip)
+ gRadianceGenProgram.unbind();
+ }
+ else if (!mRadiancePass)
{
- if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION)
+ //generate irradiance map
+ gIrradianceGenProgram.bind();
+ S32 channel = gIrradianceGenProgram.enableTexture(LLShaderMgr::REFLECTION_PROBES, LLTexUnit::TT_CUBE_MAP_ARRAY);
+ mTexture->bind(channel);
+
+ gIrradianceGenProgram.uniform1i(sSourceIdx, sourceIdx);
+ gIrradianceGenProgram.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mMaxProbeLOD);
+
+ mVertexBuffer->setBuffer();
+ int start_mip = 0;
+ // find the mip target to start with based on irradiance map resolution
+ for (start_mip = 0; start_mip < mMipChain.size(); ++start_mip)
{
- break;
+ if (mMipChain[start_mip].getWidth() == LL_IRRADIANCE_MAP_RESOLUTION)
+ {
+ break;
+ }
}
- }
- //for (int i = start_mip; i < mMipChain.size(); ++i)
- {
- int i = start_mip;
- LL_PROFILE_GPU_ZONE("probe irradiance gen");
- glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight());
- for (int cf = 0; cf < 6; ++cf)
- { // for each cube face
- LLCoordFrame frame;
- frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
-
- F32 mat[16];
- frame.getOpenGLRotation(mat);
- gGL.loadMatrix(mat);
-
- mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
-
- S32 res = mMipChain[i].getWidth();
- mIrradianceMaps->bind(channel);
- glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
- mTexture->bind(channel);
+ //for (int i = start_mip; i < mMipChain.size(); ++i)
+ {
+ int i = start_mip;
+ LL_PROFILE_GPU_ZONE("probe irradiance gen");
+ glViewport(0, 0, mMipChain[i].getWidth(), mMipChain[i].getHeight());
+ for (int cf = 0; cf < 6; ++cf)
+ { // for each cube face
+ LLCoordFrame frame;
+ frame.lookAt(LLVector3(0, 0, 0), LLCubeMapArray::sClipToCubeLookVecs[cf], LLCubeMapArray::sClipToCubeUpVecs[cf]);
+
+ F32 mat[16];
+ frame.getOpenGLRotation(mat);
+ gGL.loadMatrix(mat);
+
+ mVertexBuffer->drawArrays(gGL.TRIANGLE_STRIP, 0, 4);
+
+ S32 res = mMipChain[i].getWidth();
+ mIrradianceMaps->bind(channel);
+ glCopyTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, i - start_mip, 0, 0, probe->mCubeIndex * 6 + cf, 0, 0, res, res);
+ mTexture->bind(channel);
+ }
}
}
@@ -722,7 +751,7 @@ void LLReflectionMapManager::updateUniforms()
LLSettingsSky::ptr_t psky = environment.getCurrentSky();
F32 minimum_ambiance = psky->getTotalReflectionProbeAmbiance();
- F32 ambscale = gCubeSnapshot ? 0.5f : 1.f;
+ F32 ambscale = gCubeSnapshot && !mRadiancePass ? 0.f : 1.f;
for (auto* refmap : mReflectionMaps)
{
@@ -912,12 +941,14 @@ void LLReflectionMapManager::initReflectionMaps()
{
if (mTexture.isNull())
{
+ mProbeResolution = nhpo2(llclamp(gSavedSettings.getU32("RenderReflectionProbeResolution"), (U32)64, (U32)512));
+ mMaxProbeLOD = log2f(mProbeResolution) - 1.f; // number of mips - 1
mReflectionProbeCount = llclamp(gSavedSettings.getS32("RenderReflectionProbeCount"), 1, LL_MAX_REFLECTION_PROBE_COUNT);
mTexture = new LLCubeMapArray();
// store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source)
- mTexture->allocate(LL_REFLECTION_PROBE_RESOLUTION, 4, mReflectionProbeCount + 2);
+ mTexture->allocate(mProbeResolution, 4, mReflectionProbeCount + 2);
mIrradianceMaps = new LLCubeMapArray();
mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 4, mReflectionProbeCount, FALSE);
diff --git a/indra/newview/llreflectionmapmanager.h b/indra/newview/llreflectionmapmanager.h
index 14a6c089da..5936b26b88 100644
--- a/indra/newview/llreflectionmapmanager.h
+++ b/indra/newview/llreflectionmapmanager.h
@@ -38,7 +38,6 @@ class LLViewerObject;
#define LL_MAX_REFLECTION_PROBE_COUNT 256
// reflection probe resolution
-#define LL_REFLECTION_PROBE_RESOLUTION 128
#define LL_IRRADIANCE_MAP_RESOLUTION 64
// reflection probe mininum scale
@@ -94,6 +93,9 @@ public:
// call once at startup to allocate cubemap arrays
void initReflectionMaps();
+ // True if currently updating a radiance map, false if currently updating an irradiance map
+ bool isRadiancePass() { return mRadiancePass; }
+
private:
friend class LLPipeline;
@@ -161,9 +163,21 @@ private:
LLReflectionMap* mUpdatingProbe = nullptr;
U32 mUpdatingFace = 0;
+ // if true, we're generating the radiance map for the current probe, otherwise we're generating the irradiance map.
+ // Update sequence should be to generate the irradiance map from render of the world that has no irradiance,
+ // then generate the radiance map from a render of the world that includes irradiance.
+ // This should avoid feedback loops and ensure that the colors in the radiance maps match the colors in the environment.
+ bool mRadiancePass = false;
+
LLPointer<LLReflectionMap> mDefaultProbe; // default reflection probe to fall back to for pixels with no probe influences (should always be at cube index 0)
// number of reflection probes to use for rendering (based on saved setting RenderReflectionProbeCount)
U32 mReflectionProbeCount;
+
+ // resolution of reflection probes
+ U32 mProbeResolution = 128;
+
+ // maximum LoD of reflection probes (mip levels - 1)
+ F32 mMaxProbeLOD = 6.f;
};
diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp
index 870ac6bd5a..a49bd11ffd 100644
--- a/indra/newview/llsettingsvo.cpp
+++ b/indra/newview/llsettingsvo.cpp
@@ -68,6 +68,8 @@
#undef VERIFY_LEGACY_CONVERSION
+extern BOOL gCubeSnapshot;
+
//=========================================================================
namespace
{
@@ -714,7 +716,26 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
LLColor3 ambient(getTotalAmbient());
shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV));
- shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor()/3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT
+
+ if (gCubeSnapshot && !gPipeline.mReflectionMapManager.isRadiancePass())
+ { // during an irradiance map update, disable ambient lighting (direct lighting only) and desaturate sky color (avoid tinting the world blue)
+ shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, LLVector3::zero.mV);
+
+ auto max_vec = [](LLVector3 col)
+ {
+ col.mV[0] = col.mV[1] = col.mV[2] = llmax(llmax(col.mV[0], col.mV[1]), col.mV[2]);
+ return col;
+ };
+ shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, max_vec(linearColor3v(getBlueHorizon() / 2.f))); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY
+ shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, max_vec(linearColor3v(getBlueDensity() / 2.f)));
+ }
+ else
+ {
+ shader->uniform3fv(LLShaderMgr::AMBIENT_LINEAR, linearColor3v(getAmbientColor() / 3.f)); // note magic number 3.f comes from SLIDER_SCALE_SUN_AMBIENT
+ shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon() / 2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY
+ shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity() / 2.f));
+ }
+
shader->uniform3fv(LLShaderMgr::SUNLIGHT_LINEAR, linearColor3v(getSunlightColor()));
shader->uniform3fv(LLShaderMgr::MOONLIGHT_LINEAR,linearColor3v(getMoonlightColor()));
@@ -724,16 +745,14 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force)
shader->uniform1f(LLShaderMgr::SUN_MOON_GLOW_FACTOR, getSunMoonGlowFactor());
shader->uniform1f(LLShaderMgr::DENSITY_MULTIPLIER, getDensityMultiplier());
shader->uniform1f(LLShaderMgr::DISTANCE_MULTIPLIER, getDistanceMultiplier());
-
+
+ shader->uniform1f(LLShaderMgr::HAZE_DENSITY_LINEAR, sRGBtoLinear(getHazeDensity()));
+
F32 g = getGamma();
F32 display_gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
shader->uniform1f(LLShaderMgr::GAMMA, g);
shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, display_gamma);
-
- shader->uniform3fv(LLShaderMgr::BLUE_HORIZON_LINEAR, linearColor3v(getBlueHorizon()/2.f)); // note magic number of 2.f comes from SLIDER_SCALE_BLUE_HORIZON_DENSITY
- shader->uniform3fv(LLShaderMgr::BLUE_DENSITY_LINEAR, linearColor3v(getBlueDensity()/2.f));
- shader->uniform1f(LLShaderMgr::HAZE_DENSITY_LINEAR, sRGBtoLinear(getHazeDensity()));
}
LLSettingsSky::parammapping_t LLSettingsVOSky::getParameterMap() const
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 497b2373da..28d6267029 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -1017,6 +1017,12 @@ void display_cube_face()
display_update_camera();
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("Env Update");
+ // update all the sky/atmospheric/water settings
+ LLEnvironment::instance().update(LLViewerCamera::getInstance());
+ }
+
LLSpatialGroup::sNoDelete = TRUE;
S32 occlusion = LLPipeline::sUseOcclusion;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 64f7535f05..03ffe5da48 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -806,11 +806,12 @@ LLPipeline::eFBOStatus LLPipeline::doAllocateScreenBuffer(U32 resX, U32 resY)
bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
- if (mRT == &mMainRT)
+ if (mRT == &mMainRT && sReflectionProbesEnabled)
{ // hacky -- allocate auxillary buffer
gCubeSnapshot = TRUE;
+ mReflectionMapManager.initReflectionMaps();
mRT = &mAuxillaryRT;
- U32 res = LL_REFLECTION_PROBE_RESOLUTION * 2;
+ U32 res = mReflectionMapManager.mProbeResolution * 2; //multiply by 2 because probes will be super sampled
allocateScreenBuffer(res, res, samples);
mRT = &mMainRT;
gCubeSnapshot = FALSE;
@@ -4172,10 +4173,16 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
calcNearbyLights(camera);
setupHWLights(NULL);
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
gGL.setColorMask(true, false);
pool_set_t::iterator iter1 = mPools.begin();
+ if (gDebugGL || gDebugPipeline)
+ {
+ LLGLState::checkStates(GL_FALSE);
+ }
+
while ( iter1 != mPools.end() )
{
LLDrawPool *poolp = *iter1;
@@ -8104,6 +8111,8 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, LLRenderTarget* light_
shader.uniform3fv(LLShaderMgr::SUNLIGHT_COLOR, 1, mSunDiffuse.mV);
shader.uniform3fv(LLShaderMgr::MOONLIGHT_COLOR, 1, mMoonDiffuse.mV);
+
+ shader.uniform1f(LLShaderMgr::REFLECTION_PROBE_MAX_LOD, mReflectionMapManager.mMaxProbeLOD);
}