Search code examples
c#opengltao-framework

Trying to set VBO:s in C# using TAO and OpenGL TK framework


I'm trying to set my vertices, indices and texture points to VBO:s and the draw them with my draw method, all this in C# under TAO/OpenGL TK framwork. But my screen shows only a black screen. I've tested without VBO:s, and then it works. But with my vertices, indices and texture points I can't success.

My code:

private float[] vertices;
private byte[] indices;
private float[] texture;

private int[] mVertexBuffer;
private int[] mIndicesBuffer;
private int[] mTextureBuffer;

//...Constructor start
vertices = new float[] {
                                            -1.0f, -1.0f, 1.0f,
                                            1.0f, -1.0f, 1.0f,
                                            -1.0f, 1.0f, 1.0f,
                                            1.0f, 1.0f, 1.0f,

                                            1.0f, -1.0f, 1.0f,
                                            1.0f, -1.0f, -1.0f, 
                                            1.0f, 1.0f, 1.0f, 
                                            1.0f, 1.0f, -1.0f,

                                            1.0f, -1.0f, -1.0f, 
                                            -1.0f, -1.0f, -1.0f, 
                                            1.0f, 1.0f, -1.0f, 
                                            -1.0f, 1.0f, -1.0f,

                                            -1.0f, -1.0f, -1.0f, 
                                            -1.0f, -1.0f, 1.0f, 
                                            -1.0f, 1.0f, -1.0f, 
                                            -1.0f, 1.0f, 1.0f,

                                            -1.0f, -1.0f, -1.0f, 
                                            1.0f, -1.0f, -1.0f, 
                                            -1.0f, -1.0f, 1.0f, 
                                            1.0f, -1.0f, 1.0f,

                                            -1.0f, 1.0f, 1.0f, 
                                            1.0f, 1.0f, 1.0f, 
                                            -1.0f, 1.0f, -1.0f, 
                                            1.0f, 1.0f, -1.0f, 
                                            };

texture = new float[] {
                                                                                           0.0f, 1.0f,                                                1.0f, 1.0f,                                                0.0f, 0.0f,                                                 1.0f, 0.0f,                                                 
                                            0.0f, 1.0f, 
                                            1.0f, 1.0f, 
                                            0.0f, 0.0f, 
                                            1.0f, 0.0f, 

                                            0.0f, 1.0f, 
                                            1.0f, 1.0f, 
                                            0.0f, 0.0f, 
                                            1.0f, 0.0f, 

                                            0.0f, 1.0f, 
                                            1.0f, 1.0f, 
                                            0.0f, 0.0f, 
                                            1.0f, 0.0f, 

                                            0.0f, 1.0f, 
                                            1.0f, 1.0f, 
                                            0.0f, 0.0f, 
                                            1.0f, 0.0f, 

                                            0.0f, 1.0f, 
                                            1.0f, 1.0f, 
                                            0.0f, 0.0f, 
                                            1.0f, 0.0f,  
                                            };

indices = new byte[] {
                                            0, 1, 3, 0, 3, 2,                                                4, 5, 7, 4, 7, 6,
                                            8, 9, 11, 8, 11, 10,
                                            12, 13, 15, 12, 15, 14, 
                                            16, 17, 19, 16, 19, 18, 
                                             20, 21, 23, 20, 23, 22, 
                                            };

mVertexBuffer = new int[1];
mIndicesBuffer = new int[1];
mTextureBuffer = new int[1];

//...Constructor end

public void setBuffers() {
        gl.glGenBuffersARB(1, mVertexBuffer);
        gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mVertexBuffer[0]);
        gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB,
        (IntPtr)(vertices.Length * sizeof(float)),
  vertices, GL.GL_STATIC_DRAW_ARB);

        gl.glGenBuffersARB(1, mIndicesBuffer);
        gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, mIndicesBuffer[0]);
        gl.glBufferDataARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB,
         (IntPtr)(indices.Length * sizeof(float)),
  indices, GL.GL_DYNAMIC_DRAW_ARB);

        gl.glGenBuffersARB(1, mTextureBuffer);
        gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mTextureBuffer[0]);
        gl.glBufferDataARB(GL.GL_ARRAY_BUFFER_ARB,
         (IntPtr)(texture.Length * sizeof(float)),
  texture, GL.GL_STATIC_DRAW_ARB);
  }

    public void draw()
    {
        gl.glBegin(gl.GL_TRIANGLES);

        gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL.GL_TEXTURE_COORD_ARRAY);

        gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mVertexBuffer[0]);
        gl.glVertexPointer(3, GL.GL_FLOAT, 0, mVertexBuffer);
        gl.glBindBufferARB(GL.GL_ARRAY_BUFFER_ARB, mTextureBuffer[0]);
        gl.glTexCoordPointer(2, GL.GL_FLOAT, 0, mTextureBuffer);

        gl.glBindBufferARB(GL.GL_ELEMENT_ARRAY_BUFFER_ARB, mIndicesBuffer[0]);

        gl.glDrawElements(GL.GL_TRIANGLES, indices.Length,
 gl.GL_UNSIGNED_BYTE, mIndicesBuffer);

        gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL.GL_TEXTURE_COORD_ARRAY);
        gl.glEnd();

    }

