Question

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:

  • quad_strip2 in amount contains 34 elements (objects to draw) and each of element for it's QUAD_STRIP use 52 vertices (1767 vertices in total).
  • quad_strip3 contains 48 elements with 26 vertices for QUAD_STRIP (1247 vertices in total).

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

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top