103 lines
3.7 KiB
C#
103 lines
3.7 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Numerics;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using static OpenGL.GL;
|
|
|
|
namespace OpenGLTutorial.Rendering.Shaders {
|
|
public class Shader {
|
|
private readonly string _vertexCode;
|
|
private readonly string _fragmentCode;
|
|
private bool _loaded = false;
|
|
|
|
public uint Program { get; private set; }
|
|
|
|
public Shader(string vertexPath, string fragmentPath) {
|
|
using (var vertexReader = new StreamReader(vertexPath, Encoding.UTF8))
|
|
_vertexCode = vertexReader.ReadToEnd();
|
|
|
|
using (var fragmentReader = new StreamReader(fragmentPath, Encoding.UTF8))
|
|
_fragmentCode = fragmentReader.ReadToEnd();
|
|
}
|
|
|
|
public Shader(string shader, bool isFile = true) {
|
|
using var reader = isFile ? new StreamReader(shader, Encoding.UTF8) : null;
|
|
string source = isFile ? reader.ReadToEnd() : shader;
|
|
|
|
string[] splitString = Regex.Split(source, "(#type [a-zA-Z]+)");
|
|
string firstPattern = splitString[1].Replace("#type ", "").Trim();
|
|
string secondPattern = splitString[3].Replace("#type ", "").Trim();
|
|
|
|
if (firstPattern.ToLower().Equals("vertex"))
|
|
_vertexCode = splitString[2];
|
|
else if (firstPattern.ToLower().Equals("fragment"))
|
|
_fragmentCode = splitString[2];
|
|
else throw new IOException("Unexpected token '" + firstPattern + "' in '" + shader + "'");
|
|
|
|
if (secondPattern.ToLower().Equals("vertex"))
|
|
_vertexCode = splitString[4];
|
|
else if (secondPattern.ToLower().Equals("fragment"))
|
|
_fragmentCode = splitString[4];
|
|
else throw new IOException("Unexpected token '" + secondPattern + "' in '" + shader + "'");
|
|
}
|
|
|
|
public void Load() {
|
|
if (_loaded) return;
|
|
_loaded = true;
|
|
uint vs = glCreateShader(GL_VERTEX_SHADER);
|
|
glShaderSource(vs, _vertexCode);
|
|
glCompileShader(vs);
|
|
|
|
int[] status = glGetShaderiv(vs, GL_COMPILE_STATUS, 1);
|
|
if (status[0] == 0) {
|
|
string error = glGetShaderInfoLog(vs);
|
|
throw new Exception("Error compiling vertex shader: " + error);
|
|
}
|
|
|
|
uint fs = glCreateShader(GL_FRAGMENT_SHADER);
|
|
glShaderSource(fs, _fragmentCode);
|
|
glCompileShader(fs);
|
|
|
|
status = glGetShaderiv(fs, GL_COMPILE_STATUS, 1);
|
|
if (status[0] == 0) {
|
|
string error = glGetShaderInfoLog(fs);
|
|
throw new Exception("Error compiling fragment shader: " + error);
|
|
}
|
|
|
|
Program = glCreateProgram();
|
|
glAttachShader(Program, vs);
|
|
glAttachShader(Program, fs);
|
|
|
|
glLinkProgram(Program);
|
|
|
|
glDetachShader(Program, vs);
|
|
glDetachShader(Program, fs);
|
|
glDeleteShader(vs);
|
|
glDeleteShader(fs);
|
|
}
|
|
|
|
public void Use() {
|
|
glUseProgram(Program);
|
|
}
|
|
|
|
public void Delete() {
|
|
glUseProgram(0);
|
|
glDeleteProgram(Program);
|
|
}
|
|
|
|
public void SetMatrix4X4(string uniformName, Matrix4x4 matrix) {
|
|
int location = glGetUniformLocation(Program, uniformName);
|
|
glUniformMatrix4fv(location, 1, false, GetMatrix4X4Values(matrix));
|
|
}
|
|
|
|
private float[] GetMatrix4X4Values(Matrix4x4 m) {
|
|
return new [] {
|
|
m.M11, m.M12, m.M13, m.M14,
|
|
m.M21, m.M22, m.M23, m.M24,
|
|
m.M31, m.M32, m.M33, m.M34,
|
|
m.M41, m.M42, m.M43, m.M44
|
|
};
|
|
}
|
|
}
|
|
} |