diff options
11 files changed, 135 insertions, 109 deletions
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d6af39f97e..5ffd610fba 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10367,7 +10367,7 @@      <key>Type</key>      <string>U32</string>      <key>Value</key> -    <real>1</real> +    <real>2</real>    </map>    <key>RenderExposure</key>    <map> @@ -10403,18 +10403,17 @@      <key>Value</key>      <real>0</real>    </map> -  <key>RenderReflectionProbeTextureHackID</key> +  <key>RenderAutomaticReflectionProbes</key>    <map>      <key>Comment</key> -    <string>HACK -- Any object with a diffuse texture with this ID will be treated as a user override reflection probe. (default is "Violet Info Hub" photo from Library)</string> +    <string>Automatic reflection probes control.  0 - disable, 1 - Terrain/water only, 2- Terrain/water + objects.  Requires restart.</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> -    <string>String</string> +    <string>S32</string>      <key>Value</key> -    <string>6b186931-05da-eafa-a3ed-a012a33bbfb6</string> +    <integer>2</integer>    </map> -      <key>RenderReflectionRes</key>      <map>        <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl index 689929fe38..861b78c961 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/exposureF.glsl @@ -36,17 +36,16 @@ uniform sampler2D exposureMap;  uniform float dt;  uniform vec2 noiseVec; -// calculate luminance the same way LLColor4::calcHSL does +  float lum(vec3 col)  { -    float mx = max(max(col.r, col.g), col.b); -    float mn = min(min(col.r, col.g), col.b); -    return (mx + mn) * 0.5; +    vec3 l = vec3(0.2126, 0.7152, 0.0722); +    return dot(l, col);  }  void main()   { -    float step = 1.0/32.0; +    float step = 1.0/16.0;      float start = step;      float end = 1.0-step; @@ -55,13 +54,13 @@ void main()      vec3 col; -    vec2 nz = noiseVec * step * 0.5; +    //vec2 nz = noiseVec * step * 0.5;      for (float x = start; x <= end; x += step)      {          for (float y = start; y <= end; y += step)          { -            vec2 tc = vec2(x,y) + nz; +            vec2 tc = vec2(x,y); // + nz;              vec3 c = texture(diffuseRect, tc).rgb + texture(emissiveRect, tc).rgb;              float L = max(lum(c), 0.25); @@ -82,11 +81,13 @@ void main()      float L = lum(col); -    float s = clamp(0.1/L, 0.5, 4.0); +    float s = clamp(0.175/L, 0.125, 1.3); +      float prev = texture(exposureMap, vec2(0.5,0.5)).r; -    s = mix(prev, s, min(dt*2.0, 0.04)); +    s = mix(prev, s, min(dt*2.0*abs(prev-s), 0.04)); +          frag_color = vec4(s, s, s, dt);  } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl index 4ac1ff9368..221de0b095 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredGammaCorrect.glsl @@ -125,7 +125,6 @@ vec3 toneMap(vec3 color)      // this factor is based on the exposure correction of Krzysztof Narkowicz in his      // implemetation of ACES tone mapping      color *= 1.0/0.6; -    //color /= 0.6;      color = toneMapACES_Hill(color);  #endif diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index fc6291d438..0090155e5c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -91,7 +91,7 @@ void main()      vary_LightNormPosDot = rel_pos_lightnorm_dot;      // Initialize temp variables -    vec3 sunlight = (sun_up_factor == 1) ? sunlight_color*2.0 : moonlight_color*0.75; +    vec3 sunlight = (sun_up_factor == 1) ? sunlight_color*2.0 : moonlight_color;      // Sunlight attenuation effect (hue and brightness) due to atmosphere      // this is used later for sunlight modulation at various altitudes diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl index 0d3dbf85e2..c2527db218 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsFuncs.glsl @@ -62,8 +62,10 @@ void calcAtmosphericVars(vec3 inPositionEye, vec3 light_dir, float ambFactor, ou      vec3  rel_pos_norm = normalize(rel_pos);      float rel_pos_len  = length(rel_pos); -    float scale = 2.0; -    vec3  sunlight     = (sun_up_factor == 1) ? sunlight_color * scale: moonlight_color*0.75; +     +    float scale = sun_up_factor + 1; +    vec3  sunlight     = (sun_up_factor == 1) ? sunlight_color: moonlight_color; +    sunlight *= scale;      // sunlight attenuation effect (hue and brightness) due to atmosphere      // this is used later for sunlight modulation at various altitudes diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 7a5676e0ab..677d83a1fe 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -35,6 +35,8 @@ uniform sampler2D sceneMap;  uniform int cube_snapshot;  uniform float max_probe_lod; +#define MAX_REFMAP_COUNT 256  // must match LL_MAX_REFLECTION_PROBE_COUNT +  layout (std140) uniform ReflectionProbes  {      // list of OBBs for user override probes @@ -42,18 +44,18 @@ layout (std140) uniform ReflectionProbes      // for each box refBox[i]...      /// box[0..2] - plane 0 .. 2 in [A,B,C,D] notation      //  box[3][0..2] - plane thickness -    mat4 refBox[REFMAP_COUNT]; +    mat4 refBox[MAX_REFMAP_COUNT];      // list of bounding spheres for reflection probes sorted by distance to camera (closest first) -    vec4 refSphere[REFMAP_COUNT]; +    vec4 refSphere[MAX_REFMAP_COUNT];      // extra parameters (currently only .x used for probe ambiance) -    vec4 refParams[REFMAP_COUNT]; +    vec4 refParams[MAX_REFMAP_COUNT];      // index  of cube map in reflectionProbes for a corresponding reflection probe      // e.g. cube map channel of refSphere[2] is stored in refIndex[2]      // refIndex.x - cubemap channel in reflectionProbes      // refIndex.y - index in refNeighbor of neighbor list (index is ivec4 index, not int index)      // refIndex.z - number of neighbors      // refIndex.w - priority, if negative, this probe has a box influence -    ivec4 refIndex[REFMAP_COUNT]; +    ivec4 refIndex[MAX_REFMAP_COUNT];      // neighbor list data (refSphere indices, not cubemap array layer)      ivec4 refNeighbor[1024]; @@ -674,7 +676,7 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv,      sampleReflectionProbes(ambenv, glossenv, tc, pos, norm, glossiness);      // fudge factor to get PBR water at a similar luminance ot legacy water -    glossenv *= 0.25; +    glossenv *= 0.4;  }  void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 6eff607ea5..d639f6a54c 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -90,6 +90,12 @@ public:      // cube map used to sample this environment map      LLPointer<LLCubeMapArray> mCubeArray;      S32 mCubeIndex = -1; // index into cube map array or -1 if not currently stored in cube map array +     +    // probe has had at least one full update and is ready to render +    bool mComplete = false; + +    // fade in parameter for this probe +    F32 mFadeIn = 0.f;      // index into array packed by LLReflectionMapManager::getReflectionMaps      // WARNING -- only valid immediately after call to getReflectionMaps diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 58ce571505..09ac7e57a4 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -181,7 +181,11 @@ void LLReflectionMapManager::update()          LLVector4a d; -        if (probe->mOccluded) +        if (probe->mComplete) +        { +            probe->mFadeIn = llmin((F32) (probe->mFadeIn + gFrameIntervalSeconds), 1.f); +        } +        if (probe->mOccluded && probe->mComplete)          {              if (oldestOccluded == nullptr)              { @@ -300,7 +304,7 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma          mProbes[i]->mLastBindTime = gFrameTimeSeconds; // something wants to use this probe, indicate it's been requested          if (mProbes[i]->mCubeIndex != -1)          { -            if (!mProbes[i]->mOccluded) +            if (!mProbes[i]->mOccluded && mProbes[i]->mComplete)              {                  mProbes[i]->mProbeIndex = count;                  maps[count++] = mProbes[i]; @@ -328,29 +332,20 @@ void LLReflectionMapManager::getReflectionMaps(std::vector<LLReflectionMap*>& ma  LLReflectionMap* LLReflectionMapManager::registerSpatialGroup(LLSpatialGroup* group)  { -#if 1 -    if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME) +    static LLCachedControl<S32> automatic_probes(gSavedSettings, "RenderAutomaticReflectionProbes", 2); +    if (automatic_probes > 1)      { -        OctreeNode* node = group->getOctreeNode(); -        F32 size = node->getSize().getF32ptr()[0]; -        if (size >= 15.f && size <= 17.f) +        if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_VOLUME)          { -            return addProbe(group); +            OctreeNode* node = group->getOctreeNode(); +            F32 size = node->getSize().getF32ptr()[0]; +            if (size >= 15.f && size <= 17.f) +            { +                return addProbe(group); +            }          }      } -#endif -#if 0 -    if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_TERRAIN) -    { -        OctreeNode* node = group->getOctreeNode(); -        F32 size = node->getSize().getF32ptr()[0]; -        if (size >= 15.f && size <= 17.f) -        { -            return addProbe(group); -        } -    } -#endif      return nullptr;  } @@ -394,6 +389,7 @@ S32 LLReflectionMapManager::allocateCubeIndex()              S32 ret = mProbes[i]->mCubeIndex;              mProbes[i]->mCubeIndex = -1;              mProbes[i]->mCubeArray = nullptr; +            mProbes[i]->mComplete = false;              return ret;          }      } @@ -444,6 +440,7 @@ void LLReflectionMapManager::doProbeUpdate()          mUpdatingFace = 0;          if (isRadiancePass())          { +            mUpdatingProbe->mComplete = true;              mUpdatingProbe = nullptr;              mRadiancePass = false;          } @@ -777,7 +774,10 @@ void LLReflectionMapManager::updateUniforms()          // for sphere probes, origin (xyz) and radius (w) of refmaps in clip space          LLVector4 refSphere[LL_MAX_REFLECTION_PROBE_COUNT];  -        // extra parameters (currently only ambiance in .x) +        // extra parameters  +        //  x - irradiance scale +        //  y - radiance scale +        //  z - fade in          LLVector4 refParams[LL_MAX_REFLECTION_PROBE_COUNT];          // indices used by probe: @@ -852,7 +852,7 @@ void LLReflectionMapManager::updateUniforms()              rpd.refIndex[count][3] = -rpd.refIndex[count][3];          } -        rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, 0.f, 0.f); +        rpd.refParams[count].set(llmax(minimum_ambiance, refmap->getAmbiance())*ambscale, radscale, refmap->mFadeIn, 0.f);          S32 ni = nc; // neighbor ("index") - index into refNeighbor to write indices for current reflection probe's neighbors          { @@ -1006,11 +1006,15 @@ void LLReflectionMapManager::renderDebug()  void LLReflectionMapManager::initReflectionMaps()  { -    if (mTexture.isNull()) +    static LLCachedControl<S32> probe_count(gSavedSettings, "RenderReflectionProbeCount", LL_MAX_REFLECTION_PROBE_COUNT); + +    U32 count = llclamp((S32) probe_count, 1, LL_MAX_REFLECTION_PROBE_COUNT); + +    if (mTexture.isNull() || mReflectionProbeCount != count)      { +        mReflectionProbeCount = count;          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(); @@ -1019,6 +1023,28 @@ void LLReflectionMapManager::initReflectionMaps()          mIrradianceMaps = new LLCubeMapArray();          mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, FALSE); + +        // reset probe state +        mUpdatingFace = 0; +        mUpdatingProbe = nullptr; +        mRadiancePass = false; +        mRealtimeRadiancePass = false; +        mDefaultProbe = nullptr; + +        for (auto& probe : mProbes) +        { +            probe->mComplete = false; +            probe->mProbeIndex = -1; +            probe->mCubeArray = nullptr; +            probe->mCubeIndex = -1; +        } + +        for (bool& is_free : mCubeFree) +        { +            is_free = true; +        } + +        mCubeFree[0] = false;      }      if (mVertexBuffer.isNull()) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 8570c0cd5d..969f0a3594 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -79,6 +79,8 @@  #include <boost/bind.hpp>	// for SkinFolder listener  #include <boost/signals2.hpp> +// *TODO: Consider enabling mipmaps (they have been disabled for a long time). Likely has a significant performance impact for tiled/high texture repeat media. Mip generation in a shader may also be an option if necessary. +constexpr BOOL USE_MIPMAPS = FALSE;  void init_threaded_picker_load_dialog(LLPluginClassMedia* plugin, LLFilePicker::ELoadFilter filter, bool get_multiple)  { @@ -1564,7 +1566,8 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,  	// connect this media_impl to the media texture, creating it if it doesn't exist.0  	// This is necessary because we need to be able to use getMaxVirtualSize() even if the media plugin is not loaded. -	LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId); +    // *TODO: Consider enabling mipmaps (they have been disabled for a long time). Likely has a significant performance impact for tiled/high texture repeat media. Mip generation in a shader may also be an option if necessary. +	LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture(mTextureId, USE_MIPMAPS);  	if(media_tex)  	{  		media_tex->setMediaImpl(); @@ -1658,13 +1661,14 @@ void LLViewerMediaImpl::destroyMediaSource()  	cancelMimeTypeProbe(); -    mLock.lock();   // Delay tear-down while bg thread is updating -	if(mMediaSource) -	{ -		mMediaSource->setDeleteOK(true) ; -		mMediaSource = NULL; // shared pointer -	} -    mLock.unlock(); +    { +        LLMutexLock lock(&mLock); // Delay tear-down while bg thread is updating +        if(mMediaSource) +        { +            mMediaSource->setDeleteOK(true) ; +            mMediaSource = NULL; // shared pointer +        } +    }  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -2959,14 +2963,17 @@ bool LLViewerMediaImpl::preMediaTexUpdate(LLViewerMediaTexture*& media_tex, U8*&  void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* data, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool sync)  {      LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; -    mLock.lock();   // don't allow media source tear-down during update +    LLMutexLock lock(&mLock); // don't allow media source tear-down during update + +    const LLGLuint tex_name = media_tex->getGLTexture() ? media_tex->getGLTexture()->getTexName() : (LLGLuint)0; +    if (!tex_name) +    { +        llassert(false); +        return; +    }      // wrap "data" in an LLImageRaw but do NOT make a copy      LLPointer<LLImageRaw> raw = new LLImageRaw(data, media_tex->getWidth(), media_tex->getHeight(), media_tex->getComponents(), true); -         -    // Allocate GL texture based on LLImageRaw but do NOT copy to GL -    LLGLuint tex_name = 0; -    media_tex->createGLTexture(0, raw, 0, TRUE, LLGLTexture::OTHER, true, &tex_name);      // copy just the subimage covered by the image raw to GL      media_tex->setSubImage(data, data_width, data_height, x_pos, y_pos, width, height, tex_name); @@ -2983,8 +2990,6 @@ void LLViewerMediaImpl::doMediaTexUpdate(LLViewerMediaTexture* media_tex, U8* da      // release the data pointer before freeing raw so LLImageRaw destructor doesn't      // free memory at data pointer      raw->releaseData(); - -    mLock.unlock();  }  ////////////////////////////////////////////////////////////////////////////////////////// @@ -3002,10 +3007,10 @@ LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage()      }      llassert(!mTextureId.isNull()); -    LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture( mTextureId ); +    // *TODO: Consider enabling mipmaps (they have been disabled for a long time). Likely has a significant performance impact for tiled/high texture repeat media. Mip generation in a shader may also be an option if necessary. +    LLViewerMediaTexture* media_tex = LLViewerTextureManager::getMediaTexture( mTextureId, USE_MIPMAPS );      if ( mNeedsNewTexture -        || media_tex->getUseMipMaps()          || (media_tex->getWidth() != mMediaSource->getTextureWidth())          || (media_tex->getHeight() != mMediaSource->getTextureHeight())          || (mTextureUsedWidth != mMediaSource->getWidth()) @@ -3021,8 +3026,6 @@ LLViewerMediaTexture* LLViewerMediaImpl::updateMediaImage()          // MEDIAOPT: check to see if size actually changed before doing work          media_tex->destroyGLTexture(); -        // MEDIAOPT: apparently just calling setUseMipMaps(FALSE) doesn't work? -        media_tex->reinit(FALSE);	// probably not needed          // MEDIAOPT: seems insane that we actually have to make an imageraw then          // immediately discard it diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index dd4ff50259..192a96a408 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1255,43 +1255,45 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const  void LLViewerRegion::updateReflectionProbes()  { -#if 1 -    const F32 probe_spacing = 32.f; -    const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f); -    const F32 hover_height = 2.f; +    static LLCachedControl<S32> automatic_probes(gSavedSettings, "RenderAutomaticReflectionProbes", 2); +    if (automatic_probes > 0) +    { +        const F32 probe_spacing = 32.f; +        const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f); +        const F32 hover_height = 2.f; -    F32 start = probe_spacing * 0.5f; +        F32 start = probe_spacing * 0.5f; -    U32 grid_width = REGION_WIDTH_METERS / probe_spacing; +        U32 grid_width = REGION_WIDTH_METERS / probe_spacing; -    mReflectionMaps.resize(grid_width * grid_width); +        mReflectionMaps.resize(grid_width * grid_width); -    F32 water_height = getWaterHeight(); -    LLVector3 origin = getOriginAgent(); +        F32 water_height = getWaterHeight(); +        LLVector3 origin = getOriginAgent(); -    for (U32 i = 0; i < grid_width; ++i) -    { -        F32 x = i * probe_spacing + start; -        for (U32 j = 0; j < grid_width; ++j) +        for (U32 i = 0; i < grid_width; ++i)          { -            F32 y = j * probe_spacing + start; +            F32 x = i * probe_spacing + start; +            for (U32 j = 0; j < grid_width; ++j) +            { +                F32 y = j * probe_spacing + start; -            U32 idx = i * grid_width + j; +                U32 idx = i * grid_width + j; -            if (mReflectionMaps[idx].isNull()) -            { -                mReflectionMaps[idx] = gPipeline.mReflectionMapManager.addProbe(); -            } +                if (mReflectionMaps[idx].isNull()) +                { +                    mReflectionMaps[idx] = gPipeline.mReflectionMapManager.addProbe(); +                } -            LLVector3 probe_origin = LLVector3(x,y, llmax(water_height, mImpl->mLandp->resolveHeightRegion(x,y))); -            probe_origin.mV[2] += hover_height; -            probe_origin += origin; +                LLVector3 probe_origin = LLVector3(x, y, llmax(water_height, mImpl->mLandp->resolveHeightRegion(x, y))); +                probe_origin.mV[2] += hover_height; +                probe_origin += origin; -            mReflectionMaps[idx]->mOrigin.load3(probe_origin.mV); -            mReflectionMaps[idx]->mRadius = probe_radius; +                mReflectionMaps[idx]->mOrigin.load3(probe_origin.mV); +                mReflectionMaps[idx]->mRadius = probe_radius; +            }          }      } -#endif  }  void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 93f4d22ff8..d1f6392eae 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -401,30 +401,16 @@ void LLViewerShaderMgr::setShaders()      llassert((gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 10)); -    //bool canRenderDeferred = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred"); -    //bool hasWindLightShaders = true; // DEPRECATED -- LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders"); -    bool doingWindLight = true; //DEPRECATED -- hasWindLightShaders&& gSavedSettings.getBOOL("WindLightUseAtmosShaders"); - +          S32 light_class = 3;      S32 interface_class = 2;      S32 env_class = 2;      S32 obj_class = 2;      S32 effect_class = 2; -    S32 wl_class = 1; +    S32 wl_class = 2;      S32 water_class = 3;      S32 deferred_class = 3; -    if (doingWindLight) -    { -        // user has disabled WindLight in their settings, downgrade -        // windlight shaders to stub versions. -        wl_class = 2; -    } -    else -    { -        light_class = 2; -    } -      // Trigger a full rebuild of the fallback skybox / cubemap if we've toggled windlight shaders      if (!wl_class || (mShaderLevel[SHADER_WINDLIGHT] != wl_class && gSky.mVOSkyp.notNull()))      { @@ -670,7 +656,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()  	bool has_reflection_probes = gSavedSettings.getBOOL("RenderReflectionsEnabled") && gGLManager.mGLVersion > 3.99f; -	S32 probe_count = gSavedSettings.getS32("RenderReflectionProbeCount"); +	S32 probe_count = llclamp(gSavedSettings.getS32("RenderReflectionProbeCount"), 1, LL_MAX_REFLECTION_PROBE_COUNT);      if (ambient_kill)      {  | 
