VAO and VBOs for rendering different objects

I wrote this "Model" class to load .obj files and distribute data for them in VBO. Its code looks something like this: (note how it does not use VAO)

class Model {...}

void Model::LoadOBJ(const char *file)
{
    //load vertices, normals, UVs, and put them all in _vec, which is a private data member of std::vector<glm::vec3>
    ...

    //if an .obj file is loaded for the first time, generate a buffer object and bind it
    if(glIsBuffer(_vbo) == GL_FALSE)
    {
        glGenBuffers(1, &_vbo);//_vbo is a private data member
        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    }

    //load the data in the array buffer object
    glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3) * _vec.size(), &_vec[0][0], GL_STATIC_DRAW);
}

void Model::Draw()
{
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glDrawArrays(GL_TRIANGLES, 0, _numVertices);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
}

I used to think that the following code would work just fine for rendering two different objects:

void init()
{
    //vao dummy (?)
    GLuint VAO;
    glGenVertexArrays(1, &VAO);
    glBindVertexArray(VAO);

    //load 3d models
    Model cube = load("cube.obj");
    Model cow = load("cow.obj");

    //the next two lines should be valid for both objects?
    glVertexAttribPointer(prog.GetAttribLocation("vertex"), 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(prog.GetAttribLocation("vertex"));
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    //draw cube:
    //some matrix transformations
    ...
    cube.Draw();

    //draw cow:
    //some matrix transformations
    ...
    cow.Draw()

    glutSwapBuffers();
}

but it turns out that OpenGL will just draw two cows or two cubes. (depends on which model is loaded last in init ()) two cowstwo cubes

By the way, I’m sure that in the first image opengl tried to draw two cows, but the glDrawArrays () function was called with the number of vertices needed for the cube.

So what am I missing? Do I need a different VAO for each buffer object or something like that?

+4
2

, glVertexAttribPointer.

glVertexAttribPointer (...) , GL_ARRAY_BUFFER. , Buffer Object Vertex, , .

OpenGL:

GLuint GL_ARRAY_BUFFER_BINDING = 0; // Only 1 or 2 commands in GL care about this state
GLuint GL_VERTEX_ARRAY_BINDING = 0; // 0 is an invalid VAO (if this is 0, most vertex commands will generate `GL_INVALID_OPERATION`).

// Generic GPU-side Memory Store
struct GLBufferObject {
  GLsizeiptr* gpu_base_addr;
} *gl_buffer_objects;

// Vertex Array State
struct GLVertexArrayObject {
  GLsizeiptr* attribute_pointers [GL_MAX_VERTEX_ATTRIBUTES];
  GLboolean   attribute_enabled  [GL_MAX_VERTEX_ATTRIBUTES];
  GLuint      GL_ELEMENT_ARRAY_BUFFER_BINDING;
} *gl_array_objects;

void glBindVertexArray (GLuint array)
{
  GL_VERTEX_ARRAY_BINDING = array;
}

void glBindBuffer (GLenum target, GLuint buffer)
{
  if (target == GL_ARRAY_BUFFER)
    GL_ARRAY_BUFFER_BINDING = buffer;
}

void glVertexAttribPointer (GLuint index, ..., const GLvoid* offset)
{
  GLBufferObject*      current_vbo = &gl_buffer_objects [GL_ARRAY_BUFFER_BINDING];
  GLVertexArrayObject* current_vao = &gl_array_objects  [GL_VERTEX_ARRAY_BINDING];

  current_vao->attribute_pointers [index] = current_vbo->gpu_base_addr + offset;
}

, OpenGL , , GL_ARRAY_BUFFER, : glVertexAttribPointer (...).

, glDrawArrays (...), , "current_vao", glVertexAttribPointer (...).


, VAO . VAO, , , .

, GLVetexArrayObject , , . glVertexAttribPointer void Model::Draw().

. ..

+4

( ) . .

, vao, ( vao) , .

+2

All Articles