通过 PBO 将纹理上传到 GPU 不起作用(OpenGL 4.1 版)

Uploading texture to GPU by PBO not working (OpenGL version 4.1)

我已经阅读了著名的教程OpenGL Pixel Buffer Object (PBO)。我在我的计算机上测试了示例代码并且它可以工作(尽管启用了 PBO,它的性能没有提高但至少它可以正确呈现)。

问题在于示例代码中的 OpenGL 上下文版本很旧 (Version: 2.1 INTEL-10.22.29),而我的项目的 OpenGL 上下文版本是 version: 4.1 INTEL-10.22.29,不支持扩展 [=15] =] 不再。

我已经阅读了这个Map and fill texture using PBO (OpenGL 3.3),所以我将我的代码更改为:

// generating buffers and textures
glGenVertexArrays(1, &_vertex_array);
glBindVertexArray(_vertex_array);

glGenBuffers(1, &_vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs_data), vertexs_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

glGenBuffers(1, &_uv_buffer);
glBindBuffer(GL_ARRAY_BUFFER, _uv_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(uvs_data), uvs_data, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

glGenBuffers(1, &_pixel_buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pixel_buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);

glGenTextures(1, &_texture);
glBindTexture(GL_TEXTURE_2D, _texture);

和渲染循环:

glBindTexture(GL_TEXTURE_2D, _texture);
// ======== start process PBO =========
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pixel_buffer);
glBufferData(GL_PIXEL_UNPACK_BUFFER, DATA_SIZE, 0, GL_STREAM_DRAW);
GLubyte *ptr = (GLubyte*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
if( ptr != nullptr )
{
    cout<<"map pixel buffer success"<<endl;
    memcpy(ptr, DATA_SIZE, data );
    glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);   
}
// ========= end process PBO ==========

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
             _window_width, _window_height,
             0, GL_RGB,
             GL_UNSIGNED_BYTE, data
);
glGenerateMipmap(GL_TEXTURE_2D);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
// draw commands goes here

我的代码只是渲染一个单一的颜色纹理,如果我评论从 ======== start process PBO ================== end process PBO ========== 的块,那么一切顺利,但是对于这个块,它只是失败了,我得到的只是黑屏。我已经检查过 glMapBuffer 是否正常工作并且我成功地将纹理数据写入 ptr 指向的内存(通过打印出它的值来检查),但我不明白为什么我没有得到我的预期结果。

提前致谢。

我的环境:

OS: macOS sierra 10.12.3 (16D32)
Graphics: Intel Iris Graphics 6100 1536 MB

编辑

此答案已被接受,但需要修改。他们来了:

首先我的眼睛指出了来自 (void*) 的投射。不,这不可能,memcpy() 会再次转换它。
然后我到了glTextImage2D。并且误以为它不能和PBO一起使用(妈的,我太仓促失误了。我必须放松......)。谢谢 Nico Bolas 纠正了我。

然后,再慢慢看,只是在glTextImage2D中没有使用指向客户端数据的指针,将data改为0

文档清楚地说明了最后一个参数:

If a non-zero named buffer object is bound to the GL_PIXEL_UNPACK_BUFFER target (see glBindBuffer) while a texture image is specified, data is treated as a byte offset into the buffer object's data store.

旧:

GLubyte *ptr = (GLubyte*) glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);
您正在退化返回的指针。如果你只在 memcpy() 命令中使用它,让它成为 (void*)
void* ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_READ_WRITE);

编辑:(在我再次阅读你想从 PBO 复制到纹理之后)

glTextImage2D() 从指针 data 读取,而 glTexSubImage2D() 可用于从绑定的 PBO 读取。在最后一种情况下,glTexSubImage2D() 的最后一个参数是该 PBO 的偏移量(如果不需要偏移量则为 0)。