Skip to content

Instantly share code, notes, and snippets.

@Daomephsta
Last active December 13, 2017 21:42
Show Gist options
  • Save Daomephsta/17d36f84d4ab2452a4975999edeca8a2 to your computer and use it in GitHub Desktop.
Save Daomephsta/17d36f84d4ab2452a4975999edeca8a2 to your computer and use it in GitHub Desktop.
OpenGL Testbed
using OpenGL_Testbed.Lib;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using System;
using System.IO;
using OpenTK.Input;
namespace OpenGL_Testbed
{
public class Cameras : GameWindow
{
private ShaderProgram shaderProgram;
private VertexBuffer vbo;
private VertexArray vao;
private Texture texture1;
private Texture texture2;
//Camera variables
private Vector3 pos = new Vector3(0, 0, 3);
private Vector3 front = new Vector3(0.0f, 0.0f, -1.0f), right, up = new Vector3(0.0F, 1.0F, 0.0F);
private double pitch, yaw = -90.0F;
private int lastMouseX, lastMouseY;
private bool firstMouse = true;
private float deltaTime = 0.0F; //Time between the current frame and the last one
private float lastFrameTime = 0.0F; //The timestamp of the last frame
private readonly float[] vertices =
{
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
public Cameras() : base(800, 600, GraphicsMode.Default, "Test Game", GameWindowFlags.FixedWindow, DisplayDevice.Default, 3, 3, GraphicsContextFlags.Default) {}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
GL.Viewport(0, 0, this.Width, this.Height);
}
protected override void OnLoad(EventArgs e)
{
//Setup the viewport & capture the mouse
GL.Viewport(0, 0, this.Width, this.Height);
CursorVisible = false;
//Load the textures
try
{
texture1 = new Texture("resources/textures/container.jpg");
texture2 = new Texture("resources/textures/awesomeface.png");
}
catch (FileNotFoundException fnf)
{
Console.Write(fnf.ToString());
}
//Create a vertex shader
Shader vertShader = Shader.CreateShaderFromFile(ShaderType.VertexShader, "coordSystemsVertex");
//Create a fragment shader
Shader fragShader = Shader.CreateShaderFromFile(ShaderType.FragmentShader, "coordSystemsFragment");
//Create a shader program
shaderProgram = new ShaderProgram();
shaderProgram.Attach(vertShader, delete: true);
shaderProgram.Attach(fragShader, delete: true);
shaderProgram.Link("shaderProgram");
vao = new VertexArray();
vao.Bind();
//Create a VBO(Vertex Buffer Object)
vbo = new VertexBuffer();
vbo.Bind();
vbo.SetData(vertices, BufferUsageHint.StaticDraw);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
vbo.Unbind();
vao.Unbind();
shaderProgram.Use();
shaderProgram.SetUniform("texture1", 0);
shaderProgram.SetUniform("texture2", 1);
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45.0F), (float)Width / Height, 0.1F, 100.0F);
shaderProgram.SetUniform("projection", projection);
}
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
GL.Enable(EnableCap.DepthTest);
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
float currentFrame = Environment.TickCount / 1000.0F;
deltaTime = currentFrame - lastFrameTime;
lastFrameTime = currentFrame;
GL.ActiveTexture(TextureUnit.Texture0);
texture1.Bind();
GL.ActiveTexture(TextureUnit.Texture1);
texture2.Bind();
Matrix4 view = Matrix4.LookAt(pos, pos + front, up);
shaderProgram.SetUniform("view", view);
Vector3[] cubePositions =
{
new Vector3( 0.0f, 0.0f, 0.0f),
new Vector3( 2.0f, 5.0f, -15.0f),
new Vector3(-1.5f, -2.2f, -2.5f),
new Vector3(-3.8f, -2.0f, -12.3f),
new Vector3( 2.4f, -0.4f, -3.5f),
new Vector3(-1.7f, 3.0f, -7.5f),
new Vector3( 1.3f, -2.0f, -2.5f),
new Vector3( 1.5f, 2.0f, -2.5f),
new Vector3( 1.5f, 0.2f, -1.5f),
new Vector3(-1.3f, 1.0f, -1.5f)
};
vao.Bind();
for(int i = 0; i < 10; i++)
{
float angle = i * 20;
Matrix4 model = Matrix4.CreateFromAxisAngle(new Vector3(1.0f, 0.3f, 0.5f), MathHelper.DegreesToRadians(angle)) * Matrix4.CreateTranslation(cubePositions[i]);
shaderProgram.SetUniform("model", model);
GL.DrawArrays(PrimitiveType.Triangles, 0, 36);
}
vao.Unbind();
SwapBuffers();
}
private void RecalculateLocalUnitVectors()
{
right = Vector3.Normalize(Vector3.Cross(Vector3.UnitY, front));
up = Vector3.Cross(front, right);
}
public void MoveCamera(float x = 0.0F, float y = 0.0F, float z = 0.0F)
{
MoveCamera(new Vector3(x, y, z));
}
public void MoveCamera(Vector3 xyz)
{
pos += xyz;
}
protected override void OnKeyDown(KeyboardKeyEventArgs e)
{
float moveSpeed = 2.5F * deltaTime;
if (Keyboard.GetState().IsKeyDown(Key.Escape)) CursorVisible = true;
if (Keyboard.GetState().IsKeyDown(Key.W)) MoveCamera(moveSpeed * front);
if (Keyboard.GetState().IsKeyDown(Key.S)) MoveCamera(-moveSpeed * front);
if (Keyboard.GetState().IsKeyDown(Key.A)) MoveCamera(moveSpeed * right);
if (Keyboard.GetState().IsKeyDown(Key.D)) MoveCamera(-moveSpeed * right);
}
protected override void OnMouseDown(MouseButtonEventArgs e) { CursorVisible = false; }
protected override void OnMouseMove(MouseMoveEventArgs e)
{
if (CursorVisible) return;
if(firstMouse)
{
lastMouseX = e.X;
lastMouseY = e.Y;
firstMouse = false;
}
double xOffset = e.X - lastMouseX;
double yOffset = e.Y - lastMouseY;
lastMouseX = e.X;
lastMouseY = e.Y;
double sensitivity = 0.05F;
xOffset *= sensitivity;
yOffset *= sensitivity;
yaw = yaw + xOffset;
pitch = pitch + yOffset;
pitch = MathHelper.Clamp(pitch, -89.0D, 89.0D);
Vector3d tempFront;
tempFront.X = Math.Cos(MathHelper.DegreesToRadians(pitch)) * Math.Cos(MathHelper.DegreesToRadians(yaw));
tempFront.Y = Math.Sin(MathHelper.DegreesToRadians(pitch));
tempFront.Z = Math.Cos(MathHelper.DegreesToRadians(pitch)) * Math.Sin(MathHelper.DegreesToRadians(yaw));
front = (Vector3) Vector3d.Normalize(tempFront);
RecalculateLocalUnitVectors();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
//Cleanup
vao.Delete();
vbo.Delete();
}
}
}
#version 330 core
out vec4 fragmentColour;
in vec2 uv;
uniform sampler2D texture1;
uniform sampler2D texture2;
void main()
{
fragmentColour = mix(texture(texture1, uv), texture(texture2, uv), 0.2);
}
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec2 uvIn;
out vec2 uv;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(position, 1.0);
uv = uvIn;
}
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
using opengl = OpenTK.Graphics.OpenGL;
using imaging = System.Drawing.Imaging;
namespace OpenGL_Testbed.Lib
{
public class Shader
{
internal readonly int glID;
public Shader(ShaderType type, string shadername, params string[] shaderSource)
{
this.glID = GL.CreateShader(type);
GL.ShaderSource(this.glID, shaderSource.Length, shaderSource, (int[])null);
GL.CompileShader(this.glID);
Console.WriteLine("Compiling shader: " + shadername + ".glsl");
//Check the shader compiled successfully
int success;
GL.GetShader(this.glID, ShaderParameter.CompileStatus, out success);
if (success == 0)
{
Console.WriteLine("Could not compile shader: " + shadername + ".glsl");
string errors;
GL.GetShaderInfoLog(this.glID, out errors);
Console.WriteLine(errors);
}
else
{
Console.WriteLine("Shader: " + shadername + ".glsl compiled successfully!");
}
}
public static Shader CreateShaderFromFile(ShaderType type, String shaderName)
{
StringBuilder source = new StringBuilder();
using (StreamReader reader = new StreamReader(Environment.CurrentDirectory + "\\resources\\shaders\\" + shaderName + ".glsl"))
{
while (reader.Peek() != -1)
{
source.AppendLine(reader.ReadLine());
}
}
return new Shader(type, shaderName, source.ToString());
}
public void Delete()
{
GL.DeleteShader(this.glID);
}
public static void DeleteShaders(Shader[] shaders)
{
foreach (Shader shader in shaders)
{
GL.DeleteShader(shader.glID);
}
}
}
public class ShaderProgram
{
internal readonly int glID;
public ShaderProgram()
{
this.glID = GL.CreateProgram();
}
public void Attach(Shader shader, bool delete = false)
{
GL.AttachShader(this.glID, shader.glID);
if (delete) shader.Delete();
}
public void Link(string name)
{
GL.LinkProgram(this.glID);
Console.WriteLine("Attempting to link shader program: " + name);
//Check the link succeeded
int success;
GL.GetProgram(this.glID, GetProgramParameterName.LinkStatus, out success);
if (success == 0)
{
Console.WriteLine("Linking of shader program: " + name + " failed");
string errors;
GL.GetProgramInfoLog(this.glID, out errors);
Console.WriteLine(errors);
}
else
{
Console.WriteLine("Shader program: " + name + " linked successfully!");
}
}
public void Use()
{
GL.UseProgram(this.glID);
}
public int GetUniformLocation(string uniformName)
{
return GL.GetUniformLocation(this.glID, uniformName);
}
public void SetUniform(string uniformName, int value)
{
GL.Uniform1(GL.GetUniformLocation(this.glID, uniformName), value);
}
public void SetUniform(string uniformName, float value)
{
GL.Uniform1(GL.GetUniformLocation(this.glID, uniformName), value);
}
public void SetUniform(string uniformName, Matrix4 value)
{
GL.UniformMatrix4(GL.GetUniformLocation(this.glID, uniformName), false, ref value);
}
}
public class VertexBuffer
{
internal readonly int glID;
public VertexBuffer()
{
this.glID = GL.GenBuffer();
}
public void Bind()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, this.glID);
}
public void Unbind()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
}
public void SetData(float[] vertices, BufferUsageHint usageHint)
{
GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * vertices.Length, vertices, usageHint);
}
public void Delete()
{
GL.DeleteBuffer(this.glID);
}
public static void DeleteVBOS(VertexBuffer[] buffers)
{
foreach (VertexBuffer buffer in buffers)
{
GL.DeleteBuffer(buffer.glID);
}
}
}
public class ElementBuffer
{
internal readonly int glID;
public ElementBuffer()
{
this.glID = GL.GenBuffer();
}
public void Bind()
{
GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.glID);
}
public void Unbind()
{
GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0);
}
public void SetData(int[] indices, BufferUsageHint usageHint)
{
GL.BufferData(BufferTarget.ElementArrayBuffer, sizeof(int) * indices.Length, indices, usageHint);
}
public void Delete()
{
GL.DeleteBuffer(this.glID);
}
public static void DeleteEBOS(ElementBuffer[] buffers)
{
foreach (ElementBuffer buffer in buffers)
{
GL.DeleteBuffer(buffer.glID);
}
}
}
public class VertexArray
{
internal readonly int glID;
public VertexArray()
{
this.glID = GL.GenVertexArray();
}
public void Bind()
{
GL.BindVertexArray(this.glID);
}
public void Unbind()
{
GL.BindVertexArray(0);
}
public void Delete()
{
GL.DeleteVertexArray(this.glID);
}
public static void DeleteVAOS(VertexArray[] vaos)
{
foreach (VertexArray vao in vaos)
{
GL.DeleteVertexArray(vao.glID);
}
}
}
public struct Texture
{
internal readonly int glID;
public Texture(String fileName) : this(fileName, imaging::PixelFormat.Format24bppRgb, opengl::PixelFormat.Bgr) {}
public Texture(String fileName, imaging::PixelFormat imageFormat, opengl::PixelFormat format)
{
glID = GL.GenTexture();
using (Bitmap bitmap = new Bitmap(fileName))
{
bitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
BitmapData imageData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, imageFormat);
GL.BindTexture(TextureTarget.Texture2D, glID);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, bitmap.Width, bitmap.Height, 0, format, PixelType.UnsignedByte, imageData.Scan0);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
//Cleanup
GL.BindTexture(TextureTarget.Texture2D, 0);
bitmap.UnlockBits(imageData);
}
}
public void Bind()
{
GL.BindTexture(TextureTarget.Texture2D, glID);
}
public void Unbind()
{
GL.BindTexture(TextureTarget.Texture2D, glID);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment