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

Rud*_*udi 12 opengl fbo framebuffer glreadpixels pbo

我可以使用像素缓冲区对象(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
Run Code Online (Sandbox Code Playgroud)

以下glReadPixels工作正常

glReadPixels(0, 0, screenWidth, screenHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE,  (uchar*)cvimg->imageData);
Run Code Online (Sandbox Code Playgroud)

以下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
Run Code Online (Sandbox Code Playgroud)

Chr*_*ica 10

当使用PBO作为目标时,glReadPixels您必须指定缓冲区中的字节偏移量(0我猜),而不是(uchar*)cvimg->imageData目标地址.它类似于在glVertexPointer使用VBO时使用缓冲区偏移量.

编辑:当PBO绑定到时GL_PIXEL_PACK_BUFFER,最后一个参数glReadPixels不被视为指向系统内存的指针,而是作为绑定缓冲区内存的字节偏移量.因此,将像素写入缓冲区只需传递0(将它们写入缓冲存储器的开头).然后,您可以通过以下方式访问缓冲存储器(以获取像素)glMapBuffer.您在评论中提供的示例链接也是这样做,只是广泛阅读.我还建议阅读他们在开始时提到的关于顶点缓冲对象的部分,因为这些对于理解缓冲对象是有意义的.


Rud*_*udi 9

是的,我们可以一起使用FBO和PBO.

答案1:

对于同步读取:没有PBO的'glReadPixels'很快.

对于异步读取:具有2/n PBO的'glReadPixels'更好 - 一个用于通过GPU读取帧缓冲到PBO(n)的像素,而另一个PBO(n + 1)用于通过CPU处理像素.然而,快速不被授予,它是问题和设计spefic.

答案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);
Run Code Online (Sandbox Code Playgroud)