OpenGL顶点缓冲区混乱问题

18
有人可以解释一下VertexBufferVertexArrayVertexBufferObjectVertexArrayObject之间的区别吗?我甚至不确定这些是否都是指不同的东西,但我在OpenGL规范中看到了所有这些术语。
我知道一个VertexBuffer只包含顶点,一旦绑定,一旦我设置了顶点指针,我就可以使用DrawArrays来绘制它。我已经用这种方式做了很多次。
我正在使用我认为是一个VertexArray,它存储设置的任何顶点缓冲区的状态和任何顶点指针。绑定一个VertexArray会自动绑定顶点缓冲区并设置顶点指针。我也已经(大部分时间)成功地使用了它。
VertexBufferObjectVertexArrayObject是什么?它们更好吗?VertexArray不是已经给了我所有我需要的东西吗?
2个回答

18

一个顶点数组就是你程序中的一些数据(在你的地址空间内),你通过提供指向它的指针告诉OpenGL。


虽然比逐个指定每个顶点更有效率,但它们仍然存在性能问题。在您调用DrawElements(或类似函数)时,GL必须进行复制,因为那是它可以确定数据有效性的唯一时间(毕竟,没有任何东西防止您立即覆盖数据)。这意味着有显著的并行障碍,从而带来了性能问题。

顶点缓冲对象("顶点缓冲")是您不拥有的原始数据块,即它们不在您的地址空间中。您可以使用Copy(Sub)Data将数据复制到缓冲区对象中,也可以通过临时映射到您的地址空间。一旦取消映射缓冲区,它就不再属于您。巨大的优势是现在GL可以决定如何处理它以及何时上传它。它知道数据将有效,因为您无法访问它。这使得CPU / GPU并行化更加容易。

顶点数组对象有点称为误导。其中没有顶点或数组。它们只是一种“状态说明块”,其封装了一个或多个顶点缓冲区对象的绑定(包括任何VertexAttribPointer调用)。因此,它们既是方便函数,又更有效率(较少的函数调用),但不是必需的。您也可以手动完成VAO所做的任何操作。


所以我在第三段提到的很可能是一个顶点数组对象,这是最适合普通应用程序的。谢谢你为我澄清这一点。 - Hannesh
关于_VAO是一种方便而不是严格必要的_:如果我理解正确,在使用OpenGL 3.1+核心配置文件时,这是错误的。现在使用VBO需要有VAO。例如,如果没有绑定VAO,则glEnableVertexAttribArray将失败。但是可以像此答案中建议的那样引入一个“全局”VAO。 - bluenote10
1
@bluenote10:是的,对于版本3.1及更高版本的核心配置上下文,您需要绑定至少一个VAO(虽然您不需要使用多个进行切换)。但这不是我的意思。就其本身而言,VAO是“一种方便的东西,不是严格必要的”,因为它没有做任何“特殊”的事情,否则您无法完成。它只是使组合状态的切换更快、更容易。您不可能在没有纹理或顶点缓冲区的情况下完成纹理或顶点缓冲区所做的事情。但是,您可以在没有VAO的情况下完成使用VAO所做的事情(只需调用更多函数)。 - Damon

7
  • BufferObject: 一个在GPU上分配的内存缓冲区。
    • Vertex Buffer Object: 包含顶点信息(颜色、位置、着色器使用的自定义数据等)的BufferObject。
    • Pixel Buffer Object: 包含像素或纹素信息的BufferObject。主要用于上传纹理。
    • Element Buffer Object: 包含索引(被 glDrawElements 使用)的BufferObject。
  • Vertex Array: 由gl*Pointer调用使用的内存。如果使用glBindBuffer命令绑定GL_ARRAY_BUFFER,它可能是主机内存或Vertex Buffer Object。
  • Element Array: 由glDrawElements调用使用的内存。如果使用glBindBuffer命令绑定GL_ELEMENT_ARRAY_BUFFER,它可能是主机内存或Element Buffer Object。

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