From cea2cb6aeadc19c33dbc61b6794e5d4570aa150f Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Thu, 7 May 2026 15:06:27 -0700 Subject: [PATCH 1/4] init --- package/Shaders/Common/Permutation.hlsli | 3 +- package/Shaders/Common/ShadowSampling.hlsli | 67 +++++++++++++++++---- package/Shaders/Effect.hlsl | 6 +- src/Features/LightLimitFix.cpp | 2 + src/Hooks.cpp | 2 + src/ShaderTools/ExternalEmittance.cpp | 57 ++++++++++++++++++ src/ShaderTools/ExternalEmittance.h | 7 +++ src/State.h | 3 +- 8 files changed, 131 insertions(+), 16 deletions(-) create mode 100644 src/ShaderTools/ExternalEmittance.cpp create mode 100644 src/ShaderTools/ExternalEmittance.h diff --git a/package/Shaders/Common/Permutation.hlsli b/package/Shaders/Common/Permutation.hlsli index 4285c16a96..d3e2005526 100644 --- a/package/Shaders/Common/Permutation.hlsli +++ b/package/Shaders/Common/Permutation.hlsli @@ -74,6 +74,7 @@ namespace Permutation static const uint IsBeastRace = (1 << 2); static const uint GrassSphereNormal = (1 << 3); static const uint IsSun = (1 << 4); + static const uint SuppressExternalEmittance = (1 << 5); } namespace ExtraFeatureFlags @@ -98,4 +99,4 @@ namespace Permutation }; } -#endif // __PERMUTATION_DEPENDENCY_HLSL__ \ No newline at end of file +#endif // __PERMUTATION_DEPENDENCY_HLSL__ diff --git a/package/Shaders/Common/ShadowSampling.hlsli b/package/Shaders/Common/ShadowSampling.hlsli index a472c97602..33bd0ee350 100644 --- a/package/Shaders/Common/ShadowSampling.hlsli +++ b/package/Shaders/Common/ShadowSampling.hlsli @@ -40,6 +40,10 @@ StructuredBuffer DirectionalShadowLights : register( namespace ShadowSampling { + static const float MinDirectionalLightMultiplier = 1e-5; + static const float3 LightingSampleNormal = float3(0, 0, 1); + static const float3 ImageBasedLightingNormal = float3(0, 0, -1); + float GetWorldShadow(float3 positionWS, float3 offset, uint eyeIndex) { if (SharedData::InInterior || SharedData::HideSky || SharedData::InMapMenu) @@ -117,26 +121,63 @@ namespace ShadowSampling #endif } -#if defined(SKYLIGHTING) && !defined(INTERIOR) - void ExtractLighting(float3 inputColor, out float3 dirColor, out float3 ambientColor, float skylightingDiffuse) -#else - void ExtractLighting(float3 inputColor, out float3 dirColor, out float3 ambientColor) -#endif + float3 GetRawAmbientLighting(float3 normal) { - float3 ambientColorAmb = max(0, SharedData::GetAmbient(float3(0, 0, 1))); + return max(0, SharedData::GetAmbient(normal)); + } + + float3 GetAmbientLighting(float3 normal) + { + float3 ambientColor = GetRawAmbientLighting(normal); #if defined(IBL) if (SharedData::iblSettings.EnableIBL) { -# if defined(SKYLIGHTING) && !defined(INTERIOR) - ambientColorAmb = ImageBasedLighting::GetDiffuseIBLOccluded(ambientColorAmb, float3(0, 0, -1), skylightingDiffuse); -# else - ambientColorAmb = ImageBasedLighting::GetDiffuseIBL(ambientColorAmb, float3(0, 0, -1)); -# endif + ambientColor = ImageBasedLighting::GetDiffuseIBL(ambientColor, ImageBasedLightingNormal); + } +#endif + + return ambientColor; + } + +#if defined(SKYLIGHTING) && !defined(INTERIOR) + float3 GetAmbientLighting(float3 normal, float skylightingDiffuse) + { + float3 ambientColor = GetRawAmbientLighting(normal); + +# if defined(IBL) + if (SharedData::iblSettings.EnableIBL) { + ambientColor = ImageBasedLighting::GetDiffuseIBLOccluded(ambientColor, ImageBasedLightingNormal, skylightingDiffuse); } +# endif + + return ambientColor; + } #endif + float3 GetDirectionalLighting() + { float llDirLightMult = (SharedData::linearLightingSettings.enableLinearLighting && !SharedData::linearLightingSettings.isDirLightLinear) ? SharedData::linearLightingSettings.dirLightMult : 1.0f; - float3 dirLightColorDir = Color::DirectionalLight(SharedData::DirLightColor.xyz / max(llDirLightMult, 1e-5), SharedData::linearLightingSettings.isDirLightLinear) * llDirLightMult; + return Color::DirectionalLight(SharedData::DirLightColor.xyz / max(llDirLightMult, MinDirectionalLightMultiplier), SharedData::linearLightingSettings.isDirLightLinear) * llDirLightMult; + } + + float3 GetSceneLightingColor() + { + return GetAmbientLighting(LightingSampleNormal) + GetDirectionalLighting(); + } + +#if defined(SKYLIGHTING) && !defined(INTERIOR) + void ExtractLighting(float3 inputColor, out float3 dirColor, out float3 ambientColor, float skylightingDiffuse) +#else + void ExtractLighting(float3 inputColor, out float3 dirColor, out float3 ambientColor) +#endif + { +#if defined(SKYLIGHTING) && !defined(INTERIOR) + float3 ambientColorAmb = GetAmbientLighting(LightingSampleNormal, skylightingDiffuse); +#else + float3 ambientColorAmb = GetAmbientLighting(LightingSampleNormal); +#endif + + float3 dirLightColorDir = GetDirectionalLighting(); float inputLuma = Color::RGBToLuminance(inputColor); float ambientLuma = Color::RGBToLuminance(ambientColorAmb); @@ -155,4 +196,4 @@ namespace ShadowSampling } } -#endif // __SHADOW_SAMPLING_DEPENDENCY_HLSL__ \ No newline at end of file +#endif // __SHADOW_SAMPLING_DEPENDENCY_HLSL__ diff --git a/package/Shaders/Effect.hlsl b/package/Shaders/Effect.hlsl index 07013ed307..64894c3b2f 100644 --- a/package/Shaders/Effect.hlsl +++ b/package/Shaders/Effect.hlsl @@ -532,6 +532,10 @@ cbuffer PerGeometry : register(b2) float3 GetLightingColor(float3 msPosition, float3 worldPosition, float2 screenPosition, uint eyeIndex, inout float shadowVariance) { float3 color = DLightColor.xyz * Color::EffectLightingMult(); + bool suppressExternalEmittance = SharedData::InInterior && (Permutation::ExtraShaderDescriptor & Permutation::ExtraFlags::SuppressExternalEmittance); + if (suppressExternalEmittance) { + color = ShadowSampling::GetSceneLightingColor(); + } # if defined(SKYLIGHTING) # if defined(VR) @@ -943,4 +947,4 @@ PS_OUTPUT main(PS_INPUT input) # endif return psout; } -#endif \ No newline at end of file +#endif diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index 2683b6ad84..c988f49192 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -3,6 +3,7 @@ #include "LinearLighting.h" #include "Menu/ThemeManager.h" +#include "ShaderTools/ExternalEmittance.h" #include "Shadercache.h" #include "State.h" #include "Util.h" @@ -564,6 +565,7 @@ void LightLimitFix::Hooks::BSLightingShader_SetupGeometry::thunk(RE::BSShader* T void LightLimitFix::Hooks::BSEffectShader_SetupGeometry::thunk(RE::BSShader* This, RE::BSRenderPass* Pass, uint32_t RenderFlags) { func(This, Pass, RenderFlags); + ExternalEmittance::UpdatePermutation(Pass); auto& singleton = globals::features::lightLimitFix; singleton.BSLightingShader_SetupGeometry_Before(Pass); singleton.BSLightingShader_SetupGeometry_After(Pass); diff --git a/src/Hooks.cpp b/src/Hooks.cpp index d97cf4da87..95812779c1 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -1,6 +1,7 @@ #include "Hooks.h" #include "ShaderTools/BSShaderHooks.h" +#include "ShaderTools/ExternalEmittance.h" #include "Feature.h" #include "Globals.h" @@ -168,6 +169,7 @@ namespace EffectExtensions static void thunk(RE::BSShader* shader, RE::BSRenderPass* pass, uint32_t renderFlags) { func(shader, pass, renderFlags); + ExternalEmittance::UpdatePermutation(pass); globals::state->permutationData.EffectRadius = pass->geometry->worldBound.radius; } static inline REL::Relocation func; diff --git a/src/ShaderTools/ExternalEmittance.cpp b/src/ShaderTools/ExternalEmittance.cpp new file mode 100644 index 0000000000..1b6f14a0a8 --- /dev/null +++ b/src/ShaderTools/ExternalEmittance.cpp @@ -0,0 +1,57 @@ +#include "ExternalEmittance.h" + +#include "Globals.h" +#include "State.h" +#include "Util.h" + +namespace ExternalEmittance +{ + using ShaderPropertyFlag = RE::BSShaderProperty::EShaderPropertyFlag; + static constexpr auto ExternalEmittanceFlag = ShaderPropertyFlag::kExternalEmittance; + static constexpr auto SuppressionDescriptor = static_cast(State::ExtraShaderDescriptors::SuppressExternalEmittance); + + static RE::TESObjectREFR* GetReference(const RE::BSGeometry* a_geometry) + { + return a_geometry ? a_geometry->GetUserData() : nullptr; + } + + static const RE::ExtraEmittanceSource* GetEmittanceSource(const RE::TESObjectREFR* a_ref) + { + return a_ref ? a_ref->extraList.GetByType() : nullptr; + } + + static bool HasEmittanceSource(const RE::BSGeometry* a_geometry) + { + const auto* source = GetEmittanceSource(GetReference(a_geometry)); + return source && source->source; + } + + static bool HasExternalEmittance(const RE::BSShaderProperty* a_shaderProperty) + { + return a_shaderProperty && a_shaderProperty->flags.any(ExternalEmittanceFlag); + } + + static bool ShouldSuppress(const RE::BSShaderProperty* a_shaderProperty, const RE::BSGeometry* a_geometry) + { + return Util::IsInterior() && HasExternalEmittance(a_shaderProperty) && !HasEmittanceSource(a_geometry); + } + + bool ShouldSuppress(const RE::BSRenderPass* a_pass) + { + return a_pass && ShouldSuppress(a_pass->shaderProperty, a_pass->geometry); + } + + void UpdatePermutation(const RE::BSRenderPass* a_pass) + { + assert(globals::state); + if (!globals::state) { + return; + } + + auto& descriptor = globals::state->permutationData.ExtraShaderDescriptor; + descriptor &= ~SuppressionDescriptor; + if (ShouldSuppress(a_pass)) { + descriptor |= SuppressionDescriptor; + } + } +} diff --git a/src/ShaderTools/ExternalEmittance.h b/src/ShaderTools/ExternalEmittance.h new file mode 100644 index 0000000000..75e42c3ab0 --- /dev/null +++ b/src/ShaderTools/ExternalEmittance.h @@ -0,0 +1,7 @@ +#pragma once + +namespace ExternalEmittance +{ + bool ShouldSuppress(const RE::BSRenderPass* a_pass); + void UpdatePermutation(const RE::BSRenderPass* a_pass); +} diff --git a/src/State.h b/src/State.h index e470c0c8dc..970d201496 100644 --- a/src/State.h +++ b/src/State.h @@ -179,7 +179,8 @@ class State IsReflections = 1 << 1, IsBeastRace = 1 << 2, GrassSphereNormal = 1 << 3, - IsSun = 1 << 4 + IsSun = 1 << 4, + SuppressExternalEmittance = 1 << 5 }; enum class ExtraFeatureDescriptors : uint32_t From 542f2d2be9243e4f33805c9e34a4798ab648bfaa Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Thu, 7 May 2026 20:37:14 -0700 Subject: [PATCH 2/4] version bump --- features/Light Limit Fix/Shaders/Features/LightLimitFix.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/Light Limit Fix/Shaders/Features/LightLimitFix.ini b/features/Light Limit Fix/Shaders/Features/LightLimitFix.ini index 7cb44cf96b..7b3c6c9135 100644 --- a/features/Light Limit Fix/Shaders/Features/LightLimitFix.ini +++ b/features/Light Limit Fix/Shaders/Features/LightLimitFix.ini @@ -1,5 +1,5 @@ [Info] -Version = 3-0-2 +Version = 3-0-3 [Nexus] autoupload = false From cd700573ba420e86d66b4068635186387de79f07 Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Fri, 8 May 2026 00:16:15 -0700 Subject: [PATCH 3/4] move to utils --- src/Features/LightLimitFix.cpp | 2 +- src/Hooks.cpp | 2 +- src/{ShaderTools => Utils}/ExternalEmittance.cpp | 0 src/{ShaderTools => Utils}/ExternalEmittance.h | 5 +++++ 4 files changed, 7 insertions(+), 2 deletions(-) rename src/{ShaderTools => Utils}/ExternalEmittance.cpp (100%) rename src/{ShaderTools => Utils}/ExternalEmittance.h (80%) diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index c988f49192..c7528fe44c 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -3,7 +3,7 @@ #include "LinearLighting.h" #include "Menu/ThemeManager.h" -#include "ShaderTools/ExternalEmittance.h" +#include "Utils/ExternalEmittance.h" #include "Shadercache.h" #include "State.h" #include "Util.h" diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 95812779c1..d3dd4f8cc6 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -1,7 +1,7 @@ #include "Hooks.h" #include "ShaderTools/BSShaderHooks.h" -#include "ShaderTools/ExternalEmittance.h" +#include "Utils/ExternalEmittance.h" #include "Feature.h" #include "Globals.h" diff --git a/src/ShaderTools/ExternalEmittance.cpp b/src/Utils/ExternalEmittance.cpp similarity index 100% rename from src/ShaderTools/ExternalEmittance.cpp rename to src/Utils/ExternalEmittance.cpp diff --git a/src/ShaderTools/ExternalEmittance.h b/src/Utils/ExternalEmittance.h similarity index 80% rename from src/ShaderTools/ExternalEmittance.h rename to src/Utils/ExternalEmittance.h index 75e42c3ab0..dd27b6cd1a 100644 --- a/src/ShaderTools/ExternalEmittance.h +++ b/src/Utils/ExternalEmittance.h @@ -1,5 +1,10 @@ #pragma once +namespace RE +{ + class BSRenderPass; +} + namespace ExternalEmittance { bool ShouldSuppress(const RE::BSRenderPass* a_pass); From 8000151692abd26a5f19c3d6062295b2590f915b Mon Sep 17 00:00:00 2001 From: Dlizzio <77717521+Dlizzio@users.noreply.github.com> Date: Fri, 8 May 2026 06:15:20 -0700 Subject: [PATCH 4/4] comment fix --- src/Utils/ExternalEmittance.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Utils/ExternalEmittance.h b/src/Utils/ExternalEmittance.h index dd27b6cd1a..bed4e7072c 100644 --- a/src/Utils/ExternalEmittance.h +++ b/src/Utils/ExternalEmittance.h @@ -1,9 +1,6 @@ #pragma once -namespace RE -{ - class BSRenderPass; -} +#include namespace ExternalEmittance {