【发布时间】:2012-01-18 15:44:38
【问题描述】:
我正在用 C++/OpenGL 开发一个程序,它可以绘制整个世界的地形。我有一个存储为瓷砖的海拔高度数据库。每次我启动程序时,都会加载一个图块。然后当人移动时,应该加载另一个图块,这不会每帧都发生,可能每 5 分钟一次。
我将初始图块加载到视频卡的内存中:
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBuffer[idx]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, VBOsz * 3 * sizeof(float), tile_data, GL_STATIC_DRAW_ARB);
...有法线、颜色和索引缓冲区
然后我画它们:
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBuffer[idx]);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, VBOsz * 3 * sizeof(float), tile_data, GL_STATIC_DRAW_ARB);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBuffer[idx]);
glVertexPointer(3, GL_FLOAT, 0, BUFFER_OFFSET(0));
...
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, IndexBuffer[idx]);
glDrawElements(GL_TRIANGLES, IndexBuffersz, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
由于我希望程序尽可能的流畅,我无法计算同一帧的顶点+颜色+法线+其他纹理,因为创建一个平铺大约需要20秒。
所以我决定创建一个加载器线程,它会检查何时需要加载新图块,然后加载它。当一切都完成后,它应该只交换 VBO(因此是 [idx]。
所以对于加载器线程,我知道我需要第二个 OpenGL 上下文,我创建了一个并在它们之间共享列表。这个想法是可行的,但是在加载器线程中,当我发送新的 VBO 数据时,我需要这个函数:wglMakeCurrent
只有当所有数据都加载完毕后,我才能为渲染线程(主程序的线程)设置上下文。这会导致在这段时间内没有绘制任何内容,从而使程序无用。
您对解决方案有任何想法吗?我需要改变概念吗?
我使用的是 OpenGL 2.1。升级到 OpenGL 3 会解决问题吗?
【问题讨论】:
-
请停止使用缓冲区对象的 ARB 扩展形式。近十年来,它们一直是核心功能;没有任何借口了。
标签: multithreading opengl vbo