diff --git a/features/Interior Sun Shadows/Shaders/Features/InteriorSunShadows.ini b/features/Interior Sun/Shaders/Features/InteriorSun.ini similarity index 100% rename from features/Interior Sun Shadows/Shaders/Features/InteriorSunShadows.ini rename to features/Interior Sun/Shaders/Features/InteriorSun.ini diff --git a/src/Feature.cpp b/src/Feature.cpp index dd7a321a17..0348c6b375 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -10,7 +10,7 @@ #include "Features/GrassLighting.h" #include "Features/HairSpecular.h" #include "Features/IBL.h" -#include "Features/InteriorSunShadows.h" +#include "Features/InteriorSun.h" #include "Features/InverseSquareLighting.h" #include "Features/LODBlending.h" #include "Features/LightLimitFix.h" @@ -219,7 +219,7 @@ const std::vector& Feature::GetFeatureList() &globals::features::lodBlending, &globals::features::inverseSquareLighting, &globals::features::hairSpecular, - &globals::features::interiorSunShadows, + &globals::features::interiorSun, &globals::features::terrainVariation, &globals::features::ibl, &globals::features::extendedTranslucency diff --git a/src/Features/InteriorSunShadows.cpp b/src/Features/InteriorSun.cpp similarity index 71% rename from src/Features/InteriorSunShadows.cpp rename to src/Features/InteriorSun.cpp index 9f25d0b2ad..8114da4794 100644 --- a/src/Features/InteriorSunShadows.cpp +++ b/src/Features/InteriorSun.cpp @@ -1,13 +1,14 @@ -#include "InteriorSunShadows.h" +#include "InteriorSun.h" #include "State.h" #include NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( - InteriorSunShadows::Settings, - ForceDoubleSidedRendering) + InteriorSun::Settings, + ForceDoubleSidedRendering, + InteriorShadowDistance) -void InteriorSunShadows::DrawSettings() +void InteriorSun::DrawSettings() { ImGui::Checkbox("Force Double-Sided Rendering", &settings.ForceDoubleSidedRendering); if (auto _tt = Util::HoverTooltipWrapper()) { @@ -15,24 +16,33 @@ void InteriorSunShadows::DrawSettings() "Disables backface culling during sun shadowmap rendering in interiors. " "Will prevent most light leaking through unmasked/unprepared interiors at a small performance cost. "); } + if (ImGui::SliderFloat("Interior Shadow Distance", &settings.InteriorShadowDistance, 1000.0f, 8000.0f)) { + *gInteriorShadowDistance = settings.InteriorShadowDistance; + SetShadowDistance(globals::game::tes && globals::game::tes->interiorCell); + } + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::Text( + "Sets the distance shadows are rendered at in interiors. " + "Lower values provide higher quality shadows and improved performance but may cause distant interior spaces to light up incorrectly. "); + } } -void InteriorSunShadows::LoadSettings(json& o_json) +void InteriorSun::LoadSettings(json& o_json) { settings = o_json; } -void InteriorSunShadows::SaveSettings(json& o_json) +void InteriorSun::SaveSettings(json& o_json) { o_json = settings; } -void InteriorSunShadows::RestoreDefaultSettings() +void InteriorSun::RestoreDefaultSettings() { settings = {}; } -void InteriorSunShadows::PostPostLoad() +void InteriorSun::PostPostLoad() { // Hooks and patch to enable directional lighting for interiors stl::write_thunk_call(REL::RelocationID(35562, 36561).address() + REL::Relocate(0x399, 0x37D, 0x639)); @@ -48,6 +58,7 @@ void InteriorSunShadows::PostPostLoad() REL::safe_fill(REL::RelocationID(38900, 39946).address() + REL::Relocate(0x2CA, 0x22B), REL::NOP, REL::Module::IsAE() ? 6 : 2); gShadowDistance = reinterpret_cast(REL::RelocationID(528314, 415263).address()); + gInteriorShadowDistance = reinterpret_cast(REL::RelocationID(513755, 391724).address()); // Patches BSShadowDirectionalLight::SetFrameCamera to read the correct shadow distance value in interior cells const std::uintptr_t address = REL::RelocationID(101499, 108496).address() + REL::Relocate(0xD62, 0xE6C, 0xE72); @@ -56,41 +67,41 @@ void InteriorSunShadows::PostPostLoad() rasterStateCullMode = globals::game::isVR ? &globals::game::shadowState->GetVRRuntimeData().rasterStateCullMode : &globals::game::shadowState->GetRuntimeData().rasterStateCullMode; - logger::info("[Interior Sun Shadows] Installed hooks"); + logger::info("[Interior Sun] Installed hooks"); } -void InteriorSunShadows::EarlyPrepass() +void InteriorSun::EarlyPrepass() { isInteriorWithSun = IsInteriorWithSun(globals::game::tes->interiorCell); } -inline bool InteriorSunShadows::IsInteriorWithSun(const RE::TESObjectCELL* cell) +inline bool InteriorSun::IsInteriorWithSun(const RE::TESObjectCELL* cell) { return cell && cell->cellFlags.all(RE::TESObjectCELL::Flag::kIsInteriorCell, RE::TESObjectCELL::Flag::kShowSky, RE::TESObjectCELL::Flag::kUseSkyLighting, static_cast(CellFlagExt::kSunlightShadows)); } -RE::TESWorldSpace* InteriorSunShadows::GetWorldSpace::thunk(RE::TES* tes) +RE::TESWorldSpace* InteriorSun::GetWorldSpace::thunk(RE::TES* tes) { if (const auto cell = tes->interiorCell) - return IsInteriorWithSun(cell) ? enableInteriorSunShadows : disableInteriorSunShadows; + return IsInteriorWithSun(cell) ? enableInteriorSun : disableInteriorSun; return func(tes); } -RE::TESWorldSpace* InteriorSunShadows::enableInteriorSunShadows = [] { +RE::TESWorldSpace* InteriorSun::enableInteriorSun = [] { alignas(RE::TESWorldSpace) static char buffer[sizeof(RE::TESWorldSpace)]{}; return reinterpret_cast(buffer); }(); -RE::TESWorldSpace* InteriorSunShadows::disableInteriorSunShadows = [] { +RE::TESWorldSpace* InteriorSun::disableInteriorSun = [] { alignas(RE::TESWorldSpace) static char buffer[sizeof(RE::TESWorldSpace)] = {}; const auto noShadows = reinterpret_cast(buffer); noShadows->flags.set(RE::TESWorldSpace::Flag::kNoSky, RE::TESWorldSpace::Flag::kFixedDimensions); return noShadows; }(); -void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLight* dirLight, RE::BSTArray>>& jobArrays, RE::BSTArray>& nodes) +void InteriorSun::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLight* dirLight, RE::BSTArray>>& jobArrays, RE::BSTArray>& nodes) { - auto& singleton = globals::features::interiorSunShadows; + auto& singleton = globals::features::interiorSun; const auto cell = globals::game::tes->interiorCell; auto* passedJobArrays = &jobArrays; @@ -111,7 +122,7 @@ void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLig func(dirLight, *passedJobArrays, nodes); } -void InteriorSunShadows::ClearArrays() +void InteriorSun::ClearArrays() { currentCellRoomsAndPortals.clear(); @@ -127,7 +138,7 @@ namespace RE {}; } -void InteriorSunShadows::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray>>& jobArrays) +void InteriorSun::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray>>& jobArrays) { if (cell != currentCell) { InitialiseOnNewCell(portalGraph); @@ -170,7 +181,7 @@ void InteriorSunShadows::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, c arraysCleared = false; } -void InteriorSunShadows::InitialiseOnNewCell(const RE::NiPointer& portalGraph) +void InteriorSun::InitialiseOnNewCell(const RE::NiPointer& portalGraph) { currentCellRoomsAndPortals.clear(); @@ -183,11 +194,18 @@ void InteriorSunShadows::InitialiseOnNewCell(const RE::NiPointer& object, const RE::NiPoint3& lightDir, const RE::NiPoint3& playerPos) const +bool InteriorSun::IsInSunDirectionAndWithinShadowDistance(const RE::NiPointer& object, const RE::NiPoint3& lightDir, const RE::NiPoint3& playerPos) const { const float radius = object->worldBound.radius; const auto diff = object->worldBound.center - playerPos; const float distance = diff.Length(); const float projection = lightDir.Dot(diff); return projection >= -radius && (distance - radius) <= *gShadowDistance; +} + +void InteriorSun::SetShadowDistance(bool inInterior) +{ + using func_t = decltype(SetShadowDistance); + static REL::Relocation func{ REL::RelocationID(98978, 105631).address() }; + func(inInterior); } \ No newline at end of file diff --git a/src/Features/InteriorSunShadows.h b/src/Features/InteriorSun.h similarity index 92% rename from src/Features/InteriorSunShadows.h rename to src/Features/InteriorSun.h index 05c43556a4..fb74e3473a 100644 --- a/src/Features/InteriorSunShadows.h +++ b/src/Features/InteriorSun.h @@ -1,14 +1,14 @@ #pragma once #include "ShaderCache.h" -struct InteriorSunShadows : Feature +struct InteriorSun : Feature { private: static constexpr std::string_view MOD_ID = "153541"; public: - virtual inline std::string GetName() override { return "Interior Sun Shadows"; } - virtual inline std::string GetShortName() override { return "InteriorSunShadows"; } + virtual inline std::string GetName() override { return "Interior Sun"; } + virtual inline std::string GetShortName() override { return "InteriorSun"; } virtual std::string_view GetCategory() const override { return "Lighting"; } virtual std::pair> GetFeatureSummary() override { @@ -31,6 +31,7 @@ struct InteriorSunShadows : Feature struct Settings { bool ForceDoubleSidedRendering = true; + float InteriorShadowDistance = 5000; }; Settings settings; @@ -73,6 +74,7 @@ struct InteriorSunShadows : Feature }; float* gShadowDistance = nullptr; + float* gInteriorShadowDistance = nullptr; uint32_t* rasterStateCullMode = nullptr; RE::TESObjectCELL* currentCell = nullptr; @@ -82,8 +84,8 @@ struct InteriorSunShadows : Feature RE::BSTArray>> replacementJobArrays = {}; eastl::hash_set addedSet = {}; - static RE::TESWorldSpace* enableInteriorSunShadows; - static RE::TESWorldSpace* disableInteriorSunShadows; + static RE::TESWorldSpace* enableInteriorSun; + static RE::TESWorldSpace* disableInteriorSun; void ClearArrays(); @@ -92,4 +94,6 @@ struct InteriorSunShadows : Feature bool IsInSunDirectionAndWithinShadowDistance(const RE::NiPointer& object, const RE::NiPoint3& lightDir, const RE::NiPoint3& playerPos) const; void PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray>>& jobArrays); + + static void SetShadowDistance(bool inInterior); }; \ No newline at end of file diff --git a/src/Features/VolumetricLighting.cpp b/src/Features/VolumetricLighting.cpp index 49bcad00f9..193fb19099 100644 --- a/src/Features/VolumetricLighting.cpp +++ b/src/Features/VolumetricLighting.cpp @@ -1,6 +1,6 @@ #include "VolumetricLighting.h" -#include "InteriorSunShadows.h" +#include "InteriorSun.h" #include "ShaderCache.h" #include "State.h" @@ -220,7 +220,7 @@ void VolumetricLighting::EarlyPrepass() initialised = true; inInterior = currentlyInInterior; - inInteriorWithSunShadows = InteriorSunShadows::IsInteriorWithSun(interiorCell); + inInteriorWithSun = InteriorSun::IsInteriorWithSun(interiorCell); SetupVL(); } @@ -228,9 +228,9 @@ void VolumetricLighting::SetupVL() { if (inInterior) { if (globals::game::isVR) - SetBooleanSettings(hiddenVRSettings, GetName(), settings.InteriorEnabled && inInteriorWithSunShadows); + SetBooleanSettings(hiddenVRSettings, GetName(), settings.InteriorEnabled && inInteriorWithSun); else - *bEnableVolumetricLighting = settings.InteriorEnabled && inInteriorWithSunShadows; + *bEnableVolumetricLighting = settings.InteriorEnabled && inInteriorWithSun; *gVolumetricLightingSizeHigh = static_cast(settings.InteriorQuality) == Quality::Custom ? settings.InteriorCustomSize : defaultSizeHigh; SetVLQuality(GetVLDescriptor(), settings.InteriorQuality); } else { diff --git a/src/Features/VolumetricLighting.h b/src/Features/VolumetricLighting.h index 9eb9662896..c210b87a1e 100644 --- a/src/Features/VolumetricLighting.h +++ b/src/Features/VolumetricLighting.h @@ -128,7 +128,7 @@ struct VolumetricLighting : Feature bool initialised = false; bool inInterior = false; - bool inInteriorWithSunShadows = false; + bool inInteriorWithSun = false; struct VLData { diff --git a/src/Globals.cpp b/src/Globals.cpp index 66502e2291..763db19c9d 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -19,7 +19,7 @@ #include "Features/GrassLighting.h" #include "Features/HairSpecular.h" #include "Features/IBL.h" -#include "Features/InteriorSunShadows.h" +#include "Features/InteriorSun.h" #include "Features/InverseSquareLighting.h" #include "Features/LODBlending.h" #include "Features/LightLimitFix.h" @@ -63,7 +63,7 @@ namespace globals LightLimitFix lightLimitFix{}; LODBlending lodBlending{}; HairSpecular hairSpecular{}; - InteriorSunShadows interiorSunShadows{}; + InteriorSun interiorSun{}; InverseSquareLighting inverseSquareLighting{}; ScreenSpaceGI screenSpaceGI{}; ScreenSpaceShadows screenSpaceShadows{}; diff --git a/src/Globals.h b/src/Globals.h index ea5cfde817..cf1bd657fe 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -9,7 +9,7 @@ struct HairSpecular; struct IBL; struct LightLimitFix; struct LODBlending; -struct InteriorSunShadows; +struct InteriorSun; struct InverseSquareLighting; struct ScreenSpaceGI; struct ScreenSpaceShadows; @@ -64,7 +64,7 @@ namespace globals extern IBL ibl; extern LightLimitFix lightLimitFix; extern LODBlending lodBlending; - extern InteriorSunShadows interiorSunShadows; + extern InteriorSun interiorSun; extern InverseSquareLighting inverseSquareLighting; extern ScreenSpaceGI screenSpaceGI; extern ScreenSpaceShadows screenSpaceShadows; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 3c882a4d83..ccaef28d17 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -9,7 +9,7 @@ #include "TruePBR.h" #include "Util.h" -#include "Features/InteriorSunShadows.h" +#include "Features/InteriorSun.h" #include "Features/LightLimitFix.h" #include "Features/TerrainHelper.h" #include "Features/VR.h" @@ -900,8 +900,8 @@ namespace Hooks if (globals::features::lightLimitFix.loaded && !globals::features::lightLimitFix.CheckParticleLights(a_pass, a_technique)) return; - if (globals::features::interiorSunShadows.loaded) - globals::features::interiorSunShadows.UpdateRasterStateCullMode(a_pass, a_technique); + if (globals::features::interiorSun.loaded) + globals::features::interiorSun.UpdateRasterStateCullMode(a_pass, a_technique); func(a_pass, a_technique, a_alphaTest, a_renderFlags); } diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 36e9c13bae..0602980734 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -3,7 +3,7 @@ #include "TruePBR/BSLightingShaderMaterialPBR.h" #include "TruePBR/BSLightingShaderMaterialPBRLandscape.h" -#include "Features/InteriorSunShadows.h" +#include "Features/InteriorSun.h" #include "Hooks.h" #include "ShaderCache.h" #include "State.h" @@ -675,7 +675,7 @@ struct BSLightingShaderProperty_GetRenderPasses return renderPasses; } - const auto issEnabledAndInteriorWithSun = globals::features::interiorSunShadows.loaded && globals::features::interiorSunShadows.isInteriorWithSun; + const auto issEnabledAndInteriorWithSun = globals::features::interiorSun.loaded && globals::features::interiorSun.isInteriorWithSun; bool isPbr = false; diff --git a/src/XSEPlugin.cpp b/src/XSEPlugin.cpp index 9689b31bff..76b571444b 100644 --- a/src/XSEPlugin.cpp +++ b/src/XSEPlugin.cpp @@ -154,7 +154,7 @@ bool Load() } if (REL::Module::IsVR()) { - REL::IDDatabase::get().IsVRAddressLibraryAtLeastVersion("0.182.0", true); + REL::IDDatabase::get().IsVRAddressLibraryAtLeastVersion("0.189.0", true); } auto privateProfileRedirectorVersion = Util::GetDllVersion(L"Data/SKSE/Plugins/PrivateProfileRedirector.dll");