【问题标题】:OpenGL can't update vertex buffer with VAO procedureOpenGL 无法使用 VAO 程序更新顶点缓冲区
【发布时间】:2020-10-11 13:05:22
【问题描述】:

我试图通过修改它的位置顶点属性来移动一个顶点。作为测试,我在创建 VAO 过程之前和之后都添加了行 vertices[0] = 0.4f;,以查看我是否能够在初始渲染后修改顶点数组。当我在创建 VAO 之前添加它时,它会修改顶点的位置,而在之后添加它时不会。这让我相信我的渲染过程:

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

glfwSwapBuffers(window);
glfwPollEvents();

不知何故实际上并没有用内存中的当前float[] 更新缓冲区。但是,我可以用整个渲染过程替换 glBindVertexArray(VAO); 行:

    // 2. copy our vertices array in a buffer for OpenGL to use
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    // 2. copy our vertex indices in a buffer for OpenGL to use
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
    // 3. then set our vertex attributes pointers:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
    glEnableVertexAttribArray(1);

有了这个作为我的渲染过程,我可以更新顶点数组,这个变化被传递到 GPU,更新屏幕上顶点的位置。这是我的 VAO 创建代码:

    // Generate a Vertex Array Object to store our rendering procedure.
    unsigned int VAO;
    glGenVertexArrays(1, &VAO);
    // 1. bind Vertex Array Object, Element Buffer Object
    glBindVertexArray(VAO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    // 2. copy our vertices array in a buffer for OpenGL to use
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
    // 2. copy our vertex indices in a buffer for OpenGL to use
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
    // 3. then set our vertex attributes pointers:
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0); // Pos vec3
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(3* sizeof(float))); // Col vec4
    glEnableVertexAttribArray(1);

所以当我明确表达渲染过程时它可以工作,但当我将它存储在 VAO 中时就不行?据我了解,VAO 是一种用于存储渲染过程的构造,然后当我们运行glBindVertexArray(VAO); 时,就会执行此渲染过程。我理解错了吗?在创建 VAO 或渲染时是否需要另一行?

这里是 C++ 的完整源代码:https://pastebin.com/DgZuZt4K

同样的东西用 OpenTK,C# 编写:https://pastebin.com/DHj9UN16

【问题讨论】:

    标签: c++ opengl glfw vao vertex-array-object


    【解决方案1】:

    [...] 据我了解,VAO 是一种用于存储渲染过程的构造,[...]

    不,不是。 Vertex Array Object 存储状态。

    glBufferData/glBufferSubData被调用时,缓冲区对象的数据存储被初始化,分别更新。

    glVertexAttribPointer 被调用时,状态被设置在VAO 的状态向量中。当前绑定到目标GL_ARRAY_BUFFER的缓冲区对象与当前绑定的VAO中的指定顶点属性相关联。
    VAO存储了关于如何解释顶点信息的信息以及每个属性的VBO的id。

    但是 VAO 不存储过程甚至进程。更改顶点后,您必须通过glBufferSubData 或缓冲区映射更新Vertex Buffer Object

    相关:What is the proper way to modify OpenGL vertex buffer?


    如果要指定并启用顶点属性(glVertexAttribPointer / glEnableVertexAttribArray),则必须绑定 VAO 和 VBO。 VAO存储规范,VBO的id存储在VAO中。

    如果要更新顶点坐标和属性(例如glBufferSubData),则必须绑定VBO。

    如果你想绘制网格(例如glDrawArrays),那么绑定VAO就足够了。

    【讨论】:

    • 太棒了,非常感谢。只是为了确认:VAO 存储有关如何解释顶点信息以提供给顶点着色器的信息?所以我会先绑定数组缓冲区传递顶点信息,然后绑定VAO并渲染?
    • @MattyAB VAO 存储有关如何解释每个属性的顶点信息和 VBO id 的信息。在绘制对象之前绑定 VAO 就足够了。但是在通过glVertexAttribPointer 指定属性之前,您必须绑定 VAO 和 VBO。如果要更新顶点坐标和属性,则必须绑定 VBO
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 2014-07-31
    • 2011-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多