Skip to content

Commit

Permalink
fix: fix wetness calculation logic (#151)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
TheRiverwoodModder and TheRiverwoodModder authored Jan 10, 2024

Verified

This commit was signed with the committer’s verified signature.
amimart Arnaud Mimart
1 parent 46ea093 commit 7221579
Showing 5 changed files with 57 additions and 39 deletions.
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 0-9-2
Version = 0-9-3
Original file line number Diff line number Diff line change
@@ -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> perPassWetnessEffects : register(t22);
4 changes: 2 additions & 2 deletions package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
@@ -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;

81 changes: 49 additions & 32 deletions src/Features/WetnessEffects.cpp
Original file line number Diff line number Diff line change
@@ -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));
5 changes: 4 additions & 1 deletion src/Features/WetnessEffects.h
Original file line number Diff line number Diff line change
@@ -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);
};

0 comments on commit 7221579

Please sign in to comment.