我已经阅读了着名的教程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
更多。
我已阅读此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
答案 0 :(得分:1)
此答案已被接受,但需要修改。他们来了:
首先,我的眼睛指出了来自(void*)
的演员。不,这不可能,memcpy()会再次施放它。
然后我到了glTextImage2D
。并错误地认为它不能与PBO一起使用(大坝,我因为匆忙而犯错误。我必须放松......)。谢谢 Nico Bolas 纠正了我。
然后,再次慢慢阅读,只是在glTextImage2D中不使用指向客户端数据的指针,将data
更改为0
文档清楚地说明了最后一个参数:
如果绑定了非零命名缓冲区对象 GL_PIXEL_UNPACK_BUFFER目标(参见glBindBuffer)同时是纹理图像 如果指定,则将数据视为缓冲区中的字节偏移量 对象的数据存储。
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)。