Search code examples
c++opengl3dvertex-array-object

Issue with glGenVertexArrays and glGenVertexBuffers when drawing several cubes


I have written a small program that is supposed to display several cubes with OpenGL 4.3. I use SDL 2.0 to create a context but I don't think my problem comes from there.

I have a class Cube that has several attributes, including a GLuint m_vao for the Vertex Array and a GLuint m_vbo for the Vertex Buffer.

To display several cubes, I create several instances of this class with different coordinates. I use glGenVertexArrays(1, &m_vao) and glGenBuffers(1, &m_vbo) in the constructor of the Cube.

I have no issue when creating cubes like this :

Cube c(-4, 0, -4, "texture.jpg");
Cube c2(4, 0, 2, "texture.jpg");
Cube c3(2, 1, 2, "texture.jpg");
Cube c4(-2, 1, 2, "texture.jpg");

This creates four cubes with unique m_vao and m_vbo attributes (1 for c, 2 for c2, 3 for c3 and 4 for c4).

However, when I create my cubes like this:

std::vector<std::vector<Cube>> cubes;
for (int i = 0; i < 9; i++) {
    cubes.push_back(std::vector<Cube>());
    for (int j = 0; j < 9; j++) {
        Cube temp = Cube(i, 0, j, "texture.jpg");
        cubes[i].push_back(temp);
    }
}

All the cubes inside my vector have the same m_vao and m_vbo attributes, in this case they all have 1 as m_vao and m_vbo. If I do it after creating the cubes c, c2, c3 and c4 manually, they all get 4. Of course, since they all use the same VBO, they all have the same coordinates and only one cube appears in the end.

So my question is: what is different between creating the cubes manually (which works fine) and creating them inside a std::vector with a for loop (which generates the same VAO and VBO for all the cubes) ?


Solution

  • I'm assuming, that you call glDeleteBuffers in the destructor? When pushing the temporary cube into the vector, temp::~Cube() is called when temp goes out of context, which releases the buffers. The next cube will then get the already freed id.

    for (int j = 0; j < 9; j++)
    {
    
        // Calls Cube(...)
        Cube temp = Cube(i, 0, j, "texture.jpg");
    
        // Copies or movies temp into the vector
        // In cases where cubes has to resize, also Cube::~Cube() is called
        cubes[i].push_back(temp);
    
        // temp goes here out of scope so temp::~Cube() is called
    }