diff --git a/res/preload.json b/res/preload.json index fb202291..866ee9bf 100644 --- a/res/preload.json +++ b/res/preload.json @@ -19,7 +19,9 @@ "gui/cross", "gui/refresh", "gui/folder_icon", - "gui/settings_icon" + "gui/settings_icon", + "misc/rain", + "misc/snow" ], "fonts": [ { diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 143b3eaa..0c2ec520 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -17,7 +17,7 @@ void main() { float depth = (a_distance/256.0); float alpha = a_color.a * tex_color.a; // anyway it's any alpha-test alternative required - if (alpha < (u_alphaClip ? 0.5f : 0.2f)) + if (alpha < (u_alphaClip ? 0.5f : 0.15f)) discard; f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve))); diff --git a/res/textures/misc/rain.png b/res/textures/misc/rain.png new file mode 100644 index 00000000..aeba9017 Binary files /dev/null and b/res/textures/misc/rain.png differ diff --git a/res/textures/misc/snow.png b/res/textures/misc/snow.png new file mode 100644 index 00000000..810806ff Binary files /dev/null and b/res/textures/misc/snow.png differ diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index f61b67fd..1be7272a 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -6,10 +6,10 @@ #include "assets/assets_util.hpp" #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" -#include "graphics/render/MainBatch.hpp" #include "window/Camera.hpp" #include "world/Level.hpp" #include "voxels/Chunks.hpp" +#include "MainBatch.hpp" #include "settings.hpp" size_t ParticlesRenderer::visibleParticles = 0; @@ -179,24 +179,6 @@ void ParticlesRenderer::render(const Camera& camera, float delta) { } } -void ParticlesRenderer::gc() { - std::set usedEmitters; - for (const auto& [_, vec] : particles) { - for (const auto& particle : vec) { - usedEmitters.insert(particle.emitter); - } - } - auto iter = emitters.begin(); - while (iter != emitters.end()) { - auto emitter = iter->second.get(); - if (usedEmitters.find(emitter) == usedEmitters.end()) { - iter = emitters.erase(iter); - } else { - iter++; - } - } -} - Emitter* ParticlesRenderer::getEmitter(u64id_t id) const { const auto& found = emitters.find(id); if (found == emitters.end()) { diff --git a/src/graphics/render/ParticlesRenderer.hpp b/src/graphics/render/ParticlesRenderer.hpp index 3fe692e5..a01f1018 100644 --- a/src/graphics/render/ParticlesRenderer.hpp +++ b/src/graphics/render/ParticlesRenderer.hpp @@ -40,12 +40,6 @@ public: u64id_t add(std::unique_ptr emitter); - /// @brief Perform garbage collection (remove extra dead emitters). - /// @note Emitters are deleting without GC when there's no particles with same - /// texture left. - /// @note Currently unused - void gc(); - /// @brief Get emitter by UID /// @return Emitter or nullptr Emitter* getEmitter(u64id_t id) const; diff --git a/src/graphics/render/PrecipitationRenderer.cpp b/src/graphics/render/PrecipitationRenderer.cpp new file mode 100644 index 00000000..7673393d --- /dev/null +++ b/src/graphics/render/PrecipitationRenderer.cpp @@ -0,0 +1,155 @@ +#include "PrecipitationRenderer.hpp" + +#include "assets/Assets.hpp" +#include "assets/assets_util.hpp" +#include "graphics/core/Shader.hpp" +#include "graphics/core/Texture.hpp" +#include "window/Camera.hpp" +#include "world/Level.hpp" +#include "voxels/Chunks.hpp" +#include "MainBatch.hpp" +#include "settings.hpp" + +PrecipitationRenderer::PrecipitationRenderer( + const Assets& assets, + const Level& level, + const Chunks& chunks, + const GraphicsSettings* settings +) + : batch(std::make_unique(4096)), + level(level), + chunks(chunks), + assets(assets), + settings(settings) { +} + +PrecipitationRenderer::~PrecipitationRenderer() = default; + +int PrecipitationRenderer::getHeightAt(int x, int z) { + int y = CHUNK_H-1; + while (y > 0) { + if (auto voxel = chunks.get({x, y, z})) { + if (voxel->id == 0) { + y--; + continue; + } + } + break; + } + return y; +} + + +void PrecipitationRenderer::render(const Camera& camera, float delta) { + timer += delta * 1.0f; + batch->begin(); + + int x = glm::floor(camera.position.x); + int y = glm::floor(camera.position.y); + int z = glm::floor(camera.position.z); + + auto& texture = assets.require("misc/rain"); + texture.setMipMapping(false); + batch->setTexture(&texture, {}); + + const auto& front = camera.front; + glm::vec2 size {1, 40}; + glm::vec4 light(1, 1, 1, 0); + + float horizontal = 0.0f; + + int radius = 5; + int depth = 8; + float scale = 0.1f; + int quads = 0; + float k = 21.41149; + for (int lx = -radius; lx <= radius; lx++) { + for (int lz = -depth; lz < 0; lz++) { + glm::vec3 pos { + x + lx + 0.5f, + glm::max(y - 3, getHeightAt(x + lx, z + lz)) + 21, + z + lz + 0.5f}; + batch->quad( + pos, + {1, 0, 0}, + {0, 1, 0}, + size, + light, + glm::vec3(1.0f), + UVRegion( + (lx + x) * scale + timer * horizontal, + timer + (z + lz) * k, + (lx + x + 1) * scale + timer * horizontal, + timer + 40 * scale + (z + lz) * k + ) + ); + } + } + for (int lx = -radius; lx <= radius; lx++) { + for (int lz = depth; lz > 0; lz--) { + glm::vec3 pos { + x + lx + 0.5f, + glm::max(y - 3, getHeightAt(x + lx, z + lz)) + 21, + z + lz + 0.5f}; + batch->quad( + pos, + {-1, 0, 0}, + {0, 1, 0}, + size, + light, + glm::vec3(1.0f), + UVRegion( + (lx + x) * scale + timer * horizontal, + timer + (z + lz) * k, + (lx + x + 1) * scale + timer * horizontal, + timer + 40 * scale + (z + lz) * k + ) + ); + } + } + for (int lz = -radius; lz <= radius; lz++) { + for (int lx = -depth; lx < 0; lx++) { + glm::vec3 pos { + x + lx + 0.5f, + glm::max(y - 3, getHeightAt(x + lx, z + lz)) + 21, + z + lz + 0.5f}; + batch->quad( + pos, + {0, 0, -1}, + {0, 1, 0}, + size, + light, + glm::vec3(1.0f), + UVRegion( + (lz + z) * scale + timer * horizontal, + timer + (x + lx) * k, + (lz + z + 1) * scale + timer * horizontal, + timer + 40 * scale + (x + lx) * k + ) + ); + } + } + for (int lz = -radius; lz <= radius; lz++) { + for (int lx = depth; lx > 0; lx--) { + glm::vec3 pos { + x + lx + 0.5f, + glm::max(y - 3, getHeightAt(x + lx, z + lz)) + 21, + z + lz + 0.5f}; + batch->quad( + pos, + {0, 0, 1}, + {0, 1, 0}, + size, + light, + glm::vec3(1.0f), + UVRegion( + (lz + z) * scale + timer * horizontal, + timer + (x + lx) * k, + (lz + z + 1) * scale + timer * horizontal, + timer + 40 * scale + (x + lx) * k + ) + ); + } + } + batch->flush(); +} diff --git a/src/graphics/render/PrecipitationRenderer.hpp b/src/graphics/render/PrecipitationRenderer.hpp new file mode 100644 index 00000000..0a9a59ee --- /dev/null +++ b/src/graphics/render/PrecipitationRenderer.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "typedefs.hpp" + +class Level; +class Assets; +class Chunks; +class Camera; +class MainBatch; +struct GraphicsSettings; + +class PrecipitationRenderer { + std::unique_ptr batch; + const Level& level; + const Chunks& chunks; + const Assets& assets; + const GraphicsSettings* settings; + float timer = 0.0f; + + int getHeightAt(int x, int z); +public: + PrecipitationRenderer( + const Assets& assets, + const Level& level, + const Chunks& chunks, + const GraphicsSettings* settings + ); + + ~PrecipitationRenderer(); + + void render(const Camera& camera, float delta); +}; diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 4d36c286..54bf62e2 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -44,6 +44,7 @@ #include "graphics/core/Font.hpp" #include "BlockWrapsRenderer.hpp" #include "ParticlesRenderer.hpp" +#include "PrecipitationRenderer.hpp" #include "TextsRenderer.hpp" #include "ChunksRenderer.hpp" #include "GuidesRenderer.hpp" @@ -86,7 +87,10 @@ WorldRenderer::WorldRenderer( )), blockWraps( std::make_unique(assets, level, *player.chunks) - ) { + ), + precipitation(std::make_unique( + assets, level, *player.chunks, &engine.getSettings().graphics + )) { auto& settings = engine.getSettings(); level.events->listen( LevelEventType::CHUNK_HIDDEN, @@ -188,6 +192,10 @@ void WorldRenderer::renderLevel( scripting::on_frontend_render(); } + setupWorldShader(entityShader, camera, settings, fogFactor); + entityShader.uniform1i("u_alphaClip", false); + precipitation->render(camera, delta); + skybox->unbind(); } diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 569858d8..b1cb1fa9 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -18,6 +18,7 @@ class LineBatch; class ChunksRenderer; class ParticlesRenderer; class BlockWrapsRenderer; +class PrecipitationRenderer; class GuidesRenderer; class TextsRenderer; class Shader; @@ -71,6 +72,7 @@ public: std::unique_ptr texts; std::unique_ptr particles; std::unique_ptr blockWraps; + std::unique_ptr precipitation; static bool showChunkBorders; static bool showEntitiesDebug;