Holidays 12.10. -> 25.10.2020

~ Moved code around in files.

SM.Base:
+ PostProcessing-system
+ OnInitialization() for Scenes.
+ Shader-Extensions
+ Added option to not react while unfocused to the window.
+ Added Screenshots to the window.
+ Connected the log system to the SM.OGL-action system.

~ Replaced IShader with abstract MaterialShader.
~ When a log compression folder doesn't exist, it will create one.

SM.OGL:
+ Added support for UniformArrays
+ Added ShaderPreProcessing
+ Added Shader Extensions.
+ Added Debug actions.
+ SM.OGL settings

~ Framebuffer Size is automaticly changed, when the window and scale is set.

SM2D:
+ Added easy shader drawing.
This commit is contained in:
Michel Fedde 2020-10-24 15:10:36 +02:00
parent 2c00dbd31a
commit 03b3942732
102 changed files with 2683 additions and 1398 deletions

View file

@ -1,11 +1,20 @@
using System;
#region usings
using System;
using OpenTK.Graphics.OpenGL4;
using SM.OGL.Texture;
#endregion
namespace SM.OGL.Framebuffer
{
public class ColorAttachment : TextureBase
{
public ColorAttachment(int attachmentId)
{
AttachmentID = attachmentId;
}
public int AttachmentID { get; }
public FramebufferAttachment FramebufferAttachment => FramebufferAttachment.ColorAttachment0 + AttachmentID;
@ -13,23 +22,22 @@ namespace SM.OGL.Framebuffer
public ReadBufferMode ReadBufferMode => ReadBufferMode.ColorAttachment0 + AttachmentID;
public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID;
public ColorAttachment(int attachmentId)
{
AttachmentID = attachmentId;
}
public void Generate(Framebuffer f)
{
_id = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _id);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8,
(int) f.Size.X, (int) f.Size.Y,
(int) f.Size.X, (int) f.Size.Y,
0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
(int) TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
(int) TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS,
(int) TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT,
(int) TextureParameterName.ClampToEdge);
}
}
}

View file

@ -1,15 +1,18 @@
using System;
#region usings
using System;
using System.Collections.Generic;
using OpenTK;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Platform;
#endregion
namespace SM.OGL.Framebuffer
{
// TODO: Write summeries for framebuffer-system.
public class Framebuffer : GLObject
{
public static readonly Framebuffer Screen = new Framebuffer()
public static readonly Framebuffer Screen = new Framebuffer
{
_id = 0,
_canBeCompiled = false
@ -17,34 +20,45 @@ namespace SM.OGL.Framebuffer
private bool _canBeCompiled = true;
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer;
public Vector2 Size { get; private set; }
public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } = new Dictionary<string, ColorAttachment>();
private INativeWindow _window;
private float _windowScale;
public Framebuffer()
{ }
{
}
public Framebuffer(INativeWindow window, float scale = 1) : this(new Vector2(window.Width * scale, window.Height * scale))
{ }
public Framebuffer(INativeWindow window, float scale = 1) : this(new Vector2(window.Width * scale,
window.Height * scale))
{
_window = window;
_windowScale = scale;
}
public Framebuffer(Vector2 size)
{
Size = size;
}
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer;
public Vector2 Size { get; private set; }
public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } =
new Dictionary<string, ColorAttachment>();
public override void Compile()
{
if (!_canBeCompiled) return;
if (_window != null) Size = new Vector2(_window.Width * _windowScale, _window.Height * _windowScale);
base.Compile();
_id = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, _id);
DrawBuffersEnum[] enums = new DrawBuffersEnum[ColorAttachments.Count];
int c = 0;
foreach (KeyValuePair<string, ColorAttachment> pair in ColorAttachments)
var enums = new DrawBuffersEnum[ColorAttachments.Count];
var c = 0;
foreach (var pair in ColorAttachments)
{
pair.Value.Generate(this);
@ -53,11 +67,12 @@ namespace SM.OGL.Framebuffer
GL.DrawBuffers(enums.Length, enums);
foreach (var pair in ColorAttachments)
GL.FramebufferTexture(FramebufferTarget.Framebuffer, pair.Value.FramebufferAttachment, pair.Value.ID, 0);
GL.FramebufferTexture(FramebufferTarget.Framebuffer, pair.Value.FramebufferAttachment, pair.Value.ID,
0);
FramebufferErrorCode err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
var err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
if (err != FramebufferErrorCode.FramebufferComplete)
throw new Exception("Failed loading framebuffer.\nProblem: "+err);
throw new Exception("Failed loading framebuffer.\nProblem: " + err);
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
GL.BindTexture(TextureTarget.Texture2D, 0);
@ -66,23 +81,36 @@ namespace SM.OGL.Framebuffer
public override void Dispose()
{
base.Dispose();
foreach (ColorAttachment attachment in ColorAttachments.Values) attachment.Dispose();
foreach (var attachment in ColorAttachments.Values) attachment.Dispose();
GL.DeleteFramebuffer(this);
}
public void Append(string key, int pos) => Append(key, new ColorAttachment(pos));
public void Append(string key, ColorAttachment value)
{
ColorAttachments.Add(key, value);
}
public void Activate() => Activate(FramebufferTarget.Framebuffer, ClearBufferMask.None);
public void Activate(FramebufferTarget target) => Activate(target, ClearBufferMask.None);
public void Activate(ClearBufferMask clearMask) => Activate(FramebufferTarget.Framebuffer, clearMask);
public void Activate()
{
Activate(FramebufferTarget.Framebuffer, ClearBufferMask.None);
}
public void Activate(FramebufferTarget target)
{
Activate(target, ClearBufferMask.None);
}
public void Activate(ClearBufferMask clearMask)
{
Activate(FramebufferTarget.Framebuffer, clearMask);
}
public void Activate(FramebufferTarget target, ClearBufferMask clear)
{
GL.Clear(clear);
GL.BindFramebuffer(target, this);
GL.Clear(clear);
}
}
}

View file

@ -0,0 +1,47 @@
#region usings
using System;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL
{
public class GLCustomActions
{
/// <summary>
/// A action that is performed, when a OpenGL-error occurs.
/// </summary>
public static Action<DebugSource, DebugType, DebugSeverity, string> AtKHRDebug = DefaultDebugAction;
/// <summary>
/// A action, that is performed, when a GLError occurred.
/// <para>Doesn't account for "KHR_debugging"</para>
/// </summary>
public static Action<string> AtError;
/// <summary>
/// A action, that is performed, when a warning want to be shown.
/// </summary>
public static Action<string> AtWarning;
/// <summary>
/// A action, that is performed, when a information needs to be shown.
/// </summary>
public static Action<string> AtInfo;
/// <summary>
/// Default action for 'AtKHRDebug'.
/// </summary>
/// <param name="source"></param>
/// <param name="type"></param>
/// <param name="severity"></param>
/// <param name="msg"></param>
private static void DefaultDebugAction(DebugSource source, DebugType type, DebugSeverity severity, string msg)
{
Console.WriteLine($"{severity}, {type}, {source} -> {msg}");
if (type == DebugType.DebugTypeError) throw new Exception(msg);
}
}
}

View file

