从不同的VBO中提取问题

时间:2017-05-28 13:46:37

标签: c++ opengl

我的程序使用一个VAO,2个VBO和2个EBO。该程序非常奇怪地从VBO中抽取 这就是程序应该如何运作:

//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;
}

此代码仅错误地绘制加载的对象,并且在需要时不从其他VBO中绘制。

如果在游戏循环中代码更改为:

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(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);

谢谢。

编辑: 这是使用许多带有1个VAO而没有EBO的VBO的工作代码:

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);

1 个答案:

答案 0 :(得分:0)

每个VAO只分配 ONE 元素缓冲区。因此,只有glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *)的最后一次通话才会生效。

请参阅what VAOs are