1

我试图通过修改它的位置顶点属性来移动一个顶点。作为测试,我vertices[0] = 0.4f;在创建 VAO 过程之前和之后都添加了该行,以查看是否能够在初始渲染后修改顶点数组。当我在创建 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

4

1 回答 1

2

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

不它不是。顶点数组对象存储状态。

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

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

但是VAO不存储过程甚至进程。当您更改顶点时,您必须通过或缓冲区映射更新顶点缓冲区对象。glBufferSubData

相关:修改OpenGL顶点缓冲区的正确方法是什么?


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

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

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

于 2020-06-21T16:42:15.437 回答