diff --git a/src/Features/InteriorSunShadows.cpp b/src/Features/InteriorSunShadows.cpp index ea766f2756..47ef72cce2 100644 --- a/src/Features/InteriorSunShadows.cpp +++ b/src/Features/InteriorSunShadows.cpp @@ -1,4 +1,4 @@ -#include "InteriorSunShadows.h" +#include "InteriorSunShadows.h" #include "State.h" #include @@ -44,11 +44,27 @@ void InteriorSunShadows::EarlyPrepass() isInteriorWithSun = IsInteriorWithSun(globals::game::tes->interiorCell); } +/** + * @brief Determines if a cell is an interior that supports sun lighting and shadows. + * + * Returns true if the given cell is non-null and has the flags for interior cell, show sky, use sky lighting, and sunlight shadows all set. + * + * @param cell Pointer to the cell to check. + * @return true if the cell is an interior with sun lighting and shadows enabled; false otherwise. + */ inline bool InteriorSunShadows::IsInteriorWithSun(const RE::TESObjectCELL* cell) { - return cell && cell->cellFlags.all(RE::TESObjectCELL::Flag::kIsInteriorCell, RE::TESObjectCELL::Flag::kShowSky, RE::TESObjectCELL::Flag::kUseSkyLighting); + return cell && cell->cellFlags.all(RE::TESObjectCELL::Flag::kIsInteriorCell, RE::TESObjectCELL::Flag::kShowSky, RE::TESObjectCELL::Flag::kUseSkyLighting, static_cast(CellFlagExt::kSunlightShadows)); } +/** + * @brief Returns a dummy TESWorldSpace object based on whether the TES object's interior cell supports sun shadows. + * + * If the TES object's interior cell exists and qualifies as an interior with sun (per IsInteriorWithSun), returns a special dummy TESWorldSpace to enable sun shadows. Otherwise, returns a dummy TESWorldSpace that disables sun shadows. Falls back to the original GetWorldSpace function if no interior cell is present. + * + * @param tes The TES object whose world space is being queried. + * @return TESWorldSpace* A pointer to the appropriate dummy TESWorldSpace or the result of the original function. + */ RE::TESWorldSpace* InteriorSunShadows::GetWorldSpace::thunk(RE::TES* tes) { if (const auto cell = tes->interiorCell) diff --git a/src/Features/InteriorSunShadows.h b/src/Features/InteriorSunShadows.h index 9590a6b229..6db935d8bc 100644 --- a/src/Features/InteriorSunShadows.h +++ b/src/Features/InteriorSunShadows.h @@ -1,6 +1,12 @@ -#pragma once +#pragma once #include "ShaderCache.h" +/** + * @brief Determines if the specified cell is an interior that receives sunlight. + * + * @param cell Pointer to the cell to check. + * @return true if the cell is an interior with sunlight; otherwise, false. + */ struct InteriorSunShadows : Feature { static InteriorSunShadows* GetSingleton() @@ -51,7 +57,14 @@ struct InteriorSunShadows : Feature } } + static bool IsInteriorWithSun(const RE::TESObjectCELL* cell); + private: + enum class CellFlagExt : uint16_t + { + kSunlightShadows = 1 << 15, + }; + float* gShadowDistance = nullptr; uint32_t* rasterStateCullMode = nullptr; @@ -69,8 +82,6 @@ struct InteriorSunShadows : Feature void InitialiseOnNewCell(const RE::NiPointer& portalGraph); - static bool IsInteriorWithSun(const RE::TESObjectCELL* cell); - 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); diff --git a/src/Features/VolumetricLighting.cpp b/src/Features/VolumetricLighting.cpp index 3ca48cc947..8604a84348 100644 --- a/src/Features/VolumetricLighting.cpp +++ b/src/Features/VolumetricLighting.cpp @@ -1,5 +1,6 @@ #include "VolumetricLighting.h" +#include "InteriorSunShadows.h" #include "ShaderCache.h" #include "State.h" @@ -179,6 +180,11 @@ void VolumetricLighting::PostPostLoad() defaultSizeHigh = *gVolumetricLightingSizeHigh; } +/** + * @brief Updates volumetric lighting state based on the player's current location. + * + * Detects whether the player has entered or exited an interior cell and whether the interior supports sun shadows. Applies appropriate volumetric lighting settings if the state has changed. + */ void VolumetricLighting::EarlyPrepass() { const auto interiorCell = globals::game::tes->interiorCell; @@ -189,7 +195,7 @@ void VolumetricLighting::EarlyPrepass() initialised = true; inInterior = currentlyInInterior; - inInteriorWithSunShadows = interiorCell && interiorCell->cellFlags.all(RE::TESObjectCELL::Flag::kIsInteriorCell, RE::TESObjectCELL::Flag::kShowSky, RE::TESObjectCELL::Flag::kUseSkyLighting); + inInteriorWithSunShadows = InteriorSunShadows::IsInteriorWithSun(interiorCell); SetupVL(); }