ofFbo getPixels

one of my favorite things about some of the old ofxFBOTexture addons was that you could getPixels().

The new FBO in upcoming 007 doesn’t have this feature yet, so I was trying to add it in.

here’s my stab:

  
  
unsigned char* ofFbo::getPixels()  
{  
	  
	updateTexture(0); //may not be necessary?  
	  
	begin();  
  
	glReadBuffer(GL_COLOR_ATTACHMENT0);  
	glReadPixels(0, 0, settings.width, settings.height, settings.internalformat, GL_UNSIGNED_BYTE, pixels);  
	  
	end();    
  
	return pixels;  
}  
  
  

This only works when multisampling is disabled. the previous version of ofxFBOTexture I was working with it would work with or without multisampling. Also, the only major difference I can see is the use of GL_COLOR_ATTACHMENT0 (ofFbo) instead of GL_COLOR_ATTACHMENT0_EXT (ofxFBOTexture)

Anyone have an idea on how to change it to get it to save the multi-sampled pixels out?

thanks!

got it!

  
  
unsigned char* ofFbo::getPixels(int attachmentPoint)  
{  
	if(fbo != fboTextures) {  
		glGetIntegerv( GL_FRAMEBUFFER_BINDING, &savedFramebuffer );  
		  
		// save current drawbuffer  
		glPushAttrib(GL_COLOR_BUFFER_BIT);  
		  
		// save current readbuffer  
		GLint readBuffer;  
		glGetIntegerv(GL_READ_BUFFER, &readBuffer);  
		  
		glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);  
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboTextures);  
		glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);  
		glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);  
#ifndef TARGET_OPENGLES  
		glBlitFramebuffer(0, 0, settings.width, settings.height, 0, 0, settings.width, settings.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);  
#else  
		glRenderbufferStorageMultisampleAPPLE();	// untested  
#endif  
		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboTextures);  
  
		glReadPixels(0, 0, settings.width, settings.height, settings.internalformat, GL_UNSIGNED_BYTE, pixels);  
		  
		glBindFramebuffer(GL_READ_FRAMEBUFFER, savedFramebuffer);  
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, savedFramebuffer);  
		glBindFramebuffer( GL_FRAMEBUFFER, savedFramebuffer );  
		  
		// restore readbuffer  
		glReadBuffer(readBuffer);  
		  
		// restore drawbuffer  
		glPopAttrib();  
		  
	}  
	  
	   
	return pixels;  
}  
  
  

Hey thats awesome that you got it working with multisampled textures!

With the new 007 we’re really trying to modularize all functionality, which is why ofFbo doesn’t have a getPixels(); Instead this will probably be a global function, or method of ofTexture, or method of ofPixels - since the act of reading from a texture into main memory isn’t really the responsibility of an fbo.

E.g. it might be something like:

ofReadPixels(const ofTexture& srcTexture, ofPixels &dstPixels);

So to read from an fbo you would write

ofReadPixels(myFbo.getTexture(), myPixels);

hope that makes sense

yeah totally makes sense -

this was quick for the time being, but if i get a chance I’ll try to roll it into a function like you mention there and I"ll post it - I can see why that way is a lot more flexible.

Thanks for the pointer,

James, Is there a version of getPixels() that works with 0062 ofxFBOTexture ?

The version of ofxFBOTexture I have doesn’t have this function in, where did you get yours from?

Do you know what would also be awesome, like in openCV, setROI, on fbo and any textures. I don’t know how hard that would be.

fbo.setRoi(50, 60, 320, 240);
pixels = fbo.getPixels();
fbo.resetRoi();

Hi obviousjim, know this thread is kinda old but i think the functionality is still very useful. I have copy and pasted your getPixels() function into the ofFbo code but cant seem to get it to work.

Its complaining about pixels not being declared in the scope. Have you declared this in the ofFbo.h file. is it just an ofPixel? cheers, really would love this function to work. would save me some epic headaches.

Hi, I’m doing this with readToPixels()

http://www.openframeworks.cc/documentation/gl/ofFbo.html#readToPixels

Cool, yeah i dug in and looked into the glGetPixels call that is happening and realised that its going to eat a few frames per second each time this call is made. Was kinda dreaming hoping I could pass endless copies around with no performance hit. Thanks.

yeah there’s really no way around that, since the computation image is happening on the gpu.

In practice though I’d be curious to see how big of an FBO you can draw and read back from and still maintain a solid 30 or 60 fps, worth doing a small test

yeah, when playing a 800x600 video back i get 1000fps. As soon as I do just 1 ->

fbo.readToPixels(img.getPixelsRef());
img.update();

it goes down to 500fps…