diff --git a/src/Features/SkySync.cpp b/src/Features/SkySync.cpp index 34ba991186..344ea0494d 100644 --- a/src/Features/SkySync.cpp +++ b/src/Features/SkySync.cpp @@ -1,4 +1,4 @@ -#include "SkySync.h" +#include "SkySync.h" NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( SkySync::Settings, @@ -6,7 +6,12 @@ NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( UseAlternateSunPath, MoonLightSource, SunPath, - CustomAngle) + CustomAngle, + SunriseBeginOffset, + SunriseEndOffset, + SunsetBeginOffset, + SunsetEndOffset, + MinShadowElevation) void SkySync::DrawSettings() { @@ -25,6 +30,20 @@ void SkySync::DrawSettings() } ImGui::SliderInt("Moon light source", &settings.MoonLightSource, 0, static_cast(MoonLightSource::Count) - 1, MoonLightSourceNames[settings.MoonLightSource], ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderFloat("Min Shadow Elevation", &settings.MinShadowElevation, 0.0f, 45.0f, "%.1f deg", ImGuiSliderFlags_AlwaysClamp); + if (auto _tt = Util::HoverTooltipWrapper()) { + ImGui::Text("The minimum angle sunlight will set to. Caps shadow length. Higher = shorter shadows at sunset/sunrise."); + } + ImGui::Spacing(); + ImGui::Spacing(); + if (ImGui::TreeNodeEx("Sun Position Offsets", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::TextWrapped("Moves sun height during sunrise/sunset. Reset weather to see changes."); + ImGui::SliderFloat("Sunrise Begin (Hours)", &settings.SunriseBeginOffset, -5.0f, 5.0f, "%.1f", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderFloat("Sunrise End (Hours)", &settings.SunriseEndOffset, -5.0f, 5.0f, "%.1f", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderFloat("Sunset Begin (Hours)", &settings.SunsetBeginOffset, -5.0f, 5.0f, "%.1f", ImGuiSliderFlags_AlwaysClamp); + ImGui::SliderFloat("Sunset End (Hours)", &settings.SunsetEndOffset, -5.0f, 5.0f, "%.1f", ImGuiSliderFlags_AlwaysClamp); + ImGui::TreePop(); + } } void SkySync::LoadSettings(json& o_json) @@ -32,6 +51,12 @@ void SkySync::LoadSettings(json& o_json) settings = o_json; settings.MoonLightSource = std::clamp(settings.MoonLightSource, static_cast(MoonLightSource::Brightest), static_cast(MoonLightSource::Secunda)); settings.SunPath = std::clamp(settings.SunPath, static_cast(SunPath::Southern), static_cast(SunPath::Custom)); + settings.CustomAngle = std::clamp(settings.CustomAngle, -90.0f, 90.0f); + settings.SunriseBeginOffset = std::clamp(settings.SunriseBeginOffset, -5.0f, 5.0f); + settings.SunriseEndOffset = std::clamp(settings.SunriseEndOffset, -5.0f, 5.0f); + settings.SunsetBeginOffset = std::clamp(settings.SunsetBeginOffset, -5.0f, 5.0f); + settings.SunsetEndOffset = std::clamp(settings.SunsetEndOffset, -5.0f, 5.0f); + settings.MinShadowElevation = std::clamp(settings.MinShadowElevation, 0.0f, 45.0f); SetSunAngle(); } @@ -394,7 +419,8 @@ void SkySync::ShadowFader::SetLighting(const RE::Sun* sun, RE::NiPoint3 dir, flo inline void SkySync::ShadowFader::ClampDirection(RE::NiPoint3& dir) { - constexpr float minElev = DirectX::XMConvertToRadians(MinElevation); + const float minDegrees = globals::features::skySync.settings.MinShadowElevation; + const float minElev = DirectX::XMConvertToRadians(minDegrees); const float elev = DirectX::XMScalarASinEst(dir.z); if (elev >= minElev) return; @@ -419,10 +445,25 @@ SkySync::VolumetricLightingDescriptor* SkySync::ApplyVolumetricLighting_Volumetr void SkySync::ClimateTimings::Update(const RE::TESClimate* climate) { - sunriseBegin = climate->timing.sunrise.begin / 6.0f; - sunriseEnd = climate->timing.sunrise.end / 6.0f; - sunsetBegin = climate->timing.sunset.begin / 6.0f; - sunsetEnd = climate->timing.sunset.end / 6.0f; + const float SunriseBeginOffset = globals::features::skySync.settings.SunriseBeginOffset; + const float SunriseEndOffset = globals::features::skySync.settings.SunriseEndOffset; + const float SunsetBeginOffset = globals::features::skySync.settings.SunsetBeginOffset; + const float SunsetEndOffset = globals::features::skySync.settings.SunsetEndOffset; + + sunriseBegin = (climate->timing.sunrise.begin / 6.0f) + SunriseBeginOffset; + sunriseEnd = (climate->timing.sunrise.end / 6.0f) + SunriseEndOffset; + sunsetBegin = (climate->timing.sunset.begin / 6.0f) + SunsetBeginOffset; + sunsetEnd = (climate->timing.sunset.end / 6.0f) + SunsetEndOffset; + // Basic ordering guarantees (prevents divide-by-zero / negative duration paths). + constexpr float kMinGapHours = 0.1f; + if (sunriseEnd <= sunriseBegin) + sunriseEnd = sunriseBegin + kMinGapHours; + if (sunsetEnd <= sunsetBegin) + sunsetEnd = sunsetBegin + kMinGapHours; + if (sunsetBegin <= sunriseEnd) + sunsetBegin = sunriseEnd + kMinGapHours; + if (sunsetEnd <= sunsetBegin) + sunsetEnd = sunsetBegin + kMinGapHours; sunrise = (sunriseBegin + sunriseEnd) * 0.5f - 0.25f; sunset = (sunsetBegin + sunsetEnd) * 0.5f + 0.25f; sunriseFadeOutMoonStart = sunriseBegin - 0.5f; diff --git a/src/Features/SkySync.h b/src/Features/SkySync.h index 90546865d6..6806599183 100644 --- a/src/Features/SkySync.h +++ b/src/Features/SkySync.h @@ -31,6 +31,11 @@ struct SkySync : Feature int32_t MoonLightSource = 0; int32_t SunPath = 0; float CustomAngle = -35.0f; + float SunriseBeginOffset = 0.0f; + float SunriseEndOffset = 0.0f; + float SunsetBeginOffset = 0.0f; + float SunsetEndOffset = 0.0f; + float MinShadowElevation = 0.25f; }; Settings settings; @@ -147,7 +152,6 @@ struct SkySync : Feature static constexpr float SunHorizonDistance = 280.0f; static constexpr float SunPeakDistance = 400.0f; static constexpr float SunScaleFactor = 48.0f / 2048.0f; - static constexpr float MinElevation = 0.25f; static constexpr float SouthernSunAngle = 90.0f - 35.0f; static constexpr float NorthernSunAngle = 90.0f + 35.0f; @@ -206,4 +210,4 @@ struct SkySync : Feature static void SetSunBaseVisibility(const RE::Sun* sun, float visibility); static float SmoothStep(float start, float end, float x); -}; \ No newline at end of file +};