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