为什么我不能单独创建和初始化OpenGl VAO?

时间:2016-10-06 01:40:00

标签: c++ debugging opengl

我目前正在开发一个使用VAO(每个网格一个)的OpenGl 3.3应用程序。当我单独创建和初始化我的VAO时,对glDrawElements的任何调用都会导致程序立即退出,而不会显示任何错误消息。但是,当我一起创建并初始化它们时,完全相同的glDrawElements调用成功。

单独的初始化代码:

Chunk::Chunk(){
  glGenVertexArrays(1, &m_vaoId);
  glBindVertexArray(m_vaoId);

  glGenBuffers(1, &m_vboId);
  glGenBuffers(1, &m_eboId);

  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(0));
  glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(1*sizeof(GLfloat)));
  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);
}


void Chunk::refreshMesh(){
  /*build data into vector<GLfloat> verticies and vector<GLuint> indices...*/

  //send data to GPU
  glBindVertexArray(m_vaoId);

  glBindBuffer(GL_ARRAY_BUFFER, m_vboId);
  glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);

  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_eboId);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLfloat), indices.data(), GL_STATIC_DRAW);
}

编译初始化代码:

void Chunk::refreshMesh(){
  /*build data into vector<GLfloat> verticies and vector<GLuint> indices...*/

  //send data to GPU
  glGenVertexArrays(1, &m_vaoId);
  glBindVertexArray(m_vaoId);

  glGenBuffers(1, &m_vboId);
  glBindBuffer(GL_ARRAY_BUFFER, m_vboId);
  glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(GLfloat), vertices.data(), GL_STATIC_DRAW);

  glGenBuffers(1, &m_eboId);
  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_eboId);
  glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLfloat), indices.data(), GL_STATIC_DRAW);

  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(0));
  glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (GLvoid*)(1*sizeof(GLfloat)));
  glEnableVertexAttribArray(0);
  glEnableVertexAttribArray(1);
}

注意:我使用Ubuntu 16.04 LTS使用g ++ 5.4.0 20160609(Ubuntu 5.4.0-6ubuntu1~16.04.2),glew 1.13和SDL2 2.0.0进行编译。我想进行单独的初始化,以允许定期更新网格数据,而无需创建新的VAO等,因为我想可以在任何真正的GPU上处理有限数量的那些。

1 个答案:

答案 0 :(得分:4)

在VAO发明之前,(几乎)所有东西都保存在全球OpenGL状态中。由于VAO有自己的状态,因此VAO略有变化。

您正在使用glVertexAttribPointer设置指向缓冲区中属性的指针,但是,VAO状态不仅包含传递给函数的值,还包含它们指向的缓冲区,即缓冲区当你调用函数时绑定到GL_ARRAY_BUFFER。这允许像这样的东西(伪代码):

glBindBuffer(GL_ARRAY_BUFFER, a);
glVertexAttribPointer(...);
glBindBuffer(GL_ARRAY_BUFFER, b);
glVertexAttribPointer(...);

有了这个,你可以使用两个不同缓冲区的属性。然后你可以取消绑定缓冲区并忘记*关于它们,你不需要将它们绑定以进行绘制。

TLDR:要解决您的问题,您需要在调用GL_ARRAY_BUFFER之前将要使用的缓冲区绑定到glVertexAttribPointer。每次绘制时都不需要绑定缓冲区,因为VAO 使用当前绑定的缓冲区数组缓冲区进行绘制,但是属性指针已设置。

*:要更改或删除它们,您显然仍需要他们的名字,因此不要严格意义上“忘记”它们。