0

我目前正在学习 OpenGL,而 VAO 让我感到困惑。据我了解,VAO 只是封装了 VBO 的状态。

Bind VAO
load buffer data
Disable VAO

然后你可以像这样画

activate VAO
DrawArray ...
deactivate VAO

但我不确定这在实践中是否真的有用。假设我有一个非常大的场景要渲染。也许 10 平方公里,我显然不想一次将每个对象加载到 GPU,我可能想将场景分成不同的块。

现在我四处走动,有一次我必须将另一块对象加载到 GPU 上,对吗?但据我所知,我无法更改 VAO,而且每次我的场景发生变化时,我都必须创建一个新的 VAO。

那么在我的场景中什么是 VAO?整个场景会是 VAO 吗?还是每个对象都是 VAO?

对我来说,拥有多个 VAO 并没有多大意义,因为我无法将 VAO 组合在一起,我只能像这样将它们叠加在一起

activate VAO1
DrawArray ...
deactivate VAO1

activate VAO2
DrawArray ...
deactivate VAO2
4

2 回答 2

3

您不能启用或禁用 VAO,它们是 OpenGL 中的一类对象,称为容器(与 FBO 相同)。它们为顶点数组绘制操作提供上下文以及描述它们所需的状态。您当然可以更改 VAO,它们只是状态容器……绑定它,然后更改它存储的状态之一。是否为整个场景使用一个 VAO 或多个 VAO 取决于您,但请记住,在核心 OpenGL 3.2 上下文中,您不能发出任何没有至少一些 VAO 绑定的顶点绘制命令。

此外,VAO 与当前绑定的缓冲区对象本身无关,除了元素数组缓冲区。VAO 存储顶点数组指针,这些指针可能直接或间接(参见 :)GL_ARB_vertex_attrib_binding绑定到 VBO,但 VAO 根本不关心 VBO 当前绑定到什么GL_ARRAY_BUFFER。正如我提到的,元素数组缓冲区是不同的,VAO确实跟踪当前绑定的元素数组缓冲区,因此调用glDrawElements (...)将具有一致的行为,只需绑定一个 VAO。如果没有此属性,您将必须绑定一个 VAO,然后还绑定一个元素数组缓冲区,然后才能发出索引绘图操作。

于 2014-01-03T17:35:45.737 回答
0

你的第一句话:

据我了解,VAO 只是封装了 VBO 的状态。

大部分是正确的,因为 VBO 是 VAO 中存储最多的缓冲区类型,但与顶点处理相关的任何类型的缓冲区(即元素数组、间接绘制缓冲区等,取决于您的 OpenGL 版本支持哪些类型) ) 也包含在 VAO 中。

将 VAO 添加到 API 的原因是为了减少为不同对象交换数据所需的函数调用数量。在具有多个需要不同顶点属性集的对象的应用程序中,在 VAO 之前,您需要调用glBindBuffer渲染该对象所需的每个 VBO(包括元素数组缓冲区)(顶点属性位置和缓冲区的关联是该缓冲区的属性,而不是 VAO 的属性,以防您有这个问题)。正如您所提到的, VAO 允许将所有这些绑定封装到单个对象中,该对象可以通过对 的单个调用进行绑定glBindVertexArray

在 VAO 之间进行交换时,您也处于正确的轨道上。在应用程序的初始化中(或者当您需要添加更多对象时),您将根据需要创建和初始化尽可能多的 VAO,并为每个 VAO 绑定它,并使用其所有相关缓冲区填充它。当你想使用一个时,你只需绑定它。还值得注意的是,您始终可以使用glBufferData或类似调用更新 VBO 中的数据,并且该操作不会影响与该缓冲区关联的 VAO 包含的绑定。

于 2014-01-03T18:20:05.207 回答