From c6de7f62feec9dd02af81e3a97bb225459a01db7 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:04:48 +0300 Subject: [PATCH 01/11] add 'angle_spread' property --- src/graphics/render/Emitter.cpp | 7 ++++++- src/graphics/render/Emitter.hpp | 4 +++- src/graphics/render/ParticlesRenderer.cpp | 17 +++++++++++++++-- src/presets/ParticlesPreset.cpp | 2 ++ src/presets/ParticlesPreset.hpp | 2 ++ 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 82848a63c..09e1ddc8e 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -23,8 +23,9 @@ Emitter::Emitter( texture(texture), count(count), preset(std::move(preset)) { + random.setSeed(rand()); this->prototype.emitter = this; - timer = preset.spawnInterval; + timer = preset.spawnInterval * random.randFloat(); } const Texture* Emitter::getTexture() const { @@ -83,6 +84,10 @@ void Emitter::update( Particle particle = prototype; particle.emitter = this; particle.random = random.rand32(); + if (glm::abs(preset.angleSpread) >= 0.005f) { + particle.angle = + random.randFloat() * preset.angleSpread * glm::pi() * 2; + } glm::vec3 spawnOffset = generate_coord(preset.spawnShape); spawnOffset *= preset.spawnSpread; diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index c1d6c1683..0ad34053c 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -27,6 +27,8 @@ struct Particle { float lifetime; /// @brief UV region UVRegion region; + /// @brief Current rotation angle + float angle; }; class Texture; @@ -39,7 +41,7 @@ class Emitter { EmitterOrigin origin; /// @brief Particle prototype Particle prototype; - /// @brief Particle + /// @brief Particle texture const Texture* texture; /// @brief Number of particles should be spawned before emitter deactivation. /// -1 is infinite. diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 0e2292a50..71ec24c5b 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -91,10 +91,23 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { } float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * 0.001f * preset.sizeSpread; + + glm::vec3 localRight = right; + glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up; + float angle = particle.angle; + if (glm::abs(angle) >= 0.005f) { + glm::vec3 rotatedRight(glm::cos(angle), -glm::sin(angle), 0.0f); + glm::vec3 rotatedUp(glm::sin(angle), glm::cos(angle), 0.0f); + + localRight = right * rotatedRight.x + localUp * rotatedRight.y + + camera.front * rotatedRight.z; + localUp = right * rotatedUp.x + localUp * rotatedUp.y + + camera.front * rotatedUp.z; + } batch->quad( particle.position, - right, - preset.globalUpVector ? glm::vec3(0, 1, 0) : up, + localRight, + localUp, preset.size * scale, light, glm::vec3(1.0f), diff --git a/src/presets/ParticlesPreset.cpp b/src/presets/ParticlesPreset.cpp index 181dbeb50..272744423 100644 --- a/src/presets/ParticlesPreset.cpp +++ b/src/presets/ParticlesPreset.cpp @@ -43,6 +43,7 @@ dv::value ParticlesPreset::serialize() const { root["explosion"] = dv::to_value(explosion); root["size"] = dv::to_value(size); root["size_spread"] = sizeSpread; + root["angle_spread"] = angleSpread; root["spawn_spread"] = dv::to_value(size); root["spawn_shape"] = to_string(spawnShape); root["random_sub_uv"] = randomSubUV; @@ -58,6 +59,7 @@ void ParticlesPreset::deserialize(const dv::value& src) { src.at("spawn_interval").get(spawnInterval); src.at("lifetime").get(lifetime); src.at("lifetime_spread").get(lifetimeSpread); + src.at("angle_spread").get(angleSpread); src.at("random_sub_uv").get(randomSubUV); if (src.has("velocity")) { dv::get_vec(src["velocity"], velocity); diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index f8d5f2b4a..67c6c91b8 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -44,6 +44,8 @@ struct ParticlesPreset : public Serializable { glm::vec3 size {0.1f}; /// @brief Particles size spread float sizeSpread = 0.2f; + /// @brief Random initial angle spread + float angleSpread = 0.0f; /// @brief Spawn spread shape ParticleSpawnShape spawnShape = BALL; /// @brief Spawn spread From 6be640458d6b4ae46866b342ca0f26e561ead125 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:26:45 +0300 Subject: [PATCH 02/11] fix particles lighting --- src/graphics/render/ParticlesRenderer.cpp | 25 ++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 71ec24c5b..a68f56e25 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -82,15 +82,34 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { } update_particle(particle, delta, chunks); + float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * + 0.001f * preset.sizeSpread; + glm::vec4 light(1, 1, 1, 0); if (preset.lighting) { light = MainBatch::sampleLight( - particle.position, chunks, backlight + particle.position, + chunks, + backlight ); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + light = glm::max( + light, + MainBatch::sampleLight( + particle.position - preset.size * scale * + glm::vec3(x, y, z), + chunks, + backlight + ) + ); + } + } + } light *= 0.9f + (particle.random % 100) * 0.001f; } - float scale = 1.0f + ((particle.random ^ 2628172) % 1000) * - 0.001f * preset.sizeSpread; + glm::vec3 localRight = right; glm::vec3 localUp = preset.globalUpVector ? glm::vec3(0, 1, 0) : up; From 6ac088f7b9599dc0950dc4b3d208a13e8b5ae234 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:34:08 +0300 Subject: [PATCH 03/11] set default particles render distance to 32 --- src/graphics/render/ParticlesRenderer.cpp | 5 +++-- src/presets/ParticlesPreset.hpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index a68f56e25..6c3ed73c3 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -92,14 +92,15 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { chunks, backlight ); + auto size = glm::max(glm::vec3(0.5f), preset.size * scale); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { for (int z = -1; z <= 1; z++) { light = glm::max( light, MainBatch::sampleLight( - particle.position - preset.size * scale * - glm::vec3(x, y, z), + particle.position - + size * glm::vec3(x, y, z), chunks, backlight ) diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index 67c6c91b8..10b9f088b 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -27,7 +27,7 @@ struct ParticlesPreset : public Serializable { /// @brief Use global up vector instead of camera-dependent one bool globalUpVector = false; /// @brief Max distance of actually spawning particles. - float maxDistance = 16.0f; + float maxDistance = 32.0f; /// @brief Particles spawn interval float spawnInterval = 0.1f; /// @brief Particle life time From 7f95306c6525b91765c55ce8b1ada46d5dc77e2b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:48:07 +0300 Subject: [PATCH 04/11] add 'min_angular_vel', 'max_angular_vel' properties --- src/graphics/render/Emitter.cpp | 5 +++++ src/graphics/render/Emitter.hpp | 2 ++ src/graphics/render/ParticlesRenderer.cpp | 2 ++ src/presets/ParticlesPreset.cpp | 4 ++++ src/presets/ParticlesPreset.hpp | 4 ++++ 5 files changed, 17 insertions(+) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 09e1ddc8e..76b2f0185 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -88,6 +88,11 @@ void Emitter::update( particle.angle = random.randFloat() * preset.angleSpread * glm::pi() * 2; } + particle.angularVelocity = + (preset.minAngularVelocity + + random.randFloat() * + (preset.maxAngularVelocity - preset.minAngularVelocity)) * + ((random.rand() % 2) * 2 - 1); glm::vec3 spawnOffset = generate_coord(preset.spawnShape); spawnOffset *= preset.spawnSpread; diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index 0ad34053c..b2a371ade 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -29,6 +29,8 @@ struct Particle { UVRegion region; /// @brief Current rotation angle float angle; + /// @brief Angular velocity + float angularVelocity; }; class Texture; diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index 6c3ed73c3..f3a30cddc 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -31,12 +31,14 @@ static inline void update_particle( const auto& preset = particle.emitter->preset; auto& pos = particle.position; auto& vel = particle.velocity; + auto& angle = particle.angle; vel += delta * preset.acceleration; if (preset.collision && chunks.isObstacleAt(pos + vel * delta)) { vel *= 0.0f; } pos += vel * delta; + angle += particle.angularVelocity * delta; particle.lifetime -= delta; } diff --git a/src/presets/ParticlesPreset.cpp b/src/presets/ParticlesPreset.cpp index 272744423..8a0070767 100644 --- a/src/presets/ParticlesPreset.cpp +++ b/src/presets/ParticlesPreset.cpp @@ -44,6 +44,8 @@ dv::value ParticlesPreset::serialize() const { root["size"] = dv::to_value(size); root["size_spread"] = sizeSpread; root["angle_spread"] = angleSpread; + root["min_angular_vel"] = minAngularVelocity; + root["max_angular_vel"] = maxAngularVelocity; root["spawn_spread"] = dv::to_value(size); root["spawn_shape"] = to_string(spawnShape); root["random_sub_uv"] = randomSubUV; @@ -60,6 +62,8 @@ void ParticlesPreset::deserialize(const dv::value& src) { src.at("lifetime").get(lifetime); src.at("lifetime_spread").get(lifetimeSpread); src.at("angle_spread").get(angleSpread); + src.at("min_angular_vel").get(minAngularVelocity); + src.at("max_angular_vel").get(maxAngularVelocity); src.at("random_sub_uv").get(randomSubUV); if (src.has("velocity")) { dv::get_vec(src["velocity"], velocity); diff --git a/src/presets/ParticlesPreset.hpp b/src/presets/ParticlesPreset.hpp index 10b9f088b..2b955d13e 100644 --- a/src/presets/ParticlesPreset.hpp +++ b/src/presets/ParticlesPreset.hpp @@ -46,6 +46,10 @@ struct ParticlesPreset : public Serializable { float sizeSpread = 0.2f; /// @brief Random initial angle spread float angleSpread = 0.0f; + /// @brief Minimum angular velocity + float minAngularVelocity = 0.0f; + /// @brief Maximum angular velocity + float maxAngularVelocity = 0.0f; /// @brief Spawn spread shape ParticleSpawnShape spawnShape = BALL; /// @brief Spawn spread From e899575a7ab9a6c9c3ffab020307eedaf4dee434 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:54:25 +0300 Subject: [PATCH 05/11] update Emitter randomizer --- src/graphics/render/Emitter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 76b2f0185..ff8413d52 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -23,7 +23,7 @@ Emitter::Emitter( texture(texture), count(count), preset(std::move(preset)) { - random.setSeed(rand()); + random.setSeed(reinterpret_cast(this)); this->prototype.emitter = this; timer = preset.spawnInterval * random.randFloat(); } From 78761a445afc14b4839682a2333cd3b2a4dd02f3 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 23 Dec 2024 16:54:39 +0300 Subject: [PATCH 06/11] add leaf texture --- res/content/base/textures/particles/leaf_0.png | Bin 0 -> 5263 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 res/content/base/textures/particles/leaf_0.png diff --git a/res/content/base/textures/particles/leaf_0.png b/res/content/base/textures/particles/leaf_0.png new file mode 100644 index 0000000000000000000000000000000000000000..282fff809871a6043875be914ac134b734754131 GIT binary patch literal 5263 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 B Date: Mon, 23 Dec 2024 17:26:22 +0300 Subject: [PATCH 07/11] upgrade emitters garbage collection --- src/graphics/render/Emitter.cpp | 7 ++++++- src/graphics/render/Emitter.hpp | 6 ++++++ src/graphics/render/ParticlesRenderer.cpp | 20 +++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index ff8413d52..889515884 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -19,7 +19,7 @@ Emitter::Emitter( ) : level(level), origin(std::move(origin)), - prototype({this, 0, glm::vec3(), preset.velocity, preset.lifetime, region}), + prototype({this, 0, {}, preset.velocity, preset.lifetime, region}), texture(texture), count(count), preset(std::move(preset)) { @@ -113,6 +113,7 @@ void Emitter::update( if (count > 0) { count--; } + refCount++; } } @@ -124,6 +125,10 @@ bool Emitter::isDead() const { return count == 0; } +bool Emitter::isReferred() const { + return refCount > 0; +} + const EmitterOrigin& Emitter::getOrigin() const { return origin; } diff --git a/src/graphics/render/Emitter.hpp b/src/graphics/render/Emitter.hpp index b2a371ade..ce1ec8f47 100644 --- a/src/graphics/render/Emitter.hpp +++ b/src/graphics/render/Emitter.hpp @@ -54,6 +54,9 @@ class Emitter { util::PseudoRandom random; public: + /// @brief Number of references (alive particles) + int refCount = 0; + /// @brief Particle settings ParticlesPreset preset; Emitter( @@ -86,6 +89,9 @@ class Emitter { /// @return true if the emitter has spawned all particles bool isDead() const; + /// @return true if there is at least one alive referring particle left + bool isReferred() const; + const EmitterOrigin& getOrigin() const; void setOrigin(const EmitterOrigin& origin); diff --git a/src/graphics/render/ParticlesRenderer.cpp b/src/graphics/render/ParticlesRenderer.cpp index f3a30cddc..e96eb615a 100644 --- a/src/graphics/render/ParticlesRenderer.cpp +++ b/src/graphics/render/ParticlesRenderer.cpp @@ -63,7 +63,8 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { auto iter = vec.begin(); while (iter != vec.end()) { auto& particle = *iter; - auto& preset = particle.emitter->preset; + auto& emitter = *particle.emitter; + auto& preset = emitter.preset; if (!preset.frames.empty()) { float time = preset.lifetime - particle.lifetime; @@ -137,6 +138,7 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) { ); if (particle.lifetime <= 0.0f) { iter = vec.erase(iter); + emitter.refCount--; } else { iter++; } @@ -159,19 +161,15 @@ void ParticlesRenderer::render(const Camera& camera, float delta) { auto iter = emitters.begin(); while (iter != emitters.end()) { auto& emitter = *iter->second; + if (emitter.isDead() && !emitter.isReferred()) { + // destruct Emitter only when there is no particles spawned by it + iter = emitters.erase(iter); + continue; + } auto texture = emitter.getTexture(); const auto& found = particles.find(texture); std::vector* vec; - if (found == particles.end()) { - if (emitter.isDead()) { - // destruct Emitter only when there is no particles spawned by it - iter = emitters.erase(iter); - continue; - } - vec = &particles[texture]; - } else { - vec = &found->second; - } + vec = &particles[texture]; emitter.update(delta, camera.position, *vec); iter++; } From 40ac604e58612b76025f7b87d4d6ef46bf9bf6b8 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:00:17 +0300 Subject: [PATCH 08/11] many emitters test --- res/content/base/blocks/leaves.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/res/content/base/blocks/leaves.json b/res/content/base/blocks/leaves.json index e3ddae22d..4ea4832ff 100644 --- a/res/content/base/blocks/leaves.json +++ b/res/content/base/blocks/leaves.json @@ -3,5 +3,24 @@ "material": "base:grass", "draw-group": 5, "culling": "optional", + "particles": { + "lifetime": 4.0, + "spawn_interval": 1000.0, + "acceleration": [0, -0.1, 0], + "velocity": [0.2, -2.5, 0.3], + "explosion": [0, 0, 0], + "collision": false, + "size": [0.3, 0.3, 0.3], + "size_spread": 0.2, + "spawn_shape": "box", + "spawn_spread": [0.2, 0.2, 0.2], + "angle_spread": 1.0, + "min_angular_vel": 0.5, + "max_angular_vel": 2.0, + "lighting": true, + "frames": [ + "particles:leaf_0" + ] + }, "base:durability": 0.7 } From 344df27f611a3090dd1b555fd55c12089522212c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:14:51 +0300 Subject: [PATCH 09/11] minor refactor --- src/graphics/render/Decorator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index b7bd42188..95ccbcc23 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -99,9 +99,8 @@ void Decorator::update( void Decorator::update(float delta, const Camera& camera) { glm::ivec3 pos = camera.position; - pos -= glm::ivec3(UPDATE_AREA_DIAMETER / 2); for (int i = 0; i < ITERATIONS; i++) { - update(delta, pos, camera.position); + update(delta, pos - glm::ivec3(UPDATE_AREA_DIAMETER / 2), pos); } const auto& chunks = *level.chunks; const auto& indices = *level.content->getIndices(); From faf4cfa735cc60263c71db2ed675c1f8bf2e447b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:25:40 +0300 Subject: [PATCH 10/11] update doc/*/particles.md --- doc/en/particles.md | 4 ++++ doc/ru/particles.md | 3 +++ 2 files changed, 7 insertions(+) diff --git a/doc/en/particles.md b/doc/en/particles.md index 8b7a37e7d..47ab8ac3c 100644 --- a/doc/en/particles.md +++ b/doc/en/particles.md @@ -16,6 +16,10 @@ Particles are a table, all fields of which are optional. | acceleration | Particles acceleration. | {0, -16, 0} | | explosion | Force of particles explosion on spawn. | {2, 2, 2} | | size | Size of particles. | {0.1, 0.1, 0.1} | +| size_spread | Maximum particle size spread over time. | 0.2 | +| angle_spread | Maximum initial rotation angle spread (0 to 1) | 0.0 | +| min_angular_vel | Minimum angular velocity (radians per sec). Non-negative. | 0.0 | +| max_angular_vel | Maximum angular velocity (radians per sec). Non-negative. | 0.0 | | spawn_shape | Shape of particle spawn area. (ball/sphere/box) | ball | | spawn_spread | Size of particle spawn area. | {0, 0, 0} | | random_sub_uv | Size of random texture subregion (1 - entire texture will be used). | 1.0 | diff --git a/doc/ru/particles.md b/doc/ru/particles.md index 167337f85..90af27f15 100644 --- a/doc/ru/particles.md +++ b/doc/ru/particles.md @@ -18,6 +18,9 @@ | explosion | Сила разлёта частиц при спавне. | {2, 2, 2} | | size | Размер частиц. | {0.1, 0.1, 0.1} | | size_spread | Максимальное отклонение времени размера частиц. | 0.2 | +| angle_spread | Максимальное отклонение начального угла поворота (от 0 до 1) | 0.0 | +| min_angular_vel | Минимальная угловая скорость (радианы в сек.). Неотрицательное. | 0.0 | +| max_angular_vel | Максимальная угловая скорость (радианы в сек.). Неотрицательное. | 0.0 | | spawn_shape | Форма области спавна частиц. (ball/sphere/box) | ball | | spawn_spread | Размер области спавна частиц. | {0, 0, 0} | | random_sub_uv | Размер случайного подрегиона текстуры (1 - будет использована вся текстура). | 1.0 | From f1c7317c5ab2a148e5188e091cd1aa3490dc8b4d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 24 Dec 2024 05:35:02 +0300 Subject: [PATCH 11/11] fix non-skipping particles --- src/graphics/render/Emitter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index 889515884..e908ece89 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -77,6 +77,10 @@ void Emitter::update( count = std::max(0, count - skipped); timer -= skipped * spawnInterval; } + if (count < 0) { + int skipped = timer / spawnInterval; + timer -= skipped * spawnInterval; + } return; } while (count && timer > spawnInterval) {