@ -1,36 +1,33 @@
using System;
#region usings
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Runtime.InteropServices;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Platform.Egl;
using ErrorCode = OpenTK.Graphics.OpenGL4.ErrorCode;
#endregion
namespace SM.OGL
{
/// <summary>
/// Contains everything that is needed to debug OpenGL
/// Contains everything that is needed to debug OpenGL
/// </summary>
public static class GLDebugging
{
private static DebugProc _debugProc = DebugCallback;
private static GCHandle _debugGcHandle;
/// <summary>
/// A action that is performed, when a OpenGL-error occurs.
/// </summary>
public static Action<DebugSource, DebugType, DebugSeverity, string> DebugAction = DefaultDebugAction;
[DebuggerStepThrough]
private static void DebugCallback(DebugSource source, DebugType type, int id, DebugSeverity severity,
int length, IntPtr message, IntPtr userparam)
{
string msg = Marshal.PtrToStringAnsi(message, length);
DebugAction?.Invoke(source, type, severity, msg);
var msg = Marshal.PtrToStringAnsi(message, length);
GLCustomActions.AtKHRDebug?.Invoke(source, type, severity, msg);
}
/// <summary>
/// Enables the debugging.
/// Enables the debugging.
/// </summary>
public static void EnableDebugging()
{
@ -47,40 +44,33 @@ namespace SM.OGL
Console.WriteLine("Enableing proper GLDebugging failed. \n" +
"Often it fails, because your hardware doesn't provide proper OpenGL 4 \n" +
" or KHR_debug extension support.");
}
}
/// <summary>
/// Default action for 'DebugAction'.
/// </summary>
/// <param name="source"></param>
/// <param name="type"></param>
/// <param name="severity"></param>
/// <param name="msg"></param>
public static void DefaultDebugAction(DebugSource source, DebugType type, DebugSeverity severity, string msg)
{
Console.WriteLine($"{severity}, {type}, {source} -> {msg}");
if (type == DebugType.DebugTypeError) throw new Exception(msg);
}
/// <summary>
/// A action, that is performed, when <see cref="GLDebugging.CheckGLErrors"/> find an error.
/// </summary>
public static Action<ErrorCode> GlErrorAction;
/// <summary>
/// Checks for OpenGL errors.
/// Checks for OpenGL errors.
/// </summary>
public static bool CheckGLErrors()
{
bool hasError = false;
var hasError = false;
ErrorCode c;
while ((c = GL.GetError()) != ErrorCode.NoError)
{
hasError = true;
GlErrorAction?.Invoke(c);
GLCustomActions.AtError?.Invoke("A GLError occurred: " + c);
}
return hasError;
}
public static bool CheckGLErrors(string formating)
{
var hasError = false;
ErrorCode c;
while ((c = GL.GetError()) != ErrorCode.NoError)
{
hasError = true;
GLCustomActions.AtError?.Invoke(formating.Replace("%code%", c.ToString()));
}
return hasError;

View file

@ -1,30 +1,35 @@
using System.Diagnostics;
#region usings
using System.Diagnostics;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL
{
/// <summary>
/// Specifies default object behaviour.
/// Specifies default object behaviour.
/// </summary>
public abstract class GLObject
{
/// <summary>
/// Contains the OpenGL ID
/// Contains the OpenGL ID
/// </summary>
protected int _id = -1;
/// <summary>
/// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1.
/// If true, the system will call "Compile()", when "ID" is tried to get, but the id is still -1.
/// </summary>
protected virtual bool AutoCompile { get; } = false;
/// <summary>
/// Checks if the object was compiled.
/// Checks if the object was compiled.
/// </summary>
public bool WasCompiled => _id > 0;
/// <summary>
/// Returns the id for this object.
/// <para>It will auto compile, if needed and allowed.</para>
/// Returns the id for this object.
/// <para>It will auto compile, if needed and allowed.</para>
/// </summary>
public virtual int ID
{
@ -36,7 +41,7 @@ namespace SM.OGL
}
/// <summary>
/// Identifies the object.
/// Identifies the object.
/// </summary>
public abstract ObjectLabelIdentifier TypeIdentifier { get; }
@ -47,21 +52,21 @@ namespace SM.OGL
}
/// <summary>
/// The action, that is called, when "ID" tries to compile something.
/// The action, that is called, when "ID" tries to compile something.
/// </summary>
public virtual void Compile()
{
}
/// <summary>
/// Is triggered, when something want to dispose this object.
/// Is triggered, when something want to dispose this object.
/// </summary>
public virtual void Dispose() {}
public virtual void Dispose()
{
}
/// <summary>
/// Re-compiles the object.
/// Re-compiles the object.
/// </summary>
public void Recompile()
{
@ -72,7 +77,7 @@ namespace SM.OGL
}
/// <summary>
/// Names the object for debugging.
/// Names the object for debugging.
/// </summary>
/// <param name="name"></param>
public void Name(string name)
@ -81,9 +86,12 @@ namespace SM.OGL
}
/// <summary>
/// Returns the ID for the object.
/// Returns the ID for the object.
/// </summary>
/// <param name="glo"></param>
public static implicit operator int(GLObject glo) => glo.ID;
public static implicit operator int(GLObject glo)
{
return glo.ID;
}
}
}

View file

@ -0,0 +1,15 @@
namespace SM.OGL
{
public class GLSettings
{
public static bool InfoEveryUniform = false;
/// <summary>
/// Get/Sets the forced version for OpenGL.
/// <para>Needs to be set before init a window.</para>
/// </summary>
public static Version ForcedVersion { get; set; } = new Version();
public static bool ShaderPreProcessing { get; set; } = false;
}
}

View file

