Pages

Showing posts with label VBO. Show all posts
Showing posts with label VBO. Show all posts

OpenTK Vertex Buffer Object [VBO]

Hope it help's

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//A simple 3D vertex
public struct Vertex
{
    public float X, Y, Z;
    public Vertex(float x, float y, float z)
    {
        X = x; Y = y; Z = z;
    }

    //The stride of this vertex
    //3 floats 4 bytes each
    //if you dont like counting bytes you can get this value a few different ways
    //System.Runtime.InteropServices.Marshal.SizeOf(new Vertex());
    //OpenTK.BlittableValueType.StrideOf(new Vertex());
    public const int Stride = 12;
}

//ID of the vertex buffer we will use
private int ID_VBO;
//ID of the element buffer
private int ID_EBO;

//You are not limited to using a struct
//you can use (float[], byte[], int[]) really anything that can hold data
//then you could stride the array with
//Vertices.Length * sizeof(float)
private Vertex[] Vertices;
//I use ushort, for the simple reasons of
//i know im never going to index a negative value
//and 65,535 is a good vertex limit
//but you can use whatever just remember the max_value is your limit
private ushort[] Indices;

//Keep in mind that you are using memory for everything
//the best way to think about any GL buffer is as if its byte[] or ByteArray/ByteBuffer

//Only need to call this once, place it in your programs initialize/load method
private void InitializeVBO()
{
    //Initialize vertex data and index data

    //Simple triangle in CW winding
    Vertices = new Vertex[3]
    {
        new Vertex(  0.0f,   0.0f, 0.0f),
        new Vertex(100.0f,   0.0f, 0.0f),
        //gl y coords are reversed depending on what direction you consider is down
        new Vertex(  0.0f, -100.0f, 0.0f)
    };

    //Index data for what order to draw vertices
    Indices = new ushort[3]
    {
        //This is also something to keep in mind
        //reversing your winding has no performance advantage, 
        //dont let someone tell you otherwise, all data gets read the same way
        //its always easier to change a few indices than edit vertices
        //since you are most likely in CCW winding since that is GL's default
        //i reversed it since the vertices are in CW :D
        //you can change GL's default winding by GL.FrontFace
        0, 1, 2
    };
            
    //Setting up the vertex buffer
    //data has to be initialize before this part.
            
    //Generate a single buffer
    GL.GenBuffers(1, out ID_VBO);
    //Tell gl we are going to be using this buffer as an Array_Buffer for vertex data
    GL.BindBuffer(BufferTarget.ArrayBuffer, ID_VBO);
    //Add our vertex data to it, essentially the same thing as Array.Copy if it were a byte[]
    //1: targeting the Array_Buffer
    //2: for this we will need the full length in bytes of our vertex data
    //3: the data we want in this new buffer
    //4: we are only going to set this once so our usage will be static and draw/write
    //basically in full we're are telling gl that we want a write-only buffer that is locked :P
    GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(Vertices.Length * Vertex.Stride), Vertices, BufferUsageHint.StaticDraw);
    //This is just good practice
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

    //Generate another single buffer
    GL.GenBuffers(1, out ID_EBO);
    //Tell gl we are going to be using this buffer as an Element_Buffer for indexing data already bound to an Array_Buffer
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID_EBO);
    //the same as above only changing the data
    GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(Indices.Length * sizeof(ushort)), Indices, BufferUsageHint.StaticDraw);
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}

//This will need to be called everyframe you want to see the buffer data so use in OnRenderFrame
//or any method with a GL render context.
public void RenderVBO()
{
    GL.PushMatrix();

    //So you can see it onscreen :P
    GL.Translate(-50, 50, -100);

    //We dont have color data so it will resort to the last use GL_Color
    GL.Color3(1.0f, 1.0f, 1.0f);

    //since we only have position data thats all that needs to be writen to gl
    //if you enable another as in ArrayCap.ColorArray and have no color data
    //you will get an outofbounds/outofmemory exception because there is not data to read
    //so good practice to enable/disable so you dont run into that problem when using
    //different types of vertices :D
    //Although if you know what type you are going to use throughout the whole process
    //you can remove enable/disable from this method and add enable to your init function
    GL.EnableClientState(ArrayCap.VertexArray);

    //Bind our vertex data
    GL.BindBuffer(BufferTarget.ArrayBuffer, ID_VBO);
    //Tell gl where to start reading our position data in the length of out Vertex.Stride
    //so we will begin reading 3 floats with a length of 12 starting at 0
    GL.VertexPointer(3, VertexPointerType.Float, Vertex.Stride, 0);

    GL.BindBuffer(BufferTarget.ElementArrayBuffer, ID_EBO);
    //tell gl to draw from the bound Array_Buffer in the form of triangles with a length of indices of type ushort starting at 0
    GL.DrawElements(BeginMode.Triangles, Indices.Length, DrawElementsType.UnsignedShort, 0);

    //unlike above you will have to unbind after the data is indexed else the Element_Buffer would have nothing to index
    GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
    GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);

    //Remember to disable
    GL.DisableClientState(ArrayCap.VertexArray);

    GL.PopMatrix();
}

Also some good references
http://www.opengl.org/wiki/Vertex_Specification
http://www.opengl.org/wiki/Buffer_Object
http://www.opentk.com/doc/graphics/geometry/vertex-buffer-objects