From ce06e171f606b084dadcb6bb6a13e788acb55c2f Mon Sep 17 00:00:00 2001 From: Henri Beauchamp Date: Sat, 23 Aug 2025 15:57:11 +0200 Subject: [PATCH 1/3] Fix the alpha gamma value when rendering legacy diffuse textures and materials With the new PBR renderer, the faces using alpha blend with a simple diffuse texture or a Blinn-Phong material are badly rendered (way too opaque), which breaks rendering for an enormous amount of "legacy" (pre-PBR) objects. It has been proposed (1) to introduce a new "alpha gamma" parameter for faces, that would need to be set on legacy contents in order to fix the latter, which would also force to introduce a no-mod permission exception for this parameter alone, so that people owning a legacy no-mod object could still manually edit it to fix its rendering. This proposal is ill-conceived: how can anyone, in their right mind, hope that *every* owner of *every* "legacy" object using alpha blending in SL will bother to edit the said object (supposing they even know they can do it and how to do it) ??? The *proper* solution is to fix the renderer itself, and automatically apply a gamma correction factor to faces *not bearing* a glTF material. This commit implements this fix (which is now part of the Cool VL Viewer and proves that it works very nicely). It implements the same kind of rendering fix (at the shader level) as (2), but instead automatically detects faces rendering with a PBR material, and applies the correction to all faces *not* using such a material. In the event you want to let contents creators use linear alpha channels in objects mixing legacy BP materials and PBR materials (even though I fail to see how a creator would want to do that at all), I suggest you implement an additional flag for faces, that could be set to antagonize this auto-fix (this would let full leeway about the alpha channel scale for newly created contents while not requiring to implement some weird no-mod permission exception since this flag would be set by the creator themselves). In the mean time, this fix solves one of the remaining major issues seen with the PBR renderer. (1) https://feedback.secondlife.com/bug-reports/p/pbr-client-opacity-issue-on-textures-with-alpha-channel-windows (2) https://github.com/secondlife/viewer/pull/2668 --- indra/llrender/llshadermgr.cpp | 1 + indra/llrender/llshadermgr.h | 1 + indra/newview/app_settings/settings.xml | 11 +++++++++++ .../app_settings/shaders/class2/deferred/alphaF.glsl | 5 +++-- .../shaders/class3/deferred/materialF.glsl | 3 ++- indra/newview/lldrawpoolalpha.cpp | 7 +++++++ indra/newview/llspatialpartition.h | 2 ++ indra/newview/llvovolume.cpp | 6 ++++-- 8 files changed, 31 insertions(+), 5 deletions(-) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 4807c122263..0c3fbcace8e 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -1313,6 +1313,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("minimum_alpha"); mReservedUniforms.push_back("emissive_brightness"); + mReservedUniforms.push_back("alpha_gamma"); // Deferred mReservedUniforms.push_back("shadow_matrix"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 46788841a5d..2fd76a34ffe 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -156,6 +156,7 @@ class LLShaderMgr MINIMUM_ALPHA, // "minimum_alpha" EMISSIVE_BRIGHTNESS, // "emissive_brightness" + ALPHA_GAMMA, // "alpha_gamma" DEFERRED_SHADOW_MATRIX, // "shadow_matrix" DEFERRED_ENV_MAT, // "env_mat" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d64f82d3036..b59546f3fa1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7478,6 +7478,17 @@ Value 0 + RenderLegacyAlphaGamma + + Comment + Gamma correction factor (clamped between 1.0 and 2.2) used to render non-PBR faces with alpha blend. 1.0 to disable. + Persist + 1 + Type + F32 + Value + 1.8 + RenderLocalLightCount Comment diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index cc9d72fae61..7d458f8c936 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -37,6 +37,7 @@ uniform mat3 env_mat; uniform vec3 sun_dir; uniform vec3 moon_dir; uniform int classic_mode; +uniform float alpha_gamma; #ifdef USE_DIFFUSE_TEX uniform sampler2D diffuseMap; @@ -215,7 +216,7 @@ void main() } color.rgb = diffuse_srgb.rgb; - color.a = final_alpha; + color.a = pow(final_alpha, alpha_gamma); #else // FOR_IMPOSTOR @@ -263,7 +264,7 @@ void main() vec4 color = vec4(0.0); - color.a = final_alpha; + color.a = pow(final_alpha, alpha_gamma); color.rgb = irradiance; if (classic_mode > 0) diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 5708fc319fa..6327299d1b0 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -37,6 +37,7 @@ uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise uniform int sun_up_factor; uniform int classic_mode; +uniform float alpha_gamma; vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); vec3 scaleSoftClipFragLinear(vec3 l); @@ -420,7 +421,7 @@ void main() glare *= 1.0-emissive; glare = min(glare, 1.0); - float al = max(diffcol.a, glare) * vertex_color.a; + float al = pow(max(diffcol.a, glare) * vertex_color.a, alpha_gamma); float final_scale = 1; if (classic_mode > 0) final_scale = 1.1; diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 87b6ce6cb3a..c51e1c6c3a7 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -595,6 +595,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) above_water = !above_water; } + // Gamma correction factor for alpha faces without PBR material, in PBR + // rendering mode. HB + static LLCachedControl legacy_gamma(gSavedSettings, + "RenderLegacyAlphaGamma"); + F32 alpha_gamma = llclamp((F32)legacy_gamma, 1.f, 2.2f); for (LLCullResult::sg_iterator i = begin; i != end; ++i) { @@ -760,6 +765,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[VRED], spec_color.mV[VGREEN], spec_color.mV[VBLUE], spec_color.mV[VALPHA]); current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity); current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness); + // Fix for alpha gamma on non-PBR (legacy) faces. HB + current_shader->uniform1f(LLShaderMgr::ALPHA_GAMMA, params.mHasPBR ? 1.f : alpha_gamma); } } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 3aaa3d60e87..587d5367a74 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -136,6 +136,8 @@ class LLDrawInfo final : public LLRefCount U8 mShiny = 0; bool mFullbright = false; bool mHasGlow = false; + // Set to 'true' when a PBR material is actually used to render this face. HB + bool mHasPBR = false; struct CompareTexture { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 80fc486a103..202b42b7278 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5372,10 +5372,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U8 index = facep->getTextureIndex(); + bool has_pbr = false; LLMaterial* mat = nullptr; - LLUUID mat_id; - auto* gltf_mat = (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial(); llassert(gltf_mat == nullptr || dynamic_cast(te->getGLTFRenderMaterial()) != nullptr); if (gltf_mat != nullptr) @@ -5384,6 +5383,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, if (!facep->hasMedia() || (tex && tex->getType() != LLViewerTexture::MEDIA_TEXTURE)) { // no media texture, face texture will be unused tex = nullptr; + has_pbr = true; } } else @@ -5447,6 +5447,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, info->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && #endif info->mMaterialID == mat_id && + info->mHasPBR == has_pbr && info->mFullbright == fullbright && info->mBump == bump && (!mat || (info->mShiny == shiny)) && // need to break batches when a material is shared, but legacy settings are different @@ -5501,6 +5502,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mShaderMask = shader_mask; draw_info->mAvatar = facep->mAvatar; draw_info->mSkinInfo = facep->mSkinInfo; + draw_info->mHasPBR = has_pbr; if (gltf_mat) { From ff23e9597557335bf9508277c22b22520506acfe Mon Sep 17 00:00:00 2001 From: Henri Beauchamp Date: Sat, 13 Sep 2025 00:15:37 +0200 Subject: [PATCH 2/3] Bug fixes and improvements to the auto alpha_gamma algorithm This commit brings the following changes to the original code/proposition: - The default alpha-gamma factor has been lowered to 1.4 (1.8 was way too much for all but white textures on alpha faces). - In class2/deferred/alphaF.glsl, a boost to 'final_scale' was added (final_scale *= pow(alpha_gamma, 0.333333)) when alpha_gamma is != 1.0, so to try and compensate for the loss of saturation due to the higher alpha. - The alpha_gamma correction was removed from class3/deferred/materialF.glsl: it just ruins everything and PB materials are "less ruined" without it... - A bug (failure to set the alpha_gamma uniform on avatar shaders) which caused all black legacy eyelashes was fixed. The legacy avatar eyelashes are also now corrected with the _inverse_ of the alpha_gamma factor because, in fact, the PBR renderer makes them too transparent when compared with the legacy ALM/forward renderer (instead of too opaque for most alpha- blend faces)... Go figure ! In any case, the correction now also improves legacy eyelashes rendering. - The algorithm was changed to apply the alpha gamma factor only to faces pertaining to objects which do not use PBR materials at all on any of their other prims/faces. The rationale is that if an object bears a PBR material, then its creator or the owner who edited it made it so that the non-PBR faces would look good in the PBR viewers, and therefore don't need this hack. - A kill switch debug setting (RenderLegacyAlphaGammaEnable) was added: a quick toggle in the Advanced menu could be added for it, if desired. --- indra/newview/app_settings/settings.xml | 15 +++++++++-- .../shaders/class2/deferred/alphaF.glsl | 27 ++++++++++--------- .../shaders/class3/deferred/materialF.glsl | 25 +++++++---------- indra/newview/lldrawpoolalpha.cpp | 11 +++++--- indra/newview/lldrawpoolavatar.cpp | 14 ++++++++++ indra/newview/llspatialpartition.h | 5 ++-- indra/newview/llviewerobject.cpp | 6 +++-- indra/newview/llviewerobject.h | 5 ++++ indra/newview/llvovolume.cpp | 15 +++++++++-- 9 files changed, 84 insertions(+), 39 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 72e4a2d2528..53e6751da6f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -7481,13 +7481,24 @@ RenderLegacyAlphaGamma Comment - Gamma correction factor (clamped between 1.0 and 2.2) used to render non-PBR faces with alpha blend. 1.0 to disable. + Gamma correction factor (clamped between 1.0 and 2.0) used to render non-PBR faces with alpha blend. 1.0 to disable. Persist 1 Type F32 Value - 1.8 + 1.4 + + RenderLegacyAlphaGammaEnable + + Comment + TRUE to enable the alpha-gamma workaround (see RenderLegacyAlphaGamma). + Persist + 1 + Type + Boolean + Value + 1 RenderLocalLightCount diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 7d458f8c936..8a52d6b0477 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -216,7 +216,10 @@ void main() } color.rgb = diffuse_srgb.rgb; - color.a = pow(final_alpha, alpha_gamma); + if (alpha_gamma != 0.0 && alpha_gamma != 1.0) + color.a = pow(final_alpha, alpha_gamma); + else + color.a = final_alpha; #else // FOR_IMPOSTOR @@ -255,25 +258,21 @@ void main() vec3 legacyenv; sampleReflectionProbesLegacy(irradiance, glossenv, legacyenv, frag, pos.xyz, norm.xyz, 0.0, 0.0, true, amblit_linear); - - float da = dot(norm.xyz, light_dir.xyz); - da = clamp(da, -1.0, 1.0); - - float final_da = da; - final_da = clamp(final_da, 0.0f, 1.0f); + float final_da = clamp(dot(norm.xyz, light_dir.xyz), 0.0f, 1.0f); vec4 color = vec4(0.0); - color.a = pow(final_alpha, alpha_gamma); + if (alpha_gamma != 0.0 && alpha_gamma != 1.0) + color.a = pow(final_alpha, alpha_gamma); + else + color.a = final_alpha; color.rgb = irradiance; if (classic_mode > 0) { final_da = pow(final_da,1.2); vec3 sun_contrib = vec3(min(final_da, shadow)); - color.rgb = srgb_to_linear(color.rgb * 0.9 + linear_to_srgb(sun_contrib) * sunlit_linear * 0.7); - sunlit_linear = srgb_to_linear(sunlit_linear); } else { @@ -301,9 +300,12 @@ void main() color.rgb = applySkyAndWaterFog(pos.xyz, additive, atten, color).rgb; #endif // #else // FOR_IMPOSTOR - float final_scale = 1; + float final_scale = 1.0; + // HACK: to get more saturated colors, which otherwise get washed out when alpha_gamma > 1.0. HB + if (alpha_gamma > 1.0) + final_scale = pow(alpha_gamma, 0.333333); if (classic_mode > 0) - final_scale = 1.1; + final_scale *= 1.1; #ifdef IS_HUD color.rgb = linear_to_srgb(color.rgb); final_scale = 1; @@ -312,4 +314,3 @@ void main() color.rgb *= final_scale; frag_color = max(color, vec4(0)); } - diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 6327299d1b0..83fa5469751 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -37,7 +37,6 @@ uniform float emissive_brightness; // fullbright flag, 1.0 == fullbright, 0.0 otherwise uniform int sun_up_factor; uniform int classic_mode; -uniform float alpha_gamma; vec4 applySkyAndWaterFog(vec3 pos, vec3 additive, vec3 atten, vec4 color); vec3 scaleSoftClipFragLinear(vec3 l); @@ -285,10 +284,10 @@ float getShadow(vec3 pos, vec3 norm) #if (DIFFUSE_ALPHA_MODE == DIFFUSE_ALPHA_MODE_BLEND) return sampleDirectionalShadow(pos, norm, vary_texcoord0.xy); #else - return 1; + return 1.; #endif #else - return 1; + return 1.; #endif } @@ -349,9 +348,7 @@ void main() { da = pow(da,1.2); vec3 sun_contrib = vec3(min(da, shadow)); - color.rgb = srgb_to_linear(color.rgb * 0.9 + linear_to_srgb(sun_contrib) * sunlit_linear * 0.7); - sunlit_linear = srgb_to_linear(sunlit_linear); } else { @@ -408,20 +405,20 @@ void main() #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, spec, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w ); LIGHT_LOOP(1) - LIGHT_LOOP(2) - LIGHT_LOOP(3) - LIGHT_LOOP(4) - LIGHT_LOOP(5) - LIGHT_LOOP(6) - LIGHT_LOOP(7) + LIGHT_LOOP(2) + LIGHT_LOOP(3) + LIGHT_LOOP(4) + LIGHT_LOOP(5) + LIGHT_LOOP(6) + LIGHT_LOOP(7) - color += light; + color.rgb += light; color.rgb = applySkyAndWaterFog(pos.xyz, additive, atten, vec4(color, 1.0)).rgb; glare *= 1.0-emissive; glare = min(glare, 1.0); - float al = pow(max(diffcol.a, glare) * vertex_color.a, alpha_gamma); + float al = max(diffcol.a, glare) * vertex_color.a; float final_scale = 1; if (classic_mode > 0) final_scale = 1.1; @@ -442,5 +439,3 @@ void main() #endif } - - diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index c51e1c6c3a7..a5ac7c79b53 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -597,9 +597,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) // Gamma correction factor for alpha faces without PBR material, in PBR // rendering mode. HB + static LLCachedControl use_gamma(gSavedSettings, + "RenderLegacyAlphaGammaEnable"); static LLCachedControl legacy_gamma(gSavedSettings, "RenderLegacyAlphaGamma"); - F32 alpha_gamma = llclamp((F32)legacy_gamma, 1.f, 2.2f); + F32 alpha_gamma = use_gamma ? llclamp((F32)legacy_gamma, 1.f, 2.f) : 1.f; for (LLCullResult::sg_iterator i = begin; i != end; ++i) { @@ -765,8 +767,11 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, bool depth_only, bool rigged) current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[VRED], spec_color.mV[VGREEN], spec_color.mV[VBLUE], spec_color.mV[VALPHA]); current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity); current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness); - // Fix for alpha gamma on non-PBR (legacy) faces. HB - current_shader->uniform1f(LLShaderMgr::ALPHA_GAMMA, params.mHasPBR ? 1.f : alpha_gamma); + // Alpha-gamma correction/workaround, which only applies to + // faces pertaining to a legacy (non-PBR) object. HB + LLViewerObject* objp = params.mRootObject.get(); + F32 agamma = objp && objp->getUsePBR() ? 1.f : alpha_gamma; + current_shader->uniform1f(LLShaderMgr::ALPHA_GAMMA, agamma); } } diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 90ee95d424b..569c1c83723 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -238,6 +238,20 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha); + // Gamma correction factor for alpha faces without PBR material. HB + static LLCachedControl use_gamma(gSavedSettings, + "RenderLegacyAlphaGammaEnable"); + static LLCachedControl legacy_gamma(gSavedSettings, + "RenderLegacyAlphaGamma"); + F32 alpha_gamma = use_gamma ? llclamp((F32)legacy_gamma, 1.f, 2.f) : 1.f; + // *HACK: we apply the _inverted_ correction because for the avatar's + // eyelashes (which is the only part still playing a role in today's + // avatars, the only other alpha-sensitive part being legacy hair, + // which are nowadays always "bald" (100% alpha) to let mesh hair or + // head replace them), the gamma is too strong (too much transparency) + // in PBR rendering mode. HB + sVertexProgram->uniform1f(LLShaderMgr::ALPHA_GAMMA, 1.f / alpha_gamma); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 587d5367a74..b1e48975ee6 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -110,7 +110,8 @@ class LLDrawInfo final : public LLRefCount const LLMatrix4* mTextureMatrix = nullptr; const LLMatrix4* mModelMatrix = nullptr; - LLPointer mAvatar = nullptr; + LLPointer mAvatar; + LLPointer mRootObject; LLMeshSkinInfo* mSkinInfo = nullptr; // Material pointer here is likely for debugging only and are immaterial (zing!) @@ -136,7 +137,7 @@ class LLDrawInfo final : public LLRefCount U8 mShiny = 0; bool mFullbright = false; bool mHasGlow = false; - // Set to 'true' when a PBR material is actually used to render this face. HB + // Set to 'true' when a PBR material is actually used to render this face. HB bool mHasPBR = false; struct CompareTexture diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 9e77b40a453..f5f556bfb5b 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -312,7 +312,8 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mLastUpdateCached(false), mCachedMuteListUpdateTime(0), mCachedOwnerInMuteList(false), - mRiggedAttachedWarned(false) + mRiggedAttachedWarned(false), + mUsePBR(false) { if (!is_global) { @@ -6942,6 +6943,7 @@ void LLViewerObject::recursiveMarkForUpdate() void LLViewerObject::markForUpdate() { + getRootEdit()->mUsePBR = false; // This will be reevaluated. HB if (mDrawable.notNull()) { gPipeline.markTextured(mDrawable); @@ -7495,7 +7497,7 @@ const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const void LLViewerObject::rebuildMaterial() { llassert(!isDead()); - + getRootEdit()->mUsePBR = false; // This will be reevaluated. HB faceMappingChanged(); gPipeline.markTextured(mDrawable); } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 2b52ea20768..31eb3dec7af 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -412,6 +412,9 @@ class LLViewerObject void fitFaceTexture(const U8 face); void sendTEUpdate() const; // Sends packed representation of all texture entry information + inline void setUsePBR() { mUsePBR = true; } + inline bool getUsePBR() const { return mUsePBR; } + virtual void setScale(const LLVector3 &scale, bool damped = false); S32 getAnimatedObjectMaxTris() const; @@ -979,6 +982,8 @@ class LLViewerObject EObjectUpdateType mLastUpdateType; bool mLastUpdateCached; + bool mUsePBR; + public: // reflection probe state bool mIsReflectionProbe = false; // if true, this object should register itself with LLReflectionProbeManager diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 202b42b7278..317c8f5c1fb 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -5295,7 +5295,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, LL_WARNS_ONCE("RenderMaterials") << "Oh no! No binormals for this alpha blended face!" << LL_ENDL; } - bool selected = facep->getViewerObject()->isSelected(); + LLViewerObject* vobjp = facep->getViewerObject(); + bool selected = vobjp->isSelected(); if (selected && LLSelectMgr::getInstance()->mHideSelectedObjects) { @@ -5465,6 +5466,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, info->mTextureList.resize(index+1); info->mTextureList[index] = tex; } + // Make sure the PBR flag usage is set on the root object when PBR is + // used on this face. HB + if (has_pbr && info->mRootObject.notNull()) + { + info->mRootObject->setUsePBR(); + } info->validate(); } else @@ -5503,7 +5510,11 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_info->mAvatar = facep->mAvatar; draw_info->mSkinInfo = facep->mSkinInfo; draw_info->mHasPBR = has_pbr; - + draw_info->mRootObject = vobjp->getRootEdit(); + if (has_pbr) + { + draw_info->mRootObject->setUsePBR(); + } if (gltf_mat) { // just remember the material ID, render pools will reference the GLTF material From 113aaeabcb7152dd147e53038b4a3893fde6849a Mon Sep 17 00:00:00 2001 From: Henri Beauchamp Date: Sat, 13 Sep 2025 18:58:28 +0200 Subject: [PATCH 3/3] Fix for probes sometimes rebuilding every few seconds. --- indra/newview/llviewerobject.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index f5f556bfb5b..7b7e370192b 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -6943,7 +6943,10 @@ void LLViewerObject::recursiveMarkForUpdate() void LLViewerObject::markForUpdate() { - getRootEdit()->mUsePBR = false; // This will be reevaluated. HB + if (!isReflectionProbe()) + { + getRootEdit()->mUsePBR = false; // This will be reevaluated. HB + } if (mDrawable.notNull()) { gPipeline.markTextured(mDrawable); @@ -7497,7 +7500,12 @@ const LLUUID& LLViewerObject::getRenderMaterialID(U8 te) const void LLViewerObject::rebuildMaterial() { llassert(!isDead()); - getRootEdit()->mUsePBR = false; // This will be reevaluated. HB + // Note: do not reset mUsePBR on reflection probes (would cause probe + // rebuild every few seconds). HB + if (!isReflectionProbe()) + { + getRootEdit()->mUsePBR = false; // This will be reevaluated. HB + } faceMappingChanged(); gPipeline.markTextured(mDrawable); }