229 lines
11 KiB
C#
229 lines
11 KiB
C#
using System.Drawing;
|
|
using System.Numerics;
|
|
using System.Runtime.InteropServices;
|
|
using Dashboard.Drawing;
|
|
using Dashboard.Pal;
|
|
using OpenTK.Graphics.OpenGL;
|
|
|
|
namespace Dashboard.OpenGL.Drawing
|
|
{
|
|
public class ImmediateMode : IImmediateMode
|
|
{
|
|
public string DriverName => "Dashboard OpenGL Immediate Mode";
|
|
public string DriverVendor => "Dashboard";
|
|
public Version DriverVersion { get; } = new Version(1, 0);
|
|
|
|
public DeviceContext Context { get; private set; } = null!;
|
|
|
|
private int _program;
|
|
private uint _program_apos;
|
|
private uint _program_atexcoord;
|
|
private uint _program_acolor;
|
|
private int _program_transforms;
|
|
private int _program_image;
|
|
private int _vao;
|
|
private int _white;
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
public void Require(DeviceContext context)
|
|
{
|
|
Context = context;
|
|
|
|
_program = GL.CreateProgram();
|
|
|
|
int vs = GL.CreateShader(ShaderType.VertexShader);
|
|
|
|
using (StreamReader reader = new StreamReader(GetType().Assembly
|
|
.GetManifestResourceStream("Dashboard.OpenGL.Drawing.immediate.vert")!))
|
|
{
|
|
GL.ShaderSource(vs, reader.ReadToEnd());
|
|
}
|
|
GL.CompileShader(vs);
|
|
GL.AttachShader(_program, vs);
|
|
|
|
int fs = GL.CreateShader(ShaderType.FragmentShader);
|
|
|
|
using (StreamReader reader = new StreamReader(GetType().Assembly
|
|
.GetManifestResourceStream("Dashboard.OpenGL.Drawing.immediate.frag")!))
|
|
{
|
|
GL.ShaderSource(fs, reader.ReadToEnd());
|
|
}
|
|
|
|
GL.CompileShader(fs);
|
|
GL.AttachShader(_program, fs);
|
|
|
|
GL.LinkProgram(_program);
|
|
GL.DeleteShader(vs); GL.DeleteShader(fs);
|
|
|
|
_program_apos = (uint)GL.GetAttribLocation(_program, "aPos");
|
|
_program_atexcoord = (uint)GL.GetAttribLocation(_program, "aTexCoords");
|
|
_program_acolor = (uint)GL.GetAttribLocation(_program, "aColor");
|
|
|
|
_program_transforms = GL.GetUniformLocation(_program, "transforms");
|
|
_program_image = GL.GetUniformLocation(_program, "image");
|
|
|
|
GL.GenTexture(out _white);
|
|
GL.BindTexture(TextureTarget.Texture2d, _white);
|
|
GL.TexImage2D(TextureTarget.Texture2d, 0, InternalFormat.Rgb, 1, 1, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgb, PixelType.Byte, IntPtr.Zero);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleA, (int)All.One);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleR, (int)All.One);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleG, (int)All.One);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureSwizzleB, (int)All.One);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
|
|
GL.TexParameteri(TextureTarget.Texture2d, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
|
|
|
|
GL.GenVertexArray(out _vao);
|
|
}
|
|
|
|
public void ClearColor(Color color)
|
|
{
|
|
GL.ClearColor(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
|
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|
}
|
|
|
|
public void Line(Vector2 a, Vector2 b, float width, float depth, Vector4 color)
|
|
{
|
|
Vector2 normal = Vector2.Normalize(b - a);
|
|
Vector2 tangent = new Vector2(-normal.Y, normal.X) * width;
|
|
Span<ImmediateVertex> vertices =
|
|
[
|
|
new ImmediateVertex(new Vector3(a-tangent, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(b-tangent, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(b+tangent, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(a-tangent, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(b+tangent, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(a+tangent, depth), Vector2.Zero, color),
|
|
];
|
|
|
|
int buffer = GL.GenBuffer();
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
|
|
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
|
|
|
|
GL.BindVertexArray(_vao);
|
|
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
|
|
GL.EnableVertexAttribArray(_program_apos);
|
|
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
|
|
GL.EnableVertexAttribArray(_program_atexcoord);
|
|
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
|
|
GL.EnableVertexAttribArray(_program_acolor);
|
|
|
|
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
Matrix4x4 view = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
|
|
GL.UseProgram(_program);
|
|
|
|
GL.ActiveTexture(TextureUnit.Texture0);
|
|
GL.BindTexture(TextureTarget.Texture2d, _white);
|
|
|
|
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
|
|
GL.Uniform1i(_program_image, 0);
|
|
|
|
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
|
|
|
|
GL.DeleteBuffer(buffer);
|
|
}
|
|
|
|
public void Rectangle(Box2d rectangle, float depth, Vector4 color)
|
|
{
|
|
Span<ImmediateVertex> vertices =
|
|
[
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Min.Y, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), Vector2.Zero, color),
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Max.Y, depth), Vector2.Zero, color),
|
|
];
|
|
|
|
int buffer = GL.GenBuffer();
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
|
|
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
|
|
|
|
GL.BindVertexArray(_vao);
|
|
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
|
|
GL.EnableVertexAttribArray(_program_apos);
|
|
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
|
|
GL.EnableVertexAttribArray(_program_atexcoord);
|
|
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
|
|
GL.EnableVertexAttribArray(_program_acolor);
|
|
|
|
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
Matrix4x4 view = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
|
|
GL.UseProgram(_program);
|
|
|
|
GL.ActiveTexture(TextureUnit.Texture0);
|
|
GL.BindTexture(TextureTarget.Texture2d, _white);
|
|
|
|
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
|
|
GL.Uniform1i(_program_image, 0);
|
|
|
|
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
|
|
|
|
GL.DeleteBuffer(buffer);
|
|
}
|
|
|
|
public void Image(Box2d rectangle, Box2d uv, float depth, ITexture texture)
|
|
{
|
|
Span<ImmediateVertex> vertices =
|
|
[
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), new Vector2(uv.Min.X, uv.Min.Y), Vector4.One),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Min.Y, depth), new Vector2(uv.Max.X, uv.Min.Y), Vector4.One),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), new Vector2(uv.Max.X, uv.Max.Y), Vector4.One),
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Min.Y, depth), new Vector2(uv.Min.X, uv.Min.Y), Vector4.One),
|
|
new ImmediateVertex(new Vector3(rectangle.Max.X, rectangle.Max.Y, depth), new Vector2(uv.Max.X, uv.Max.Y), Vector4.One),
|
|
new ImmediateVertex(new Vector3(rectangle.Min.X, rectangle.Max.Y, depth), new Vector2(uv.Min.X, uv.Max.Y), Vector4.One),
|
|
];
|
|
|
|
int buffer = GL.GenBuffer();
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, buffer);
|
|
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * ImmediateVertex.Size, ref vertices[0], BufferUsage.StreamDraw);
|
|
|
|
GL.BindVertexArray(_vao);
|
|
GL.VertexAttribPointer(_program_apos, 3, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.PosOffset);
|
|
GL.EnableVertexAttribArray(_program_apos);
|
|
GL.VertexAttribPointer(_program_atexcoord, 2, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.TexCoordsOffset);
|
|
GL.EnableVertexAttribArray(_program_atexcoord);
|
|
GL.VertexAttribPointer(_program_acolor, 4, VertexAttribPointerType.Float, false, ImmediateVertex.Size, ImmediateVertex.ColorOffset);
|
|
GL.EnableVertexAttribArray(_program_acolor);
|
|
Size size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
Matrix4x4 view = Context.ExtensionRequire<IDeviceContextBase>().Transforms;
|
|
|
|
GL.UseProgram(_program);
|
|
|
|
GL.ActiveTexture(TextureUnit.Texture0);
|
|
GL.BindTexture(TextureTarget.Texture2d, ((GLTexture)texture).Handle);
|
|
|
|
GL.UniformMatrix4f(_program_transforms, 1, true, ref view);
|
|
GL.Uniform1i(_program_image, 0);
|
|
|
|
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
|
|
|
|
GL.DeleteBuffer(buffer);
|
|
}
|
|
|
|
IContextBase IContextExtensionBase.Context => Context;
|
|
|
|
void IContextExtensionBase.Require(IContextBase context)
|
|
{
|
|
Require((DeviceContext)context);
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit, Pack = sizeof(float) * 4, Size = Size)]
|
|
private struct ImmediateVertex(Vector3 position, Vector2 texCoords, Vector4 color)
|
|
{
|
|
[FieldOffset(PosOffset)] public Vector3 Position = position;
|
|
[FieldOffset(TexCoordsOffset)] public Vector2 TexCoords = texCoords;
|
|
[FieldOffset(ColorOffset)] public Vector4 Color = color;
|
|
|
|
public const int Size = 16 * sizeof(float);
|
|
public const int PosOffset = 0 * sizeof(float);
|
|
public const int TexCoordsOffset = 4 * sizeof(float);
|
|
public const int ColorOffset = 8 * sizeof(float);
|
|
}
|
|
}
|
|
}
|