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

我注意到这非常缓慢,我开始阅读有关 PBO 的内容,并想看看这是否能让事情变得更顺利。因此,我按如下方式创建 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。

4

1 回答 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 保持忙碌。

您可以使用同步调用知道传输何时完成,例如在传输调用之后插入的同步对象。

于 2016-11-25T22:21:12.880 回答