init
This commit is contained in:
135
engine/src/Weather.cpp
Normal file
135
engine/src/Weather.cpp
Normal 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
|
||||
Reference in New Issue
Block a user