OpenGL顶点缓冲区混淆

Posted

技术标签:

【中文标题】OpenGL顶点缓冲区混淆【英文标题】:OpenGL vertex buffer confusion 【发布时间】:2011-08-01 17:50:11 【问题描述】:

有人愿意解释一下 VertexBufferVertexArrayVertexBufferObjectVertexArrayObject?我什至不确定这些是否都是不同事物的术语,但我已经看到它们都出现在 OpenGL 规范中。

我知道 VertexBuffer 只包含顶点,没有其他内容,一旦绑定,一旦我设置了顶点指针,我就可以使用 DrawArrays 来绘制它。我已经多次这样做了。

我正在使用我认为是 VertexArray,它存储设置的任何顶点缓冲区的状态,以及任何顶点指针。绑定 VertexArray 会自动绑定顶点缓冲区并设置顶点指针。我也(大部分)成功地使用了这个。

但是什么是 VertexBufferObjectVertexArrayObject?他们更好吗? VertexArray 没有给我所需的一切吗?

【问题讨论】:

【参考方案1】:

顶点数组只是程序中的一些数据(在地址空间内),通过提供指向它的指针告诉 OpenGL。 虽然比单独指定每个顶点更有效,但它们仍然存在性能问题。 GL 必须在您调用 DrawElements(或类似函数)时进行复制,因为这是唯一可以确定数据有效的时间(毕竟,没有什么可以阻止您立即覆盖数据)。这意味着并行性存在很大障碍,因此存在性能问题。

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

顶点数组 abject 有点用词不当。其中没有顶点或数组。它们只是一种“状态描述块”,封装了一个或多个顶点缓冲区对象(包括任何 VertexAttribPointer 调用)的绑定。因此,它们既是一个方便的函数,也更有效(更少的函数调用),但不是绝对必要的。你也可以做任何 VAO 手动做的事情。

【讨论】:

所以我在第三段中提到的很可能是一个顶点数组对象,它最适合普通应用程序。感谢您为我解决这个问题。 关于 VAO 是一种便利,并非绝对必要:如果我理解正确,那么在使用 OpenGL 3.1+ 核心配置文件时这是错误的。现在使用 VBO 需要有 VAO。例如,glEnableVertexAttribArrayfails 如果没有绑定 VAO。不过可以引入一个“全局”VAO,as suggested in this answer。 @bluenote10:是的,对于版本 3.1 和更高版本的核心配置文件上下文,您需要绑定至少一个 VAO(但您不需要使用多个来切换)。但这不是我的意思。 VAO 是“一种并非绝对必要的便利”,因为它不会做任何你不能做的“特殊”事情。它只会使切换组合状态更快更容易。如果没有纹理或没有顶点缓冲区,您不可能做纹理所做的事情或顶点缓冲区所做的事情。但是您可以在没有 VAO 的情况下使用 VAO(只是更多的函数调用)。【参考方案2】: BufferObject:GPU 分配的内存缓冲区 顶点缓冲区对象:一个包含顶点信息(颜色、位置、着色器使用的自定义数据……)的缓冲区对象 像素缓冲区对象:包含像素或纹素信息的缓冲区对象。主要用于上传贴图。 Element Buffer Object:一个包含索引的BufferObject(由glDrawElements使用)。 顶点数组:gl*Pointer 调用使用的内存。如果使用glBindBuffer 命令与GL_ARRAY_BUFFER 绑定,则可能是主机内存或顶点缓冲区对象。 元素数组:glDrawElements 调用使用的内存。如果使用glBindBuffer 命令与GL_ELEMENT_ARRAY_BUFFER 绑定,则可能是主机内存或元素缓冲区对象。

【讨论】:

以上是关于OpenGL顶点缓冲区混淆的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL复制顶点缓冲区对象

OpenGL更新顶点数组/缓冲区

OpenGL 顶点数组/缓冲区对象

OpenGL顶点缓冲区不正确的渲染

顶点缓冲区对象(删除进程)opengl

使用顶点缓冲区使用 OpenGL 显示常规网格的最快方法是啥?