更新 openGL VBO
Updating an openGL VBO
我是一名新的 openGL 程序员,到目前为止我已经取得了很大进展。我用 C# 编程,所以没有太多示例,我的最后一个任务是每帧用新数据更新 VBO。我找不到任何例子。我也是 Vectors 的新手。所以这是基本代码和我尝试过的代码。我正在使用 opengl4csharp 和 freeglut 库。
我最初在渲染回调之外设置了一个简单的金字塔,如下所示:
program = new ShaderProgram(VertexShader, FragmentShader)
// set the view and projection matrix for pyramid
program.Use();
program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, new Vector3(0, 1, 0)));
// create a pyramid with vertices and colors
pyramid = new VBO<Vector3>(new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }); // left face
pyramidColor = new VBO<Vector3>(new Vector3[] {
new Vector3(0.5f, 0, 0), new Vector3(0, 0.5f, 0), new Vector3(0, 0, 0.5f),
new Vector3(0.5f, 0, 0), new Vector3(0, 0, 0.5f), new Vector3(0, 0.5f, 0),
new Vector3(0.5f, 0, 0), new Vector3(0, 0.5f, 0), new Vector3(0, 0, 0.5f),
new Vector3(0.5f, 0, 0), new Vector3(0, 0, 0.5f), new Vector3(0, 0.5f, 0) });
pyramidTriangles = new VBO<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, BufferTarget.ElementArrayBuffer);
然后我在 OnRender 回调中执行以下操作:
// use our vertex shader program
Gl.UseProgram(program);
// bind the vertex positions, colors and elements of the pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
Gl.BindBufferToShaderAttribute(pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(pyramidColor, program, "vertexColor");
Gl.BindBuffer(pyramidTriangles);
Gl.DrawElements(BeginMode.Triangles, pyramidTriangles.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
效果很好,然后我就有了一个漂亮的金字塔显示器。现在在实际应用中,它会比单个金字塔多很多,而且会实时更新。这是我遇到问题的地方。我不明白如何正确更新 VBO。这是我在 OnRender 回调中尝试过的。这只是第一个顶点更改的示例
Gl.UseProgram(program);
pyramid = new VBO<Vector3>(new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }); // left face
// bind the vertex positions, colors and elements of the pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
Gl.BindBufferToShaderAttribute(pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(pyramidColor, program, "vertexColor");
Gl.BindBuffer(pyramidTriangles);
Gl.DrawElements(BeginMode.Triangles, pyramidTriangles.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
这也有效,但是当我退出程序时,我得到一个系统访问冲突异常。如果他们不处理其中一个顶点对象,这与他们得到的错误相同。但是在这种情况下,我会调用 dispose。这是否意味着我每次使用它时都需要调用 dispose?
我也听说过有关 glMapBuffers 的一些信息,但找不到任何示例。
感谢您的帮助。
您创建了新的 VBO 对象,而不是更新现有对象。所以 VBO 堆积在视频卡上。
当库的文档不好时,查看其源代码是个好主意。该库主要由 3 个部分组成:
低级 OpenGL 绑定:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlCore.cs
那里的代码只是从 OpenGL dll 调用函数。
更高级别的功能。例如,您在评论中提到,您使用 BindBufferToShaderAttribute 函数将缓冲区上传到 GPU:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlMethods.cs#L600
如您所见,该函数只是调用了一些较低级别的 OpenGL 函数。另请注意,它不会将缓冲区上传到 GPU,所以这种情况发生在其他地方。 (它只是标记缓冲区中的条目,以便将它们作为属性传递给着色器。)
高级别 classes。例如,您在示例中使用的 VBO class:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs
注意它的构造函数调用CreateVBO:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs#L54
并且 CreateVBO 方法调用了 glBufferData,我在评论中提到了这一点:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlMethods.cs#L342
所以是VBO class,将缓冲区上传到GPU。我们可以预期您可以使用相同的 class 修改缓冲区。它就在那里:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs#L129
VBO 对象的 BufferSubData 方法可用于修改缓冲区。示例:
Vector3[] vertexBuffer = new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }; // left face
pyramid.BufferSubData(vertexBuffer);
我是一名新的 openGL 程序员,到目前为止我已经取得了很大进展。我用 C# 编程,所以没有太多示例,我的最后一个任务是每帧用新数据更新 VBO。我找不到任何例子。我也是 Vectors 的新手。所以这是基本代码和我尝试过的代码。我正在使用 opengl4csharp 和 freeglut 库。 我最初在渲染回调之外设置了一个简单的金字塔,如下所示:
program = new ShaderProgram(VertexShader, FragmentShader)
// set the view and projection matrix for pyramid
program.Use();
program["projection_matrix"].SetValue(Matrix4.CreatePerspectiveFieldOfView(0.45f, (float)width / height, 0.1f, 1000f));
program["view_matrix"].SetValue(Matrix4.LookAt(new Vector3(0, 0, 10), Vector3.Zero, new Vector3(0, 1, 0)));
// create a pyramid with vertices and colors
pyramid = new VBO<Vector3>(new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }); // left face
pyramidColor = new VBO<Vector3>(new Vector3[] {
new Vector3(0.5f, 0, 0), new Vector3(0, 0.5f, 0), new Vector3(0, 0, 0.5f),
new Vector3(0.5f, 0, 0), new Vector3(0, 0, 0.5f), new Vector3(0, 0.5f, 0),
new Vector3(0.5f, 0, 0), new Vector3(0, 0.5f, 0), new Vector3(0, 0, 0.5f),
new Vector3(0.5f, 0, 0), new Vector3(0, 0, 0.5f), new Vector3(0, 0.5f, 0) });
pyramidTriangles = new VBO<int>(new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, BufferTarget.ElementArrayBuffer);
然后我在 OnRender 回调中执行以下操作:
// use our vertex shader program
Gl.UseProgram(program);
// bind the vertex positions, colors and elements of the pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
Gl.BindBufferToShaderAttribute(pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(pyramidColor, program, "vertexColor");
Gl.BindBuffer(pyramidTriangles);
Gl.DrawElements(BeginMode.Triangles, pyramidTriangles.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
效果很好,然后我就有了一个漂亮的金字塔显示器。现在在实际应用中,它会比单个金字塔多很多,而且会实时更新。这是我遇到问题的地方。我不明白如何正确更新 VBO。这是我在 OnRender 回调中尝试过的。这只是第一个顶点更改的示例
Gl.UseProgram(program);
pyramid = new VBO<Vector3>(new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }); // left face
// bind the vertex positions, colors and elements of the pyramid
program["model_matrix"].SetValue(Matrix4.CreateRotationY(yangle) * Matrix4.CreateRotationX(xangle));
Gl.BindBufferToShaderAttribute(pyramid, program, "vertexPosition");
Gl.BindBufferToShaderAttribute(pyramidColor, program, "vertexColor");
Gl.BindBuffer(pyramidTriangles);
Gl.DrawElements(BeginMode.Triangles, pyramidTriangles.Count, DrawElementsType.UnsignedInt, IntPtr.Zero);
这也有效,但是当我退出程序时,我得到一个系统访问冲突异常。如果他们不处理其中一个顶点对象,这与他们得到的错误相同。但是在这种情况下,我会调用 dispose。这是否意味着我每次使用它时都需要调用 dispose? 我也听说过有关 glMapBuffers 的一些信息,但找不到任何示例。 感谢您的帮助。
您创建了新的 VBO 对象,而不是更新现有对象。所以 VBO 堆积在视频卡上。
当库的文档不好时,查看其源代码是个好主意。该库主要由 3 个部分组成:
低级 OpenGL 绑定:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlCore.cs
那里的代码只是从 OpenGL dll 调用函数。
更高级别的功能。例如,您在评论中提到,您使用 BindBufferToShaderAttribute 函数将缓冲区上传到 GPU:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlMethods.cs#L600
如您所见,该函数只是调用了一些较低级别的 OpenGL 函数。另请注意,它不会将缓冲区上传到 GPU,所以这种情况发生在其他地方。 (它只是标记缓冲区中的条目,以便将它们作为属性传递给着色器。)
高级别 classes。例如,您在示例中使用的 VBO class:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs
注意它的构造函数调用CreateVBO:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs#L54
并且 CreateVBO 方法调用了 glBufferData,我在评论中提到了这一点:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlMethods.cs#L342
所以是VBO class,将缓冲区上传到GPU。我们可以预期您可以使用相同的 class 修改缓冲区。它就在那里:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Constructs/VBO.cs#L129
VBO 对象的 BufferSubData 方法可用于修改缓冲区。示例:
Vector3[] vertexBuffer = new Vector3[] {
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, 0.5f), // front face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, -0.5f, -0.5f), // right face
new Vector3(0, 0.5f, 0), new Vector3(0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f), // back face
new Vector3(0, 0.5f, 0), new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f) }; // left face
pyramid.BufferSubData(vertexBuffer);