#pragma once #include "hd2d/Scene.h" #include #include namespace hd2d { struct RenderSettings; // Everything time of day and weather change about the look, so it can be // blended. One look fully describes the lighting of a frame. struct WeatherLook { // Directional light: the sun by day, the moon at night (shadows follow it). float sunAzimuth = -0.6f, sunElevation = 0.66f; // radians, see Sun float sunIntensity = 0.0f; glm::vec3 sunColor{1.0f}; glm::vec3 zenith{0.5f}, horizon{0.5f}, ground{0.2f}; float ambient = 0.5f, fill = 0.35f; float night = 0.0f; // 0..1: star field + moon disc (Sky::night) float clouds = 0.0f; // 0..1: extra sky cloud cover (Sky::clouds) float daylight = 1.0f; // 0 night .. 1 day: scales weather presets (a storm at night is dark) glm::vec3 fogColor{0.5f}; float fogDensity = 0.0f, fogHeightFalloff = 0.1f, godRays = 0.0f, shaftStrength = 0.0f, cookieStrength = 0.0f; float shadowSoftness = 1.5f; float windStrength = 0.0f, windGustSpeed = 0.0f; float bloomStrength = 0.0f, saturation = 1.0f, exposure = 1.0f; glm::vec3 lift{0.0f}; // grading lift (shadow tint) glm::vec3 gain{1.0f}; // grading gain (highlight tint) float fireflyGlow = 1.0f; // ParticleSystem::fireflyGlow (raise at night) }; // Linear blend of every field (t = 0: a, t = 1: b). WeatherLook mixLooks(const WeatherLook& a, const WeatherLook& b, float t); // Blends the scene from its clear-weather look toward overcast, fog (mist) // and storm presets, and drives rain intensity, wetness, ground splashes, // lightning and the fading of ambient particles. // // The clear look is either captured from the current scene + settings while // the weather is fully clear (so manual tuning is kept), or supplied every // frame with setClearLook() (e.g. from a DayCycle). Presets are authored at // full daylight and darkened by the clear look's `daylight`. class Weather { public: Weather(); // Replaces the captured clear look (call every frame, e.g. with // DayCycle::look(hour)). Once called, the scene is no longer captured. void setClearLook(const WeatherLook& look); void setRain(float target) { targetRain_ = glm::clamp(target, 0.0f, 1.0f); } void setOvercast(float target) { targetOvercast_ = glm::clamp(target, 0.0f, 1.0f); } void setFog(float target) { targetFog_ = glm::clamp(target, 0.0f, 1.0f); } void setLightning(bool enabled) { lightning_ = enabled; } // occasional flashes while raining float targetRain() const { return targetRain_; } float targetOvercast() const { return targetOvercast_; } float targetFog() const { return targetFog_; } bool lightning() const { return lightning_; } float rain() const { return rain_; } float overcast() const { return overcast_; } float fog() const { return fog_; } // Jumps straight to every target (no transition), e.g. for screenshots. void snap(); void update(float dt, Scene& scene, RenderSettings& settings); // Presets at full daylight. Time-of-day fields (sun direction, night, // daylight, exposure, lift, gain, fill, fireflies) always come from the clear look. WeatherLook storm; // full rain intensity WeatherLook overcastLook; // grey sky, weak sun, soft shadows WeatherLook mist; // thick low fog (morning mist) float nightBrightness = 0.3f; // preset brightness at daylight = 0 float transitionSeconds = 5.0f; // fade time for every target float splashesPerSecond = 500.0f; float splashRadius = 12.0f; // around Scene::focusPoint float lightningInterval = 7.0f; // mean seconds between flashes at full rain // The look currently set on a scene + settings (e.g. a hand-tuned noon). static WeatherLook capture(const Scene& scene, const RenderSettings& settings); private: static void apply(const WeatherLook& look, Scene& scene, RenderSettings& settings); WeatherLook relative(const WeatherLook& preset, float hueKeep) const; bool clear() const; WeatherLook clear_; bool haveClear_ = false, externalClear_ = false, lightning_ = false; float rain_ = 0.0f, targetRain_ = 0.0f, wetness_ = 0.0f, splashAccum_ = 0.0f; float overcast_ = 0.0f, targetOvercast_ = 0.0f, fog_ = 0.0f, targetFog_ = 0.0f; float flash_ = 0.0f, flashAge_ = 1e3f, nextFlash_ = 3.0f; std::mt19937 rng_{99}; }; } // namespace hd2d