使用像素缓冲对象将纹理从GPU复制到CPU

时间:2016-11-25 22:05:47

标签: opengl textures pbo

我是OpenGL的新手,目前正在将2D纹理的内容复制回CPU内存,如下所示:

std::vector<unsigned char> frame-data(width * height * 4);
glBindTexture(GL_TEXTURE_2D, tid);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &frame_data[0]);                 

我注意到这种情况非常缓慢,我开始阅读关于公益组织的事情并想到试图看看这是否让事情变得更加顺畅。所以我按如下方式创建了PBO:

GLuint  pbo;
glGenBuffers(1, &pbo);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, width*height* 4, NULL, GL_STREAM_READ); 

我认为以上几行只需执行一次即可初始化PBO。

我现在的问题是如何实际将数据从纹理映射到此PBO对象?我之后知道我需要拨打glMapBuffer,但我不知道如何将这个纹理附加到我的PBO。

1 个答案:

答案 0 :(得分:4)

当缓冲区绑定到GL_PIXEL_PACK_BUFFER时,纹理下载函数会将其最后data参数解释为不作为客户端内存中的指针,而是作为偏移量以字节为单位当前绑定的像素包缓冲区的开头。

换句话说,假设已创建的纹理和已创建的适当大小的缓冲区:

// bind PBO
glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer); 

// bind texture
glBindTexture(GL_TEXTURE_2D, texture);

// transfer texture into PBO
glGetTexImage(GL_TEXTURE_2D,                 
              level,
              pixelformat,
              pixeltype,
              (GLvoid*)0 // offset in bytes into "buffer",
                         // not pointer to client memory!
             ); 

传输完成后,您可以读取缓冲区中包含的纹理数据,例如通过映射它。

请注意,如果您立即映射缓冲区,您将无法从PBO获得任何好处。这种方法的重点是让您通过提交其他命令让GPU保持忙碌而异步进行传输。

您可以通过使用同步呼叫(例如转接呼叫后插入sync objects)来了解传输何时完成。

相关问题