From f0313c1d49682adb6346e459b1197c728b519942 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Tue, 12 May 2026 17:00:56 +0800 Subject: [PATCH 1/5] feat(TruePBR): add settings to disable vertex AO --- package/Shaders/Common/SharedData.hlsli | 9 ++++++++- package/Shaders/Lighting.hlsl | 6 ++++-- src/FeatureBuffer.cpp | 4 +++- src/TruePBR.cpp | 24 ++++++++++++++++++++++++ src/TruePBR.h | 13 +++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index cae68835fe..1e08450d55 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -20,7 +20,7 @@ namespace SharedData float Timer; uint FrameCount; uint FrameCountAlwaysActive; - bool InInterior; // If the current cell is an interior + bool InInterior; // If the current cell is an interior bool HasDirectionalShadows; bool InMapMenu; // If the world/local map is open (note that the renderer is still deferred here) bool HideSky; // HideSky flag in WorldSpace, e.g. Blackreach @@ -269,6 +269,12 @@ namespace SharedData float3 pad; }; + struct TruePBRSettings + { + uint DisableVertexAO; + uint3 pad; + }; + cbuffer FeatureData : register(b6) { GrassLightingSettings grassLightingSettings; @@ -287,6 +293,7 @@ namespace SharedData LinearLightingSettings linearLightingSettings; TerrainBlendingSettings terrainBlendingSettings; ExponentialHeightFogSettings exponentialHeightFogSettings; + TruePBRSettings truePBRSettings; }; Texture2D DepthTexture : register(t17); diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 375e7fcd39..c847fa95ef 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2890,11 +2890,13 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) # elif defined(SKYLIGHTING) float3 vertexColor = input.Color.xyz; float vertexAO = max(max(vertexColor.r, vertexColor.g), vertexColor.b); - // Modify skylightingDiffuse such that skylightingDiffuse * vertexAO = min(skylightingDiffuse, vertexAO) - skylightingDiffuse = saturate(skylightingDiffuse / max(vertexAO, 1e-5)); # if defined(TRUE_PBR) + if (SharedData::truePBRSettings.DisableVertexAO) + vertexAO = 1; vertexColor = 1; # endif + // Modify skylightingDiffuse such that skylightingDiffuse * vertexAO = min(skylightingDiffuse, vertexAO) + skylightingDiffuse = saturate(skylightingDiffuse / max(vertexAO, 1e-5)); # else # if defined(TRUE_PBR) float3 vertexColor = 1; diff --git a/src/FeatureBuffer.cpp b/src/FeatureBuffer.cpp index f876879095..98f5aa834b 100644 --- a/src/FeatureBuffer.cpp +++ b/src/FeatureBuffer.cpp @@ -16,6 +16,7 @@ #include "Features/TerrainShadows.h" #include "Features/TerrainVariation.h" #include "Features/WetnessEffects.h" +#include "TruePBR.h" template std::pair _GetFeatureBufferData(Ts... feat_datas) @@ -51,5 +52,6 @@ std::pair GetFeatureBufferData(bool a_inWorld) globals::features::extendedTranslucency.GetCommonBufferData(), globals::features::linearLighting.GetCommonBufferData(), globals::features::terrainBlending.settings, - globals::features::exponentialHeightFog.settings); + globals::features::exponentialHeightFog.settings, + globals::features::truePBR.settings); } \ No newline at end of file diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 1b8d6e3870..0883338ac3 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -40,6 +40,10 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( specularLevel, glintParameters); +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + TruePBR::Settings, + DisableVertexAO); + #define CHECK_PBR_TEXTURE(textureName) \ if (!(pbrMaterial->textureName)) { \ logger::warn("[TruePBR] {} missing {}; treating as nonPBR", pbrMaterial->inputFilePath, #textureName); \ @@ -106,6 +110,11 @@ void SetupPBRLandscapeTextureParameters(BSLightingShaderMaterialPBRLandscape& ma void TruePBR::DrawSettings() { + if (ImGui::TreeNodeEx("Global Settings", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("Disable Vertex AO", (bool*)&settings.DisableVertexAO); + ImGui::TreePop(); + } + if (ImGui::TreeNodeEx("Texture Set Settings", ImGuiTreeNodeFlags_DefaultOpen)) { if (Util::SearchableCombo("Texture Set", selectedPbrTextureSetName, pbrTextureSets)) { selectedPbrTextureSet = &pbrTextureSets[selectedPbrTextureSetName]; @@ -300,6 +309,21 @@ void TruePBR::DrawSettings() } } +void TruePBR::SaveSettings(json& o_json) +{ + o_json = settings; +} + +void TruePBR::LoadSettings(json& o_json) +{ + settings = o_json; +} + +void TruePBR::RestoreDefaultSettings() +{ + settings = {}; +} + void TruePBR::SetupResources() { SetupTextureSetData(); diff --git a/src/TruePBR.h b/src/TruePBR.h index 782d9a9498..8aafe667df 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -42,6 +42,19 @@ struct TruePBR : Feature virtual void Prepass() override; virtual void PostPostLoad() override; virtual void DataLoaded() override; + + virtual void SaveSettings(json& o_json) override; + virtual void LoadSettings(json& o_json) override; + virtual void RestoreDefaultSettings() override; + + struct alignas(16) Settings + { + uint DisableVertexAO = false; + uint pad[3]; + }; + STATIC_ASSERT_ALIGNAS_16(Settings); + + Settings settings; bool TESObjectLAND_SetupMaterial(RE::TESObjectLAND* land); bool BSLightingShader_SetupMaterial(RE::BSLightingShader* shader, RE::BSLightingShaderMaterialBase const* material); From 3c3684536b14f90e7a5735eaf5bd8f8e8679de7a Mon Sep 17 00:00:00 2001 From: Jiaye Date: Wed, 13 May 2026 09:59:35 +0800 Subject: [PATCH 2/5] feat(TruePBR): replace DisableVertexAO with VertexAOStrength for better control --- package/Shaders/Common/SharedData.hlsli | 2 +- package/Shaders/Lighting.hlsl | 3 +-- src/TruePBR.cpp | 4 ++-- src/TruePBR.h | 2 +- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index 1e08450d55..8168507571 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -271,7 +271,7 @@ namespace SharedData struct TruePBRSettings { - uint DisableVertexAO; + float VertexAOStrength; uint3 pad; }; diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index c847fa95ef..1d2bf7d841 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2891,8 +2891,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float3 vertexColor = input.Color.xyz; float vertexAO = max(max(vertexColor.r, vertexColor.g), vertexColor.b); # if defined(TRUE_PBR) - if (SharedData::truePBRSettings.DisableVertexAO) - vertexAO = 1; + vertexAO = lerp(1, vertexAO, SharedData::truePBRSettings.VertexAOStrength); vertexColor = 1; # endif // Modify skylightingDiffuse such that skylightingDiffuse * vertexAO = min(skylightingDiffuse, vertexAO) diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 0883338ac3..734319b6a9 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -42,7 +42,7 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( TruePBR::Settings, - DisableVertexAO); + VertexAOStrength); #define CHECK_PBR_TEXTURE(textureName) \ if (!(pbrMaterial->textureName)) { \ @@ -111,7 +111,7 @@ void SetupPBRLandscapeTextureParameters(BSLightingShaderMaterialPBRLandscape& ma void TruePBR::DrawSettings() { if (ImGui::TreeNodeEx("Global Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("Disable Vertex AO", (bool*)&settings.DisableVertexAO); + ImGui::SliderFloat("Vertex AO Strength", &settings.VertexAOStrength, 0.f, 1.f, "%.2f"); ImGui::TreePop(); } diff --git a/src/TruePBR.h b/src/TruePBR.h index 8aafe667df..3bf5d73e64 100644 --- a/src/TruePBR.h +++ b/src/TruePBR.h @@ -49,7 +49,7 @@ struct TruePBR : Feature struct alignas(16) Settings { - uint DisableVertexAO = false; + float VertexAOStrength = 1.0f; uint pad[3]; }; STATIC_ASSERT_ALIGNAS_16(Settings); From 1a694bd44427fa6370bb3752d706e14fc09c7984 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Thu, 14 May 2026 00:44:26 +0800 Subject: [PATCH 3/5] feat(PBR): enhance vertex color application with AO adjustment --- package/Shaders/Lighting.hlsl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 1d2bf7d841..e2109df70c 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2156,6 +2156,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) // Apply vertex color to base color so PBR metals use it float3 pbrVertexColor = Color::SrgbToLinear(input.Color.xyz); + float pbrVertexAO = max(max(pbrVertexColor.x, pbrVertexColor.y), pbrVertexColor.z); + pbrVertexColor *= lerp(max(1 / pbrVertexAO, 0.001), 1, SharedData::truePBRSettings.VertexAOStrength); if (!SharedData::linearLightingSettings.enableLinearLighting) { baseColor.xyz = Color::SrgbToLinear(baseColor.xyz) * pbrVertexColor; From 2ca4ea7057e0aa6d0d3312f652f29488d90c9bdc Mon Sep 17 00:00:00 2001 From: Jiaye Date: Thu, 14 May 2026 10:15:40 +0800 Subject: [PATCH 4/5] feat(TruePBR): improve vertex color application by handling zero AO cases --- package/Shaders/Lighting.hlsl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 84a65627b7..bcc82bb865 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -2156,7 +2156,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) // Apply vertex color to base color so PBR metals use it float3 pbrVertexColor = Color::SrgbToLinear(input.Color.xyz); float pbrVertexAO = max(max(pbrVertexColor.x, pbrVertexColor.y), pbrVertexColor.z); - pbrVertexColor *= lerp(max(1 / pbrVertexAO, 0.001), 1, SharedData::truePBRSettings.VertexAOStrength); + pbrVertexColor = pbrVertexAO == 0.0f ? 1.0f : pbrVertexColor * lerp(1 / max(pbrVertexAO, 0.001), 1, SharedData::truePBRSettings.VertexAOStrength); if (!SharedData::linearLightingSettings.enableLinearLighting) { baseColor.xyz = Color::SrgbToLinear(baseColor.xyz) * pbrVertexColor; @@ -2816,17 +2816,19 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace) float3 glowColor = Color::Glowmap(TexGlowSampler.Sample(SampGlowSampler, uv).xyz); # if defined(TRUE_PBR) - float3 vertexColor = Color::SrgbToLinear(input.Color.xyz); + float3 emitVertexColor = Color::SrgbToLinear(input.Color.xyz); + float emitVertexAO = max(max(emitVertexColor.r, emitVertexColor.g), emitVertexColor.b); + emitVertexColor = emitVertexAO == 0.0f ? 1.0f : emitVertexColor * lerp(1 / max(emitVertexAO, 1e-4), 1, SharedData::truePBRSettings.VertexAOStrength); if (!SharedData::linearLightingSettings.enableLinearLighting) { emitColor = Color::SrgbToLinear(emitColor); glowColor = Color::SrgbToLinear(glowColor); emitColor *= glowColor; - emitColor *= vertexColor; + emitColor *= emitVertexColor; emitColor = Color::LinearToSrgb(emitColor); } else { emitColor *= glowColor; - emitColor *= vertexColor; + emitColor *= emitVertexColor; } # else if (!SharedData::linearLightingSettings.enableLinearLighting) { From 9a6b6e7751345d581709077d08c823de52daf9e0 Mon Sep 17 00:00:00 2001 From: Jiaye Date: Thu, 14 May 2026 14:25:13 +0800 Subject: [PATCH 5/5] always clamp vao --- src/TruePBR.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 734319b6a9..5bb1e2f8d9 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -111,7 +111,7 @@ void SetupPBRLandscapeTextureParameters(BSLightingShaderMaterialPBRLandscape& ma void TruePBR::DrawSettings() { if (ImGui::TreeNodeEx("Global Settings", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::SliderFloat("Vertex AO Strength", &settings.VertexAOStrength, 0.f, 1.f, "%.2f"); + ImGui::SliderFloat("Vertex AO Strength", &settings.VertexAOStrength, 0.f, 1.f, "%.2f", ImGuiSliderFlags_AlwaysClamp); ImGui::TreePop(); }