acdream/src/AcDream.App/Rendering/Shader.cs
Erik ff325abd7b feat(ui): debug overlay + refined input controls
Adds the first on-screen HUD for the dev client plus today's mouse-control
refinements. Also lands yesterday's scenery-alignment changes that were
left uncommitted in the working tree.

Overlay:
- BitmapFont rasterizes a system TTF via StbTrueTypeSharp into a 512x512
  R8 atlas at startup (Consolas on Windows, DejaVu/Menlo fallbacks)
- TextRenderer batches 2D quads in screen-space with ortho projection;
  one shader + two draw calls (rect then text) for panel backgrounds
  under glyphs
- DebugOverlay composes info / stats / compass / help panels on top of
  the 3D scene; toggles via F1/F4/F5/F6; transient toasts for key events
- DebugLineRenderer and its shaders (carried over from the scenery work)
  are properly committed in this commit

Controls:
- Per-mode mouse sensitivity (Chase 0.15, Fly 1.0, Orbit 1.0); F8/F9 to
  adjust the active mode multiplicatively (x1.2)
- Hold RMB to free-orbit the chase camera around the player; release
  stays at the new angle (no snap-back)
- Mouse-wheel zooms chase distance between 2m and 40m
- Chase pitch widened to [-0.7, 1.4] so mouse-Y tilts both ways from
  the default neutral angle

Scenery alignment (carried from yesterday's session):
- ShadowObjectRegistry AllEntriesForDebug + Scale field
- SceneryGenerator uses ACViewer's OnRoad polygon test + baseLoc +
  set_heading rotation
- BSPQuery dispatchers accept localToWorld so normals/offsets transform
  correctly per part
- TransitionTypes.CylinderCollision rewritten with wall-slide + push-out
- PhysicsDataCache caches visual-mesh AABB for scenery that lacks
  physics Setup bounds
2026-04-17 18:45:38 +02:00

80 lines
2.4 KiB
C#

using System.Numerics;
using Silk.NET.OpenGL;
namespace AcDream.App.Rendering;
public sealed class Shader : IDisposable
{
private readonly GL _gl;
public uint Program { get; }
public Shader(GL gl, string vertexPath, string fragmentPath)
{
_gl = gl;
uint vert = Compile(File.ReadAllText(vertexPath), ShaderType.VertexShader);
uint frag = Compile(File.ReadAllText(fragmentPath), ShaderType.FragmentShader);
Program = _gl.CreateProgram();
_gl.AttachShader(Program, vert);
_gl.AttachShader(Program, frag);
_gl.LinkProgram(Program);
_gl.GetProgram(Program, ProgramPropertyARB.LinkStatus, out int linked);
if (linked == 0)
throw new Exception("program link failed: " + _gl.GetProgramInfoLog(Program));
_gl.DetachShader(Program, vert);
_gl.DetachShader(Program, frag);
_gl.DeleteShader(vert);
_gl.DeleteShader(frag);
}
private uint Compile(string source, ShaderType type)
{
uint id = _gl.CreateShader(type);
_gl.ShaderSource(id, source);
_gl.CompileShader(id);
_gl.GetShader(id, ShaderParameterName.CompileStatus, out int ok);
if (ok == 0)
throw new Exception($"{type} compile failed: " + _gl.GetShaderInfoLog(id));
return id;
}
public void Use() => _gl.UseProgram(Program);
public unsafe void SetMatrix4(string name, Matrix4x4 m)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.UniformMatrix4(loc, 1, false, (float*)&m);
}
public void SetInt(string name, int value)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.Uniform1(loc, value);
}
public void SetFloat(string name, float value)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.Uniform1(loc, value);
}
public void SetVec3(string name, Vector3 v)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.Uniform3(loc, v.X, v.Y, v.Z);
}
public void SetVec2(string name, Vector2 v)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.Uniform2(loc, v.X, v.Y);
}
public void SetVec4(string name, Vector4 v)
{
int loc = _gl.GetUniformLocation(Program, name);
_gl.Uniform4(loc, v.X, v.Y, v.Z, v.W);
}
public void Dispose() => _gl.DeleteProgram(Program);
}