diff --git a/Platformer/Driver.cs b/Platformer/Driver.cs
new file mode 100644
index 0000000..77ddee2
--- /dev/null
+++ b/Platformer/Driver.cs
@@ -0,0 +1,11 @@
+namespace Platformer
+{
+ internal static class Driver
+ {
+ public static void Main(string[] args)
+ {
+ using (var pw = new PlatformWindow())
+ pw.Run();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/PlatformWindow.cs b/Platformer/PlatformWindow.cs
new file mode 100644
index 0000000..fecd484
--- /dev/null
+++ b/Platformer/PlatformWindow.cs
@@ -0,0 +1,74 @@
+using System;
+using OpenTK;
+using OpenTK.Graphics.OpenGL4;
+using Platformer.Util;
+using Buffer = Platformer.Util.Buffer;
+
+namespace Platformer
+{
+ public class PlatformWindow : GameWindow
+ {
+ private Program _render;
+
+ private Buffer _vbo;
+ private Buffer _ibo;
+
+ private Vector4[] _verts;
+ private uint[] _inds;
+ private VertexArray _vao;
+
+ protected override void OnLoad(EventArgs e)
+ {
+ base.OnLoad(e);
+
+ _verts = new[]
+ {
+ new Vector4(-.5f, -.5f, +0, +1),
+ new Vector4(-.5f, +.5f, +0, +1),
+ new Vector4(+.5f, -.5f, +0, +1),
+ new Vector4(+.5f, +.5f, +0, +1),
+ };
+
+ _inds = new uint[]
+ {
+ 0, 1, 2,
+ };
+
+ var vert = Shader.Compile("shaders/simple.vert");
+ var frag = Shader.Compile("shaders/simple.frag");
+
+ _render = Program.Link(vert, frag);
+
+ _vbo = new Buffer();
+ _vbo.SetData(_verts);
+
+ _ibo = new Buffer();
+ _ibo.SetData(_inds);
+
+ _vao = new VertexArray();
+ _vao.VertexPointer(_vbo, index: 0, size: 4);
+ }
+
+ protected override void OnRenderFrame(FrameEventArgs e)
+ {
+ base.OnRenderFrame(e);
+
+ GL.Clear(ClearBufferMask.ColorBufferBit);
+
+ GL.Viewport(ClientRectangle);
+
+ GL.UseProgram(_render);
+ GL.BindVertexArray(_vao);
+ GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ibo);
+ GL.DrawElements(BeginMode.Triangles, _inds.Length, DrawElementsType.UnsignedInt, 0);
+ GL.Flush();
+
+ SwapBuffers();
+ }
+
+ protected override void OnUpdateFrame(FrameEventArgs e)
+ {
+ base.OnUpdateFrame(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/Platformer.csproj b/Platformer/Platformer.csproj
new file mode 100644
index 0000000..b4c6fac
--- /dev/null
+++ b/Platformer/Platformer.csproj
@@ -0,0 +1,70 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}
+ Exe
+ Properties
+ Platformer
+ Platformer
+ v4.0
+ 512
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\OpenTK.3.0.0-pre\lib\net20\OpenTK.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+
+
+
\ No newline at end of file
diff --git a/Platformer/Properties/AssemblyInfo.cs b/Platformer/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b8550e7
--- /dev/null
+++ b/Platformer/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Platformer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Platformer")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("9A4A039D-58DF-4FA1-8743-A0CBB452B9D3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
\ No newline at end of file
diff --git a/Platformer/Util/Buffer.cs b/Platformer/Util/Buffer.cs
new file mode 100644
index 0000000..c43fbdc
--- /dev/null
+++ b/Platformer/Util/Buffer.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Runtime.InteropServices;
+using OpenTK.Graphics.OpenGL4;
+
+namespace Platformer.Util
+{
+ public class Buffer : GlObj
+ {
+ public Buffer() : base(GL.GenBuffer())
+ {
+ }
+
+ public void SetData(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) where T : struct
+ {
+ GL.BindBuffer(BufferTarget.ArrayBuffer, this);
+ GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)(data.Length * Marshal.SizeOf(typeof(T))), data, usage);
+ GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/Util/GlObj.cs b/Platformer/Util/GlObj.cs
new file mode 100644
index 0000000..982a86b
--- /dev/null
+++ b/Platformer/Util/GlObj.cs
@@ -0,0 +1,14 @@
+namespace Platformer.Util
+{
+ public abstract class GlObj
+ {
+ public readonly int Id;
+
+ public GlObj(int id)
+ {
+ Id = id;
+ }
+
+ public static implicit operator int(GlObj o) => o.Id;
+ }
+}
\ No newline at end of file
diff --git a/Platformer/Util/Program.cs b/Platformer/Util/Program.cs
new file mode 100644
index 0000000..fa53870
--- /dev/null
+++ b/Platformer/Util/Program.cs
@@ -0,0 +1,20 @@
+using OpenTK.Graphics.OpenGL4;
+
+namespace Platformer.Util
+{
+ public class Program : GlObj
+ {
+ public Program() : base(GL.CreateProgram())
+ {
+ }
+
+ public static Program Link(params Shader[] shaders)
+ {
+ var p = new Program();
+ foreach (var s in shaders)
+ GL.AttachShader(p, s);
+ GL.LinkProgram(p);
+ return p;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/Util/Shader.cs b/Platformer/Util/Shader.cs
new file mode 100644
index 0000000..bc7b06b
--- /dev/null
+++ b/Platformer/Util/Shader.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using OpenTK.Graphics.OpenGL4;
+
+namespace Platformer.Util
+{
+ public class Shader : GlObj
+ {
+ private static Dictionary _shaderTypes = new Dictionary()
+ {
+ [".vert"] = ShaderType.VertexShader,
+ [".frag"] = ShaderType.FragmentShader,
+ [".geom"] = ShaderType.GeometryShader,
+ [".comp"] = ShaderType.ComputeShader,
+ };
+
+ public Shader(ShaderType type) : base(GL.CreateShader(type))
+ {
+ }
+
+ public static Shader Compile(ShaderType type, string source)
+ {
+ var s = new Shader(type);
+ GL.ShaderSource(s, source);
+ GL.CompileShader(s);
+ return s;
+ }
+
+ public static Shader Compile(string filename)
+ {
+ var ext = Path.GetExtension(filename);
+
+ if (!_shaderTypes.ContainsKey(ext))
+ throw new InvalidOperationException($"Can't infer shader type for {filename}");
+
+ return Compile(_shaderTypes[ext], File.ReadAllText(filename));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/Util/VertexArray.cs b/Platformer/Util/VertexArray.cs
new file mode 100644
index 0000000..633ee1d
--- /dev/null
+++ b/Platformer/Util/VertexArray.cs
@@ -0,0 +1,26 @@
+using OpenTK.Graphics.OpenGL4;
+
+namespace Platformer.Util
+{
+ public class VertexArray : GlObj
+ {
+ public VertexArray() : base(GL.GenVertexArray())
+ {
+ }
+
+ public void VertexPointer(Buffer buffer, int index, int size,
+ VertexAttribPointerType type = VertexAttribPointerType.Float,
+ bool normalized = false, int stride = 0, int offset = 0)
+ {
+ GL.BindVertexArray(this);
+
+ GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
+ GL.VertexAttribPointer(index, size, type, normalized, stride, offset);
+ GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
+
+ GL.EnableVertexArrayAttrib(this, index);
+
+ GL.BindVertexArray(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Platformer/shaders/simple.frag b/Platformer/shaders/simple.frag
new file mode 100644
index 0000000..3bc0b13
--- /dev/null
+++ b/Platformer/shaders/simple.frag
@@ -0,0 +1,5 @@
+#version 430
+
+void main () {
+ gl_Fragcolor = vec4(1);
+}
\ No newline at end of file
diff --git a/Platformer/shaders/simple.vert b/Platformer/shaders/simple.vert
new file mode 100644
index 0000000..4a14504
--- /dev/null
+++ b/Platformer/shaders/simple.vert
@@ -0,0 +1,7 @@
+#version 430
+
+in vec4 pos;
+
+void main () {
+ gl_Position = pos;
+}
\ No newline at end of file
diff --git a/Tetrahedrons.sln b/Tetrahedrons.sln
index c08ff30..296c85c 100644
--- a/Tetrahedrons.sln
+++ b/Tetrahedrons.sln
@@ -2,6 +2,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tetrahedrons", "Tetrahedrons\Tetrahedrons.csproj", "{D70DFA78-49B4-404B-BE1C-7CDC0DAE26FD}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Platformer", "Platformer\Platformer.csproj", "{9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -12,5 +14,9 @@ Global
{D70DFA78-49B4-404B-BE1C-7CDC0DAE26FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D70DFA78-49B4-404B-BE1C-7CDC0DAE26FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D70DFA78-49B4-404B-BE1C-7CDC0DAE26FD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9A4A039D-58DF-4FA1-8743-A0CBB452B9D3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal