update particles garbage collection scheme
This commit is contained in:
parent
cee214754b
commit
1974298c82
@ -16,6 +16,7 @@ Emitter::Emitter(
|
|||||||
texture(texture),
|
texture(texture),
|
||||||
spawnInterval(spawnInterval),
|
spawnInterval(spawnInterval),
|
||||||
count(count) {
|
count(count) {
|
||||||
|
this->prototype.emitter = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Texture* Emitter::getTexture() const {
|
const Texture* Emitter::getTexture() const {
|
||||||
|
|||||||
@ -8,10 +8,19 @@
|
|||||||
|
|
||||||
#include "maths/UVRegion.hpp"
|
#include "maths/UVRegion.hpp"
|
||||||
|
|
||||||
|
class Emitter;
|
||||||
|
|
||||||
struct Particle {
|
struct Particle {
|
||||||
|
/// @brief Pointer used to access common behaviour.
|
||||||
|
/// Emitter must be utilized after all related particles despawn.
|
||||||
|
Emitter* emitter;
|
||||||
|
/// @brief Global position
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
|
/// @brief Linear velocity
|
||||||
glm::vec3 velocity;
|
glm::vec3 velocity;
|
||||||
|
/// @brief Remaining life time
|
||||||
float lifetime;
|
float lifetime;
|
||||||
|
/// @brief UV region
|
||||||
UVRegion region;
|
UVRegion region;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,6 +52,7 @@ public:
|
|||||||
int count
|
int count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// @return Emitter particles texture
|
||||||
const Texture* getTexture() const;
|
const Texture* getTexture() const;
|
||||||
|
|
||||||
/// @brief Update emitter and spawn particles
|
/// @brief Update emitter and spawn particles
|
||||||
@ -50,7 +60,9 @@ public:
|
|||||||
/// @param particles destination particles vector
|
/// @param particles destination particles vector
|
||||||
void update(float delta, std::vector<Particle>& particles);
|
void update(float delta, std::vector<Particle>& particles);
|
||||||
|
|
||||||
|
/// @brief Set initial random velocity magitude
|
||||||
void setExplosion(const glm::vec3& magnitude);
|
void setExplosion(const glm::vec3& magnitude);
|
||||||
|
|
||||||
|
/// @return true if the emitter has spawned all particles
|
||||||
bool isDead() const;
|
bool isDead() const;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -15,24 +15,24 @@ ParticlesRenderer::ParticlesRenderer(const Assets& assets)
|
|||||||
|
|
||||||
auto region = util::get_texture_region(assets, "blocks:grass_side", "");
|
auto region = util::get_texture_region(assets, "blocks:grass_side", "");
|
||||||
Emitter emitter(glm::vec3(0, 100, 0), Particle {
|
Emitter emitter(glm::vec3(0, 100, 0), Particle {
|
||||||
glm::vec3(), glm::vec3(), 5.0f, region.region
|
nullptr, glm::vec3(), glm::vec3(), 5.0f, region.region
|
||||||
},region.texture, 0.001f, -1);
|
},region.texture, 0.001f, 1000);
|
||||||
emitters.push_back(std::move(emitter));
|
emitters.push_back(std::make_unique<Emitter>(emitter));
|
||||||
}
|
}
|
||||||
|
|
||||||
ParticlesRenderer::~ParticlesRenderer() = default;
|
ParticlesRenderer::~ParticlesRenderer() = default;
|
||||||
|
|
||||||
void ParticlesRenderer::render(
|
void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
|
||||||
const Assets& assets, const Camera& camera, float delta
|
|
||||||
) {
|
|
||||||
const auto& right = camera.right;
|
const auto& right = camera.right;
|
||||||
const auto& up = camera.up;
|
const auto& up = camera.up;
|
||||||
|
|
||||||
batch->begin();
|
std::vector<const Texture*> unusedTextures;
|
||||||
|
|
||||||
aliveEmitters = emitters.size();
|
|
||||||
visibleParticles = 0;
|
|
||||||
for (auto& [texture, vec] : particles) {
|
for (auto& [texture, vec] : particles) {
|
||||||
|
if (vec.empty()) {
|
||||||
|
unusedTextures.push_back(texture);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
batch->setTexture(texture);
|
batch->setTexture(texture);
|
||||||
|
|
||||||
visibleParticles += vec.size();
|
visibleParticles += vec.size();
|
||||||
@ -62,24 +62,36 @@ void ParticlesRenderer::render(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
batch->flush();
|
batch->flush();
|
||||||
|
for (const auto& texture : unusedTextures) {
|
||||||
|
particles.erase(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticlesRenderer::render(const Camera& camera, float delta) {
|
||||||
|
batch->begin();
|
||||||
|
|
||||||
|
aliveEmitters = emitters.size();
|
||||||
|
visibleParticles = 0;
|
||||||
|
|
||||||
|
renderParticles(camera, delta);
|
||||||
|
|
||||||
auto iter = emitters.begin();
|
auto iter = emitters.begin();
|
||||||
while (iter != emitters.end()) {
|
while (iter != emitters.end()) {
|
||||||
auto& emitter = *iter;
|
auto& emitter = **iter;
|
||||||
auto texture = emitter.getTexture();
|
auto texture = emitter.getTexture();
|
||||||
const auto& found = particles.find(texture);
|
const auto& found = particles.find(texture);
|
||||||
std::vector<Particle>* vec;
|
std::vector<Particle>* vec;
|
||||||
if (found == particles.end()) {
|
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];
|
vec = &particles[texture];
|
||||||
} else {
|
} else {
|
||||||
vec = &found->second;
|
vec = &found->second;
|
||||||
}
|
}
|
||||||
emitter.update(delta, *vec);
|
emitter.update(delta, *vec);
|
||||||
|
|
||||||
if (emitter.isDead()) {
|
|
||||||
iter = emitters.erase(iter);
|
|
||||||
} else {
|
|
||||||
iter++;
|
iter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "Emitter.hpp"
|
#include "Emitter.hpp"
|
||||||
@ -12,13 +13,15 @@ class MainBatch;
|
|||||||
|
|
||||||
class ParticlesRenderer {
|
class ParticlesRenderer {
|
||||||
std::unordered_map<const Texture*, std::vector<Particle>> particles;
|
std::unordered_map<const Texture*, std::vector<Particle>> particles;
|
||||||
std::vector<Emitter> emitters;
|
std::vector<std::unique_ptr<Emitter>> emitters;
|
||||||
std::unique_ptr<MainBatch> batch;
|
std::unique_ptr<MainBatch> batch;
|
||||||
|
|
||||||
|
void renderParticles(const Camera& camera, float delta);
|
||||||
public:
|
public:
|
||||||
ParticlesRenderer(const Assets& assets);
|
ParticlesRenderer(const Assets& assets);
|
||||||
~ParticlesRenderer();
|
~ParticlesRenderer();
|
||||||
|
|
||||||
void render(const Assets& assets, const Camera& camera, float delta);
|
void render(const Camera& camera, float delta);
|
||||||
|
|
||||||
static size_t visibleParticles;
|
static size_t visibleParticles;
|
||||||
static size_t aliveEmitters;
|
static size_t aliveEmitters;
|
||||||
|
|||||||
@ -203,7 +203,8 @@ void WorldRenderer::renderLevel(
|
|||||||
auto assets = engine->getAssets();
|
auto assets = engine->getAssets();
|
||||||
|
|
||||||
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
bool culling = engine->getSettings().graphics.frustumCulling.get();
|
||||||
float fogFactor = 15.0f / ((float)settings.chunks.loadDistance.get() - 2);
|
float fogFactor =
|
||||||
|
15.0f / static_cast<float>(settings.chunks.loadDistance.get() - 2);
|
||||||
|
|
||||||
auto entityShader = assets->get<Shader>("entity");
|
auto entityShader = assets->get<Shader>("entity");
|
||||||
setupWorldShader(entityShader, camera, settings, fogFactor);
|
setupWorldShader(entityShader, camera, settings, fogFactor);
|
||||||
@ -216,7 +217,7 @@ void WorldRenderer::renderLevel(
|
|||||||
delta,
|
delta,
|
||||||
pause
|
pause
|
||||||
);
|
);
|
||||||
particles->render(*assets, camera, delta * !pause);
|
particles->render(camera, delta * !pause);
|
||||||
modelBatch->render();
|
modelBatch->render();
|
||||||
|
|
||||||
auto shader = assets->get<Shader>("main");
|
auto shader = assets->get<Shader>("main");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user