Search code examples
openglvboidovao

Simple curiosity about OpenGL VBO allocation


I have written a simple graphic engine using OpenGL and GLSL. Until here, when I needed to create a new mesh scene node I created a VAO, a VBO and an IBO for each mesh. I loaded my vertex attributes for each mesh this way:

glBufferData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION)
        + this->GetVerticesByteSize(VERTEX_TEXTURE) + this->GetVerticesByteSize(VERTEX_NORMAL), NULL, this->m_Usage);
    glBufferSubData(GL_ARRAY_BUFFER, 0, this->GetVerticesByteSize(VERTEX_POSITION), &this->m_VertexBuffer[VERTEX_POSITION][0]);
    if (!this->m_VertexBuffer[VERTEX_TEXTURE].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION),
            this->GetVerticesByteSize(VERTEX_TEXTURE), &this->m_VertexBuffer[VERTEX_TEXTURE][0]);
    if (!this->m_VertexBuffer[VERTEX_NORMAL].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(
            VERTEX_POSITION) + this->GetVerticesByteSize(VERTEX_TEXTURE),
                this->GetVerticesByteSize(VERTEX_NORMAL), &this->m_VertexBuffer[VERTEX_NORMAL][0]);

But if the scene is composed by a lot of meshes it's not correct for the performance (too many state changes). So, I decided to create a unique VAO, VBO and IBO (singleton classes) for all the geometry of my scene.

The way to do this is the following :

Load all the vertex attributes in a specific class (let's call it 'VertexAttributes') for each mesh. After all the meshes are loaded we can allocate the big vertex buffer in a unique VBO. So like above I call in first the function 'glBufferData' to allocate the whole memory with the size of all the vertex attributes in my scene and after that call the function 'glBufferSubData' for each kind of vertex attribute in a loop.

But is it possible to call glBufferData several times (for each mesh) and fill the VBO during the scene loading (step by step for each mesh). So it looks like a realloc. Is it possible to do this with OpenGL or my first method is the good one ?


Solution

  • But is it possible to call glBufferData several times (for each mesh) and fill the VBO during the scene loading (step by step for each mesh). So it looks like a realloc. Is it possible to do this with OpenGL or my first method is the good one ?

    No. Whenever you call glBufferData, a new data storage (with the new size is created, and the previous contents are lost.

    However, combining multiple objects in the same VBO is still a valid strategy in many cases, especially if many of those objects are likely to be drawn together.

    You cannot dynamically resizes buffer objects. What you can do is pre-allocate bigger buffers and update parts of it. Having a bunch of reasonably-sized buffers available and dynamically fill can be a viable strategy. Note that there is also GL_ARB_copy_buffer (in core since GL 3.1, so widely available) which will allow you quite efficient server-side copies, and you can even emulate the "realloc" behavior by allocating a new buffer and copying the old contents over.

    Which strategy is best will always depend on the situation. If you often load or destroy objects dynamically, using some complex buffer allocation and management strategies might pay off.