@ -1,43 +1,44 @@
using System.Linq;
#region usings
using System.Linq;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL
{
/// <summary>
/// Contains data about the current OpenGL system.
/// Contains data and settings about the current OpenGL system.
/// </summary>
public class GLSystem
{
private static bool _init = false;
private static bool _init;
/// <summary>
/// Contains the device version of OpenGL.
/// Contains the device version of OpenGL.
/// </summary>
public static Version DeviceVersion { get; private set; }
/// <summary>
/// Get/Sets the forced version for OpenGL.
/// <para>Needs to be set before init a window.</para>
/// </summary>
public static Version ForcedVersion { get; set; } = new Version();
/// <summary>
/// Contains the shader version for GLSL.
/// Contains the shader version for GLSL.
/// </summary>
public static Version ShadingVersion { get; private set; }
/// <summary>
/// Contains the extensions for OpenGL.
/// Contains the extensions for OpenGL.
/// </summary>
public static string[] Extensions { get; private set; }
/// <summary>
/// Checks if proper Debugging is for this system available.
/// <para>Determent, if the system has the "KHR_debug"-extension. </para>
/// Checks if proper Debugging is for this system available.
/// <para>Determent, if the system has the "KHR_debug"-extension. </para>
/// </summary>
public static bool Debugging { get; private set; }
/// <summary>
/// Initialize the system data.
/// <para>Does nothing after the data was already collected.</para>
/// Initialize the system data.
/// <para>Does nothing after the data was already collected.</para>
/// </summary>
public static void INIT_SYSTEM()
{

View file

@ -1,39 +1,36 @@
using System;
using System.Runtime.CompilerServices;
#region usings
using System;
using OpenTK;
#endregion
namespace SM.OGL.Mesh
{
/// <summary>
/// Contains information about bounding boxes of meshes
/// Contains information about bounding boxes of meshes
/// </summary>
public class BoundingBox
{
/// <summary>
/// The minimum corner.
/// </summary>
public Vector3 Min = Vector3.Zero;
/// <summary>
/// The maximum corner.
/// The maximum corner.
/// </summary>
public Vector3 Max = Vector3.Zero;
/// <summary>
/// Returns specific configurations of corners
/// The minimum corner.
/// </summary>
/// <param name="x">If true, it takes the X-value of maximum, otherwise the minimum.</param>
/// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param>
/// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 this[bool x, bool y, bool z] => new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z);
public Vector3 Min = Vector3.Zero;
/// <summary>
/// Empty constructor
/// Empty constructor
/// </summary>
public BoundingBox() {}
public BoundingBox()
{
}
/// <summary>
/// Creates the bounding box with predefined min and max values
/// Creates the bounding box with predefined min and max values
/// </summary>
/// <param name="min"></param>
/// <param name="max"></param>
@ -44,12 +41,22 @@ namespace SM.OGL.Mesh
}
/// <summary>
/// Updates the bounding box.
/// Returns specific configurations of corners
/// </summary>
/// <param name="x">If true, it takes the X-value of maximum, otherwise the minimum.</param>
/// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param>
/// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param>
/// <returns></returns>
public Vector3 this[bool x, bool y, bool z] =>
new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z);
/// <summary>
/// Updates the bounding box.
/// </summary>
/// <param name="vector"></param>
public void Update(Vector2 vector)
{
for (int i = 0; i < 2; i++)
for (var i = 0; i < 2; i++)
{
Min[i] = Math.Min(Min[i], vector[i]);
Max[i] = Math.Max(Max[i], vector[i]);
@ -57,12 +64,12 @@ namespace SM.OGL.Mesh
}
/// <summary>
/// Updates the bounding box.
/// Updates the bounding box.
/// </summary>
/// <param name="vector"></param>
public void Update(Vector3 vector)
{
for (int i = 0; i < 3; i++)
for (var i = 0; i < 3; i++)
{
Min[i] = Math.Min(Min[i], vector[i]);
Max[i] = Math.Max(Min[i], vector[i]);

View file

@ -1,15 +1,31 @@
using System;
#region usings
using System;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using Buffer = OpenTK.Graphics.OpenGL4.Buffer;
#endregion
namespace SM.OGL.Mesh
{
/// <summary>
/// Contains information for meshes
/// Contains information for meshes
/// </summary>
public abstract class GenericMesh : GLObject
{
/// <summary>
/// Generates the AttribDataIndex
/// </summary>
protected GenericMesh()
{
AttribDataIndex = new Dictionary<int, VBO>
{
{0, Vertex},
{1, UVs},
{2, Normals}
};
}
/// <inheritdoc />
protected override bool AutoCompile { get; } = true;
@ -17,61 +33,50 @@ namespace SM.OGL.Mesh
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.VertexArray;
/// <summary>
/// The primitive type, that determinants how the mesh is drawn.
/// <para>Default: Triangles</para>
/// The primitive type, that determinants how the mesh is drawn.
/// <para>Default: Triangles</para>
/// </summary>
public virtual PrimitiveType PrimitiveType { get; } = PrimitiveType.Triangles;
/// <summary>
/// Contains the vertices for the mesh.
/// Contains the vertices for the mesh.
/// </summary>
public virtual VBO Vertex { get; }
/// <summary>
/// Contains the texture coords for the mesh.
/// Contains the texture coords for the mesh.
/// </summary>
public virtual VBO UVs { get; }
/// <summary>
/// Contains the normals for the mesh.
/// Contains the normals for the mesh.
/// </summary>
public virtual VBO Normals { get; }
/// <summary>
/// Represents the bounding box.
/// Represents the bounding box.
/// </summary>
public virtual BoundingBox BoundingBox { get; } = new BoundingBox();
/// <summary>
/// Connects the different buffer objects with ids.
/// Connects the different buffer objects with ids.
/// </summary>
public Dictionary<int, VBO> AttribDataIndex { get; }
/// <summary>
/// Stores indices for a more performance friendly method to draw objects.
/// Stores indices for a more performance friendly method to draw objects.
/// </summary>
public virtual int[] Indices { get; set; }
/// <summary>
/// Generates the AttribDataIndex
/// </summary>
protected GenericMesh()
{
AttribDataIndex = new Dictionary<int, VBO>()
{
{0, Vertex},
{1, UVs},
{2, Normals},
};
}
/// <inheritdoc />
public override void Compile()
{
_id = GL.GenVertexArray();
GL.BindVertexArray(_id);
if (AttribDataIndex == null) throw new Exception("[Critical] The model requires a attribute data index.");
foreach (KeyValuePair<int, VBO> kvp in AttribDataIndex) kvp.Value?.BindBuffer(kvp.Key);
foreach (var kvp in AttribDataIndex) kvp.Value?.BindBuffer(kvp.Key);
GL.BindVertexArray(0);
}

View file

@ -1,51 +1,78 @@
using System;
#region usings
using System.Collections.Generic;
using System.Linq;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL.Mesh
{
/// <summary>
/// Represents a Vertex Buffer Object used for meshes.
/// Represents a Vertex Buffer Object used for meshes.
/// </summary>
public class VBO : List<float>
{
/// <summary>
/// Specifies the expected usage pattern of the data store.
/// Specifies the expected usage pattern of the data store.
/// </summary>
public BufferUsageHint BufferUsageHint;
/// <summary>
/// Specifies the data type of each component in the array.
/// </summary>
public VertexAttribPointerType PointerType;
/// <summary>
/// Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4.
/// </summary>
public int PointerSize;
/// <summary>
/// Normalise floats?
/// Normalise floats?
/// </summary>
public bool Normalised;
/// <summary>
/// Specifies the byte offset between consecutive generic vertex attributes.
/// </summary>
public int PointerStride;
/// <summary>
/// Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target.
/// Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of
/// the buffer currently bound to the GL_ARRAY_BUFFER target.
/// </summary>
public int PointerOffset;
/// <summary>
/// Generates a VBO for inserting mesh data.
/// Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4.
/// </summary>
/// <param name="bufferUsageHint">Specifies the expected usage pattern of the data store. <para>Default: StaticDraw</para></param>
/// <param name="pointerType">Specifies the data type of each component in the array. <para>Default: Float</para></param>
/// <param name="pointerSize">Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4. <para>Default: 3</para></param>
/// <param name="pointerStride">Specifies the byte offset between consecutive generic vertex attributes. <para>Default: 0</para></param>
/// <param name="pointerOffset">Specifies a offset of the first component of the first generic vertex attribute in the array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target. <para>Default: 0</para></param>
/// <param name="normalised">Normalise floats? <para>Default: false</para></param>
public int PointerSize;
/// <summary>
/// Specifies the byte offset between consecutive generic vertex attributes.
/// </summary>
public int PointerStride;
/// <summary>
/// Specifies the data type of each component in the array.
/// </summary>
public VertexAttribPointerType PointerType;
/// <summary>
/// Generates a VBO for inserting mesh data.
/// </summary>
/// <param name="bufferUsageHint">
/// Specifies the expected usage pattern of the data store.
/// <para>Default: StaticDraw</para>
/// </param>
/// <param name="pointerType">
/// Specifies the data type of each component in the array.
/// <para>Default: Float</para>
/// </param>
/// <param name="pointerSize">
/// Specifies the number of components per generic vertex attribute. Must be 1, 2, 3, 4.
/// <para>Default: 3</para>
/// </param>
/// <param name="pointerStride">
/// Specifies the byte offset between consecutive generic vertex attributes.
/// <para>Default: 0</para>
/// </param>
/// <param name="pointerOffset">
/// Specifies a offset of the first component of the first generic vertex attribute in the
/// array in the data store of the buffer currently bound to the GL_ARRAY_BUFFER target.
/// <para>Default: 0</para>
/// </param>
/// <param name="normalised">
/// Normalise floats?
/// <para>Default: false</para>
/// </param>
public VBO(BufferUsageHint bufferUsageHint = BufferUsageHint.StaticDraw,
VertexAttribPointerType pointerType = VertexAttribPointerType.Float, int pointerSize = 3,
int pointerStride = 0, int pointerOffset = 0, bool normalised = false)
@ -59,56 +86,95 @@ namespace SM.OGL.Mesh
}
/// <summary>
/// Adds two values to the VBO.
/// Adds two values to the VBO.
/// </summary>
public void Add(float x, float y) => AddRange(new[] {x,y});
/// <summary>
/// Adds three values to the VBO.
/// </summary>
public void Add(float x, float y, float z) => AddRange(new[] {x,y,z});
/// <summary>
/// Adds four values to the VBO.
/// </summary>
public void Add(float x, float y, float z, float w) => AddRange(new[] {x,y,z,w});
/// <summary>
/// Adds a Vector2.
/// </summary>
public void Add(Vector2 vector) => Add(vector.X, vector.Y);
/// <summary>
/// Adds a Vector2 and a value.
/// </summary>
public void Add(Vector2 vector, float z) => Add(vector.X, vector.Y, z);
/// <summary>
/// Adds a Vector2 and two values.
/// </summary>
public void Add(Vector2 vector, float z, float w) => Add(vector.X, vector.Y, z, w);
/// <summary>
/// Adds a Vector3.
/// </summary>
public void Add(Vector3 vector) => Add(vector.X, vector.Y, vector.Z);
/// <summary>
/// Adds a Vector3 and a value.
/// </summary>
public void Add(Vector3 vector, float w) => Add(vector.X, vector.Y, vector.Z, w);
/// <summary>
/// Adds a vector4.
/// </summary>
/// <param name="vector"></param>
public void Add(Vector4 vector) => Add(vector.X, vector.Y, vector.Z, vector.W);
/// <summary>
/// Adds a color.
/// </summary>
public void Add(Color4 color) => Add(color.R, color.G, color.B, color.A);
public void Add(float x, float y)
{
AddRange(new[] {x, y});
}
/// <summary>
/// Binds the buffer to the active VAO.
/// Adds three values to the VBO.
/// </summary>
public void Add(float x, float y, float z)
{
AddRange(new[] {x, y, z});
}
/// <summary>
/// Adds four values to the VBO.
/// </summary>
public void Add(float x, float y, float z, float w)
{
AddRange(new[] {x, y, z, w});
}
/// <summary>
/// Adds a Vector2.
/// </summary>
public void Add(Vector2 vector)
{
Add(vector.X, vector.Y);
}
/// <summary>
/// Adds a Vector2 and a value.
/// </summary>
public void Add(Vector2 vector, float z)
{
Add(vector.X, vector.Y, z);
}
/// <summary>
/// Adds a Vector2 and two values.
/// </summary>
public void Add(Vector2 vector, float z, float w)
{
Add(vector.X, vector.Y, z, w);
}
/// <summary>
/// Adds a Vector3.
/// </summary>
public void Add(Vector3 vector)
{
Add(vector.X, vector.Y, vector.Z);
}
/// <summary>
/// Adds a Vector3 and a value.
/// </summary>
public void Add(Vector3 vector, float w)
{
Add(vector.X, vector.Y, vector.Z, w);
}
/// <summary>
/// Adds a vector4.
/// </summary>
/// <param name="vector"></param>
public void Add(Vector4 vector)
{
Add(vector.X, vector.Y, vector.Z, vector.W);
}
/// <summary>
/// Adds a color.
/// </summary>
public void Add(Color4 color)
{
Add(color.R, color.G, color.B, color.A);
}
/// <summary>
/// Binds the buffer to the active VAO.
/// </summary>
/// <param name="attribID">The id for the attribute.</param>
internal void BindBuffer(int attribID)
{
float[] data = ToArray();
var data = ToArray();
int buffer = GL.GenBuffer();
var buffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, BufferUsageHint);

View file

@ -1,16 +1,19 @@
using System.Reflection;
using System.Runtime.CompilerServices;
#region usings
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// 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("SM.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("OpenGL Bindings for SMRederer")]
[assembly: AssemblyDescription("Defines classes to work with OpenTK/OpenGL")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyCompany("iedSoftworks")]
[assembly: AssemblyProduct("SM.Core")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2020")]
[assembly: AssemblyCopyright("Copyright © iedSoftworks 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -33,4 +36,4 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -23,6 +23,7 @@
<WarningLevel>4</WarningLevel>
<DocumentationFile>
</DocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -31,39 +32,39 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=3.2.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\packages\OpenTK.3.2\lib\net20\OpenTK.dll</HintPath>
<Reference Include="OpenTK, Version=3.2.1.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>..\..\packages\OpenTK.3.2.1\lib\net20\OpenTK.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Framebuffer\ColorAttachment.cs" />
<Compile Include="Framebuffer\Framebuffer.cs" />
<Compile Include="GLCustomActions.cs" />
<Compile Include="GLDebugging.cs" />
<Compile Include="GLObject.cs" />
<Compile Include="GLSettings.cs" />
<Compile Include="GLSystem.cs" />
<Compile Include="Mesh\BoundingBox.cs" />
<Compile Include="Mesh\GenericMesh.cs" />
<Compile Include="Mesh\VBO.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Shaders\GenericShader.cs" />
<Compile Include="Shaders\IUniform.cs" />
<Compile Include="Shaders\ShaderExtensions.cs" />
<Compile Include="Shaders\ShaderFileCollection.cs" />
<Compile Include="Shaders\ShaderFile.cs" />
<Compile Include="Shaders\ShaderPreProcess.cs" />
<Compile Include="Shaders\Uniform.cs" />
<Compile Include="Shaders\UniformArray.cs" />
<Compile Include="Shaders\UniformCollection.cs" />
<Compile Include="Texture\TextureBase.cs" />
<Compile Include="Version.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />

View file

@ -1,25 +1,30 @@
using System;
#region usings
using OpenTK.Graphics.OpenGL4;
using SM.OGL.Mesh;
#endregion
namespace SM.OGL.Shaders
{
/// <summary>
/// Abstract class, that is used to create graphic shader.
/// Abstract class, that is used to create graphic shader.
/// </summary>
public abstract class GenericShader : GLObject
{
protected override bool AutoCompile { get; } = true;
/// <summary>
/// Contains the different files for the shader.
/// Contains the different files for the shader.
/// </summary>
protected ShaderFileCollection ShaderFileFiles;
/// <summary>
/// Contains and manage the uniforms from the shader.
/// Contains and manage the uniforms from the shader.
/// </summary>
protected UniformCollection Uniforms;
/// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Program;
protected GenericShader(string vertex, string fragment) : this(new ShaderFileCollection(vertex, fragment)){}
/// <inheritdoc />
protected GenericShader(ShaderFileCollection shaderFileFiles)
@ -27,35 +32,26 @@ namespace SM.OGL.Shaders
ShaderFileFiles = shaderFileFiles;
}
/// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Program;
/// <summary>
/// Loads the shader to the GPU.
/// Loads the shader to the GPU.
/// </summary>
public void Load()
{
_id = GL.CreateProgram();
ShaderFileFiles.Append(this);
GL.LinkProgram(_id);
this.Name(GetType().Name);
Name(GetType().Name);
ShaderFileFiles.Detach(this);
GL.GetProgram(_id, GetProgramParameterName.ActiveUniforms, out int uniformCount);
if (uniformCount < 1)
throw new Exception("[Critical] No uniforms has been found.");
Uniforms = new UniformCollection();
Uniforms._parentShader = this;
for (int i = 0; i < uniformCount; i++)
{
string key = GL.GetActiveUniform(_id, i, out _, out _);
int loc = GL.GetUniformLocation(_id, key);
if (key.EndsWith("]"))
key = key.Split('[', ']')[0];
Uniforms.Add(key, loc);
}
Uniforms.ParentShader = this;
Uniforms.Import(this);
GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%");
}
/// <inheritdoc />
@ -65,22 +61,21 @@ namespace SM.OGL.Shaders
}
/// <summary>
/// Draws the mesh.
/// Draws the mesh.
/// </summary>
/// <param name="mesh">The mesh.</param>
/// <param name="amount">The amounts for instancing.</param>
/// <param name="bindVAO">Binds the vertex array for the mesh.</param>
protected void DrawObject(Mesh.GenericMesh mesh, int amount = 1, bool bindVAO = false)
protected void DrawObject(GenericMesh mesh, int amount = 1)
{
if (bindVAO) GL.BindVertexArray(mesh);
if (mesh.Indices != null)
GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount);
else
else
GL.DrawArraysInstanced(mesh.PrimitiveType, 0, mesh.Vertex.Count, amount);
}
/// <summary>
/// Resets the shader specific settings to ensure proper workings.
/// Resets the shader specific settings to ensure proper workings.
/// </summary>
protected void CleanUp()
{

View file

@ -0,0 +1,7 @@
namespace SM.OGL.Shaders
{
public interface IUniform
{
int Location { get; }
}
}

View file

@ -0,0 +1,38 @@
#region usings
using System.Collections.Generic;
using System.IO;
using System.Reflection;
#endregion
namespace SM.OGL.Shaders
{
public class ShaderExtensions
{
public static Dictionary<string, ShaderFile> Extensions { get; private set; } =
new Dictionary<string, ShaderFile>();
public static void AddAssemblyExtensions(string prefix, string path)
{
AddAssemblyExtensions(prefix, Assembly.GetCallingAssembly(), path);
}
public static void AddAssemblyExtensions(string prefix, Assembly assembly, string path)
{
var paths = assembly.GetManifestResourceNames();
for (var i = 0; i < paths.Length; i++)
{
var filePath = paths[i];
if (!filePath.StartsWith(path)) continue;
using (var reader = new StreamReader(assembly.GetManifestResourceStream(filePath)))
{
var name =
$"{prefix}{Path.GetFileNameWithoutExtension(filePath.Substring(path.Length)).Replace('.', '_')}";
Extensions.Add(name, new ShaderFile(reader.ReadToEnd()));
}
}
}
}
}

View file

@ -1,30 +1,37 @@
using System;
#region usings
using System;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL.Shaders
{
/// <summary>
/// Contains/Represents a file used in shaders.
/// Contains/Represents a file used in shaders.
/// </summary>
public class ShaderFile : GLObject
{
private string _data;
/// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Shader;
/// <summary>
/// Contains overrides, that can be used to import values from the CPU to the shader before it is been send to the GPU.
/// </summary>
public Dictionary<string, string> StringOverrides = new Dictionary<string, string>();
/// <summary>
/// Contains other shader files to allow access to their functions.
/// Contains other shader files to allow access to their functions.
/// </summary>
public List<ShaderFile> GLSLExtensions = new List<ShaderFile>();
/// <summary>
/// Creates a file.
/// Gets/Sets the name for this shader file.
/// </summary>
public new string Name;
/// <summary>
/// Contains overrides, that can be used to import values from the CPU to the shader before it is been send to the GPU.
/// </summary>
public Dictionary<string, string> StringOverrides = new Dictionary<string, string>();
/// <summary>
/// Creates a file.
/// </summary>
/// <param name="data">The source file.</param>
public ShaderFile(string data)
@ -32,11 +39,28 @@ namespace SM.OGL.Shaders
_data = data;
}
/// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Shader;
private void GenerateSource()
{
foreach (KeyValuePair<string, string> kvp in StringOverrides)
_data = _data.Replace("//! " + kvp.Key, kvp.Value);
if (!GLSettings.ShaderPreProcessing) return;
if (_data.Contains("//#"))
{
var commandSplits = _data.Split(new[] {"//#"}, StringSplitOptions.RemoveEmptyEntries);
for (var i = 1; i < commandSplits.Length; i++)
{
var split = commandSplits[i].Split('\r', '\n')[0].Trim();
var cmdArgs = split.Split(new[] {' '}, 2);
ShaderPreProcess.Actions[cmdArgs[0]]?.Invoke(this, cmdArgs[1]);
}
}
foreach (var kvp in StringOverrides)
_data = _data.Replace("//!" + kvp.Key, kvp.Value);
}
internal void Compile(GenericShader shader, ShaderType type)
@ -49,7 +73,11 @@ namespace SM.OGL.Shaders
GL.ShaderSource(_id, _data);
GL.CompileShader(_id);
}
GL.AttachShader(shader, _id);
GLDebugging.CheckGLErrors($"Error at loading shader file: '{shader.GetType()}', '{type}', %code%");
for (var i = 0; i < GLSLExtensions.Count; i++) GLSLExtensions[i].Compile(shader, type);
}
}
}

View file

@ -1,36 +1,43 @@
using System;
using System.Collections.Generic;
#region usings
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL.Shaders
{
/// <summary>
/// Collects all files that are needed for a shader.
/// Collects all files that are needed for a shader.
/// </summary>
public struct ShaderFileCollection
{
/// <summary>
/// Contains the vertex file.
/// Contains the vertex file.
/// </summary>
public ShaderFile Vertex;
/// <summary>
/// Contains the geometry file.
/// Contains the geometry file.
/// </summary>
public ShaderFile Geometry;
/// <summary>
/// Contains the fragment file.
/// Contains the fragment file.
/// </summary>
public ShaderFile Fragment;
/// <summary>
/// Creating the collection with vertex and fragment files.
/// Creating the collection with vertex and fragment files.
/// </summary>
/// <param name="vertex">The vertex source file.</param>
/// <param name="fragment">The fragment source file.</param>
public ShaderFileCollection(string vertex, string fragment) : this(new ShaderFile(vertex), new ShaderFile(fragment)) {}
public ShaderFileCollection(string vertex, string fragment) : this(new ShaderFile(vertex),
new ShaderFile(fragment))
{
}
/// <summary>
/// Creating the collection with shader files.
/// Creating the collection with shader files.
/// </summary>
/// <param name="vertex"></param>
/// <param name="fragment"></param>
@ -43,7 +50,7 @@ namespace SM.OGL.Shaders
}
/// <summary>
/// Appends the files to the shader.
/// Appends the files to the shader.
/// </summary>
/// <param name="shader"></param>
internal void Append(GenericShader shader)
@ -54,14 +61,16 @@ namespace SM.OGL.Shaders
}
/// <summary>
/// Removes the files form the shader.
/// Removes the files form the shader.
/// </summary>
/// <param name="shader"></param>
internal void Detach(GenericShader shader)
{
GL.DetachShader(Vertex, shader);
if (Geometry != null) GL.DetachShader(Geometry, shader);
GL.DetachShader(Fragment, shader);
GL.DetachShader(shader, Vertex);
if (Geometry != null) GL.DetachShader(shader, Geometry);
GL.DetachShader(shader, Fragment);
GLDebugging.CheckGLErrors($"Error at detaching '{shader.GetType()}'");
}
}
}

View file

@ -0,0 +1,24 @@
#region usings
using System;
using System.Collections.Generic;
#endregion
namespace SM.OGL.Shaders
{
public class ShaderPreProcess
{
public static Dictionary<string, Action<ShaderFile, string>> Actions =
new Dictionary<string, Action<ShaderFile, string>>
{
{"import", Import}
};
private static void Import(ShaderFile file, string param)
{
foreach (var extension in param.Split(' '))
file.GLSLExtensions.Add(ShaderExtensions.Extensions[extension]);
}
}
}

View file

@ -1,27 +1,35 @@
using OpenTK;
#region usings
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using SM.OGL.Texture;
#endregion
namespace SM.OGL.Shaders
{
/// <summary>
/// Manages the uniforms.
/// Manages the uniforms.
/// </summary>
public struct Uniform
public struct Uniform : IUniform
{
/// <summary>
/// This contains the location for the uniform.
/// This contains the location for the uniform.
/// </summary>
private int Location;
/// <summary>
/// This contains the Parent collection of this uniform.
/// </summary>
internal UniformCollection Parent;
public int Location { get; internal set; }
/// <summary>
/// This create a new uniform manager
/// This contains the Parent collection of this uniform.
/// </summary>
public UniformCollection Parent { get; }
public Uniform(int location) : this(location, null)
{
}
/// <summary>
/// This create a new uniform manager
/// </summary>
/// <param name="location">Location id</param>
/// <param name="parent">Parent collection</param>
@ -38,114 +46,343 @@ namespace SM.OGL.Shaders
GL.Uniform1(Location, value ? 1 : 0);
}
public void SetUniform1(int value) { GL.Uniform1(Location, value); }
public void SetUniform1(int count, params int[] values) { GL.Uniform1(Location, count, values); }
public void SetUniform1(int count, ref int values) { GL.Uniform1(Location, count, ref values); }
public void SetUniform1(int value)
{
GL.Uniform1(Location, value);
}
public void SetUniform1(int count, params int[] values)
{
GL.Uniform1(Location, count, values);
}
public void SetUniform1(int count, ref int values)
{
GL.Uniform1(Location, count, ref values);
}
public void SetUniform1(uint value) { GL.Uniform1(Location, value); }
public void SetUniform1(int count, params uint[] values) { GL.Uniform1(Location, count, values); }
public void SetUniform1(int count, ref uint values) { GL.Uniform1(Location, count, ref values); }
public void SetUniform1(uint value)
{
GL.Uniform1(Location, value);
}
public void SetUniform1(int count, params uint[] values)
{
GL.Uniform1(Location, count, values);
}
public void SetUniform1(int count, ref uint values)
{
GL.Uniform1(Location, count, ref values);
}
public void SetUniform1(float value) { GL.Uniform1(Location, value); }
public void SetUniform1(int count, params float[] values) { GL.Uniform1(Location, count, values); }
public void SetUniform1(int count, ref float value) { GL.Uniform1(Location, count, ref value); }
public void SetUniform1(float value)
{
GL.Uniform1(Location, value);
}
public void SetUniform1(int count, params float[] values)
{
GL.Uniform1(Location, count, values);
}
public void SetUniform1(int count, ref float value)
{
GL.Uniform1(Location, count, ref value);
}
public void SetUniform1(double value) { GL.Uniform1(Location, value); }
public void SetUniform1(int count, params double[] values) { GL.Uniform1(Location, count, values); }
public void SetUniform1(int count, ref double value) { GL.Uniform1(Location, count, ref value); }
public void SetUniform1(double value)
{
GL.Uniform1(Location, value);
}
public void SetUniform1(int count, params double[] values)
{
GL.Uniform1(Location, count, values);
}
public void SetUniform1(int count, ref double value)
{
GL.Uniform1(Location, count, ref value);
}
#endregion
#region Uniform2
public void SetUniform2(float x, float y) { GL.Uniform2(Location, x, y); }
public void SetUniform2(double x, double y) { GL.Uniform2(Location, x, y); }
public void SetUniform2(uint x, uint y) { GL.Uniform2(Location, x, y); }
public void SetUniform2(int x, int y) { GL.Uniform2(Location, x, y); }
public void SetUniform2(float x, float y)
{
GL.Uniform2(Location, x, y);
}
public void SetUniform2(int count, params float[] values) { GL.Uniform2(Location, count, values); }
public void SetUniform2(int count, params double[] values) { GL.Uniform2(Location, count, values); }
public void SetUniform2(int count, params int[] values) { GL.Uniform2(Location, count, values); }
public void SetUniform2(int count, params uint[] values) { GL.Uniform2(Location, count, values); }
public void SetUniform2(double x, double y)
{
GL.Uniform2(Location, x, y);
}
public void SetUniform2(int count, ref float values) { GL.Uniform2(Location, count, ref values); }
public void SetUniform2(int count, ref double values) { GL.Uniform2(Location, count, ref values); }
public void SetUniform2(int count, ref uint values) { GL.Uniform2(Location, count, ref values); }
public void SetUniform2(uint x, uint y)
{
GL.Uniform2(Location, x, y);
}
public void SetUniform2(Vector2 vector2) { GL.Uniform2(Location, vector2); }
public void SetUniform2(ref Vector2 vector2) { GL.Uniform2(Location, ref vector2); }
public void SetUniform2(int x, int y)
{
GL.Uniform2(Location, x, y);
}
public void SetUniform2(int count, params float[] values)
{
GL.Uniform2(Location, count, values);
}
public void SetUniform2(int count, params double[] values)
{
GL.Uniform2(Location, count, values);
}
public void SetUniform2(int count, params int[] values)
{
GL.Uniform2(Location, count, values);
}
public void SetUniform2(int count, params uint[] values)
{
GL.Uniform2(Location, count, values);
}
public void SetUniform2(int count, ref float values)
{
GL.Uniform2(Location, count, ref values);
}
public void SetUniform2(int count, ref double values)
{
GL.Uniform2(Location, count, ref values);
}
public void SetUniform2(int count, ref uint values)
{
GL.Uniform2(Location, count, ref values);
}
public void SetUniform2(Vector2 vector2)
{
GL.Uniform2(Location, vector2);
}
public void SetUniform2(ref Vector2 vector2)
{
GL.Uniform2(Location, ref vector2);
}
#endregion
#region Uniform3
public void SetUniform3(float x, float y, float z) { GL.Uniform3(Location, x, y, z); }
public void SetUniform3(double x, double y, double z) { GL.Uniform3(Location, x, y, z); }
public void SetUniform3(uint x, uint y, uint z) { GL.Uniform3(Location, x, y, z); }
public void SetUniform3(int x, int y, int z) { GL.Uniform3(Location, x, y, z); }
public void SetUniform3(float x, float y, float z)
{
GL.Uniform3(Location, x, y, z);
}
public void SetUniform3(int count, params float[] values) { GL.Uniform3(Location, count, values); }
public void SetUniform3(int count, params double[] values) { GL.Uniform3(Location, count, values); }
public void SetUniform3(int count, params int[] values) { GL.Uniform3(Location, count, values); }
public void SetUniform3(int count, params uint[] values) { GL.Uniform3(Location, count, values); }
public void SetUniform3(double x, double y, double z)
{
GL.Uniform3(Location, x, y, z);
}
public void SetUniform3(int count, ref float values) { GL.Uniform3(Location, count, ref values); }
public void SetUniform3(int count, ref double values) { GL.Uniform3(Location, count, ref values); }
public void SetUniform3(int count, ref uint values) { GL.Uniform3(Location, count, ref values); }
public void SetUniform3(uint x, uint y, uint z)
{
GL.Uniform3(Location, x, y, z);
}
public void SetUniform3(Vector3 vector) { GL.Uniform3(Location, vector); }
public void SetUniform3(ref Vector3 vector) { GL.Uniform3(Location, ref vector); }
public void SetUniform3(int x, int y, int z)
{
GL.Uniform3(Location, x, y, z);
}
public void SetUniform3(int count, params float[] values)
{
GL.Uniform3(Location, count, values);
}
public void SetUniform3(int count, params double[] values)
{
GL.Uniform3(Location, count, values);
}
public void SetUniform3(int count, params int[] values)
{
GL.Uniform3(Location, count, values);
}
public void SetUniform3(int count, params uint[] values)
{
GL.Uniform3(Location, count, values);
}
public void SetUniform3(int count, ref float values)
{
GL.Uniform3(Location, count, ref values);
}
public void SetUniform3(int count, ref double values)
{
GL.Uniform3(Location, count, ref values);
}
public void SetUniform3(int count, ref uint values)
{
GL.Uniform3(Location, count, ref values);
}
public void SetUniform3(Vector3 vector)
{
GL.Uniform3(Location, vector);
}
public void SetUniform3(ref Vector3 vector)
{
GL.Uniform3(Location, ref vector);
}
#endregion
#region Uniform4
public void SetUniform4(float x, float y, float z, float w) { GL.Uniform4(Location, x, y, z, w); }
public void SetUniform4(double x, double y, double z, double w) { GL.Uniform4(Location, x, y, z, w); }
public void SetUniform4(uint x, uint y, uint z, uint w) { GL.Uniform4(Location, x, y, z, w); }
public void SetUniform4(int x, int y, int z, int w) { GL.Uniform4(Location, x, y, z, w); }
public void SetUniform4(float x, float y, float z, float w)
{
GL.Uniform4(Location, x, y, z, w);
}
public void SetUniform4(int count, params float[] values) { GL.Uniform4(Location, count, values); }
public void SetUniform4(int count, params double[] values) { GL.Uniform4(Location, count, values); }
public void SetUniform4(int count, params int[] values) { GL.Uniform4(Location, count, values); }
public void SetUniform4(int count, params uint[] values) { GL.Uniform4(Location, count, values); }
public void SetUniform4(double x, double y, double z, double w)
{
GL.Uniform4(Location, x, y, z, w);
}
public void SetUniform4(int count, ref float values) { GL.Uniform4(Location, count, ref values); }
public void SetUniform4(int count, ref double values) { GL.Uniform4(Location, count, ref values); }
public void SetUniform4(int count, ref uint values) { GL.Uniform4(Location, count, ref values); }
public void SetUniform4(uint x, uint y, uint z, uint w)
{
GL.Uniform4(Location, x, y, z, w);
}
public void SetUniform4(Vector4 vector) { GL.Uniform4(Location, vector); }
public void SetUniform4(ref Vector4 vector) { GL.Uniform4(Location, ref vector); }
public void SetUniform4(int x, int y, int z, int w)
{
GL.Uniform4(Location, x, y, z, w);
}
public void SetUniform4(Color4 color) { GL.Uniform4(Location, color); }
public void SetUniform4(Quaternion quaternion) { GL.Uniform4(Location, quaternion); }
public void SetUniform4(int count, params float[] values)
{
GL.Uniform4(Location, count, values);
}
public void SetUniform4(int count, params double[] values)
{
GL.Uniform4(Location, count, values);
}
public void SetUniform4(int count, params int[] values)
{
GL.Uniform4(Location, count, values);
}
public void SetUniform4(int count, params uint[] values)
{
GL.Uniform4(Location, count, values);
}
public void SetUniform4(int count, ref float values)
{
GL.Uniform4(Location, count, ref values);
}
public void SetUniform4(int count, ref double values)
{
GL.Uniform4(Location, count, ref values);
}
public void SetUniform4(int count, ref uint values)
{
GL.Uniform4(Location, count, ref values);
}
public void SetUniform4(Vector4 vector)
{
GL.Uniform4(Location, vector);
}
public void SetUniform4(ref Vector4 vector)
{
GL.Uniform4(Location, ref vector);
}
public void SetUniform4(Color4 color)
{
GL.Uniform4(Location, color);
}
public void SetUniform4(Quaternion quaternion)
{
GL.Uniform4(Location, quaternion);
}
#endregion
#region Matrix2
public void SetMatrix2(ref Matrix2 matrix, bool transpose = false) { GL.UniformMatrix2(Location, transpose, ref matrix); }
public void SetMatrix2(ref Matrix2 matrix, bool transpose = false)
{
GL.UniformMatrix2(Location, transpose, ref matrix);
}
public void SetMatrix2(int count, ref double value, bool transpose = false) { GL.UniformMatrix2(Location, count, transpose, ref value); }
public void SetMatrix2(int count, ref float value, bool transpose = false) { GL.UniformMatrix2(Location, count, transpose, ref value); }
public void SetMatrix2(int count, ref double value, bool transpose = false)
{
GL.UniformMatrix2(Location, count, transpose, ref value);
}
public void SetMatrix2(int count, double[] value, bool transpose = false) { GL.UniformMatrix2(Location, count, transpose, value); }
public void SetMatrix2(int count, float[] value, bool transpose = false) { GL.UniformMatrix2(Location, count, transpose, value); }
public void SetMatrix2(int count, ref float value, bool transpose = false)
{
GL.UniformMatrix2(Location, count, transpose, ref value);
}
public void SetMatrix2(int count, double[] value, bool transpose = false)
{
GL.UniformMatrix2(Location, count, transpose, value);
}
public void SetMatrix2(int count, float[] value, bool transpose = false)
{
GL.UniformMatrix2(Location, count, transpose, value);
}
#endregion
#region Matrix3
public void SetMatrix3(ref Matrix3 matrix, bool transpose = false) { GL.UniformMatrix3(Location, transpose, ref matrix); }
public void SetMatrix3(ref Matrix3 matrix, bool transpose = false)
{
GL.UniformMatrix3(Location, transpose, ref matrix);
}
public void SetMatrix3(int count, ref double value, bool transpose = false) { GL.UniformMatrix3(Location, count, transpose, ref value); }
public void SetMatrix3(int count, ref float value, bool transpose = false) { GL.UniformMatrix3(Location, count, transpose, ref value); }
public void SetMatrix3(int count, ref double value, bool transpose = false)
{
GL.UniformMatrix3(Location, count, transpose, ref value);
}
public void SetMatrix3(int count, double[] value, bool transpose = false) { GL.UniformMatrix3(Location, count, transpose, value); }
public void SetMatrix3(int count, float[] value, bool transpose = false) { GL.UniformMatrix3(Location, count, transpose, value); }
public void SetMatrix3(int count, ref float value, bool transpose = false)
{
GL.UniformMatrix3(Location, count, transpose, ref value);
}
public void SetMatrix3(int count, double[] value, bool transpose = false)
{
GL.UniformMatrix3(Location, count, transpose, value);
}
public void SetMatrix3(int count, float[] value, bool transpose = false)
{
GL.UniformMatrix3(Location, count, transpose, value);
}
#endregion
@ -155,18 +392,36 @@ namespace SM.OGL.Shaders
{
GL.UniformMatrix4(Location, transpose, ref matrix);
}
public void SetMatrix4(ref Matrix4 matrix, bool transpose = false) { GL.UniformMatrix4(Location, transpose, ref matrix); }
public void SetMatrix4(int count, ref double value, bool transpose = false) { GL.UniformMatrix4(Location, count, transpose, ref value); }
public void SetMatrix4(int count, ref float value, bool transpose = false) { GL.UniformMatrix4(Location, count, transpose, ref value); }
public void SetMatrix4(ref Matrix4 matrix, bool transpose = false)
{
GL.UniformMatrix4(Location, transpose, ref matrix);
}
public void SetMatrix4(int count, double[] value, bool transpose = false) { GL.UniformMatrix4(Location, count, transpose, value); }
public void SetMatrix4(int count, float[] value, bool transpose = false) { GL.UniformMatrix4(Location, count, transpose, value); }
public void SetMatrix4(int count, ref double value, bool transpose = false)
{
GL.UniformMatrix4(Location, count, transpose, ref value);
}
public void SetMatrix4(int count, ref float value, bool transpose = false)
{
GL.UniformMatrix4(Location, count, transpose, ref value);
}
public void SetMatrix4(int count, double[] value, bool transpose = false)
{
GL.UniformMatrix4(Location, count, transpose, value);
}
public void SetMatrix4(int count, float[] value, bool transpose = false)
{
GL.UniformMatrix4(Location, count, transpose, value);
}
#endregion
/// <summary>
/// Try to sets the texture at the next possible position and tells the checkUniform, if worked or not.
/// Try to sets the texture at the next possible position and tells the checkUniform, if worked or not.
/// </summary>
/// <param name="texture">The texture you want to add</param>
/// <param name="checkUniform">The check uniform.</param>
@ -177,7 +432,7 @@ namespace SM.OGL.Shaders
}
/// <summary>
/// Try to sets the texture at the specified position and tells the checkUniform, if worked or not.
/// Try to sets the texture at the specified position and tells the checkUniform, if worked or not.
/// </summary>
/// <param name="texture">The texture you want to add</param>
/// <param name="pos">The position</param>
@ -187,14 +442,18 @@ namespace SM.OGL.Shaders
checkUniform.SetUniform1(texture != null);
if (texture != null) SetTexture(texture);
}
/// <summary>
/// Sets the texture to the next possible position.
/// </summary>
/// <param name="texture"></param>
public void SetTexture(TextureBase texture) => SetTexture(texture, Parent.NextTexture++);
/// <summary>
/// Sets the texture to the specified position.
/// Sets the texture to the next possible position.
/// </summary>
/// <param name="texture"></param>
public void SetTexture(TextureBase texture)
{
if (Parent != null) SetTexture(texture, Parent.NextTexture++);
}
/// <summary>
/// Sets the texture to the specified position.
/// </summary>
/// <param name="texture"></param>
/// <param name="texturePos"></param>
@ -206,9 +465,12 @@ namespace SM.OGL.Shaders
}
/// <summary>
/// Returns the location from the uniform
/// Returns the location from the uniform
/// </summary>
/// <param name="u"></param>
public static implicit operator int(Uniform u) => u.Location;
public static implicit operator int(Uniform u)
{
return u.Location;
}
}
}

View file

@ -0,0 +1,50 @@
#region usings
using System;
using System.Collections.Generic;
#endregion
namespace SM.OGL.Shaders
{
public class UniformArray : IUniform
{
internal UniformCollection collection;
internal Dictionary<string, int> Offsets = new Dictionary<string, int>();
internal int Size;
internal bool Struct = false;
public int Location { get; internal set; }
public GenericShader Parent { get; internal set; }
public string Name { get; internal set; }
public UniformArray()
{
collection = new UniformCollection()
{
ParentShader = Parent
};
}
public void Set(Action<int, Uniform> setAction)
{
for (var i = 0; i < Size; i++) setAction(i, new Uniform(Location + i));
}
public void Set(Func<int, UniformCollection, bool> setAction)
{
collection.ParentShader ??= Parent;
for (var i = 0; i < Size; i++)
{
collection.KeyString = $"{Name}[{i}]";
foreach (var pair in Offsets)
collection.Set(pair.Key, new Uniform(Location + pair.Value + i));
if (!setAction(i, collection)) break;
}
}
}
}

View file

@ -1,56 +1,109 @@
using System;
#region usings
using System;
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL.Shaders
{
/// <summary>
/// Contains and manages the uniform of the parent shader.
/// </summary>
public class UniformCollection : Dictionary<string, Uniform>
public class UniformCollection : Dictionary<string, IUniform>
{
/// <summary>
/// The next texture id for the uniform.
/// </summary>
internal int NextTexture = 0;
internal string KeyString = "";
public GenericShader ParentShader { get; internal set; }
/// <summary>
/// The parent shader.
/// </summary>
internal GenericShader _parentShader;
public new Uniform this[string key] => Get(key);
/// <summary>
/// Get you the uniform under the variable name.
/// <para>If it don't find the uniform, it tries to recreate it.</para>
/// <para>If the variable doesn't exist in the first place, it will after the recreation send everything to -1, what is the void.</para>
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public new Uniform this[string key]
public Uniform Get(string key)
{
get
try
{
try
{
return base[key];
}
catch (KeyNotFoundException)
{
Console.WriteLine("[Error] Uniform '"+key+"' was not found. Tried to recreate it.");
Uniform u = new Uniform(GL.GetUniformLocation(_parentShader, key), this);
Add(key, u);
return u;
}
return (Uniform) base[key];
}
catch (KeyNotFoundException)
{
GLCustomActions.AtWarning?.Invoke("Uniform '" + KeyString + key + "' was not found. Tried to recreate it.");
var u = new Uniform(GL.GetUniformLocation(ParentShader, KeyString + key), this);
Add(key, u);
return u;
}
}
/// <summary>
/// Adds a uniform with a location.
/// </summary>
/// <param name="key"></param>
/// <param name="location"></param>
public UniformArray GetArray(string key)
{
try
{
return (UniformArray) base[key];
}
catch (KeyNotFoundException)
{
throw new Exception("UniformArray '"+key+"' wasn't found");
}
}
public void Add(string key, int location)
{
base.Add(key, new Uniform(location, this));
}
internal void Set(string key, IUniform value)
{
base[key] = value;
}
internal void Import(GenericShader shader)
{
GL.GetProgram(shader, GetProgramParameterName.ActiveUniforms, out var uniformCount);
if (uniformCount < 1)
GLCustomActions.AtError("No uniforms has been found.");
var lastArrayKey = "";
var array = new UniformArray();
var arrayFilled = false;
if (GLSettings.InfoEveryUniform) GLCustomActions.AtInfo?.Invoke("Uniforms for: " + shader.GetType());
for (var i = 0; i < uniformCount; i++)
{
var key = GL.GetActiveUniform(shader, i, out _, out _);
var loc = GL.GetUniformLocation(shader, key);
if (GLSettings.InfoEveryUniform) GLCustomActions.AtInfo?.Invoke($"{key} - {loc}");
if (key.Contains("["))
{
var keySplits = key.Split('[', ']');
if (keySplits[0] != lastArrayKey)
{
if (arrayFilled) Add(lastArrayKey, array);
array = new UniformArray
{
Location = loc,
Name = keySplits[0],
Parent = ParentShader,
Struct = keySplits.Length > 2
};
arrayFilled = true;
lastArrayKey = keySplits[0];
}
var curIndex = int.Parse(keySplits[1]);
if (array.Size < curIndex) array.Size = curIndex;
if (array.Struct)
if (!array.Offsets.ContainsKey(keySplits[2].Trim('.')))
array.Offsets.Add(keySplits[2].Trim('.'), loc - array.Location);
}
else
{
Add(key, loc);
}
}
if (arrayFilled) Add(lastArrayKey, array);
}
}
}

View file

@ -1,9 +1,13 @@
using OpenTK.Graphics.OpenGL4;
#region usings
using OpenTK.Graphics.OpenGL4;
#endregion
namespace SM.OGL.Texture
{
/// <summary>
/// Works as a basis for textures.
/// Works as a basis for textures.
/// </summary>
public abstract class TextureBase : GLObject
{
@ -14,23 +18,24 @@ namespace SM.OGL.Texture
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture;
/// <summary>
/// The texture filter.
/// <para>Default: <see cref="TextureMinFilter.Linear"/></para>
/// The texture filter.
/// <para>Default: <see cref="TextureMinFilter.Linear" /></para>
/// </summary>
public virtual TextureMinFilter Filter { get; set; } = TextureMinFilter.Linear;
/// <summary>
/// The wrap mode.
/// <para>Default: <see cref="TextureWrapMode.Repeat"/></para>
/// The wrap mode.
/// <para>Default: <see cref="TextureWrapMode.Repeat" /></para>
/// </summary>
public virtual TextureWrapMode WrapMode { get; set; } = TextureWrapMode.Repeat;
/// <summary>
/// The Width of the texture
/// The Width of the texture
/// </summary>
public int Width { get; protected set; }
/// <summary>
/// The height of the texture
/// The height of the texture
/// </summary>
public int Height { get; protected set; }

View file

@ -1,21 +1,22 @@
namespace SM.OGL
{
/// <summary>
/// Helper struct to manage versions.
/// Helper struct to manage versions.
/// </summary>
public struct Version
{
/// <summary>
/// The major version.
/// The major version.
/// </summary>
public int MajorVersion;
/// <summary>
/// The minor version.
/// The minor version.
/// </summary>
public int MinorVersion;
/// <summary>
/// Creates the struct with specific major and minor versions.
/// Creates the struct with specific major and minor versions.
/// </summary>
/// <param name="majorVersion"></param>
/// <param name="minorVersion"></param>
@ -26,12 +27,12 @@
}
/// <summary>
/// Creates the struct by reading it out of a string.
/// Creates the struct by reading it out of a string.
/// </summary>
/// <param name="version"></param>
public Version(string version)
{
string[] splits = version.Trim().Split(new []{'.'}, 2);
var splits = version.Trim().Split(new[] {'.'}, 2);
MajorVersion = int.Parse(splits[0]);
MinorVersion = int.Parse(splits[1]);
}
@ -43,7 +44,7 @@
}
/// <summary>
/// Create a version struct, with a OpenGL Version string.
/// Create a version struct, with a OpenGL Version string.
/// </summary>
/// <param name="version"></param>
/// <returns></returns>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="OpenTK" version="3.2" targetFramework="net452" />
<package id="OpenTK" version="3.2.1" targetFramework="net452" />
</packages>