简体   繁体   中英

How to draw 2 or more objects with different VAO, VBO?

I want to draw cube and sphere, but openGl draws only cube. I've made 2 VAOs: first VAO contains VBO (with coordinates cube), other VAO contains coordinates sphere. If I want to draw only sphere, it doen't work as well. Maybe it happens because of inorrect VBO binding...but I don't exactly understand how to deal with it.

Code below (making sphere):

GLuint sphere(float radius, int slices, int stacks) {
GLuint vbo;
int n = 2 * (slices + 1) * stacks;
int i = 0;
vec3 *points = new vec3[n];

for (float theta = -M_PI / 2; theta < M_PI / 2 - 0.0001; theta += M_PI / stacks) {
    for (float phi = -M_PI; phi <= M_PI + 0.0001; phi += 2 * M_PI / slices) {
        points[i++] = vec3(cos(theta) * sin(phi), -sin(theta), cos(theta) * cos(phi));
        points[i++] = vec3(cos(theta + M_PI / stacks) * sin(phi), -sin(theta + M_PI / stacks), cos(theta + M_PI / stacks) * cos(phi));
    }
}

glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);

return vbo;}

Main (I remove cube coordinates in code, because it's too long):

glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "Laba5", nullptr, nullptr);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glewExperimental = GL_TRUE;
glewInit();

glViewport(0, 0, WIDTH, HEIGHT);
glEnable(GL_DEPTH_TEST);

Shader ourShader("shader.vs", "shader.frag");
GLuint VBO, VAO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
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);
glBindVertexArray(0); // Unbind VAO
//-----------------------------------------------------------2
GLuint VAO2;
glGenVertexArrays(1, &VAO2);
glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, sphere(1, 30, 30));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindVertexArray(0); // Unbind VAO

while (!glfwWindowShouldClose(window))
{

    // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
    glfwPollEvents();

    glClearColor(0.32f, 0.31f, 0.30f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    ourShader.Use();

    mat4 view = mat4(1.0);
    mat4 projection = mat4(1.0);
    view = translate(view, vec3(1.0f, 1.0f, -4.8f));
    projection = perspective(45.0f, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
    GLint modelLoc = glGetUniformLocation(ourShader.Program, "model");
    GLint viewLoc = glGetUniformLocation(ourShader.Program, "view");
    GLint projLoc = glGetUniformLocation(ourShader.Program, "projection");

    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

    if (lbutton_down)
    {
        double cur_mx, cur_my;
        glfwGetCursorPos(window, &cur_mx, &cur_my);
        if (cur_mx != last_mx || cur_my != last_my)
        {
            vec3 va = get_arcball_vector(last_mx, last_my);
            vec3 vb = get_arcball_vector(cur_mx, cur_my);
            float angle = acos(min(1.0f, dot(va, vb)));
            vec3 axis_in_camera_coord = cross(va, vb);
            mat3 camera2object = inverse(model);
            vec3 axis_in_object_coord = camera2object * axis_in_camera_coord;
            model = rotate(model, degrees(angle)*0.05f, axis_in_object_coord);
            last_mx = cur_mx;
            last_my = cur_my;
        }
    }

    glBindVertexArray(VAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);

    glBindVertexArray(VAO2);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 2 * 31 * 30);
    glBindVertexArray(0);

    glfwSwapBuffers(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteVertexArrays(1, &VAO2);
glfwTerminate();
return 0;

Your sphere function internally creates a new GL buffer object and returns its name, so:

 GLuint sphereVBO = sphere(1, 30, 30); 

you now have sphereVBO containing the name of that buffer.

 glGenVertexArrays(1, &VAO2); glGenBuffers(1, &sphereVBO); 

But now, you created a new buffer object, and did overwrite sphereVBO with the new name. As a result, you are trying to draw from an empty buffer object (there was no call to glBufferData to actually create a data storage for it), and you totally lost track of the original VBO with the sphere data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM