How to use createGraphics buffer properly?

zgazga
edited November 2015 in Questions about Code

I first copied the exercise from section 6.4 (document page 166) of Algorithms for Visual Design using the Processing Language.The code works, but it is slow to draw, obviously.

I then tried to use createGraphics as a kind of 'buffer' as outlined on the next section of the book, section 6.5 (document page 168). I've pasted my attempt below, which doesn't quite work.

My question is how does one integrate already working code with an off-screen buffer (something like this)? Is there a general method, or do off-screen buffers use entirely different methods?

It can't be as simple as adding an extra line to the setup and draw functions, can it? What is the purpose of using elements like pg.background, if they seem to merely duplicate the information already in background?

Thanks,

frustrated guy new to processing

my attempt to replicate the example with a buffer:

PGraphics pg;

void setup() {
  noSmooth();
  size(300,300, P2D);
  pg = createGraphics(150,120, P2D);
}

  float px[] = new float [300];
  float py[] = new float [300];
  float pr[] = new float [360];

void draw() {
  for(int i=0; i<mouseY; i++){
    px[i] = random(width);
    py[i] = random(height);
    pr[i] = random(360);
  }
  background(255);
  for(int i=0; i<mouseY; i++){
    pushMatrix();
    rectMode(CENTER);
    translate(px[i],py[i]);
    rotate(radians(pr[i] + mouseX));
    rect(0,0,5,500);
    popMatrix();
  }
    
  pg.beginDraw();
  pg.endDraw();
  
  image(pg, 0, 0, width, height);
}

Answers

  • I can't really run that code above, but maybe a little explanaiton can help.
    When you use a PGraphics-object then you usually want this "buffer" to be independent from your main-window drawing and its settings. So you can decide if you want to set a background for the window or the buffe for example.

    These instructions affect the main window:

    background(255);
    pushMatrix();
    rectMode(CENTER);
    ....
    

    When you want them to work on you buffer, you have to do it like this:

    pg.background(255);
    pg.pushMatrix();
    pg.rectMode(CENTER);
    ....
    

    So i regret, but there's no simple one-liner.

  • edited November 2015

    A PApplet actually uses a PGraphics object for its underlying rendering operations. When you call, for instance

    background(255);

    what's really happening is something like this

    this.graphics.background(255);

    So to use a PGraphics buffer, all you need to do is to initialize a new PGraphics object:

    pg = createGraphics(width, height);
    pg.beginDraw();  //this MUST be called before you do anything else with pg,
                     //or you'll get NullPointerExceptions
    

    Then you change all your drawing function calls to execute on the buffer object rather than the PApplet:

    /*this.graphics*/pg.background(255);

    Don't call PGraphics.endDraw() until you're ready to display the buffer contents on screen, because that "finalize" the PGraphics object until you call PGraphics.beginDraw() again.

  • after pg.endDraw(); use image(pg.....

  • edited November 2015
    pg.beginDraw();  //this MUST be called before you do anything else with pg,
    

    There's a curious caveat: if we need to call smooth() or noSmooth() in P3, it gotta be called before beginDraw()! @-)

    after pg.endDraw(); use image(pg.....

    We can also use set() & background() to display PImage objects too! O:-)

    P.S.: PGraphics extends PImage. ;;) Movie & Capture idem. :>

  • How to use createGraphics buffer properly?

    This is a very general question, since there are so many possible applications of image buffers. I haven't read the linked book; but I'm assuming the intent in this case is to use the buffer to store the result of expensive drawing operations...

    If you're drawing something that requires a lot of slow calculations, and especially if you then want to draw lots of copies of this object, do the drawing to a buffer image in setup(); then use image(bufferIMage, x, y) in draw() (example refactored from the reference):

    PGraphics pg;
    
    void setup() {
      size(100, 100);
      pg = createGraphics(40, 40);
      pg.beginDraw();
      // expensive drawing operations go here...
      pg.endDraw();
    }
    
    void draw() {
      // now you can draw the buffer image to the sketch window 
      image(pg, 9, 30); 
      image(pg, 51, 30);
    }
    

    This does have limitations: for example the image is fixed; but you might want it to update with user interaction. In this case the buffer approach is probably only worth applying if you're creating lots of copies of the object that all change in unison. You'd also have to move the drawing operation into its own function, call this from setup() and again when you get user interaction...

  • PGraphics is the only safe way to draw outside the "Animation" Thread.
    PGraphics allows us to draw in some speed different than draw()'s frameRate() too.

Sign In or Register to comment.