using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; namespace Voxel { public class Shader { private int _handle; private bool disposedValue = false; public Shader(string vertexPath, string fragmentPath) { string vertexShaderSource = File.ReadAllText(vertexPath); string fragmentShaderSource = File.ReadAllText(fragmentPath); int vertexShader = GL.CreateShader(ShaderType.VertexShader); int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(vertexShader, vertexShaderSource); GL.ShaderSource(fragmentShader, fragmentShaderSource); GL.CompileShader(vertexShader); GL.GetShader(vertexShader, ShaderParameter.CompileStatus, out int success); if (success == 0) { string infoLog = GL.GetShaderInfoLog(vertexShader); Console.WriteLine(infoLog); } GL.CompileShader(fragmentShader); if (success == 0) { string infoLog = GL.GetShaderInfoLog(fragmentShader); Console.WriteLine(infoLog); } // attach _handle = GL.CreateProgram(); GL.AttachShader(_handle, vertexShader); GL.AttachShader(_handle, fragmentShader); GL.LinkProgram(_handle); GL.GetProgram(_handle, GetProgramParameterName.LinkStatus, out success); if (success == 0) { string infoLog = GL.GetProgramInfoLog(_handle); Console.WriteLine(infoLog); } GL.DetachShader(_handle, vertexShader); GL.DetachShader(_handle, fragmentShader); GL.DeleteShader(fragmentShader); GL.DeleteShader(vertexShader); } public void SetMatrix4(string name, Matrix4 matrix) { int location = GL.GetUniformLocation(_handle, name); if (location == -1) { Console.WriteLine($"Uniform '{name}' not found in shader."); return; } GL.UniformMatrix4(location, false, ref matrix); } public void SetVector3(string name, Vector3 vector3) { int location = GL.GetUniformLocation(_handle, name); if (location == -1) { Console.WriteLine($"Uniform '{name}' not found in shader."); return; } GL.Uniform3(location, ref vector3); } public void SetInt(string name, int value) { int location = GL.GetUniformLocation(_handle, name); if (location == -1) { Console.WriteLine($"Uniform '{name}' not found in shader."); return; } GL.Uniform1(location, value); } public void Use() { GL.UseProgram(_handle); } protected virtual void Dispose(bool disposing) { if (!disposedValue) { GL.DeleteProgram(_handle); disposedValue = true; } } ~Shader() { if (disposedValue == false) { Console.WriteLine("GPU Resource leak! Did you forget to call Dispose()?"); } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } } }