Search code examples
c++openglvbovao

OpenGL VAO is pointing to address 0 for some reason


I am having some trouble with my VAO not binding properly (at least that's what I think is happening).

So, what I am doing is I have a class that is creating a vbo and vao from some raw data, in this case a pointer to an array of floats.

RawModel* Loader::loadToVao(float* positions, int sizeOfPositions) {
    unsigned int vaoID = this->createVao();
    this->storeDataInAttributeList(vaoID, positions, sizeOfPositions);
    this->unbindVao();
    return new RawModel(vaoID, sizeOfPositions / 3);
}

unsigned int Loader::createVao() {
    unsigned int vaoID;
    glGenVertexArrays(1, &vaoID);
    glBindVertexArray(vaoID);

    unsigned int copyOfVaoID = vaoID;
    vaos.push_back(copyOfVaoID);
    return vaoID;
}

void Loader::storeDataInAttributeList(unsigned int attributeNumber, float* data, int dataSize) {
    unsigned int vboID;
    glGenBuffers(1, &vboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);
    glBufferData(GL_ARRAY_BUFFER, dataSize * sizeof(float), data, GL_STATIC_DRAW);
    glVertexAttribPointer(attributeNumber, 3, GL_FLOAT, false, 0, 0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);

    unsigned int copyOfVboID = vboID;
    vbos.push_back(copyOfVboID);
}

void Loader::unbindVao() {
    glBindVertexArray(0);
}

The RawModel is just a class that should take in the array of floats and create a vbo and a vao. The vectors vbos and vaos that I am using are just there to keep track of all the ids so that I can delete them once I am done using all the data.

I am 90% confident that this should all work properly. However, when I go to try and just run some code that would draw it, OpenGL is exiting because it is trying to read from address 0x0000000 and it doesn't like that. I pass the raw model that I created from the code before this into a function in my renderer that looks like this:

void Renderer::render(RawModel* model) {
    glBindVertexArray(model->getVaoID());
    glEnableVertexAttribArray(0);   
    glDrawArrays(GL_TRIANGLES, 0, model->getVertexCount());
    glDisableVertexAttribArray(0);
    glBindVertexArray(0);
}

I have checked to make sure that the VaoID is the same when I am creating the vao, and when I am trying to retrieve the vao. It is in fact the same.

I have no idea how to read what address is currently stored in whatever OpenGL has currently bound as the vertex attrib array, so I cannot test whether or not it is pointing to the vertex data. I'm pretty sure that it's pointing to address 0 for some reason though.

Edit:

It turns out it was not the hard-coded 0 that was a problem. It removed the errors that Visual Studio and OpenGL were giving me, but the actual error was somewhere else. I realized that I was passing in the vaoID as the attributeNumber in some of the code above, when I should have been passing in a hard-coded 0. I edited my code here:

RawModel* Loader::loadToVao(float* positions, int sizeOfPositions) {
    unsigned int vaoID = this->createVao();
    this->storeDataInAttributeList(0, positions, sizeOfPositions);
    this->unbindVao();
    return new RawModel(vaoID, sizeOfPositions / 3);
}

I changed the line this->storeDataInAttributeList(vaoID, positions, sizeOfPositions); to what you see above, with a hard-coded 0. So, it turns out I wasn't even binding the array to the correct location in the vbo. But, after changing that it worked fine.


Solution

  • You should be using your vertex attribute index with glVertexAttribPointer, glEnableVertexAttribArray and glDisableVertexAttribArray but what you've got is:

    • VAO id used with glVertexAttribPointer
    • hard coded 0 used with glEnableVertexAttribArray and glDisableVertexAttribArray (this isn't necessarily a bug though if you're sure about the value)

    If you are not sure about the index value (e.g. if you don't specify the layout in your shader) then you can get it with a glGetAttribLocation call:

    // The code assumes `program` is created with glCreateProgram
    // and `position` is the attribute name in your vertex shader
    
    const auto index = glGetAttribLocation(program, "position");
    

    Then you can use the index with the calls mentioned above.