using System; using System.Collections.Generic; using Quik; using Quik.VertexGenerator; using OpenTK.Graphics.OpenGL4; using OpenTK.Mathematics; using OpenTK.Windowing.Common; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; using Quik.OpenTK; using Quik.Typography; namespace QuikTestApplication { public class Program { public const string vertex = @"#version 140 uniform mat4 matrix; in vec2 position; in vec2 texcoord; in vec4 color; out vec2 ftexcoord; out vec4 fcolor; void main() { fcolor = color; ftexcoord = texcoord; gl_Position = matrix * vec4(position.xy, 0, 1); } "; public const string fragment = @"#version 140 in vec2 ftexcoord; in vec4 fcolor; out vec4 outcolor; uniform sampler2D texture0; void main() { outcolor = fcolor * texture(texture0, ftexcoord); } "; public static void Main(string[] args) { NativeWindowSettings windowSettings = NativeWindowSettings.Default; windowSettings.NumberOfSamples = 4; NativeWindow window = new NativeWindow(windowSettings); window.Context.MakeCurrent(); GL.LoadBindings(new GLFWBindingsContext()); QuikContext context = new QuikContext(new OpenGLTextureManager(), new TextFontManager()); QuikVertexGenerator gen = new QuikVertexGenerator(context); GL.Enable(EnableCap.Multisample); int sp; { int vs, fs; sp = GL.CreateProgram(); vs = GL.CreateShader(ShaderType.VertexShader); fs = GL.CreateShader(ShaderType.FragmentShader); GL.ShaderSource(vs, vertex); GL.CompileShader(vs); GL.ShaderSource(fs, fragment); GL.CompileShader(fs); GL.AttachShader(sp, vs); GL.AttachShader(sp, fs); GL.LinkProgram(sp); GL.UseProgram(sp); } int vbo, ebo, vao; vbo = GL.GenBuffer(); ebo = GL.GenBuffer(); vao = GL.GenVertexArray(); GL.BindVertexArray(vao); GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ebo); int loc; GL.VertexAttribPointer( loc = GL.GetAttribLocation(sp, "position"), 2, VertexAttribPointerType.Float, false, QuikVertex.Stride, QuikVertex.PositionOffset); GL.EnableVertexAttribArray(loc); GL.VertexAttribPointer( loc = GL.GetAttribLocation(sp, "texcoord"), 2, VertexAttribPointerType.Float, false, QuikVertex.Stride, QuikVertex.TextureCoordinatesOffset); GL.EnableVertexAttribArray(loc); GL.VertexAttribPointer( loc = GL.GetAttribLocation(sp, "color"), 4, VertexAttribPointerType.UnsignedByte, true, QuikVertex.Stride, QuikVertex.ColorOffset); GL.EnableVertexAttribArray(loc); loc = GL.GetUniformLocation(sp, "matrix"); int i = 0; QuikStrokeStyle strokeBorder = new QuikStrokeStyle() { Color = new QuikColor(0xaaaaaaff), Width = 8 }; QuikStrokeStyle strokeNoBorder = new QuikStrokeStyle() { Color = new QuikColor(0xaaaaaaff), Width = 0 }; QuikFillStyle fill = new QuikFillStyle() { Color = new QuikColor(0xeeeeeeff) }; int whiteTexture = GL.GenTexture(); uint[] whitePixel = {0xFFFFFFFF}; GL.BindTexture(TextureTarget.Texture2D, whiteTexture); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, 1, 1, 0, PixelFormat.Rgba, PixelType.UnsignedByte, whitePixel); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Nearest); context.DefaultFont = context.FontManager.GetFont(null); window.Context.SwapInterval = 0; for (;!window.IsExiting;) { NativeWindow.ProcessWindowEvents(false); GL.Viewport(0, 0, window.Size.X, window.Size.Y); GL.ClearColor(1,1,1,1); GL.Clear(ClearBufferMask.ColorBufferBit); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); Matrix4 matrix = Matrix4.CreateOrthographicOffCenter( 0, (float)window.Size.X, 0, (float)window.Size.Y, 1, -1); GL.UniformMatrix4(loc, false, ref matrix); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(120, 60, 20, 20)) { CornerRadius = 0, FillStyle = fill, StrokeStyle = strokeNoBorder }); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(240, 60, 140, 20)) { CornerRadius = 4, FillStyle = fill, StrokeStyle = strokeNoBorder }); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(360, 60, 260, 20)) { CornerRadius = 15, FillStyle = fill, StrokeStyle = strokeNoBorder }); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(120, 120, 20, 80)) { CornerRadius = 0, FillStyle = fill, StrokeStyle = strokeBorder }); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(240, 120, 140, 80)) { CornerRadius = 4, FillStyle = fill, StrokeStyle = strokeBorder }); context.Draw.Commands.Enqueue( new QuikCommandRectangle(new QuikRectangle(360, 120, 260, 80)) { CornerRadius = 15, FillStyle = fill, StrokeStyle = strokeBorder }); context.Draw.PutText("Aaah! the cat turned into a cat!", new QuikVec2(25,30)); QuikCommand command; while (context.Draw.Commands.TryDequeue(out command)) { gen.ConsumeCommand(command); } GL.BufferData(BufferTarget.ArrayBuffer, gen.VertexCount * QuikVertex.Stride, ref gen.VertexBuffer[0], BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ElementArrayBuffer, gen.ElementCount * 2, ref gen.ElementBuffer[0], BufferUsageHint.StreamDraw); foreach (QuikDrawCall call in gen.DrawCalls) { GL.BindTexture( TextureTarget.Texture2D, call.Texture == null ? whiteTexture : (call.Texture as OpenGLTexture).TextureId); GL.DrawElements(BeginMode.Triangles, call.Count, DrawElementsType.UnsignedShort, call.Offset); } int callCount = gen.DrawCalls.Count; gen.Clear(); if (++i % 60 == 0) { Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1} Calls: {2}", gen.VertexUsage, gen.ElementUsage, callCount); } window.Context.SwapBuffers(); } } public class TextFontManager : IQuikFontManager { public QuikContext Context { get; set; } private TestFont _font; public void Clear() { } public QuikFont GetFont(QuikFontStyle fontStyle) { if (_font is null) { _font = new TestFont(Context); } return _font; } } } }