OpenGL. 使用glBufferData更新顶点缓冲区

17

我正在使用 OpenGL 实现一些批处理绘图。为此,我创建了一个 顶点缓冲区 来存储数据。

注意:这个缓冲区通常会在每帧更新,但永远不会减小大小(但仍然可以增加)。

我的问题是:在更新它时(而不是使用 glMapBuffer 等),是否可以技术上使用 glBufferData(以流式写入模式)? 我想,没有必要映射它,因为完整的数据会被更新,所以我只需一次发送完整的数据包。如果当前缓冲区大小小于我要发送的大小,它会自动增加,对吗? 我不确定它的工作方式(也许它每次调用都会重新创建缓冲区,是吗?)。

2个回答

14

最好使用固定大小的缓冲区,并且不要在每帧重新创建它。

实现方法如下:

  • 创建一个具有最大大小的缓冲区,例如可以容纳1000个顶点
  • 仅使用glMapBuffer更新缓冲区开头的新数据。因此,如果您更改了500个顶点的数据,则只填充缓冲区的前半部分
  • 在绘制时改变绘制的顶点数。例如,您可以从整个1000个顶点的缓冲区中仅使用一些范围的顶点(例如从200到500)。使用 glDrawArrays(mode, first, count)

评论中提出的想法:

  • glMapBufferRange和glBufferSubData也可能有所帮助
  • 还要考虑缓冲区的双重缓冲

链接:http://hacksoflife.blogspot.com/2010/02/double-buffering-vbos.html

希望这有所帮助


1
每一帧丢弃一个缓冲区并创建一个新的,你肯定会得到更好的GPU/CPU性能,对吗?如果更新一个正在使用的缓冲区,会导致潜在的阻塞,如果GPU当前正在使用它的话。 - Robinson
1
这里有一些有趣的链接:http://hacksoflife.blogspot.com/2010/02/double-buffering-vbos.html,还有一个glMapBufferRange函数可能会有所帮助。 - fen
3
@Celestis: 是的,和所有内存分配一样,glBufferData是一个较慢的操作。然而,glBufferSubData非常快,glMapBuffer[Range]和glUnmapBuffer也是如此。顺便说一句,在客户端/CPU端进行内存分配也很慢;如果你告诉OpenGL要分配一些内存,它必须在GPU和CPU两侧都这样做。因此最好避免这样做。预先分配一个大缓冲区,其中只使用了一部分,这是可行的方式。 - datenwolf
@datenwolf,谢谢,看起来glBufferSubData是我需要的东西!所以,我想我会通常使用它来更新缓冲区,如果很少发生缓冲区增加的情况,我会重用glBufferData。 - Celestis
4
@Celestis: 是的,那是一般的想法。但是如果您不断更新数据,则应使用2或3个缓冲区,在其中循环更新数据。例如,仅在过去的2天里,我编写了一个小型“示波器”,以可视化实验中DAQ系统传递的波形...速率为1.5GSamples/sec;即,我必须以1.5GByte/s的速率更新VBOs。 - datenwolf
显示剩余3条评论

5
除了fen和datenwolf所说的,还可以参考OpenGL Insights第22章;特别是其中包括各种硬件和技术的时间表。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接