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

Started by
-1 comments, last by Klutzershy 12 years, 1 month ago
[color=#333333][font=arial,helvetica,sans-serif]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.[/font]
[color=#333333][font=arial,helvetica,sans-serif]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.[/font]
[color=#333333][font=arial,helvetica,sans-serif]Can anyone give me a quick rundown of how this works?[/font]

[color=#333333][font=arial, helvetica, sans-serif]EDIT:[/font]

[font=arial, helvetica, sans-serif][color=#333333]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.[/font]

Application.cs

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)
{
base.OnLoad(e);

GL.ClearDepth(0.0f);
GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);
GL.Enable(EnableCap.DepthTest);

// 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)
{
base.OnResize(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)
{
base.OnUpdateFrame(e);

angle += (float)e.Time;

if (Keyboard[Key.Escape])
Exit();
}

protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(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);
matNormalTransform.Invert();

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

triangle.Render();

SwapBuffers();
}

[STAThread]
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())
{
game.Run(30.0);
}
}
}
}


Mesh.cs

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);
GL.BindVertexArray(vao);

// position attribute
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, vboPositions);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, Vector3.SizeInBytes, 0);

// normal attribute
GL.EnableVertexAttribArray(1);
GL.BindBuffer(BufferTarget.ArrayBuffer, vboNormals);
GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0);

// finalize
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo);
BindToShader(shader);

// unbind VAO, and VBO
GL.BindVertexArray(0);
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
currentShader.Use();

// render
GL.BindVertexArray(vao);
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);
}
}
}


Shader.cs

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());
GL.CompileShader(vertexShader);

// load and compile fragment shader
fragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(fragmentShader, new StreamReader(fragmentShaderPath).ReadToEnd());
GL.CompileShader(fragmentShader);

// create shader program
program = GL.CreateProgram();
GL.AttachShader(program, vertexShader);
GL.AttachShader(program, fragmentShader);
GL.LinkProgram(program);

// check for errors
string log;
GL.GetProgramInfoLog(program, out log);
Console.WriteLine(log);
}

public void Use()
{
GL.UseProgram(program);
}

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


shader.vert


#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;
}


shader.frag

#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

boreal.aggydaggy.com

This topic is closed to new replies.

Advertisement