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

时间:2011-05-26 19:54:47

标签: opengl framebuffer fbo glreadpixels pbo

我可以使用像素缓冲区对象(PBO)直接从FBO读取像素值(即使用glReadPixels)(即当FBO仍然连接时)?

如果是,

  1. PBO与FBO一起使用有哪些优点和缺点?
  2. 以下代码有什么问题
  3. {

    //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 个答案:

答案 0 :(得分:10)

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

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

答案 1 :(得分:8)

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

回答1:

对于同步阅读:没有PBO的'glReadPixels'很快。

对于异步读取:'glReadPixels'具有2 / n PBO更好 - 一个用于通过GPU读取帧缓冲到PBO(n)的像素和另一个PBO(n + 1)来处理像素中央处理器。然而,快速没有被授予,这是问题和设计的特点。

回答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);