After a long time, I have a basic library for handling OpenGL with no errors to my knowledge.
This commit is contained in:
Jacob Guin 2022-12-21 21:48:40 -05:00
parent a6b2fae045
commit 91db2b6471
23 changed files with 1383 additions and 0 deletions

View File

@ -0,0 +1,10 @@
namespace GraphicsManager.Enums;
public enum ObjectAnchor
{
Left = 0b_0001,
Top = 0b_0010,
Right = 0b_0100,
Bottom = 0b_1000,
All = Left | Top | Right | Bottom,
}

View File

@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Resources/**"></EmbeddedResource>
</ItemGroup>
<ItemGroup>
<PackageReference Include="OpenTK" Version="4.7.1" />
<PackageReference Include="SharpFontCore" Version="0.1.1" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="SpaceWizards.SharpFont" Version="1.0.1" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,18 @@
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
namespace GraphicsManager.Interfaces;
public interface IParent
{
public Vector2i Size { get; }
public void Resize(ResizeEventArgs e);
public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f);
public float IntToFloat(int p, bool Invert = false);
public float FloatToInt(float p, bool Invert = false);
public event Action<MouseButtonEventArgs> MouseDown;
public event Action<KeyboardKeyEventArgs> KeyDown;
public Vector2 MousePosition { get; }
public Vector2i Position { get; }
}

View File

@ -0,0 +1,23 @@
using GraphicsManager.Enums;
using OpenTK.Mathematics;
namespace GraphicsManager.Interfaces;
public interface IRenderObject
{
public ObjectAnchor Anchor { get; set; }
public bool Loaded { get; }
public void LoadToParent(IParent Parent, Window Window);
public void Draw();
public void Clean();
public Vector2i Size { get; set; }
public Vector2i Location { get; set; }
public Vector2 SizeAsFloat { get; }
public Vector2 LocationAsFloat { get; }
public Vector2i Distance { get; }
public IParent? Parent { get; }
public Window? Window { get; }
public bool Visible { get; set; }
public event Func<IRenderObject, Task>? Clicked;
}

View File

@ -0,0 +1,13 @@
using GraphicsManager.Objects.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GraphicsManager.Interfaces;
public interface ITextureObject : IRenderObject
{
public Texture? Texture { get; }
}

View File

@ -0,0 +1,59 @@
using System.Reflection;
namespace GraphicsManager.Objects.Core;
public class Font
{
public void SetEmbeddedFont(string Font, Assembly? Assembly = null)
{
_ = Font ?? throw new ArgumentNullException(nameof(Font));
this.Assembly = Assembly;
this.Embeded = true;
this.Name = Font;
}
public static Font MakeEmbeddedFont(string Font, Assembly? Assembly = null)
{
_ = Font ?? throw new ArgumentNullException(nameof(Font));
return new Font()
{
Assembly = Assembly,
Embeded = true,
Name = Font,
};
}
public static Font MakeFontFromFile(string Font)
{
_ = Font ?? throw new ArgumentNullException(nameof(Font));
return new Font()
{
Assembly = null,
Embeded = false,
Name = Font,
};
}
public void SetFontFile(string Font)
{
_ = Font ?? throw new ArgumentNullException(nameof(Font));
this.Assembly = null;
this.Embeded = false;
this.Name = Font;
}
public byte[] GetData()
{
if (Embeded)
{
string Base = "GraphicsManager.Resources.Fonts.";
if (Assembly is not null) Base = string.Empty;
return (Assembly is null ? Tools.GetResourceBytes(Base + Name) : Tools.GetResourceBytes(Assembly!, $"{Base}{Name}"));
}
return File.ReadAllBytes(Name);
}
public string Name { get; private set; } = "shal be default";
public bool Embeded { get; private set; }
public Assembly? Assembly { get; private set; }
}

View File

@ -0,0 +1,129 @@
using OpenTK.Graphics.OpenGL4;
using System.Reflection;
namespace GraphicsManager.Objects.Core;
public class Shader : IDisposable
{
public int Handle { get; }
private readonly int VertexShader;
private readonly int FragmentShader;
private bool disposedValue = false;
public Shader(string VertexShaderSource, string FragmentShaderSource, bool VertextBuiltIn = false, bool FragmentShaderBuiltIn = false, Assembly? Assembly = null)
{
VertexShader = GL.CreateShader(ShaderType.VertexShader);
string Base = "GraphicsManager.Resources.Shaders.";
if (Assembly is not null) Base = string.Empty;
string vss = (VertextBuiltIn ? Tools.GetResourceString((Assembly == null ? typeof(Tools).Assembly : Assembly), $"{Base}{VertexShaderSource}") : File.ReadAllText(VertexShaderSource))!;
string fss = (FragmentShaderBuiltIn ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{FragmentShaderSource}") : File.ReadAllText(FragmentShaderSource))!;
GL.ShaderSource(VertexShader, vss);
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(FragmentShader, fss);
GL.CompileShader(VertexShader);
string infoLogVert = GL.GetShaderInfoLog(VertexShader);
if (infoLogVert != string.Empty)
Console.WriteLine(infoLogVert);
GL.CompileShader(FragmentShader);
string infoLogFrag = GL.GetShaderInfoLog(FragmentShader);
if (infoLogFrag != string.Empty)
Console.WriteLine(infoLogFrag);
Handle = GL.CreateProgram();
GL.AttachShader(Handle, VertexShader);
GL.AttachShader(Handle, FragmentShader);
GL.LinkProgram(Handle);
GL.DetachShader(Handle, VertexShader);
GL.DetachShader(Handle, FragmentShader);
GL.DeleteShader(FragmentShader);
GL.DeleteShader(VertexShader);
}
public Shader(string ShaderSource, bool Embeded = false, Assembly? Assembly = null)
{
VertexShader = GL.CreateShader(ShaderType.VertexShader);
string Base = "GraphicsManager.Resources.Shaders.";
if (Assembly is not null) Base = string.Empty;
GL.ShaderSource(VertexShader, (Embeded ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{ShaderSource}.vert") : File.ReadAllText($"{ShaderSource}.vert")));
FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(FragmentShader, (Embeded ? Tools.GetResourceString((Assembly ?? typeof(Tools).Assembly), $"{Base}{ShaderSource}.frag") : File.ReadAllText($"{ShaderSource}.frag")));
GL.CompileShader(VertexShader);
string infoLogVert = GL.GetShaderInfoLog(VertexShader);
if (infoLogVert != string.Empty)
Console.WriteLine(infoLogVert);
GL.CompileShader(FragmentShader);
string infoLogFrag = GL.GetShaderInfoLog(FragmentShader);
if (infoLogFrag != string.Empty)
Console.WriteLine(infoLogFrag);
Handle = GL.CreateProgram();
GL.AttachShader(Handle, VertexShader);
GL.AttachShader(Handle, FragmentShader);
GL.LinkProgram(Handle);
GL.DetachShader(Handle, VertexShader);
GL.DetachShader(Handle, FragmentShader);
GL.DeleteShader(FragmentShader);
GL.DeleteShader(VertexShader);
}
public void Use()
{
GL.UseProgram(Handle);
}
public int GetAttribLocation(string attribName)
{
return GL.GetAttribLocation(Handle, attribName);
}
public void SetInt(string name, int value)
{
int location = GL.GetUniformLocation(Handle, name);
GL.Uniform1(location, value);
}
public Shader Clone()
{
return (Shader)MemberwiseClone();
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
GL.DeleteProgram(Handle);
disposedValue = true;
}
}
~Shader()
{
GL.DeleteProgram(Handle);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

View File

@ -0,0 +1,106 @@
using GraphicsManager.Structs;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using SharpFont;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Image = SixLabors.ImageSharp.Image;
namespace GraphicsManager.Objects.Core;
public class Texture
{
public static readonly Shader TextureShader = new("RectangleTexture", true);
public int handel;
public Texture(byte[] File)
{
Image<Rgba32> image = Image.Load<Rgba32>(File);
image.Mutate(x => x.Flip(FlipMode.Vertical));
var pixels = new List<byte>(4 * image.Width * image.Height);
for (int y = 0; y < image.Height; y++)
{
var row = image.GetPixelRowSpan(y);
for (int x = 0; x < image.Width; x++)
{
pixels.Add(row[x].R);
pixels.Add(row[x].G);
pixels.Add(row[x].B);
pixels.Add(row[x].A);
}
}
handel = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, handel);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixels.ToArray());
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
}
internal Texture(Label l, char charter, uint PixelHeight, Face face)
{
if (!Label._characters.ContainsKey(l)) Label._characters.Add(l, new Dictionary<uint, Character>());
face.SetPixelSizes(0, PixelHeight);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
GL.ActiveTexture(TextureUnit.Texture0);
face.SelectCharmap(Encoding.Unicode);
ushort temp = ((ushort)charter);
try
{
face.LoadChar(temp, LoadFlags.Render, LoadTarget.Normal);
GlyphSlot glyph = face.Glyph;
FTBitmap bitmap = glyph.Bitmap;
handel = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, handel);
GL.TexImage2D(TextureTarget.Texture2D, 0,
PixelInternalFormat.R8, bitmap.Width, bitmap.Rows, 0,
PixelFormat.Red, PixelType.UnsignedByte, bitmap.Buffer);
Character cha = new()
{
Size = new Vector2(bitmap.Width, bitmap.Rows),
Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop),
Advance = (int)glyph.Advance.X.Value,
Texture = this,
};
Label._characters[l].Add(temp, cha);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
public void LoadText()
{
GL.TextureParameter(handel, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TextureParameter(handel, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TextureParameter(handel, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
GL.TextureParameter(handel, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
}
public void Load(int loc)
{
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.EnableVertexAttribArray(loc);
GL.VertexAttribPointer(loc, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
}
public void Use(TextureUnit unit = TextureUnit.Texture0)
{
GL.ActiveTexture(unit);
GL.BindTexture(TextureTarget.Texture2D, handel);
}
}

View File

@ -0,0 +1,214 @@
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core;
using GraphicsManager.Structs;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using SharpFont;
using System.Reflection;
using Encoding = SharpFont.Encoding;
namespace GraphicsManager.Objects;
public class Label : IRenderObject
{
public static readonly Shader DefaultTextShader = new("Label", true);
public IParent? Parent { get; private set; }
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
private Vector2 laf = new(), saf = new();
public Vector2 LocationAsFloat { get { return laf; } }
public Vector2 SizeAsFloat { get { return saf; } }
public bool Visible { get; set; } = true;
public static readonly Dictionary<Label, Dictionary<uint, Character>> _characters = new();
private string text = string.Empty;
public int VAO { get; set; }
public int VBO { get; set; }
public Vector2 DIR { get; set; } = new Vector2(1f, 0f);
public string Text
{
get => text;
set
{
if (Loaded)
{
Library lib = new();
Face face = new(lib, Font.GetData(), 0);
face.SetPixelSizes(0, PixelHeight);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
face.SelectCharmap(Encoding.Unicode);
if (!_characters.ContainsKey(this)) _characters.Add(this, new Dictionary<uint, Character>());
foreach (char character in value)
{
if (_characters[this].ContainsKey(character) == false)
{
var f = new Texture(this, character, PixelHeight, face);
f.LoadText();
}
}
}
text = value;
}
}
public uint PixelHeight { get; set; } = 20;
public float Scale { get; set; } = 1.2f;
public Shader Shader { get; } = DefaultTextShader;
public Font Font { get; set; } = Font.MakeEmbeddedFont("TektonPro-Regular.otf");
public Vector4 Color { get; set; } = new Vector4(1, 1, 1, 1);
public Vector2i Distance { get; private set; }
private Vector2i loc_ = new();
private Vector2i locc_ = new();
public Vector2i Location
{
get
{
return loc_;
}
set
{
loc_ = value;
if (Window is null || Parent is null) return;
locc_ = new(value.X + Parent.Position.X, value.Y + Parent.Position.Y);
}
}
public Vector2i Size { get; set; }
public void Clean()
{
}
public void Draw()
{
if (Visible & loadd)
{
Shader.Use();
GL.Enable(EnableCap.Blend);
GL.Uniform4(2, Color);
Matrix4 projectionM = Matrix4.CreateOrthographicOffCenter(0, Window!.Size.X, Window!.Size.Y, 0, -1.0f, 1.0f);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
GL.UniformMatrix4(1, false, ref projectionM);
GL.BindVertexArray(VAO);
float angle_rad = (float)Math.Atan2(DIR.Y, DIR.X);
Matrix4 rotateM = Matrix4.CreateRotationZ(angle_rad);
Matrix4 transOriginM = Matrix4.CreateTranslation(new Vector3(locc_.X, locc_.Y, 0f));
float char_x = 0.0f;
Library lib = new();
Face face = new(lib, Font.GetData(), 0);
face.SetPixelSizes(0, PixelHeight);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
GL.ActiveTexture(TextureUnit.Texture0);
face.SelectCharmap(Encoding.Unicode);
float hhh = 0f;
foreach (char c in Text)
{
if (!_characters[this].ContainsKey(c)) break;
Character ch = _characters[this][c];
if (c == '\n')
{
hhh += PixelHeight;
char_x = 0f;
}
else
{
float w = ch.Size.X * Scale;
float h = ch.Size.Y * Scale;
float xrel = char_x + ch.Bearing.X * Scale;
float yrel = (ch.Size.Y - ch.Bearing.Y) * Scale;
yrel += hhh;
char_x += (ch.Advance >> 6) * Scale;
Matrix4 scaleM = Matrix4.CreateScale(new Vector3(w, h, 1.0f));
Matrix4 transRelM = Matrix4.CreateTranslation(new Vector3(xrel, yrel, 0.0f));
Matrix4 modelM = scaleM * transRelM * rotateM * transOriginM;
GL.UniformMatrix4(0, false, ref modelM);
ch.Texture.Use();
GL.DrawArrays(PrimitiveType.Triangles, 0, 6);
}
}
GL.Disable(EnableCap.Blend);
}
}
public Window? Window { get; private set; }
public void LoadToParent(IParent window, Window win)
{
Parent = window;
Window = win;
//X = window.FloatToInt(X, window.Size.X);
//Y = window.FloatToInt(Y, window.Size.Y, true);
Library lib = new();
Face face = new(lib, Font.GetData(), 0);
face.SetPixelSizes(0, PixelHeight);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
face.SelectCharmap(Encoding.Unicode);
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 4);
float[] vquad =
{
0.0f, -1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 1.0f, 1.0f,
0.0f, -1.0f, 0.0f, 0.0f,
1.0f, 0.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f
};
VBO = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, VBO);
GL.BufferData(BufferTarget.ArrayBuffer, 4 * 6 * 4, vquad, BufferUsageHint.StaticDraw);
VAO = GL.GenVertexArray();
if (!_characters.ContainsKey(this)) _characters.Add(this, new Dictionary<uint, Character>());
foreach (char character in Text)
{
if (_characters[this].ContainsKey(character) == false)
{
var f = new Texture(this, character, PixelHeight, face);
f.LoadText();
}
}
GL.BindVertexArray(VAO);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 4 * 4, 0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 4 * 4, 2 * 4);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(0);
Text = text;
loadd = true;
Location = Location;
Distance = new(window.Size.X - Size.X - Location.X, window.Size.Y - Size.Y - Location.Y);
}
private bool loadd = false;
public event Func<IRenderObject, Task>? Clicked;
public bool Loaded => loadd;
}

View File

@ -0,0 +1,212 @@
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
namespace GraphicsManager.Objects;
public class Rectangle : ITextureObject
{
public static readonly Shader DefaultShader = new("Rectangle", true);
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
public Texture? Texture { get; private set; }
public Rectangle(Texture? texture = null)
{
Texture = texture;
if (Points_ is null)
{
bool tex = (Texture is null);
Points_ = new float[(tex ? 12 : 20)];
if (!tex)
{
Points[3] = 1.0f;
Points[4] = 1.0f;
Points[8] = 1.0f;
Points[19] = 1.0f;
}
}
}
public Vector4 Color { get; set; }
public bool Visible { get; set; } = true;
public void Draw()
{
if (Visible)
{
if (Texture is not null) Texture.Use();
Shader.Use();
GL.Uniform4(0, Color);
if (Texture is not null)
{
GL.Enable(EnableCap.Blend);
GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
GL.BlendFunc(0, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
}
GL.BindVertexArray(ArrayObject);
GL.DrawElements(PrimitiveType.Triangles, Indexs.Length, DrawElementsType.UnsignedInt, 0);
if (Texture is not null) GL.Disable(EnableCap.Blend);
}
}
public void Clean()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.DeleteBuffer(BufferObject);
}
public void LoadToParent(IParent Parent, Window Window)
{
this.Parent = Parent;
this.Window = Window;
int pos = Points.Length - 3;
if (Texture is not null) pos -= 2;
pos = 4;
if (Texture is not null) pos += 2;
BufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
ArrayObject = GL.GenVertexArray();
GL.BindVertexArray(ArrayObject);
int add = 3;
if (Texture is not null) add = 5;
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0);
if (Texture is not null)
{
Shader = Texture.TextureShader;
Texture.Load(Shader.GetAttribLocation("aTexCoord"));
}
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, Points.Length * sizeof(float), Points, Hint);
GL.BindVertexArray(ArrayObject);
ElementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint);
load = true;
loadd = true;
Window.MouseDown += Window_MouseDown;
Location = Location;
Distance = new(Parent.Size.X - Size.X - Location.X, Parent.Size.Y - Size.Y - Location.Y);
}
public IParent? Parent { get; private set; }
public Window? Window { get; private set; }
private void Window_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e)
{
if (Clicked is not null && e.Button == OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button1 && Location.X <= Parent?.MousePosition.X && Size.X + Location.X >= Parent?.MousePosition.X && Location.Y + Size.Y >= Parent?.MousePosition.Y && Location.Y <= Parent?.MousePosition.Y) Clicked.Invoke(this);
}
~Rectangle()
{
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.DeleteBuffer(BufferObject);
}
public Shader Shader { get; set; } = DefaultShader;
public int ElementBufferObject { get; private set; }
public int BufferObject { get; private set; }
public int ArrayObject { get; private set; }
private float[] Points_;
private Vector2i size_ = new(), loc_ = new();
bool load = false;
public float[] Points
{
get
{
return Points_;
}
set
{
Points_ = value;
try
{
if (load)
{
int add = 3;
if (Texture is not null) add = 5;
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
GL.BindVertexArray(ArrayObject);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, add * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
GL.BindBuffer(BufferTarget.ArrayBuffer, BufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, Points_.Length * sizeof(float), Points_, Hint);
GL.BindVertexArray(ArrayObject);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, Indexs.Length * sizeof(uint), Indexs, Hint);
}
}
catch (AccessViolationException v)
{
Console.WriteLine(v.Message);
}
}
}
public uint[] Indexs { get; set; } = new uint[6] { 0, 1, 3, 1, 2, 3 };
public BufferUsageHint Hint { get; set; } = BufferUsageHint.StaticDraw;
private bool loadd = false;
public event Func<IRenderObject, Task>? Clicked;
public bool Loaded => loadd;
public Vector2i Distance { get; private set; }
public Vector2i Size
{
get
{
return size_;
}
set
{
size_ = value;
if (Window is null || Parent is null) return;
float[] temp = Points;
saf = new Vector2(Window.IntToFloat(value.X + loc_.X + Parent.Position.X, false), Window.IntToFloat(value.Y + loc_.Y + Parent.Position.Y, true));
temp[0] = saf.X;
temp[(Texture is null ? 3 : 5)] = saf.X;
temp[(Texture is null ? 4 : 6)] = saf.Y;
temp[(Texture is null ? 7 : 11)] = saf.Y;
Points = temp;
}
}
public Vector2i Location
{
get
{
return loc_;
}
set
{
loc_ = value;
if (Window is null || Parent is null) return;
float[] temp = Points;
laf = new Vector2(Window.IntToFloat(value.X + Parent.Position.X, false), Window.IntToFloat(value.Y + Parent.Position.Y, true));
temp[(Texture is null ? 6 : 10)] = laf.X;
temp[(Texture is null ? 9 : 15)] = laf.X;
temp[1] = laf.Y;
temp[(Texture is null ? 10 : 16)] = laf.Y;
saf = new Vector2(Window.IntToFloat(Size.X + value.X + Parent.Position.X, false), Window.IntToFloat(Size.Y + value.Y + Parent.Position.Y, true));
temp[0] = saf.X;
temp[(Texture is null ? 3 : 5)] = saf.X;
temp[(Texture is null ? 4 : 6)] = saf.Y;
temp[(Texture is null ? 7 : 11)] = saf.Y;
Points = temp;
}
}
private Vector2 laf = new(), saf = new();
public Vector2 LocationAsFloat { get { return laf; } }
public Vector2 SizeAsFloat { get { return saf; } }
}

View File

@ -0,0 +1,121 @@
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using GraphicsManager.Objects.Core;
using OpenTK.Mathematics;
using OpenTK.Windowing.GraphicsLibraryFramework;
namespace GraphicsManager.Objects;
public class Textbox : ITextureObject
{
public event Func<IRenderObject, Task>? Clicked;
public Rectangle Bounds;
public Label Label;
public IParent Parent { get; private set; }
public Textbox(Texture texture = null!)
{
Bounds = new Rectangle(texture ?? new Texture(Tools.GetResourceBytes("GraphicsManager.Resources.Textures.Textbox.png")));
Label = new Label()
{
Text = nameof(Textbox)
};
}
public Vector2i Size { get { return Bounds.Size; } set { Bounds.Size = value; } }
public Vector2i Location { get { return Bounds.Location; } set { Bounds.Location = value; } }
public Vector2i Distance { get { return Bounds.Distance; }}
public Texture Texture => Bounds.Texture!;
public string Text { get => Label.Text; set => Label.Text = value; }
public Font Font { get => Label.Font; set => Label.Font = value; }
public Vector4 BackgroundColor { get => Bounds.Color; set => Bounds.Color = value; }
public float[] Points
{
get
{
return Bounds.Points;
}
set
{
if (Label is not null && Parent is not null)
{
Label.Location = new Vector2i((int)Parent.FloatToInt(value[10] + ((-1 - Parent.IntToFloat(10)) * -1)), (int)Parent.FloatToInt(value[6] + (-1 - Parent.IntToFloat(5)) * -1, true));
}
Bounds.Points = value;
}
}
public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top;
private bool _loaded = false;
public bool Loaded => _loaded;
public bool Visible { get; set; } = true;
public void Clean()
{
Bounds.Clean();
Label.Clean();
}
public void Draw()
{
Bounds.Draw();
Label.Draw();
}
public Window? Window { get; private set; }
public void LoadToParent(IParent Parent, Window Window)
{
this.Parent = Parent;
this.Window = Window;
this.Parent.MouseDown += Parrent_MouseDown;
this.Parent.KeyDown += Parrent_KeyDown;
Bounds.LoadToParent(Parent, Window);
Points = Points;
Label.LoadToParent(Parent, Window);
_loaded = true;
}
private void Parrent_KeyDown(OpenTK.Windowing.Common.KeyboardKeyEventArgs obj)
{
if (use)
{
if (obj.Key == Keys.CapsLock || obj.Key == Keys.Menu || obj.Key == Keys.LeftSuper || obj.Key == Keys.RightSuper || obj.Key == Keys.End || obj.Key == Keys.Home || obj.Key == Keys.PageDown || obj.Key == Keys.PageUp || obj.Key == Keys.Insert || obj.Key == Keys.Up || obj.Key == Keys.Down || obj.Key == Keys.Left || obj.Key == Keys.Right) return;
if (obj.Key == Keys.Backspace)
{
if (!(Text.Length > 0)) return;
Text = Text.Remove(Text.Length - 1, 1);
}
else if (obj.Key == Keys.Delete)
{
if (!(Text.Length > 0)) return;
Text = Text.Remove(Text.Length - 1, 1);
}
else if (obj.Shift)
{
if (obj.Key == Keys.Enter || obj.Key == Keys.KeyPadEnter) Text += '\n';
else if (obj.Key == Keys.LeftShift || obj.Key == Keys.KeyPadEnter || obj.Key == Keys.Enter || obj.Key == Keys.End || obj.Key == Keys.Down) return;
else Text += ((char)obj.Key).ToString().ToUpper();
}
else if (obj.Command || obj.Alt || obj.Control) { }
else
{
Text += ((char)obj.Key).ToString().ToLower();
}
}
}
bool use = false;
private void Parrent_MouseDown(OpenTK.Windowing.Common.MouseButtonEventArgs e)
{
if (e.Button == MouseButton.Button1 && Location.X <= Parent?.MousePosition.X && Size.X + Location.X >= Parent?.MousePosition.X && Location.Y + Size.Y >= Parent?.MousePosition.Y && Location.Y <= Parent?.MousePosition.Y)
{
use = true;
if (Clicked is not null) Clicked.Invoke(this);
}
else use = false;
}
public Vector2 LocationAsFloat { get { return Bounds.LocationAsFloat; } }
public Vector2 SizeAsFloat { get { return Bounds.SizeAsFloat; } }
}

View File

@ -0,0 +1,183 @@
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
namespace GraphicsManager.Objects;
public class UserControl : IRenderObject, IParent
{
private Rectangle _bounds;
public UserControl()
{
_bounds = new Rectangle();
_bounds.Clicked += _bounds_Clicked;
}
private Task _bounds_Clicked(IRenderObject arg)
{
_ = Clicked?.Invoke(arg)!;
return Task.CompletedTask;
}
public ICollection<IRenderObject> Controls { get; } = new List<IRenderObject>();
public ObjectAnchor Anchor { get => _bounds.Anchor; set => _bounds.Anchor = value; }
public Vector4 Color { get => _bounds.Color; set => _bounds.Color = value; }
public bool Visible { get => _bounds.Visible; set => _bounds.Visible = value; }
public Vector2i Size { get => _bounds.Size; set => _bounds.Size = value; }
public Vector2 SizeAsFloat { get => _bounds.SizeAsFloat; }
public Vector2i Location { get => _bounds.Location; set => _bounds.Location = value; }
public Vector2i Position => Location;
public Vector2 LocationAsFloat { get => _bounds.LocationAsFloat; }
public Vector2i Distance { get => _bounds.Distance; }
public event Func<IRenderObject, Task>? Clicked;
public event Action<MouseButtonEventArgs> MouseDown;
public event Action<KeyboardKeyEventArgs> KeyDown;
public IParent? Parent { get; private set; }
public Window? Window { get; private set; }
public bool Loaded { get; private set; } = false;
public Vector2 MousePosition => throw new NotImplementedException();
public void LoadToParent(IParent Parent, Window Window)
{
this.Parent = Parent;
this.Window = Window;
_bounds.LoadToParent(Parent, Window);
foreach (IRenderObject obj in Controls)
{
obj.LoadToParent(this, Window);
}
Loaded = true;
}
public void Draw()
{
if (Loaded)
{
_bounds.Draw();
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
if (needload.Any())
{
foreach (IRenderObject Control in needload)
{
Control.LoadToParent(this, Window!);
}
}
foreach (IRenderObject Control in Controls)
{
Control.Draw();
}
}
}
public void Clean()
{
foreach (IRenderObject Control in Controls)
{
Control.Clean();
}
_bounds.Clean();
}
public void Resize(ResizeEventArgs e)
{
if (e.Width == 0 && e.Height == 0) return;
foreach (IRenderObject Control in Controls)
{
if (Control.Loaded)
{
bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; }
if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; }
int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X);
int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y);
int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y);
int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X);
Control.Size = new(sx, sy);
Control.Location = new(lx, ly);
}
}
}
#region Cool Math Things
public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f)
{
if (hastexture)
{
return new float[20] {
IntToFloat(x + Width), IntToFloat(y, true), z, 1.0f, 1.0f,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, 1.0f, 0.0f,//b r
IntToFloat(x), IntToFloat(y + Height, true), z, 0.0f, 0.0f,//bot l
IntToFloat(x), IntToFloat(y, true), z, 0.0f, 1.0f// top l
};
}
else
{
return new float[12] {
IntToFloat(x + Width), IntToFloat(y, true), z,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, //b r
IntToFloat(x), IntToFloat(y + Height, true), z, //bot l
IntToFloat(x), IntToFloat(y, true), z,// top l
};
}
}
public float IntToFloat(int p, bool Invert = false)
{
int Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 1);
double Per = Math.Round((double)1 / half, 15);
if (p == half) return 0.0f;
if (Invert)
{
if (p > half) return (float)(((double)(p - half) * Per) * -1);
else return (float)(1 - (p * Per));
}
else
{
if (p > half) return (float)((double)(p - half) * Per);
else return (float)((1 - (p * Per)) * -1);
}
}
public float FloatToInt(float p, bool Invert = false)
{
int Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 15);
if (p == 0) return (int)half;
if (Invert)
{
if (p < 0)
{
p *= -1;
p++;
return (float)(half * p);
}
else
{
return (float)(half - (p * half));
}
}
else
{
if (p < 0)
{
p *= -1;
p++;
return (float)(Size - (half * p));
}
else
{
return (float)(p * half + half);
}
}
}
#endregion
}

Binary file not shown.

View File

@ -0,0 +1,16 @@
#version 460
in vec2 vUV;
layout (binding=0) uniform sampler2D u_texture;
layout (location = 2) uniform vec4 textColor;
out vec4 fragColor;
void main()
{
vec2 uv = vUV.xy;
float text = texture(u_texture, uv).r;
fragColor = vec4(textColor.rgba*text);
}

View File

@ -0,0 +1,15 @@
#version 460
layout (location = 0) in vec2 in_pos;
layout (location = 1) in vec2 in_uv;
out vec2 vUV;
layout (location = 0) uniform mat4 model;
layout (location = 1) uniform mat4 projection;
void main()
{
vUV = in_uv.xy;
gl_Position = projection * model * vec4(in_pos.xy, 0.0, 1.0);
}

View File

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
in vec4 vertexColor;
void main()
{
FragColor = vertexColor;
}

View File

@ -0,0 +1,10 @@
#version 330 core
layout (location = 0) in vec3 aPos;
uniform vec4 objColor;
out vec4 vertexColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
vertexColor = objColor;
}

View File

@ -0,0 +1,8 @@
#version 330
out vec4 outputColor;
in vec2 texCoord;
uniform sampler2D texture1;
void main(void)
{
outputColor = texture(texture1, texCoord);
}

View File

@ -0,0 +1,9 @@
#version 330
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexCoord;
out vec2 texCoord;
void main(void)
{
texCoord = aTexCoord;
gl_Position = vec4(aPosition, 1.0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

View File

@ -0,0 +1,12 @@
using GraphicsManager.Objects.Core;
using OpenTK.Mathematics;
namespace GraphicsManager.Structs;
public struct Character
{
public Texture Texture { get; set; }
public Vector2 Size { get; set; }
public Vector2 Bearing { get; set; }
public int Advance { get; set; }
}

31
GraphicsManager/Tools.cs Normal file
View File

@ -0,0 +1,31 @@
using System.Reflection;
namespace GraphicsManager;
public class Tools
{
public static byte[] GetResourceBytes(Assembly Assembly, string Resource)
{
Stream str = Assembly.GetManifestResourceStream(Resource)!;
MemoryStream ms = new();
str.CopyTo(ms);
str.Dispose();
byte[] result = ms.ToArray();
ms.Dispose();
return result;
}
public static string GetResourceString(Assembly Assembly, string Resource)
{
Stream str = Assembly.GetManifestResourceStream(Resource)!;
StreamReader sr = new(str);
string result = sr.ReadToEnd();
sr.Dispose();
str.Dispose();
return result;
}
public static byte[] GetResourceBytes(string Resource) => GetResourceBytes(typeof(Tools).Assembly, Resource);
public static string GetResourceString(string Resource) => GetResourceString(typeof(Tools).Assembly, Resource);
}

165
GraphicsManager/Window.cs Normal file
View File

@ -0,0 +1,165 @@
using GraphicsManager.Enums;
using GraphicsManager.Interfaces;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
namespace GraphicsManager;
public class Window : NativeWindow , IParent
{
public Window(NativeWindowSettings nativeWindowSettings) : base(nativeWindowSettings)
{
}
public Window() : base(new NativeWindowSettings())
{
}
public Vector2i Position { get; } = new Vector2i(0, 0);
public Color4 BackgroundColor { get; set; } = new Color4(0, 0, 0, 255);
public ICollection<IRenderObject> Controls { get; } = new List<IRenderObject>();
#region Cool Math Things
public float[] RctToFloat(int x, int y, int Width, int Height, bool hastexture = false, float z = 0.0f)
{
if (hastexture)
{
return new float[20] {
IntToFloat(x + Width), IntToFloat(y, true), z, 1.0f, 1.0f,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, 1.0f, 0.0f,//b r
IntToFloat(x), IntToFloat(y + Height, true), z, 0.0f, 0.0f,//bot l
IntToFloat(x), IntToFloat(y, true), z, 0.0f, 1.0f// top l
};
}
else
{
return new float[12] {
IntToFloat(x + Width), IntToFloat(y, true), z,// top r
IntToFloat(x + Width), IntToFloat(y + Height, true), z, //b r
IntToFloat(x), IntToFloat(y + Height, true), z, //bot l
IntToFloat(x), IntToFloat(y, true), z,// top l
};
}
}
public float IntToFloat(int p, bool Invert = false)
{
int Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 1);
double Per = Math.Round((double)1 / half, 15);
if (p == half) return 0.0f;
if (Invert)
{
if (p > half) return (float)(((double)(p - half) * Per) * -1);
else return (float)(1 - (p * Per));
}
else
{
if (p > half) return (float)((double)(p - half) * Per);
else return (float)((1 - (p * Per)) * -1);
}
}
public float FloatToInt(float p, bool Invert = false)
{
int Size = (Invert ? this.Size.Y : this.Size.X);
double half = Math.Round((double)Size / (double)2, 15);
if (p == 0) return (int)half;
if (Invert)
{
if (p < 0)
{
p *= -1;
p++;
return (float)(half * p);
}
else
{
return (float)(half - (p * half));
}
}
else
{
if (p < 0)
{
p *= -1;
p++;
return (float)(Size - (half * p));
}
else
{
return (float)(p * half + half);
}
}
}
#endregion
public void Resize(ResizeEventArgs e)
{
if (e.Width == 0 && e.Height == 0) return;
base.OnResize(e);
GL.Viewport(0, 0, e.Width, e.Height);
foreach (IRenderObject Control in Controls)
{
if (Control.Loaded)
{
bool top = (Control.Anchor & ObjectAnchor.Top) == ObjectAnchor.Top;
bool left = (Control.Anchor & ObjectAnchor.Left) == ObjectAnchor.Left;
bool right = (Control.Anchor & ObjectAnchor.Right) == ObjectAnchor.Right;
bool bottom = (Control.Anchor & ObjectAnchor.Bottom) == ObjectAnchor.Bottom;
if (!top && !bottom) { Control.Anchor |= ObjectAnchor.Top; top = true; }
if (!left && !right) { Control.Anchor |= ObjectAnchor.Left; left = true; }
int lx = (left ? Control.Location.X : Size.X - Control.Distance.X - Control.Size.X);
int ly = (top ? Control.Location.Y : Size.Y - Control.Distance.Y - Control.Size.Y);
int sy = (bottom ? Size.Y - Control.Distance.Y - ly : Control.Size.Y);
int sx = (right ? Size.X - Control.Distance.X - lx : Control.Size.X);
Control.Size = new(sx, sy);
Control.Location = new(lx, ly);
if (Control is IParent)
{
IParent parent = (IParent)Control;
parent.Resize(e);
}
}
}
}
protected override void OnResize(ResizeEventArgs e)
{
Resize(e);
}
public void StartRender()
{
Context.MakeCurrent();
while (Exists && IsVisible && !IsExiting)
{
DrawFrame();
}
}
public void DrawFrame()
{
ProcessEvents();
GL.ClearColor(BackgroundColor.R, BackgroundColor.G, BackgroundColor.B, (BackgroundColor.A * -1) + 1);
IEnumerable<IRenderObject> needload = Controls.Where(a => a.Loaded == false);
if (needload.Any())
{
foreach (IRenderObject obj in needload)
{
obj.LoadToParent(this, this);
}
}
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
foreach (IRenderObject obj in Controls)
{
if (obj.Loaded) obj.Draw();
}
Context.SwapBuffers();
Thread.Sleep(8);
}
}