将缓冲区合二为一

Adding up buffers into one

我有一个由多个条目组成的网格。 每个条目都包含它自己的面、顶点、法线、颜色和纹理坐标列表。

我可以遍历我的所有条目并使用 glVertexAttribPointer 来累积单个缓冲区对象中的属性数据,就像这样吗?:

glBindBuffer(vbo);
for(Entry* e : entries) {
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, e->vertices);
    ...
}

换句话说,缓冲区vbo的属性0重复调用glVertexAttribPointer会不会重写之前指向的数据?

如果是,在对整个缓冲区只调用一次glVertexAttribPointer之前,将所有顶点复制到一个连续的内存块中是否有任何有效的解决方案?

glVertexAttribPointer 只存储(对于每个属性)您提供给它的最后信息。因此,这种方法无法附加缓冲区。

当您遇到像您这样的情况时,您有两种选择:

  1. 为每个缓冲区发出一个单独的绘图调用
  2. 将所有缓冲区中的数据复制到一个缓冲区中,并为其发出一个绘图调用。请注意,在这种情况下,可能必须调整索引以指向组合缓冲区中的正确位置。

glVertexAttribPointer() 不复制任何内容。它只设置指定从何处获取顶点数据的状态。如果对同一个属性重复调用,每次调用都会替换之前的状态,最后一个为准。

从 OpenGL 3.1 开始,有一个 glCopyBufferSubData() 调用 (man page) 允许您将数据从一个缓冲区复制到另一个缓冲区。使用它,您可以为所有顶点分配一个具有足够 space 的缓冲区,然后将较小的缓冲区复制到包含所有顶点的缓冲区中。

话虽如此,以这种方式使用它听起来并不是一个好主意。如果您希望所有顶点都在同一个缓冲区中,那么从一开始就将它们存储在该缓冲区中会更加容易和高效。

绝对不应该在每次绘制调用时复制顶点数据。虽然减少绘图调用的数量是可取的,但围绕顶点数据复制会昂贵。