From 589518fb25cd60927dbdd29e7c32582cd50d82f0 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 26 Feb 2025 06:24:05 +0300 Subject: [PATCH] add fall.max_opacity, fall.opaque properties & update snow texture & weather mix test --- res/presets/weather/rain.json | 3 +- res/presets/weather/snow.json | 5 +- res/textures/misc/snow.png | Bin 716 -> 5810 bytes src/frontend/screens/LevelScreen.cpp | 2 +- src/graphics/render/PrecipitationRenderer.cpp | 4 ++ src/graphics/render/WorldRenderer.cpp | 52 ++++++++++++------ src/graphics/render/WorldRenderer.hpp | 2 +- src/presets/WeatherPreset.cpp | 6 ++ src/presets/WeatherPreset.hpp | 4 +- 9 files changed, 57 insertions(+), 21 deletions(-) diff --git a/res/presets/weather/rain.json b/res/presets/weather/rain.json index a193978c..56f35063 100644 --- a/res/presets/weather/rain.json +++ b/res/presets/weather/rain.json @@ -12,7 +12,8 @@ "particles:rain_splash_1", "particles:rain_splash_2" ] - } + }, + "min_opacity": 0.8 }, "fog_opacity": 0.8, "fog_dencity": 2.0, diff --git a/res/presets/weather/snow.json b/res/presets/weather/snow.json index 04b77462..7c7b9a15 100644 --- a/res/presets/weather/snow.json +++ b/res/presets/weather/snow.json @@ -3,7 +3,10 @@ "vspeed": 0.75, "hspeed": 0.5, "texture": "misc/snow", - "scale": 0.35 + "scale": 0.35, + "opaque": true, + "min_opacity": 0.8, + "max_opacity": 2.0 }, "fog_opacity": 0.8, "fog_dencity": 2.5, diff --git a/res/textures/misc/snow.png b/res/textures/misc/snow.png index a687e84151979ee002104ef505420468b410f90b..107eacb419cdd62f04f6e4cb7d73711e8553f039 100644 GIT binary patch literal 5810 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 literal 716 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7xzrV4Cdd;uumf=k48xUbh2e+CI*m zu`Q!8r|03{_}g~9hGuG^w~qaJF8J3dW=-y`XLFwajBRMy$G@agCD)!~t?hTl7khXZ z&M`bd5chZGSuKk$F zctDaN#*|U!vrXh?Ev6gm9vA+Z((~Z&DvpG09xLA~&r-AeXB{f&@a)I$m1+!ck0V=# zu$JdRWXWoew?gICHyP#$9zTyH199KFUkrJV?bcmZ{UlW{ewF>fkHf3@9S*~lxo!G+ z@%W$Y%JZsH2RyuF?2Q>Lm>WO@L-f(@1`I3i|NS1ZY<3Dm!2DUWmxsTSa8OkG<&k;E z`|KY(Rc4JNHy-c5q1o_a+r(Ru6V0tma+Wj5?2ntrgcL4tn_yyjn;32W+&Xgf`Og0> zR+~<;J@~QQ@Fqiv6f~&JB@WDA*WI7{diusLUZCXH&mxF0gs|E<7l4ANGXAmr3<~$1m^dHMhH8P51^?WpD*0{0oaXKPC7PD`7yRHAe z&+F>VFYfN@U+p?`KetKB7lteu`_+Yi&IB{e0mTmy#GNNh5|0zv-{u7|u6b;imN`c~ zZp&;>)(sxhUz*j~xfZ-jUN|F!;b!TtM?cg}b~2Pif!*+*SHUcH$We;WT(4ggargQu&X%Q~loCIFUQDPsTt diff --git a/src/frontend/screens/LevelScreen.cpp b/src/frontend/screens/LevelScreen.cpp index 62fc747d..5926cdf2 100644 --- a/src/frontend/screens/LevelScreen.cpp +++ b/src/frontend/screens/LevelScreen.cpp @@ -210,7 +210,7 @@ void LevelScreen::update(float delta) { hud->update(hudVisible); decorator->update( - hud->isPause() ? 0.0f : delta, *camera, worldRenderer->weather + hud->isPause() ? 0.0f : delta, *camera, worldRenderer->weatherInstances.at(0) ); } diff --git a/src/graphics/render/PrecipitationRenderer.cpp b/src/graphics/render/PrecipitationRenderer.cpp index beef0ed1..2b626921 100644 --- a/src/graphics/render/PrecipitationRenderer.cpp +++ b/src/graphics/render/PrecipitationRenderer.cpp @@ -127,7 +127,11 @@ void PrecipitationRenderer::render( {{0, 0, 1}, {1, 0, 0}}, }; + bool cutBack = glm::dot(camera.up, glm::vec3(0, 1, 0)) > 0.35f * camera.getFov(); for (const auto& face : faces) { + if (glm::dot(camera.right, face.right) < 0.0f && cutBack) { + continue; + } for (int lx = -radius; lx <= radius; lx++) { for (int lz = depth; lz > 0; lz--) { // Position calculations diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 06952ad9..4df63e2f 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -102,8 +102,15 @@ WorldRenderer::WorldRenderer( assets->require("skybox_gen") ); - weather = {}; + 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; @@ -122,9 +129,18 @@ void WorldRenderer::setupWorldShader( shader.uniform1f("u_gamma", settings.graphics.gamma.get()); shader.uniform1f("u_fogFactor", fogFactor); shader.uniform1f("u_fogCurve", settings.graphics.fogCurve.get()); - shader.uniform1f("u_weatherFogOpacity", weather.fogOpacity * weather.intensity); - shader.uniform1f("u_weatherFogDencity", weather.fogDencity); - shader.uniform1f("u_weatherFogCurve", weather.fogCurve); + + 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_dayTime", level.getWorld()->getInfo().daytime); shader.uniform2f("u_lightDir", skybox->getLightDir()); shader.uniform3f("u_cameraPos", camera.position); @@ -200,13 +216,16 @@ void WorldRenderer::renderLevel( } setupWorldShader(entityShader, camera, settings, fogFactor); - entityShader.uniform1i("u_alphaClip", false); - float zero = weather.fall.minOpacity; - entityShader.uniform1f("u_opacity", (weather.intensity * (1.0f - zero)) + zero); - if (weather.intensity > 1.e-3f && !weather.fall.texture.empty()) { - precipitation->render(camera, pause ? 0.0f : delta, weather); + + 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); + } } - //weather.intensity = -glm::cos(timer * 0.2f) * 0.5f + 0.5f; skybox->unbind(); } @@ -336,11 +355,12 @@ void WorldRenderer::draw( const auto& settings = engine.getSettings(); const auto& worldInfo = world->getInfo(); - - float mie = 1.0f + glm::max( - worldInfo.fog, - weather.clouds * glm::sqrt(weather.intensity) * 0.5f - ) * 2.0f; + float clouds = 0.0f; + for (const auto& weather : weatherInstances) { + clouds += weather.clouds * glm::sqrt(weather.intensity); + } + clouds = glm::max(worldInfo.fog, clouds); + float mie = 1.0f + glm::max(worldInfo.fog, clouds * 0.5f) * 2.0f; skybox->refresh(pctx, worldInfo.daytime, mie, 4); @@ -354,7 +374,7 @@ void WorldRenderer::draw( Window::clearDepth(); // Drawing background sky plane - skybox->draw(pctx, camera, assets, worldInfo.daytime, mie); + skybox->draw(pctx, camera, assets, worldInfo.daytime, clouds); /* Actually world render with depth buffer on */ { DrawContext ctx = wctx.sub(); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 4ac9299c..78d81a15 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -75,7 +75,7 @@ public: std::unique_ptr particles; std::unique_ptr blockWraps; std::unique_ptr precipitation; - WeatherPreset weather; + std::vector weatherInstances; static bool showChunkBorders; static bool showEntitiesDebug; diff --git a/src/presets/WeatherPreset.cpp b/src/presets/WeatherPreset.cpp index 6a55c7ec..d681878a 100644 --- a/src/presets/WeatherPreset.cpp +++ b/src/presets/WeatherPreset.cpp @@ -11,6 +11,9 @@ dv::value WeatherPreset::serialize() const { froot["hspeed"] = fall.hspeed; froot["scale"] = fall.scale; froot["noise"] = fall.noise; + froot["min_opacity"] = fall.minOpacity; + froot["max_opacity"] = fall.maxOpacity; + froot["opaque"] = fall.opaque; if (fall.splash) { froot["splash"] = fall.splash->serialize(); } @@ -32,6 +35,9 @@ void WeatherPreset::deserialize(const dv::value& src) { froot.at("hspeed").get(fall.hspeed); froot.at("scale").get(fall.scale); froot.at("noise").get(fall.noise); + froot.at("min_opacity").get(fall.minOpacity); + froot.at("max_opacity").get(fall.maxOpacity); + froot.at("opaque").get(fall.opaque); if (froot.has("splash")) { const auto& sroot = froot["splash"]; diff --git a/src/presets/WeatherPreset.hpp b/src/presets/WeatherPreset.hpp index 8b449e90..a9a78f9c 100644 --- a/src/presets/WeatherPreset.hpp +++ b/src/presets/WeatherPreset.hpp @@ -20,7 +20,9 @@ struct WeatherPreset : Serializable { float scale = 0.1f; /// @brief Fall opacity interpreted as zero. /// @example if 0.8 then opacity range is 0.8-1.0 for 0.0-1.0 intensity - float minOpacity = 0.8f; + float minOpacity = 0.0f; + float maxOpacity = 1.0f; + bool opaque = false; /// @brief Fall splash std::optional splash; } fall {};