使用像素缓冲对象(PBO)从帧缓冲对象(FBO)中读取像素值

13

我能否使用像素缓冲对象(PBO)直接从帧缓冲对象(FBO)读取像素值(即使用glReadPixels),而 FBO 仍然被附加?

如果可以,

  1. PBO 与 FBO 结合使用的优缺点是什么?
  2. 以下代码有什么问题?

{

//DATA_SIZE = WIDTH * HEIGHT * 3 (BECAUSE I AM USING 3 CHANNELS ONLY)
// FBO and PBO status is good
.
.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboId);
//Draw the objects

以下 glReadPixels 的操作正常

glReadPixels(0, 0, screenWidth, screenHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE,  (uchar*)cvimg->imageData);

以下的glReadPixels不起作用:(

glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
//yes glWriteBuffer has also same target and I also checked with every possible values
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); 
glReadPixels(0, 0, screenWidth, screenHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, (uchar*)cvimg->imageData);
.
.
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); //back to window framebuffer
2个回答

11

使用PBO作为glReadPixels的目标时,您需要指定一个字节偏移量作为缓冲区的目标地址(我想是0),而不是(uchar*)cvimg->imageData。这类似于在使用VBO时在glVertexPointer中使用缓冲区偏移量。

编辑:当将PBO绑定到GL_PIXEL_PACK_BUFFER时,glReadPixels的最后一个参数不再被视为指向系统内存的指针,而是被视为绑定缓冲区内存中的字节偏移量。因此,要将像素写入缓冲区,请传递0(将它们写入缓冲区内存的起始位置)。然后,您可以通过glMapBuffer访问缓冲区内存(以获取像素)。您提供的评论中的示例链接也是如此,只需详细阅读。我还建议阅读他们在开头提到的关于顶点缓冲对象的部分,因为这些是理解缓冲区对象的基础。


我不明白,请您能否提供一个可用的示例代码?因为在“glReadPixels”中没有提供偏移量的选项。而且,这个示例并没有使用您提到的任何东西,但仅使用PBO就可以正常工作。 - Rudi
@Rudi希望您在尝试写入之前绑定了PBO。 - Christian Rau

9
是的,我们可以同时使用FBO和PBO。
答案1:
对于同步读取:没有PBO的'glReadPixels'速度很快。
对于异步读取:使用2/n个PBO的'glReadPixels'更好-一个用于由GPU从帧缓冲区读取像素到PBO(n),另一个PBO(n+1)用于由CPU处理像素。然而,速度不保证,这是问题和设计特定的。
答案2:
Christian Rau的解释是正确的,修订后的代码如下。
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pboId);
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
//glReadBuffer(GL_DEPTH_ATTACHMENT_EXT);

glReadPixels(0, 0, screenWidth, screenHeight, GL_BGR, GL_UNSIGNED_BYTE, 0);

//GLubyte* src = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
//OR
cvimg->imageData = (char*) glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
if(cvimg_predict_contour->imageData)
{
  //Process src OR cvim->imageData
  glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);     // release pointer to the mapped buffer
}
glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接