Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -219,7 +219,7 @@ const std::vector<Feature*>& 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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
#include "InteriorSunShadows.h"
#include "InteriorSun.h"
#include "State.h"

#include <numbers>

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()) {
ImGui::Text(
"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);
}
Comment thread
sicsix marked this conversation as resolved.
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<GetWorldSpace>(REL::RelocationID(35562, 36561).address() + REL::Relocate(0x399, 0x37D, 0x639));
Expand All @@ -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<float*>(REL::RelocationID(528314, 415263).address());
gInteriorShadowDistance = reinterpret_cast<float*>(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);
Expand All @@ -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<RE::TESObjectCELL::Flag>(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<RE::TESWorldSpace*>(buffer);
}();

RE::TESWorldSpace* InteriorSunShadows::disableInteriorSunShadows = [] {
RE::TESWorldSpace* InteriorSun::disableInteriorSun = [] {
alignas(RE::TESWorldSpace) static char buffer[sizeof(RE::TESWorldSpace)] = {};
const auto noShadows = reinterpret_cast<RE::TESWorldSpace*>(buffer);
noShadows->flags.set(RE::TESWorldSpace::Flag::kNoSky, RE::TESWorldSpace::Flag::kFixedDimensions);
return noShadows;
}();

void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLight* dirLight, RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>>& jobArrays, RE::BSTArray<RE::NiPointer<RE::NiAVObject>>& nodes)
void InteriorSun::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLight* dirLight, RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>>& jobArrays, RE::BSTArray<RE::NiPointer<RE::NiAVObject>>& nodes)
{
auto& singleton = globals::features::interiorSunShadows;
auto& singleton = globals::features::interiorSun;
const auto cell = globals::game::tes->interiorCell;
auto* passedJobArrays = &jobArrays;

Expand All @@ -111,7 +122,7 @@ void InteriorSunShadows::DirShadowLightCulling::thunk(RE::BSShadowDirectionalLig
func(dirLight, *passedJobArrays, nodes);
}

void InteriorSunShadows::ClearArrays()
void InteriorSun::ClearArrays()
{
currentCellRoomsAndPortals.clear();

Expand All @@ -127,7 +138,7 @@ namespace RE
{};
}

void InteriorSunShadows::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer<RE::BSPortalGraph>& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>>& jobArrays)
void InteriorSun::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer<RE::BSPortalGraph>& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>>& jobArrays)
{
if (cell != currentCell) {
InitialiseOnNewCell(portalGraph);
Expand Down Expand Up @@ -170,7 +181,7 @@ void InteriorSunShadows::PopulateReplacementJobArrays(RE::TESObjectCELL* cell, c
arraysCleared = false;
}

void InteriorSunShadows::InitialiseOnNewCell(const RE::NiPointer<RE::BSPortalGraph>& portalGraph)
void InteriorSun::InitialiseOnNewCell(const RE::NiPointer<RE::BSPortalGraph>& portalGraph)
{
currentCellRoomsAndPortals.clear();

Expand All @@ -183,11 +194,18 @@ void InteriorSunShadows::InitialiseOnNewCell(const RE::NiPointer<RE::BSPortalGra
}
}

bool InteriorSunShadows::IsInSunDirectionAndWithinShadowDistance(const RE::NiPointer<RE::NiAVObject>& object, const RE::NiPoint3& lightDir, const RE::NiPoint3& playerPos) const
bool InteriorSun::IsInSunDirectionAndWithinShadowDistance(const RE::NiPointer<RE::NiAVObject>& 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;
}
Comment thread
sicsix marked this conversation as resolved.

void InteriorSun::SetShadowDistance(bool inInterior)
{
using func_t = decltype(SetShadowDistance);
static REL::Relocation<func_t> func{ REL::RelocationID(98978, 105631).address() };
func(inInterior);
}
14 changes: 9 additions & 5 deletions src/Features/InteriorSunShadows.h → src/Features/InteriorSun.h
Original file line number Diff line number Diff line change
@@ -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<std::string, std::vector<std::string>> GetFeatureSummary() override
{
Expand All @@ -31,6 +31,7 @@ struct InteriorSunShadows : Feature
struct Settings
{
bool ForceDoubleSidedRendering = true;
float InteriorShadowDistance = 5000;
};

Settings settings;
Expand Down Expand Up @@ -73,6 +74,7 @@ struct InteriorSunShadows : Feature
};

float* gShadowDistance = nullptr;
float* gInteriorShadowDistance = nullptr;
uint32_t* rasterStateCullMode = nullptr;

RE::TESObjectCELL* currentCell = nullptr;
Expand All @@ -82,8 +84,8 @@ struct InteriorSunShadows : Feature
RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>> replacementJobArrays = {};
eastl::hash_set<RE::NiAVObject*> addedSet = {};

static RE::TESWorldSpace* enableInteriorSunShadows;
static RE::TESWorldSpace* disableInteriorSunShadows;
static RE::TESWorldSpace* enableInteriorSun;
static RE::TESWorldSpace* disableInteriorSun;

void ClearArrays();

Expand All @@ -92,4 +94,6 @@ struct InteriorSunShadows : Feature
bool IsInSunDirectionAndWithinShadowDistance(const RE::NiPointer<RE::NiAVObject>& object, const RE::NiPoint3& lightDir, const RE::NiPoint3& playerPos) const;

void PopulateReplacementJobArrays(RE::TESObjectCELL* cell, const RE::NiPointer<RE::BSPortalGraph>& portalGraph, const RE::BSShadowDirectionalLight* dirLight, RE::BSTArray<RE::BSTArray<RE::NiPointer<RE::NiAVObject>>>& jobArrays);

static void SetShadowDistance(bool inInterior);
};
8 changes: 4 additions & 4 deletions src/Features/VolumetricLighting.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "VolumetricLighting.h"

#include "InteriorSunShadows.h"
#include "InteriorSun.h"
#include "ShaderCache.h"
#include "State.h"

Expand Down Expand Up @@ -220,17 +220,17 @@ void VolumetricLighting::EarlyPrepass()

initialised = true;
inInterior = currentlyInInterior;
inInteriorWithSunShadows = InteriorSunShadows::IsInteriorWithSun(interiorCell);
inInteriorWithSun = InteriorSun::IsInteriorWithSun(interiorCell);
SetupVL();
}

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<Quality>(settings.InteriorQuality) == Quality::Custom ? settings.InteriorCustomSize : defaultSizeHigh;
SetVLQuality(GetVLDescriptor(), settings.InteriorQuality);
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/Features/VolumetricLighting.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct VolumetricLighting : Feature

bool initialised = false;
bool inInterior = false;
bool inInteriorWithSunShadows = false;
bool inInteriorWithSun = false;

struct VLData
{
Expand Down
4 changes: 2 additions & 2 deletions src/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -63,7 +63,7 @@ namespace globals
LightLimitFix lightLimitFix{};
LODBlending lodBlending{};
HairSpecular hairSpecular{};
InteriorSunShadows interiorSunShadows{};
InteriorSun interiorSun{};
InverseSquareLighting inverseSquareLighting{};
ScreenSpaceGI screenSpaceGI{};
ScreenSpaceShadows screenSpaceShadows{};
Expand Down
4 changes: 2 additions & 2 deletions src/Globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct HairSpecular;
struct IBL;
struct LightLimitFix;
struct LODBlending;
struct InteriorSunShadows;
struct InteriorSun;
struct InverseSquareLighting;
struct ScreenSpaceGI;
struct ScreenSpaceShadows;
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions src/TruePBR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/XSEPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down