I'm trying to render frames from a Processing sketch in a separate thread.
Processing has a loadPixels() function. The catch is with the OpenGL renderer (P2D
or P3D
in Processing.): PGraphicsOpenGL loadPixels()
Here's my example sketch:
void setup(){
size(300,300,P2D);
noFill();
background(255);
rectMode(CENTER);
stroke(0,32);
smooth(8);
// instantiate and start rendering thread
new PNGRenderer(this);
}
void draw(){
// draw moving shapes
translate(width * 0.5, height * 0.5);
rotate(sin(frameCount * 0.075));
scale(sin(frameCount * 0.01));
translate(cos(frameCount * 0.01) * width * 0.1,sin(frameCount * 0.01) * height * 0.1);
rect(0,0,width * .9,height * .9);
}
public class PNGRenderer implements Runnable{
PApplet parent;
PImage frame;
boolean shouldSave = false;
int savedFrameCount;
boolean isRunning = true;
PNGRenderer(PApplet parent){
this.parent = parent;
this.parent.registerMethod("draw",this);
frame = createImage(parent.width,parent.height,ARGB);
frame.loadPixels();
Thread renderThread = new Thread(this);
renderThread.setName("Renderer-Thread");
renderThread.start();
}
public void draw(){
// all is well if I sample pixels in the same OpenGL thread
//parent.loadPixels();
shouldSave = true;
}
synchronized void sampleAndSavePixels(){
if(shouldSave){
// program crashes if I try to save in a separate thread
parent.loadPixels();
arrayCopy(parent.pixels,frame.pixels);
frame.updatePixels();
frame.save(dataPath("frames/frame_"+nf(savedFrameCount++,4)+".png"));
println("saved frame",savedFrameCount);
shouldSave = false;
}
}
public void run(){
while(isRunning){
sampleAndSavePixels();
}
}
}
As far I understand (and I'm not an OpenGL wizard by far) reading pixels needs to be done in the same OpenGL thread. This is a slowdown I'm trying to avoid.
I did look a similar threads on stackoverflow and other forums:
As far a I understand from the above I need to create a separate OpenGL context in my renderer thread and share the texture/buffer from Processing's OpenGL thread to mine. I'm unsure on the syntax at the moment.
It might be a case of RTFM but can you please point me in the direction in terms of Java OpenGL reading pixels in a separate thread (can be plain Java, not necessarily using Processing)?
The OpenGL Context is thread-local. The context has to be made "current" in the thread. Different threads can use the same context, but a context cannot be current in multiple threads at the same time.
You've to ensure that the threads don't use the same context at the same time. Of course you can create different contexts for different threads and share one context to the other.
See OPENGL MULTI-CONTEXT
But note, the GPU already operates parallel. There is no benefit of using the 1 GPU in different threads. The GPU can only handle the instructions of 1 thread at once. Of course each stage of the Rendering Pipeline process the vertices, fragments, etc. parallel