From 7221579e3939e4fb6d3c03d8b758dad40f3d473f Mon Sep 17 00:00:00 2001 From: TheRiverwoodModder <125157333+TheRiverwoodModder@users.noreply.github.com> Date: Wed, 10 Jan 2024 08:50:58 -0800 Subject: [PATCH] fix: fix wetness calculation logic (#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Added Fog wetness, Refactored Rain and Snow logic, Moved MaxWetness to the CPU, and Fixed perPass struct * style: 🎨 apply clang-format changes * Removed snow and fog detection logic * style: 🎨 apply clang-format changes --------- Co-authored-by: TheRiverwoodModder --- .../Shaders/Features/WetnessEffects.ini | 2 +- .../WetnessEffects/WetnessEffects.hlsli | 4 +- package/Shaders/Lighting.hlsl | 4 +- src/Features/WetnessEffects.cpp | 81 +++++++++++-------- src/Features/WetnessEffects.h | 5 +- 5 files changed, 57 insertions(+), 39 deletions(-) diff --git a/features/Wetness Effects/Shaders/Features/WetnessEffects.ini b/features/Wetness Effects/Shaders/Features/WetnessEffects.ini index 305f89b11..c2827628a 100644 --- a/features/Wetness Effects/Shaders/Features/WetnessEffects.ini +++ b/features/Wetness Effects/Shaders/Features/WetnessEffects.ini @@ -1,2 +1,2 @@ [Info] -Version = 0-9-2 \ No newline at end of file +Version = 0-9-3 \ No newline at end of file diff --git a/features/Wetness Effects/Shaders/WetnessEffects/WetnessEffects.hlsli b/features/Wetness Effects/Shaders/WetnessEffects/WetnessEffects.hlsli index 2a8c576a2..8979699e4 100644 --- a/features/Wetness Effects/Shaders/WetnessEffects/WetnessEffects.hlsli +++ b/features/Wetness Effects/Shaders/WetnessEffects/WetnessEffects.hlsli @@ -7,12 +7,10 @@ struct PerPassWetnessEffects uint EnableWetnessEffects; float MaxRainWetness; float MaxShoreWetness; - float MaxOcclusion; uint ShoreRange; - float PuddleMinWetness; float PuddleRadius; float PuddleMaxAngle; - float PuddleFlatness; + float PuddleMinWetness; }; StructuredBuffer perPassWetnessEffects : register(t22); diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index b5306ebe4..53ccd0b17 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -1576,9 +1576,9 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif # if !defined(LOD) - wetness = max(shoreFactor * perPassWetnessEffects[0].MaxShoreWetness, rainWetness * perPassWetnessEffects[0].MaxRainWetness); + wetness = max(shoreFactor * perPassWetnessEffects[0].MaxShoreWetness, rainWetness); # else - wetness = rainWetness * perPassWetnessEffects[0].MaxRainWetness; + wetness = rainWetness; # endif float3 wetnessNormal = worldSpaceNormal; diff --git a/src/Features/WetnessEffects.cpp b/src/Features/WetnessEffects.cpp index 4daa5e273..e2d2d0919 100644 --- a/src/Features/WetnessEffects.cpp +++ b/src/Features/WetnessEffects.cpp @@ -3,8 +3,9 @@ const float MIN_START_PERCENTAGE = 0.05f; const float DEFAULT_TRANSITION_PERCENTAGE = 1.0f; -const float TRANSITION_CURVE_MULTIPLIER = 3.0f; +const float TRANSITION_CURVE_MULTIPLIER = 2.0f; const float TRANSITION_DENOMINATOR = 256.0f; +const float DRY_WETNESS = 0.0f; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( WetnessEffects::Settings, @@ -41,6 +42,37 @@ void WetnessEffects::DrawSettings() } } +float WetnessEffects::CalculateWeatherTransitionPercentage(RE::TESWeather* weather, float skyCurrentWeatherPct, float beginFade) +{ + float weatherTransitionPercentage = DEFAULT_TRANSITION_PERCENTAGE; + if (weather) { + // Correct if beginFade is zero or negative + beginFade = beginFade > 0 ? beginFade : beginFade + TRANSITION_DENOMINATOR; + // Wait to start transition until precipitation begins/ends + float startPercentage = (TRANSITION_DENOMINATOR - beginFade) * (1.0f / TRANSITION_DENOMINATOR); + startPercentage = startPercentage > MIN_START_PERCENTAGE ? startPercentage : MIN_START_PERCENTAGE; + float currentPercentage = (skyCurrentWeatherPct - startPercentage) / (1 - startPercentage); + weatherTransitionPercentage = std::clamp(currentPercentage, 0.0f, 1.0f); + } + return weatherTransitionPercentage; +} + +float WetnessEffects::CalculateWetness(RE::TESWeather* weather, RE::Sky* sky) +{ + float wetness = DRY_WETNESS; + if (weather && sky) { + const char* name = weather->GetName(); + if (name) { + // Figure out the weather type and set the wetness + if (weather->precipitationData && weather->data.flags.any(RE::TESWeather::WeatherDataFlag::kRainy)) { + // Raining + wetness = settings.MaxRainWetness; + } + } + } + return wetness; +} + void WetnessEffects::Draw(const RE::BSShader* shader, const uint32_t) { if (shader->shaderType.any(RE::BSShader::Type::Lighting)) { @@ -49,51 +81,34 @@ void WetnessEffects::Draw(const RE::BSShader* shader, const uint32_t) auto context = RE::BSGraphics::Renderer::GetSingleton()->GetRuntimeData().context; PerPass data{}; - data.Wetness = 0; + data.Wetness = DRY_WETNESS; if (settings.EnableWetnessEffects) { if (auto player = RE::PlayerCharacter::GetSingleton()) { if (auto cell = player->GetParentCell()) { if (!cell->IsInteriorCell()) { if (auto sky = RE::Sky::GetSingleton()) { - float weatherTransitionPercentage = DEFAULT_TRANSITION_PERCENTAGE; - float wetnessCurrentWeather = 0.0f; - float wetnessOutgoingDay = 0.0f; if (auto currentWeather = sky->currentWeather) { - // Fade in gradually after precipitation has started - float beginFade = currentWeather->data.precipitationBeginFadeIn; - beginFade = beginFade > 0 ? beginFade : beginFade + TRANSITION_DENOMINATOR; - float startPercentage = (TRANSITION_DENOMINATOR - beginFade) * (1.0f / TRANSITION_DENOMINATOR); - startPercentage = startPercentage > MIN_START_PERCENTAGE ? startPercentage : MIN_START_PERCENTAGE; - float currentPercentage = (sky->currentWeatherPct - startPercentage) / (1 - startPercentage); - weatherTransitionPercentage = std::clamp(currentPercentage, 0.0f, 1.0f); - - float wetness = 0.0; - if (currentWeather->data.flags.any(RE::TESWeather::WeatherDataFlag::kRainy)) { - // Currently raining - wetnessCurrentWeather = 1.0f; - } else if (currentWeather->data.flags.any(RE::TESWeather::WeatherDataFlag::kSnow)) { - wetnessCurrentWeather = 0.5f; - } else { - wetnessCurrentWeather = 0.0f; - } - - wetness += wetnessCurrentWeather * std::pow(weatherTransitionPercentage, 0.5f); + float weatherTransitionPercentage = DEFAULT_TRANSITION_PERCENTAGE; + float wetnessCurrentWeather = CalculateWetness(currentWeather, sky); + float wetnessLastWeather = DRY_WETNESS; + // If there is a lastWeather, figure out what type it is and set the wetness if (auto lastWeather = sky->lastWeather) { + wetnessLastWeather = CalculateWetness(lastWeather, sky); + + // If it was raining, wait to transition until precipitation ends, otherwise use the current weather's fade in if (lastWeather->data.flags.any(RE::TESWeather::WeatherDataFlag::kRainy)) { - // Was raining before - wetnessOutgoingDay = 1.0f; - } else if (lastWeather->data.flags.any(RE::TESWeather::WeatherDataFlag::kSnow)) { - wetnessOutgoingDay = 0.5f; + weatherTransitionPercentage = CalculateWeatherTransitionPercentage(lastWeather, sky->currentWeatherPct, lastWeather->data.precipitationEndFadeOut); } else { - wetnessOutgoingDay = 0.0f; + weatherTransitionPercentage = CalculateWeatherTransitionPercentage(currentWeather, sky->currentWeatherPct, currentWeather->data.precipitationBeginFadeIn); } + // Adjust the transition curve to ease in/out of the transition + weatherTransitionPercentage = (exp2(TRANSITION_CURVE_MULTIPLIER * log2(weatherTransitionPercentage))); } - wetness += wetnessOutgoingDay * std::pow(1.0f - (sky->currentWeatherPct), 0.5f); - - data.Wetness = std::clamp(wetness, 0.0f, 1.0f); + // Transition between CurrentWeather and LastWeather wetness values + data.Wetness = std::lerp(wetnessLastWeather, wetnessCurrentWeather, weatherTransitionPercentage); } } } @@ -106,6 +121,8 @@ void WetnessEffects::Draw(const RE::BSShader* shader, const uint32_t) Util::StoreTransform3x4NoScale(data.DirectionalAmbientWS, dalcTransform); data.settings = settings; + // Disable Shore Wetness if Wetness Effects are Disabled + data.settings.MaxShoreWetness = settings.EnableWetnessEffects ? settings.MaxShoreWetness : 0.0f; D3D11_MAPPED_SUBRESOURCE mapped; DX::ThrowIfFailed(context->Map(perPass->resource.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped)); diff --git a/src/Features/WetnessEffects.h b/src/Features/WetnessEffects.h index 55f43f75d..5fe21230e 100644 --- a/src/Features/WetnessEffects.h +++ b/src/Features/WetnessEffects.h @@ -29,7 +29,7 @@ struct WetnessEffects : Feature float PuddleMinWetness = 0.75f; }; - struct PerPass + struct alignas(16) PerPass { float Wetness; DirectX::XMFLOAT3X4 DirectionalAmbientWS; @@ -51,4 +51,7 @@ struct WetnessEffects : Feature virtual void Load(json& o_json); virtual void Save(json& o_json); + + float CalculateWeatherTransitionPercentage(RE::TESWeather* weather, float skyCurrentWeatherPct, float beginFade); + float CalculateWetness(RE::TESWeather* weather, RE::Sky* sky); };