Jump to content
  • Advertisement
Sign in to follow this  
Klutzershy

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

This topic is 2378 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

[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.

Share this post


Link to post
Share on other sites
Advertisement
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!