从不同的缓冲区中绘制多个对象(数组切换)

时间:2014-05-12 07:23:37

标签: c# opengl vbo

目前我正在尝试使用多个缓冲区绘制多个对象。

我不确定是否以适当的方式切换缓冲区以进行绘制,并且无法弄清楚如何进行绘制。

我有2个阵列:

    数量
  • quad_strip2包含34个元素(要绘制的对象),每个元素QUAD_STRIP使用52个顶点(总共1767个顶点)。
  • quad_strip3包含48个元素,其中包含26个QUAD_STRIP个顶点(总共1247个顶点)。

初始化代码

        gl.GenBuffers(2, Buffers);

        //SKIPED MATRICES AND SHADERS INITIALIZATION

        float[] quad_strip2 = new float[]
        {
            // COUNT OF ELEMENTS: 34
            // COUNT OF VERTICES: 52

            -19.66171f, 8.161709f, 2f, //0
            -19.66171f, 8.161709f, 4f, //1
             ........
            -19.66171f, -6.838291f, 35f, //1767

        };

        float[] quad_strip3 = new float[]
        {
            // COUNT OF ELEMENTS: 48
            // COUNT OF VERTICES: 26
            -0.8537037f, 7.25f, 2f, //0
            -0.8537037f, 7.25f, 4f, //1
             ........
            -20f, -3.25f, 34.45f, //1247
        };

        //bind first buffer
        gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[0]);

        //fill buffer with vertices
        unsafe
        {
            fixed (float* verts = quad_strip2)
            {
                var prt = new IntPtr(verts);

                gl.BufferData(OpenGL.GL_ARRAY_BUFFER, quad_strip2.Length * sizeof(float), prt,
                    OpenGL.GL_STATIC_DRAW);

            }
        }

        //bind second buffer
        gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[1]);

        //fill buffer
        unsafe
        {
            fixed (float* verts = quad_strip3)
            {
                var prt = new IntPtr(verts);

                gl.BufferData(OpenGL.GL_ARRAY_BUFFER, quad_strip3.Length * sizeof(float), prt,
                    OpenGL.GL_STATIC_DRAW);

            }
        }

        gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
        gl.EnableVertexAttribArray((uint)Attrib_IDs.vPosition);

绘图代码

    //SKIPED FILLING VERTEX SHADER WITH MATRIXES


     //DRAW ARRAYS
    //binf first array and draw it 
    gl.BindVertexArray(Buffers[0]);
    for (int i = 0; i < 34; i++)
    {
        gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
    }


    //binf second array and draw it 
    gl.BindVertexArray(Buffers[1]);
    shaderProgram.SetUniform3(gl, "color", 0, 0.4f, 1);
    for (int i = 0; i < 48; i++)
    {
        gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
    }


    //DRAW WIREFRAMES
    shaderProgram.SetUniform3(gl, "color", 0, 0, 0);
    gl.Enable(OpenGL.GL_POLYGON_OFFSET_FILL);

    gl.PolygonOffset(1.0f, 1.0f);

    gl.PolygonMode(FaceMode.FrontAndBack, PolygonMode.Lines);


    gl.BindVertexArray(Buffers[0]);
    for (int i = 0; i < 34; i++)
    {
        gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
    }

    gl.BindVertexArray(Buffers[1]);
    for (int i = 0; i < 48; i++)
    {
        gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
    }

    gl.PolygonMode(FaceMode.FrontAndBack, PolygonMode.Filled);

结果我有这样的输出,这看起来不像我需要得到的。 enter image description here

1 个答案:

答案 0 :(得分:2)

在绘图代码中的每个VertexAttribPointer调用后,您需要BindBuffer个调用。 VertexAttribPointer适用于当前绑定的缓冲区。您当前的代码在init代码中只有一个VertexAttribPointer调用,这在调用Buffers[1]时发生。因此,所有绘制调用都将使用该缓冲区中的顶点数据。

编辑:我还注意到您在绘图代码中使用了BindVertexArray。顶点数组对象(VAO)是顶点缓冲区(VBO)中不同类型的对象,您不能仅使用VBO的id进行BindVertexArray调用。为了使这一切在没有VAO的情况下正常工作,您可以从初始化代码中删除VertexAttribPointer调用。然后向您的绘图代码添加两个VertexAttribPointer次调用,并将BindVertexArray替换为BindBuffer,将其结构如下:

gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[0]);
gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
for (int i = 0; i < 34; i++)
{
    gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 52, 52);
}

gl.BindBuffer(OpenGL.GL_ARRAY_BUFFER, Buffers[1]);
gl.VertexAttribPointer((uint)Attrib_IDs.vPosition, 3, OpenGL.GL_FLOAT, false, 0, new IntPtr(0));
shaderProgram.SetUniform3(gl, "color", 0, 0.4f, 1);
for (int i = 0; i < 48; i++)
{
    gl.DrawArrays(OpenGL.GL_QUAD_STRIP, i * 26, 26);
}

另一个选择是你真正使用顶点阵列对象(VAO)。为了实现这一点,您必须在init代码(glGenVertexArrays)中创建这些对象,并在为每个缓冲区设置状态时绑定它们。它们允许您在设置期间设置所有状态,然后在准备绘制时仅进行单个绑定调用。您可以通过一些搜索找到代码示例。