summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llrender/llshadermgr.cpp1
-rw-r--r--indra/llrender/llshadermgr.h1
-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
16 files changed, 463 insertions, 387 deletions
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 27ac4053df..421b9ee2d6 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -1431,6 +1431,7 @@ void LLShaderMgr::initAttribsAndUniforms()
mReservedUniforms.push_back("moon_brightness");
mReservedUniforms.push_back("cloud_variance");
mReservedUniforms.push_back("reflection_probe_ambiance");
+ mReservedUniforms.push_back("max_probe_lod");
mReservedUniforms.push_back("sh_input_r");
mReservedUniforms.push_back("sh_input_g");
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 86ada6c132..a224b2a19b 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -267,6 +267,7 @@ public:
CLOUD_VARIANCE, // "cloud_variance"
REFLECTION_PROBE_AMBIANCE, // "reflection_probe_ambiance"
+ REFLECTION_PROBE_MAX_LOD, // "max_probe_lod"
SH_INPUT_L1R, // "sh_input_r"
SH_INPUT_L1G, // "sh_input_g"
SH_INPUT_L1B, // "sh_input_b"
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);
}