9

我的代码可以正常工作,但这可能是巧合,我不想稍后再讨论一个错误,所以我尽量保持它尽可能干净:

我执行以下操作来初始化网格:

  1. 生成并绑定 VBO 和缓冲区数据
  2. 生成和绑定 IBO 和缓冲数据
  3. 生成并绑定 VAO
  4. 绑定与之前相同的 VBO,在 1 中生成。
  5. 启用我需要的顶点属性数组并设置顶点属性指针
  6. 再次绑定IBO(不知道为什么)
  7. BindVertexArray 回到 0,这样我就不会弄乱我刚刚创建的 VAO

据我了解,VAO 将存储我启用的顶点属性数组的状态。它还将存储我绑定的 VBO 和 IBO。由于我通过将顶点数组绑定回 0 “关闭”了 VAO 上的所有操作,因此我确保没有其他代码会弄乱我的 VAO。所以如果这没问题,我需要渲染的是:

  1. 绑定VAO
  2. 绘制元素
  3. 解除绑定 VAO(绑定到 0)

这应该带来 AttribArray 状态以及存储的 VBO 和 IBO。我的问题是:

A.设置 VertexAttribPointers 后是否需要绑定 IBO?如果是这样,为什么?

B. VAO 是否真的同时存储VBOIBO?我听说它只存储最后一个绑定的缓冲区,这意味着我必须像这样渲染:

  1. 绑定VAO
  2. 绑定 VBO
  3. 绘制元素
  4. 解除绑定 VAO

但这没有任何意义,为什么在不存储两个缓冲区对象的情况下使用 VAO?这和绑定 VBO 和 IBO 然后绘制元素而不绑定 VAO 不一样吗?

预先感谢您的帮助。

代码如下:

初始化

// generate VBO
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size()*sizeof(GLfloat), m_vertices.data(), GL_STATIC_DRAW);

// generate IBO
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size()*sizeof(unsigned short), m_indices.data(), GL_STATIC_DRAW);

// generate VAO
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);

// set the vertex attribute pointer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,vertexSize,reinterpret_cast<const GLvoid*>(0));         

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBindVertexArray(0);

绘画

glBindVertexArray(m_vao);
glDrawElements(GL_TRIANGLES,size,GL_UNSIGNED_SHORT,reinterpret_cast<const GLvoid*>(0));
glBindVertexArray(0);

另外,如果我这样说是不是更干净:

  1. 生成并绑定 VAO
  2. 生成并绑定 IBO 和 BufferData
  3. 生成并绑定 VBO 和 BufferData
  4. 我需要的 EnableVertexAttribArrays 并设置 VertexAttribPointers
  5. 解除绑定 VAO(绑定到 0)

看起来更干净,但我不知道结果是否相同,特别是在第 4 步和第 5 步之间缺少 IBO 绑定。

4

1 回答 1

9

解决您的问题:

A.设置 VertexAttribPointers 后是否需要绑定 IBO?如果是这样,为什么?

不,您可以先绑定元素数组(术语中的 IBO),然后再执行顶点属性,但一般来说,它们是 VAO 中的单独绑定。例如,您可以绑定您的 IBO 以及多个 VBO,并glDrawElements使用 IBO 中的数据使用(和变体)渲染,或者使用glDrawArrays(和变体)仅使用 VBO 中的顺序顶点数据 - 渲染命令确定是否是否使用 IBO。

B. VAO 是否真的同时存储了 VBO 和 IBO?

是的。一个 VAO 可以存储单个 IBO 和至少 16 个 VBO 的绑定信息。

我听说它只存储最后一个绑定的缓冲区,这意味着我必须像这样渲染:

绑定 VAO
绑定 VBO
绘制元素
取消绑定 VAO

正如您在原始帖子中所推测的那样,此声明是不正确的,并且您包含的 VBO 的绑定是不必要的。一个 VAO 可以存储与实现相关的最大(至少 16 个)VBO 数量,每个 VBO 都可以绑定到一个顶点属性。

另外,如果我这样说是不是更干净:

  1. 生成并绑定 VAO
  2. 生成并绑定 IBO 和 BufferData
  3. 生成并绑定 VBO 和 BufferData
  4. 我需要的 EnableVertexAttribArrays 并设置 VertexAttribPointers
  5. 解除绑定 VAO(绑定到 0)

是的。正如您所指出的,这仅允许您在三个命令中绑定、渲染和清理。

真的,这就是 VAO 的全部意义,收集所有这些绑定和顶点属性关联,这样您就可以一次性完成所有的管道工作,然后一劳永逸。

于 2013-06-27T07:56:51.040 回答