Jump to content

View more

Image of the Day

WIP title screen for #DeathOfAPartisan #screenshotsaturday #gamedev https://t.co/qJNhfZCvd4
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.

Sign up now

VAO and VBOs in OpenTK don't draw with simple shader

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
No replies to this topic

#1 Boreal   Members   


Posted 20 March 2012 - 12:16 AM

I'm implementing a "Mesh" class to use in my OpenTK game. You pass in a vertex array and an index array when you create it, 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 anyone give me a quick rundown of how this works?


I implemented a VBO and VAO system based on the HelloGL3 example that comes with OpenTK. When I copy and paste the example code into my project, it works perfectly, but mine doesn't draw a thing.

using System;
using System.Threading;

using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Audio;
using OpenTK.Audio.OpenAL;
using OpenTK.Input;

namespace OpenTKTest
class Application : GameWindow
Matrix4 matProjection;
Matrix4 matView;
Matrix4 matWorld;
int uniformProjection;
int uniformView;
int uniformWorld;
int uniformNormalTransform;

Shader shader;
Mesh triangle;
float angle = 0.0f;

   public Application() : base(800, 600, new GraphicsMode(), "OpenGL 3 Example", 0, DisplayDevice.Default, 3, 0,
			GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug)
	   VSync = VSyncMode.On;

   protected override void OnLoad(EventArgs e)

	   GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);

// load the shader
shader = new Shader("shaders/shader.vert", "shaders/shader.frag");
uniformProjection = shader.GetUniformLocation("mat_projection");
uniformView = shader.GetUniformLocation("mat_view");
uniformWorld = shader.GetUniformLocation("mat_world");
uniformNormalTransform = shader.GetUniformLocation("mat_normalTransform");

// vertices
Vector3[] pos = {
new Vector3(0.0f, 1.0f, 0.0f),
new Vector3(-1.0f, -1.0f, 0.0f),
new Vector3(1.0f, -1.0f, 0.0f)
Vector3[] nml = {
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, -1.0f),
new Vector3(0.0f, 0.0f, -1.0f)

// indices
ushort[] ia = { 0, 1, 2 };

// create a mesh
triangle = new Mesh(pos, nml, ia, shader);

   protected override void OnResize(EventArgs e)

	   GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);

	   matProjection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 0.1f, 100.0f);

   protected override void OnUpdateFrame(FrameEventArgs e)

angle += (float)e.Time;

	   if (Keyboard[Key.Escape])

   protected override void OnRenderFrame(FrameEventArgs e)

	   GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

Vector3 eye = new Vector3(0.0f, 0.0f, -1.0f);
Vector3 target = Vector3.Zero;
Vector3 up = new Vector3(0.0f, 1.0f, 0.0f);
	   matView = Matrix4.LookAt(eye, target, up);

matWorld = Matrix4.CreateRotationY(angle);

Matrix4 matNormalTransform;
Matrix4.Mult(ref matProjection, ref matView, out matNormalTransform);
Matrix4.Mult(ref matNormalTransform, ref matWorld, out matNormalTransform);

GL.UniformMatrix4(uniformProjection, false, ref matProjection);
GL.UniformMatrix4(uniformView, false, ref matView);
GL.UniformMatrix4(uniformWorld, false, ref matWorld);
GL.UniformMatrix4(uniformNormalTransform, true, ref matNormalTransform);



   static void Main()
	   // The 'using' idiom guarantees proper resource cleanup.
	   // We request 30 UpdateFrame events per second, and unlimited
	   // RenderFrame events (as fast as the computer can handle).
	   using (Application game = new Application())

