Skip to content

Commit ea92f35

Browse files
committed
Fix weather interpolation resync precision for fog transitions.
Compute interpolation in double and step one float ULP down when needed to preserve the engine v0 >= InterpolationValue invariant and prevent precision-induced 2dfx light flicker.
1 parent 884bb1e commit ea92f35

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

Client/game_sa/CWeatherSA.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,16 @@ void CWeatherSA::ResyncInterpolationWithGameClock(unsigned char primary, unsigne
3737
else
3838
{
3939
// Match the value CWeather::Update derives at 0x72B897:
40-
// v0 = (seconds / 60 + minutes) / 60
41-
// Snapping to minutes only would drop seconds and make CTimeCycle::CalcColoursForPoint
42-
// step m_CurrentColours per game-minute, which surfaces as flicker on vehicle coronas
43-
// (m_fSpriteBrightness) and shadows (m_wShadowStrength) when the clock runs fast.
40+
// v0 = ((double)seconds * 0.016666668 + (double)minutes) * 0.016666668
41+
// Keep this <= engine v0 to avoid triggering the wrap branch on precision mismatches.
4442
const auto ucMinute = *reinterpret_cast<unsigned char*>(VAR_TimeMinutes);
4543
const auto ucSecond = *reinterpret_cast<unsigned char*>(VAR_TimeSeconds);
46-
const float fInterp = std::min(1.f, static_cast<float>(ucMinute) / 60.f + static_cast<float>(ucSecond) / 3600.f);
44+
const double dInterp = std::min(1.0, (static_cast<double>(ucSecond) * 0.016666668 + static_cast<double>(ucMinute)) * 0.016666668);
45+
float fInterp = static_cast<float>(dInterp);
46+
47+
if (static_cast<double>(fInterp) > dInterp)
48+
fInterp = std::nextafterf(fInterp, 0.0f);
49+
4750
MemPutFast<float>(VAR_InterpolationValue, fInterp);
4851
}
4952
}

0 commit comments

Comments
 (0)