PShape slower than processing immediate mode

edited November 2014 in GLSL / Shaders

I have been trying to get a grip of the "new" PShape object, hoping to get some performance gains from it when drawing big meshes and shapes, but looking at the Examples and some relevant posts, I seem to be missing something, as I don't see any performance improvement, but in contrary, it is actually slower than the old processing immediate method (beginShape etc).

The code below is taken from the PShape examples (PolygonPShapeOOP2) with an addition of an old display method. I have also tried to divide the drawing in batches (two for loops, as in Andres's example) to see if that has a better effect, with no luck. Any ideas on what I am missing would be very welcome.

ArrayList<Polygon> polygons;

void setup() {
  size(640, 360, P3D);
  smooth();

  PShape star = createShape();
  star.beginShape();
  star.noStroke();
  star.fill(0, 127);
  star.vertex(0, -2.5);
  star.vertex(.7, -1.0);
  star.vertex(2.35, -.75);
  star.vertex(1.15, .35);
  star.vertex(1.45, 2.0);
  star.vertex(0, 1.25);
  star.vertex(-1.45, 2.0);
  star.vertex(-1.15, .35);
  star.vertex(-2.35, -.75);
  star.vertex(-.75, -1.0);
  star.endShape(CLOSE);  

  polygons = new ArrayList<Polygon>();
  for (int i = 0; i < 50000; i++) {
    polygons.add(new Polygon(star));
  }
}

void draw() {
  println(frameRate);
  background(255);
  for (Polygon poly : polygons) {
    poly.display();                   //Shape Mode
    //poly.displayOld();                //Old Mode
    poly.move();
  }
}

class Polygon {
  PShape s;
  float x, y;
  float speed;

  Polygon(PShape s_) {
    x = random(width);
    y = random(-100); 
    s = s_;
    speed = random(2, 6);
  }

  void move() {
    y += speed;
    if (y > height+100) {
      y = -100;
    }
  }

  void display() {
    pushMatrix();
    translate(x, y);
    shape(s);
    popMatrix();
  }

  void displayOld() {
    pushMatrix();
    translate(x, y);
    beginShape();
    noStroke();
    fill(0, 127);
    vertex(0, -2.5);
    vertex(.7, -1.0);
    vertex(2.35, -.75);
    vertex(1.15, .35);
    vertex(1.45, 2.0);
    vertex(0, 1.25);
    vertex(-1.45, 2.0);
    vertex(-1.15, .35);
    vertex(-2.35, -.75);
    vertex(-.75, -1.0);
    rect(0, 0, 2, 2);    
    endShape(CLOSE);
    popMatrix();
  }
}

Answers

  • frameRates on my machine: ~ 3fps for PShape method ~13fps for Old method

  • edited November 2014

    Try drawing them as a group:

    ArrayList<Polygon> polygons;
    PShape group;
    
    void setup() {
      size(640, 360, P3D);
      smooth();
    
      group = createShape(GROUP);
      polygons = new ArrayList<Polygon>();
      for (int i = 0; i < 10000; i++) {
        Polygon cur = new Polygon(); 
        polygons.add(cur);
        group.addChild(cur.s);
      }
    }
    
    void draw() {
      if (frameCount%30==0) println(frameRate);
      background(255);
      for (Polygon poly : polygons) {
        poly.updateShape();
      }
      shape(group);
    }
    
    class Polygon {
      PShape s;
      float x, y;
      float speed;
    
      Polygon() {
        x = random(width);
        y = random(-100);
        s = createShape();   
        s.beginShape();
        s.fill(0, 127);
        s.noStroke();
        s.vertex(0, -2.5);
        s.vertex(.7, -1.0);
        s.vertex(2.35, -.75);
        s.vertex(1.15, .35);
        s.vertex(1.45, 2.0);
        s.vertex(0, 1.25);
        s.vertex(-1.45, 2.0);
        s.vertex(-1.15, .35);
        s.vertex(-2.35, -.75);
        s.vertex(-.75, -1.0);
        s.endShape(CLOSE);
        s.translate(x,y);
        speed = random(2, 6);
      }
    
      void updateShape() {
        y += speed;
        if(y > height+100) {
          y = -100;
          s.resetMatrix();
          s.translate(x, y);
          return;
        }
        s.translate(0,speed);
      }
    }
    
  • @rbrauer why did you change the object count from 50000 to 10000? :)

    I tried the examples and thought "wow! so smooth! it makes a HUGE difference!". Then I noticed the lower object count. When using 50000 it does not make much of a difference in my computer.

    In the first example is 3 fps vs 8 fps, using a group I get 10 fps.

  • edited November 2014 Answer ✓

    The biggest difference will be for static shapes. With immediate mode you would have to draw them over and over again, while in retained mode you would send the data to the GPU once and the just draw from the GPU. Doing this would mean you could look at a very high-resolution model (also move around it) at interactive frameRates. Something that would not have been possible using immediate mode.

    The achilles heel of retained mode is changes to the shape. Read: anything that results in communication between the CPU and the GPU. Because this will lower the frameRate a lot. That was the whole point why you wanted a retained shape, to remove the constant interaction between the (slow) CPU and the (fast) GPU. So the key to keeping it fast, is to have as little interaction between CPU and GPU as possible.

    The ideal for the retained mode is one big, unchanging shape (which can consist of many smaller ones of course, as shown by rbrauer). The worst for the retained mode is very many, constantly changing shapes.

    There are more advanced methods to have a fast retained shape on the one hand and still have movement on the other hand. For example you can think of vertex displacement, which is moving vertices via the vertex shader.

    Things like shaders and PShape are tools that you can use (not magic solutions that always speed up your sketch). Understanding these tools will allow you know when and how to use them most effectively.

  • Also see the examples under Demos\Performance.

    For example DynamicParticles.

  • why did you change the object count from 50000 to 10000?

    Sorry @hamoid, I should have pointed that out.

Sign In or Register to comment.