何时在 OpenGL 中使用 glBufferData

Posted

技术标签:

【中文标题】何时在 OpenGL 中使用 glBufferData【英文标题】:When to use glBufferData in OpenGL 【发布时间】:2013-11-27 17:47:12 【问题描述】:

我刚刚开始学习 C++ 中的顶点缓冲区对象。我正在阅读一本关于 OpenGL 的书,它说 VBO 渲染比其他形式的渲染更有效,因为数据存储在 GPU 上而不是堆上。但是,如果您仍然必须将一组数据从堆加载到 GPU,我会感到困惑。每隔几秒钟,我就会更新程序的顶点数据,这意味着我必须使用glBufferData() 刷新数据以更新到新状态。我看不出这比正常渲染数组更有效。我想知道我是否对glBufferData() 的调用超出了必要的范围,或者是否有更好的方法可以直接在 GPU 上更新顶点数据。

【问题讨论】:

您是通过一个全新的缓冲区发送还是只是发生了变化?另外,你为什么要发送一个新的缓冲区?如果是用于动画,请考虑将动画的“关键帧”作为多个缓冲区发送并将它们绑定到着色器中,然后将原始网格变形为关键帧。 我正在发送一个全新的缓冲区,我认为我的书还没有超越所有其他内容,在所有书籍示例中,整个程序的顶点都保持不变。 有一种更好的方法可以在 GPU 上更新顶点数据。它们被称为顶点着色器,如果您可以通过一些静态输入数据以编程方式计算每个顶点的位置,那么这将始终在性能方面胜出。希望你的书不是太古老以至于它不包括顶点着色器; VBO 和顶点程序大约在同一时间被引入 OpenGL,但 GLSL 和顶点着色器在几年后被引入。我怀疑很多书都涉及顶点程序,因为它们是一种很快被 GLSL 取代的汇编语言。 【参考方案1】:

嗯,glBufferData (...) 做的比你想象的要多。确实,它向 VBO 提供数据,但更重要的一点是它在服务器端分配内存(用于所有意图和目的的 GPU)用于顶点存储。

在您的示例中,当您刷新数据时,顶点的数量以及存储它们所需的大小似乎并没有改变。您实际上应该做的是调用glBufferSubData (...) 来更新数据而不为它重新分配空间。再加上正确的使用标志(例如GL_DYNAMIC_DRAW),这比每次绘制内容时从客户端复制到服务器要高效得多。

glBufferData (...) 视为malloc (...)memcpy (...) 的组合。另一方面,glBufferSubData (...)memcpy (...)。为此,您甚至可以将 VBO 的内存映射到应用程序的地址空间,而无需使用 glMapBuffer (...)glUnmapBuffer (...) 在客户端和服务器中分配存储空间,这类似于 mmap (...)munmap (...)

【讨论】:

【参考方案2】:

您应该尽量避免每隔几帧就修改一次顶点数据。顶点/片段着色器专门用于允许您动态修改几何图形,当然有一些限制。

但是,在最简单的情况下(如果您不关心最大化性能),完全有可能在每一帧上重写缓冲区,并且它仍然应该优于调用glBegin..glEnd对象。

【讨论】:

以上是关于何时在 OpenGL 中使用 glBufferData的主要内容,如果未能解决你的问题,请参考以下文章

何时使用 openGL 将数据发送到 GPU

何时应该在OpenGL ES 2中使用glDeleteBuffers,glDeleteShader和glDeleteProgram?

OpenGL:多种渲染方法.. 何时使用哪个?

VBO 何时比“简单”的 OpenGL 基元 (glBegin()) 更快?

如何避免 OpenGL 中的光旋转?

OpenGL 无效的纹理或状态