Open DeroXP opened 1 year ago
using System; using System.Collections.Generic; using System.IO; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; namespace Gepe3D { /* This whole class came from the OpenTK tutorial repository, pls dont come after me */ public class Shader { public readonly int Handle; private readonly Dictionary<string, int> _uniformLocations; public Shader(string vertPath, string fragPath) { vertPath = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), vertPath); fragPath = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), fragPath); string vertexShaderSource = File.ReadAllText(vertPath); string fragmentShaderSource = File.ReadAllText(fragPath); int vertexShader = CompileShader(ShaderType.VertexShader, vertexShaderSource); int fragmentShader = CompileShader(ShaderType.FragmentShader, fragmentShaderSource); Handle = LinkProgram(vertexShader, fragmentShader); _uniformLocations = new Dictionary<string, int>(); ExtractUniformLocations(); } private int CompileShader(ShaderType type, string source) { int shader = GL.CreateShader(type); GL.ShaderSource(shader, source); GL.CompileShader(shader); GL.GetShader(shader, ShaderParameter.CompileStatus, out var code); if (code != (int)All.True) { var infoLog = GL.GetShaderInfoLog(shader); throw new Exception($"Error occurred while compiling {type} shader.\n\n{infoLog}"); } return shader; } private int LinkProgram(int vertexShader, int fragmentShader) { int program = GL.CreateProgram(); GL.AttachShader(program, vertexShader); GL.AttachShader(program, fragmentShader); GL.LinkProgram(program); GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var code); if (code != (int)All.True) { throw new Exception($"Error occurred while linking the program."); } GL.DetachShader(program, vertexShader); GL.DetachShader(program, fragmentShader); GL.DeleteShader(fragmentShader); GL.DeleteShader(vertexShader); return program; } private void ExtractUniformLocations() { GL.GetProgram(Handle, GetProgramParameterName.ActiveUniforms, out var numberOfUniforms); for (int i = 0; i < numberOfUniforms; i++) { string key = GL.GetActiveUniform(Handle, i, out _, out _); int location = GL.GetUniformLocation(Handle, key); _uniformLocations.Add(key, location); } } public void Use() { GL.UseProgram(Handle); } public int GetAttribLocation(string attribName) { return GL.GetAttribLocation(Handle, attribName); } public void SetInt(string name, int data) { GL.UseProgram(Handle); GL.Uniform1(_uniformLocations[name], data); } public void SetBool(string name, bool flag) { GL.UseProgram(Handle); GL.Uniform1(_uniformLocations[name], flag ? 1 : 0); } public void SetFloat(string name, float data) { GL.UseProgram(Handle); GL.Uniform1(_uniformLocations[name], data); } public void SetMatrix4(string name, Matrix4 data) { GL.UseProgram(Handle); GL.UniformMatrix4(_uniformLocations[name], true, ref data); } public void SetMatrix3(string name, Matrix3 data) { GL.UseProgram(Handle); GL.UniformMatrix3(_uniformLocations[name], true, ref data); } public void SetVector3(string name, Vector3 data) { GL.UseProgram(Handle); GL.Uniform3(_uniformLocations[name], data); } public void SetVector4(string name, Vector4 data) { GL.UseProgram(Handle); GL.Uniform4(_uniformLocations[name], data); } } }