diff options
| -rw-r--r-- | indra/llrender/llshadermgr.cpp | 1 | ||||
| -rw-r--r-- | indra/llrender/llshadermgr.h | 1 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 11 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/interface/irradianceGenF.glsl | 198 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class1/interface/radianceGenF.glsl | 4 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class2/interface/irradianceGenF.glsl | 231 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl | 80 | ||||
| -rw-r--r-- | indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl | 7 | ||||
| -rw-r--r-- | indra/newview/featuretable.txt | 9 | ||||
| -rw-r--r-- | indra/newview/llenvironment.cpp | 51 | ||||
| -rw-r--r-- | indra/newview/llfeaturemanager.cpp | 4 | ||||
| -rw-r--r-- | indra/newview/llreflectionmapmanager.cpp | 187 | ||||
| -rw-r--r-- | indra/newview/llreflectionmapmanager.h | 16 | ||||
| -rw-r--r-- | indra/newview/llsettingsvo.cpp | 31 | ||||
| -rw-r--r-- | indra/newview/llviewerdisplay.cpp | 6 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 13 | 
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);  } | 
