Run shader multiple times on an image?


#1

I’d like to run a single shader several times on an image (to build up the effect), but if I stick the basic shader code in a for loop it doesn’t seem to work:

for (int i=0; i<10; i++) {
  shader(doSomething);
  image(img, 0,0);
}

Is there a way to do this?

(I can think of hacks that would use the draw() loop but they’re all ugly and I’d like to do this realtime with a webcam anyway.)


#2

Hi,

The main problem here is that you cannot read and write into a texture at the same time, so each time you do an iteration your shader use the original image not the modified one at the last iteration. In order to do that you will need to use two offscreen buffer (PGraphics) and swapping theme at each iteration. So at each new iteration you will be using the previous modified image.

Here a sample code :

//Here we using 2 PGraphics in order to write your modified image into a offscreen buffer
PGraphics buffer1 = createGraphics(img.width, img.height, P2D);
PGraphics buffer2 = createGraphics(img.width, img.height, P2D);

buffer2.beginDraw();
buffer2.image(img, 0, 0);
buffer2.endDraw();

for(int i=0; i<10; i++){
    //apply your effect on an offscreen buffer in order to kept it and use it a the next iteration
    buffer1.beginDraw();
    buffer1.shader(doSomething);
    buffer1.image(buffer2, 0, 0);
    buffer1.endDraw();
    
    //then swap the buffer for the next iteration
    PGraphics tmp = buffer2;
    buffer2 = buffer1;
    buffer1 = tmp;
  }

image(buffer1, 0, 0);

#3

Thanks alexr4, that makes sense. I found a simpler way: turns out you can pass a shader to the filter() command!

PGraphics pg;
PShader shader;

void setup() {
  size(1280,720, P2D);
  pg = createGraphics(width, height, P2D);
  shader = loadShader("myShader.glsl");
}

void draw() {
  pg.beginDraw();
  // do something, then run the shader 10 times
  for (int i=0; i<10; i++) {
    pg.filter(shader);
  }
  pg.endDraw();
  image(pg, 0,0);
}

#4

Sure you can do it using filter method.

I found out the filter method quite slow if you are using larges images or lot of iteration on the main surface (g) because it involve using PImage.get() which can be a lot of computation. But in your case your using on PGraphics and for 10 iteration this might work well :wink: