This commit is contained in:
Gabrieal Jimmy
2026-10-02 12:42:00 -05:00
commit 2c99305fb0
145 changed files with 6525 additions and 0 deletions

135
engine/src/Weather.cpp Normal file
View File

@@ -0,0 +1,135 @@
#include "hd2d/Weather.h"
#include "hd2d/Renderer.h"
#include <algorithm>
#include <cmath>
namespace hd2d {
Weather::Weather() {
// Heavy overcast rain: weak grey sun, flat cool ambient, thick low fog,
// almost no god rays, strong gusty wind.
storm.sunIntensity = 0.7f;
storm.sunColor = {0.78f, 0.82f, 0.9f};
storm.zenith = {0.30f, 0.34f, 0.40f};
storm.horizon = {0.42f, 0.45f, 0.50f};
storm.ground = {0.13f, 0.15f, 0.13f};
storm.ambient = 0.62f;
storm.fogColor = {0.30f, 0.33f, 0.38f};
storm.fogDensity = 0.03f;
storm.fogHeightFalloff = 0.22f;
storm.godRays = 0.6f;
storm.shaftStrength = 0.2f;
storm.cookieStrength = 0.0f;
storm.windStrength = 0.2f;
storm.windGustSpeed = 3.0f;
storm.bloomStrength = 0.06f;
storm.saturation = 0.82f;
}
WeatherLook Weather::capture(const Scene& s, const RenderSettings& r) {
WeatherLook l;
l.sunIntensity = s.sun.intensity;
l.sunColor = s.sun.color;
l.zenith = s.sky.zenith;
l.horizon = s.sky.horizon;
l.ground = s.sky.ground;
l.ambient = s.sky.ambient;
l.fogColor = r.fogColor;
l.fogDensity = r.fogDensity;
l.fogHeightFalloff = r.fogHeightFalloff;
l.godRays = r.godRayIntensity;
l.shaftStrength = r.shaftStrength;
l.cookieStrength = r.cookieStrength;
l.windStrength = r.windStrength;
l.windGustSpeed = r.windGustSpeed;
l.bloomStrength = r.bloomStrength;
l.saturation = r.saturation;
return l;
}
void Weather::apply(const WeatherLook& l, Scene& s, RenderSettings& r) {
s.sun.intensity = l.sunIntensity;
s.sun.color = l.sunColor;
s.sky.zenith = l.zenith;
s.sky.horizon = l.horizon;
s.sky.ground = l.ground;
s.sky.ambient = l.ambient;
r.fogColor = l.fogColor;
r.fogDensity = l.fogDensity;
r.fogHeightFalloff = l.fogHeightFalloff;
r.godRayIntensity = l.godRays;
r.shaftStrength = l.shaftStrength;
r.cookieStrength = l.cookieStrength;
r.windStrength = l.windStrength;
r.windGustSpeed = l.windGustSpeed;
r.bloomStrength = l.bloomStrength;
r.saturation = l.saturation;
}
static WeatherLook mixLook(const WeatherLook& a, const WeatherLook& b, float t) {
WeatherLook o;
auto m = [t](auto x, auto y) { return x + (y - x) * t; };
o.sunIntensity = m(a.sunIntensity, b.sunIntensity);
o.sunColor = m(a.sunColor, b.sunColor);
o.zenith = m(a.zenith, b.zenith);
o.horizon = m(a.horizon, b.horizon);
o.ground = m(a.ground, b.ground);
o.ambient = m(a.ambient, b.ambient);
o.fogColor = m(a.fogColor, b.fogColor);
o.fogDensity = m(a.fogDensity, b.fogDensity);
o.fogHeightFalloff = m(a.fogHeightFalloff, b.fogHeightFalloff);
o.godRays = m(a.godRays, b.godRays);
o.shaftStrength = m(a.shaftStrength, b.shaftStrength);
o.cookieStrength = m(a.cookieStrength, b.cookieStrength);
o.windStrength = m(a.windStrength, b.windStrength);
o.windGustSpeed = m(a.windGustSpeed, b.windGustSpeed);
o.bloomStrength = m(a.bloomStrength, b.bloomStrength);
o.saturation = m(a.saturation, b.saturation);
return o;
}
void Weather::update(float dt, Scene& scene, RenderSettings& settings) {
// While fully clear, keep tracking the live look so UI tweaks survive.
if (rain_ <= 0.0f && targetRain_ <= 0.0f) {
clear_ = capture(scene, settings);
haveClear_ = true;
} else if (!haveClear_) {
clear_ = capture(scene, settings);
haveClear_ = true;
}
float step = dt / std::max(transitionSeconds, 1e-3f);
rain_ = rain_ < targetRain_ ? std::min(targetRain_, rain_ + step) : std::max(targetRain_, rain_ - step);
// Surfaces soak quickly and dry slowly.
float wetRate = wetness_ < rain_ ? step * 1.5f : step * 0.3f;
wetness_ = wetness_ < rain_ ? std::min(rain_, wetness_ + wetRate) : std::max(rain_, wetness_ - wetRate);
float k = rain_ * rain_ * (3.0f - 2.0f * rain_); // smoothstep
if (rain_ > 0.0f || targetRain_ > 0.0f) apply(mixLook(clear_, storm, k), scene, settings);
scene.rain = rain_;
scene.wetness = wetness_;
if (scene.particles) {
ParticleSystem& ps = *scene.particles;
ps.ambientFade = 1.0f - k;
glm::vec2 wd = glm::length(settings.windDirection) > 1e-4f ? glm::normalize(settings.windDirection)
: glm::vec2(1, 0);
ps.wind = glm::vec3(wd.x, 0.0f, wd.y) * settings.windStrength * 10.0f;
// Ground splashes around the focus point (water gets ripples instead).
splashAccum_ += splashesPerSecond * rain_ * dt;
std::uniform_real_distribution<float> u(-1.0f, 1.0f);
glm::vec3 color = (scene.sky.horizon * 0.8f + glm::vec3(0.15f)) * scene.sky.ambient * 1.6f;
while (splashAccum_ >= 1.0f) {
splashAccum_ -= 1.0f;
glm::vec2 p = glm::vec2(scene.focusPoint.x, scene.focusPoint.z) + glm::vec2(u(rng_), u(rng_)) * splashRadius;
if (!scene.terrain) continue;
float y = scene.terrain->heightAt(p.x, p.y);
if (scene.water && y < scene.water->level()) continue;
ps.burst({p.x, y + 0.02f, p.y}, 2, color, 0.9f, 0.022f, 0.28f);
}
}
}
} // namespace hd2d