0
votes

I am trying to draw two different meshes using OpenGL 4.1. At any given time, only one of the meshes will be drawn, and my goal is to switch between them. I am storing the vertex and index data for the meshes in an object, which below, is called g_obj. So, the data for the first mesh is gotten by g_obj->vertices_ and g_obj->indices, and the data for the second mesh is gotten from g_obj->vertices_linear_ and g_obj->indices_linear_.

My horrible idea is to have distinct VBO's and VAO's for each mesh. Then on the draw call, I would simply bind the appropriate VAO and then do glDraw*. However, my code segfaults on the first draw call (see below).

enum VAO_ID 
{
    VAO,
    VAO_LINEAR,
    NUM_VAOS
};

enum BUFFER_ID 
{
    VERTEX_BUFFER,
    VERTEX_BUFFER_LINEAR,
    INDEX_BUFFER,
    INDEX_BUFFER_LINEAR,
    NUM_BUFFERS
};

enum ATTRIBUTE_ID 
{
    VERTEX_POSITION,
    VERTEX_COLOR
};

GLuint g_vaos[NUM_VAOS];
GLuint g_buffers[NUM_BUFFERS];

further down, I create vertex/index buffers and vertex array objects:

void bufferGeometry()
{

   // create vertex buffers and vertex array object 
    glGenVertexArrays(NUM_VAOS, g_vaos);
    glGenBuffers(NUM_BUFFERS, g_buffers);

    // rotational grating
    glBindBuffer(GL_ARRAY_BUFFER, g_buffers[VERTEX_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER,
                 g_obj->num_vertices_ * sizeof(vertex2D),
                 g_obj->vertices_,
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffers[INDEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 g_obj->num_indices_ * sizeof(GLushort),
                 g_obj->indices_,
                 GL_STATIC_DRAW);
    glBindVertexArray(g_vaos[VAO]);
    glEnableVertexAttribArray(VERTEX_POSITION);
    glVertexAttribPointer(VERTEX_POSITION, 2, GL_FLOAT, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, position));
    glEnableVertexAttribArray(VERTEX_COLOR);
    glVertexAttribPointer(VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, color));
    glBindVertexArray(0);

    // linear grating
    glBindBuffer(GL_ARRAY_BUFFER, g_buffers[VERTEX_BUFFER_LINEAR]);
    glBufferData(GL_ARRAY_BUFFER,
                 g_obj->num_vertices_linear_ * sizeof(vertex2D),
                 g_obj->vertices_linear_,
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffers[INDEX_BUFFER_LINEAR]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 g_obj->num_indices_linear_ * sizeof(GLushort),
                 g_obj->indices_linear_,
                 GL_STATIC_DRAW);

    glBindVertexArray(g_vaos[VAO_LINEAR]);
    glEnableVertexAttribArray(VERTEX_POSITION);
    glVertexAttribPointer(VERTEX_POSITION, 2, GL_FLOAT, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, position));

    glEnableVertexAttribArray(VERTEX_COLOR);
    glVertexAttribPointer(VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, color));

    glBindVertexArray(0);

}

then, here is the draw call:

glBindVertexArray(g_vaos[VAO]);
g_obj = &g_grating_uno;
glUseProgram(g_program);
glUniform3fv(g_trans_scale_location, 1, g_obj->trans_scale_);
glDrawElements(GL_TRIANGLES, g_obj->num_indices_,
               GL_UNSIGNED_SHORT, (const GLvoid *)0);

Which segfaults at the glDrawElements line.

I know that the general "performant" strategy is to pack data from both meshes in single VBO's, and since the data format is the same between the two meshes, then I only need one VAO. But, since I am lazy, I was wondering if anyone can see why my existing strategy does not work or cannot work or if you think the problem lies elsewhere. My guess is that it has to do with my bufferGeometry() function. I am a little weak in my understanding of how VAO's are linked to specific VBO's, if they are at all. Thanks, and sorry for being dumb!

2

2 Answers

0
votes

you should repeat the call to bind the element buffer between the glBindVertexArray:

glBindVertexArray(g_vaos[VAO]);
glEnableVertexAttribArray(VERTEX_POSITION);
glVertexAttribPointer(VERTEX_POSITION, 2, GL_FLOAT, GL_FALSE, 
                      sizeof(vertex2D),
                      (const GLvoid *)offsetof(vertex2D, position));
glEnableVertexAttribArray(VERTEX_COLOR);
glVertexAttribPointer(VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, 
                      sizeof(vertex2D),
                      (const GLvoid *)offsetof(vertex2D, color));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffers[INDEX_BUFFER]);
glBindVertexArray(0);

the element buffer binding is part of the VAO state and gets reset when a new VAO gets bound.

0
votes

Ah, fixed it (I think) by binding the VAO's before binding the VBO's:

void bufferGeometry()
{

   // create vertex buffers and vertex array object 
    glGenVertexArrays(NUM_VAOS, g_vaos);
    glGenBuffers(NUM_BUFFERS, g_buffers);

    // rotational grating
    glBindVertexArray(g_vaos[VAO]);
    glBindBuffer(GL_ARRAY_BUFFER, g_buffers[VERTEX_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER,
                 g_obj->num_vertices_ * sizeof(vertex2D),
                 g_obj->vertices_,
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffers[INDEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 g_obj->num_indices_ * sizeof(GLushort),
                 g_obj->indices_,
                 GL_STATIC_DRAW);
    glEnableVertexAttribArray(VERTEX_POSITION);
    glVertexAttribPointer(VERTEX_POSITION, 2, GL_FLOAT, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, position));
    glEnableVertexAttribArray(VERTEX_COLOR);
    glVertexAttribPointer(VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, color));
    glBindVertexArray(0);

    // linear grating
    glBindVertexArray(g_vaos[VAO_LINEAR]);
    glBindBuffer(GL_ARRAY_BUFFER, g_buffers[VERTEX_BUFFER_LINEAR]);
    glBufferData(GL_ARRAY_BUFFER,
                 g_obj->num_vertices_linear_ * sizeof(vertex2D),
                 g_obj->vertices_linear_,
                 GL_STATIC_DRAW);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_buffers[INDEX_BUFFER_LINEAR]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
                 g_obj->num_indices_linear_ * sizeof(GLushort),
                 g_obj->indices_linear_,
                 GL_STATIC_DRAW);

    glEnableVertexAttribArray(VERTEX_POSITION);
    glVertexAttribPointer(VERTEX_POSITION, 2, GL_FLOAT, GL_FALSE, 
                          sizeof(vertex2D),
                          (const GLvoid *)offsetof(vertex2D, position));

    glEnableVertexAttribArray(VERTEX_COLOR);
    glVertexAttribPointer(VERTEX_COLOR, 4, GL_UNSIGNED_BYTE, GL_FALSE, 
                          sizeof(vertex2D),
                         (const GLvoid *)offsetof(vertex2D, color));

    glBindVertexArray(0);

}