何时在 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 ES 2中使用glDeleteBuffers,glDeleteShader和glDeleteProgram?