Search code examples
c++openglopengl-3

glDrawElements throws divide by zero error when using multiple VAO


I'm building a game using opengl. When I call glDrawElements, a divide by zero error from ig9icd32.dll is thrown. With a little bit of research I found that it's an Intel library

Since ig9icd32.dll is an Intel driver, I tried to run the game with the dedicated GPU, but the same error occurs.

Using a single VAO and compiling without drawing the second does not give any errors. I checked VAO generation and VBO bindings: they work just fine.

    {
        glGenVertexArrays(1, &m_HighwayVAO);
        glGenVertexArrays(1, &m_lanesVAO);

        {
            glBindVertexArray(m_HighwayVAO);

            unsigned int vbo, ebo;
            glGenBuffers(1, &vbo);
            glGenBuffers(1, &ebo);

            glBindBuffer(GL_ARRAY_BUFFER, vbo);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);

            //Vertex: x,y,z, u,v
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
            glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);

            glBindVertexArray(0);
        }


        {

            glBindVertexArray(m_lanesVAO);

            unsigned int buffer, index;
            glGenBuffers(1, &buffer);
            glGenBuffers(1, &index);
            glBindBuffer(GL_ARRAY_BUFFER, buffer);
            glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);

            //Vertex: x,y,z, r,g,b,
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), 0);
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));
            glEnableVertexAttribArray(0);
            glEnableVertexAttribArray(1);


            glBindVertexArray(0);

        }

    }

this is where I initialize the VAO's. They are on separated scopes just so I can collapse on the editor. Without scopes the same error occurs.

m_HighwayVAO and m_lanesVAO are variables defined in a Header.They are initialised to 0.

void Rendr::highway(double time) {

    float factor = time / 3;
    //Vertex: x,y,z, u,v
    float data[] = {
            -1.0f, 0.0f, 0.0f, 0.0f, 1.0f + factor,
             1.0f, 0.0f, 0.0f, 1.0f, 1.0f + factor,
            -1.0f, 0.0f, 6.0f, 0.0f, 0.0f + factor,
             1.0f, 0.0f, 6.0f, 1.0f, 0.0f + factor
    };

    unsigned int indices[] = {
            0,2,3,
            3,1,0
    };

    glBindVertexArray(m_HighwayVAO);

    glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);

    glUseProgram(m_TextureProgram);
    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(int), GL_UNSIGNED_INT, (void*)0);
    //error thrown here

    glBindVertexArray(0);

}

If you need more code, I'll be happy to add to the post.

Thanks in advance for the help.


Solution

  • To creates and initializes a buffer object's data store, you've to bind the proper ARRAY_BUFFER buffer object:

    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
    

    glBindVertexArray does not bind any buffer object to a ARRAY_BUFFER buffer target.


    Note, the last buffer which is bound to the target ARRAY_BUFFER, is buffer:

    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    

    This state is kept and is never changed again. So the buffer object's data store for vbo is never created and initialized.

    This behaves different to the index buffer (ELEMENT_ARRAY_BUFFER). The index buffer binding is stored within the Vertex Array Object.
    Note, each attribute which is stated in the VAOs state vector may refer to a different ARRAY_BUFFER. This reference is stored when glVertexAttribPointer is called. Then the buffer which is currently bound to the target ARRAY_BUFFER is associated to the attribute and the name (value) of the object is stored in the state vector of the VAO.