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

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

【问题讨论】:

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

标签: c++ opengl vbo


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2018-03-26
      • 2012-05-27
      • 2020-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-01
      • 2014-08-04
      • 2020-12-14
      相关资源
      最近更新 更多