Search code examples
c++openglrenderingopengl-3

Can I call `glDrawArrays` multiple times while updating the same `GL_ARRAY_BUFFER`?


In a single frame, is it "allowed" to update the same GL_ARRAY_BUFFER continuously and keep calling glDrawArrays after each update?

I know this is probably not the best and not the most recommended way to do it, but my question is: Can I do this and expect to get the GL_ARRAY_BUFFER updated before every call to glDrawArrays ?

Code example would look like this:

// setup a single buffer and bind it
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);

while (!renderStack.empty())
{
    SomeObjectClass * my_object = renderStack.back();
    renderStack.pop_back();

    // calculate the current buffer size for data to be drawn in this iteration
    SomeDataArrays * subArrays = my_object->arrayData();
    unsigned int totalBufferSize = subArrays->bufferSize();
    unsigned int vertCount = my_object->vertexCount();

    // initialise the buffer to the desired size and content
    glBufferData(GL_ARRAY_BUFFER, totalBufferSize, NULL, GL_STREAM_DRAW);

    // actually transfer some data to the GPU through glBufferSubData
    for (int j = 0; j < subArrays->size(); ++j)
    {
        unsigned int subBufferOffset = subArrays->get(j)->bufferOffset();
        unsigned int subBufferSize = subArrays->get(j)->bufferSize();
        void * subBufferData = subArrays->get(j)->bufferData();

        glBufferSubData(GL_ARRAY_BUFFER, subBufferOffset, subBufferSize, subBufferData);

        unsigned int subAttributeLocation = subArrays->get(j)->attributeLocation();

        // set some vertex attribute pointers
        glVertexAttribPointer(subAttributeLocation, ...);
        glEnableVertexAttribArray(subAttributeLocation, ...);
    }

    glDrawArrays(GL_POINTS, 0, (GLsizei)vertCount);
}

You may ask - why would I want to do that and not just preload everything onto the GPU at once ... well, obvious answer, because I can't do that when there is too much data that can't fit into a single buffer.

My problem is, that I can only see the result of one of the glDrawArrays calls (I believe the first one) or in other words, it appears as if the GL_ARRAY_BUFFER is not updated before each glDrawArrays call, which brings me back to my question, if this is even possible.

I am using an OpenGL 3.2 CoreProfile (under OS X) and link with GLEW for OpenGL setup as well as Qt 5 for setting up the window creation.


Solution

  • Yes, this is legal OpenGL code. It is in no way something that anyone should ever actually do. But it is legal. Indeed, it makes even less sense in your case, because you're calling glVertexAttribPointer for every object.

    If you can't fit all your vertex data into memory, or need to generate it on the GPU, then you should stream the data with proper buffer streaming techniques.