From d269760c807861f10d7a11a83d9c9557743f33a7 Mon Sep 17 00:00:00 2001 From: Harrison Date: Thu, 28 May 2020 13:51:44 -0500 Subject: [PATCH] Progress on adding GL shader system. --- .../Exceptions/OpenGLException.cs | 17 ++++++ src/SlatedGameToolkit.Framework/GameEngine.cs | 2 +- .../Graphics/OpenGL/GLFunctionDelegates.cs | 23 ++++---- .../Graphics/OpenGL/GLProgram.cs | 42 ++++++++++++++ .../Graphics/OpenGL/GLShaderProgram.cs | 57 +++++++++++++++++++ .../Graphics/OpenGL/ShaderHandle.cs | 13 ----- .../Graphics/OpenGL/Shaders/GLShader.cs | 42 ++++++++++++++ .../Graphics/OpenGL/Shaders/GLVertexShader.cs | 32 +++++++++++ .../Graphics/Window/WindowContext.cs | 7 ++- .../Graphics/Window/WindowManager.cs | 2 +- .../Graphics/Window/WindowsOption.cs | 2 - .../StateSystem/Manager.cs | 4 +- .../Commands/GraphicalPlaygroundCommand.cs | 2 +- 13 files changed, 212 insertions(+), 33 deletions(-) create mode 100644 src/SlatedGameToolkit.Framework/Exceptions/OpenGLException.cs create mode 100644 src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLProgram.cs create mode 100644 src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLShaderProgram.cs delete mode 100644 src/SlatedGameToolkit.Framework/Graphics/OpenGL/ShaderHandle.cs create mode 100644 src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLShader.cs create mode 100644 src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLVertexShader.cs diff --git a/src/SlatedGameToolkit.Framework/Exceptions/OpenGLException.cs b/src/SlatedGameToolkit.Framework/Exceptions/OpenGLException.cs new file mode 100644 index 0000000..18e6323 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Exceptions/OpenGLException.cs @@ -0,0 +1,17 @@ +using System; + +namespace SlatedGameToolkit.Framework.Exceptions +{ + public class OpenGLException : Exception { + public OpenGLException() : base() { + + } + + public OpenGLException(string message) : base(message) { + + } + + public OpenGLException(string message, Exception inner) : base(message, inner) { + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/GameEngine.cs b/src/SlatedGameToolkit.Framework/GameEngine.cs index 2b0724f..c9215a4 100644 --- a/src/SlatedGameToolkit.Framework/GameEngine.cs +++ b/src/SlatedGameToolkit.Framework/GameEngine.cs @@ -136,7 +136,7 @@ namespace SlatedGameToolkit.Framework { Keyboard.OnKeyReleased((Key) SDL_Event.key.keysym.sym); break; case SDL.SDL_EventType.SDL_WINDOWEVENT: - WindowContext handle = WindowManager.HandleFromID(SDL_Event.window.windowID); + WindowContext handle = WindowManager.ContextFromID(SDL_Event.window.windowID); switch (SDL_Event.window.windowEvent) { case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLFunctionDelegates.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLFunctionDelegates.cs index 0f9c76b..5df603b 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLFunctionDelegates.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLFunctionDelegates.cs @@ -3,15 +3,18 @@ using System; namespace SlatedGameToolkit.Framework.Graphics.OpenGL { internal delegate void GLClearColour(float r, float g, float b); - internal delegate void GLClear(uint flags); + internal delegate void GLClear(GLEnums flags); internal delegate void GLViewport(int x, int y, int width, int height); - internal delegate IntPtr GLCreateShader(GLEnums type); - internal delegate IntPtr GLShaderSource(IntPtr shaderHandle, int count, string program); - internal delegate void GLCompileShader(IntPtr shaderHandle); - internal delegate void GLGetShaderLogInfo(IntPtr shaderHandle, int maxLength, out int writtenLength, out string output); - internal delegate IntPtr GLCreateProgram(); - internal delegate IntPtr GLDeleteProgram(); - internal delegate void GLAttachShader(IntPtr program, IntPtr shader); - internal delegate void GLDetachShader(IntPtr program, IntPtr shader); - internal delegate void GLDeleteShader(IntPtr shader); + internal delegate UIntPtr GLCreateShader(GLEnums type); + internal delegate UIntPtr GLShaderSource(UIntPtr shaderHandle, uint count, string program, int[] length); + internal delegate void GLCompileShader(UIntPtr shaderHandle); + internal delegate void GLGetShaderLogInfo(UIntPtr shader, uint maxLength, out uint writtenLength, out string output); + internal delegate UIntPtr GLCreateProgram(); + internal delegate UIntPtr GLDeleteProgram(UIntPtr program); + internal delegate void GLAttachShader(UIntPtr program, UIntPtr shader); + internal delegate void GLDetachShader(UIntPtr program, UIntPtr shader); + internal delegate void GLDeleteShader(UIntPtr shader); + internal delegate void GLBindAttribLocation(UIntPtr program, uint index, string name); + internal delegate void GLGetProgramInfoLog(UIntPtr program, uint maxLength, out uint writtenLength, out string output); + internal delegate void GLLinkProgram(UIntPtr program); } \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLProgram.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLProgram.cs new file mode 100644 index 0000000..24577b5 --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLProgram.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.InteropServices; +using SDL2; +using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.Window; + +namespace SlatedGameToolkit.Framework.Graphics.OpenGL +{ + public abstract class GLProgram : IDisposable + { + private WindowContext context; + private protected UIntPtr handle; + private protected GLCreateProgram createProgram; + private protected GLDeleteProgram deleteProgram; + private protected GLLinkProgram linkProgram; + private protected GLGetProgramInfoLog getProgramInfoLog; + + public GLProgram(WindowContext context) { + this.context = context; + context.MakeCurrent(); + createProgram = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glCreateProgram")); + if (createProgram == null) throw new FrameworkSDLException(); + deleteProgram = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glDeleteProgram")); + if (deleteProgram == null) throw new FrameworkSDLException(); + linkProgram = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glLinkProgram")); + if (linkProgram == null) throw new FrameworkSDLException(); + getProgramInfoLog = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glGetProgramInfoLog")); + if (getProgramInfoLog == null) throw new FrameworkSDLException(); + + handle = createProgram(); + } + + public virtual void Dispose() + { + deleteProgram(handle); + } + + ~GLProgram() { + Dispose(); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLShaderProgram.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLShaderProgram.cs new file mode 100644 index 0000000..ad0d38f --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/GLShaderProgram.cs @@ -0,0 +1,57 @@ +using System; +using System.Runtime.InteropServices; +using SDL2; +using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.OpenGL.Shaders; +using SlatedGameToolkit.Framework.Graphics.Window; + +namespace SlatedGameToolkit.Framework.Graphics.OpenGL +{ + public class ShaderProgram : GLProgram + { + private GLShader[] shaders; + private GLAttachShader attachShader; + private GLDetachShader detachShader; + private GLBindAttribLocation bindAttribLocation; + public ShaderProgram(WindowContext context, params GLShader[] shaders) : base(context) { + this.shaders = shaders; + attachShader = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glAttachShader")); + if (attachShader == null) throw new FrameworkSDLException(); + bindAttribLocation = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glBindAttribLocation")); + if (bindAttribLocation == null) throw new FrameworkSDLException(); + detachShader = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glDetachShader")); + if (detachShader == null) throw new FrameworkSDLException(); + + foreach (GLShader shader in shaders) + { + attachShader(handle, shader.Handle); + } + + linkProgram(handle); + uint length; + string log; + getProgramInfoLog(handle, 1024, out length, out log); + if (length > 0) { + Dispose(); + throw new OpenGLException(log); + } + + foreach (GLShader shader in shaders) + { + detachShader(handle, shader.Handle); + } + } + + public override void Dispose() { + foreach (GLShader shader in shaders) + { + shader.Dispose(); + } + base.Dispose(); + } + + ~ShaderProgram() { + Dispose(); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/ShaderHandle.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/ShaderHandle.cs deleted file mode 100644 index 0b104c9..0000000 --- a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/ShaderHandle.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace SlatedGameToolkit.Framework.Graphics.OpenGL -{ - public class ShaderHandle - { - private IntPtr shaderProgram; - - public ShaderHandle() { - - } - } -} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLShader.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLShader.cs new file mode 100644 index 0000000..60e1d8d --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLShader.cs @@ -0,0 +1,42 @@ +using System; +using System.Runtime.InteropServices; +using SDL2; +using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.Window; + +namespace SlatedGameToolkit.Framework.Graphics.OpenGL.Shaders +{ + public abstract class GLShader : IDisposable { + private WindowContext context; + public UIntPtr Handle { get; private protected set; } + + private protected GLCreateShader createShader; + private protected GLShaderSource shaderSource; + private protected GLCompileShader compileShader; + private protected GLGetShaderLogInfo getShaderLogInfo; + private protected GLDeleteShader deleteShader; + + public GLShader(WindowContext context) { + context.MakeCurrent(); + createShader = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glCreateShader")); + if (createShader == null) throw new FrameworkSDLException(); + shaderSource = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glShaderSource")); + if (shaderSource == null) throw new FrameworkSDLException(); + compileShader = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glCompileShader")); + if (compileShader == null) throw new FrameworkSDLException(); + getShaderLogInfo = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glGetShaderLogInfo")); + if(getShaderLogInfo == null) throw new FrameworkSDLException(); + deleteShader = Marshal.GetDelegateForFunctionPointer(SDL.SDL_GL_GetProcAddress("glDeleteShader")); + if (deleteShader == null) throw new FrameworkSDLException(); + + } + + public virtual void Dispose() + { + } + + ~GLShader() { + Dispose(); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLVertexShader.cs b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLVertexShader.cs new file mode 100644 index 0000000..2151fda --- /dev/null +++ b/src/SlatedGameToolkit.Framework/Graphics/OpenGL/Shaders/GLVertexShader.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; +using SDL2; +using SlatedGameToolkit.Framework.Exceptions; +using SlatedGameToolkit.Framework.Graphics.Window; + +namespace SlatedGameToolkit.Framework.Graphics.OpenGL.Shaders +{ + public class GLVertexShader : GLShader { + public GLVertexShader(WindowContext context, string shader) : base(context) { + Handle = createShader(GLEnums.GL_VERTEX_SHADER); + shaderSource(Handle, 1, shader, null); + compileShader(Handle); + uint logLength; + string shaderLog; + getShaderLogInfo(Handle, 1024, out logLength, out shaderLog); + if (logLength > 0) { + Dispose(); + throw new OpenGLException(shaderLog); + } + } + + public override void Dispose() + { + deleteShader(Handle); + } + + ~GLVertexShader() { + Dispose(); + } + } +} \ No newline at end of file diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs index 5068c27..a46f3df 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowContext.cs @@ -58,6 +58,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window internal readonly GLClear clear; internal readonly GLViewport viewport; + /// /// Whether or not to show this window. /// @@ -90,7 +91,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window IntPtr currentWindow = SDL.SDL_GL_GetCurrentWindow(); bool diff = false; if (currentContext != glContext || currentWindow != window) { - DrawToWindow(); + MakeCurrent(); diff = true; } bool vSync = SDL.SDL_GL_GetSwapInterval() != 0; @@ -102,7 +103,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window IntPtr currentWindow = SDL.SDL_GL_GetCurrentWindow(); bool diff = false; if (currentContext != glContext || currentWindow != window) { - DrawToWindow(); + MakeCurrent(); diff = true; } if (SDL.SDL_GL_SetSwapInterval(value ? -1 : 0) < 0) { @@ -296,7 +297,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window /// /// If the current context is already of this window, nothing happens. /// - internal void DrawToWindow() { + internal void MakeCurrent() { if (SDL.SDL_GL_GetCurrentContext() != glContext) { SDL.SDL_GL_MakeCurrent(window, glContext); } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowManager.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowManager.cs index 8c9b9a0..3fa909d 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowManager.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowManager.cs @@ -15,7 +15,7 @@ namespace SlatedGameToolkit.Framework.Graphics.Window existingWindows.Remove(windowHandle.WindowID); } - internal static WindowContext HandleFromID(uint ID) { + internal static WindowContext ContextFromID(uint ID) { return existingWindows[ID]; } } diff --git a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowsOption.cs b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowsOption.cs index 52fcd25..5b7a17a 100644 --- a/src/SlatedGameToolkit.Framework/Graphics/Window/WindowsOption.cs +++ b/src/SlatedGameToolkit.Framework/Graphics/Window/WindowsOption.cs @@ -1,6 +1,4 @@ -using System; using SDL2; -using SlatedGameToolkit.Framework.Exceptions; namespace SlatedGameToolkit.Framework.Graphics.Window { diff --git a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs b/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs index 62a99ee..7582b72 100644 --- a/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs +++ b/src/SlatedGameToolkit.Framework/StateSystem/Manager.cs @@ -45,10 +45,10 @@ namespace SlatedGameToolkit.Framework.StateSystem internal void render(double delta) { if (CurrentWindow != currentState.CurrentWindow) { CurrentWindow = currentState.CurrentWindow; - CurrentWindow.DrawToWindow(); + CurrentWindow.MakeCurrent(); } CurrentWindow.clearColour(backgroundColour.r, backgroundColour.g, backgroundColour.b); - CurrentWindow.clear((uint) (GLEnums.GL_COLOR_BUFFER_BIT | GLEnums.GL_DEPTH_STENCIL)); + CurrentWindow.clear(GLEnums.GL_COLOR_BUFFER_BIT | GLEnums.GL_DEPTH_STENCIL); currentState.Render(delta); CurrentWindow.SwapBuffer(); } diff --git a/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs b/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs index 69b7d3a..c6d32ae 100644 --- a/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs +++ b/src/SlatedGameToolkit.Tools/Commands/GraphicalPlaygroundCommand.cs @@ -31,7 +31,7 @@ namespace SlatedGameToolkit.Tools.Commands } else if (args[0].Equals("status")) { interactable.Tell("Running: " + GameEngine.IsRunning()); interactable.Tell("Target FPS: " + (GameEngine.targetFPS <= 0 ? "Not bounded." : GameEngine.targetFPS.ToString())); - interactable.Tell("Update Step: " + (GameEngine.UpdatesPerSecond <= 0 ? "Not bounded." : GameEngine.UpdatesPerSecond.ToString())); + interactable.Tell("Update Step: " + (GameEngine.UpdatesPerSecond <= 0 ? "Not Locked." : GameEngine.UpdatesPerSecond.ToString())); return true; } return false;