OpenGL 无法使用 VAO 过程更新顶点缓冲区

OpenGL can't update vertex buffer with VAO procedure

我正在尝试通过修改顶点的位置属性来移动顶点。作为测试,我在创建我的 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

[...] From what I understand, a VAO is a construct for storing a rendering procedure, [...]

不,不是。 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即可