Started migrating to Factory/Wrapper pattern - Shader complete
This commit is contained in:
@@ -5,7 +5,7 @@ using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace Diamond.Buffers
|
||||
{
|
||||
public class GLBuffer<T> : GLObject where T : struct
|
||||
public class GLBuffer<T> : GLWrapper where T : struct
|
||||
{
|
||||
public readonly BufferTarget Target;
|
||||
public readonly BufferUsageHint Usage;
|
||||
|
||||
@@ -52,9 +52,10 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Buffers\GLBuffer.cs" />
|
||||
<Compile Include="GLObject.cs" />
|
||||
<Compile Include="Util\SubArray.cs" />
|
||||
<Compile Include="Buffers\VertexDataAttribute.cs" />
|
||||
<Compile Include="GLObject.cs" />
|
||||
<Compile Include="GLWrapper.cs" />
|
||||
<Compile Include="Level\Level.cs" />
|
||||
<Compile Include="Level\TileData.cs" />
|
||||
<Compile Include="Level\TileGroup.cs" />
|
||||
|
||||
@@ -1,66 +1,47 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using OpenTK.Graphics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace Diamond
|
||||
{
|
||||
/// <summary>
|
||||
/// Parent class for all gl Object wrappers.
|
||||
/// </summary>
|
||||
public abstract class GLObject : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Logger for this class
|
||||
/// </summary>
|
||||
protected Logger Log { get; }
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// The name of this object
|
||||
/// </summary>
|
||||
public uint Id { get; protected set; }
|
||||
public abstract int Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Force all <code>GLObject</code>s to define their name.
|
||||
/// </summary>
|
||||
/// <param name="id">The name of this object</param>
|
||||
protected GLObject(uint id)
|
||||
protected abstract GLWrapper Wrapper { get; }
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
Id = id;
|
||||
|
||||
Log = LogManager.GetLogger(GetType().FullName);
|
||||
Log.Trace("Created {0}", this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to free the name of this object. Usually corresponds to <code>glDelete*</code>.
|
||||
/// </summary>
|
||||
protected abstract void Delete();
|
||||
|
||||
/// <summary>
|
||||
/// Free the name of this object
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (GraphicsContext.CurrentContext == null)
|
||||
{
|
||||
Log.Warn("No current context, assuming {0} is disposed.", this);
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
if (GraphicsContext.CurrentContext == null)
|
||||
Logger.Warn("No graphics context, cannot dispose GLObject: {0}", Wrapper);
|
||||
else
|
||||
Wrapper.Dispose();
|
||||
}
|
||||
|
||||
Delete();
|
||||
Log.Trace("Disposed {0}", this);
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~GLObject()
|
||||
{
|
||||
Dispose();
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
public override string ToString() => $"{GetType().Name} {Id}";
|
||||
|
||||
public static explicit operator uint(GLObject o) => o.Id;
|
||||
public static explicit operator int(GLObject o) => (int) o.Id;
|
||||
}
|
||||
}
|
||||
41
Diamond/GLWrapper.cs
Normal file
41
Diamond/GLWrapper.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using OpenTK.Graphics;
|
||||
using NLog;
|
||||
|
||||
namespace Diamond
|
||||
{
|
||||
internal abstract class GLWrapper : IDisposable
|
||||
{
|
||||
protected static Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public int Id { get; protected set; }
|
||||
|
||||
public override string ToString() => $"{GetType().Name} {Id}";
|
||||
|
||||
#region IDisposable
|
||||
|
||||
public abstract void GLDelete();
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
return;
|
||||
|
||||
GLDelete();
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static explicit operator int(GLWrapper o) => o.Id;
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using System.Linq;
|
||||
using Diamond.Buffers;
|
||||
using Diamond.Shaders;
|
||||
using Diamond.Textures;
|
||||
using Diamond.Util;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using OpenTK;
|
||||
@@ -70,7 +71,7 @@ namespace Diamond.Level
|
||||
var texturePaths = levelData["textures"]
|
||||
.Select(path => (string) path)
|
||||
.ToArray();
|
||||
var textures = texturePaths.Select(path => Texture.FromBitmap(new Bitmap(Path.Combine(dir, (string)path)))).ToArray();
|
||||
var textures = texturePaths.Select(path => Texture.FromBitmap(new Bitmap(Path.Combine(dir, path)))).ToArray();
|
||||
var textureMap = texturePaths.Select((path, i) => new {path = path, i = i})
|
||||
.ToDictionary(v => v.path, v => v.i);
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLogger.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
|
||||
xsi:schemaLocation="http://www.nlog-project.org/schemas/NLogger.xsd NLogger.xsd"
|
||||
autoReload="true"
|
||||
throwExceptions="false"
|
||||
internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">
|
||||
internalLoggerLevel="Off" internalLoggerFile="c:\temp\nlog-internal.log">
|
||||
|
||||
<variable name="Layout" value="[${level}] ${logger}: ${message}" />
|
||||
|
||||
<targets>
|
||||
<target xsi:type="File" name="file" fileName="${basedir}/Log/${shortdate}.log"
|
||||
<target xsi:type="File" name="file" fileName="${basedir}/Logger/${shortdate}.log"
|
||||
layout="${Layout}"/>
|
||||
<target xsi:type="Debugger" name="debug" layout="${Layout}"/>
|
||||
</targets>
|
||||
|
||||
380
Diamond/NLog.xsd
380
Diamond/NLog.xsd
File diff suppressed because it is too large
Load Diff
@@ -5,18 +5,18 @@ using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace Diamond.Shaders
|
||||
{
|
||||
public class Program : GLObject
|
||||
public class Program : GLWrapper
|
||||
{
|
||||
public static Program Current { get; private set; }
|
||||
|
||||
private readonly Dictionary<string, int> _uniforms = new Dictionary<string, int>();
|
||||
private readonly Dictionary<string, int> _attributes = new Dictionary<string, int>();
|
||||
|
||||
public string InfoLog => GL.GetProgramInfoLog((int) Id).Trim();
|
||||
public string InfoLog => GL.GetProgramInfoLog(Id).Trim();
|
||||
|
||||
public Program()
|
||||
: base((uint) GL.CreateProgram())
|
||||
{
|
||||
Id = GL.CreateProgram();
|
||||
}
|
||||
|
||||
protected override void Delete()
|
||||
@@ -47,18 +47,18 @@ namespace Diamond.Shaders
|
||||
|
||||
if (!Linked)
|
||||
{
|
||||
Log.Warn("Failed to link Program {0}", Id);
|
||||
Log.Debug("Program {0} InfoLog\n{1}", Id, InfoLog);
|
||||
Logger.Warn("Failed to link Program {0}", Id);
|
||||
Logger.Debug("Program {0} InfoLog\n{1}", Id, InfoLog);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log.Info("Successfully linked Program {0}", Id);
|
||||
Logger.Info("Successfully linked Program {0}", Id);
|
||||
|
||||
GL.GetProgram(Id, GetProgramParameterName.ActiveUniforms, out int uniformcount);
|
||||
for (var i = 0; i < uniformcount; i++)
|
||||
{
|
||||
var sb = new StringBuilder(256);
|
||||
GL.GetActiveUniformName((int) Id, i, sb.Capacity, out int length, sb);
|
||||
GL.GetActiveUniformName(Id, i, sb.Capacity, out int length, sb);
|
||||
_uniforms[sb.ToString()] = i;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace Diamond.Shaders
|
||||
for (var i = 0; i < attributecount; i++)
|
||||
{
|
||||
var sb = new StringBuilder(256);
|
||||
GL.GetActiveAttrib((int) Id, i, sb.Capacity, out int length, out int size,
|
||||
GL.GetActiveAttrib(Id, i, sb.Capacity, out int length, out int size,
|
||||
out ActiveAttribType type, sb);
|
||||
_attributes[sb.ToString()] = i;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ namespace Diamond.Shaders
|
||||
{
|
||||
if (TryGetUniform(name, out int id)) return id;
|
||||
|
||||
Log.Warn("Attempted to access uniform {0} on Program {1}", name, Id);
|
||||
Logger.Warn("Attempted to access uniform {0} on Program {1}", name, Id);
|
||||
throw new ShaderException($"Shader Program {Id} does not contain uniform '{name}'");
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace Diamond.Shaders
|
||||
{
|
||||
if (TryGetAttribute(name, out int id)) return id;
|
||||
|
||||
Log.Warn("Attempted to access attribute {0} on Program {1}", name, Id);
|
||||
Logger.Warn("Attempted to access attribute {0} on Program {1}", name, Id);
|
||||
throw new ShaderException($"Shader Program {Id} does not contain id '{name}'");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using NLog;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
|
||||
namespace Diamond.Shaders
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps methods for GL Shader objects.
|
||||
/// </summary>
|
||||
public class Shader : GLObject
|
||||
internal sealed class ShaderWrapper : GLWrapper
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of this shader.
|
||||
/// </summary>
|
||||
public readonly ShaderType ShaderType;
|
||||
|
||||
/// <summary>
|
||||
/// The source file name, if it was loaded from a file.
|
||||
/// </summary>
|
||||
public string SourceFile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets and sets the shader source with <code>glShaderSource</code> and <code>glGetShaderSource</code>.
|
||||
/// </summary>
|
||||
public string Source
|
||||
{
|
||||
get
|
||||
@@ -30,103 +19,123 @@ namespace Diamond.Shaders
|
||||
GL.GetShaderSource(Id, sb.Capacity, out int length, sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
set { GL.ShaderSource((int) Id, value); }
|
||||
set { GL.ShaderSource(Id, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves this shader's compilation log with <code>glGetShaderInfoLog</code>.
|
||||
/// </summary>
|
||||
public string InfoLog => GL.GetShaderInfoLog((int) Id).Trim();
|
||||
|
||||
/// <summary>
|
||||
/// Checks the compilation status of this shader with <code>glGetShader</code>.
|
||||
/// </summary>
|
||||
public bool Compiled
|
||||
{
|
||||
get
|
||||
{
|
||||
GL.GetShader(Id, ShaderParameter.CompileStatus, out int success);
|
||||
return success != 0;
|
||||
GL.GetShader(Id, ShaderParameter.CompileStatus, out int res);
|
||||
return res != 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a wrapper for a gl Shader object.
|
||||
/// </summary>
|
||||
/// <param name="shaderType">The type of the shader to create</param>
|
||||
public Shader(ShaderType shaderType)
|
||||
: base((uint) GL.CreateShader(shaderType))
|
||||
public string InfoLog => GL.GetShaderInfoLog(Id).Trim();
|
||||
|
||||
internal ShaderWrapper(ShaderType shaderType)
|
||||
{
|
||||
Id = GL.CreateShader(shaderType);
|
||||
ShaderType = shaderType;
|
||||
}
|
||||
|
||||
protected override void Delete() => GL.DeleteShader(Id);
|
||||
public override void GLDelete()
|
||||
{
|
||||
GL.DeleteShader(Id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compile the shader.
|
||||
/// </summary>
|
||||
/// <returns>Compilation success</returns>
|
||||
public bool Compile()
|
||||
public void Compile()
|
||||
{
|
||||
GL.CompileShader(Id);
|
||||
|
||||
var compiled = Compiled;
|
||||
if (!compiled)
|
||||
{
|
||||
Log.Warn("Failed to compile {0} {1} {2}", ShaderType, Id, SourceFile);
|
||||
Log.Debug("{0} {1} InfoLog\n{2}", ShaderType, Id, InfoLog);
|
||||
}
|
||||
|
||||
return compiled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and compiles a shader from a source file. Infers shader type from file extension
|
||||
/// Extension must be of the form .[type] or .[type].glsl
|
||||
/// Valid types are vs, vert, fs, and frag.
|
||||
/// </summary>
|
||||
/// <param name="path">Source file location</param>
|
||||
/// <returns>The compiled shader</returns>
|
||||
public static Shader FromFile(string path)
|
||||
{
|
||||
var ex = Path.GetExtension(path);
|
||||
|
||||
if (ex == ".glsl")
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
if (Path.HasExtension(name))
|
||||
ex = Path.GetExtension(name);
|
||||
}
|
||||
|
||||
switch (ex)
|
||||
{
|
||||
case ".vs":
|
||||
case ".vert":
|
||||
return FromFile(path, ShaderType.VertexShader);
|
||||
case ".fs":
|
||||
case ".frag":
|
||||
return FromFile(path, ShaderType.FragmentShader);
|
||||
default:
|
||||
throw new ShaderException("Can't infer shader type from extension");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and compiles a shader from a source file.
|
||||
/// </summary>
|
||||
/// <param name="path">Source file location</param>
|
||||
/// <param name="type">Type of the shader</param>
|
||||
/// <returns>The compiled shader</returns>
|
||||
public static Shader FromFile(string path, ShaderType type)
|
||||
{
|
||||
var s = new Shader(type)
|
||||
{
|
||||
Source = File.ReadAllText(path),
|
||||
SourceFile = path
|
||||
};
|
||||
|
||||
s.Compile();
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public class Shader : GLObject
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly ShaderWrapper _shader;
|
||||
|
||||
public override int Id => _shader.Id;
|
||||
protected override GLWrapper Wrapper => _shader;
|
||||
|
||||
public string Name { get; }
|
||||
public string Source { get; }
|
||||
|
||||
private Shader(ShaderWrapper shader, string source, string name)
|
||||
{
|
||||
_shader = shader;
|
||||
Name = name;
|
||||
Source = source;
|
||||
}
|
||||
|
||||
#region Factory Methods
|
||||
|
||||
public static Shader FromSource(string source, ShaderType type, string name = "Shader")
|
||||
{
|
||||
var wrapper = new ShaderWrapper(type);
|
||||
Logger.Debug("Created {0} \'{1}\' {2}", type, name, wrapper.Id);
|
||||
|
||||
wrapper.Source = source;
|
||||
wrapper.Compile();
|
||||
|
||||
if (!wrapper.Compiled)
|
||||
{
|
||||
Logger.Warn("Failed to compile {0} \'{1}\' {2}", type, name, wrapper.Id);
|
||||
Logger.Debug("InfoLog for {0} \'{1}\' {2}", type, name, wrapper.Id);
|
||||
wrapper.Dispose();
|
||||
return null;
|
||||
}
|
||||
|
||||
Logger.Debug("Successfully compiled {0} \'{1}\' {2}", type, name, wrapper.Id);
|
||||
return new Shader(wrapper, source, name);
|
||||
}
|
||||
|
||||
public static Shader FromFile(string path, ShaderType type)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logger.Warn("Could not find glsl file {0}", path);
|
||||
return null;
|
||||
}
|
||||
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
return FromSource(File.ReadAllText(path), type, name);
|
||||
}
|
||||
|
||||
public static Shader FromFile(string path)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logger.Warn("Could not find glsl file {0}", path);
|
||||
return null;
|
||||
}
|
||||
|
||||
var ext = Path.GetExtension(path);
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
|
||||
var extensions = new Dictionary<string, ShaderType>
|
||||
{
|
||||
[".vs"] = ShaderType.VertexShader,
|
||||
[".vert"] = ShaderType.VertexShader,
|
||||
[".fs"] = ShaderType.VertexShader,
|
||||
[".frag"] = ShaderType.VertexShader,
|
||||
};
|
||||
|
||||
if (ext != null)
|
||||
if (!extensions.ContainsKey(ext))
|
||||
ext = Path.GetExtension(name);
|
||||
|
||||
if (ext == null || !extensions.ContainsKey(ext))
|
||||
{
|
||||
Logger.Warn("Could not infer shader type from glsl file name {0}", path);
|
||||
return null;
|
||||
}
|
||||
|
||||
var type = extensions[ext];
|
||||
return FromFile(path, type);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Diamond.Textures
|
||||
/// <summary>
|
||||
/// Wrapper class for gl Textures.
|
||||
/// </summary>
|
||||
public class Texture : GLObject
|
||||
public class Texture : GLWrapper
|
||||
{
|
||||
public TextureTarget Target;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user