From 21ace2e12a113bb70467200657b2749117d6a920 Mon Sep 17 00:00:00 2001 From: sicsix <8847273+sicsix@users.noreply.github.com> Date: Tue, 27 May 2025 10:39:32 +1000 Subject: [PATCH 1/2] fix(iss): fixes broken shadowmap culling on leaving and re-entering interiors --- src/Features/InteriorSunShadows.cpp | 36 +++++++++++++++++++++-------- src/Features/InteriorSunShadows.h | 5 +++- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/Features/InteriorSunShadows.cpp b/src/Features/InteriorSunShadows.cpp index 41ea4f1c0d..aeef2717e9 100644 --- a/src/Features/InteriorSunShadows.cpp +++ b/src/Features/InteriorSunShadows.cpp @@ -12,11 +12,26 @@ void InteriorSunShadows::DrawSettings() ImGui::Checkbox("Force Double-Sided Rendering", &settings.ForceDoubleSidedRendering); if (auto _tt = Util::HoverTooltipWrapper()) { ImGui::Text( - "Forces double-sided vertices during sun shadowmap rendering on interiors. " + "Disables backface culling during sun shadowmap rendering in interiors. " "Will prevent most light leaking through unmasked/unprepared interiors at a small performance cost. "); } } +void InteriorSunShadows::LoadSettings(json& o_json) +{ + settings = o_json; +} + +void InteriorSunShadows::SaveSettings(json& o_json) +{ + o_json = settings; +} + +void InteriorSunShadows::RestoreDefaultSettings() +{ + settings = {}; +} + void InteriorSunShadows::PostPostLoad() { // Hooks and patch to enable directional lighting for interiors @@ -74,14 +89,18 @@ void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLig const auto cell = globals::game::tes->interiorCell; auto* passedJobArrays = &jobArrays; - if (!cell) { - singleton->ClearArrays(); - } else { - const auto portalGraph = cell->GetRuntimeData().loadedData->portalGraph; - if (singleton->isInteriorWithSun && portalGraph) { + if (cell && singleton->isInteriorWithSun) { + const auto* loadedData = cell->GetRuntimeData().loadedData; + const auto portalGraph = loadedData ? loadedData->portalGraph : nullptr; + if (portalGraph) { singleton->PopulateReplacementJobArrays(cell, portalGraph, dirLight, jobArrays); passedJobArrays = &singleton->replacementJobArrays; - } + } else + singleton->currentCell = nullptr; + } else { + if (!singleton->arraysCleared) + singleton->ClearArrays(); + singleton->currentCell = nullptr; } func(dirLight, *passedJobArrays, nodes); @@ -89,9 +108,6 @@ void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLig void InteriorSunShadows::ClearArrays() { - if (arraysCleared) - return; - currentCellRoomsAndPortals.clear(); for (auto& jobArray : replacementJobArrays) diff --git a/src/Features/InteriorSunShadows.h b/src/Features/InteriorSunShadows.h index 0139654a53..0ab5c475ef 100644 --- a/src/Features/InteriorSunShadows.h +++ b/src/Features/InteriorSunShadows.h @@ -12,6 +12,9 @@ struct InteriorSunShadows : Feature virtual inline std::string GetName() override { return "Interior Sun Shadows"; } virtual inline std::string GetShortName() override { return "InteriorSunShadows"; } virtual void DrawSettings() override; + virtual void LoadSettings(json& o_json) override; + virtual void SaveSettings(json& o_json) override; + virtual void RestoreDefaultSettings() override; virtual bool SupportsVR() override { return true; } virtual void PostPostLoad() override; virtual void EarlyPrepass() override; @@ -40,7 +43,7 @@ struct InteriorSunShadows : Feature void UpdateRasterStateCullMode(const RE::BSRenderPass* pass, const uint32_t technique) const { if (isInteriorWithSun && settings.ForceDoubleSidedRendering && technique & static_cast(SIE::ShaderCache::UtilityShaderFlags::RenderShadowmap)) { - const auto renderTwoSided = pass->shaderProperty->flags.none(RE::BSShaderProperty::EShaderPropertyFlag::kAssumeShadowmask); + const auto renderTwoSided = pass->shaderProperty->flags.none(RE::BSShaderProperty::EShaderPropertyFlag::kAssumeShadowmask, RE::BSShaderProperty::EShaderPropertyFlag::kSkinned); if (renderTwoSided && *rasterStateCullMode != 0) { *rasterStateCullMode = 0; globals::game::stateUpdateFlags->set(RE::BSGraphics::DIRTY_RASTER_CULL_MODE); From b5f4f17d65f4a564a42db57535fe61e147bea113 Mon Sep 17 00:00:00 2001 From: sicsix <8847273+sicsix@users.noreply.github.com> Date: Tue, 27 May 2025 12:14:51 +1000 Subject: [PATCH 2/2] fix double-sided meshes from being rendered single-sided --- src/Features/InteriorSunShadows.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Features/InteriorSunShadows.h b/src/Features/InteriorSunShadows.h index 0ab5c475ef..97d9f9ecd2 100644 --- a/src/Features/InteriorSunShadows.h +++ b/src/Features/InteriorSunShadows.h @@ -43,7 +43,8 @@ struct InteriorSunShadows : Feature void UpdateRasterStateCullMode(const RE::BSRenderPass* pass, const uint32_t technique) const { if (isInteriorWithSun && settings.ForceDoubleSidedRendering && technique & static_cast(SIE::ShaderCache::UtilityShaderFlags::RenderShadowmap)) { - const auto renderTwoSided = pass->shaderProperty->flags.none(RE::BSShaderProperty::EShaderPropertyFlag::kAssumeShadowmask, RE::BSShaderProperty::EShaderPropertyFlag::kSkinned); + const auto flags = pass->shaderProperty->flags; + const auto renderTwoSided = flags.all(RE::BSShaderProperty::EShaderPropertyFlag::kTwoSided) || flags.none(RE::BSShaderProperty::EShaderPropertyFlag::kAssumeShadowmask, RE::BSShaderProperty::EShaderPropertyFlag::kSkinned); if (renderTwoSided && *rasterStateCullMode != 0) { *rasterStateCullMode = 0; globals::game::stateUpdateFlags->set(RE::BSGraphics::DIRTY_RASTER_CULL_MODE);