95 lines
3.4 KiB
C#
95 lines
3.4 KiB
C#
using Silk.NET.Maths;
|
|
using Silk.NET.OpenGL;
|
|
using System.Numerics;
|
|
|
|
namespace Nebulix.Rendering;
|
|
|
|
public class Shader
|
|
{
|
|
private readonly GL _glContext;
|
|
private readonly uint _shaderProgramId;
|
|
|
|
public Shader(GL openGLContext, string pathToVertexShader, string pathToFragmentShader)
|
|
{
|
|
_glContext = openGLContext;
|
|
var vertexCode = File.ReadAllText(pathToVertexShader);
|
|
var fragmentCode = File.ReadAllText(pathToFragmentShader);
|
|
|
|
var vertexShader = CompileShader(vertexCode, ShaderType.VertexShader);
|
|
var fragmentShader = CompileShader(fragmentCode, ShaderType.FragmentShader);
|
|
|
|
_shaderProgramId = CreateProgram(vertexShader, fragmentShader);
|
|
}
|
|
|
|
public void Use() { _glContext.UseProgram(_shaderProgramId); }
|
|
|
|
#region Set uniforms
|
|
public void SetInt(string name, int value)
|
|
{
|
|
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
|
|
}
|
|
|
|
public void SetFloat(string name, float value)
|
|
{
|
|
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
|
|
}
|
|
|
|
public unsafe void SetMatrix(string name, Matrix4x4 matrix)
|
|
{
|
|
_glContext.UniformMatrix4(_glContext.GetUniformLocation(_shaderProgramId, name), 1, false, (float*) &matrix);
|
|
}
|
|
public unsafe void SetMatrix(string name, Matrix4X4<float> matrix)
|
|
{
|
|
_glContext.UniformMatrix4(_glContext.GetUniformLocation(_shaderProgramId, name), 1, false, (float*) &matrix);
|
|
}
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
/// Compiles the given shadercode.
|
|
/// </summary>
|
|
/// <param name="shaderCode">The shadercode</param>
|
|
/// <param name="shaderType">The type of shader to compile</param>
|
|
/// <returns>Returns the id of the compiled shader.</returns>
|
|
/// <exception cref="ShaderCompileException"></exception>
|
|
protected uint CompileShader(string shaderCode, ShaderType shaderType)
|
|
{
|
|
uint shader = _glContext.CreateShader(shaderType);
|
|
_glContext.ShaderSource(shader, shaderCode);
|
|
_glContext.CompileShader(shader);
|
|
|
|
_glContext.GetShader(shader, ShaderParameterName.CompileStatus, out int status);
|
|
|
|
if (status != (int)GLEnum.True)
|
|
throw new ShaderCompileException(shaderType, $"Failed to compile shader with message: \n {_glContext.GetShaderInfoLog(shader)}");
|
|
|
|
return shader;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a shader program and links the vertex and fragment shader together.
|
|
/// </summary>
|
|
/// <returns>Returns the id of the created shader program</returns>
|
|
/// <exception cref="ShaderLinkException"></exception>
|
|
protected uint CreateProgram(uint vertexShader, uint fragmentShader)
|
|
{
|
|
uint program = _glContext.CreateProgram();
|
|
_glContext.AttachShader(program, vertexShader);
|
|
_glContext.AttachShader(program, fragmentShader);
|
|
_glContext.LinkProgram(program);
|
|
|
|
_glContext.GetProgram(program, ProgramPropertyARB.LinkStatus, out int lStatus);
|
|
if (lStatus != (int)GLEnum.True)
|
|
throw new ShaderLinkException("Error occured while trying to link a shader with message: \n" + _glContext.GetProgramInfoLog(program));
|
|
|
|
// should be done right after compiling and linking
|
|
_glContext.DetachShader(program, vertexShader);
|
|
_glContext.DetachShader(program, fragmentShader);
|
|
_glContext.DeleteShader(vertexShader);
|
|
_glContext.DeleteShader(fragmentShader);
|
|
|
|
return program;
|
|
}
|
|
|
|
}
|