我一直在阅读VAO如何与VBO合作。据我所知,当我们调用glVertexAttribPointer时,VAO只存储有关VBO的状态信息。我的问题是,它何时存储关于EBO的状态(对于索引绘图),当调用glVertexAttribPointer时它是否为两者保存状态?
//Vertices of the rectangle
std::vector<GLfloat> vertices
{
0.5f, 0.5f, 0.0f, // Top Right
0.5f, -0.5f, 0.0f, // Bottom Right
-0.5f, 0.5f, 0.0f, // Top Left
-0.5f, -0.5f, 0.0f, // Bottom Left
};
//Indices of the triangle
std::vector<GLuint> indices
{
0, 1, 3,
0, 3, 2
};
GLuint VAO, VBO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO); //Bind the VAO
//Bind the buffers
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(GLfloat), &vertices[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0); //Unbind the VAO
//Supply Index Buffer information
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), &indices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//Custom shader class that stores the program to be used at render time
Shader shader("..path_to_shader\\shaders\\vertexshader.vert", "..path_to_shader\\shaders\\fragmentshader.frag");
while (!glfwWindowShouldClose(window))
{
glUseProgram(shader.Program());
glBindVertexArray(VAO); //Bind the VAO to draw.
glClearBufferfv(GL_COLOR, 0, &color[0]);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
glfwPollEvents();
glfwSwapBuffers(window);
glBindVertexArray(0);
glUseProgram(0);
}
答案 0 :(得分:10)
当您将GL_ELEMENT_ARRAY_BUFFER
绑定绑定到:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...);
虽然VAO受到约束。
请注意,在没有VAO绑定的情况下绑定元素数组缓冲区也是合法的。这对于使用glBufferData()
或类似调用填充数据非常有用。由于在Core Profile中你需要一个VAO绑定任何绘制调用,你需要绑定你想要用来渲染的元素数组缓冲区,同时绑定VAO。
关于您的代码,您使用的调用序列将无法提供所需的结果。以下是您的重要电话,其中的评论解释了结果:
glBindVertexArray(VAO);
// VAO is now bound. If this is the first time, it will have the default VAO state.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// The element array buffer is bound, and this binding becomes part of the VAO state.
glBindVertexArray(0);
// The VAO is unbound. Since the element array buffer binding was part of the
// VAO state, the element array buffer is also unbound.
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint),
&indices[0], GL_STATIC_DRAW);
// This will not work, since you do not have an element array buffer bound.
为了实现这一目标,最简单的解决方案是更改最后两次调用的顺序:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint),
&indices[0], GL_STATIC_DRAW);
// The currently bound element array buffer is filled with data.
glBindVertexArray(0);
// The VAO is unbound. Since the element array buffer binding was part of the
// VAO state, the element array buffer is also unbound.
为了进一步探讨这个问题,以下序列也可以起作用:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// The element array buffer is bound, Since no VAO is bound, the binding becomes
// part of the global state (or more precisely, of the default VAO 0).
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint),
&indices[0], GL_STATIC_DRAW);
// The currently bound element array buffer is filled with data.
glBindVertexArray(VAO);
// VAO is now bound. If this is the first time, it will have the default VAO state.
// Since the element array binding is part of the VAO state, the previously bound
// element array buffer is not bound anymore.
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// The element array buffer is bound, and this binding becomes part of the VAO state.
glBindVertexArray(0);
// The VAO is unbound. Since the element array buffer binding was part of the
// VAO state, the element array buffer binding is restored to the binding that
// was current before the VAO was bound.
请注意,在此序列中,您必须在绑定VAO后再次绑定元素数组缓冲区,因为一旦绑定VAO,VAO状态中的元素数组缓冲区绑定将覆盖当前绑定。
答案 1 :(得分:6)
来自opengl.org:
顶点数组对象(VAO)是一个存储所有数据的OpenGL对象 状态需要提供顶点数据(注意到一个小的例外 下面)。它存储顶点数据的格式以及缓冲区 提供顶点数据数组的对象(见下文)。
索引缓冲区绑定存储在VAO中。
对于GL_ARRAY_BUFFER
,当您致电glVertexAttribPointer
时,VAO会保存绑定。这主要是因为GL_ARRAY_BUFFER
绑定不属于VAO的状态。因此,呼叫glBindBuffer(GL_ARRAY_BUFFER, vertexBufferHandle)
不会对VAO的状态做任何事情。
对GL_ELEMENT_ARRAY_BUFFER
而言并非如此:
当你调用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferHandle)
时,VAO(如果绑定)将保存索引缓冲区绑定到它的状态。
有关于OpenGL indexed buffering的精彩教程以及opengl-tutorial.org上的其他基本内容。