From 7abb1a88c785bea7ba72d23352954233724ba5c0 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sun, 3 Nov 2024 02:23:37 +0300 Subject: [PATCH] add particles lighting --- src/graphics/render/Emitter.cpp | 5 +++- src/graphics/render/Emitter.hpp | 2 ++ src/graphics/render/MainBatch.cpp | 18 ++++++++++++++ src/graphics/render/MainBatch.hpp | 5 ++++ src/graphics/render/ModelBatch.cpp | 12 +-------- src/graphics/render/ParticlesRenderer.cpp | 30 +++++++++++++++++------ src/graphics/render/ParticlesRenderer.hpp | 8 +++++- src/graphics/render/WorldRenderer.cpp | 4 ++- src/voxels/Chunks.cpp | 4 +-- src/voxels/Chunks.hpp | 4 +-- 10 files changed, 66 insertions(+), 26 deletions(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index ae2cdc48..fd3ac978 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -39,11 +39,14 @@ void Emitter::update(float delta, std::vector& particles) { // spawn particle Particle particle = prototype; particle.emitter = this; + particle.random = rand(); particle.position = position; particle.velocity += glm::ballRand(1.0f) * explosion; particles.push_back(std::move(particle)); timer -= spawnInterval; - count--; + if (count > 0) { + count--; + } } } diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index 9f6940a4..2582e969 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -14,6 +14,7 @@ struct Particle { /// @brief Pointer used to access common behaviour. /// Emitter must be utilized after all related particles despawn. Emitter* emitter; + int random; /// @brief Global position glm::vec3 position; /// @brief Linear velocity @@ -28,6 +29,7 @@ class Texture; struct ParticleBehaviour { bool collision = true; + bool lighting = true; glm::vec3 gravity {0.0f, -16.0f, 0.0f}; }; diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index 786bd39c..c07a798a 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -3,6 +3,8 @@ #include "graphics/core/Texture.hpp" #include "graphics/core/Mesh.hpp" #include "graphics/core/ImageData.hpp" +#include "voxels/Chunks.hpp" +#include "voxels/Chunk.hpp" static const vattr attrs[] = { {3}, {2}, {3}, {1}, {0} @@ -62,3 +64,19 @@ void MainBatch::prepare(int vertices) { flush(); } } + +glm::vec4 MainBatch::sampleLight( + const glm::vec3& pos, const Chunks& chunks, bool backlight +) { + light_t light = chunks.getLight( + std::floor(pos.x), + std::floor(std::min(CHUNK_H-1.0f, pos.y)), + std::floor(pos.z)); + light_t minIntensity = backlight ? 1 : 0; + return glm::vec4( + glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f, + glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f, + glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f, + glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f + ); +} diff --git a/src/graphics/render/MainBatch.hpp b/src/graphics/render/MainBatch.hpp index 4af077ed..bb25e83b 100644 --- a/src/graphics/render/MainBatch.hpp +++ b/src/graphics/render/MainBatch.hpp @@ -9,6 +9,7 @@ class Mesh; class Texture; +class Chunks; class MainBatch { std::unique_ptr const buffer; @@ -36,6 +37,10 @@ public: void setTexture(const Texture* texture, const UVRegion& region); void flush(); + static glm::vec4 sampleLight( + const glm::vec3& pos, const Chunks& chunks, bool backlight + ); + inline void vertex( const glm::vec3& pos, const glm::vec2& uv, diff --git a/src/graphics/render/ModelBatch.cpp b/src/graphics/render/ModelBatch.cpp index 02615602..e222b349 100644 --- a/src/graphics/render/ModelBatch.cpp +++ b/src/graphics/render/ModelBatch.cpp @@ -65,17 +65,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix, bool backlight) { glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); gpos += lightsOffset; - light_t light = chunks->getLight( - std::floor(gpos.x), - std::floor(std::min(CHUNK_H-1.0f, gpos.y)), - std::floor(gpos.z)); - light_t minIntensity = backlight ? 1 : 0; - glm::vec4 lights( - glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f, - glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f, - glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f, - glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f - ); + glm::vec4 lights = MainBatch::sampleLight(gpos, *chunks, backlight); setTexture(mesh.texture, varTextures); size_t vcount = mesh.vertices.size(); const auto& vertexData = mesh.vertices.data(); diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 913deb23..4036dd90 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -8,16 +8,20 @@ #include "window/Camera.hpp" #include "world/Level.hpp" #include "voxels/Chunks.hpp" +#include "settings.hpp" size_t ParticlesRenderer::visibleParticles = 0; size_t ParticlesRenderer::aliveEmitters = 0; -ParticlesRenderer::ParticlesRenderer(const Assets& assets, const Level& level) - : batch(std::make_unique(1024)), level(level) { - - auto region = util::get_texture_region(assets, "blocks:bazalt", ""); - emitters.push_back(std::make_unique(glm::vec3(0, 100, 0), Particle { - nullptr, glm::vec3(), glm::vec3(), 5.0f, region.region +ParticlesRenderer::ParticlesRenderer( + const Assets& assets, const Level& level, const GraphicsSettings* settings +) + : batch(std::make_unique(1024)), + level(level), + settings(settings) { + auto region = util::get_texture_region(assets, "blocks:grass_top", ""); + emitters.push_back(std::make_unique(glm::vec3(0, 80, 0), Particle { + nullptr, 0, glm::vec3(), glm::vec3(), 5.0f, region.region },region.texture, 0.002f, -1)); } @@ -42,6 +46,9 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { const auto& right = camera.right; const auto& up = camera.up; + const auto& chunks = *level.chunks; + bool backlight = settings->backlight.get(); + std::vector unusedTextures; for (auto& [texture, vec] : particles) { @@ -57,14 +64,21 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { while (iter != vec.end()) { auto& particle = *iter; - update_particle(particle, delta, *level.chunks); + update_particle(particle, delta, chunks); + glm::vec4 light(1, 1, 1, 0); + if (particle.emitter->behaviour.lighting) { + light = MainBatch::sampleLight( + particle.position, chunks, backlight + ); + light *= 0.7f + (particle.random % 300) * 0.001f; + } batch->quad( particle.position, right, up, glm::vec2(0.3f), - glm::vec4(1), + light, glm::vec3(1.0f), particle.region ); diff --git a/src/graphics/render/ParticlesRenderer.hpp b/src/graphics/render/ParticlesRenderer.hpp index 6d1bbb94..ca7906da 100644 --- a/src/graphics/render/ParticlesRenderer.hpp +++ b/src/graphics/render/ParticlesRenderer.hpp @@ -11,16 +11,22 @@ class Assets; class Camera; class MainBatch; class Level; +struct GraphicsSettings; class ParticlesRenderer { const Level& level; + const GraphicsSettings* settings; std::unordered_map> particles; std::vector> emitters; std::unique_ptr batch; void renderParticles(const Camera& camera, float delta); public: - ParticlesRenderer(const Assets& assets, const Level& level); + ParticlesRenderer( + const Assets& assets, + const Level& level, + const GraphicsSettings* settings + ); ~ParticlesRenderer(); void render(const Camera& camera, float delta); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index ef579d7c..730125ad 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -63,7 +63,9 @@ WorldRenderer::WorldRenderer( &engine->getSettings() )), particles(std::make_unique( - *engine->getAssets(), *frontend->getLevel() + *engine->getAssets(), + *frontend->getLevel(), + &engine->getSettings().graphics )) { renderer = std::make_unique( level, frontend->getContentGfxCache(), &engine->getSettings() diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 70c73140..a380aeda 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -112,7 +112,7 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) { return indices->blocks.get(v->id)->obstacle; //-V522 } -ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) { +ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) const { if (y < 0 || y >= CHUNK_H) { return 0; } @@ -132,7 +132,7 @@ ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) { return chunk->lightmap.get(lx, y, lz, channel); } -light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) { +light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) const { if (y < 0 || y >= CHUNK_H) { return 0; } diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index a1131f1b..98979423 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -60,8 +60,8 @@ public: return get(pos.x, pos.y, pos.z); } - light_t getLight(int32_t x, int32_t y, int32_t z); - ubyte getLight(int32_t x, int32_t y, int32_t z, int channel); + light_t getLight(int32_t x, int32_t y, int32_t z) const; + ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const; void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state); /// @brief Seek for the extended block origin position