Skip to content

Instantly share code, notes, and snippets.

@GeirGrusom
Created November 4, 2014 05:44
Show Gist options
  • Save GeirGrusom/347f30e981f33972c934 to your computer and use it in GitHub Desktop.
Save GeirGrusom/347f30e981f33972c934 to your computer and use it in GitHub Desktop.
OpenTK colored triangle example
using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
namespace OpenTKExample
{
class Program
{
static void Main()
{
var display = new Form { Text = "OpenTK loop example", Size = new Size(640, 480)};
display.Show();
// Create window info and context
var windowInfo = OpenTK.Platform.Utilities.CreateWindowsWindowInfo(display.Handle);
IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, windowInfo);
// Make the new context current
context.MakeCurrent(windowInfo);
var isRunning = true;
display.FormClosing += (sender, e) => isRunning = false;
// Load all function pointers
context.LoadAll();
// Set clear color
GL.ClearColor(Color4.Black);
var vertexBuffer = CreateVertexBuffer();
var vertexArray = CreateVertexArray(vertexBuffer);
// The most basic of verrtex shaders.
const string vertexShaderCode =
"uniform mat4 Mvp; in vec4 color; in vec3 position; out vec4 fragcolor; void main() { gl_Position = Mvp * vec4(position, 1); fragcolor = color; }";
// The most basic of fragment shaders.
const string fragmentShaderCode = "in vec4 fragcolor; out vec4 FragColor; void main() { FragColor = fragcolor; }";
var vertexShader = CreateVertexShader(vertexShaderCode);
var fragmentShader = CreateFragmentShader(fragmentShaderCode);
// Create the shader program
int program = GL.CreateProgram();
// Attach the shaders to the program
GL.AttachShader(program, vertexShader);
GL.AttachShader(program, fragmentShader);
// Set FragColor as output fragment variable
GL.BindFragDataLocation(program, 0, "FragColor");
GL.BindAttribLocation(program, 0, "position");
GL.BindAttribLocation(program, 1, "color");
GL.LinkProgram(program);
GL.ValidateProgram(program);
GL.UseProgram(program);
// Get the uniform location of mvp which we will use to set the value with later on.
int mvp = GL.GetUniformLocation(program, "Mvp");
Matrix4 view = Matrix4.LookAt(new Vector3(0, 2, 2), new Vector3(), Vector3.UnitY);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(((float)Math.PI / 180) * 80, 640.0f/480.0f, 0.1f, 10f);
float angle = 0;
var lastTimestamp = Stopwatch.GetTimestamp();
var freq = Stopwatch.Frequency;
do
{
var timeStamp = Stopwatch.GetTimestamp();
angle += (float)((timeStamp - lastTimestamp) / (double)freq);
lastTimestamp = timeStamp;
// Clear color and depth buffers
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
// Create a rotation matrix
var model = Matrix4.CreateFromAxisAngle(Vector3.UnitY, angle);
Matrix4 modelViewProjection = model * view * projection;
GL.UniformMatrix4(mvp, false, ref modelViewProjection);
GL.BindVertexArray(vertexArray);
GL.DrawArrays(PrimitiveType.Triangles, 0, 3);
// Present result
context.SwapBuffers();
// Process windows events (this may invoke the FormClosing event if the user closed the form)
Application.DoEvents();
} while (isRunning); // If the user closed the form then FormClosing should have changed isRunning variable to false
context.Dispose();
}
private static int CreateVertexShader(string code)
{
var shader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(shader, code);
GL.CompileShader(shader);
return shader;
}
private static int CreateFragmentShader(string code)
{
var shader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(shader, code);
GL.CompileShader(shader);
return shader;
}
private static int CreateVertexArray(int vertexBuffer)
{
int array = GL.GenVertexArray();
GL.BindVertexArray(array);
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 28, IntPtr.Zero);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 28, new IntPtr(12));
GL.EnableVertexAttribArray(1);
GL.BindVertexArray(0);
return array;
}
private static int CreateVertexBuffer()
{
var vertexBuffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer);
var vertices = new Vertex[]
{
new Vertex { Color = Color4.Red, Position = new Vector3(-0.5f, 0, 0)},
new Vertex { Color = Color4.Green, Position = new Vector3(0.5f, 0.5f, 0)},
new Vertex { Color = Color4.Blue, Position = new Vector3(-0.5f, 1, 0)}
};
var handle = GCHandle.Alloc(vertices, GCHandleType.Pinned);
try
{
GL.BufferData(BufferTarget.ArrayBuffer, new IntPtr(28*vertices.Length), handle.AddrOfPinnedObject(),
BufferUsageHint.StaticDraw);
}
finally
{
handle.Free();
}
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
return vertexBuffer;
}
[StructLayout(LayoutKind.Sequential, Pack = 4)]
struct Vertex
{
public Vector3 Position;
public Color4 Color;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment