我试图在OpenGL中绘制2个对象。窗口/视口是(0,0,950,1050)。我不确定这是正确的做法,但我是这么认为的。我认为这个想法是为每个对象创建一个VBO / VAO,绑定它,设置数据,并为每个对象重复该操作。
然后在绘制对象时:
当我这样做时,我只获得在屏幕上绘制的第二个对象的点,但是使用第一个对象的颜色(它是蓝色而不是红色)。
我的错误必须对那里的任何专家都很明显。我错过了什么?
// BLUE -----------------------------------
GLuint vbo1, vao1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// RED -----------------------------------
GLuint vbo2, vao2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
while (!glfwWindowShouldClose(window))
{
glClearColor(1, 1, 1, 0.1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pointShader);
GLint loc;
loc = glGetUniformLocation(pointShader, "pointColor");
// it draws this one but with the color blue!
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float ptColor2[3] = { 1, 0, 0 };
glUniform3fv(loc, 1, ptColor2);
glDrawArrays(GL_POINTS, 0, 4);
// it doesn't draw this one???
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float ptColor1[3] = { 0, 0, 1 };
glUniform3fv(loc, 1, ptColor1);
glDrawArrays(GL_POINTS, 0, 4);
glfwSwapBuffers(window);
glfwWaitEvents();
}
非常感谢Reto Koradi和Datenwolf。结合答案,有助于得到正确的答案。遗憾的是,书中没有正确解释这些事情。希望这篇文章能够帮助其他初学者(对不起,如果结果有点误导,我在询问问题时和我得到答案时交换颜色)。
// RED -----------------------------------
GLuint vbo1, vao1;
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// BLUE -----------------------------------
GLuint vbo2, vao2;
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
while (!glfwWindowShouldClose(window))
{
float ratio;
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glClearColor(1, 1, 1, 0.1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(pointShader);
GLint loc;
loc = glGetUniformLocation(pointShader, "pointColor");
// red
glBindVertexArray(vao1);
float ptColor1[3] = { 1, 0, 0 };
glUniform3fv(loc, 1, ptColor1);
glDrawArrays(GL_POINTS, 0, 4);
// blue
glBindVertexArray(vao2);
float ptColor2[3] = { 0, 0, 1 };
glUniform3fv(loc, 1, ptColor2);
glDrawArrays(GL_POINTS, 0, 4);
glfwSwapBuffers(window);
glfwWaitEvents();
}
请注意,虽然VAO / VBO订单声明的第一个代码片段的顺序也可以。所以上面的版本和下面的版本都是有效的:
// RED -----------------------------------
GLuint vbo1, vao1;
glGenBuffers(1, &vbo1);
glBindBuffer(GL_ARRAY_BUFFER, vbo1);
float arr1[] = { 10, 10, 10, 110, 110, 110, 110, 10 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr1, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao1);
glBindVertexArray(vao1);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
// BLUE -----------------------------------
GLuint vbo2, vao2;
glGenBuffers(1, &vbo2);
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
float arr2[] = { 400, 400, 400, 800, 800, 800, 800, 400 };
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 8, arr2, GL_STATIC_DRAW);
glGenVertexArrays(1, &vao2);
glBindVertexArray(vao2);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray(0);
代码中唯一缺少的是glBindVertexArray
。
答案 0 :(得分:2)
在指定顶点属性数据位置(glVertexAttribPointer)之前,必须创建并绑定顶点数组对象。 VAO类型在进行这些调用时获取属于当前绑定的VBO的数据的所有权。
(EDIT在打字时意外提交)
假设您有一个核心配置文件上下文,当您尝试创建第一个缓冲区对象时,尚未将VAO绑定到它,因此整个BO的创建失败。因此,当您尝试绘制它时,根本没有绘制任何内容。但是你看到的是你想要绑定到第二个VAO的BO,但是由于你的操作顺序错误,它最终会出现在第一个VAO中。
答案 1 :(得分:2)
问题出在您的绘制循环中,您可以在其中调用:
glBindBuffer(GL_ARRAY_BUFFER, vbo2);
进行绘制调用时,当前绑定的GL_ARRAY_BUFFER
无关紧要。当您调用glVertexAttribPointer()
时,需要绑定正确的缓冲区,这是您在设置代码中正确执行的操作。
VAO跟踪所有顶点设置状态。因此,在每次绘制调用之前,您需要通过调用glBindVertexArray()
来绑定相应的VAO,而不是在发布的代码中调用glBindBuffer()
:
glBindVertexArray(vao2);
glUniform3fv(...);
glDrawArrays(...);
glBindVertexArray(vao1);
glUniform3fv(...);
glDrawArrays(...);