// Convert an HSL value into an RGB value. public static RGBA ToRGB(this HSLA hsl) { double p2; if (hsl.L <= 0.5) { p2 = hsl.L * (1 + hsl.S); } else { p2 = hsl.L + hsl.S - hsl.L * hsl.S; } double p1 = 2 * hsl.L - p2; double r, g, b; if (hsl.S == 0) { r = hsl.L; g = hsl.L; b = hsl.L; } else { r = QqhToRgb(p1, p2, hsl.H + 120); g = QqhToRgb(p1, p2, hsl.H); b = QqhToRgb(p1, p2, hsl.H - 120); } // Convert RGB to the 0 to 255 range. return(new RGBA((byte)(r * 255.0), (byte)(g * 255.0), (byte)(b * 255.0))); }
static void Main(string[] args) { Console.WriteLine("The Grid..."); var fd = Libc.Context.open("/dev/dri/card1", Libc.OpenFlags.ReadWrite); using (var ctx = new EGL.Context(fd, EGL.RenderableSurfaceType.OpenGLES) { VerticalSynchronization = true }) { Console.WriteLine($"GL Extensions: {OpenGLES.GL.GetString(OpenGLES.Def.StringName.Extensions)}"); Console.WriteLine($"GL Version: {OpenGLES.GL.GetString(OpenGLES.Def.StringName.Version)}"); Console.WriteLine($"GL Sharding Language Version: {OpenGLES.GL.GetString(OpenGLES.Def.StringName.ShadingLanguageVersion)}"); Console.WriteLine($"GL Vendor: {OpenGLES.GL.GetString(OpenGLES.Def.StringName.Vendor)}"); Console.WriteLine($"GL Renderer: {OpenGLES.GL.GetString(OpenGLES.Def.StringName.Renderer)}"); OpenGLES.GL.glClearColor(1.0f, 1.0f, 1.0f, 0.0f); OpenGLES.GL.glViewport(0, 0, ctx.Width, ctx.Height); var st = DateTime.Now; var frame = 0u; var totalTime = TimeSpan.Zero; var hsl = new Graphic.Drawing.Color.HSLA(0.0d, 1.0d, 0.5d, 255); uint size = 3; const float TRIANGLE_SIZE = 0.8f; var vertices = new Vertex[size]; vertices[0].x = -.5f; vertices[0].y = .5f; vertices[0].r = 1f; vertices[0].g = .0f; vertices[0].b = .0f; vertices[0].a = 1f; vertices[1].x = -.5f; vertices[1].y = -.5f; vertices[1].r = .0f; vertices[1].g = 1f; vertices[1].b = .0f; vertices[1].a = 1f; vertices[2].x = .5f; vertices[2].y = -.5f; vertices[2].r = .0f; vertices[2].g = .0f; vertices[2].b = 1f; vertices[2].a = 1f; var indices = new short[] { 0, 1, 2, 0, 2, 3 }; var vbos = new uint[2]; unsafe { fixed(Vertex *ptrVertex = vertices) fixed(short *ptrIndices = indices) { for (int i = 0; i < size; i++) { vertices[i].x = (float)Math.Cos(-i * (2.0f * Math.PI / (size))) * TRIANGLE_SIZE; vertices[i].y = (float)Math.Sin(-i * (2.0f * Math.PI / (size))) * TRIANGLE_SIZE; } OpenGLES.GL.glBindVertexArray(0); OpenGLES.GL.GenBuffers((uint)vbos.Length, out vbos); OpenGLES.GL.glBindBuffer(OpenGLES.Def.BufferTarget.ArrayBuffer, vbos[0]); OpenGLES.GL.glBufferData(OpenGLES.Def.BufferTarget.ArrayBuffer, (int)(Marshal.SizeOf(typeof(Vertex)) * size), (nint)ptrVertex, OpenGLES.Def.BufferUsageHint.StreamDraw); OpenGLES.GL.glBindBuffer(OpenGLES.Def.BufferTarget.ElementArrayBuffer, vbos[1]); OpenGLES.GL.glBufferData(OpenGLES.Def.BufferTarget.ElementArrayBuffer, (int)(Marshal.SizeOf(typeof(short)) * 6), (nint)ptrIndices, OpenGLES.Def.BufferUsageHint.StreamDraw); OpenGLES.GL.glGenVertexArrays(1, out var vao); OpenGLES.GL.glBindVertexArray(vao); OpenGLES.GL.GenBuffers((uint)vbos.Length, out vbos); OpenGLES.GL.glBindBuffer(OpenGLES.Def.BufferTarget.ArrayBuffer, vbos[0]); OpenGLES.GL.glBufferData(OpenGLES.Def.BufferTarget.ArrayBuffer, (int)(Marshal.SizeOf(typeof(Vertex)) * size), (nint)ptrVertex, OpenGLES.Def.BufferUsageHint.StreamDraw); OpenGLES.GL.glBindBuffer(OpenGLES.Def.BufferTarget.ElementArrayBuffer, vbos[1]); OpenGLES.GL.glBufferData(OpenGLES.Def.BufferTarget.ElementArrayBuffer, (int)(Marshal.SizeOf(typeof(short)) * 6), (nint)ptrIndices, OpenGLES.Def.BufferUsageHint.StreamDraw); OpenGLES.GL.glBindVertexArray(0); using (var program = new OpenGLES.GFX.GfxProgram(@"Shader/simplevertshader_v3.glsl", @"Shader/simplefragshader_v3.glsl")) { OpenGLES.GL.glClearColor(1f, 1f, 1f, .2f); OpenGLES.GL.glUseProgram(program); OpenGLES.GL.glBindVertexArray(0); uint posAttrib = OpenGLES.GL.glGetAttribLocation(program, "position"); OpenGLES.GL.glEnableVertexAttribArray(posAttrib); OpenGLES.GL.glVertexAttribPointerN(posAttrib, 2, false, (uint)Marshal.SizeOf(typeof(Vertex)), 0); uint colorAttrib = OpenGLES.GL.glGetAttribLocation(program, "color"); OpenGLES.GL.glEnableVertexAttribArray(colorAttrib); OpenGLES.GL.glVertexAttribPointerN(colorAttrib, 4, false, (uint)Marshal.SizeOf(typeof(Vertex)), Marshal.SizeOf(typeof(float)) * 2); var proj_mat_location = OpenGLES.GL.glGetUniformLocation(program, "proj_mat"); var model_mat_location = OpenGLES.GL.glGetUniformLocation(program, "model_mat"); OpenGLES.GL.glBindVertexArray(vao); uint posAttrib1 = OpenGLES.GL.glGetAttribLocation(program, "position"); OpenGLES.GL.glEnableVertexAttribArray(posAttrib); OpenGLES.GL.glVertexAttribPointerN(posAttrib, 2, false, (uint)Marshal.SizeOf(typeof(Vertex)), 0); uint colorAttrib1 = OpenGLES.GL.glGetAttribLocation(program, "color"); OpenGLES.GL.glEnableVertexAttribArray(colorAttrib); OpenGLES.GL.glVertexAttribPointerN(colorAttrib, 4, false, (uint)Marshal.SizeOf(typeof(Vertex)), Marshal.SizeOf(typeof(float)) * 2); var proj_mat_location1 = OpenGLES.GL.glGetUniformLocation(program, "proj_mat"); var model_mat_location1 = OpenGLES.GL.glGetUniformLocation(program, "model_mat"); ctx.Initialize( () => { Resize(ctx.Width, ctx.Height, proj_mat_location); } ).Render( () => { var rgb = hsl.ToRGB(); var angle = System.Environment.TickCount64 % (360 * 20d) / 20d; OpenGLES.GL.glClearColor((float)rgb.R / 255, (float)rgb.G / 255, (float)rgb.B / 255, .2f); OpenGLES.GL.glClear(OpenGLES.Def.ClearBufferMask.ColorBufferBit); OpenGLES.GL.glBindVertexArray(0); SetRotationMatrix(angle / 360d * Math.PI * 2, model_mat_location); OpenGLES.GL.glDrawElements(OpenGLES.Def.BeginMode.Triangles, 6, OpenGLES.Def.DrawElementsType.UnsignedShort, 0); OpenGLES.GL.glBindVertexArray(vao); SetRotationMatrix((angle + 90) / 360d * Math.PI * 2, model_mat_location1); OpenGLES.GL.glDrawElements(OpenGLES.Def.BeginMode.Triangles, 6, OpenGLES.Def.DrawElementsType.UnsignedShort, 0); // OpenGLES.GL.glDrawArrays(OpenGLES.Def.BeginMode.Triangles, 0, size); OpenGLES.GL.glBindVertexArray(0); hsl.H = angle + 90; var et = DateTime.Now; var dt = et - st; st = et; frame++; totalTime += dt; if (totalTime.TotalMilliseconds > 2 * 1000) { using (var mproc = System.Diagnostics.Process.GetCurrentProcess()) { Console.WriteLine($"[{DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss")}]: {frame} frames rendered in {(float)totalTime.TotalMilliseconds / 1000:.##} seconds -> FPS={(float)frame / totalTime.TotalMilliseconds * 1000:.##}, memory used: {(double)mproc.WorkingSet64 / 1024 / 1024:.##}M, system memory used: {(double)mproc.PrivateMemorySize64 / 1024 / 1024:.##}M"); frame = 0; totalTime = TimeSpan.Zero; } } } ); } } } } }
public static HSLA ToHSL(this RGBA rgb) { var hsl = new HSLA(); // Convert RGB to a 0.0 to 1.0 range. double r = rgb.R / 255.0; double g = rgb.G / 255.0; double b = rgb.B / 255.0; // Get the maximum and minimum RGB components. double max = r; if (max < g) { max = g; } if (max < b) { max = b; } double min = r; if (min > g) { min = g; } if (min > b) { min = b; } double diff = max - min; hsl.L = (max + min) / 2; if (Math.Abs(diff) < 0.00001) { hsl.S = 0; hsl.H = 0; // H is really undefined. } else { if (hsl.L <= 0.5) { hsl.S = diff / (max + min); } else { hsl.S = diff / (2 - max - min); } double rd = (max - r) / diff; double gd = (max - g) / diff; double bd = (max - b) / diff; if (r == max) { hsl.H = bd - gd; } else if (g == max) { hsl.H = 2 + rd - bd; } else { hsl.H = 4 + gd - rd; } hsl.H *= 60; if (hsl.H < 0) { hsl.H += 360; } } return(hsl); }