PGraphics and P2D renderer do not play well

edited November 2013 in Questions about Code

Hi everybody, I have a test sketch in which I have two PGraphics layers for drawing boxes and circles respectively. The code works as is with the default renderer, but when I change the renderer to P2D as outlined below, the sketch no longer runs:

size(500, 200,P2D);
layer_spots = createGraphics(width, height,P2D);
layer_boxes = createGraphics(width, height,P2D);

Is there any way that I can get PGraphics to work with the P2D renderer? I need to use P2D because it supports per-vertex geometry coloring (for another sketch), which is not supported in the default Java renderer.

Below is the full sketch. Hit one of [b,s,x] keys to draw boxes,circles, or to clear

spot s; // declare object spot
box b; // declare object box
PGraphics layer_spots; // layer for spots
PGraphics layer_boxes; // layer for boxes

void setup() {
  //size(500, 200);  // using the default renderer allows the code to work
  size(500, 200,P2D);
  noLoop();  // sketch will only update when user hits one of [b,s,x] keys

  //layer_spots = createGraphics(width, height); //sketch will run using default renderer for PGraphics
  layer_spots = createGraphics(width, height,P2D);
  layer_spots.beginDraw(); layer_spots.endDraw();
  //layer_boxes = createGraphics(width, height); //sketch will run using default renderer for PGraphics
  layer_boxes = createGraphics(width, height,P2D);
  layer_boxes.beginDraw(); layer_boxes.endDraw();
} // end of setup()

void draw() {
  frame.setTitle(int(frameRate) + " fps");
  background(250);
  image(layer_spots, 0, 0);
  image(layer_boxes, 0, 0);
} // end of draw()

void keyPressed() {
  if (key == 'x') {
    println ("...pressed clear!");

    layer_spots.beginDraw(); 
    layer_spots.clear();
    layer_spots.endDraw();
    layer_boxes.beginDraw();
    layer_boxes.clear();
    layer_boxes.endDraw();
    redraw();
  }

  if (key == 'b') {
    println ("...make box!");

    layer_boxes.beginDraw();
    b = new box(random(width), random(height), int(15 + random(25)), int(random(255)) );
    b.display(layer_boxes);
    layer_boxes.endDraw();
    redraw();
  }
  if (key == 's') {
    println("...make spot!");

    layer_spots.beginDraw();
    s = new spot(random(width), random(height), int(15 + random(25)), int(random(255)) );
    s.display(layer_spots);
    layer_spots.endDraw();
    redraw();
  }
} // end of keyPressed()


    //////////////classes

    class box {
      float x;
      float y;
      float side;
      int value;

      // constructor
      box (float xp, float yp, float w,int v){
        x = xp;
        y = yp;
        side = w;
        value = v;
      } // end of constructor

      void display(PGraphics pg){
        pg.fill (value);
        pg.rect (x,y,side,side); 
      }
    } // end of box

    class spot {
      float x;
      float y;
      float diameter;
      int value;

      // constructor
      spot (float xp, float yp, float diam,int v){
        x = xp;
        y = yp;
        diameter = diam;
        value = v;
      } // end of constructor

      void display(PGraphics pg){
        pg.fill (value);
        pg.ellipse (x,y,diameter,diameter); 
      }
    } // end of spot

Answers

  • My answer in the PShape always writes to main buffer? topic can be relevant, I think...

    I hope somebody with a better knowledge of OpenGL than me will step in and give more information.

  • The problem is that you cannot run OpenGL code outside of the main animation thread (which is the one that executes the draw() method).

    The event handling methods, including keyPressed(), are run on the event handling thread, so this leads to the error with P2D.

    You could do the following instead:

    void setup() {
      //size(500, 200);  // using the default renderer allows the code to work
      size(500, 200,P2D);
      noLoop();  // sketch will only update when user hits one of [b,s,x] keys
    
      //layer_spots = createGraphics(width, height); //sketch will run using default renderer for PGraphics
      layer_spots = createGraphics(width, height,P2D);
      layer_spots.beginDraw(); layer_spots.clear(); layer_spots.endDraw();
      //layer_boxes = createGraphics(width, height); //sketch will run using default renderer for PGraphics
      layer_boxes = createGraphics(width, height,P2D);
      layer_boxes.beginDraw(); layer_boxes.clear(); layer_boxes.endDraw();
    } // end of setup()
    
    void draw() {
      frame.setTitle(int(frameRate) + " fps");
    
      if (keyPressed) {
        if (key == 'x') {
          println ("...pressed clear!");
    
          layer_spots.beginDraw(); 
          layer_spots.clear();
          layer_spots.endDraw();    
          layer_boxes.beginDraw();
          layer_boxes.clear();
          layer_boxes.endDraw();
        }
    
        if (key == 'b') {
          println ("...make box!");
    
          layer_boxes.beginDraw();
          b = new box(random(width), random(height), int(15 + random(25)), int(random(255)) );
          b.display(layer_boxes);
          layer_boxes.endDraw();
        }
        if (key == 's') {
          println("...make spot!");
    
          layer_spots.beginDraw();
          s = new spot(random(width), random(height), int(15 + random(25)), int(random(255)) );
          s.display(layer_spots);
          layer_spots.endDraw();    
        }   
      } 
    
      background(250);
      image(layer_spots, 0, 0);
      image(layer_boxes, 0, 0);
    } // end of draw()
    
    void keyPressed() {
      redraw();
    } // end of keyPressed()
    

    so all the rendering happens inside draw().

  • The subtleties of Processing...Thanks codeanticode!

Sign In or Register to comment.