Files
VoxelEngine/Rendering/Shader.cs
MDietermann 689536348b feat(rendering): on-screen debug overlay showing current biome and coordinates
Asset-free bitmap-text overlay: a 5x7 font (glyphs defined as verifiable ASCII-art) drawn as solid quads through a tiny 2D shader, white text with a drop shadow for legibility over any background. Renders 'BIOME: <name>' and 'XYZ: x, y, z' top-left, updating live. Adds Shader.SetVector2 and WorldGenerator.BiomeNameAt support; text scale and spawn-height offset read from Configuration.
2026-06-03 16:27:15 +02:00

72 lines
2.4 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 = CompileFromFile(ShaderType.VertexShader, vertexPath);
int fragment = 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);
public void SetFloat(string name, float value) =>
GL.Uniform1(this.Location(name), value);
public void SetVector3(string name, Vector3 value) =>
GL.Uniform3(this.Location(name), value.X, value.Y, value.Z);
public void SetVector2(string name, Vector2 value) =>
GL.Uniform2(this.Location(name), value.X, value.Y);
private int Location(string name)
{
if (this._uniforms.TryGetValue(name, out int location)) return 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);
}