4

Presently I am trying to read the pixel data from the frame Buffer in order to capture the screen in IOS. GlreadPixels command works fine when using the following code to setup frame buffer :-

//buffers
// Create a depth buffer that has the same size as the color buffer.
glGenRenderbuffersOES(1, &m_depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT24_OES, width, height);

// Create the framebuffer object.

glGenFramebuffersOES(1, &framebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES,
                             GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES,
                             GL_RENDERBUFFER_OES, m_depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer);

but when I use depth buffer and colorbuffer for Multi-Sampling glreadpixels() don't capture any pixel data as with earlier code ....for multi-sampling I use following code :-

glGenFramebuffersOES(1, &sampleFramebuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer);

//GLuint sampleColorRenderbuffer;
glGenRenderbuffersOES(1, &sampleColorRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleColorRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer);

//glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_RGBA8_OES, width, height);
//glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, sampleColorRenderbuffer);

GLuint sampleDepthRenderbuffer;
glGenRenderbuffersOES(1, &sampleDepthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, sampleDepthRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER_OES, 4, GL_DEPTH_COMPONENT24_OES, width, height);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, sampleDepthRenderbuffer);
//glBindRenderbufferOES(GL_RENDERBUFFER_OES,sampleColorRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, m_colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, sampleFramebuffer);

I use the follwing code to read pixel data :-

CGRect screenBounds = [[UIScreen mainScreen] bounds];

int backingWidth = screenBounds.size.width;
int backingHeight =screenBounds.size.height;

glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
NSInteger myDataLength = backingWidth * backingHeight * 4;

buffer= (GLuint *) malloc(myDataLength);
glReadPixels(0, 0, backingWidth, backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

Any idea how to capture correct pixel data with multi-Sampling technique....or Am I doing something wrong? Please guide me in right direction. Thanks

brainjam
  • 18,863
  • 8
  • 57
  • 82
Tornado
  • 1,069
  • 12
  • 28

1 Answers1

5

When using multisampled FBOs you cannot just read the sample buffer (as it doesn't contain simple pixels). You first need to resolve the sample buffers into a single buffer.

You do this by creating another non-multisampled FBO (let's call it resultFramebuffer) with the neccessary renderbuffer storage you want to read and then calling:

glBindFramebuffer(GL_READ_FRAMEBUFFER, sampleFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resultFramebuffer);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);

And then you read from the result buffer (of course the actual constant and function names may contain OES or APPLE). If you don't need the final depth values, the result buffer doesn't need a depth renderbuffer.

EDIT: As you wrote in your comment and what I searched, there is a dedicated function glResolveMultisampleFramebufferAPPLE you have to use instead of glBlitFramebuffer. The rest stays the same.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • hey first glBlitFramebuffer() is not present in the OES ...also glreadpixels() read data from the framebuffer only...i found glreadbuffer() for reading the non fbo but it is also not available in OES – Tornado Jul 30 '11 at 05:27
  • @Tornado First, if multisampled FBOs are supported there also needs to be support for `glBlitFramebuffer`, otherwise multisampled FBOs are just useless, as then you cannot resolve the sample buffers like said above (maybe it's an APPLE extension, like the multisampled FBOs?). If `glReadPixels` cannot read from an FBO, then how does your first code example work? If you don't want to read from the FBO, then where's the problem? You should explain, what your FBO is for, if you don't want to read its data. – Christian Rau Jul 30 '11 at 10:59
  • hmmm i will check the glBlitFramebuffer() for apple again..actually m new to OpenGl part....regarding the glreadpixels() i was saying it only reads from an FBO .. i was concerned about reading the pixel data from your resultFramebuffer ... hey i will check the whole thing again talk u soon ...thanks for explaining – Tornado Jul 30 '11 at 18:09
  • @Tornado You just need to bind the `resultFramebuffer` (which is a standard non-multisampled FBO, like in your first example) as the current FBO (using `glBindFramebuffer`) and then you can read from it, like you did in your first non-multisampled example. The only thing you do is copy the multisampled FBO into another FBO and read from this one. – Christian Rau Jul 30 '11 at 23:53
  • found that there's function named glResolveMultisampleFramebufferAPPLE() that is used for blitting purpose ....what m i doing now is creating a multi-sampled FBO named sampleframebuffer and then bind it as current FBO then i used glBindFramebufferOES(GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer); glBindFramebufferOES(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer); glResolveMultisampleFramebufferAPPLE(); glBindFramebufferOES(GL_FRAMEBUFFER_OES, framebuffer); code – Tornado Aug 01 '11 at 12:27
  • @Tornado Sounds reasonable. Sorry, I didn't know there is a dedicated function for multisample resolving in ES. – Christian Rau Aug 01 '11 at 12:40
  • even i am not sure this will work or not but gonna try this....but in Opengl ES there's no such function glBlitFramebuffer().... – Tornado Aug 01 '11 at 12:46
  • hey it worked but FPS got down from 30 to 2-3....does glreadpixels() drop down the FPS ? – Tornado Aug 02 '11 at 07:12
  • @Tornado Maybe, remember that you are copying a large chunk of memory from GPU to CPU memory (although I'm not that sure about the hardware architecture of an iDevice, I'm sure there has to be a copy). But if it ran at 30 FPS in the non-multisampled example WITH `glReadPixels`, then this would be a bit much of a performance drop. – Christian Rau Aug 02 '11 at 11:39
  • i checked the fps with non-multisampled code with glReadPixels its also very less 3-4 fps...i hadn't checked that earlier as i was more concerned with getting the pixel data with multi-sampling techinique...any idea how can i increase the FPS ..20 fps would be fine enough..!! – Tornado Aug 02 '11 at 11:56
  • @Tornado I don't know if you really need to capture every frame. A one-time performance drop would be acceptable. Otherwise doing the reading asynchronously using PBOs might help, although I don't know if it is supported in ES or if the iHardware let's you profit from it. – Christian Rau Aug 02 '11 at 12:23
  • No PBO support in ios(apple)..already checked...hey does synchronous reading from framebuffer will help increasing the performance ? i can try that but dont know how...let me do R&D over this – Tornado Aug 02 '11 at 12:34