1

my program uses one VAO, 2 VBOs and 2 EBOs. The program draws from the VBO very oddly This is how the program should function:

//cube
GLfloat vertices1[] = {
   0.5f, 0.5f, 0.5f,
   0.5f, 0.5f, -0.5f,
   0.5f, -0.5f, 0.5f,
   0.5f, -0.5f, -0.5f,
   -0.5f, 0.5f, 0.5f,
   -0.5f, 0.5f, -0.5f,
   -0.5f, -0.5f, 0.5f,
   -0.5f, -0.5f, -0.5f,
};
GLint indices1[]{
   2, 0, 4,
   4, 6, 2,
   0, 2, 3,
   3, 1, 0,
   5, 1, 3,
   3, 7, 5,
   0, 1, 5,
   4, 0, 5,
   6, 4, 7,
   4, 5, 7,
   7, 3, 2,
   7, 2, 6,
};

//loaded model
std::vector < GLfloat > teddy_vertices;
std::vector < GLuint > teddy_indices;
loadOBJ("teddy.obj", teddy_vertices, teddy_indices);

GLuint VAO, TEDDY, TEDDY_EBO, newVBO, newEBO;
glGenVertexArrays(1, & VAO);
glGenBuffers(1, & TEDDY);
glGenBuffers(1, & TEDDY_EBO);
glGenBuffers(1, & newVBO);
glGenBuffers(1, & newEBO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, newVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid * ) 0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
glBufferData(GL_ARRAY_BUFFER, teddy_vertices.size() * sizeof(GLfloat), & teddy_vertices.front(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid * ) 0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, TEDDY_EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, teddy_indices.size() * sizeof(GLuint), & teddy_indices.front(), GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind

glBindVertexArray(0);

//...

while (!glfwWindowShouldClose(window)) {
    glfwPollEvents();

    glClearColor(0.2 f, 0.3 f, 0.3 f, 1.0 f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glm::mat4 model_matrix = glm::mat4(1.0 f);
    glm::mat4 view;
    glm::mat4 tilt_view;
    glm::mat4 projection;

    view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); //cameraPos + cameraFront

    projection = glm::perspective(fov, (GLfloat) WIDTH / (GLfloat) HEIGHT, 0.1 f, 100.0 f);

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model_matrix));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
    glUniform4fv(color, 1, glm::value_ptr(glm::vec4(1, 1, 1, 1)));

    glBindVertexArray(VAO);

    if (!teddy_render) {
        glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
        glDrawElements(
            GL_TRIANGLES,
            teddy_indices.size(),
            GL_UNSIGNED_INT,
            (void * ) 0
        );
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    } else {
        glBindBuffer(GL_ARRAY_BUFFER, newVBO);
        glDrawElements(
            GL_TRIANGLES,
            36,
            GL_UNSIGNED_INT, 0);
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    glBindVertexArray(0);

    glfwSwapBuffers(window);
}

glfwTerminate();
return 0;
}

this code only draws the loaded object incorrectly, and does not draw from the other VBO when wanted.

If in the game loop the code is changed to :

glBindVertexArray(VAO);

//if (!teddy_render){ 
glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
glDrawElements(
    GL_TRIANGLES,
    teddy_indices.size(),
    GL_UNSIGNED_INT,
    (void * ) 0
);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//}
//else{
// glBindBuffer(GL_ARRAY_BUFFER, newVBO);
// glDrawElements(
//             GL_TRIANGLES, 
//              36, 
//             GL_UNSIGNED_INT, 0);
// glBindBuffer(GL_ARRAY_BUFFER, 0);
//}

then the loaded object renders. Then if in the configuration above the game loop the, cube is configured after the object, the cube renders even though the loaded object is being bound in the game loop with the cube code still commented out:

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
glBufferData(GL_ARRAY_BUFFER, teddy_vertices.size() * sizeof(GLfloat), & teddy_vertices.front(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid * ) 0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, TEDDY_EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, teddy_indices.size() * sizeof(GLuint), & teddy_indices.front(), GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, newVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices1), vertices1, GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, newEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices1), indices1, GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid * ) 0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0);

glBindVertexArray(0);

Thank you.

EDIT: This is working code that uses many VBOs with 1 VAO without EBOs:

std::vector<GLfloat> teddy_vertices;
loadOBJ("teddy.obj", teddy_vertices); //read the vertices from the teddy.obj file

GLuint VAO, VBO, VBO_AXIS, TEDDY;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &VBO_AXIS);
glGenBuffers(1, &TEDDY);
// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointer(s).
glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, VBO_AXIS);
glBufferData(GL_ARRAY_BUFFER, sizeof(axis), axis, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
glBufferData(GL_ARRAY_BUFFER, teddy_vertices.size()*sizeof(GLfloat), &teddy_vertices.front(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
glEnableVertexAttribArray(0);

glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind

glBindVertexArray(0);

//... in game loop

    glBindVertexArray(VAO);

    if (!teddy_render){
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
        glEnableVertexAttribArray(0);
        glDrawArrays(render_mode, 0, 36);
    }
    else{
        glBindBuffer(GL_ARRAY_BUFFER, TEDDY);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
        glEnableVertexAttribArray(0);
        glDrawArrays(render_mode, 0, teddy_vertices.size());
    }
    glBindVertexArray(0);
rur2641
  • 691
  • 1
  • 10
  • 26

1 Answers1

1

There is only ONE elements buffer assigned to each VAO. Therefore only the last of your calls to glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *) has any effect.

See what state VAOs contain.

Yakov Galka
  • 70,775
  • 16
  • 139
  • 220
  • I have a program that uses many VBO2s with 1 VAO. Please see edit. In the program that uses EBO, why would binding the element array buffer in the game loop after binding array buffer not work? – rur2641 May 28 '17 at 16:15
  • @rur2641: The answer is still the same. You can have many VBOs but only **ONE** element buffer. Your code does otherwise. – Yakov Galka May 28 '17 at 16:19