Drawing a shader generated PGraphics onto a non OpenGL PGraphics object

Hello everyone !

I am currently developping quite a big project, and for simplicity I have chosen to use Processing as a graphical engine. I am coding with Eclipse Neon.

The issue is that I have developped GLSL Fragment shaders to accelerate image processing, and then apply them to a P2D PGraphics object (which works fine), the general PApplet is also P2D but there are a few in-between PGraphics objects that aren’t P2D and that I can’t make P2D since for some reason this messes up the whole look of the project (and this represent quite a substantial amount of time).

So basically, I run a shader onto a P2D PGraphics object and I then want to draw the resulting image onto a non OpenGL PGraphics object, and for some reason this doesn’t work, even though I assumed that after rendering the shader on the first PGraphics object, I would simply have an image I could render elsewhere…

Thank you for your help !

Maybe transferring the contents of pixels[] to another’s via arrayCopy() might work:


@GoToLoop Thanks for your reply !

So I’ve tried adapting my code the following way :


	public void render(){
		this.image.beginDraw();
		this.image.filter(alphaOverlayShader);
		this.image.endDraw();
	}
	
	public PGraphics getImage() {
		PGraphics out = context.createGraphics(w, h);
		this.image.beginDraw();
		this.image.loadPixels();
		out.beginDraw();
		out.loadPixels();
		PApplet.arrayCopy(this.image.pixels, out.pixels);
		out.updatePixels();
		out.endDraw();
		this.image.updatePixels();
		this.image.endDraw();
		return out;
	}

But this still doesn’t work, or at least I am still doing something wrong…

Merely stating it doesn’t work w/o describing exactly what happened doesn’t help.

And btW, we just use updatePixels() and/or loadPixels() for pixels[].

Methods beginDraw() & endDraw() shouldn’t be used on that context.

And given you’re createGraphics() every time rather than using an existing 1 you can instead clone a PGraphics as a PImage calling method get():

Yeah you’re right. So basically the sketch runs as if the shader wasn’t applied (this shader doesn’t modify the current pixels array, but it actually draws over it, in this case a checkerboard pattern) and the result here is that it’s as if this image is transparent.

Oh I didn’t know that, I sometimes run into NullPointerExceptions when loadPixels() is called without beginDraw() before but I think that this is due to the fact there was actually nothing drawn onto the PGraphics beforehand.

This is also one of the things I tried before. This is why I tried recreating my issue on a simpler sketch :

PGraphics inBetween;
PGraphics shadedLayer;

PImage image;

void setup(){
  size(1280, 720, P2D);
  
  inBetween = createGraphics(1280, 720);
  
  inBetween.beginDraw();
  inBetween.background(255);
  inBetween.endDraw();
  
  shadedLayer = createGraphics(1280, 720, P2D);
  
  image = loadImage("image.png");
}

void draw(){
  shadeLayer();
  
  method1();
  //method2();
  //method3();
  //method4();
  
  image(inBetween, 0, 0);
}

void method1(){
  inBetween.beginDraw();
  inBetween.image(shadedLayer, 0, 0);
  inBetween.endDraw();
}

void method2(){
  shadedLayer.loadPixels();
  inBetween.loadPixels();
  arrayCopy(shadedLayer.pixels, inBetween.pixels);
  inBetween.updatePixels();
  shadedLayer.updatePixels();
}

void method3(){
  inBetween.beginDraw();
  inBetween.image(shadedLayer.get(), 0, 0);
  inBetween.endDraw();
}

void method4(){
  shadedLayer.loadPixels();
  inBetween.loadPixels();
  for(int x = 0; x < shadedLayer.width; x++){
    for(int y = 0; y < shadedLayer.height; y++){
      inBetween.pixels[x + y * inBetween.width] = shadedLayer.pixels[x + y * shadedLayer.width];
    }
  }
  inBetween.updatePixels();
  shadedLayer.updatePixels();
}

void shadeLayer(){
  shadedLayer.beginDraw();
  shadedLayer.image(image, 0, 0);
  shadedLayer.endDraw();
  shadedLayer.filter(BLUR, 10);
}

But in this case all methods seem to work so… perhaps my issue isn’t even where I thought it was…

Thanks for your help @GoToLoop by the way.

I know nothing about Processing’s shader implementation.
I guess it’s tightly bound to a PGraphics and can’t be transferred.

I am writing this answer to close subject : apparently to apply a shader, something has to already have been drawn onto the PGraphics object, weither it is P2D or not. The simple fix was to apply a background color before applying the shader, weither it is a modifyer fragment shader or a “rendering” shader that draws “on top” of the previous pixels.

1 Like