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);
 | |
|         }
 | |
|     }
 | |
| } |