Question

I have been playing around with OpenGL for a while now and wanted to get familiar with Vertex Array Objects(VAO's). I am using the cube example here to test with. First of all I verified that I could draw a cube by manually binding the two Vertex Buffers and Element Array Buffer and Vertex Attribs for each call of the render function Here is my code

    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);

       }

 

And here is the draw function


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);
}

The result is a cube as expected.

enter image description here

Using Vertex Array Object This is my implementation of the buffers being packed into a VAO. The initTest() with the following code:


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
}

Then in my draw function I just call the VAO like this


void Project::drawDebug()
{
    glBindVertexArray(vao);
    glDrawElements(GL_TRIANGLES,36, GL_UNSIGNED_SHORT, 0);
    glBindVertexArray(0);
}

However the result is this: enter image description here

Ultimately, I would like to know where I am going wrong with this. I also would like to know if you bind an ELEMENT_ARRAY_BUFFER within the currently bound VAO, do you need to explicity rebind that ELEMENT_ARRAY_BUFFER before calling glDraw* or does the VAO detect that it has an index buffer and renders using indices.

Was it helpful?

Solution

It is going wrong here:

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);

This has nothing to do with VAOs at all, and would fail without VAOs the same way.

When switching to VAOs, you also seem to have switched from using two separate VBOs for your attributes. You can of course do that, and you could have done it that way without VAOs. But you have to do it correctly: glVertexAttribPointer() will make the currently bound GL_ARRAY_BUFFER part of the attrib pointer, which is vbo[1] in both cases. So you are using the color data as color and position.

However, your original code was also wrong: It did only use the postion data as color and position (which together with the clamping of the color values to the range [0,1] resulted in that asymmetrical coloring you get).

As I side note: whenever you see two GL binding operations for the same binding target right after another, the first one is always useless.

So the correct code would be (if you are acutally using two different VBOs now, which is unclear):

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);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top