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

6

我是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]);                 

我注意到这个程序运行得相当缓慢,于是我开始了解PBOs,并尝试创建一个以期使程序更加流畅。因此,我按照以下方式创建了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个回答

9
当一个缓冲区被绑定到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保持繁忙状态。
您可以使用同步调用(例如传输调用后插入的同步对象)来了解传输何时完成。

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