Slow performance when passing multiple PGraphics into each other as shader textures

Hey all,
I’m attempting to use multiple pgraphics objects for my code. I want to draw some shapes on the first pgraphics. I then want to use a shader on the second pgraphics object to apply blur to the red channel and to generate a feedback loop by saving the previous version of this pgraphics and feeding it in as a texture. Finally, I want to feed the output of the second pgraphics into the third pgraphics so that I can apply some color transformations.

This process seems to be tanking my framerate. I’ve written a much simpler piece of code that uses 3 pgraphics objects and shaders. Adding the second pgraphics takes the framerate from 60 to 30, and adding the third takes it from 30 to 20. Any thoughts on how this can be optimized?

PDE

PGraphics canvas0;
PGraphics canvas1;
PGraphics canvas2;
PGraphics canvas3;

PShader testShader;

void setup() {
 size(1000,1000,P2D);
 canvas0 = createGraphics(1000,1000,P2D);
 canvas1 = createGraphics(1000,1000,P2D);
 canvas2 = createGraphics(1000,1000,P2D);
 canvas3 = createGraphics(1000,1000,P2D);

 testShader = loadShader("test.frag");
}


void draw() {



  canvas0.beginDraw();
  canvas0.blendMode(REPLACE);
  canvas0.fill(0);
  canvas0.rect(0,0,width,height);
  canvas0.blendMode(ADD);
  canvas0.fill(255,0,0);
  canvas0.rect(0,0,750,750);
  canvas0.fill(0,255,0);
  canvas0.rect(250,250,1000,1000);
  canvas0.endDraw();

  canvas1.beginDraw();
  canvas1.shader(testShader);
  testShader.set("u_canvas",canvas0.get());
  canvas1.fill(0);
  canvas1.rect(0,0,width,height);
  canvas1.endDraw();

  canvas2.beginDraw();
  canvas2.shader(testShader);
  testShader.set("u_canvas",canvas1.get());
  canvas2.fill(0);
  canvas2.rect(0,0,width,height);
  canvas2.endDraw();

  image(canvas2,0,0);
  text(frameRate,10,10);
}

fragment shader

        #ifdef GL_ES
        precision mediump float;
        #endif

        uniform vec2 u_resolution;
        uniform sampler2D u_canvas;



        void main() {
            vec2 st = gl_FragCoord.xy/u_resolution.xy;
            gl_FragColor =  texture2D(u_canvas, st);
        }

1 Like

Update: I got some help from user neilcsmith in another thread! calling .get() on PGraphics options brings the data back to the cpu, which is slow. I can pass the PGraphics objects directly into the shader and get much better performance.

This doesn’t totally solve my issue with keeping the previous version of one of the PGraphics objects so that I can use it for visual feedback, but I also didn’t represent that in the sample code above. I’ll continue to chip away at that problem.

2 Likes

One again, user neilcsmith has helped me understand how I can optimize my code. I was still using .get() to save a PImage of the previous frame so that I could generate feedback. It turns out this is completely unnecessary. My 14 fps code now runs at 60fps because I have cut the use of .get() when passing images into shaders and when converting PGraphics to PImage.