65 lines
2.1 KiB
C#
65 lines
2.1 KiB
C#
using OpenTK.Graphics.OpenGL4;
|
|
using OpenTK.Mathematics;
|
|
|
|
namespace VoxelEngine.Rendering;
|
|
|
|
public sealed class Shader : IDisposable
|
|
{
|
|
private readonly int _handle;
|
|
private readonly Dictionary<string, int> _uniforms = new();
|
|
|
|
public Shader(string vertexPath, string fragmentPath)
|
|
{
|
|
int vertex = Shader.CompileFromFile(ShaderType.VertexShader, vertexPath);
|
|
int fragment = Shader.CompileFromFile(ShaderType.FragmentShader, fragmentPath);
|
|
|
|
this._handle = GL.CreateProgram();
|
|
GL.AttachShader(this._handle, vertex);
|
|
GL.AttachShader(this._handle, fragment);
|
|
GL.LinkProgram(this._handle);
|
|
|
|
GL.GetProgram(this._handle, GetProgramParameterName.LinkStatus, out int linked);
|
|
if (linked == 0)
|
|
throw new InvalidOperationException($"Program link failed: {GL.GetProgramInfoLog(this._handle)}");
|
|
|
|
GL.DetachShader(this._handle, vertex);
|
|
GL.DetachShader(this._handle, fragment);
|
|
GL.DeleteShader(vertex);
|
|
GL.DeleteShader(fragment);
|
|
}
|
|
|
|
public void Use() => GL.UseProgram(this._handle);
|
|
|
|
public void SetMatrix4(string name, Matrix4 value) =>
|
|
GL.UniformMatrix4(this.Location(name), true, ref value);
|
|
|
|
public void SetInt(string name, int value) =>
|
|
GL.Uniform1(this.Location(name), value);
|
|
|
|
private int Location(string name)
|
|
{
|
|
if (!this._uniforms.TryGetValue(name, out int location))
|
|
{
|
|
location = GL.GetUniformLocation(this._handle, name);
|
|
this._uniforms[name] = location;
|
|
}
|
|
return location;
|
|
}
|
|
|
|
private static int CompileFromFile(ShaderType type, string path)
|
|
{
|
|
string source = File.ReadAllText(path);
|
|
int shader = GL.CreateShader(type);
|
|
GL.ShaderSource(shader, source);
|
|
GL.CompileShader(shader);
|
|
|
|
GL.GetShader(shader, ShaderParameter.CompileStatus, out int compiled);
|
|
if (compiled == 0)
|
|
throw new InvalidOperationException($"{type} compile failed ({path}): {GL.GetShaderInfoLog(shader)}");
|
|
|
|
return shader;
|
|
}
|
|
|
|
public void Dispose() => GL.DeleteProgram(this._handle);
|
|
}
|