Draw into ofImage as you would FBO

Hello,
I’d like to draw generative visuals into a “sub window” and then do some pixel-level analyzation on the content of that sub window. I’ve done this by drawing into an FBO, then using the ReadToPixels(ofPixels pix) function. This works, but is very slow. Is there a way to draw directly into an ofPixel or ofImage type, for quicker access to pixels?

Psuedo code that should be replaced:

fbo.begin();
drawThings();
fbo.end();

fbo.readToPixels(pix);

...do stuff with pix

In short… can the fbo in that code be replaced with an ofImage or ofPixels?

Thanks,
Jake

I believe that’s not possible. Most you can do is use a PBO (Pixel buffer object) to make an asynchronous texture download from GPU. Here’s an addon that I found yesterday, haven’t tried it but it looks promising.

There’s also this one, I actually wanted to try them out so keep me updated if you succeed! :smile:

Note: from what I’ve read PBOs are actually not at all similar to FBOs, they are actually more similar to VBOs but work with pixels instead of vertices.

Can you can pass the fbo as a texture to a shader? And do image processing in the shader. It will probably be faster. Here is an example of a Gaussian blur

@chuckleplant and @Ahbee, thanks very much. ofxFastFBOReader works well for me. I haven’t tried ofxPBO yet, although I will try this evening. It turns out that my biggest issue was not reading from FBO, but a forgotten to remove an unwieldy ofLog() statement that was trying to write 5000 times a frame.

Regardless, ofxFastFBOReader is working well. One thing I found was that any graphics being called within the fbo need to be within the fbo and not within another function. In other words:

fbo.begin();
    ofClear(0);
    drawStuff();
fbo.end();

drawStuff(){
    ofSetColor(0);
    ofCircle(100,100,100);
}

results in all pixels values being 0, when sampled through ofPixel.getColor or whatever. Whereas:

fbo.begin();
    ofClear(0);
    ofSetColor(0);
    ofCircle(100,100,100);
fbo.end();

works just fine.

just to say that ofxPBO right now only does the opposite, upload to a texture through a PBO instead of read back from it

just to add I’ve used libraries in the past for drawing to an image / pixels – opencv has drawing functionality (http://docs.opencv.org/doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.html), see also

1 Like

actually cairo is included in OF and you can render directly to an ofPixels using the cairo renderer like:

shared_ptr<ofCairoRenderer> renderer(new ofCairoRenderer);
renderer->setupMemoryOnly(ofCairoRenderer::IMAGE);
ofSetCurrentRenderer(renderer);
//draw
ofPixels & pixels = renderer->getImageSurfacePixels();

but cairo is only good at rendering in 2d, there’s some options to draw in 3d in the renderer, but is really limited so if you want to do 3d it’s better to just use the gpu and download through a PBO

3 Likes