Zen 0.3.0
Loading...
Searching...
No Matches
ZEN_ParticleSystem.h
1#pragma once
2
3#define GLM_ENABLE_EXPERIMENTAL
4#include <glm/gtc/random.hpp>
5#include <glm/gtx/rotate_vector.hpp>
6#include <zen/renderer/ZEN_Shader.h>
7#include <zen/renderer/ZEN_VertexArray.h>
8#include <zen/time/ZEN_DeltaTime.h>
9#include <zen/zen_pch.h>
10
11namespace Zen {
13 glm::vec2 position{0};
14 glm::vec2 velocity{0};
15 float lifeTime{1.0f};
16 float sizeBegin{8.0f};
17 float sizeEnd{0};
18 glm::vec4 colourBegin{1.0f, 1.0f, 1.0f, 1.0f};
19 glm::vec4 colourEnd{1.0f, 1.0f, 1.0f, 0};
20 };
21
22 struct Particle {
23 glm::vec2 pos{0};
24 glm::vec2 vel{0};
25 float lifeRemaining{0};
26 float lifeTime{1.0f};
27 float sizeBegin{8.0f};
28 float sizeEnd{0};
29 glm::vec4 colourBegin{1.0f};
30 glm::vec4 colourEnd{0, 0, 0, 0};
31 bool active{false};
32 };
33
34 struct QuadVertex {
35 glm::vec2 pos;
36 glm::vec4 colour;
37 };
38
40 float coneDeg = 1.0f;
41 float speedMinMul = 0.5f;
42 float speedMaxMul = 1.5f;
43 float noiseSigma = 1.0f;
44 };
45
46 inline glm::vec2 sampleVelocityFromBase(glm::vec2 baseVelocity, const VelocityRandomizer &vRand) {
47 float baseSpeed = glm::length(baseVelocity);
48 glm::vec2 direction = (baseSpeed > 0) ? baseVelocity / baseSpeed : glm::vec2{0, 1};
49
50 float theta = glm::radians(glm::linearRand(-vRand.coneDeg, vRand.coneDeg));
51 direction = glm::rotate(direction, theta);
52
53 float k = glm::linearRand(vRand.speedMinMul, vRand.speedMaxMul);
54 float speed = baseSpeed * k;
55
56 glm::vec2 noise{glm::linearRand(-vRand.noiseSigma, vRand.noiseSigma),
57 glm::linearRand(-vRand.noiseSigma, vRand.noiseSigma)};
58 return direction * speed + noise;
59 }
60
61 struct ParticleEmitter {
62 glm::vec2 pos{0, 0};
63 glm::vec2 size{1.0f, 1.0f};
64 glm::vec4 colour{1.0f, 1.0f, 1.0f, 1.0f};
65 VelocityRandomizer vRand{};
66
67 ParticleProps props;
68 float spawnRate = 30.0f;
69 float emitAccumulator = 0;
70
71 ParticleEmitter(const glm::vec2 &position, const glm::vec2 &sz, const glm::vec4 &col)
72 : pos(position), size(sz), colour(col) {
73 props.colourBegin = col;
74 props.position = position;
75 props.sizeBegin = sz.x;
76 }
77 };
78
79 class ParticleSystem {
80 public:
81 explicit ParticleSystem(size_t maxParticles = 1000);
82
83 void emit(const ParticleProps &props);
84
85 void update(DeltaTime deltaTime);
86
87 void upload();
88 void clear();
89
90 const std::shared_ptr<VertexArray> &vao() const { return m_vao; }
91 std::shared_ptr<Shader> &shader() { return m_shader; }
92
93 size_t capacity() const { return m_max; }
94
95 void updateEmitter(ParticleEmitter &emitter, DeltaTime deltaTime);
96 void updateEmitters(std::vector<ParticleEmitter> &emitters, DeltaTime deltaTime);
97
98 private:
99 size_t m_max{0};
100 int32_t m_alive{0};
101 std::vector<Particle> m_pool;
102 size_t m_poolIndex{0}; // ring index
103
104 std::vector<QuadVertex> m_cpuQuad; // size = m_max * 4
105
106 std::shared_ptr<VertexArray> m_vao;
107 std::shared_ptr<VertexBuffer> m_vbo; // dynamic, max*4 vertices
108 std::shared_ptr<IndexBuffer> m_ibo; // static, max*6 indices
109 std::shared_ptr<Shader> m_shader;
110 };
111} // namespace Zen