Search code examples
c++openglglm-mathvbovao

Problem displaying multiple objects in modern OpenGL


I'm trying to display two shapes in OpenGL. First I got the vertices,uvs, normals,indices from an obj file and texture form DDS and stored them in an array of struct Shape.

Then I indexed the vertices, uvs, normals and indices for all the shapes in 4 respective array, also storing the number of total number of vertices, uvs , normals and indices in another vector. Then I initialized the VBOs.

Then I creates vertex array objects for the two shapes and set them up giving respective VertexAttribPointer. (I think the problem is in this step)

Finally I bind the respective VAOs and display them but only one shape is being displayed. Where exactly am I going wrong.

Code for VBOindexing :

std::vector<glm::vec4> elecount;
long long int endind = 0,endver=0,enduv=0,endnr=0;

std::vector<unsigned short> indices;
std::vector<glm::vec3> indexed_vertices;
std::vector<glm::vec2> indexed_uvs;
std::vector<glm::vec3> indexed_normals;
for (int i = 0;i < componentcount ;i++)
{
    endver = endind = enduv = endnr = 0;
    indexVBO(component[i].vertices, component[i].uvs, component[i].normals, indices, indexed_vertices, indexed_uvs, indexed_normals);
    endind = indices.size();
    endver = indexed_vertices.size();
    enduv = indexed_uvs.size();
    endnr = indexed_normals.size();
    elecount.push_back(glm::vec4(endver, enduv, endnr, endind));
}

Code for VBOs :

GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);

GLuint uvbuffer;
glGenBuffers(1, &uvbuffer);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_uvs.size() * sizeof(glm::vec2), &indexed_uvs[0], GL_STATIC_DRAW);

GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);

GLuint elementbuffer;
glGenBuffers(1, &elementbuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);

Code for VAOs :

    GLuint CubeVertexArrayID, SphereVertexArrayID;
glGenVertexArrays(1, &CubeVertexArrayID);
glGenVertexArrays(1, &SphereVertexArrayID);

glBindVertexArray(CubeVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

glBindVertexArray(SphereVertexArrayID);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)(sizeof(glm::vec3) * ((int)elecount[0][0])));
glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec2) * ((int)elecount[0][1])));
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)(sizeof(glm::vec3) * ((int)elecount[0][2])));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);

Code for displaying :

    glBindVertexArray(CubeVertexArrayID);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, component[0].Texture);
    glUniform1i(TextureID, 0);
    glDrawElements(GL_TRIANGLES,(int)elecount[0][3],GL_UNSIGNED_SHORT,(void*)0);

    glm::mat4 ModelMatrix2 = glm::mat4(1.0);
    ModelMatrix2 = glm::translate(ModelMatrix2, glm::vec3(2.0f, 0.0f, 0.0f));
    glm::mat4 MVP2 = ProjectionMatrix * ViewMatrix * ModelMatrix2;
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP2[0][0]);
    glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix2[0][0]);
    glUseProgram(shaderProg);

    glBindVertexArray(SphereVertexArrayID);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, component[1].Texture);
    glUniform1i(TextureID, 0);
    glDrawElements(GL_TRIANGLES, (int)(elecount[1][3]-elecount[0][3]), GL_UNSIGNED_SHORT,(void*)(sizeof(unsigned short) * ((int)elecount[0][3])));

Solution

  • There's nothing wrong in the code you posted, so it's hard to say for sure where's the problem. However my best guess is that indexVBO (that you didn't show) pushes the absolute indices within indexed_* arrays. Combined with the offset glVertexAttribPointer of SphereVertexArrayID this causes out-of-bound reads.

    You could fix your indexVBO code. However, since both VAOs reference the same buffer, the simplest solution (and I would say, the correct solution) is to use a single VAO for both components. If my hypothesis is correct, it is as simple as changing the

    glBindVertexArray(SphereVertexArrayID);
    

    to

    glBindVertexArray(CubeVertexArrayID);
    

    when you're drawing the 2nd component. Then you can get rid of SphereVertexArrayID completely.