diff --git a/Diamond/Buffers/VertexPointerAttribute.cs b/Diamond/Buffers/VertexPointerAttribute.cs index b4dbfdd..f588634 100644 --- a/Diamond/Buffers/VertexPointerAttribute.cs +++ b/Diamond/Buffers/VertexPointerAttribute.cs @@ -3,14 +3,45 @@ using OpenTK.Graphics.OpenGL4; namespace Diamond.Buffers { - [AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = true)] + /// + /// Marks a field as an attribute to be sent to a shader. Must be used on public fields of a struct. + /// + [AttributeUsage(AttributeTargets.Field, AllowMultiple = true)] public sealed class VertexPointerAttribute : Attribute { + /// + /// The attribute name that the values of this field should point to + /// public string Name { get; } + + /// + /// The number of elements in this attribute + /// Corresponds to the size parameter to glVertexAttribPointer. + /// public int Size { get; } + + /// + /// The element type of the attribute + /// Corresponds to the type parameter to glVertexAttribPointer + /// public VertexAttribPointerType Type { get; set; } = VertexAttribPointerType.Float; + + /// + /// Whether to normalize the values of this attribute + /// Corresponds to the normalized parameter to glVertexAttribPointer + /// public bool Normalized { get; set; } = false; + + /// + /// The divisor to Instanced draw calls + /// Corresponds to the divisor parameter to glVertexAttribDivisor + /// public int Divisor { get; set; } = 0; + + /// + /// The offset of this attribute within each element + /// Corresponds to the offset parameter to glVertexAttribPointer + /// public int Offset { get; set; } = 0; public VertexPointerAttribute(string name, int size) diff --git a/Diamond/GLObject.cs b/Diamond/GLObject.cs index 37013c7..23eabbc 100644 --- a/Diamond/GLObject.cs +++ b/Diamond/GLObject.cs @@ -2,18 +2,35 @@ namespace Diamond { + /// + /// Parent class for all gl Object wrappers. + /// public abstract class GLObject : IDisposable { + /// + /// The name of this object + /// public uint Id { get; protected set; } + /// + /// Force all GLObjects to define their name. + /// + /// The name of this object protected GLObject(uint id) { Id = id; } + /// + /// Called to free the name of this object. Usually corresponds to glDelete*. + /// protected abstract void Delete(); private bool _disposed = false; + + /// + /// Free the name of this object + /// public void Dispose() { if (_disposed) return; diff --git a/Diamond/Shaders/Program.cs b/Diamond/Shaders/Program.cs index 181658f..e575320 100644 --- a/Diamond/Shaders/Program.cs +++ b/Diamond/Shaders/Program.cs @@ -9,7 +9,7 @@ namespace Diamond.Shaders private Dictionary uniforms = new Dictionary(); private Dictionary attributes = new Dictionary(); - public string Log => GL.GetProgramInfoLog((int) Id); + public string Log => GL.GetProgramInfoLog((int) Id).Trim(); public Program() : base((uint) GL.CreateProgram()) @@ -23,7 +23,7 @@ namespace Diamond.Shaders public void Attach(Shader shader) => GL.AttachShader(Id, shader.Id); - public bool LinkStatus + public bool Linked { get { diff --git a/Diamond/Shaders/Shader.cs b/Diamond/Shaders/Shader.cs index 8e6fcaa..4a05290 100644 --- a/Diamond/Shaders/Shader.cs +++ b/Diamond/Shaders/Shader.cs @@ -4,10 +4,19 @@ using OpenTK.Graphics.OpenGL4; namespace Diamond.Shaders { + /// + /// Wraps methods for GL Shader objects. + /// public class Shader : GLObject { + /// + /// The type of this shader. + /// public readonly ShaderType Type; - + + /// + /// Gets and sets the shader source with glShaderSource and glGetShaderSource. + /// public string Source { get @@ -19,8 +28,14 @@ namespace Diamond.Shaders set { GL.ShaderSource((int) Id, value); } } - public string Log => GL.GetShaderInfoLog((int) Id); + /// + /// Retrieves this shader's compilation log with glGetShaderInfoLog. + /// + public string Log => GL.GetShaderInfoLog((int) Id).Trim(); + /// + /// Checks the compilation status of this shader with glGetShader. + /// public bool Compiled { get @@ -30,29 +45,52 @@ namespace Diamond.Shaders } } + /// + /// Creates a wrapper for a gl Shader object. + /// + /// The type of the shader to create public Shader(ShaderType type) : base((uint) GL.CreateShader(type)) { Type = type; } + /// + /// Frees this gl object. Called by GLObject.Dispose(). + /// protected override void Delete() { GL.DeleteShader(Id); } + /// + /// Compile the shader. + /// + /// Compilation success public bool Compile() { GL.CompileShader(Id); - GL.GetShader(Id, ShaderParameter.CompileStatus, out int success); - return success != 0; + return Compiled; } + /// + /// Creates and compiles a shader from a source file. + /// + /// Source file location + /// Type of the shader + /// The compiled shader public static Shader FromFile(string path, ShaderType type) { return FromFile(path, type, out bool success); } + /// + /// Creates and compiles a shader from a source file. + /// + /// Source file location + /// Type of the shader + /// Compilation success + /// The compiled shader public static Shader FromFile(string path, ShaderType type, out bool success) { var s = new Shader(type); diff --git a/Diamond/Shaders/ShaderException.cs b/Diamond/Shaders/ShaderException.cs index 76de65c..361816e 100644 --- a/Diamond/Shaders/ShaderException.cs +++ b/Diamond/Shaders/ShaderException.cs @@ -3,6 +3,9 @@ using System.Runtime.Serialization; namespace Diamond.Shaders { + /// + /// Exception relating to Shader and Program operations. + /// [Serializable] public class ShaderException : Exception { diff --git a/Diamond/Textures/Texture.cs b/Diamond/Textures/Texture.cs index d3df8a2..da57ddf 100644 --- a/Diamond/Textures/Texture.cs +++ b/Diamond/Textures/Texture.cs @@ -5,6 +5,9 @@ using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat; namespace Diamond.Textures { + /// + /// Wrapper class for gl Textures. + /// public class Texture : GLObject { public TextureTarget Target; diff --git a/hexworld/HexRender.cs b/hexworld/HexRender.cs index a02376d..81ec166 100644 --- a/hexworld/HexRender.cs +++ b/hexworld/HexRender.cs @@ -1,23 +1,30 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; -using System.Runtime.InteropServices; -using System.Security.Policy; +using System.Text; +using System.Threading.Tasks; using Diamond; using Diamond.Buffers; using Diamond.Shaders; using Diamond.Textures; using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; namespace hexworld { - public partial class HexRender : GameWindow + public class HexRender : GameWindow { + private readonly VertexData[] _cubeVerts = + JsonConvert.DeserializeObject(File.ReadAllText("cube.json")); + + private readonly TileData[] _tilesData = + JsonConvert.DeserializeObject(File.ReadAllText("tiles.json")); + private Program _pgm; private Texture _grass; @@ -26,8 +33,10 @@ namespace hexworld private Matrix4 _view; private Matrix4 _proj; - private VBO _tileVbo; - private VBO _cubeVbo; + private VBO _tileVbo; + private VBO _cubeVbo; + + private double _time; public HexRender(int width, int height) : base(width, height, new GraphicsMode(32, 24, 0, 0)) @@ -38,24 +47,24 @@ namespace hexworld Y = (DisplayDevice.Default.Height - Height) / 2; } - private double _t; - protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); - _t += e.Time; + + _time += e.Time; _view = Matrix4.LookAt(10 * Vector3.One, Vector3.Zero, Vector3.UnitZ); _proj = Matrix4.CreateOrthographic(Width / 100f, Height / 100f, -100, 100); + // wavy blocks around perimeter for (var i = 0; i < 16; i++) { - var ti = tiles[i]; - tiles[i].Position.Z = (float) (Math.Sin((_t + ti.Position.X - ti.Position.Y / 1.5) / 1.5) * .25); + var ti = _tilesData[i]; + _tilesData[i].Position.Z = (float) (Math.Sin((_time + ti.Position.X - ti.Position.Y / 1.5) / 1.5) * .25); } _tileVbo.Bind(); - GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr) (0), (IntPtr) (16 * 3 * sizeof(float)), tiles); + GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr) (0), (IntPtr) (16 * 3 * sizeof(float)), _tilesData); VBO.Unbind(); } @@ -63,42 +72,34 @@ namespace hexworld { base.OnLoad(e); - _cubeVbo = new VBO(); - _cubeVbo.Data(cubeVerts, BufferUsageHint.StaticDraw); - - _tileVbo = new VBO(); - _tileVbo.Data(tiles, BufferUsageHint.DynamicDraw); - using (var vs = Shader.FromFile("s.vs.glsl", ShaderType.VertexShader)) using (var fs = Shader.FromFile("s.fs.glsl", ShaderType.FragmentShader)) { - _pgm = Program.FromShaders(vs, fs); - if (!vs.Compiled | !fs.Compiled) { - Console.Out.WriteLine("Failed to compile shaders:"); - if (!vs.Compiled) - Console.Out.WriteLine("Vertex Shader:\n" + vs.Log.Trim()); - if (!fs.Compiled) - Console.Out.WriteLine("Fragment Shader:\n" + fs.Log.Trim()); - Console.Out.WriteLine("Press any key to exit."); - Console.ReadKey(); + Debug.WriteLine("Failed to compile shaders:"); + Debug.WriteLineIf(!vs.Compiled, $"Vertex Log:\n{vs.Log}"); + Debug.WriteLineIf(!fs.Compiled, $"Fragment Log:\n{fs.Log}"); + Exit(); + return; + } + + _pgm = Program.FromShaders(vs, fs); + + if (!_pgm.Link()) + { + Debug.WriteLine($"Failed to link program:\n{_pgm.Log}"); Exit(); return; } } - if (!_pgm.LinkStatus) - { - Console.Out.WriteLine("Failed to link program:"); - Console.Out.WriteLine(_pgm.Log.Trim()); - Console.Out.WriteLine("Press any key to exit."); - Console.ReadKey(); - Exit(); - return; - } - + _cubeVbo = new VBO(); + _cubeVbo.Data(_cubeVerts, BufferUsageHint.StaticDraw); _cubeVbo.AttribPointers(_pgm); + + _tileVbo = new VBO(); + _tileVbo.Data(_tilesData, BufferUsageHint.DynamicDraw); _tileVbo.AttribPointers(_pgm); _grass = Texture.FromBitmap(new Bitmap("grass.png")); @@ -111,11 +112,11 @@ namespace hexworld _pgm.Dispose(); - _grass.Dispose(); - _stone.Dispose(); - _tileVbo.Dispose(); _cubeVbo.Dispose(); + + _grass.Dispose(); + _stone.Dispose(); } protected override void OnRenderFrame(FrameEventArgs e) diff --git a/hexworld/TileData.cs b/hexworld/TileData.cs new file mode 100644 index 0000000..78abcd8 --- /dev/null +++ b/hexworld/TileData.cs @@ -0,0 +1,18 @@ +using Diamond.Buffers; +using Newtonsoft.Json; +using OpenTK; + +namespace hexworld +{ + public struct TileData + { + [JsonProperty("pos")] + [VertexPointer("glbpos", 3, Divisor = 1)] + public Vector3 Position; + + public TileData(Vector3 position) + { + Position = position; + } + } +} \ No newline at end of file diff --git a/hexworld/VertexData.cs b/hexworld/VertexData.cs index 819a274..9f869e3 100644 --- a/hexworld/VertexData.cs +++ b/hexworld/VertexData.cs @@ -1,53 +1,28 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Diamond; -using Diamond.Buffers; +using Diamond.Buffers; using Newtonsoft.Json; using OpenTK; namespace hexworld { - public partial class HexRender + public struct VertexData { - public struct Tile + [JsonProperty("pos")] + [VertexPointer("locpos", 3)] + public Vector3 Position; + + [JsonProperty("uv")] + [VertexPointer("coord", 2)] + public Vector2 UV; + + [JsonProperty("norm")] + [VertexPointer("norm", 3)] + public Vector3 Normal; + + public VertexData(Vector3 position, Vector2 uv, Vector3 normal) { - [JsonProperty("pos")] - [VertexPointer("glbpos", 3, Divisor = 1)] - public Vector3 Position; - - public Tile(Vector3 position) - { - Position = position; - } + Position = position; + UV = uv; + Normal = normal; } - - public struct Vertex - { - [JsonProperty("pos")] - [VertexPointer("locpos", 3)] - public Vector3 Position; - - [JsonProperty("uv")] - [VertexPointer("coord", 2)] - public Vector2 UV; - - [JsonProperty("norm")] - [VertexPointer("norm", 3)] - public Vector3 Normal; - - public Vertex(Vector3 position, Vector2 uv, Vector3 normal) - { - Position = position; - UV = uv; - Normal = normal; - } - } - - private readonly Vertex[] cubeVerts = JsonConvert.DeserializeObject(File.ReadAllText("cube.json")); - private Tile[] tiles = JsonConvert.DeserializeObject(File.ReadAllText("tiles.json")); } } \ No newline at end of file diff --git a/hexworld/hexworld.csproj b/hexworld/hexworld.csproj index 273820e..62595a0 100644 --- a/hexworld/hexworld.csproj +++ b/hexworld/hexworld.csproj @@ -51,9 +51,10 @@ + - + diff --git a/hexworld/stone.png b/hexworld/stone.png index 3d44249..1240af3 100644 Binary files a/hexworld/stone.png and b/hexworld/stone.png differ