diff --git a/Diamond/Buffers/Buffer.cs b/Diamond/Buffers/Buffer.cs
index aefe9be..1aa2ae9 100644
--- a/Diamond/Buffers/Buffer.cs
+++ b/Diamond/Buffers/Buffer.cs
@@ -8,6 +8,10 @@ using OpenTK.Graphics.OpenGL4;
namespace Diamond.Buffers
{
+ ///
+ /// Manages an OpenGL Buffer object
+ ///
+ /// The type of data used for this buffer
public class Buffer : GLObject where T : struct
{
private readonly BufferWrap _buffer;
@@ -16,8 +20,15 @@ namespace Diamond.Buffers
private readonly int _size;
+ ///
+ /// The target for this buffer; its type
+ ///
public BufferTarget Target => _buffer.Target;
+ ///
+ /// The usage hint for this buffer. Use StaticDraw for one-time uploads to
+ /// vertex buffers, and DynamicDraw for repeated uploads to vertex buffers.
+ ///
public BufferUsageHint Usage
{
get => _buffer.Usage;
@@ -32,12 +43,31 @@ namespace Diamond.Buffers
_vdi = VertexDataInfo.GetInfo();
}
+ ///
+ /// Upload data to this buffer
+ ///
+ /// The data to upload
public void Data(T[] data) => _buffer.Data(_size, data);
+ ///
+ /// Upload a range of data to this buffer
+ ///
+ /// The range offset
+ /// The range length
+ /// The data to upload, offset and length apply to both this and the target
public void Data(int offset, int count, T[] data) => _buffer.SubData(_size, offset, count, data);
+ ///
+ /// Upload a range of data to this buffer
+ ///
+ /// The data to upload
public void Data(SubArray data) => Data(data.Offset, data.Length, data.Array);
+ ///
+ /// Point this buffer to a program's vertex attributes. T must have [VertexDataAttribute], and all fields
+ /// of T must have [VertexPointerAttribute] to infer vertex pointer locations.
+ ///
+ /// The program to point this buffer to
public void PointTo(Program program)
{
if (_vdi == null)
@@ -60,6 +90,13 @@ namespace Diamond.Buffers
? $"Buffer<{typeof(T).Name}> {Target} ({Id})"
: $"Buffer<{typeof(T).Name}> {Target} {Name} ({Id})";
+ ///
+ /// Create an empty buffer of this type
+ ///
+ /// The buffer target
+ /// The initial usage hint
+ /// The name of this GLObject
+ /// The buffer, or null if initialization failed
internal static Buffer Empty(BufferTarget target, BufferUsageHint usage, string name)
{
var wrapper = new BufferWrap(target, usage);
@@ -70,6 +107,14 @@ namespace Diamond.Buffers
return service;
}
+ ///
+ /// Create a buffer of this type and upload data
+ ///
+ /// The data to upload
+ /// The buffer target
+ /// The initial usage hint
+ /// The name of this GLObject
+ /// The buffer, or null if initialization failed
internal static Buffer FromData(T[] data, BufferTarget target, BufferUsageHint usage, string name = null)
{
var service = Empty(target, usage, name);
@@ -80,11 +125,29 @@ namespace Diamond.Buffers
}
}
+ ///
+ /// Class for static Buffer operations and public factory methods
+ ///
public static class Buffer
{
+ ///
+ /// Create an empty buffer of this type
+ ///
+ /// The buffer target
+ /// The initial usage hint
+ /// The name of this GLObject
+ /// The buffer, or null if initialization failed
public static Buffer Empty(BufferTarget target, BufferUsageHint usage = BufferUsageHint.StaticDraw,
string name = null) where T : struct => Buffer.Empty(target, usage, name);
+ ///
+ /// Create a buffer of this type and upload data
+ ///
+ /// The data to upload
+ /// The buffer target
+ /// The initial usage hint
+ /// The name of this GLObject
+ /// The buffer, or null if initialization failed
public static Buffer FromData(T[] data, BufferTarget target,
BufferUsageHint usage = BufferUsageHint.StaticDraw,
string name = null) where T : struct => Buffer.FromData(data, target, usage, name);
diff --git a/Diamond/Diamond.csproj b/Diamond/Diamond.csproj
index 16be66b..a02a020 100644
--- a/Diamond/Diamond.csproj
+++ b/Diamond/Diamond.csproj
@@ -60,13 +60,12 @@
-
+
-
diff --git a/Diamond/GLObject.cs b/Diamond/GLObject.cs
index 7fce728..d784304 100644
--- a/Diamond/GLObject.cs
+++ b/Diamond/GLObject.cs
@@ -4,17 +4,33 @@ using NLog;
namespace Diamond
{
+ ///
+ /// Provide managed access to OpenGL objects
+ ///
public abstract class GLObject : IDisposable
{
+ ///
+ /// Logger for all GLObjects
+ ///
protected static readonly Logger Logger = LogManager.GetLogger("GLObject");
- private bool _disposed;
-
+ ///
+ /// Name of this GLObject used for identification
+ ///
public string Name { get; protected set; } = "GLObject";
+ ///
+ /// Underlying managed wrapper to this OpenGL object
+ ///
internal abstract Wrapper Wrapper { get; }
+
+ ///
+ /// The OpenGL name of this object
+ ///
public int Id => Wrapper.Id;
+ #region IDisposable
+
protected virtual void Dispose(bool disposing)
{
if (_disposed)
@@ -29,6 +45,10 @@ namespace Diamond
_disposed = true;
}
+ #region Implemented
+
+ private bool _disposed;
+
public void Dispose()
{
Dispose(true);
@@ -39,5 +59,9 @@ namespace Diamond
{
Dispose(false);
}
+
+ #endregion
+
+ #endregion
}
}
\ No newline at end of file
diff --git a/Diamond/Shaders/Program.cs b/Diamond/Shaders/Program.cs
index 23e5dae..90aad0a 100644
--- a/Diamond/Shaders/Program.cs
+++ b/Diamond/Shaders/Program.cs
@@ -6,14 +6,22 @@ using OpenTK.Graphics.OpenGL4;
namespace Diamond.Shaders
{
+ ///
+ /// Manages an OpenGL Program object
+ ///
public class Program : GLObject
{
private readonly ProgramWrap _program;
internal override Wrapper Wrapper => _program;
+ ///
+ /// The currently active program. Manually invoking glUseProgram will break this.
+ ///
public static Program Current { get; private set; }
+ // keep a cache of uniform and attributes to prevent repeated queries
private readonly Dictionary _uniforms = new Dictionary();
+
private readonly Dictionary _attributes = new Dictionary();
internal Program(ProgramWrap program, string name)
@@ -22,24 +30,42 @@ namespace Diamond.Shaders
Name = name;
}
+ // todo change these to not use int? - possibly use TryGet, or return negative value if not present
+
+ ///
+ /// Get the location of a uniform
+ ///
+ /// The name of the uniform
+ /// The location, or no value if uniform not present
public int? UniformLocation(string name)
{
if (_uniforms.ContainsKey(name)) return _uniforms[name];
return null;
}
+ ///
+ /// Get the location of an attribute
+ ///
+ /// The name of the attribute
+ /// The location, or no value if attribute not present
public int? AttributeLocation(string name)
{
if (_attributes.ContainsKey(name)) return _attributes[name];
return null;
}
+ ///
+ /// Use this Program to render. Also updates Program.Current
+ ///
public void Use()
{
GL.UseProgram(Id);
Current = this;
}
+ ///
+ /// Use the default shader to render
+ ///
//? Could create static Program instance which wraps the default shader
// ie Shader.Default.Use()
// would also allow sending arrays to the default attribs like gl_Vertex etc.
@@ -49,6 +75,10 @@ namespace Diamond.Shaders
Current = null;
}
+ ///
+ /// Helper method to try to link this program
+ ///
+ ///
private bool Link()
{
_uniforms.Clear();
@@ -68,6 +98,10 @@ namespace Diamond.Shaders
return true;
}
+ ///
+ /// Helper method to attach a shader to this program
+ ///
+ /// The shader to attach
private void Attach(Shader shader)
{
_program.Attach((ShaderWrap) shader.Wrapper);
@@ -75,16 +109,23 @@ namespace Diamond.Shaders
public override string ToString() => $"Program \'{Name}\' ({Id})";
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- }
-
#region Factory Methods
+ ///
+ /// Create a program from compiled shaders
+ ///
+ /// The name of this GLObject
+ /// The shaders to use in this program
+ /// The linked program, or null if initialization failed
public static Program FromShaders(string name, params Shader[] shaders) => FromShaders(name,
(IEnumerable) shaders);
+ ///
+ /// Create a program from compiled shaders
+ ///
+ /// The name of this GLObject
+ /// The shaders to use in this program
+ /// The linked program, or null if initialization failed
public static Program FromShaders(string name, IEnumerableshaders)
{
if (shaders == null)
@@ -110,9 +151,9 @@ namespace Diamond.Shaders
service.Attach(shader);
}
- service.Link();
+ var linked = service.Link();
- if (!wrapper.Linked)
+ if (!linked)
{
Logger.Warn("Failed to link {0}", service);
Logger.Debug("InfoLog for {0}", service);
@@ -125,9 +166,18 @@ namespace Diamond.Shaders
return service;
}
-
+ ///
+ /// Create a program from compiled shaders
+ ///
+ /// The shaders to use in this program
+ /// The linked program, or null if initialization failed
public static Program FromShaders(params Shader[] shaders) => FromShaders((IEnumerable) shaders);
+ ///
+ /// Create a program from compiled shaders
+ ///
+ /// The shaders to use in this program
+ /// The linked program, or null if initialization failed
public static Program FromShaders(IEnumerable shaders)
{
var shaderList = shaders.ToList(); // prevent multiple enumeration
@@ -136,14 +186,26 @@ namespace Diamond.Shaders
return FromShaders(name, shaderList);
}
+ ///
+ /// Create shaders from glsl source files, and create a program using them.
+ /// Shader types must be inferrable from file extensions.
+ ///
+ /// The glsl source files
+ /// The linked program, or null if initialization faileds
public static Program FromFiles(params string[] paths)
{
- var shaders = paths.Select(Shader.FromFile).ToList();
+ if (paths == null)
+ {
+ Logger.Warn("Cannot create a program from no shaders.");
+ return null;
+ }
+
+ var shaders = paths.Select(path => Shader.FromFile(path)).ToList();
var program = FromShaders(shaders);
foreach (var shader in shaders)
- shader.Dispose();
+ shader?.Dispose();
return program;
}
diff --git a/Diamond/Shaders/Shader.cs b/Diamond/Shaders/Shader.cs
index 05ebbe7..18d672a 100644
--- a/Diamond/Shaders/Shader.cs
+++ b/Diamond/Shaders/Shader.cs
@@ -6,12 +6,22 @@ using OpenTK.Graphics.OpenGL4;
namespace Diamond.Shaders
{
+ ///
+ /// Manges a OpenGL Shader object
+ ///
public class Shader : GLObject
{
private readonly ShaderWrap _shader;
internal override Wrapper Wrapper => _shader;
+ ///
+ /// The source used to create this shader
+ ///
public string Source { get; }
+
+ ///
+ /// The type of this shader
+ ///
public ShaderType Type { get; }
internal Shader(ShaderWrap shader, string source, ShaderType type, string name)
@@ -26,14 +36,24 @@ namespace Diamond.Shaders
#region Factory Methods
+ // Used to infer shader type based on file extension
private static readonly Dictionary Extensions = new Dictionary
{
[".vs"] = ShaderType.VertexShader,
[".vert"] = ShaderType.VertexShader,
[".fs"] = ShaderType.FragmentShader,
[".frag"] = ShaderType.FragmentShader,
+ [".gs"] = ShaderType.GeometryShader,
+ [".geom"] = ShaderType.GeometryShader,
};
-
+
+ ///
+ /// Create and compile a shader from glsl source code
+ ///
+ /// The glsl source
+ /// The type of shader to create
+ /// The name of this GLObject
+ /// The compiled Shader, or null if initialization failed
public static Shader FromSource(string source, ShaderType type, string name = "Shader")
{
var wrapper = new ShaderWrap(type);
@@ -57,7 +77,14 @@ namespace Diamond.Shaders
return service;
}
- public static Shader FromFile(string path, ShaderType type)
+ ///
+ /// Create and compile a shader from a glsl source file
+ ///
+ /// The path to the glsl source file
+ /// The type of the shader to create
+ /// The name of this GLObject
+ ///
+ public static Shader FromFile(string path, ShaderType type, string name = null)
{
if (!File.Exists(path))
{
@@ -65,11 +92,21 @@ namespace Diamond.Shaders
return null;
}
- var name = Path.GetFileNameWithoutExtension(path);
+ if (name == null)
+ name = Path.GetFileNameWithoutExtension(path);
+
return FromSource(File.ReadAllText(path), type, name);
}
- public static Shader FromFile(string path)
+ ///
+ /// Create and compile a shader from a glsl source file. Shader type is inferred from file extension.
+ /// Extension must be .vs, .vert, .fs, .frag, .gs, or .geom. This can optionally be followed by .glsl or .txt,
+ /// but the shader type extension must be present.
+ ///
+ /// The path to the glsl source file
+ /// The name of this GLObject
+ /// The compiled shader, or null if initialization failed or shader type cannot be inferred
+ public static Shader FromFile(string path, string name = null)
{
if (!File.Exists(path))
{
@@ -78,12 +115,14 @@ namespace Diamond.Shaders
}
var ext = Path.GetExtension(path);
- var name = Path.GetFileNameWithoutExtension(path);
+ var fileName = Path.GetFileNameWithoutExtension(path);
+ // get sub-extension if real extension is not valid
if (ext != null)
if (!Extensions.ContainsKey(ext))
- ext = Path.GetExtension(name);
+ ext = Path.GetExtension(fileName);
+ // if no extension, no sub-extension, or invalid sub-extension
if (ext == null || !Extensions.ContainsKey(ext))
{
Logger.Warn("Could not infer shader type from glsl file name {0}", path);
@@ -91,8 +130,10 @@ namespace Diamond.Shaders
}
var type = Extensions[ext];
+ if (name == null)
+ name = fileName;
- return FromFile(path, type);
+ return FromFile(path, type, name);
}
#endregion
diff --git a/Diamond/Shaders/ShaderException.cs b/Diamond/Shaders/ShaderException.cs
deleted file mode 100644
index 361816e..0000000
--- a/Diamond/Shaders/ShaderException.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Runtime.Serialization;
-
-namespace Diamond.Shaders
-{
- ///
- /// Exception relating to Shader and Program operations.
- ///
- [Serializable]
- public class ShaderException : Exception
- {
- public ShaderException()
- {
- }
-
- public ShaderException(string message)
- : base(message)
- {
- }
-
- public ShaderException(string message, Exception inner)
- : base(message, inner)
- {
- }
-
- protected ShaderException(
- SerializationInfo info,
- StreamingContext context)
- : base(info, context)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/Diamond/Textures/Texture.cs b/Diamond/Textures/Texture.cs
index cbe28d3..a5c9eb7 100644
--- a/Diamond/Textures/Texture.cs
+++ b/Diamond/Textures/Texture.cs
@@ -1,5 +1,6 @@
using System.Drawing;
using System.Drawing.Imaging;
+using System.IO;
using Diamond.Wrappers;
using NLog;
using OpenTK.Graphics.OpenGL4;
@@ -7,6 +8,9 @@ using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat;
namespace Diamond.Textures
{
+ ///
+ /// Manages a OpenGL Texture object
+ ///
public class Texture : GLObject
{
private readonly TextureWrap _texture;
@@ -18,15 +22,26 @@ namespace Diamond.Textures
Name = name;
}
+ ///
+ /// This textures target; how it is used
+ ///
public TextureTarget Target => _texture.Target;
- public void Bind() => _texture.Bind();
+ ///
+ /// Bind this texture to a particular unit
+ ///
public void Bind(int unit) => _texture.Bind(unit);
public override string ToString() => Name == null ? $"{Target} ({Id})" : $"{Target} \'{Name}\' ({Id})";
#region Factory Methods
+ ///
+ /// Create a texture object and upload bitmap data to it
+ ///
+ /// The image to upload
+ /// The name of this GLObject
+ /// The initialized Texture, or null if initialsation failed
public static Texture FromBitmap(Bitmap bmp, string name = null)
{
var wrapper = new TextureWrap(TextureTarget.Texture2D);
@@ -35,6 +50,8 @@ namespace Diamond.Textures
Logger.Debug("Created Texture {0}", service);
wrapper.Bind();
+
+ // todo: expose texture parameters to enable setting different filters
wrapper.TexParameter(TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Nearest);
wrapper.TexParameter(TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest);
@@ -47,9 +64,18 @@ namespace Diamond.Textures
return service;
}
- public static Texture FromFile(string path)
+ ///
+ /// Create a texture and upload the contents of an image file to it
+ ///
+ /// The path to the file
+ /// The name of this GLObject
+ /// The initialized Texture, or null if instantiation failed
+ public static Texture FromFile(string path, string name = null)
{
- return FromBitmap(new Bitmap(path));
+ if (name == null)
+ name = Path.GetFileNameWithoutExtension(path);
+
+ return FromBitmap(new Bitmap(path), name);
}
#endregion
diff --git a/Diamond/Level/TileData.cs b/Diamond/Util/TileData.cs
similarity index 94%
rename from Diamond/Level/TileData.cs
rename to Diamond/Util/TileData.cs
index d857b7b..2af7f99 100644
--- a/Diamond/Level/TileData.cs
+++ b/Diamond/Util/TileData.cs
@@ -1,7 +1,7 @@
using Diamond.Buffers;
using OpenTK;
-namespace Diamond.Level
+namespace Diamond.Util
{
[VertexData(Divisor = 1)]
public struct TileData
diff --git a/hexworld/HexRender.cs b/hexworld/HexRender.cs
index 4ac30d4..889c509 100644
--- a/hexworld/HexRender.cs
+++ b/hexworld/HexRender.cs
@@ -2,7 +2,6 @@
using System.IO;
using System.Linq;
using Diamond.Buffers;
-using Diamond.Level;
using Diamond.Shaders;
using Diamond.Textures;
using Diamond.Util;