using System;
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace OpenTKTest
class Mesh
  // buffer handles
  private uint vboPositions;
  private uint vboNormals;
  private uint ibo;
  private uint vao;

  private Shader currentShader;

  private int numVertices;
  private int numIndices;

  private ushort[] indices;

  public Mesh(Vector3[] positions, Vector3[] normals, ushort[] indices, Shader shader)
   // set from parameters
   numVertices = positions.Length;
   numIndices = indices.Length;
   this.indices = indices;
   // create VBOs and IBO
   vboPositions = CreateVBO<Vector3>(positions, Vector3.SizeInBytes);
   vboNormals = CreateVBO<Vector3>(normals, Vector3.SizeInBytes);
   ibo = CreateIBO(indices);
   // create VAO
   GL.GenVertexArrays(1, out vao);
   // position attribute
   GL.BindBuffer(BufferTarget.ArrayBuffer, vboPositions);
   GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);
   // normal attribute
   GL.BindBuffer(BufferTarget.ArrayBuffer, vboNormals);
   GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);
   // finalize
   GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
   // unbind VAO, and VBO
   GL.BindBuffer(BufferTarget.ArrayBuffer, 0);

  private uint CreateVBO<T>(T[] data, int size) where T : struct
   uint vbo;
   GL.GenBuffers(1, out vbo);
   GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);
   GL.BufferData<T>(BufferTarget.ArrayBuffer, (IntPtr)(data.Length * size), data, BufferUsageHint.StaticDraw);
   GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
   return vbo;

  private uint CreateIBO(ushort[] data)
   uint ibo;
   GL.GenBuffers(1, out ibo);
   GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
   GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)(data.Length * sizeof(ushort)), data, BufferUsageHint.StaticDraw);
   GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
   return ibo;

  public void BindToShader(Shader shader)
   GL.BindAttribLocation(shader.program, 0, "in_position");
   GL.BindAttribLocation(shader.program, 1, "in_normal");
   currentShader = shader;

  public void Render()
   // use correct shader
   // render
   GL.DrawElements(BeginMode.Triangles, numIndices, DrawElementsType.UnsignedShort, IntPtr.Zero);

  public void Free()
   // delete buffers
   GL.DeleteBuffers(1, ref vboPositions);
   GL.DeleteBuffers(1, ref vboNormals);
   GL.DeleteBuffers(1, ref ibo);
   GL.DeleteVertexArrays(1, ref vao);

using System;
using System.IO;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL;
namespace OpenTKTest
public class Shader
  public int program { get; private set; }
  private int vertexShader;
  private int fragmentShader;

  public Shader(string vertexShaderPath, string fragmentShaderPath)
   // load and compile vertex shader
   vertexShader = GL.CreateShader(ShaderType.VertexShader);
   GL.ShaderSource(vertexShader, new StreamReader(vertexShaderPath).ReadToEnd());
   // load and compile fragment shader
   fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
   GL.ShaderSource(fragmentShader, new StreamReader(fragmentShaderPath).ReadToEnd());
   // create shader program
   program = GL.CreateProgram();
   GL.AttachShader(program, vertexShader);
   GL.AttachShader(program, fragmentShader);
   // check for errors
   string log;
   GL.GetProgramInfoLog(program, out log);

  public void Use()

  public int GetUniformLocation(string uniform)
   return GL.GetUniformLocation(program, uniform);


#version 330

uniform mat4 mat_projection;
uniform mat4 mat_view;
uniform mat4 mat_world;
uniform mat4 mat_normalTransform

in vec4 in_position;
in vec3 in_normal;

out vec3 normal;

void main()
normal = (vec4(in_normal, 1.0f) * mat_normalTransform).xyz;
vec4 wPos = vec4(in_position, 1.0f) * mat_world;
vec4 vPos = wPos * mat_view;
vec4 gl_Position = vPos * mat_projection;

#version 330
out vec4 out_color;
void main()
out_color = vec4(1.0f, 1.0f, 1.0f, 1.0f);

The main source of the problem will probably with Application.cs or Mesh.cs.

"So there you have it, ladies and gentlemen: the only API I’ve ever used that requires both elevated privileges and a dedicated user thread just to copy a block of structures from the kernel to the user." - Casey Muratori



Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.