Loading...
Logo
Processing Forum
I am interested to find out more about how others improve performance when it comes to building Particle Systems. Mainly, when I work with alot of particles I see a degrade in the frame rate and overall speed of the sketch. Can anyone shed any light on this for me?

Here is my sketch below. It is based on the particle systems examples from Daniel Shiffman's upcoming Nature of Code book. Any help would be greatly appreciated. Thanks!

MultipleFireParticleSystem.pde
Copy code
  1. ArrayList<ParticleSystem> psArray;
    Random generator;

    void setup() {
      size(400, 400);
      background(255); 
      smooth();

      generator = new Random();
      psArray = new ArrayList<ParticleSystem>();

      for (int i = 0; i< 10; i++) {
        psArray.add(new ParticleSystem(0, new PVector(random(width), random(height))));
      }
    }

    void draw() {
      background(0);

      Iterator it = psArray.iterator();
      while (it.hasNext()) {
        ParticleSystem ps = (ParticleSystem)it.next();

        float dx = map(mouseX, 0,width,-0.1,0.1);
        PVector wind = new PVector(dx,0); 
        ps.applyForce(wind);
     
        ps.addParticle();
        ps.run();
      
      }
    }
Class: Particle
Copy code
  1. class Particle {
      PVector location;
      PVector velocity;
      PVector acceleration;
      float lifespan;    // keep track of how long the particle is alive

      float mass = 1;

      PImage img;

      Particle (PVector l, PImage img_) {
        location = l.get(); // make copy of PVector
        acceleration = new PVector(0,0); //init to 0,0

          // create initial velocities
        float vx = (float) generator.nextGaussian() * 0.3;
        float vy = (float) generator.nextGaussian() * 0.3-1.0;
        velocity = new PVector(vx, vy);    
        //velocity = new PVector(random(-2, 2), random(-3, 0));
        lifespan = 255;
        img = img_;
      }

      void run() {
        update();
        display();
      }

      void applyForce(PVector force) {
        PVector f = force.get();
        //f.div(mass); //ignore mass
        acceleration.add(f);
      }

      void update() {
        velocity.add(acceleration);
        location.add(velocity);
        acceleration.mult(0);
        lifespan -= 2.0;
      }

      void display() {
        imageMode(CENTER);
        tint(255, lifespan);
        image(img, location.x, location.y);
      } 

      boolean isDead() {
        if (lifespan < 0.0) {
          return true;
        }
        else {
          return false;
        }
      }
    }
Class: ParticleSystem
Copy code
  1. class ParticleSystem {
      ArrayList<Particle> particles;  // use one list to include all subclasses of Particle - polymorphism awesomeness!
      PVector origin;
     
      PImage pImg;

      ParticleSystem (int num, PVector location) {
        origin = location.get();
        particles = new ArrayList<Particle>();
        //img = img_;
       
        for(int i=0; i < num; i++) {
          addParticle();
        }
      }

      void addParticle() {
          pImg = loadImage("textureRed.png");             
         particles.add(new Particle(origin, pImg));
      }
     
     // Recieve a force as a pVector and apply that force to all the Particles in the Particle System
      void applyForce(PVector f) {
        for(Particle p: particles) {
          p.applyForce(f);
        } 
      }

      void run() {
        Iterator it = particles.iterator();
        while (it.hasNext()) {
          Particle p = (Particle)it.next();
          p.run();
          if (p.isDead()) {
            it.remove();
          }
        }
      }
    }

Image

Replies(3)

Hi,

At first i would try to use opengl & even better opengl2 renderers (see the examples coming with last processing release).
Then i'd dig into opengl performance tricks like display list, VBO, etc...(on the processing wiki they are some info).
Search the forum, some ppl have made great works with lot of particles.
Then in a more advanced stage you could dive into the OpenCL world.



This is probably sacrilege, but the object oriented approach might not be the best way to handle particle systems. Creating and destroying individual particles creates overhead, which can add up if you have lots and lots of particles. Also, iterating over large blocks of data is best done in continuous blocks, instead of constantly dereferencing different objects spread through the RAM.

To quote myself from the Cinder board:

When I was programming in Processing, I couldn't make heads or tails of their container objects, so I resorted to this technique:
  • decide the maximum number of particles possible, let's call this maxParticles (note that deciding this number can be done dynamically at runtime)
  • create arrays accordingly for x, y, etc.
  • have an int that counts the number of "living" particles, let's call it totalParticles
  • if I want to add a new particle:
    • if totalParticles < maxParticles : insert new particle at x[totalParticles], y[totalParticles], etcetera, then ++totalParticles
    • else you decide whatever you wanted to happen if the max number of particles is reached
  • if a particle dies at, say particle n, all we have to do is --totalParticles, followed by x[n] = x[totalParticles], y[n] = y[totalParticles], etceter (in my case, the order in which the particles were iterated over didn't matter).
  • iterating is a matter of "for int i = 0; i < totalParticles; ++i"
A friend I've discussed this with reminded me that primitive types are the only non-objects in Java, so maybe I accidentally made really optimised Processing programs because I didn't understand the Java container objects ;).
Now, this usually is bad practice, but it's certainly more efficient because it's closer to the metal (and theoretically, the primitive type arrays also make better use of the CPU cache), so in the case of particle systems it might be worth it.

See also "Data Oriented Design"

And yeah, using GLGraphics to leviate particle systems to you GPU is a good idea as well ;)
Awesome feedback, thanks!!. I really appreciate it and will investigate these techniques.