更新openGL VBO

时间:2017-01-07 20:07:58

标签: c# opengl vbo

我是一名新的openGL程序员,到目前为止,我已经走得很远了。我在C#中编程所以没有很多例子,我的最后任务是每帧更新一个带有新数据的VBO。我找不到任何例子。我也是Vector的新手。所以这里是基本代码和我尝试过的。我正在使用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? 我也听说过一些关于glMapBuffers但没有找到任何例子。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

您创建了新的VBO对象,而不是更新现有的VBO对象。所以维多利亚州立大学正在堆积在视频卡上。

当库的文档很糟糕时,查看其源代码是个好主意。该库主要由3部分组成:

  1. 低级OpenGL绑定:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlCore.cs

    那里的代码只是从OpenGL DLL调用函数。

  2. 更高级别的功能。例如,您在评论中提到,您使用BindBufferToShaderAttribute函数将缓冲区上传到GPU:https://github.com/giawa/opengl4csharp/blob/master/OpenGL/Core/GlMethods.cs#L600

    如您所见,该函数只调用一些较低级别的OpenGL函数。另请注意,它不会将缓冲区上传到GPU,因此会发生在其他地方。 (它只是标记缓冲区中的条目,以将它们作为属性传递给着色器。)

  3. 高级课程。例如,您在示例中使用的VBO类: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

  4. 所以它是VBO类,它将缓冲区上传到GPU。我们可以期望您可以使用相同的类修改缓冲区。它是: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);