frankie
frankie

Reputation: 728

Draw multiple objects from different buffers (arrays switching)

Currently I'am trying to draw multiple object using number of buffers.

I'am not sure that I switch buffers for drawing in proper way and cannot figure out how to do it.

I have 2 arrays:

Initialization code

        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);

Drawing code

    //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);

As result I have such output, which is not looks like what I need to get. enter image description here

Upvotes: 0

Views: 993

Answers (1)

Reto Koradi
Reto Koradi

Reputation: 54592

You need a VertexAttribPointer call after each of the BindBuffer calls in your drawing code. VertexAttribPointer applies to the currently bound buffer. Your current code has only one VertexAttribPointer call in the init code, which happened while Buffers[1] was called. So all your draw calls will use vertex data from that buffer.

EDIT: I also just notice that you use BindVertexArray in your draw code. Vertex array objects (VAO) are different kinds of objects from vertex buffers (VBO), and you can't just use the id of a VBO for a BindVertexArray call. To get this all working without VAOs for now, you can remove the VertexAttribPointer call from the init code. Then add two VertexAttribPointer calls to your draw code, and replace the BindVertexArray with BindBuffer, to structure it like this:

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);
}

The other option is that you really use Vertex Array Objects (VAO) all the way. For that to work, you have to create those objects in the init code (glGenVertexArrays), and bind them while setting up the state for each buffer. They allow you to set up all your state during setup, and then only make a single bind call when you get ready to draw. You should be able to find code examples for that with some searching.

Upvotes: 2

Related Questions