From 6539dd5ee63304d4cc0f14bdb5061c66ae9383a2 Mon Sep 17 00:00:00 2001 From: allem Date: Mon, 9 Apr 2018 18:22:02 -0400 Subject: [PATCH] starting compute shader for tetrahedron intersections --- Platformer/PlatformWindow.cs | 170 +++++++++++++++++++++--------- Platformer/Platformer.csproj | 3 + Platformer/Util/Buffer.cs | 60 ++++++++--- Platformer/Util/Program.cs | 63 ++++++++--- Platformer/Util/Shader.cs | 55 +++++----- Platformer/Util/VertexArray.cs | 41 +++---- Platformer/shaders/intersect.comp | 25 +++++ Platformer/shaders/simple.frag | 4 +- Platformer/shaders/simple.vert | 9 +- 9 files changed, 303 insertions(+), 127 deletions(-) create mode 100644 Platformer/shaders/intersect.comp diff --git a/Platformer/PlatformWindow.cs b/Platformer/PlatformWindow.cs index fecd484..49f7257 100644 --- a/Platformer/PlatformWindow.cs +++ b/Platformer/PlatformWindow.cs @@ -1,74 +1,142 @@ using System; +using System.Drawing; using OpenTK; -using OpenTK.Graphics.OpenGL4; +using OpenTK.Graphics.OpenGL; using Platformer.Util; -using Buffer = Platformer.Util.Buffer; +using BeginMode = OpenTK.Graphics.OpenGL4.BeginMode; +using BufferRangeTarget = OpenTK.Graphics.OpenGL4.BufferRangeTarget; +using BufferTarget = OpenTK.Graphics.OpenGL4.BufferTarget; +using ClearBufferMask = OpenTK.Graphics.OpenGL4.ClearBufferMask; +using DrawElementsType = OpenTK.Graphics.OpenGL4.DrawElementsType; +using EnableCap = OpenTK.Graphics.OpenGL4.EnableCap; +using GL = OpenTK.Graphics.OpenGL4.GL; namespace Platformer { - public class PlatformWindow : GameWindow - { - private Program _render; + public struct ViewMats + { + public Matrix4 Model; + public Matrix4 View; + public Matrix4 Proj; - private Buffer _vbo; - private Buffer _ibo; + public static ViewMats Identity => new ViewMats {Model = Matrix4.Identity, View = Matrix4.Identity}; + } - private Vector4[] _verts; - private uint[] _inds; - private VertexArray _vao; + public class PlatformWindow : GameWindow + { + private Program _render; - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); + private Buffer _tVerts; + private Buffer _tFaces; + private Buffer _tEdges; + private Buffer _ubo; - _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), - }; + private VertexArray _tetraVao; - _inds = new uint[] - { - 0, 1, 2, - }; + private ViewMats _view; + private Buffer _tInds; + private Buffer _pVerts; + private Program _compute; + private Buffer _pEdges; + private Buffer _pAreas; + private VertexArray _polyVao; - var vert = Shader.Compile("shaders/simple.vert"); - var frag = Shader.Compile("shaders/simple.frag"); + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); - _render = Program.Link(vert, frag); + X = (DisplayDevice.Default.Width - Width) / 2; + Y = (DisplayDevice.Default.Height - Height) / 2; - _vbo = new Buffer(); - _vbo.SetData(_verts); + var vert = Shader.Compile("shaders/simple.vert"); + var frag = Shader.Compile("shaders/simple.frag"); + _render = Program.Link(vert, frag); - _ibo = new Buffer(); - _ibo.SetData(_inds); + var comp = Shader.Compile("shaders/intersect.comp"); + _compute = Program.Link(comp); - _vao = new VertexArray(); - _vao.VertexPointer(_vbo, index: 0, size: 4); - } + _tFaces = Buffer.FromData(new uint[] {0, 1, 2, 0, 1, 3, 0, 2, 3, 1, 2, 3}); + _tEdges = Buffer.FromData(new uint[] {0, 1, 0, 2, 0, 3, 1, 2, 1, 3, 2, 3}); + _tVerts = Buffer.FromData(new[] + { + new Vector4(-.5f - 1, -.5f, -.5f, 1), + new Vector4(+.5f - 1, +.5f, -.5f, 1), + new Vector4(+.5f - 1, -.5f, +.5f, 1), + new Vector4(-.5f - 1, +.5f, +.5f, 1), - protected override void OnRenderFrame(FrameEventArgs e) - { - base.OnRenderFrame(e); + new Vector4(-.5f + 1, -.5f, -.5f, 1), + new Vector4(+.5f + 1, +.5f, -.5f, 1), + new Vector4(+.5f + 1, -.5f, +.5f, 1), + new Vector4(-.5f + 1, +.5f, +.5f, 1), + }); - GL.Clear(ClearBufferMask.ColorBufferBit); + _tInds = Buffer.FromData(new uint[] {0, 1, 2, 3}); + _pVerts = new Buffer(_tInds.Count / 4 * 4); + _pEdges = new Buffer(_tInds.Count / 4 * 8); + _pAreas = new Buffer(_tInds.Count / 4 * 6); - GL.Viewport(ClientRectangle); + _ubo = new Buffer(); + _view = ViewMats.Identity; - GL.UseProgram(_render); - GL.BindVertexArray(_vao); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ibo); - GL.DrawElements(BeginMode.Triangles, _inds.Length, DrawElementsType.UnsignedInt, 0); - GL.Flush(); + GL.BindBufferBase(BufferRangeTarget.UniformBuffer, 0, _ubo); + GL.UniformBlockBinding(_render, _render.UnifBlockInd("ViewMats"), 0); - SwapBuffers(); - } + _tetraVao = new VertexArray(); + _tetraVao.VertexPointer(_tVerts, index: _render.AttrLoc("pos"), size: 4); - protected override void OnUpdateFrame(FrameEventArgs e) - { - base.OnUpdateFrame(e); - } - } + _polyVao = new VertexArray(); + _polyVao.VertexPointer(_pVerts, index: _render.AttrLoc("pos"), size: 4); + } + + protected override void OnRenderFrame(FrameEventArgs e) + { + base.OnRenderFrame(e); + + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + GL.Viewport(ClientRectangle); + + GL.UseProgram(_render); + + GL.BindVertexArray(_tetraVao); + + GL.Enable(EnableCap.DepthTest); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tEdges); + GL.Uniform3(_render.UnifLoc("color"), 0f, 0, 0); + GL.DrawElements(BeginMode.Lines, _tEdges.Count, DrawElementsType.UnsignedInt, 0); + GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tFaces); + GL.Uniform3(_render.UnifLoc("color"), 1f, 1, 1); + GL.DrawElements(BeginMode.Triangles, _tEdges.Count, DrawElementsType.UnsignedInt, 0); + GL.Disable(EnableCap.DepthTest); + + GL.BindVertexArray(_polyVao); + + GL.BindBuffer(BufferTarget.ElementArrayBuffer, _pEdges); + GL.Uniform3(_render.UnifLoc("color"), .1f, .1f, .9f); + GL.DrawElements(BeginMode.Lines, _pEdges.Count, DrawElementsType.UnsignedInt, 0); + + GL.Flush(); + + SwapBuffers(); + } + + protected override void OnUpdateFrame(FrameEventArgs e) + { + base.OnUpdateFrame(e); + + _view.Proj = Matrix4.CreateOrthographic(5, 5f * Height / Width, -2.5f, 2.5f); + _view.View = Matrix4.LookAt(Vector3.Zero, -Vector3.One, Vector3.UnitZ); + + _view.Model *= Matrix4.CreateRotationZ((float) e.Time); + + _ubo.SetData(ref _view); + + GL.UseProgram(_compute); + GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 0, _tVerts); + GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 1, _tInds); + GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 2, _pVerts); + GL.BindBufferBase(BufferRangeTarget.ShaderStorageBuffer, 3, _pEdges); + GL.DispatchCompute(_tInds.Count / 4, 1, 1); + } + } } \ No newline at end of file diff --git a/Platformer/Platformer.csproj b/Platformer/Platformer.csproj index b4c6fac..9cc4ced 100644 --- a/Platformer/Platformer.csproj +++ b/Platformer/Platformer.csproj @@ -52,6 +52,9 @@ + + Always + Always diff --git a/Platformer/Util/Buffer.cs b/Platformer/Util/Buffer.cs index c43fbdc..be3bc00 100644 --- a/Platformer/Util/Buffer.cs +++ b/Platformer/Util/Buffer.cs @@ -1,20 +1,56 @@ using System; +using System.Net; using System.Runtime.InteropServices; using OpenTK.Graphics.OpenGL4; namespace Platformer.Util { - public class Buffer : GlObj - { - public Buffer() : base(GL.GenBuffer()) - { - } + public class Buffer : GlObj where T : struct + { + public static readonly int ElementSize = Marshal.SizeOf(typeof(T)); + public int Count { get; private set; } - 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); - } - } + public Buffer() : base(GL.GenBuffer()) + { + Count = 0; + } + + public Buffer(int size, BufferUsageHint usage = BufferUsageHint.StaticDraw) : base(GL.GenBuffer()) + { + Count = size; + GL.BindBuffer(BufferTarget.ArrayBuffer, this); + GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (size * ElementSize), IntPtr.Zero, usage); + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + } + + public void SetData(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) + { + Count = data.Length; + GL.BindBuffer(BufferTarget.ArrayBuffer, this); + GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (data.Length * ElementSize), data, usage); + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + } + + public void SetData(ref T data, BufferUsageHint usage = BufferUsageHint.StaticDraw) + { + Count = 1; + GL.BindBuffer(BufferTarget.ArrayBuffer, this); + GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr) (ElementSize), ref data, usage); + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + } + + public static Buffer FromData(T[] data, BufferUsageHint usage = BufferUsageHint.StaticDraw) + { + var buf = new Buffer(); + buf.SetData(data, usage); + return buf; + } + + public static Buffer FromData(ref T data, BufferUsageHint usage = BufferUsageHint.StaticDraw) + { + var buf = new Buffer(); + buf.SetData(ref data, usage); + return buf; + } + } } \ No newline at end of file diff --git a/Platformer/Util/Program.cs b/Platformer/Util/Program.cs index fa53870..945cd91 100644 --- a/Platformer/Util/Program.cs +++ b/Platformer/Util/Program.cs @@ -1,20 +1,53 @@ -using OpenTK.Graphics.OpenGL4; +using System; +using System.Collections.Generic; +using OpenTK.Graphics.OpenGL4; namespace Platformer.Util { - public class Program : GlObj - { - public Program() : base(GL.CreateProgram()) - { - } + public class Program : GlObj + { + private Dictionary _unifCache; + private Dictionary _attrCache; + private Dictionary _unifBlockCache; - 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; - } - } + public Program() : base(GL.CreateProgram()) + { + _unifCache = new Dictionary(); + _attrCache = new Dictionary(); + _unifBlockCache = new Dictionary(); + } + + public int UnifLoc(string name) + { + if (!_unifCache.ContainsKey(name)) + _unifCache[name] = GL.GetUniformLocation(this, name); + return _unifCache[name]; + } + + public int UnifBlockInd(string name) + { + if (!_unifBlockCache.ContainsKey(name)) + _unifBlockCache[name] = GL.GetUniformBlockIndex(this, name); + return _unifBlockCache[name]; + } + + public int AttrLoc(string name) + { + if (!_attrCache.ContainsKey(name)) + _attrCache[name] = GL.GetAttribLocation(this, name); + return _attrCache[name]; + } + + public static Program Link(params Shader[] shaders) + { + var p = new Program(); + foreach (var s in shaders) + GL.AttachShader(p, s); + GL.LinkProgram(p); + + Console.Error.WriteLine(GL.GetProgramInfoLog(p)); + + return p; + } + } } \ No newline at end of file diff --git a/Platformer/Util/Shader.cs b/Platformer/Util/Shader.cs index bc7b06b..926b57f 100644 --- a/Platformer/Util/Shader.cs +++ b/Platformer/Util/Shader.cs @@ -5,36 +5,37 @@ 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 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 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(ShaderType type, string source) + { + var s = new Shader(type); + GL.ShaderSource(s, source); + GL.CompileShader(s); + Console.Error.WriteLine(GL.GetShaderInfoLog(s)); + return s; + } - public static Shader Compile(string filename) - { - var ext = Path.GetExtension(filename); + 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}"); + if (!_shaderTypes.ContainsKey(ext)) + throw new InvalidOperationException($"Can't infer shader type for {filename}"); - return Compile(_shaderTypes[ext], File.ReadAllText(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 index 633ee1d..fae927b 100644 --- a/Platformer/Util/VertexArray.cs +++ b/Platformer/Util/VertexArray.cs @@ -2,25 +2,26 @@ namespace Platformer.Util { - public class VertexArray : GlObj - { - public VertexArray() : base(GL.GenVertexArray()) - { - } + 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); - } - } + public void VertexPointer(Buffer buffer, int index, int size, + VertexAttribPointerType type = VertexAttribPointerType.Float, + bool normalized = false, int stride = 0, int offset = 0) + where T : struct + { + 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/intersect.comp b/Platformer/shaders/intersect.comp new file mode 100644 index 0000000..78c0094 --- /dev/null +++ b/Platformer/shaders/intersect.comp @@ -0,0 +1,25 @@ +#version 430 + +layout(std430, binding=0) buffer TetraVerts +{ + vec4 tetraVerts[]; +}; + +layout(std430, binding=1) buffer TetraInds +{ + uint tetraInds[]; +}; + +layout(std430, binding=2) buffer PolyVerts +{ + vec4 polyVerts[]; +}; + +layout(std430, binding=3) buffer EdgeInds +{ + uint edgeInds[]; +}; + +void main () { + +} \ No newline at end of file diff --git a/Platformer/shaders/simple.frag b/Platformer/shaders/simple.frag index 3bc0b13..34e31b4 100644 --- a/Platformer/shaders/simple.frag +++ b/Platformer/shaders/simple.frag @@ -1,5 +1,7 @@ #version 430 +uniform vec3 color; + void main () { - gl_Fragcolor = vec4(1); + gl_FragColor = vec4(color, 1); } \ No newline at end of file diff --git a/Platformer/shaders/simple.vert b/Platformer/shaders/simple.vert index 4a14504..2f0b658 100644 --- a/Platformer/shaders/simple.vert +++ b/Platformer/shaders/simple.vert @@ -1,7 +1,14 @@ #version 430 +uniform ViewMats +{ + mat4 model; + mat4 view; + mat4 proj; +}; + in vec4 pos; void main () { - gl_Position = pos; + gl_Position = proj * view * model * pos; } \ No newline at end of file