渲染一个包含两个VBO的VAO [英] Render one VAO containing two VBOs

查看:809
本文介绍了渲染一个包含两个VBO的VAO的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在OpenGL 3.3的窗口中绘制两个三角形.我正在将GLFW库用于窗口系统.

I'm trying to draw two triangles in a window in OpenGL 3.3. I'm using the GLFW library for the windowing system.

据我了解,我应该有两个VBO (每个三角形一个)和一个VAO ,其中包含这两个VBO.那就是我所做的.

From what I understand, I should have two VBOs (one for each triangle) and one VAO containing these two VBOs. That's what I did.

但是,我无法弄清楚应如何渲染这两个VBO.确实,无论我做什么,都会仅绘制第一个 VBO(第一个三角形).第二个永远不会出现.

However, I can't figure out what calls I should make to render these two VBOs. Indeed, whatever I do, only the first VBO (first triangle) gets drawn. The second one never shows up.

int main()
{
    GLFWwindow *window = setupWindow();
    GLfloat triangle1Vertices[] = {
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    GLfloat triangle2Vertices[] = {
        0.f, -0.5f, 0.0f,
        0.8f, -0.5f, 0.0f,
        0.0f,  0.5f, 0.0f
    };
    GLuint vao, vbo[2];

    glGenVertexArrays(1, &vao);
    glGenBuffers(2, vbo);

    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle1Vertices), triangle1Vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2Vertices), triangle2Vertices, GL_STATIC_DRAW);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

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

        glClearColor(0.3f, 0.3f, 0.5f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);


        glBindVertexArray(vao);

        glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(0);


        glfwSwapBuffers(window);
    }

    glDeleteVertexArrays(1, &vao);
    glDeleteBuffers(2, vbo);

    glfwTerminate();

    return 0;
}

我显然错过了什么,但是呢?

I'm clearly missing something, but what?

推荐答案

据我了解,我应该有两个VBO(每个三角形一个)和一个包含这两个VBO的VAO.

From what I understand, I should have two VBOs (one for each triangle) and one VAO containing these two VBOs.

那你的理解是错误的.

如果要使用两个不同的缓冲区和两个不同的三角形,则要么需要两个不同的VAO,要么需要在呈现每个对象之间交换VAO使用的缓冲区.

If you want to have two different buffers with two different triangles, then you either need two different VAOs, or you need to swap which buffer the VAO uses between rendering each object.

您的呈现代码接近正确,但不完全正确:

Your rendering code is close to correct, but not quite:

    glBindVertexArray(vao);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glDrawArrays(GL_TRIANGLES, 0, 3);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
    glDrawArrays(GL_TRIANGLES, 0, 3);

请注意,第二个glVertexAttribPointer调用也使用属性0.传递给glVertexAttribPointer的属性索引指定从该数组获取哪个着色器输入变量.您想要做的是使用相同的着色器渲染第二个对象,仅更改顶点数组的来源.这就需要使用相同的属性索引.

Notice that the second glVertexAttribPointer call uses attribute 0 as well. The attribute indices you pass to glVertexAttribPointer specify which shader input variable gets fed from that array. What you're trying to do is render a second object using the same shader, changing only where the vertex arrays come from. And that requires using the same attribute index.

但是,如果您可以使用OpenGL 4.3/ARB_vertex_attrib_binding,我强烈建议您只使用这些API .它使您的代码很多更直接:

However, if OpenGL 4.3/ARB_vertex_attrib_binding is available to you, I would highly encourage you to just use those APIs. It makes your code much more straightforward:

//vertex setup
glGenVertexArrays(1, &vao);

glBindVertexArray(vao);
//Sets up the format, *without* a buffer object.
glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, 0);
//Sets up where the buffer object comes from
glVertexAttribBinding(0, 0);
//Enable VAO
glEnableVertexAttribArray(0);
//Done with VAO
glBindVertexArray(0);

//Set up buffer object data storage.
glGenBuffers(2, vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle1Vertices), triangle1Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(triangle2Vertices), triangle2Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

然后,在您的循环中:

glBindVertexArray(vao);

//Use buffer 0 to render.
glBindVertexBuffer(0, vbo[0], 0, 3 * sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);
//Use buffer 1 to render.
glBindVertexBuffer(0, vbo[1], 0, 3 * sizeof(float));
glDrawArrays(GL_TRIANGLES, 0, 3);

glBindVertexArray(0);

这篇关于渲染一个包含两个VBO的VAO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