diff options
| -rw-r--r-- | Unicity.RenderTest/Program.cs | 59 | ||||
| -rw-r--r-- | Unicity.RenderTest/Unicity.RenderTest.csproj | 2 | ||||
| -rw-r--r-- | Unicity.Renderer/Camera.cs | 50 | ||||
| -rw-r--r-- | Unicity.Renderer/GraphicsRenderer.cs | 64 | ||||
| -rw-r--r-- | Unicity.Renderer/OpenTK.dll.config | 25 | ||||
| -rw-r--r-- | Unicity.Renderer/Properties/Resources.Designer.cs | 83 | ||||
| -rw-r--r-- | Unicity.Renderer/Properties/Resources.resx | 127 | ||||
| -rw-r--r-- | Unicity.Renderer/RenderWindow.cs | 78 | ||||
| -rw-r--r-- | Unicity.Renderer/Resources/fragmentShader.frag | 10 | ||||
| -rw-r--r-- | Unicity.Renderer/Resources/vertexShader.vert | 19 | ||||
| -rw-r--r-- | Unicity.Renderer/Shader.cs | 95 | ||||
| -rw-r--r-- | Unicity.Renderer/ShaderCompilationFailedException.cs | 9 | ||||
| -rw-r--r-- | Unicity.Renderer/Shapes/Rectangle.cs | 26 | ||||
| -rw-r--r-- | Unicity.Renderer/Shapes/Shape.cs | 12 | ||||
| -rw-r--r-- | Unicity.Renderer/Shapes/Triangle.cs | 59 | ||||
| -rw-r--r-- | Unicity.Renderer/Unicity.Renderer.csproj | 30 | ||||
| -rw-r--r-- | Unicity.Renderer/WindowCreationFailedException.cs | 6 | ||||
| -rw-r--r-- | Unicity.Renderer/glfw.dll | bin | 206848 -> 0 bytes | |||
| -rw-r--r-- | Unicity.Renderer/packages.config | 3 | ||||
| -rw-r--r-- | Unicity.sln | 4 |
20 files changed, 656 insertions, 105 deletions
diff --git a/Unicity.RenderTest/Program.cs b/Unicity.RenderTest/Program.cs index 0de65c1..5a3bbc5 100644 --- a/Unicity.RenderTest/Program.cs +++ b/Unicity.RenderTest/Program.cs @@ -6,27 +6,64 @@ namespace Unicity.RenderTest class Program { static RenderWindow window = null; + static Camera camera = null; static GraphicsRenderer renderer = null; - static Triangle triangle; + static Rectangle[] cube = null; static void Main(string[] args) { - using (window = new RenderWindow(400, 400, "Test123")) - using (renderer = new GraphicsRenderer(window)) + camera = new Camera(CameraProjectionMode.Perspective); + + using (window = new RenderWindow(400, 400, "Render Test")) + using (renderer = new GraphicsRenderer(window, camera)) { window.Init += Window_Init; window.Update += Window_Update; window.Render += Window_Render; + window.Destroy += Window_Destroy; - window.StartUpdateLoop(); + window.Open(); } } private static void Window_Init(object sender, System.EventArgs e) { - renderer.SetClearColor(0, 1, 0, 1); - triangle = new Triangle(0.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f); + renderer.SetClearColor(0.0f, 0.0f, 0.0f, 1.0f); + renderer.SetDrawColor(1.0f, 0.0f, 1.0f); + + cube = new Rectangle[] + { + new Rectangle(-1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f), + + new Rectangle(-1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f), + + new Rectangle(-1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, -1.0f), + + new Rectangle(-1.0f, -1.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f), + + new Rectangle(-1.0f, 1.0f, -1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f), + + new Rectangle(1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, -1.0f, -1.0f) + }; } private static void Window_Update(object sender, System.EventArgs e) @@ -37,7 +74,15 @@ namespace Unicity.RenderTest private static void Window_Render(object sender, System.EventArgs e) { renderer.ClearScreen(); - renderer.RenderShape(triangle); + renderer.DrawShapes(cube); + } + + private static void Window_Destroy(object sender, System.EventArgs e) + { + foreach (Rectangle rect in cube) + { + rect.Dispose(); + } } } } diff --git a/Unicity.RenderTest/Unicity.RenderTest.csproj b/Unicity.RenderTest/Unicity.RenderTest.csproj index 3bbc39e..556c185 100644 --- a/Unicity.RenderTest/Unicity.RenderTest.csproj +++ b/Unicity.RenderTest/Unicity.RenderTest.csproj @@ -7,7 +7,7 @@ <ProjectGuid>{0155C998-9189-4C19-8DCC-13499797C7EA}</ProjectGuid> <OutputType>Exe</OutputType> <RootNamespace>Unicity.RenderTest</RootNamespace> - <AssemblyName>Unicity.RenderTest</AssemblyName> + <AssemblyName>RenderTest</AssemblyName> <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> diff --git a/Unicity.Renderer/Camera.cs b/Unicity.Renderer/Camera.cs new file mode 100644 index 0000000..b58b571 --- /dev/null +++ b/Unicity.Renderer/Camera.cs @@ -0,0 +1,50 @@ +using OpenTK; + +namespace Unicity.Renderer +{ + public enum CameraProjectionMode + { + Ortographic, + Perspective + } + + public class Camera + { + float x = 0f; + float y = 0f; + float z = 0f; + + Matrix4 projectionMatrix = Matrix4.Identity; + + CameraProjectionMode projectionMode = CameraProjectionMode.Ortographic; + + public Camera(CameraProjectionMode projectionMode = CameraProjectionMode.Ortographic) + { + this.projectionMode = projectionMode; + } + + public void Initialize() + { + switch (projectionMode) + { + case CameraProjectionMode.Ortographic: + projectionMatrix = Matrix4.CreateOrthographic(600f, 600.0f, 0.1f, 100f); + break; + case CameraProjectionMode.Perspective: + projectionMatrix = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(45f), 1f, 0.1f, 100f); + break; + + } + } + + public void UpdateView(Shader shader) + { + Matrix4 modelMatrix = Matrix4.CreateRotationX(MathHelper.DegreesToRadians(-55.0f)); + Matrix4 viewMatrix = Matrix4.CreateTranslation(0.0f, 0.0f, -8.0f); + + shader.SetUniform("model", modelMatrix); + shader.SetUniform("view", viewMatrix); + shader.SetUniform("projection", projectionMatrix); + } + } +} diff --git a/Unicity.Renderer/GraphicsRenderer.cs b/Unicity.Renderer/GraphicsRenderer.cs index f417e14..6508a4c 100644 --- a/Unicity.Renderer/GraphicsRenderer.cs +++ b/Unicity.Renderer/GraphicsRenderer.cs @@ -1,20 +1,46 @@ -using GLFW; -using SharpGL; -using System; +using System; +using System.Text; +using OpenTK; +using OpenTK.Graphics.OpenGL4; using Unicity.Renderer.Shapes; -using static SharpGL.OpenGL; namespace Unicity.Renderer { public class GraphicsRenderer : IDisposable { - internal static OpenGL GL = new OpenGL(); - public RenderWindow window { get; } + public Camera camera = null; - public GraphicsRenderer(RenderWindow window) + Shader shader = null; + + public GraphicsRenderer(RenderWindow window, Camera camera) { this.window = window; + this.camera = camera; + + Console.WriteLine("Compiling GLSL shaders..."); + + string vertexShader = Encoding.UTF8.GetString(Properties.Resources.vertexShader); + string fragmentShader = Encoding.UTF8.GetString(Properties.Resources.fragmentShader); + shader = new Shader(vertexShader, fragmentShader); + shader.Use(); + + Console.WriteLine("Reticulating splines..."); + + GL.ClearDepth(1.0f); + GL.Enable(EnableCap.DepthTest); + GL.DepthFunc(DepthFunction.Lequal); + + camera.Initialize(); + window.Update += Window_Update; + + GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Line); + } + + private void Window_Update(object sender, EventArgs e) + { + camera.UpdateView(shader); + shader.Use(); } public void SetClearColor(float red, float green, float blue, float alpha) @@ -22,15 +48,28 @@ namespace Unicity.Renderer GL.ClearColor(red, green, blue, alpha); } - public void ClearScreen() + public void SetDrawColor(float red, float green, float blue) + { + shader.SetUniform("color", new Vector3(red, green, blue)); + } + + public void DrawShape(Shape shape) + { + shape.Draw(shader, this); + } + + public void DrawShapes(Shape[] shapes) { - Glfw.MakeContextCurrent(window.window); - GL.Clear(GL_COLOR_BUFFER_BIT); + foreach (Shape shape in shapes) + { + DrawShape(shape); + } } - public void RenderShape(Shape shape) + public void ClearScreen() { - shape.Render(); + window.window.MakeCurrent(); + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); } bool disposed = false; @@ -49,6 +88,7 @@ namespace Unicity.Renderer // Dispose of any unmanaged resources window?.Dispose(); + shader.Delete(); // Set disposed flag to true disposed = true; diff --git a/Unicity.Renderer/OpenTK.dll.config b/Unicity.Renderer/OpenTK.dll.config new file mode 100644 index 0000000..7098d39 --- /dev/null +++ b/Unicity.Renderer/OpenTK.dll.config @@ -0,0 +1,25 @@ +<configuration> + <dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/> + <dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/> + <dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/> + <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/> + <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/> + <dllmap os="linux" dll="libX11" target="libX11.so.6"/> + <dllmap os="linux" dll="libXi" target="libXi.so.6"/> + <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/> + <dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/> + <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" /> + <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" /> + <dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> + <dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/> + <dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/> + <!-- XQuartz compatibility (X11 on Mac) --> + <dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/> + <dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/> + <dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/> + <dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/> + <dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/> + <dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/> +</configuration> diff --git a/Unicity.Renderer/Properties/Resources.Designer.cs b/Unicity.Renderer/Properties/Resources.Designer.cs new file mode 100644 index 0000000..c1bc96c --- /dev/null +++ b/Unicity.Renderer/Properties/Resources.Designer.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace Unicity.Renderer.Properties { + using System; + + + /// <summary> + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// </summary> + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Unicity.Renderer.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Sucht eine lokalisierte Ressource vom Typ System.Byte[]. + /// </summary> + internal static byte[] fragmentShader { + get { + object obj = ResourceManager.GetObject("fragmentShader", resourceCulture); + return ((byte[])(obj)); + } + } + + /// <summary> + /// Sucht eine lokalisierte Ressource vom Typ System.Byte[]. + /// </summary> + internal static byte[] vertexShader { + get { + object obj = ResourceManager.GetObject("vertexShader", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/Unicity.Renderer/Properties/Resources.resx b/Unicity.Renderer/Properties/Resources.resx new file mode 100644 index 0000000..093fbf3 --- /dev/null +++ b/Unicity.Renderer/Properties/Resources.resx @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="fragmentShader" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\fragmentShader.frag;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </data> + <data name="vertexShader" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\vertexShader.vert;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </data> +</root>
\ No newline at end of file diff --git a/Unicity.Renderer/RenderWindow.cs b/Unicity.Renderer/RenderWindow.cs index 840d4fb..2026780 100644 --- a/Unicity.Renderer/RenderWindow.cs +++ b/Unicity.Renderer/RenderWindow.cs @@ -1,22 +1,24 @@ using System; using System.Diagnostics; using System.Drawing; -using System.IO; -using GLFW; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL4; namespace Unicity.Renderer { public class RenderWindow : IDisposable { - const int FPS = 60; + const int UPS = 60; - internal NativeWindow window = null; + internal GameWindow window = null; Stopwatch loopTimer = new Stopwatch(); public event EventHandler Init; public event EventHandler Update; public event EventHandler Render; + public event EventHandler Destroy; public int Width { @@ -36,57 +38,58 @@ namespace Unicity.Renderer set => window.Title = value; } + bool running = false; + public RenderWindow(int width, int height, string title) { - if (!File.Exists(Glfw.LIBRARY + ".dll")) - { - throw new WindowCreationFailedException("A required library file is missing and operation cannot continue."); - } - - if (!Glfw.Init()) - { - throw new WindowCreationFailedException("Failed to initialize GLFW."); - } + window = new GameWindow(width, height, GraphicsMode.Default, title, GameWindowFlags.Default); - window = new NativeWindow(width, height, title); - window.SizeChanged += Window_SizeChanged; + window.UpdateFrame += Window_UpdateFrame; + window.RenderFrame += Window_RenderFrame; + window.Unload += Window_Unload; + window.Resize += Window_Resize; } - private void Window_SizeChanged(object sender, SizeChangeEventArgs e) + private void Window_UpdateFrame(object sender, FrameEventArgs e) { - GraphicsRenderer.GL.Viewport(0, 0, Width, Height); - UpdateWindow(); + Update?.Invoke(this, EventArgs.Empty); } - public void StartUpdateLoop() + private void Window_RenderFrame(object sender, FrameEventArgs e) { - if (loopTimer.IsRunning) return; + Render?.Invoke(this, EventArgs.Empty); + window.SwapBuffers(); + } - loopTimer.Start(); + private void Window_Unload(object sender, EventArgs e) + { + Destroy?.Invoke(this, EventArgs.Empty); + } - Init?.Invoke(this, EventArgs.Empty); + private void Window_Resize(object sender, EventArgs e) + { + GL.Viewport(0, 0, Width, Height); + Render?.Invoke(this, EventArgs.Empty); + window.SwapBuffers(); + } - while (!window.IsClosed) + public void Open() + { + if (running) { - Glfw.PollEvents(); - - if (!window.IsClosing) UpdateWindow(); + return; } - loopTimer.Stop(); + Init?.Invoke(this, EventArgs.Empty); + window.VSync = VSyncMode.Off; + window.Run(UPS, 0); + + running = true; } - private void UpdateWindow() + public double GetFPS() { - if (loopTimer.Elapsed.TotalMilliseconds >= 1000 / FPS) - { - loopTimer.Restart(); - - Update?.Invoke(this, EventArgs.Empty); - Render?.Invoke(this, EventArgs.Empty); - - window.SwapBuffers(); - } + return window.RenderFrequency; } bool disposed = false; @@ -105,7 +108,6 @@ namespace Unicity.Renderer // Dispose of any unmanaged resources window?.Dispose(); - Glfw.Terminate(); // Set disposed flag to true disposed = true; diff --git a/Unicity.Renderer/Resources/fragmentShader.frag b/Unicity.Renderer/Resources/fragmentShader.frag new file mode 100644 index 0000000..a5941bd --- /dev/null +++ b/Unicity.Renderer/Resources/fragmentShader.frag @@ -0,0 +1,10 @@ +#version 330 core + +out vec4 color; + +in vec4 inColor; + +void main() +{ + color = inColor; +}
\ No newline at end of file diff --git a/Unicity.Renderer/Resources/vertexShader.vert b/Unicity.Renderer/Resources/vertexShader.vert new file mode 100644 index 0000000..330b3e0 --- /dev/null +++ b/Unicity.Renderer/Resources/vertexShader.vert @@ -0,0 +1,19 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; + +uniform mat4 model; +uniform mat4 view; +uniform mat4 projection; + +uniform vec3 color; +uniform float alpha; + +out vec4 inColor; + +void main() +{ + gl_Position = projection * view * model * vec4(vertexPosition_modelspace, 1.0); + + inColor = vec4(color, 1.0); +}
\ No newline at end of file diff --git a/Unicity.Renderer/Shader.cs b/Unicity.Renderer/Shader.cs new file mode 100644 index 0000000..76393a0 --- /dev/null +++ b/Unicity.Renderer/Shader.cs @@ -0,0 +1,95 @@ +using OpenTK; +using OpenTK.Graphics.OpenGL4; + +namespace Unicity.Renderer +{ + public class Shader + { + int id = 0; + + public Shader(string vertexShaderSource, string fragmentShaderSource) + { + int vertexShader = GL.CreateShader(ShaderType.VertexShader); + GL.ShaderSource(vertexShader, vertexShaderSource); + GL.CompileShader(vertexShader); + + int[] isCompiled = new int[1]; + GL.GetShader(vertexShader, ShaderParameter.CompileStatus, isCompiled); + if (isCompiled[0] == 0) + { + string infoLog = GL.GetShaderInfoLog(vertexShader); + GL.DeleteShader(vertexShader); + throw new ShaderCompilationFailedException("Failed to compile vertex shader:\n" + infoLog); + } + + int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); + GL.ShaderSource(fragmentShader, fragmentShaderSource); + GL.CompileShader(fragmentShader); + + GL.GetShader(fragmentShader, ShaderParameter.CompileStatus, isCompiled); + if (isCompiled[0] == 0) + { + string infoLog = GL.GetShaderInfoLog(fragmentShader); + GL.DeleteShader(fragmentShader); + GL.DeleteShader(vertexShader); + throw new ShaderCompilationFailedException("Failed to compile fragment shader:\n" + infoLog); + } + + int program = GL.CreateProgram(); + + GL.AttachShader(program, vertexShader); + GL.AttachShader(program, fragmentShader); + + GL.LinkProgram(program); + + int[] isLinked = new int[1]; + GL.GetProgram(program, GetProgramParameterName.LinkStatus, isLinked); + if (isLinked[0] == 0) + { + string infoLog = GL.GetProgramInfoLog(program); + GL.DeleteProgram(program); + GL.DeleteShader(fragmentShader); + GL.DeleteShader(vertexShader); + throw new ShaderCompilationFailedException("Failed to link shader program"); + } + + GL.DetachShader(program, vertexShader); + GL.DetachShader(program, fragmentShader); + GL.DeleteShader(vertexShader); + GL.DeleteShader(fragmentShader); + + id = program; + } + + public void Use() + { + GL.UseProgram(id); + } + + public void SetUniform(string name, Matrix4 value) + { + int uniformLocation = GL.GetUniformLocation(id, name); + + GL.UniformMatrix4(uniformLocation, false, ref value); + } + + public void SetUniform(string name, Vector3 value) + { + int uniformLocation = GL.GetUniformLocation(id, name); + + GL.Uniform3(uniformLocation, ref value); + } + + public void SetUniform(string name, float value) + { + int uniformLocation = GL.GetUniformLocation(id, name); + + GL.Uniform1(uniformLocation, value); + } + + public void Delete() + { + GL.DeleteProgram(id); + } + } +} diff --git a/Unicity.Renderer/ShaderCompilationFailedException.cs b/Unicity.Renderer/ShaderCompilationFailedException.cs new file mode 100644 index 0000000..ab40cea --- /dev/null +++ b/Unicity.Renderer/ShaderCompilationFailedException.cs @@ -0,0 +1,9 @@ +using System; + +namespace Unicity.Renderer +{ + class ShaderCompilationFailedException : Exception + { + public ShaderCompilationFailedException(string message) : base(message) { } + } +} diff --git a/Unicity.Renderer/Shapes/Rectangle.cs b/Unicity.Renderer/Shapes/Rectangle.cs new file mode 100644 index 0000000..2239426 --- /dev/null +++ b/Unicity.Renderer/Shapes/Rectangle.cs @@ -0,0 +1,26 @@ +namespace Unicity.Renderer.Shapes +{ + public class Rectangle : Shape + { + Triangle rect1 = null; + Triangle rect2 = null; + + public Rectangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4) + { + rect1 = new Triangle(x1, y1, z1, x2, y2, z2, x3, y3, z3); + rect2 = new Triangle(x3, y3, z3, x2, y2, z2, x4, y4, z4); + } + + internal override void Draw(Shader shader, GraphicsRenderer renderer) + { + rect1.Draw(shader, renderer); + rect2.Draw(shader, renderer); + } + + public override void Dispose() + { + rect1.Dispose(); + rect2.Dispose(); + } + } +} diff --git a/Unicity.Renderer/Shapes/Shape.cs b/Unicity.Renderer/Shapes/Shape.cs index b051a89..8e6e322 100644 --- a/Unicity.Renderer/Shapes/Shape.cs +++ b/Unicity.Renderer/Shapes/Shape.cs @@ -1,17 +1,17 @@ using System; -using static Unicity.Renderer.GraphicsRenderer; namespace Unicity.Renderer.Shapes { public class Shape : IDisposable { - protected uint[] buffers = new uint[1]; - - public void Dispose() + internal virtual void Draw(Shader shader, GraphicsRenderer renderer) { - GL.DeleteBuffers(1, buffers); + } - internal virtual void Render() { } + public virtual void Dispose() + { + + } } } diff --git a/Unicity.Renderer/Shapes/Triangle.cs b/Unicity.Renderer/Shapes/Triangle.cs index 2aec109..7ab94e2 100644 --- a/Unicity.Renderer/Shapes/Triangle.cs +++ b/Unicity.Renderer/Shapes/Triangle.cs @@ -1,43 +1,50 @@ -using System; -using System.Drawing; -using static Unicity.Renderer.GraphicsRenderer; -using static SharpGL.OpenGL; +using OpenTK.Graphics.OpenGL4; namespace Unicity.Renderer.Shapes { public class Triangle : Shape { - public Triangle(PointF pos1, PointF pos2, PointF pos3) - { - Init(pos1.X, pos1.Y, pos2.X, pos2.Y, pos3.X, pos3.Y); - } + int vao = 0; + int vbo = 0; - public Triangle(float x1, float y1, float x2, float y2, float x3, float y3) - { - Init(x1, y1, x2, y2, x3, y3); - } + float[] vertices = null; - private void Init(float x1, float y1, float x2, float y2, float x3, float y3) + public Triangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) { - float[] data = + vertices = new float[] { - x1, y1, - x2, y2, - x3, y3 + x1, y1, z1, + x2, y2, z2, + x3, y3, z3 }; - GL.GenBuffers(1, buffers); - GL.BindBuffer(GL_ARRAY_BUFFER, buffers[0]); - GL.BufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW); + vao = GL.GenVertexArray(); + vbo = GL.GenBuffer(); + + GL.BindVertexArray(vao); + GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); + + GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw); + + GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0); + GL.EnableVertexAttribArray(0); + } - internal override void Render() + internal override void Draw(Shader shader, GraphicsRenderer renderer) { - GL.EnableVertexAttribArray(0); - GL.BindBuffer(GL_ARRAY_BUFFER, buffers[0]); - GL.VertexAttribPointer(0, 2, GL_FLOAT, false, 0, IntPtr.Zero); - GL.DrawArrays(GL_TRIANGLES, 0, 3); - GL.DisableVertexAttribArray(0); + GL.BindVertexArray(vao); + GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); + + float[] newVertices = new float[vertices.Length]; + + GL.DrawArrays(PrimitiveType.Triangles, 0, 3); + } + + public override void Dispose() + { + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + GL.DeleteBuffer(vbo); } } } diff --git a/Unicity.Renderer/Unicity.Renderer.csproj b/Unicity.Renderer/Unicity.Renderer.csproj index 4be8ec2..e82117f 100644 --- a/Unicity.Renderer/Unicity.Renderer.csproj +++ b/Unicity.Renderer/Unicity.Renderer.csproj @@ -7,7 +7,7 @@ <ProjectGuid>{F6EBB1F8-FCA9-4A8D-A807-E877CD047908}</ProjectGuid> <OutputType>Library</OutputType> <RootNamespace>Unicity.Renderer</RootNamespace> - <AssemblyName>Unicity.Renderer</AssemblyName> + <AssemblyName>Renderer</AssemblyName> <TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> @@ -36,11 +36,8 @@ <StartupObject /> </PropertyGroup> <ItemGroup> - <Reference Include="GLFW.NET, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL"> - <HintPath>..\packages\glfw-net.3.3.1\lib\netstandard2.0\GLFW.NET.dll</HintPath> - </Reference> - <Reference Include="SharpGL, Version=2.4.1.2, Culture=neutral, PublicKeyToken=27fc851303210b27, processorArchitecture=MSIL"> - <HintPath>..\packages\SharpGL.2.4.1.2\lib\net40-client\SharpGL.dll</HintPath> + <Reference Include="OpenTK, Version=3.1.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL"> + <HintPath>..\packages\OpenTK.3.1.0\lib\net20\OpenTK.dll</HintPath> </Reference> <Reference Include="System" /> <Reference Include="System.Core" /> @@ -53,20 +50,35 @@ <Reference Include="System.Xml" /> </ItemGroup> <ItemGroup> + <Compile Include="Camera.cs" /> <Compile Include="GraphicsRenderer.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> <Compile Include="RenderWindow.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Shader.cs" /> + <Compile Include="ShaderCompilationFailedException.cs" /> + <Compile Include="Shapes\Rectangle.cs" /> <Compile Include="Shapes\Shape.cs" /> <Compile Include="Shapes\Triangle.cs" /> <Compile Include="WindowCreationFailedException.cs" /> </ItemGroup> <ItemGroup> + <None Include="OpenTK.dll.config" /> <None Include="packages.config" /> + <None Include="Resources\fragmentShader.frag" /> + <None Include="Resources\vertexShader.vert" /> </ItemGroup> <ItemGroup> - <Content Include="glfw.dll"> - <CopyToOutputDirectory>Always</CopyToOutputDirectory> - </Content> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <SubType>Designer</SubType> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> </ItemGroup> + <ItemGroup /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/Unicity.Renderer/WindowCreationFailedException.cs b/Unicity.Renderer/WindowCreationFailedException.cs index 380ffb6..322c6e5 100644 --- a/Unicity.Renderer/WindowCreationFailedException.cs +++ b/Unicity.Renderer/WindowCreationFailedException.cs @@ -1,6 +1,8 @@ -namespace Unicity.Renderer +using System; + +namespace Unicity.Renderer { - class WindowCreationFailedException : System.Exception + class WindowCreationFailedException : Exception { public WindowCreationFailedException(string message) : base(message) { diff --git a/Unicity.Renderer/glfw.dll b/Unicity.Renderer/glfw.dll Binary files differdeleted file mode 100644 index f9747a3..0000000 --- a/Unicity.Renderer/glfw.dll +++ /dev/null diff --git a/Unicity.Renderer/packages.config b/Unicity.Renderer/packages.config index a52cd52..ba26cbc 100644 --- a/Unicity.Renderer/packages.config +++ b/Unicity.Renderer/packages.config @@ -1,5 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="glfw-net" version="3.3.1" targetFramework="net472" /> - <package id="SharpGL" version="2.4.1.2" targetFramework="net472" /> + <package id="OpenTK" version="3.1.0" targetFramework="net472" /> </packages>
\ No newline at end of file diff --git a/Unicity.sln b/Unicity.sln index a423de1..edd6888 100644 --- a/Unicity.sln +++ b/Unicity.sln @@ -3,10 +3,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29418.71 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unicity.Renderer", "Unicity.Renderer\Unicity.Renderer.csproj", "{F6EBB1F8-FCA9-4A8D-A807-E877CD047908}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unicity.RenderTest", "Unicity.RenderTest\Unicity.RenderTest.csproj", "{0155C998-9189-4C19-8DCC-13499797C7EA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unicity.Renderer", "Unicity.Renderer\Unicity.Renderer.csproj", "{F6EBB1F8-FCA9-4A8D-A807-E877CD047908}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU |
