using System; using System.IO; using System.Reflection; using OpenTK.Graphics.OpenGL; namespace RecrownedGTK.Graphics.Render.Shaders { public class Shader : IDisposable { int handle; public bool IsDisposed { get; private set; } /// /// Creates a shader program using the given paths. /// /// The relative path to the vertex shader file. /// The relative path to the fragment shader file. /// public Shader(string pathToVertexFile, string pathToFragmentFile) : this(new StreamReader(pathToVertexFile), new StreamReader(pathToFragmentFile)) { } /// /// Creates a shader program using the given streams. /// Automatically disposes of streams immediately after use. /// /// The vertex shader file stream. /// The fragment shader file stream. public Shader(StreamReader vertexFileStream, StreamReader fragmentFileStream) { int vertShader = 0; int fragShader = 0; string vertShaderSource = vertexFileStream.ReadToEnd(); string fragShaderSource = fragmentFileStream.ReadToEnd(); fragmentFileStream.Dispose(); vertexFileStream.Dispose(); vertShader = GL.CreateShader(ShaderType.VertexShader); GL.ShaderSource(vertShader, vertShaderSource); fragShader = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(fragShader, fragShaderSource); string log; GL.CompileShader(vertShader); if ((log = GL.GetShaderInfoLog(vertShader)) != "") { throw new ArgumentException("Error while compiling vertex shader: " + log, "vertexPath"); } GL.CompileShader(fragShader); if ((log = GL.GetShaderInfoLog(fragShader)) != "") { throw new ArgumentException("Error while compiling fragment shader: " + log, "fragmentPath"); } //Creates the shader program. handle = GL.CreateProgram(); //Attaches shader to program and links it. GL.AttachShader(handle, vertShader); GL.AttachShader(handle, fragShader); GL.LinkProgram(handle); GL.DetachShader(handle, vertShader); GL.DetachShader(handle, fragShader); GL.DeleteShader(vertShader); GL.DeleteShader(fragShader); } public void Use() { GL.UseProgram(handle); } public int GetAttribLocation(string attributeName) { return GL.GetAttribLocation(handle, attributeName); } protected virtual void Dispose(bool disposing) { if (IsDisposed) { return; } if (disposing) { } GL.DeleteProgram(handle); IsDisposed = true; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~Shader() { Dispose(false); } public static Shader CreateBasicShader() { string resourceLoc = "RecrownedGTK.Graphics.Render.Shaders.{0}"; Shader shader = new Shader(new StreamReader(Utilities.ReadEmbeddedFile(String.Format(resourceLoc, "default.vert"))), new StreamReader(Utilities.ReadEmbeddedFile(String.Format(resourceLoc, "default.frag")))); return shader; } } }