我一直在玩OpenGL一段时间,想要熟悉Vertex Array Objects(VAO' s)。我正在使用多维数据集示例here进行测试。首先,我验证了我可以通过为渲染函数的每次调用手动绑定两个顶点缓冲区和元素阵列缓冲区和顶点Attrib来绘制一个立方体。这是我的代码
void Project::initTest(void)
{
GLfloat cube_vertices[] = {
// front
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
};
glGenBuffers(1, &vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
GLfloat cube_colors[] = {
// front colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
// back colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
};
glGenBuffers(1, &vbo[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colors), cube_colors, GL_STATIC_DRAW);
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// top
3, 2, 6,
6, 7, 3,
// back
7, 6, 5,
5, 4, 7,
// bottom
4, 5, 1,
1, 0, 4,
// left
4, 0, 3,
3, 7, 4,
// right
1, 5, 6,
6, 2, 1,
};
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
glBindBuffer(GL_ARRAY_BUFFER,0);
}
这是绘图功能
void Project::drawTest()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 1);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
}
结果是预期的多维数据集。
使用顶点数组对象 这是我将缓冲区打包到VAO中的实现。 initTest()包含以下代码:
void Project::initTest()
{
//Upload Vertex Data into VBO's
//Upload Index Data into Element Array Buffer
//...
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
glBindVertexArray(0);
//Unbind ARRAY and ELEMENT_ARRAY Buffers like before
}
然后在我的绘图功能中,我就像这样调用VAO
void Project::drawDebug()
{
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES,36, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
}
但结果如下:
最终,我想知道我在哪里出错了。我还想知道你是否在当前绑定的VAO中绑定ELEMENT_ARRAY_BUFFER,你是否需要在调用glDraw *之前明确重新绑定ELEMENT_ARRAY_BUFFER,或者VAO是否检测到它有索引缓冲区并使用索引进行渲染。
答案 0 :(得分:3)
这里出错:
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
这与VAO完全无关,如果没有VAO也会失败。
当切换到VAO时,您似乎也已从使用两个单独的VBO切换为您的属性。你当然可以这样做,你可以在没有VAO的情况下这样做。但是你必须正确地做到这一点:glVertexAttribPointer()
将使当前绑定 GL_ARRAY_BUFFER
attrib指针的一部分,中的vbo[1]
案件。所以你使用颜色数据作为颜色和位置。
然而,您的原始代码也是错误的:它只使用位置数据作为颜色和位置(它与颜色值到范围[0,1]的钳位一起导致您得到的不对称颜色)。
正如我所注意的那样:每当你看到同一个绑定目标的两个GL绑定操作一个接一个,第一个总是无用的。
所以正确的代码就是(如果你现在正在使用两个不同的VBO,目前还不清楚):
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);