在 OpenGL 中,除非我再次重新指定顶点属性,否则为什么我的缓冲区对象不会绘制?

In OpenGL why won't my buffer object draw unless I respecify the vertex attributes again?

我认为 VAO(顶点数组对象)应该像顶点属性一样存储状态。当我创建一个 VBO 时,我指定了我的顶点属性:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)nullptr);
glEnableVertexAttribArray(0);
// And so on

如果我绑定另一个 VBO,我必须调用 glVertexAttribPointer 和 glEnableVertexAttribArray 三次,这是我每次切换 VBO 时的调用。我只有一个 VAO,我从不改变它。有什么不对?我只使用一个顶点布局,如果每次切换时它都丢失此信息,我不明白 VAO 会做什么。每个 VAO 是否只有一个 VBO?

如果您不想在调用 glDraw* 函数之前重新指定 glVertexAttribPointer,那么您需要多个 VAO,而不仅仅是一个。我认为您混淆了 VBO 和 VAO 是什么。 VBO 只是一块包含数据的惰性内存。 VAO 包含 OpenGL 绘制网格所需的所有信息,包括:
- 对包含顶点数据的 Buffer 对象的引用(通常命名为 VBO)
- 对包含顶点索引的 Buffer 对象的引用(如果您使用的是 glDrawElements*)
- 您将要使用的不同顶点属性的索引及其在包含顶点数据的 Buffer 对象中的布局(使用 glEnableVertexAttribArray 和 glVertexAttribPointer 指定)

所以基本上对于你要绘制的每个网格你需要准备一个相应的 vao:

// at scene preparation time
glBindVertexArray(vaoA); // the following functions will only affect vaoA
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshA);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshA);
foreach attrib of meshA
  glEnableVertexAttribArray(***);
  glVertexAttribPointer(***)
glBindVertexArray(0)

glBindVertexArray(vaoB); // the following functions will only affect vaoB
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_of_meshB);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_of_meshB);
foreach attrib of meshB
  glEnableVertexAttribArray(***);
  glVertexAttribPointer(***)
glBindVertexArray(0)

//And now at render time:
void render()
{
   glBindVertexArray(vaoA);
   glDrawElements(***);

   glBindVertexArray(vaoB);
   glDrawElements(***);
}

查看更多信息:https://www.opengl.org/wiki/Vertex_Specification