The vertices/indices/texture points works in my C++ VBO enviroment, but not here. So I'm guessing I had missed something with the bind stuff.


Solution

  • Actually, I've been looking for this some weeks too. Now I have a correct working solution.

    There are several problems you need to be aware of to successfully create a Vertex Buffer Object. The first problem is that people mess things up. GL_INDEX_ARRAY isn't for your indices. You shall use GL_INDEX_ARRAY when you use a color array for smoothing out the color(s) between your verts.

    Another problem is that the Tao framework uses IntPtr.Zero for an offset and not an ordinary 0. You're using the last parameter in the glDrawElements call as Vertex Array style when it's a Vertex Buffer Object.

    On the other hand, it looks like you're mixing two different concepts together. You're trying to load your data into a buffer, which you totally will success with if you're using your posted code. The problem here though is that you're using wrong GL_ARRAY_BUFFER command. For your indices you should use GL_ELEMENT_ARRAY_BUFFER.

    With that said I will show one solution using standard Vertex Arrays and another using Vertex Buffer Objects. I hope this will clear things out.

    Vertex Arrays:

    public void draw()
    {
         gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
         gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
    
         gl.glVertexPointer(3, gl.GL_FLOAT, 0, verticesArray);
         gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, textureArray);
    
         //With Vertex Arrays, the last parameter is your pointer to your indices
         gl.glDrawElements(gl.GL_TRIANGLES, indices.Length,
                                   gl.GL_UNSIGNED_SHORT, indicesArray);
    
         gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY);
         gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
    }
    

    Vertex Buffer Objects:

    //This should be used in the constructor 
    //or in another method than the draw method
    mVertexBuffer = new int[1];
    mTextureBuffer = new int[1];
    mIndexBuffer = new int[1];
    
    gl.glGenBuffers(1, mVertexBuffer);
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
    gl.glBufferData(gl.GL_ARRAY_BUFFER,
         (IntPtr)(verticesArray.Length * sizeof(float)),
                      verticesArray, gl.GL_STATIC_DRAW);
    
    gl.glGenBuffers(1, mTextureBuffer);
    gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
    gl.glBufferData(gl.GL_ARRAY_BUFFER,
         (IntPtr)(textureArray.Length * sizeof(float)),
                      textureArray, gl.GL_STATIC_DRAW);
    
    gl.glGenBuffers(1, mIndexBuffer);
    gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer[0]);
    gl.glBufferData(gl.GL_ELEMENT_ARRAY_BUFFER,
         (IntPtr)(indicesArray.Length * sizeof(short)),
                      indicesArray, gl.GL_STATIC_DRAW);
    
    //Your draw method
    public void draw()
    {     
        gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
        gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
    
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mVertexBuffer[0]);
    
        //Notice: IntPtr.Zero is used...
        gl.glVertexPointer(3, gl.GL_FLOAT, 0, IntPtr.Zero);
    
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, mTextureBuffer[0]);
    
        //Notice: IntPtr.Zero is used...
        gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, IntPtr.Zero); 
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer[0]);
    
        //Notice: IntPtr.Zero is used. Last parameter is
        //an offset using Vertex Buffer Objects and in Vertex Arrays
        //it is a pointer
        gl.glDrawElements(gl.GL_TRIANGLES, indices.Length,
                 gl.GL_UNSIGNED_SHORT, IntPtr.Zero); 
    
        //Remember to unbind your buffer to prevent it to destroy
        //other draw calls or objects
        gl.glBindBuffer(gl.GL_ARRAY_BUFFER, 0);
        gl.glBindBuffer(gl.GL_ELEMENT_ARRAY_BUFFER, 0);
    
        gl.glDisableClientState(gl.GL_VERTEX_ARRAY);
        gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY);            
    }
    

    I hope this was useful, it took me a while to figure this out.