189 lines
6.8 KiB
C#
189 lines
6.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using Quik.OpenGL;
|
|
using Quik.VertexGenerator;
|
|
using Matrix4 = OpenTK.Mathematics.Matrix4;
|
|
using static Quik.OpenGL.GLEnum;
|
|
|
|
namespace Quik.OpenTK
|
|
{
|
|
public class GL30Driver : IDisposable
|
|
{
|
|
public GL30Driver()
|
|
{
|
|
Assembly asm = typeof(GL30Driver).Assembly;
|
|
|
|
using (StreamReader vert = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.vert")))
|
|
using (StreamReader frag = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.frag")))
|
|
{
|
|
int vs;
|
|
int fs;
|
|
|
|
vs = GL.CreateShader(GL_VERTEX_SHADER);
|
|
fs = GL.CreateShader(GL_FRAGMENT_SHADER);
|
|
|
|
_sp = GL.CreateProgram();
|
|
|
|
GL.ShaderSource(vs, vert.ReadToEnd());
|
|
GL.ShaderSource(fs, frag.ReadToEnd());
|
|
|
|
GL.CompileShader(vs);
|
|
GL.CompileShader(fs);
|
|
|
|
#if DEBUG
|
|
int status;
|
|
|
|
GL.GetShader(vs, GL_COMPILE_STATUS, out status);
|
|
if (status == 0)
|
|
{
|
|
throw new Exception(GL.GetShaderInfoLog(vs));
|
|
}
|
|
|
|
GL.GetShader(fs, GL_COMPILE_STATUS, out status);
|
|
if (status == 0)
|
|
{
|
|
throw new Exception(GL.GetShaderInfoLog(fs));
|
|
}
|
|
#endif
|
|
|
|
GL.AttachShader(_sp, vs);
|
|
GL.AttachShader(_sp, fs);
|
|
|
|
GL.LinkProgram(_sp);
|
|
|
|
#if DEBUG
|
|
GL.GetProgram(_sp, GL_LINK_STATUS, out status);
|
|
if (status == 0)
|
|
{
|
|
throw new Exception(GL.GetProgramInfoLog(_sp));
|
|
}
|
|
#endif
|
|
|
|
GL.DetachShader(_sp, vs);
|
|
GL.DetachShader(_sp, fs);
|
|
GL.DeleteShader(vs);
|
|
GL.DeleteShader(fs);
|
|
}
|
|
|
|
LoadUniform(_nameM4View, out _locM4View);
|
|
LoadUniform(_nameM4Model, out _locM4Model);
|
|
LoadUniform(_nameIFlags, out _locIFlags);
|
|
LoadUniform(_nameFSdfThreshold, out _locFSdfThreshold);
|
|
LoadUniform(_nameFSdfAuxilliaryThreshold, out _locFSdfAuxilliaryThreshold);
|
|
LoadUniform(_nameV4SdfAuxilliaryColor, out _locV4SdfAuxilliaryColor);
|
|
LoadUniform(_nameX2Texture, out _locX2Texture);
|
|
LoadUniform(_nameV2TextureOffset, out _locV2TextureOffset);
|
|
|
|
LoadAttribute(_nameV2Postion, out _locV2Position);
|
|
LoadAttribute(_nameV2Texture, out _locV2Texture);
|
|
LoadAttribute(_nameV4Color, out _locV4Color);
|
|
|
|
void LoadUniform(string name, out int location)
|
|
{
|
|
location = GL.GetUniformLocation(_sp, name);
|
|
}
|
|
|
|
void LoadAttribute(string name, out int location)
|
|
{
|
|
location = GL.GetAttribLocation(_sp, name);
|
|
}
|
|
|
|
_vbo = GL.GenBuffer();
|
|
_ebo = GL.GenBuffer();
|
|
_vao = GL.GenVertexArray();
|
|
}
|
|
|
|
private readonly int _sp;
|
|
private readonly int _vao;
|
|
private readonly int _vbo;
|
|
private readonly int _ebo;
|
|
|
|
private const string _nameM4View = "m4View";
|
|
private readonly int _locM4View;
|
|
private const string _nameM4Model = "m4Model";
|
|
private readonly int _locM4Model;
|
|
private const string _nameV2Postion = "v2Position";
|
|
private readonly int _locV2Position;
|
|
private const string _nameV2Texture = "v2Texture";
|
|
private readonly int _locV2Texture;
|
|
private const string _nameV4Color = "v4Color";
|
|
private readonly int _locV4Color;
|
|
private const string _nameIFlags = "iFlags";
|
|
private readonly int _locIFlags;
|
|
private const string _nameFSdfThreshold = "fSdfThreshold";
|
|
private readonly int _locFSdfThreshold;
|
|
private const string _nameFSdfAuxilliaryThreshold = "fSdfAuxilliaryThreshold";
|
|
private readonly int _locFSdfAuxilliaryThreshold;
|
|
private const string _nameV4SdfAuxilliaryColor = "v4SdfAuxilliaryColor";
|
|
private readonly int _locV4SdfAuxilliaryColor;
|
|
private const string _nameX2Texture = "x2Texture";
|
|
private readonly int _locX2Texture;
|
|
private const string _nameV2TextureOffset = "v2TextureOffset";
|
|
private readonly int _locV2TextureOffset;
|
|
|
|
[Flags]
|
|
private enum Flags : int
|
|
{
|
|
Texture = 1 << 0,
|
|
DiscardEnable = 1 << 1,
|
|
Sdf = 1 << 2,
|
|
SdfAuxEnable = 1 << 3,
|
|
}
|
|
|
|
public void Draw(DrawQueue queue)
|
|
{
|
|
GL.UseProgram(_sp);
|
|
GL.BindVertexArray(_vao);
|
|
|
|
GL.BindBuffer(GL_ARRAY_BUFFER, _vbo);
|
|
GL.BufferData(GL_ARRAY_BUFFER, queue.VertexCount * QuikVertex.Stride, queue.VertexArray, GL_STREAM_DRAW);
|
|
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
|
|
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, queue.ElementCount * sizeof(int), queue.ElementArray, GL_STREAM_DRAW);
|
|
|
|
GL.VertexAttribPointer(_locV2Position, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.PositionOffset);
|
|
GL.VertexAttribPointer(_locV2Texture, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.TextureCoordinatesOffset);
|
|
GL.VertexAttribPointer(_locV4Color, 4, GL_UNSIGNED_BYTE, false, QuikVertex.Stride, QuikVertex.ColorOffset);
|
|
GL.EnableVertexAttribArray(_locV2Position);
|
|
GL.EnableVertexAttribArray(_locV2Texture);
|
|
GL.EnableVertexAttribArray(_locV4Color);
|
|
|
|
GL.Enable(GL_BLEND);
|
|
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
Matrix4 m = Matrix4.Identity;
|
|
GL.UniformMatrix4(_locM4Model, false, ref m.Row0.X);
|
|
|
|
foreach (DrawCall call in queue)
|
|
{
|
|
GL.BindTexture(GL_TEXTURE_2D, 0);
|
|
m = Matrix4.CreateOrthographicOffCenter(0, call.Bounds.Right, 0, call.Bounds.Top, 1.0f, -1.0f);
|
|
GL.UniformMatrix4(_locM4View, false, ref m.Row0.X);
|
|
GL.DrawElements(GL_TRIANGLES, call.Count, GL_UNSIGNED_INT, call.Start);
|
|
}
|
|
}
|
|
|
|
private bool _isDisposed = false;
|
|
private void Dispose(bool disposing)
|
|
{
|
|
if (_isDisposed) return;
|
|
|
|
if (disposing)
|
|
{
|
|
GL.DeleteProgram(_sp);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("OpenGL resource is leaked. Dispose unreferenced OpenGL objects in the context thread.");
|
|
}
|
|
|
|
_isDisposed = true;
|
|
}
|
|
|
|
public void Dispose() => Dispose(true);
|
|
~GL30Driver()
|
|
{
|
|
Dispose(false);
|
|
}
|
|
}
|
|
} |