diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add57be --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +riderModule.iml +/_ReSharper.Caches/ \ No newline at end of file diff --git a/.idea/.idea.shdr/.idea/.gitignore b/.idea/.idea.shdr/.idea/.gitignore new file mode 100644 index 0000000..cd90912 --- /dev/null +++ b/.idea/.idea.shdr/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/.idea.shdr.iml +/projectSettingsUpdater.xml +/modules.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.shdr/.idea/discord.xml b/.idea/.idea.shdr/.idea/discord.xml new file mode 100644 index 0000000..cf77f1e --- /dev/null +++ b/.idea/.idea.shdr/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/.idea.shdr/.idea/encodings.xml b/.idea/.idea.shdr/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.shdr/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.shdr/.idea/indexLayout.xml b/.idea/.idea.shdr/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.shdr/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/before.bat b/before.bat new file mode 100644 index 0000000..65d82f2 --- /dev/null +++ b/before.bat @@ -0,0 +1,2 @@ +xcopy "C:\Users\richard may clarkson\RiderProjects\shdr\shdr\Resource" "C:\Users\richard may clarkson\RiderProjects\shdr\shdr\bin\Debug\net6.0\Resource" /E /H /C /R /Q /Y +xcopy "C:\Users\richard may clarkson\RiderProjects\shdr\shdr\Resource" "C:\Users\richard may clarkson\RiderProjects\shdr\shdr\bin\Release\net6.0\Resource" /E /H /C /R /Q /Y \ No newline at end of file diff --git a/global.json b/global.json new file mode 100644 index 0000000..9e5e1fd --- /dev/null +++ b/global.json @@ -0,0 +1,7 @@ +{ + "sdk": { + "version": "6.0.0", + "rollForward": "latestMajor", + "allowPrerelease": true + } +} \ No newline at end of file diff --git a/shdr.sln b/shdr.sln new file mode 100644 index 0000000..f8dcd1c --- /dev/null +++ b/shdr.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "shdr", "shdr\shdr.csproj", "{5F7BB6FD-5D0B-4E3A-8D87-295F9802F734}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5F7BB6FD-5D0B-4E3A-8D87-295F9802F734}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F7BB6FD-5D0B-4E3A-8D87-295F9802F734}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F7BB6FD-5D0B-4E3A-8D87-295F9802F734}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F7BB6FD-5D0B-4E3A-8D87-295F9802F734}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/shdr.sln.DotSettings.user b/shdr.sln.DotSettings.user new file mode 100644 index 0000000..e25f193 --- /dev/null +++ b/shdr.sln.DotSettings.user @@ -0,0 +1,6 @@ + + <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /> + <Policy Inspect="True" Prefix="__" Suffix="" Style="aa_bb" /> + <AssemblyExplorer> + <Assembly Path="C:\Users\richard may clarkson\RiderProjects\shdr\shdr\bin\Debug\net6.0\NAudio.Core.dll" /> +</AssemblyExplorer> \ No newline at end of file diff --git a/shdr/Engine/Fbo.cs b/shdr/Engine/Fbo.cs new file mode 100644 index 0000000..ca391da --- /dev/null +++ b/shdr/Engine/Fbo.cs @@ -0,0 +1,136 @@ +using OpenTK.Graphics.OpenGL4; + +namespace shdr.Engine +{ + public class __fbo + { + private static int _active; + private static readonly Dictionary _frames = new(); + private readonly bool _useDepth; + private int _colorAttachment; + private int _depthAttachment; + public int handle; + private int _height; + private int _width; + + public __fbo(int width, int height) + { + _width = width; + _height = height; + _useDepth = false; + handle = -1; + init(); + _frames[handle] = this; + } + + public __fbo(int width, int height, bool useDepth) + { + _width = width; + _height = height; + _useDepth = useDepth; + handle = -1; + init(); + _frames[handle] = this; + } + + private void dispose() + { + GL.DeleteFramebuffer(handle); + GL.DeleteTexture(_colorAttachment); + if (_useDepth) GL.DeleteTexture(_depthAttachment); + } + + private void init() + { + if (handle != -1) dispose(); + + handle = GL.GenFramebuffer(); + bind(); + _colorAttachment = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, _colorAttachment); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, + (int)TextureWrapMode.ClampToBorder); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, + (int)TextureWrapMode.ClampToBorder); + GL.TexStorage2D(TextureTarget2d.Texture2D, 1, SizedInternalFormat.Rgba8, _width, _height); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, + TextureTarget.Texture2D, _colorAttachment, 0); + if (_useDepth) + { + _depthAttachment = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, _depthAttachment); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, + (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, + (int)TextureMagFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureCompareMode, + (int)TextureCompareMode.None); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, + (int)TextureWrapMode.ClampToEdge); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, + (int)TextureWrapMode.ClampToEdge); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, _width, _height, 0, + PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, + TextureTarget.Texture2D, _depthAttachment, 0); + } + + FramebufferErrorCode status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); + if (status != FramebufferErrorCode.FramebufferComplete) + throw new Exception( + $"Incomplete Framebuffer! {status} should be {FramebufferErrorCode.FramebufferComplete}"); + + unbind(); + } + + private void _resize(int width, int height) + { + _width = width; + _height = height; + init(); + } + + public static void resize(int width, int height) + { + foreach (KeyValuePair frame in _frames) frame.Value._resize(width, height); + } + + public void bind_color(TextureUnit unit) + { + GL.ActiveTexture(unit); + GL.BindTexture(TextureTarget.Texture2D, _colorAttachment); + } + + public int bind_depth(TextureUnit unit) + { + if (!_useDepth) throw new Exception("Trying to bind depth texture of a framebuffer without depth!"); + GL.ActiveTexture(unit); + GL.BindTexture(TextureTarget.Texture2D, _depthAttachment); + return _depthAttachment; + } + + public void bind() + { + if (handle == _active) return; + GL.BindFramebuffer(FramebufferTarget.Framebuffer, handle); + _active = handle; + } + + public void blit(int handle = 0) + { + GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, this.handle); + GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, handle); + GL.BlitFramebuffer(0, 0, _width, _height, 0, 0, _width, _height, ClearBufferMask.ColorBufferBit, + BlitFramebufferFilter.Nearest); + unbind(); + } + + public static void unbind() + { + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); + _active = 0; + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Font.cs b/shdr/Engine/Font.cs new file mode 100644 index 0000000..6040eeb --- /dev/null +++ b/shdr/Engine/Font.cs @@ -0,0 +1,185 @@ +using OpenTK.Graphics.OpenGL4; +using shdr.Shared; +using StbTrueTypeSharp; + +namespace shdr.Engine +{ + public static class __font + { + private const float ipw = 1.0f / 2048f; + private const float iph = ipw; + private static readonly float[] _ascent; + private static readonly StbTrueType.stbtt_packedchar[][] _chars; + + private static readonly __mesh _mesh; + private static readonly __texture[] _texture; + + private static readonly KeyValuePair[] _paths = { + new("Resource/Font/Dank Mono Italic.otf", 18), + new("Resource/Font/JetBrainsMono-Regular.ttf", 20), + new("Resource/Font/monofur-regular.ttf", 19) + }; + + + private static int _index; + public static int index + { + set => _index = value % _paths.Length; + get => _index; + } + + // I have absolutely no idea how to use unsafe :(( + static unsafe __font() + { + _mesh = new __mesh( + __mesh.__draw_mode.triangle, + new __shader("Resource/Shader/font.vert", "Resource/Shader/font.frag"), + __vao.__attrib.float3, __vao.__attrib.float2, __vao.__attrib.float4 + ); + + _chars = new StbTrueType.stbtt_packedchar[_paths.Length][]; + _ascent = new float[_paths.Length]; + _texture = new __texture[_paths.Length]; + + for (int i = 0; i < _paths.Length; i++) + { + int height = _paths[i].Value; + _chars[i] = new StbTrueType.stbtt_packedchar[256]; + byte[] buffer = File.ReadAllBytes(_paths[i].Key); + StbTrueType.stbtt_fontinfo fontInfo = StbTrueType.CreateFont(buffer, 0); + + StbTrueType.stbtt_pack_context packContext = new(); + + byte[] bitmap = new byte[2048 * 2048]; + fixed (byte* dat = bitmap) + { + StbTrueType.stbtt_PackBegin(packContext, dat, 2048, 2048, 0, 1, null); + } + + StbTrueType.stbtt_PackSetOversampling(packContext, 8, 8); + fixed (byte* dat = buffer) + { + fixed (StbTrueType.stbtt_packedchar* c = _chars[i]) + { + StbTrueType.stbtt_PackFontRange(packContext, dat, 0, height, 32, 256, c); + } + } + + StbTrueType.stbtt_PackEnd(packContext); + + int asc; + StbTrueType.stbtt_GetFontVMetrics(fontInfo, &asc, null, null); + _ascent[i] = asc * StbTrueType.stbtt_ScaleForPixelHeight(fontInfo, height); + + _texture[i] = __texture.load_from_buffer(bitmap, 2048, 2048, PixelFormat.Red, PixelInternalFormat.R8, + TextureMinFilter.Nearest, TextureMagFilter.Nearest); + } + } + + public static void bind() + { + _texture[index].bind(TextureUnit.Texture0); + _mesh.begin(); + } + + public static void render() + { + _mesh.render(); + __texture.unbind(); + } + + public static void draw(string text, float x, float y, uint color, bool shadow, float scale = 1.0f) + { + int length = text.Length; + float drawX = x; + float drawY = y + _ascent[index] * scale; + float alpha = ((color >> 24) & 0xFF) / 255.0f; + float red = ((color >> 16) & 0xFF) / 255.0f; + float green = ((color >> 8) & 0xFF) / 255.0f; + float blue = (color & 0xFF) / 255.0f; + for (int i = 0; i < length; i++) + { + char charCode = text[i]; + char previous = i > 0 ? text[i - 1] : ' '; + if (previous == '\u00a7') continue; + + if (charCode == '\u00a7' && i < length - 1) + { + char next = text[i + 1]; + if (__fmt.values.TryGetValue(next, out __fmt fmt)) + { + uint newColor = fmt.color; + red = ((newColor >> 16) & 0xFF) / 255.0f; + green = ((newColor >> 8) & 0xFF) / 255.0f; + blue = (newColor & 0xFF) / 255.0f; + } + + continue; + } + + if (charCode < 32 || charCode > 32 + 256) charCode = ' '; + + StbTrueType.stbtt_packedchar c = _chars[index][charCode - 32]; + + float dxs = drawX + c.xoff * scale; + float dys = drawY + c.yoff * scale; + float dx1S = drawX + c.xoff2 * scale; + float dy1S = drawY + c.yoff2 * scale; + + if (shadow) + { + int j1 = _mesh.float3(dxs + scale * 1.5f, dys + scale * 1.5f, 1).float2(c.x0 * ipw, c.y0 * iph) + .float4(red * 0, green * 0, blue * 0, alpha).next(); + int j2 = _mesh.float3(dxs + scale * 1.5f, dy1S + scale * 1.5f, 1).float2(c.x0 * ipw, c.y1 * iph) + .float4(red * 0, green * 0, blue * 0, alpha).next(); + int j3 = _mesh.float3(dx1S + scale * 1.5f, dy1S + scale * 1.5f, 1).float2(c.x1 * ipw, c.y1 * iph) + .float4(red * 0, green * 0, blue * 0, alpha).next(); + int j4 = _mesh.float3(dx1S + scale * 1.5f, dys + scale * 1.5f, 1).float2(c.x1 * ipw, c.y0 * iph) + .float4(red * 0, green * 0, blue * 0, alpha).next(); + _mesh.quad(j1, j2, j3, j4); + } + + int k1 = _mesh.float3(dxs, dys, 0).float2(c.x0 * ipw, c.y0 * iph) + .float4(red, green, blue, alpha).next(); + int k2 = _mesh.float3(dxs, dy1S, 0).float2(c.x0 * ipw, c.y1 * iph) + .float4(red, green, blue, alpha).next(); + int k3 = _mesh.float3(dx1S, dy1S, 0).float2(c.x1 * ipw, c.y1 * iph) + .float4(red, green, blue, alpha).next(); + int k4 = _mesh.float3(dx1S, dys, 0).float2(c.x1 * ipw, c.y0 * iph) + .float4(red, green, blue, alpha).next(); + _mesh.quad(k1, k2, k3, k4); + + drawX += c.xadvance * scale; + drawX -= 0.4f * scale; + } + } + + public static float get_width(string text, float scale = 1.0f) + { + int length = text.Length; + float width = 0; + for (int i = 0; i < length; i++) + { + char charCode = text[i]; + char previous = i > 0 ? text[i - 1] : ' '; + if (previous == '\u00a7') continue; + + if (charCode < 32 || charCode > 32 + 256) charCode = ' '; + + StbTrueType.stbtt_packedchar c = _chars[index][charCode - 32]; + + width += c.xadvance * scale; + width -= 0.4f * scale; + } + + width += 0.4f * scale; + + return width; + } + + public static float get_height(float scale = 1.0f) + { + return _ascent[index] * scale; + } + } +} \ No newline at end of file diff --git a/shdr/Engine/GlStateManager.cs b/shdr/Engine/GlStateManager.cs new file mode 100644 index 0000000..fbd494f --- /dev/null +++ b/shdr/Engine/GlStateManager.cs @@ -0,0 +1,83 @@ +using OpenTK.Graphics.OpenGL4; + +namespace shdr.Engine +{ + public static class __gl_state_manager + { + private static bool _depthEnabled; + private static bool _blendEnabled; + private static bool _cullEnabled; + + private static bool _depthSaved; + private static bool _blendSaved; + private static bool _cullSaved; + + public static void save_state() + { + _depthSaved = _depthEnabled; + _blendSaved = _blendEnabled; + _cullSaved = _cullEnabled; + } + + public static void restore_state() + { + if (_depthSaved) + enable_depth(); + else + disable_depth(); + if (_blendSaved) + enable_blend(); + else + disable_blend(); + if (_cullSaved) + enable_cull(); + else + disable_cull(); + } + + public static void enable_depth() + { + if (_depthEnabled) return; + _depthEnabled = true; + GL.Enable(EnableCap.DepthTest); + } + + public static void disable_depth() + { + if (!_depthEnabled) return; + _depthEnabled = false; + GL.Disable(EnableCap.DepthTest); + } + + public static void enable_blend() + { + if (_blendEnabled) return; + _blendEnabled = true; + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + } + + public static void disable_blend() + { + if (_blendEnabled) + { + _blendEnabled = false; + GL.Disable(EnableCap.Blend); + } + } + + public static void enable_cull() + { + if (_cullEnabled) return; + _cullEnabled = true; + GL.Enable(EnableCap.CullFace); + } + + public static void disable_cull() + { + if (!_cullEnabled) return; + _cullEnabled = false; + GL.Disable(EnableCap.CullFace); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Ibo.cs b/shdr/Engine/Ibo.cs new file mode 100644 index 0000000..2778a8c --- /dev/null +++ b/shdr/Engine/Ibo.cs @@ -0,0 +1,50 @@ +using OpenTK.Graphics.OpenGL4; + +namespace shdr.Engine +{ + public class __ibo + { + private static int _active; + private readonly byte[] _bitDest = new byte[4]; + private readonly int _handle; + private readonly MemoryStream _indices; + + public __ibo(int initialCapacity) + { + _handle = GL.GenBuffer(); + _indices = new MemoryStream(initialCapacity); + } + + public void bind() + { + if (_handle == _active) return; + GL.BindBuffer(BufferTarget.ElementArrayBuffer, _handle); + _active = _handle; + } + + public static void unbind() + { + GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); + _active = 0; + } + + public void put(int element) + { + BitConverter.TryWriteBytes(_bitDest, element); + _indices.Write(_bitDest); + } + + public void upload(bool unbindAfter = true) + { + if (_active != _handle) bind(); + GL.BufferData(BufferTarget.ElementArrayBuffer, (int)_indices.Length, _indices.GetBuffer(), + BufferUsageHint.DynamicDraw); + if (unbindAfter) unbind(); + } + + public void clear() + { + _indices.SetLength(0); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Mesh.cs b/shdr/Engine/Mesh.cs new file mode 100644 index 0000000..c99bcbc --- /dev/null +++ b/shdr/Engine/Mesh.cs @@ -0,0 +1,218 @@ +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using shdr.Shared; + +namespace shdr.Engine +{ + public class __mesh + { + private readonly __draw_mode _drawMode; + private readonly __ibo _ibo; + private readonly __shader _shader; + + private readonly __vao _vao; + private readonly __vbo _vbo; + private bool _building; + private int _index; + private int _vertex; + + public __mesh(__draw_mode drawMode, __shader shader, params __vao.__attrib[] attribs) + { + _drawMode = drawMode; + _shader = shader; + int stride = attribs.Sum(attrib => (int)attrib * sizeof(float)); + _vbo = new __vbo(stride * drawMode.size * 256 * sizeof(float)); + _vbo.bind(); + _ibo = new __ibo(drawMode.size * 512 * sizeof(float)); + _ibo.bind(); + _vao = new __vao(attribs); + __vbo.unbind(); + __ibo.unbind(); + __vao.unbind(); + } + + public int next() + { + return _vertex++; + } + + public __mesh float1(float p0) + { + _vbo.put(p0); + return this; + } + + public __mesh float2(float p0, float p1) + { + _vbo.put(p0); + _vbo.put(p1); + return this; + } + + public __mesh float2(Vector2 p0) + { + _vbo.put(p0.X); + _vbo.put(p0.Y); + return this; + } + + public __mesh float3(float p0, float p1, float p2) + { + _vbo.put(p0); + _vbo.put(p1); + _vbo.put(p2); + return this; + } + + public __mesh float3(Matrix4 transform, float p0, float p1, float p2) + { + Vector4 pos = new(p0, p1, p2, 1); + pos.transform(transform); + _vbo.put(pos.X); + _vbo.put(pos.Y); + _vbo.put(pos.Z); + return this; + } + + public __mesh float3(Vector3 p0) + { + _vbo.put(p0.X); + _vbo.put(p0.Y); + _vbo.put(p0.Z); + return this; + } + + public __mesh float4(float p0, float p1, float p2, float p3) + { + _vbo.put(p0); + _vbo.put(p1); + _vbo.put(p2); + _vbo.put(p3); + return this; + } + + public __mesh float4(uint color) + { + return float4(((color >> 16) & 0xff) * 0.003921569f, ((color >> 8) & 0xff) * 0.003921569f, + (color & 0xff) * 0.003921569f, ((color >> 24) & 0xff) * 0.003921569f); + } + + public __mesh float4(uint color, float alpha) + { + return float4(((color >> 16) & 0xff) * 0.003921569f, ((color >> 8) & 0xff) * 0.003921569f, + (color & 0xff) * 0.003921569f, alpha); + } + + public void line(int p0, int p1) + { + _ibo.put(p0); + _ibo.put(p1); + _index += 2; + } + + public void tri(int p0, int p1, int p2) + { + _ibo.put(p0); + _ibo.put(p1); + _ibo.put(p2); + _index += 3; + } + + public void quad(int p0, int p1, int p2, int p3) + { + _ibo.put(p0); + _ibo.put(p1); + _ibo.put(p2); + _ibo.put(p2); + _ibo.put(p3); + _ibo.put(p0); + _index += 6; + } + + public void begin() + { + if (_building) throw new Exception("Already building"); + _vbo.clear(); + _ibo.clear(); + _vertex = 0; + _index = 0; + _building = true; + } + + public void end() + { + if (!_building) throw new Exception("Not building"); + + if (_index > 0) + { + _vbo.upload(); + _ibo.upload(); + } + + _building = false; + } + + public void render() + { + if (_building) end(); + + if (_index <= 0) return; + __gl_state_manager.save_state(); + __gl_state_manager.enable_blend(); + if (__render_system.rendering3d) + __gl_state_manager.enable_depth(); + else + __gl_state_manager.disable_depth(); + _shader?.bind(); + _shader?.set_defaults(); + _vao.bind(); + _ibo.bind(); + _vbo.bind(); + GL.DrawElements(_drawMode.as_gl(), _index, DrawElementsType.UnsignedInt, 0); + __ibo.unbind(); + __vbo.unbind(); + __vao.unbind(); + __gl_state_manager.restore_state(); + } + + public sealed class __draw_mode + { + private static int _cidCounter; + + public static readonly __draw_mode line = new(2); + public static readonly __draw_mode triangle = new(3); + public static readonly __draw_mode triangleFan = new(3); + private readonly int _cid; + public readonly int size; + + private __draw_mode(int size) + { + this.size = size; + _cid = _cidCounter++; + } + + public override bool Equals(object obj) + { + if (obj is __draw_mode mode) return _cid == mode._cid; + + return false; + } + + public override int GetHashCode() + { + return _cid; + } + + public BeginMode as_gl() + { + return _cid switch + { + 0 => BeginMode.Lines, + 1 => BeginMode.Triangles, + 2 => BeginMode.TriangleFan, + _ => throw new Exception("wtf is going on?") + }; + } + } + } +} \ No newline at end of file diff --git a/shdr/Engine/RenderSystem.cs b/shdr/Engine/RenderSystem.cs new file mode 100644 index 0000000..882262c --- /dev/null +++ b/shdr/Engine/RenderSystem.cs @@ -0,0 +1,56 @@ +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace shdr.Engine +{ + public static class __render_system + { + private static readonly __shader _basic = new("Resource/Shader/basic.vert", "Resource/Shader/basic.frag"); + + public static __shader user = null; + + private static Matrix4 _projection; + private static Matrix4 _lookAt; + private static readonly Matrix4[] _model = new Matrix4[7]; + private static int _modelIdx; + + public static readonly __mesh basic = new(__mesh.__draw_mode.triangle, _basic, __vao.__attrib.float3, __vao.__attrib.float4); + + public static readonly __mesh post = new(__mesh.__draw_mode.triangle, null, __vao.__attrib.float2); + public static readonly __fbo frame = new(__shdr.instance.Size.X, __shdr.instance.Size.Y, true); + public static readonly __fbo prevFrame = new(__shdr.instance.Size.X, __shdr.instance.Size.Y, true); + public static bool rendering3d; + + static __render_system() + { + Array.Fill(_model, Matrix4.Identity); + } + + public static ref Matrix4 model => ref _model[_modelIdx]; + + public static Vector2i size => __shdr.instance.Size; + + public static void push() + { + _model[_modelIdx + 1] = model; + _modelIdx++; + } + + public static void pop() + { + _modelIdx--; + } + + public static void set_defaults(this __shader shader) + { + shader.set_matrix4("_proj", _projection); + shader.set_float("_time", (float)GLFW.GetTime()); + } + + public static void update_projection() + { + Matrix4.CreateOrthographicOffCenter(0, __shdr.instance.Size.X, __shdr.instance.Size.Y, 0, -1, 1, out _projection); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Shader.cs b/shdr/Engine/Shader.cs new file mode 100644 index 0000000..3569a24 --- /dev/null +++ b/shdr/Engine/Shader.cs @@ -0,0 +1,164 @@ +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; + +namespace shdr.Engine +{ + // taken from https://github.com/opentk/LearnOpenTK/blob/master/Common/Shader.cs + public class __shader + { + private static int _active; + private readonly int _handle; + private readonly Dictionary _uniformLocations; + + public __shader(string vertPath, string fragPath, string geomPath = null) + { + string shaderSource = File.ReadAllText(vertPath); + int vertexShader = GL.CreateShader(ShaderType.VertexShader); + GL.ShaderSource(vertexShader, shaderSource); + compile_shader(vertexShader); + + shaderSource = File.ReadAllText(fragPath); + int fragmentShader = GL.CreateShader(ShaderType.FragmentShader); + GL.ShaderSource(fragmentShader, shaderSource); + compile_shader(fragmentShader); + + int geometryShader = -1; + if (geomPath != null) + { + shaderSource = File.ReadAllText(geomPath); + geometryShader = GL.CreateShader(ShaderType.GeometryShader); + GL.ShaderSource(geometryShader, shaderSource); + compile_shader(geometryShader); + } + + _handle = GL.CreateProgram(); + + GL.AttachShader(_handle, vertexShader); + GL.AttachShader(_handle, fragmentShader); + if (geometryShader != -1) GL.AttachShader(_handle, geometryShader); + + link_program(_handle); + + GL.DetachShader(_handle, vertexShader); + GL.DetachShader(_handle, fragmentShader); + if (geometryShader != -1) GL.DetachShader(_handle, geometryShader); + GL.DeleteShader(fragmentShader); + GL.DeleteShader(vertexShader); + if (geometryShader != -1) GL.DeleteShader(geometryShader); + + GL.GetProgram(_handle, GetProgramParameterName.ActiveUniforms, out int numberOfUniforms); + + _uniformLocations = new Dictionary(); + + for (int i = 0; i < numberOfUniforms; i++) + { + string key = GL.GetActiveUniform(_handle, i, out _, out _); + int location = GL.GetUniformLocation(_handle, key); + _uniformLocations.Add(key, location); + } + } + + private static void compile_shader(int shader) + { + GL.CompileShader(shader); + + GL.GetShader(shader, ShaderParameter.CompileStatus, out int code); + if (code == (int)All.True) return; + string infoLog = GL.GetShaderInfoLog(shader); + throw new Exception($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}"); + } + + private static void link_program(int program) + { + GL.LinkProgram(program); + + GL.GetProgram(program, GetProgramParameterName.LinkStatus, out int code); + if (code == (int)All.True) return; + string infoLog = GL.GetProgramInfoLog(program); + throw new Exception($"Error occurred whilst linking Program({program}) \n\n{infoLog}"); + } + + public void bind() + { + if (_handle == _active) return; + GL.UseProgram(_handle); + _active = _handle; + } + + public static void unbind() + { + GL.UseProgram(0); + _active = 0; + } + + public int get_attrib_location(string attribName) + { + return GL.GetAttribLocation(_handle, attribName); + } + + /// + /// Set a uniform int on this shader. + /// + /// The name of the uniform + /// The data to set + public void set_int(string name, int data) + { + if (!_uniformLocations.ContainsKey(name)) return; + bind(); + GL.Uniform1(_uniformLocations[name], data); + } + + /// + /// Set a uniform float on this shader. + /// + /// The name of the uniform + /// The data to set + public void set_float(string name, float data) + { + if (!_uniformLocations.ContainsKey(name)) return; + bind(); + GL.Uniform1(_uniformLocations[name], data); + } + + /// + /// Set a uniform Matrix4 on this shader + /// + /// The name of the uniform + /// The data to set + /// + /// + /// The matrix is transposed before being sent to the shader. + /// + /// + public void set_matrix4(string name, Matrix4 data) + { + if (!_uniformLocations.ContainsKey(name)) return; + bind(); + GL.UniformMatrix4(_uniformLocations[name], true, ref data); + } + + /// + /// Set a uniform Vector3 on this shader. + /// + /// The name of the uniform + /// The data to set + public void set_vector3(string name, Vector3 data) + { + if (!_uniformLocations.ContainsKey(name)) return; + bind(); + GL.Uniform3(_uniformLocations[name], data); + } + + /// + /// Set a uniform Vector2 on this shader. + /// + /// The name of the uniform + /// The data to set + public void set_vector2(string name, Vector2 data) + { + if (!_uniformLocations.ContainsKey(name)) return; + bind(); + GL.Uniform2(_uniformLocations[name], data); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Texture.cs b/shdr/Engine/Texture.cs new file mode 100644 index 0000000..e4b0bc1 --- /dev/null +++ b/shdr/Engine/Texture.cs @@ -0,0 +1,112 @@ +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using StbImageSharp; + +namespace shdr.Engine +{ + // taken from https://github.com/opentk/LearnOpenTK/blob/master/Common/Texture.cs + public class __texture + { + private static int _active; + private static readonly Dictionary _textures = new(); + private readonly int _handle; + public readonly float height; + + public readonly float width; + + private __texture(int glHandle, int width, int height) + { + _handle = glHandle; + this.width = width; + this.height = height; + _textures[glHandle] = this; + } + + public static __texture load_from_file(string path) + { + int handle = GL.GenTexture(); + + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, handle); + + StbImage.stbi_set_flip_vertically_on_load(1); + using Stream stream = File.OpenRead(path); + ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha); + + GL.TexImage2D(TextureTarget.Texture2D, + 0, + PixelInternalFormat.Rgba, + image.Width, + image.Height, + 0, + PixelFormat.Bgra, + PixelType.UnsignedByte, + image.Data); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, + (int)TextureMinFilter.NearestMipmapNearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); + + GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + + return new __texture(handle, image.Width, image.Height); + } + + public static __texture load_from_buffer(byte[] buffer, int width, int height, PixelFormat format, + PixelInternalFormat internalFormat, TextureMinFilter minFilter = TextureMinFilter.LinearMipmapLinear, + TextureMagFilter magFilter = TextureMagFilter.Linear) + { + int handle = GL.GenTexture(); + + GL.ActiveTexture(TextureUnit.Texture0); + GL.BindTexture(TextureTarget.Texture2D, handle); + +#pragma warning disable CA1416 + GL.TexImage2D(TextureTarget.Texture2D, + 0, + internalFormat, + width, + height, + 0, + format, + PixelType.UnsignedByte, + buffer); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)minFilter); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)magFilter); + + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); + + if (minFilter is TextureMinFilter.LinearMipmapLinear or TextureMinFilter.LinearMipmapNearest or TextureMinFilter.NearestMipmapNearest) + GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); + + return new __texture(handle, width, height); +#pragma warning restore CA1416 + } + + public void bind(TextureUnit unit) + { + if (_handle == _active) return; + GL.ActiveTexture(unit); + GL.BindTexture(TextureTarget.Texture2D, _handle); + _active = _handle; + } + + public static void unbind() + { + GL.BindTexture(TextureTarget.Texture2D, 0); + _active = 0; + } + + public static Vector2 current_bounds() + { + if (!_textures.ContainsKey(_active)) return new Vector2(1, 1); + __texture current = _textures[_active]; + return new Vector2(current.width, current.height); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Vao.cs b/shdr/Engine/Vao.cs new file mode 100644 index 0000000..e815d68 --- /dev/null +++ b/shdr/Engine/Vao.cs @@ -0,0 +1,48 @@ +using OpenTK.Graphics.OpenGL4; + +namespace shdr.Engine +{ + public class __vao + { + public enum __attrib + { + float1 = 1, + float2 = 2, + float3 = 3, + float4 = 4 + } + + private static int _active; + private readonly int _handle; + + public __vao(params __attrib[] attribs) + { + _handle = GL.GenVertexArray(); + bind(); + int stride = attribs.Sum(attrib => (int)attrib); + int offset = 0; + for (int i = 0; i < attribs.Length; i++) + { + GL.EnableVertexAttribArray(i); + GL.VertexAttribPointer(i, (int)attribs[i], VertexAttribPointerType.Float, false, stride * sizeof(float), + offset); + offset += (int)attribs[i] * sizeof(float); + } + + unbind(); + } + + public void bind() + { + if (_handle == _active) return; + GL.BindVertexArray(_handle); + _active = _handle; + } + + public static void unbind() + { + GL.BindVertexArray(0); + _active = 0; + } + } +} \ No newline at end of file diff --git a/shdr/Engine/Vbo.cs b/shdr/Engine/Vbo.cs new file mode 100644 index 0000000..d265cc9 --- /dev/null +++ b/shdr/Engine/Vbo.cs @@ -0,0 +1,50 @@ +using OpenTK.Graphics.OpenGL4; + +namespace shdr.Engine +{ + public class __vbo + { + private static int _active; + private readonly byte[] _bitDest = new byte[4]; + private readonly int _handle; + private readonly MemoryStream _vertices; + + public __vbo(int initialCapacity) + { + _handle = GL.GenBuffer(); + _vertices = new MemoryStream(initialCapacity); + } + + public void bind() + { + if (_handle == _active) return; + GL.BindBuffer(BufferTarget.ArrayBuffer, _handle); + _active = _handle; + } + + public static void unbind() + { + GL.BindBuffer(BufferTarget.ArrayBuffer, 0); + _active = 0; + } + + public void put(float element) + { + BitConverter.TryWriteBytes(_bitDest, element); + _vertices.Write(_bitDest); + } + + public void upload(bool unbindAfter = true) + { + if (_active != _handle) bind(); + GL.BufferData(BufferTarget.ArrayBuffer, (int)_vertices.Length, _vertices.GetBuffer(), + BufferUsageHint.DynamicDraw); + if (unbindAfter) unbind(); + } + + public void clear() + { + _vertices.SetLength(0); + } + } +} \ No newline at end of file diff --git a/shdr/Engine/VertexData.cs b/shdr/Engine/VertexData.cs new file mode 100644 index 0000000..f8697ef --- /dev/null +++ b/shdr/Engine/VertexData.cs @@ -0,0 +1,18 @@ +using OpenTK.Mathematics; + +namespace shdr.Engine +{ + public class __vertex_data + { + public uint color = 0xffffffff; + public Vector3 normal; + public Vector3 pos; + public Vector2 uv; + + public __vertex_data(Vector3 pos, Vector2 uv) + { + this.pos = pos; + this.uv = uv; + } + } +} \ No newline at end of file diff --git a/shdr/Program.cs b/shdr/Program.cs new file mode 100644 index 0000000..695b529 --- /dev/null +++ b/shdr/Program.cs @@ -0,0 +1,27 @@ +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.Desktop; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace shdr +{ + public static class __program + { + // ReSharper disable once InconsistentNaming + [STAThread] + public static void Main(string[] args) + { + NativeWindowSettings nativeWindowSettings = new() + { + Size = new Vector2i(1152, 720), + Title = "shdr", + Flags = ContextFlags.ForwardCompatible + }; + + GLFW.Init(); + GLFW.WindowHint(WindowHintBool.Resizable, false); + using __shdr window = new(GameWindowSettings.Default, nativeWindowSettings); + window.Run(); + } + } +} \ No newline at end of file diff --git a/shdr/Resource/Font/Dank Mono Italic.otf b/shdr/Resource/Font/Dank Mono Italic.otf new file mode 100644 index 0000000..3b879b2 Binary files /dev/null and b/shdr/Resource/Font/Dank Mono Italic.otf differ diff --git a/shdr/Resource/Font/JetBrainsMono-Regular.ttf b/shdr/Resource/Font/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000..8da8aa4 Binary files /dev/null and b/shdr/Resource/Font/JetBrainsMono-Regular.ttf differ diff --git a/shdr/Resource/Font/monofur-regular.ttf b/shdr/Resource/Font/monofur-regular.ttf new file mode 100644 index 0000000..9aebf80 Binary files /dev/null and b/shdr/Resource/Font/monofur-regular.ttf differ diff --git a/shdr/Resource/Font/saxmono.ttf b/shdr/Resource/Font/saxmono.ttf new file mode 100644 index 0000000..76c77d6 Binary files /dev/null and b/shdr/Resource/Font/saxmono.ttf differ diff --git a/shdr/Resource/Shader/basic.frag b/shdr/Resource/Shader/basic.frag new file mode 100644 index 0000000..5a21f21 --- /dev/null +++ b/shdr/Resource/Shader/basic.frag @@ -0,0 +1,9 @@ +#version 330 core + +in vec4 ourColor; + +out vec4 color; + +void main() { + color = ourColor; +} \ No newline at end of file diff --git a/shdr/Resource/Shader/basic.vert b/shdr/Resource/Shader/basic.vert new file mode 100644 index 0000000..f8180d1 --- /dev/null +++ b/shdr/Resource/Shader/basic.vert @@ -0,0 +1,13 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec4 aColor; + +out vec4 ourColor; + +uniform mat4 _proj; + +void main() { + gl_Position = vec4(aPos, 1.0) * _proj; + ourColor = aColor; +} \ No newline at end of file diff --git a/shdr/Resource/Shader/font.frag b/shdr/Resource/Shader/font.frag new file mode 100644 index 0000000..f4be206 --- /dev/null +++ b/shdr/Resource/Shader/font.frag @@ -0,0 +1,12 @@ +#version 330 core + +in vec4 ourColor; +in vec2 ourTexCoord; + +out vec4 color; + +uniform sampler2D ourTexture; + +void main() { + color = vec4(vec3(1), texture(ourTexture, ourTexCoord)) * ourColor; +} \ No newline at end of file diff --git a/shdr/Resource/Shader/font.vert b/shdr/Resource/Shader/font.vert new file mode 100644 index 0000000..aad8085 --- /dev/null +++ b/shdr/Resource/Shader/font.vert @@ -0,0 +1,16 @@ +#version 330 core + +layout (location = 0) in vec3 aPos; +layout (location = 1) in vec2 aTexCoord; +layout (location = 2) in vec4 color; + +out vec4 ourColor; +out vec2 ourTexCoord; + +uniform mat4 _proj; + +void main() { + gl_Position = vec4(aPos, 1.0) * _proj; + ourColor = color; + ourTexCoord = aTexCoord; +} \ No newline at end of file diff --git a/shdr/Resource/Shader/user.frag b/shdr/Resource/Shader/user.frag new file mode 100644 index 0000000..a46b983 --- /dev/null +++ b/shdr/Resource/Shader/user.frag @@ -0,0 +1,13 @@ +#version 410 core + +vec2 uv; +out vec4 color; + +uniform vec2 _resolution; +uniform float _time; +uniform sampler2D _prevFrame; + +void main() { + uv = gl_FragCoord.xy / _resolution.xy; + color = vec4(uv.r, 0., uv.g, 1.); +} \ No newline at end of file diff --git a/shdr/Resource/Shader/user.vert b/shdr/Resource/Shader/user.vert new file mode 100644 index 0000000..36d3ffd --- /dev/null +++ b/shdr/Resource/Shader/user.vert @@ -0,0 +1,7 @@ +#version 410 core + +layout (location = 0) in vec2 aPos; + +void main() { + gl_Position = vec4(aPos, 0.0, 1.0); +} \ No newline at end of file diff --git a/shdr/Resource/Texture/glslfuncs.txt b/shdr/Resource/Texture/glslfuncs.txt new file mode 100644 index 0000000..ee6dca7 --- /dev/null +++ b/shdr/Resource/Texture/glslfuncs.txt @@ -0,0 +1,196 @@ +all +any +asin +asinh +atan +atanh +atomicAdd +atomicAnd +atomicCompSwap +atomicCounter +atomicCounterDecrement +atomicCounterIncrement +atomicExchange +atomicMax +atomicMin +atomicOr +atomicXor +abs +acos +acosh +barrier +bitCount +bitfieldExtract +bitfieldInsert +bitfieldReverse +ceil +clamp +cos +cosh +cross +degrees +determinant +dFdx +dFdxCoarse +dFdxFine +dFdy +dFdyCoarse +dFdyFine +distance +dot +EmitStreamVertex +EmitVertex +EndPrimitive +EndStreamPrimitive +equal +exp +exp2 +faceforward +findLSB +findMSB +floatBitsToInt +floatBitsToUint +floor +fma +fract +frexp +fwidth +fwidthCoarse +fwidthFine +gl_ClipDistance +gl_CullDistance +gl_FragCoord +gl_FragDepth +gl_FrontFacing +gl_GlobalInvocationID +gl_HelperInvocation +gl_InstanceID +gl_InvocationID +gl_Layer +gl_LocalInvocationID +gl_LocalInvocationIndex +gl_NumSamples +gl_NumWorkGroups +gl_PatchVerticesIn +gl_PointCoord +gl_PointSize +gl_Position +gl_PrimitiveID +gl_PrimitiveIDIn +gl_SampleID +gl_SampleMask +gl_SampleMaskIn +gl_SamplePosition +gl_TessCoord +gl_TessLevelInner +gl_TessLevelOuter +gl_VertexID +gl_ViewportIndex +gl_WorkGroupID +gl_WorkGroupSize +greaterThan +greaterThanEqual +groupMemoryBarrier +imageAtomicAdd +imageAtomicAnd +imageAtomicCompSwap +imageAtomicExchange +imageAtomicMax +imageAtomicMin +imageAtomicOr +imageAtomicXor +imageLoad +imageSamples +imageSize +imageStore +imulExtended +intBitsToFloat +interpolateAtCentroid +interpolateAtOffset +interpolateAtSample +inverse +inversesqrt +isinf +isnan +ldexp +length +lessThan +lessThanEqual +log +log2 +matrixCompMult +max +memoryBarrier +memoryBarrierAtomicCounter +memoryBarrierBuffer +memoryBarrierImage +memoryBarrierShared +min +mix +mod +modf +noise +noise1 +noise2 +noise3 +noise4 +normalize +not +notEqual +outerProduct +packDouble2x32 +packHalf2x16 +packSnorm2x16 +packSnorm4x8 +packUnorm +packUnorm2x16 +packUnorm4x8 +pow +radians +reflect +refract +removedTypes +round +roundEven +sign +sin +sinh +smoothstep +sqrt +step +tan +tanh +texelFetch +texelFetchOffset +texture +textureGather +textureGatherOffset +textureGatherOffsets +textureGrad +textureGradOffset +textureLod +textureLodOffset +textureOffset +textureProj +textureProjGrad +textureProjGradOffset +textureProjLod +textureProjLodOffset +textureProjOffset +textureQueryLevels +textureQueryLod +textureSamples +textureSize +transpose +trunc +uaddCarry +uintBitsToFloat +umulExtended +unpackDouble2x32 +unpackHalf2x16 +unpackSnorm2x16 +unpackSnorm4x8 +unpackUnorm +unpackUnorm2x16 +unpackUnorm4x8 +usubBorrow \ No newline at end of file diff --git a/shdr/Shared/AABB.cs b/shdr/Shared/AABB.cs new file mode 100644 index 0000000..67444bf --- /dev/null +++ b/shdr/Shared/AABB.cs @@ -0,0 +1,22 @@ +namespace shdr.Shared +{ + public struct __aabb + { + public float minX; + public float minY; + public float minZ; + public float maxX; + public float maxY; + public float maxZ; + + public __aabb(float minX, float minY, float minZ, float maxX, float maxY, float maxZ) + { + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + } + } +} \ No newline at end of file diff --git a/shdr/Shared/DiscordRpc.cs b/shdr/Shared/DiscordRpc.cs new file mode 100644 index 0000000..bd80f34 --- /dev/null +++ b/shdr/Shared/DiscordRpc.cs @@ -0,0 +1,39 @@ +using NetDiscordRpc; +using NetDiscordRpc.RPC; +using OpenTK.Windowing.GraphicsLibraryFramework; + +namespace shdr.Shared +{ + public static class __discord_rpc + { + private static DiscordRPC _client; + + public static void init() + { + _client = new DiscordRPC("1043932456606244896"); + _client.Initialize(); + + new Thread(() => + { + unsafe + { + while (!GLFW.WindowShouldClose(__shdr.instance.WindowPtr)) + { + _client.SetPresence(new RichPresence + { + Assets = new Assets + { + LargeImageKey = "cover-image", + LargeImageText = "GLSLand" + }, + Details = $"Editing {__shdr.path}", + State = $"Line {__shdr.dat.end.lin}" + }); + Thread.Sleep(2000); + } + _client.Dispose(); + } + }).Start(); + } + } +} \ No newline at end of file diff --git a/shdr/Shared/Extensions.cs b/shdr/Shared/Extensions.cs new file mode 100644 index 0000000..2401554 --- /dev/null +++ b/shdr/Shared/Extensions.cs @@ -0,0 +1,160 @@ +using System.Text; +using OpenTK.Mathematics; + +namespace shdr.Shared +{ + public static class __maps + { + public static Dictionary create(params KeyValuePair[] pairs) + { + return pairs.ToDictionary(pair => pair.Key, pair => pair.Value); + } + } + + public static class __extensions + { + public static string content_to_string(this t[] arr) + { + string o = arr.ToString() ?? string.Empty; + o = o[..^1]; + foreach (t item in arr) o += item + ", "; + o = o[..^2]; + o += "]"; + return o; + } + + public static string repeat(this string str, int times) + { + return new StringBuilder(str.Length * times).Insert(0, str, times).ToString(); + } + + public static string content_to_string(this Dictionary arr) + { + StringBuilder o = new("Map<"); + o.Append(typeof(t)); + o.Append(", "); + o.Append(typeof(tv)); + o.Append(">("); + foreach (KeyValuePair item in arr) + { + o.Append('('); + o.Append(item.Key); + o.Append(", "); + o.Append(item.Value); + o.Append("), "); + } + + if (arr.Count > 0) o.Remove(o.Length - 3, 3); + o.Append(')'); + return o.ToString(); + } + + public static void transform(this ref Vector4 vec, Matrix4 m4F) + { + float f = vec.X; + float g = vec.Y; + float h = vec.Z; + float i = vec.W; + vec.X = MathF.FusedMultiplyAdd(m4F.M11, f, + MathF.FusedMultiplyAdd(m4F.M21, g, MathF.FusedMultiplyAdd(m4F.M31, h, m4F.M41 + i))); + vec.Y = MathF.FusedMultiplyAdd(m4F.M12, f, + MathF.FusedMultiplyAdd(m4F.M22, g, MathF.FusedMultiplyAdd(m4F.M32, h, m4F.M42 + i))); + vec.Z = MathF.FusedMultiplyAdd(m4F.M13, f, + MathF.FusedMultiplyAdd(m4F.M23, g, MathF.FusedMultiplyAdd(m4F.M33, h, m4F.M43 + i))); + vec.W = MathF.FusedMultiplyAdd(m4F.M14, f, + MathF.FusedMultiplyAdd(m4F.M24, g, MathF.FusedMultiplyAdd(m4F.M34, h, m4F.M44 + i))); + } + + public static Vector2 normalized_fast(this ref Vector2 vec) + { + if (vec == Vector2.Zero) return vec; + float length = MathHelper.InverseSqrtFast((float)(vec.X * (double)vec.X + vec.Y * (double)vec.Y)); + vec.X *= length; + vec.Y *= length; + return vec; + } + + public static Vector3 normalized_fast(this ref Vector3 vec) + { + if (vec == Vector3.Zero) return vec; + float length = + MathHelper.InverseSqrtFast((float)(vec.X * (double)vec.X + vec.Y * (double)vec.Y + vec.Z * (double)vec.Z)); + vec.X *= length; + vec.Y *= length; + vec.Z *= length; + return vec; + } + + public static float to_radians(this float degrees) + { + return (float)(degrees * Math.PI / 180.0); + } + + public static float to_degrees(this float radians) + { + return (float)(radians * 180 / Math.PI); + } + + public static void scale(this ref Matrix4 matrix4, float scalar) + { + matrix4 *= Matrix4.CreateScale(scalar); + } + + public static void scale(this ref Matrix4 matrix4, Vector3 scalar) + { + matrix4 *= Matrix4.CreateScale(scalar); + } + + public static void scale(this ref Matrix4 matrix4, float x, float y, float z) + { + matrix4 *= Matrix4.CreateScale(x, y, z); + } + + public static void translate(this ref Matrix4 matrix4, Vector3 translation) + { + matrix4 *= Matrix4.CreateTranslation(translation); + } + + public static void translate(this ref Matrix4 matrix4, float x, float y, float z) + { + matrix4 *= Matrix4.CreateTranslation(x, y, z); + } + + public static void rotate(this ref Matrix4 matrix4, float angle, Vector3 axis) + { + matrix4 *= Matrix4.CreateFromAxisAngle(axis, angle / 180f * MathF.PI); + } + + public static void rotate(this ref Matrix4 matrix4, float angle, float x, float y, float z) + { + matrix4 *= Matrix4.CreateFromAxisAngle(new Vector3(x, y, z), angle / 180f * MathF.PI); + } + + public static void set(this ref Matrix4 mat, Matrix4 other) + { + mat.M11 = other.M11; + mat.M12 = other.M12; + mat.M13 = other.M13; + mat.M14 = other.M14; + mat.M21 = other.M21; + mat.M22 = other.M22; + mat.M23 = other.M23; + mat.M24 = other.M24; + mat.M31 = other.M31; + mat.M32 = other.M32; + mat.M33 = other.M33; + mat.M34 = other.M34; + mat.M41 = other.M41; + mat.M42 = other.M42; + mat.M43 = other.M43; + mat.M44 = other.M44; + } + + public static int distance_sq(this Vector2i vec, Vector2i other) + { + (int x, int y) = vec; + (int i, int i1) = other; + return (x - i) * (x - i) + (y - i1) * (y - i1); + } + } +} \ No newline at end of file diff --git a/shdr/Shared/Formatting.cs b/shdr/Shared/Formatting.cs new file mode 100644 index 0000000..a5b898a --- /dev/null +++ b/shdr/Shared/Formatting.cs @@ -0,0 +1,71 @@ +namespace shdr.Shared +{ + public sealed class __fmt + { + public static readonly Dictionary values = new(); + + public static readonly __fmt black = new(0, '0'); + public static readonly __fmt darkblue = new(0x0000aa, '1'); + public static readonly __fmt darkgreen = new(0x00aa00, '2'); + public static readonly __fmt darkcyan = new(0x00aaaa, '3'); + public static readonly __fmt darkred = new(0xaa0000, '4'); + public static readonly __fmt darkpurple = new(0xaa00aa, '5'); + public static readonly __fmt gold = new(0xffaa00, '6'); + public static readonly __fmt gray = new(0xaaaaaa, '7'); + public static readonly __fmt darkgray = new(0x555555, '8'); + public static readonly __fmt blue = new(0x5555ff, '9'); + public static readonly __fmt green = new(0x55ff55, 'a'); + public static readonly __fmt cyan = new(0x55ffff, 'b'); + public static readonly __fmt red = new(0xff5555, 'c'); + public static readonly __fmt purple = new(0xff55ff, 'd'); + public static readonly __fmt yellow = new(0xffff55, 'e'); + public static readonly __fmt white = new(0xffffff, 'f'); + public static readonly __fmt reset = new(0, 'r'); + public static readonly __fmt keyword = new(0xff7084, 'g'); + public static readonly __fmt number = new(0xa0ffe0, 'h'); + public static readonly __fmt normal = new (0xffffff, 'i'); + public static readonly __fmt operator_ = new(0xabc8ff, 'j'); + public static readonly __fmt function = new(0x66e5ff, 'k'); + + public static string key(string str) + { + return $"{__fmt.keyword}{str}{__fmt.normal}"; + } + + public static string num(string str) + { + return $"{__fmt.number}{str}{__fmt.normal}"; + } + + public static string norm(string str) + { + return $"{__fmt.normal}{str}{__fmt.normal}"; + } + + public static string op(string str) + { + return $"{__fmt.operator_}{str}{__fmt.normal}"; + } + + public static string func(string str) + { + return $"{__fmt.function}{str}{__fmt.normal}"; + } + + public override string ToString() + { + return "\u00a7" + _code; + } + + private readonly char _code; + + public readonly uint color; + + private __fmt(uint color, char code) + { + this.color = color; + _code = code; + values[code] = this; + } + } +} \ No newline at end of file diff --git a/shdr/Shared/TextBox.cs b/shdr/Shared/TextBox.cs new file mode 100644 index 0000000..7e0c9fc --- /dev/null +++ b/shdr/Shared/TextBox.cs @@ -0,0 +1,516 @@ +using System.Collections.Concurrent; +using System.Numerics; +using System.Text; +using System.Text.RegularExpressions; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using OpenTK.Windowing.GraphicsLibraryFramework; +using shdr.Engine; + +namespace shdr.Shared +{ + public static class __text_box + { + public struct __pos + { + public int col; + public int lin; + + public static bool operator ==(__pos one, __pos two) + { + return one.col == two.col && one.lin == two.lin; + } + + public static bool operator !=(__pos one, __pos two) + { + return !(one == two); + } + } + + public struct __data + { + public float lastUpdate = 0; + public __pos prevStart = default; + public __pos prevEnd = default; + public __pos start = new(); + public __pos end = new(); + public float scroll = 0f; + public List text = new(); + public List display = new(); + + public __data() + { + } + } + + public enum __dir + { + up, + down, + left, + right, + none + } + + private static readonly Dictionary> _fmt; + private static readonly HashSet _fmtKeys; + private static readonly HashSet _delimiters; + private static readonly HashSet _operators; + + static __text_box() + { + List keywords = new() + { + "^float$", + "^int$", + "^vec2$", + "^vec3$", + "^vec4$", + "^void$", + "^layout$", + "^in$", + "^out$", + "^inout$", + "^if$", + "^for$", + "^while$", + "^const$", + "^uniform$", + "^sampler2D$", + "^sampler1D$", + "^sampler3D$", + "^return$", + "^break$", + "^continue$", + "^#[a-zA-Z0-9_]+$", + }; + _fmt = new Dictionary> + { + { "-?^\\d*e?\\.?\\d*", __fmt.num } + }; + foreach (string str in keywords) + { + _fmt[str] = __fmt.key; + } + + foreach (string str in File.ReadLines("Resource/Texture/glslfuncs.txt")) + { + _fmt[str] = __fmt.func; + } + + _fmtKeys = new HashSet(_fmt.Keys); + _delimiters = new HashSet + { + "(", ")", "{", "}", "[", "]", ";", ",", ".", "+", "-", "*", "/", "%", "=", "!", "<", ">", "&", "|", "^", + "~", "?", ":", "\\", "\"", "'", "`", " ", "\n" + }; + _operators = new HashSet + { + "(", ")", "{", "}", "[", "]", "+", "-", "*", "/", "%", "=", "!", "<", ">", "&", "|", "^", "~", "?", ":", "\\", "\"", "'", "`", ";" + }; + } + + public static void update(ref __data dat, bool firstRun = false) + { + if (dat.display.Count < dat.text.Count) + { + dat.display.AddRange(new string[dat.text.Count - dat.display.Count]); + } + if (dat.display.Count > dat.text.Count) + { + dat.display.RemoveRange(dat.text.Count, dat.display.Count - dat.text.Count); + } + for (int i = firstRun ? 0 : Math.Min(dat.start.lin, dat.end.lin); + i <= + (firstRun + ? dat.text.Count - 1 + : Math.Max(dat.start.lin, dat.end.lin)); + i++) + { + string str = dat.text[i]; + StringBuilder full = new(); + StringBuilder word = new(); + foreach (char c in str) + { + if (_delimiters.Contains(c.ToString())) + { + string st = word.ToString(); + string works = ""; + foreach (string key in _fmtKeys) + { + Match mat = Regex.Match(st, key); + if (mat.Value == st) + { + works = key; + break; + } + } + + full.Append(works != "" ? _fmt[works](st) : __fmt.norm(st)); + full.Append(_operators.Contains(c.ToString()) ? __fmt.op(c.ToString()) : __fmt.norm(c.ToString())); + word.Clear(); + continue; + } + + word.Append(c); + } + + { + string st = word.ToString(); + string works = ""; + foreach (string key in _fmtKeys) + { + Match mat = Regex.Match(st, key); + if (mat.Value == st) + { + works = key; + break; + } + } + + full.Append(works != "" ? _fmt[works](st) : __fmt.norm(st)); + word.Clear(); + } + + dat.display[i] = full.ToString(); + } + } + + private static float safe(int e) + { + return __font.get_width(" ") * e - (e - 1) * 0.4f; + } + + public static void render(ref __data dat, float x, float y, float width, float height) + { + float d = MathF.Pow(MathHelper.Clamp((Environment.TickCount - dat.lastUpdate) / 100f, 0, 1), 2f); + float sline = __util.lerp(dat.prevStart.lin, dat.start.lin, d); + float scol = __util.lerp(safe(dat.prevStart.col), + __font.get_width(dat.text[dat.start.lin][..dat.start.col]), d); + float eline = __util.lerp(dat.prevEnd.lin, dat.end.lin, d); + float ecol = __util.lerp(safe(dat.prevEnd.col), + __font.get_width(dat.text[dat.end.lin][..dat.end.col]), d); + float lineHeight = __font.get_height() * 1.6f; + + if (sline < -dat.scroll) + { + dat.scroll = -sline; + } + if (eline > -dat.scroll + (int)(height - 20) / lineHeight - 1.5f) + { + dat.scroll = -eline + (int)(height - 20) / lineHeight - 1.5f; + } + + uint cyan = (uint)new Color4(0, 238, 255, + (byte)((Math.Abs(Math.Sin(GLFW.GetTime() % 1.0 * Math.PI)) + 1) * 127)).ToArgb(); + + uint hotPink = (uint)new Color4(0xFF, 0x00, 0x94, + (byte)((Math.Abs(Math.Sin(GLFW.GetTime() % 1.0 * Math.PI)) + 1) * 127)).ToArgb(); + GL.Enable(EnableCap.ScissorTest); + GL.Scissor((int)Math.Floor(x), (int)Math.Floor(y), (int)Math.Ceiling(width), (int)Math.Ceiling(height)); + float textOffset = dat.scroll * lineHeight + 15f; + + __util.draw_rect(x, y, width, textOffset + lineHeight * eline, 0xcc202531); + __util.draw_rect(x, y + textOffset + lineHeight + lineHeight * eline, width, + height + lineHeight * dat.text.Count, 0xcc202531); + __util.draw_rect(x, y + textOffset + lineHeight * eline, width, lineHeight, 0xee202531); + + __font.bind(); + for (int i = 0; i < dat.display.Count; i++) + { + __font.draw((i + 1).ToString(), x + 20, y + i * lineHeight + textOffset + 2.5f, 0xffcccccc, true); + __font.draw(dat.display[i], x + 50, y + i * lineHeight + textOffset + 2.5f, 0xffffffff, true); + } + + __font.render(); + + __util.draw_rect(x + 50 + scol + -1, y + textOffset + sline * lineHeight + 2, 2, lineHeight - 4, cyan); + __util.draw_rect(x + 50 + ecol - 1, y + textOffset + eline * lineHeight + 2, 2, lineHeight - 4, hotPink); + + GL.Disable(EnableCap.ScissorTest); + } + + private static void ensure_pos(ref __data dat, ref __pos pos, __dir dir) + { + pos.lin = MathHelper.Clamp(pos.lin, 0, dat.text.Count - 1); + + if (pos.col > dat.text[pos.lin].Length) + { + if (pos.lin == dat.text.Count - 1) + { + pos.col = dat.text[pos.lin].Length; + } + else if (dir is __dir.down or __dir.up) + { + pos.col = dat.text[pos.lin].Length; + } + else + { + pos.lin++; + pos.col = 0; + } + } + + if (pos.col < 0) + { + if (pos.lin == 0) + { + pos.col = 0; + } + else + { + pos.lin--; + pos.col = dat.text[pos.lin].Length; + } + } + } + + private static void ensure_poses(ref __data dat, __dir dir) + { + if (dat.start.lin > dat.end.lin || (dat.start.lin == dat.end.lin && dat.start.col > dat.end.col)) + { + (dat.start, dat.end) = (dat.end, dat.start); + } + + ensure_pos(ref dat, ref dat.start, dir); + ensure_pos(ref dat, ref dat.end, dir); + } + + private static int spaces(string str) + { + return str.Length - str.TrimStart().Length; + } + + public static void wheel(ref __data dat, float scroll) + { + dat.scroll += Math.Sign(scroll); + } + + public static void key(ref __data dat, Keys key, bool shiftDown, bool controlDown) + { + dat.lastUpdate = Environment.TickCount; + dat.prevEnd = dat.end; + dat.prevStart = dat.start; + + bool typingHappened = false; + bool important = false; + + void cursor(ref __data dat, Vector2i dir) + { + ref __pos one = ref dat.end; + if (dir.X < 0 || dir.Y < 0) + { + one = ref dat.start; + } + + ref __pos two = ref dat.end; + if (dir.X > 0 || dir.Y > 0) + { + two = ref dat.start; + } + + one.col += dir.X; + one.lin += dir.Y; + if (shiftDown) return; + two.col = one.col; + two.lin = one.lin; + } + + __dir dir = __dir.none; + + switch (key) + { + case Keys.S: + if (controlDown) + { + string str = string.Join("\n", dat.text); + File.WriteAllText(__shdr.path, str); + try + { + __render_system.user = new __shader("Resource/Shader/user.vert", __shdr.path); + } + catch (Exception e) + { + Console.WriteLine(e); + } + } + + break; + case Keys.Down: + cursor(ref dat, (0, 1)); + dir = __dir.down; + break; + case Keys.Up: + cursor(ref dat, (0, -1)); + dir = __dir.up; + break; + case Keys.Left: + cursor(ref dat, (-1, 0)); + dir = __dir.left; + break; + case Keys.Right: + cursor(ref dat, (1, 0)); + dir = __dir.right; + break; + case Keys.Home: + if (controlDown) + { + dat.end.lin = 0; + dat.end.col = 0; + } + else + { + dat.end.col = spaces(dat.text[dat.end.lin]); + } + + if (!shiftDown) + { + dat.start.col = dat.end.col; + dat.start.lin = dat.end.lin; + } + + break; + case Keys.End: + if (controlDown) + { + dat.end.lin = dat.text.Count - 1; + } + + dat.end.col = dat.text[dat.end.lin].Length; + if (!shiftDown) + { + dat.start.col = dat.end.col; + dat.start.lin = dat.end.lin; + } + + break; + case Keys.Enter: + { + important = true; + typingHappened = true; + string text = dat.text[dat.start.lin]; + int s = spaces(dat.text[dat.start.lin]); + if (dat.start == dat.end) + { + dat.text[dat.start.lin] = text[..dat.start.col]; + dat.text.Insert(dat.end.lin + 1, " ".repeat(s) + text[dat.start.col..]); + } + + dat.start.lin++; + dat.start.col = s; + dat.end.col = s; + dat.end.lin = dat.start.lin; + break; + } + case Keys.Backspace: + typingHappened = true; + string text1 = dat.text[dat.start.lin]; + if (dat.start == dat.end) + { + if (dat.start.col > 0) + { + dat.text[dat.start.lin] = text1[..(dat.start.col - 1)] + text1[dat.start.col..]; + dat.start.col--; + dat.end.col--; + } + else if (dat.start.lin > 0) + { + important = true; + dat.start.lin--; + dat.end.lin--; + dat.start.col = dat.end.col = dat.text[dat.start.lin].Length; + dat.text[dat.start.lin] += text1; + dat.text.RemoveAt(dat.start.lin + 1); + } + } + else + { + if (dat.end.lin != dat.start.lin) + { + important = true; + dat.text[dat.start.lin] = text1[..dat.start.col] + dat.text[dat.end.lin][dat.end.col..]; + dat.text[dat.end.lin] = dat.text[dat.end.lin][dat.end.col..]; + for (int i = dat.start.lin + 1; i <= dat.end.lin; i++) + { + dat.text.RemoveAt(dat.start.lin + 1); + } + } + else + { + dat.text[dat.start.lin] = text1[..dat.start.col] + text1[dat.end.col..]; + } + + dat.end = dat.start; + } + + break; + case Keys.Delete: + typingHappened = true; + dat.end.col++; + dat.start.col++; + ensure_pos(ref dat, ref dat.end, __dir.right); + ensure_pos(ref dat, ref dat.start, __dir.right); + __text_box.key(ref dat, Keys.Backspace, shiftDown, controlDown); + break; + case Keys.Tab: + typingHappened = true; + if (dat.start == dat.end) + { + string text2 = dat.text[dat.start.lin]; + if (shiftDown) + { + int ec = dat.end.col; + int el = dat.end.lin; + if (ec >= 2) + { + dat.end.col -= 2; + dat.start.col -= 2; + if (dat.text[el][ec - 1] == dat.text[el][ec - 2] && dat.text[el][ec - 1] == ' ') + { + // remove chars @ ec - 1 and ec -2 + dat.text[el] = text2[..(ec - 2)] + text2[ec..]; + } + } + } + else + { + type(ref dat, " "); + } + } + + break; + } + + if (typingHappened) + update(ref dat, important); + + ensure_poses(ref dat, dir); + } + + public static void type(ref __data dat, string str) + { + dat.lastUpdate = Environment.TickCount; + dat.prevEnd = dat.end; + dat.prevStart = dat.start; + + if (dat.start == dat.end) + { + dat.text[dat.start.lin] = dat.text[dat.start.lin][..dat.start.col] + str + + dat.text[dat.start.lin][dat.start.col..]; + dat.start.col += str.Length; + dat.end.col = dat.start.col; + } + else + { + string text = dat.text[dat.start.lin]; + dat.text[dat.start.lin] = text[..dat.start.col] + str + text[dat.end.col..]; + dat.start.col += str.Length; + dat.end.col = dat.start.col; + } + + update(ref dat); + + ensure_poses(ref dat, __dir.none); + } + } +} \ No newline at end of file diff --git a/shdr/Shared/Util.cs b/shdr/Shared/Util.cs new file mode 100644 index 0000000..03c1606 --- /dev/null +++ b/shdr/Shared/Util.cs @@ -0,0 +1,31 @@ +using shdr.Engine; + +namespace shdr.Shared +{ + public static class __util + { + public static readonly float sqrt2 = MathF.Sqrt(2); + + public static float lerp(float start, float end, float delta) + { + return start + (end - start) * delta; + } + + public static void clamp(ref int val, int start, int end) + { + val = Math.Min(Math.Max(val, start), end); + } + + public static void draw_rect(float x, float y, float width, float height, uint color) + { + __render_system.basic.begin(); + __render_system.basic.quad( + __render_system.basic.float3(x, y, 0).float4(color).next(), + __render_system.basic.float3(x + width, y, 0).float4(color).next(), + __render_system.basic.float3(x + width, y + height, 0).float4(color).next(), + __render_system.basic.float3(x, y + height, 0).float4(color).next() + ); + __render_system.basic.render(); + } + } +} \ No newline at end of file diff --git a/shdr/code-edit.svg b/shdr/code-edit.svg new file mode 100644 index 0000000..7bdf511 --- /dev/null +++ b/shdr/code-edit.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shdr/shdr.cs b/shdr/shdr.cs new file mode 100644 index 0000000..64abe20 --- /dev/null +++ b/shdr/shdr.cs @@ -0,0 +1,147 @@ +using System.Drawing; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using OpenTK.Windowing.Common; +using OpenTK.Windowing.Desktop; +using OpenTK.Windowing.GraphicsLibraryFramework; +using shdr.Engine; +using shdr.Shared; + +namespace shdr +{ + public class __shdr : GameWindow + { + private static int _ticks; + public static __shdr instance; + public static __text_box.__data dat; + public static string path; + public static __mesh uMesh; + + public __shdr(GameWindowSettings windowSettings, NativeWindowSettings nativeWindowSettings) : base( + windowSettings, nativeWindowSettings) + { + instance = this; + { + path = Console.ReadLine(); + if (path.Trim().Length == 0) + { + int i = 0; + while (File.Exists($"shader{i}.frag")) + { + i++; + } + + path = $"shader{i}.frag"; + } + } + List defaultText = File.ReadLines("Resource/Shader/user.frag").ToList(); + dat = new __text_box.__data + { + text = File.Exists(path) ? File.ReadAllLines(path).ToList() : defaultText + }; + __text_box.update(ref dat, true); + string str = string.Join("\n", dat.text); + File.WriteAllText(path, str); + + try + { + __render_system.user = new __shader("Resource/Shader/user.vert", path); + } + catch (Exception e) + { + __render_system.user = new __shader("Resource/Shader/user.vert", "shader1.frag"); + Console.WriteLine(e.Message); + } + uMesh = new __mesh(__mesh.__draw_mode.triangle, null, __vao.__attrib.float2); + uMesh.begin(); + uMesh.quad( + uMesh.float2(-1, -1).next(), + uMesh.float2(1, -1).next(), + uMesh.float2(1, 1).next(), + uMesh.float2(-1, 1).next() + ); + uMesh.end(); + __discord_rpc.init(); + } + + protected override void OnLoad() + { + base.OnLoad(); + + GL.ClearColor(0f, 0f, 0f, 0f); + GL.DepthFunc(DepthFunction.Lequal); + __gl_state_manager.enable_blend(); + } + + protected override void OnResize(ResizeEventArgs e) + { + base.OnResize(e); + + if (e.Size == Vector2i.Zero) + return; + + GL.ClearColor(0f, 0f, 0f, 0f); + __render_system.update_projection(); + GL.Viewport(new Rectangle(0, 0, Size.X, Size.Y)); + __fbo.resize(Size.X, Size.Y); + } + + protected override void OnMouseWheel(MouseWheelEventArgs e) + { + base.OnMouseWheel(e); + + __text_box.wheel(ref dat, e.OffsetY); + } + + protected override void OnTextInput(TextInputEventArgs e) + { + base.OnTextInput(e); + + __text_box.type(ref dat, e.AsString); + } + + private bool _renderTextBox = true; + + protected override void OnKeyDown(KeyboardKeyEventArgs e) + { + base.OnKeyDown(e); + + if (e.Key == Keys.F1) + { + _renderTextBox = !_renderTextBox; + } + else if (e.Key == Keys.F2) + { + __font.index++; + } + + __text_box.key(ref dat, e.Key, KeyboardState.IsKeyDown(Keys.LeftShift), KeyboardState.IsKeyDown(Keys.LeftControl)); + } + + protected override void OnRenderFrame(FrameEventArgs args) + { + base.OnRenderFrame(args); + + __render_system.frame.bind(); + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + __render_system.user.bind(); + __render_system.prevFrame.bind_color(TextureUnit.Texture15); + __render_system.user.set_int("_prevFrame", 15); + __render_system.user.set_vector2("_resolution", Size.ToVector2()); + __render_system.user.set_float("_time", (float)GLFW.GetTime()); + uMesh.render(); + + __render_system.frame.blit(__render_system.prevFrame.handle); + + __render_system.frame.bind(); + + if (_renderTextBox) + __text_box.render(ref dat, 10, 10, Size.X - 20, Size.Y - 20); + + __render_system.frame.blit(); + + SwapBuffers(); + } + } +} \ No newline at end of file diff --git a/shdr/shdr.csproj b/shdr/shdr.csproj new file mode 100644 index 0000000..53e6c59 --- /dev/null +++ b/shdr/shdr.csproj @@ -0,0 +1,27 @@ + + + + Exe + net6.0 + enable + disable + true + + + + + + + + + + + + + + + + + + +