From 587cd0d0af7235d4a3629b95b443e746f8454ba2 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 23 Aug 2025 15:44:30 +0200 Subject: [PATCH] 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) {