1

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

问题在于示例代码中的 OpenGL 上下文版本相当旧(Version: 2.1 INTEL-10.22.29),而我的项目的 OpenGL 上下文版本version: 4.1 INTEL-10.22.29不再支持扩展GL_ARB_pixel_buffer_object

我已使用 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
4

1 回答 1

1

编辑

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

首先,我的眼睛指出了一个来自 的演员表(void*)。不,这不可能,memcpy() 会再次施放它。
然后我到了glTextImage2D。并且错误地认为它不能和PBO一起使用(dam,我因为匆忙而犯了太多错误。我必须放松......)。谢谢Nico Bolas纠正了我。

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

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

如果在指定纹理图像时将非零命名缓冲区对象绑定到 GL_PIXEL_UNPACK_BUFFER 目标(请参阅 glBindBuffer),则数据将被视为缓冲区对象数据存储中的字节偏移量。

老的:

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

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

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

于 2017-03-23T12:02:55.440 回答