1

I've been trying to use Vertex Buffer Objects to save vertex data on the GPU and reduce the overhead, but I cannot get it to work. The code is below.

From what I understand you generate the buffer with glGenBuffers, then you bind the buffer with glBindBuffer so it's ready to be used, then you write data to it with glBufferData and its done and can be unbinded and ready for use later with simply binding it again.

However the last part is what I'm having trouble with, when I bind it after I have created and loaded data to it and try to draw using it, it gives me lots of GL Error: Out of Memory.

I doubt that I am running out of memory for my simple mesh, so I must be doing something very wrong.

Thanks.

EDIT 1: I call glGetError after every frame, but since this is the only OpenGL I do in the entire program it shouldn't be a problem

//when loading the mesh we create the VBO
void createBuffer()
{
    GLuint buf;
    glGenBuffers(1, &buf);
    glBindBuffer(GL_ARRAY_BUFFER, buf);
    glBufferData(GL_ARRAY_BUFFER, vertNormalBuffer->size() * sizeof(GLfloat), (GLvoid*) bufferData, GL_STATIC_DRAW);

    //EDIT 1: forgot to show how I handle the buffer
    model->vertexNormalBuffer = &buf;
    //Unbinds it
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}


void Fighter::doRedraw(GLuint shaderProgram)
{
    glm::mat4 transformationMatrix = getTransform();
    GLuint loc = glGetUniformLocation(shaderProgram,"modelviewMatrix");
    glUniformMatrix4fv(loc, 1, GL_FALSE, (GLfloat*) &transformationMatrix);

    glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);

    //If I uncomment this line below all works wonderfully, but isnt the purpose of VBO of not uploading the same data again and again?
    //glBufferData(GL_ARRAY_BUFFER, model->vertAndNormalArraySize * sizeof(GLfloat), model->vertAndNormalArray, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(2);

    renderChild(model, model);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void Fighter::renderChild(ModelObject* model, ModelObject* parent)
{
    //Recursively render the mesh children
    for(int i = 0; i < model->nChildren; i++)
    {
        renderChild( dynamic_cast<ModelObject*>(model->children[i]), parent);
    }
    //Vertex and normal data are interlieved
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat),(void*)(model-            >vertexDataPosition*sizeof(GLfloat)));
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (void*)((model->vertexDataPosition + 4)*sizeof(GLfloat)));

    //Draws using two sets of indices
    glDrawElements(GL_QUADS,  model->nQuads * 4, GL_UNSIGNED_INT,(void*) model->quadsIndices);
    glDrawElements(GL_TRIANGLES, model->nTriangles * 3, GL_UNSIGNED_INT, (void*) model->trisIndices);

}
NangiDev
  • 55
  • 6
  • I don't find any `glGetError` in your code. Where do you actually check? Do you check directly after you've created the buffer itself? Couldn't it be that you're just seeing an error from a previous operation? – Dolda2000 Feb 16 '14 at 00:22
  • Also, I don't see how you let `buf` "escape" from your `createBuffer` function. – Dolda2000 Feb 16 '14 at 00:25
  • Thanks @Dolda2000 for noticing, I edited the post to show what I do with buf and explain about when I call glGetError. – NangiDev Feb 16 '14 at 00:35

1 Answers1

5

This is your problem:

model->vertexNormalBuffer = &buf;
/* ... */
glBindBuffer(GL_ARRAY_BUFFER, *model->vertexNormalBuffer);

You're storing the address of your buf variable, rather than its contents, and then it falls out of scope when createBuffer returns, and is most likely overwritten with other data, so when you're later rendering, you're using an uninitialized buffer. Just store the contents of buf in your vertexNormalBuffer field instead.

I'll admit I don't know why OpenGL thinks it proper to say that it's "out of memory" just because of that, but perhaps you're just invoking undefined behavior. It does explain, however, why it starts working when you re-fill the buffer with data after you rebind it, because you then implicitly initialize the buffer that you just bound.

Dolda2000
  • 25,216
  • 4
  • 51
  • 92
  • Thanks! I am coming from Java and is very new to c++. This was the solution! – NangiDev Feb 16 '14 at 00:45
  • @user3021593: Just for reference, would you mind telling me what OpenGL implementation you're using? The driver, that is. – Dolda2000 Feb 16 '14 at 00:46
  • not sure, but my graphic card driver is Nvidia 9.18.13.3221 if that's what you are asking about. Where can I find what implementation I am using? – NangiDev Feb 16 '14 at 00:57
  • Thanks, that's exactly what I meant. – Dolda2000 Feb 16 '14 at 00:58
  • **+1**: But I feel this is worth asking... why did you answer this question twice? Individuals with 10K+ reputation can see deleted answers, so its not like you started with a clean slate by deleting your original answer ;) You probably could have edited the original instead of deleting it. – Andon M. Coleman Feb 16 '14 at 01:26
  • 1
    @AndonM.Coleman: Because I misread the code at first and thought he used the address of the variable when binding the buffer. It felt easier to delete and rewrite the answer than to edit it (especially considering someone might have read it and become confused during the edit). – Dolda2000 Feb 16 '14 at 01:28