Particle systems are an important aspect of any game engine. Particle systems allow for a variety of different effects, such as fire, smoke, and rain. For our game, we'll have a few different systems that will use particles, so we wanted to implement a generic system that could easily be adapted and modified for different particle types. Our particle system also loads data from JSON files into the scene and component system. This way, we can easily change files to test different particle effects and parameters, without having to recompile the engine.
Particle Implementation:
The backend of our particle system is built using a circular buffer provided by boost. The circular buffer allows us to reuse old slots instead of creating new ones, which helps to avoid unnecessary memory allocation. The implementation follows the general entity-component-system style with a few additional helper classes. This means that the three main aspects are the helper data / classes, particle emitter components, and the particle system.
Data and Helper classes:
The first part of the particle system is the data and helper classes. These classes are mostly just to help with rendering and simulating, and they act as a way to store data. The first of these is the ParticleData struct. The struct contains information on the current particle, such as position, size, age, and opacity. This data is used in two places: simulation of particles and rendering. The particles are first simulated, which required their data to be read, calculations need to be performed, and then their data is set. Next, in the rendering pass, the unique data is added to list of instance data to render for the particle.
The second helper class is the Particle class, which handles all of the rendering backend for a particle. This class contains a list of ParticleData, and each render pass adds the data to the list before it is rendered and clear for next frame. This class is essentially what gets bound to the renderer for rendering.
Particle Emitter Components:
The Particle Emitter Component contains all the data needed to simulate the particles, and can be attached to any entity that needs to have particles. Particle emitters contain the circular buffer of ParticleData information on timing, velocity, spawning, fading, etc; and the actual information on the particle to render. Particle emitter components are what connect the simulation aspect to the helper classes. All the data in this class is used to simulate the particles, and that simulated data is stored in the buffer of ParticleData. When the particles need to be rendered, the Particle object and ParticleData buffer are used to process the information and send them to the GPU.
The Particle Emitter Component is what is loaded from JSON. Since the data of each particle only matters at run-time, there's no need for that to be created in JSON, and the Particle class that contains the rendering information only needs to know of the material to use for rendering the particle. This means that the particle JSON file can looks pretty simple.
Every value except for the last are directly loaded into the Particle Emitter Component, with the last one being used to make the Particle object for rendering.
Particle System:
The Particle System itself is what brings life to the data. After gathering all entity with particle components, it runs through all the particle components and: updates their timer, checks if the component should spawn a particle, and, if it is time, spawns a particle. The system them moves all active particles in the direction of the velocity, and uses linear interpolation to calculate the opacity and size of the particle. After this step, the particles are run through the rendering pipeline to be added to the queue of particles, and to add the instanced data to each particle. From there, the queue is traversed and the particles are drawn to the screen.
Overall, the particle system is pretty simplistic while also remaining flexible. For our game, we most likely won't need very complex particles, but the system always has room for improvements and updates. With that, here's a simple demo of some cloud particles being rendered with the system!
Comments