2

I'm working on my first game engine, and trying to implement a GPU particle system. I've implemented one on the CPU before, but now I'm trying to make it more efficient. My problem, specifically, is with spawning particles on a lifetime.

Since I'm working with framebuffer textures for the particle engine, it's very parallel, but at the cost of not being able to return to the CPU, right? I have a first pass in drawing a quad that handles the calculations for that specific particle system (there will probably have to be a second quad for the sake of sorting), and then I run a glDrawArraysInstanced

One idea I had was to use a boolean or an int for when I need to create a particle, representing either the need to create a particle or the amount of particles to spawn, both initialized by the CPU. So if I find one particle (pixel) that's lifetime (let's say the alpha value of the first fbo texture) is less than zero, and I know I'm supposed to create it, how do I disable the creation for the rest of the particles, or decrement the number of particles to be burst? I've heard of things like transform feedback, but I don't know if that's the best way. And stateless particles sound limiting - not all particles have a 1:1 spawning rate.

To repeat the question briefly: What is the best way to spawn GPU particles?

If I could have the number of particles on the CPU, by the way, I could set the amount to draw in glDrawArraysInstanced, so if you could include that in your answer, I would be grateful.

  • 1
    I've worked on games before. Tired of using other people's engines, and don't want to write an entirely new codebase for every game. I've already done tons of work on rendering, physics, lighting, input, and tons of other systems. Stopping doesn't sound like a good idea right now. – Karim Abdel Hamid Jul 09 '16 at 19:51
  • 1
    Oh, and @JesperJuhl - I just read the article. I already have several game ideas planned, and every single system in the code is planned to work among different types of games. If I coded one game, it would not be very flexible. My input system, for example, is compatible with Linux and Windows, and soon Mac, as well as designed to function with various inputs and functions to be simple to use and flexible. So thanks for some tough love, but I don't really need it - I just need to figure out the best (and most flexible) way to solve this issue. – Karim Abdel Hamid Jul 09 '16 at 20:28

1 Answers1

0

I'll have a go…

The CPU should know what the maximum number of particles is (which will be the pool size) and the current number of 'live' particles. First number is used to initialize, or resize, the particle state VBOs and shouldn't change often. The second can change frame by frame if you like.

Individual particle lifetimes should be stored as part of the VBO values. Presumably you use a counter or time value to determine position, color, etc and when this counter reaches a maximum you 'kill' the particle and re-allocate. By varying the initial counter values, the particles don't have to all start and update identically.

For updating particle state, yes you want transform feedback. You'll have a 'vertex shader' which calculates new values for each particle from old and writes these to another VBO. See the OpenGL SuperBible for details and example code. I just ping-pong between two VBOs, one for old values, one for new, but you might also decide to use Texture Buffer Objects which are large arrays (much larger than uniform) you can write to within shaders. The number of particles which get updated each time is controlled by the CPU live counter.

Hope this helps.

Hugh Fisher
  • 2,321
  • 13
  • 8
  • Thank you for your answer, but while I considered using VBOs, I decided against it. I thought texture (like this http://nullprogram.com/blog/2014/06/29/ ) would be a better solution for a large number of particles. My particles currently have a looping lifetime, but I want them to be able to "die" for a bit, and that's my issue. I don't how to create exactly one new particle on the GPU alone. – Karim Abdel Hamid Jul 10 '16 at 02:29
  • If you want to do efficient parallel processing, DON'T think in terms of controlling individual particles. You need algorithms that work across huge numbers. Individual particles can 'die' for a bit by either reducing the live count used in glDrawArraysInstanced or whatever, or by allowing particles to have a negative age and being invisible until the age is > 0 – Hugh Fisher Jul 10 '16 at 09:14
  • that's exactly my plan, my issue is with implementation. Due to particles' random lifetime, it will be difficult to control the number of particles that are alive for gldrawarrayinstanced but in addition. If I have the number of particles, which is incremented and decremented on the GPU, i can solve this issue. – Karim Abdel Hamid Jul 10 '16 at 11:28