Initializing and drawing a mesh using OpenTK
- by Boreal
I'm implementing a "Mesh" class to use in my OpenTK game. You pass in a vertex array and an index array, and then you can call Mesh.Draw() to draw it using a shader.
I've heard VBO's and VAO's are the way to go for this approach, but nowhere have I found a guide that shows how to get Data Video Memory Shader.
Can someone give me a quick rundown of how this works?
EDIT:
So far, I have this:
struct Vertex
{
public Vector3 position;
public Vector3 normal;
public Vector3 color;
public static int memSize = 9 * sizeof(float);
public static byte[] memOffset = { 0, 3 * sizeof(float), 6 * sizeof(float) };
}
class Mesh
{
private uint vbo;
private uint ibo;
// stores the numbers of vertices and indices
private int numVertices;
private int numIndices;
public Mesh(int numVertices, Vertex[] vertices, int numIndices, ushort[] indices)
{
// set numbers
this.numVertices = numVertices;
this.numIndices = numIndices;
// generate buffers
GL.GenBuffers(1, out vbo);
GL.GenBuffers(1, out ibo);
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
// send data to the buffers
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(Vertex.memSize * numVertices), vertices, BufferUsageHint.StaticDraw);
GL.BufferData(BufferTarget.ElementArrayBuffer, new IntPtr(sizeof(ushort) * numIndices), indices, BufferUsageHint.StaticDraw);
}
public void Render()
{
// bind buffers
GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
// define offsets
GL.VertexPointer(3, VertexPointerType.Float, Vertex.memSize, new IntPtr(Vertex.memOffset[0]));
GL.NormalPointer(NormalPointerType.Float, Vertex.memSize, new IntPtr(Vertex.memOffset[1]));
GL.ColorPointer(3, ColorPointerType.Float, Vertex.memSize, new IntPtr(Vertex.memOffset[2]));
// draw
GL.DrawElements(BeginMode.Triangles, numIndices, DrawElementsType.UnsignedInt, (IntPtr)0);
}
}
class Application : GameWindow
{
Mesh triangle;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);
GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.VertexArray);
GL.Enable(EnableCap.NormalArray);
GL.Enable(EnableCap.ColorArray);
Vertex v0 = new Vertex();
v0.position = new Vector3(-1.0f, -1.0f, 4.0f);
v0.normal = new Vector3(0.0f, 0.0f, -1.0f);
v0.color = new Vector3(1.0f, 1.0f, 0.0f);
Vertex v1 = new Vertex();
v1.position = new Vector3(1.0f, -1.0f, 4.0f);
v1.normal = new Vector3(0.0f, 0.0f, -1.0f);
v1.color = new Vector3(1.0f, 0.0f, 0.0f);
Vertex v2 = new Vertex();
v2.position = new Vector3(0.0f, 1.0f, 4.0f);
v2.normal = new Vector3(0.0f, 0.0f, -1.0f);
v2.color = new Vector3(0.2f, 0.9f, 1.0f);
Vertex[] va = { v0, v1, v2 };
ushort[] ia = { 0, 1, 2 };
triangle = new Mesh(3, va, 3, ia);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
GL.MatrixMode(MatrixMode.Modelview);
GL.LoadMatrix(ref modelview);
triangle.Render();
SwapBuffers();
}
}
It doesn't draw anything.