diff --git a/res/presets/weather/snow.json b/res/presets/weather/snow.json index 7c7b9a15..da80a856 100644 --- a/res/presets/weather/snow.json +++ b/res/presets/weather/snow.json @@ -10,5 +10,6 @@ }, "fog_opacity": 0.8, "fog_dencity": 2.5, + "fog_curve": 0.5, "clouds": 0.5 } diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 5926cdf2..3fbe9082 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -210,7 +210,10 @@ void LevelScreen::update(float delta) { hud->update(hudVisible); decorator->update( - hud->isPause() ? 0.0f : delta, *camera, worldRenderer->weatherInstances.at(0) + hud->isPause() ? 0.0f : delta, + *camera, + worldRenderer->weather.a, + worldRenderer->weather.b ); } diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index baf174c1..e1d1704b 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -173,7 +173,10 @@ void Decorator::update( } void Decorator::update( - float delta, const Camera& camera, const WeatherPreset& weather + float delta, + const Camera& camera, + const WeatherPreset& weatherA, + const WeatherPreset& weatherB ) { glm::ivec3 pos = camera.position; for (int i = 0; i < ITERATIONS; i++) { @@ -181,7 +184,12 @@ void Decorator::update( } int randIters = std::min(50'000, static_cast(delta * 24'000)); for (int i = 0; i < randIters; i++) { - updateRandom(delta, pos, weather); + if (weatherA.intensity > 1.e-3f) { + updateRandom(delta, pos, weatherA); + } + if (weatherB.intensity > 1.e-3f) { + updateRandom(delta, pos, weatherB); + } } const auto& chunks = *player.chunks; const auto& indices = *level.content.getIndices(); diff --git a/src/graphics/render/Decorator.hpp b/src/graphics/render/Decorator.hpp index acc87d1c..b29e7e5e 100644 --- a/src/graphics/render/Decorator.hpp +++ b/src/graphics/render/Decorator.hpp @@ -53,5 +53,10 @@ public: Player& player ); - void update(float delta, const Camera& camera, const WeatherPreset& weather); + void update( + float delta, + const Camera& camera, + const WeatherPreset& weatherA, + const WeatherPreset& weatherB + ); }; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 4df63e2f..9fd1536b 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -101,16 +101,6 @@ WorldRenderer::WorldRenderer( settings.graphics.skyboxResolution.get(), assets->require("skybox_gen") ); - - WeatherPreset weather = {}; - weather.deserialize(io::read_json("res:presets/weather/rain.json")); - weather.intensity = 0.5f; - weatherInstances.push_back(std::move(weather)); - - weather = {}; - weather.deserialize(io::read_json("res:presets/weather/snow.json")); - weather.intensity = 0.5f; - weatherInstances.push_back(std::move(weather)); } WorldRenderer::~WorldRenderer() = default; @@ -129,18 +119,9 @@ void WorldRenderer::setupWorldShader( shader.uniform1f("u_gamma", settings.graphics.gamma.get()); shader.uniform1f("u_fogFactor", fogFactor); shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get()); - - float fog_opacity = 0.0f; - float fog_dencity = 0.0f; - float fog_curve = 0.0f; - for (const auto& weather : weatherInstances) { - fog_opacity += weather.fogOpacity * weather.intensity; - fog_dencity += weather.fogDencity * weather.intensity; - fog_curve += weather.fogCurve * weather.intensity; - } - shader.uniform1f("u_weatherFogOpacity", fog_opacity); - shader.uniform1f("u_weatherFogDencity", fog_dencity); - shader.uniform1f("u_weatherFogCurve", fog_curve); + shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity()); + shader.uniform1f("u_weatherFogDencity", weather.fogDencity()); + shader.uniform1f("u_weatherFogCurve", weather.fogCurve()); shader.uniform1f("u_dayTime", level.getWorld()->getInfo().daytime); shader.uniform2f("u_lightDir", skybox->getLightDir()); shader.uniform3f("u_cameraPos", camera.position); @@ -171,6 +152,24 @@ void WorldRenderer::renderLevel( bool pause, bool hudVisible ) { + weather.update(delta); + + if (timer > 1.0f && weather.b.fall.texture.empty() && timer < 2.0f) { + weather.b.deserialize(io::read_json("res:presets/weather/snow.json")); + weather.t = 0.0f; + weather.speed = 0.5f; + weather.update(delta); + } + + if (timer > 15.0f && weather.a.fall.texture.empty()) { + std::swap(weather.a, weather.b); + weather.b = {}; + weather.b.deserialize(io::read_json("res:presets/weather/fog.json")); + weather.t = 0.0f; + weather.speed = 0.1f; + weather.update(delta); + } + texts->render(ctx, camera, settings, hudVisible, false); bool culling = engine.getSettings().graphics.frustumCulling.get(); @@ -217,13 +216,15 @@ void WorldRenderer::renderLevel( setupWorldShader(entityShader, camera, settings, fogFactor); + std::array weatherInstances {&weather.a, &weather.b}; for (const auto& weather : weatherInstances) { - float zero = weather.fall.minOpacity; - float one = weather.fall.maxOpacity; - entityShader.uniform1i("u_alphaClip", weather.fall.opaque); - entityShader.uniform1f("u_opacity", (weather.intensity * (one - zero)) + zero); - if (weather.intensity > 1.e-3f && !weather.fall.texture.empty()) { - precipitation->render(camera, pause ? 0.0f : delta, weather); + float zero = weather->fall.minOpacity; + float one = weather->fall.maxOpacity; + float t = (weather->intensity * (one - zero)) + zero; + entityShader.uniform1i("u_alphaClip", weather->fall.opaque); + entityShader.uniform1f("u_opacity", weather->fall.opaque ? t * t : t); + if (weather->intensity > 1.e-3f && !weather->fall.texture.empty()) { + precipitation->render(camera, pause ? 0.0f : delta, *weather); } } @@ -355,10 +356,8 @@ void WorldRenderer::draw( const auto& settings = engine.getSettings(); const auto& worldInfo = world->getInfo(); - float clouds = 0.0f; - for (const auto& weather : weatherInstances) { - clouds += weather.clouds * glm::sqrt(weather.intensity); - } + float clouds = weather.b.clouds * glm::sqrt(weather.t) + + weather.a.clouds * glm::sqrt(1.0f - weather.t); clouds = glm::max(worldInfo.fog, clouds); float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f; diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 78d81a15..cb0b902c 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -34,6 +34,32 @@ class ModelBatch; class Assets; struct EngineSettings; +struct Weather { + WeatherPreset a {}; + WeatherPreset b {}; + float t = 1.0f; + float speed = 0.0f; + + void update(float delta) { + t += delta * speed; + t = std::min(t, 1.0f); + b.intensity = t; + a.intensity = 1.0f - t; + } + + float fogOpacity() const { + return b.fogOpacity * t + a.fogOpacity * (1.0f - t); + } + + float fogDencity() const { + return b.fogDencity * t + a.fogDencity * (1.0f - t); + } + + float fogCurve() const { + return b.fogCurve * t + a.fogCurve * (1.0f - t); + } +}; + class WorldRenderer { Engine& engine; const Level& level; @@ -75,7 +101,7 @@ public: std::unique_ptr particles; std::unique_ptr blockWraps; std::unique_ptr precipitation; - std::vector weatherInstances; + Weather weather {}; static bool showChunkBorders; static bool showEntitiesDebug; diff --git a/src/presets/WeatherPreset.hpp b/src/presets/WeatherPreset.hpp index a9a78f9c..69daf48e 100644 --- a/src/presets/WeatherPreset.hpp +++ b/src/presets/WeatherPreset.hpp @@ -28,15 +28,15 @@ struct WeatherPreset : Serializable { } fall {}; /// @brief Max weather fog opacity - float fogOpacity = 0.8f; + float fogOpacity = 0.0f; /// @brief Weather fog depth multiplier - float fogDencity = 2.0f; + float fogDencity = 1.0f; /// @brief Weather fog curve - float fogCurve = 0.5f; + float fogCurve = 1.0f; - float clouds = 0.5f; + float clouds = 0.0f; /// @brief Weather effects intensity float intensity = 1.0f;