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

Luc*_*uca 3 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]);                 
Run Code Online (Sandbox Code Playgroud)

我注意到这很慢,我开始阅读有关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); 
Run Code Online (Sandbox Code Playgroud)

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

我的问题是,现在我该如何实际将纹理中的数据映射到该PBO对象?我知道之后需要打电话给glMapBuffer我,但是我不确定如何将此纹理附加到我的PBO。

pep*_*ppe 6

当绑定缓冲区时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!
             ); 
Run Code Online (Sandbox Code Playgroud)

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

请注意,如果您立即映射缓冲区,则不会从PBO中获得任何好处。这种方法的全部目的是让传输异步进行,同时通过提交其他命令使GPU保持繁忙。

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