This commit is contained in:
Gabrieal Jimmy
2026-10-02 12:42:00 -05:00
commit 2c99305fb0
145 changed files with 6525 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
#pragma once
#include "hd2d/GL.h"
#include <glm/glm.hpp>
#include <random>
#include <vector>
namespace hd2d {
struct PointLight;
// High-resolution (non pixel-art) particles: ambient fields (fireflies, dust),
// fire emitters (flames, embers, smoke, glow + flickering light) and bursts.
class ParticleSystem {
public:
// Must match the kind ids in particles.vert / particles.frag.
enum class Kind : int {
Firefly = 0, // blinking emissive glow, wanders near the ground
Mote = 1, // dust speck only visible where sunlight hits it (god rays)
Spark = 2, // ballistic burst particle (footstep dust, rain splashes, ...)
Flame = 3, // additive tongue of fire, eroded by noise as it ages
Ember = 4, // tiny hot spark drifting up on turbulent air
Smoke = 5, // alpha-blended puff rising above a fire
Glow = 6, // large soft halo around a fire (one per emitter per frame)
};
struct Field { // region that keeps a constant population of ambient particles
Kind kind;
glm::vec3 min, max;
int count;
};
struct Fire {
glm::vec3 pos; // base of the flames
float scale = 1.0f; // overall size / intensity
float flameAccum = 0.0f, emberAccum = 0.0f, smokeAccum = 0.0f;
float flicker = 1.0f; // current light flicker multiplier
float phase = 0.0f;
};
~ParticleSystem();
void addField(Kind kind, glm::vec3 min, glm::vec3 max, int count);
int addFire(glm::vec3 pos, float scale = 1.0f);
void burst(glm::vec3 pos, int count, glm::vec3 color, float speed, float size, float life);
void update(float dt, float time);
void draw() const;
// Appends fire lights first, then up to `maxFireflies` firefly lights.
void collectLights(std::vector<PointLight>& out, int maxFireflies) const;
const std::vector<Fire>& fires() const { return fires_; }
glm::vec3 fireflyColor{2.6f, 3.2f, 0.9f};
glm::vec3 moteColor{1.0f, 0.95f, 0.8f};
float fireflyLightRadius = 2.2f;
glm::vec3 fireLightColor{4.0f, 1.75f, 0.55f};
float fireLightRadius = 7.0f;
glm::vec3 wind{0.0f}; // world-space drift applied to smoke and embers
float ambientFade = 1.0f; // scales fireflies + motes (Weather lowers it in rain)
private:
struct Particle {
glm::vec3 pos, vel;
glm::vec3 color;
float size, age, life, phase;
Kind kind;
int field; // ambient field index, or -1
int fire; // owning fire, or -1
};
struct GpuParticle {
glm::vec4 posSize;
glm::vec4 color; // rgb, a = alpha
glm::vec4 params; // x = kind, y = age / life, z = random seed
};
void spawnInField(Particle& p, int fieldIndex, bool randomAge);
void spawnFire(const Fire& f, int fireIndex, Kind kind);
std::vector<Field> fields_;
std::vector<Fire> fires_;
std::vector<Particle> particles_;
std::vector<GpuParticle> gpu_;
std::mt19937 rng_{1337};
GLuint vao_ = 0, vbo_ = 0;
size_t capacity_ = 0;
};
} // namespace hd2d