我正在尝试在OpenGL 3.3中的窗口中绘制两个三角形。我正在使用GLFW库作为窗口系统。
根据我的理解,我应该有两个VBO (每个三角形一个)和一个VAO 包含这两个VBO。这就是我所做的。
然而,我无法弄清楚我应该做些什么来渲染这两个VBO。实际上,无论我做什么,只会第一个 VBO(第一个三角形)被绘制。第二个永远不会出现。
int main()
{
GLFWwindow *window = setupWindow();
GLfloat triangle1Vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLfloat triangle2Vertices[] = {
0.f, -0.5f, 0.0f,
0.8f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
GLuint vao, vbo[2];
glGenVertexArrays(1, &vao);
glGenBuffers(2, vbo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle1Vertices), triangle1Vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2Vertices), triangle2Vertices, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
glfwPollEvents();
glClearColor(0.3f, 0.3f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &vao);
glDeleteBuffers(2, vbo);
glfwTerminate();
return 0;
}
我显然错过了什么,但是什么?
答案 0 :(得分:2)
根据我的理解,我应该有两个VBO(每个三角形一个)和一个包含这两个VBO的VAO。
然后你的理解是错误的。
如果你想要两个不同的缓冲区有两个不同的三角形,那么你需要两个不同的VAO,或者你需要交换VAO在渲染每个对象之间使用的缓冲区。
您的渲染代码接近正确但不完全:
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glDrawArrays(GL_TRIANGLES, 0, 3);
通知第二个glVertexAttribPointer
调用也使用属性0。传递给glVertexAttribPointer
的属性索引指定从该数组馈送哪个着色器输入变量。您尝试做的是使用相同的着色器渲染第二个对象,仅更改顶点数组的来源。这需要使用相同的属性索引。
但是,如果您可以使用OpenGL 4.3 / ARB_vertex_attrib_binding,I would highly encourage you to just use those APIs。它使您的代码更多更直接:
//vertex setup
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//Sets up the format, *without* a buffer object.
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
//Sets up where the buffer object comes from
glVertexAttribBinding(0, 0);
//Done with VAO
glBindVertexArray(0);
//Set up buffer object data storage.
glGenBuffers(2, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle1Vertices), triangle1Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2Vertices), triangle2Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
然后,在你的循环中:
glBindVertexArray(vao);
//Use buffer 0 to render.
glBindVertexBuffer(0, vbo[0], 0, 3 * sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
//Use buffer 1 to render.
glBindVertexBuffer(0, vbo[1], 0, 3 * sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);