protected override void Renderer_ContextCreated(RenderThread sender, ContextCreationEventArgs args) { Log.WriteLine("Context created. Using: " + Gl.GetString(StringName.Renderer) + Gl.GetString(StringName.Version)); Log.WriteLine("Renderer_ContextCreated"); Renderer.TargetWindow.Resize += TargetWindow_Resize; // Load Shaders string vertex = File.ReadAllText("./shaders/hello.vert".Replace('/', Path.DirectorySeparatorChar)); string fragment = File.ReadAllText("./shaders/hello.frag".Replace('/', Path.DirectorySeparatorChar)); // Compile shaders Log.WriteLine("Compiling shader 'hello'..."); shader = new ShaderProgram(vertex, fragment); shader.Compile(); Log.WriteLine("Compiled shader index: %@", LogLevel.Message, shader.ProgramId); // Load vertices and indices vertices = new float[] { 0.0f, 0.5f, 0.0f, // top 0.5f, -0.5f, 0.0f, // bottom right -0.5f, -0.5f, 0.0f, // bottom left }; // Setup global VAO VAO = Gl.GenVertexArray(); Gl.BindVertexArray(VAO); CheckGlErrors("Renderer_ContextCreated:AfterVAO"); // Setup VBO (vertices) VBO = Gl.GenBuffer(); Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO); int size = (sizeof(float) * vertices.Length); // size must be 36 Gl.BufferData(BufferTarget.ArrayBuffer, size, vertices, BufferUsageHint.StaticDraw); CheckGlErrors("Renderer_ContextCreated:AfterBufferDataVBO"); Gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0); CheckGlErrors("Renderer_ContextCreated:AfterVAP_VBO"); Gl.EnableVertexAttribArray(0); CheckGlErrors("Renderer_ContextCreated:AfterVBO"); // Unbind Gl.BindVertexArray(0); CheckGlErrors("Renderer_ContextCreated:End"); }
protected override void Renderer_ContextCreated(RenderThread sender, ContextCreationEventArgs args) { Log.WriteLine("Render context created. Continuing initialization..."); Log.WriteLine("Running on OpenGL: %@", LogLevel.Message, Gl.GetString(StringName.Renderer) + Gl.GetString(StringName.Version)); Renderer.TargetWindow.KeyDown += TargetWindow_KeyDown; Renderer.TargetWindow.KeyUp += TargetWindow_KeyUp; CompileShaders(); LoadTextures(); Gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); VAO = Gl.GenVertexArray(); Gl.BindVertexArray(VAO); CheckGlErrors("pre-texture"); Gl.ActiveTexture(TextureUnit.Texture0); Gl.BindTexture(TextureTarget.Texture2D, fontAtlasTexture); CheckGlErrors("post-texture"); VBO = Gl.GenBuffer(); Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO); EBO = Gl.GenBuffer(); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, EBO); CheckGlErrors("pre_va_pointer"); Gl.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, 12 * sizeof(float), 0 * sizeof(float)); CheckGlErrors("post-va-pointer-0-set"); Gl.EnableVertexAttribArray(0); CheckGlErrors("post-va-pointer-0-enable"); Gl.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 12 * sizeof(float), 2 * sizeof(float)); Gl.EnableVertexAttribArray(1); CheckGlErrors("post-va-pointer-1"); Gl.VertexAttribPointer(2, 4, VertexAttribPointerType.Float, false, 12 * sizeof(float), 4 * sizeof(float)); Gl.EnableVertexAttribArray(2); CheckGlErrors("post-va-pointer-2"); Gl.VertexAttribPointer(3, 4, VertexAttribPointerType.Float, false, 12 * sizeof(float), 8 * sizeof(float)); Gl.EnableVertexAttribArray(3); }
protected override void Renderer_Draw(RenderThread sender, FrameStageEventArgs args) { Log.WriteLine("Renderer_Draw(%@)", LogLevel.Message, args.CurrentTime.FrameIndex); Gl.BindVertexArray(VAO); CheckGlErrors("Renderer_Draw:BindVAO"); Gl.ClearColor(0.2f, 0.3f, 0.3f, 1.0f); Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); CheckGlErrors("Renderer_Draw:Clear"); Gl.UseProgram(shader.ProgramId); CheckGlErrors("Renderer_Draw:UseProgram"); Gl.DrawElements(PrimitiveType.Triangles, 6, DrawElementsType.UnsignedInt, 0); CheckGlErrors("Renderer_Draw:DrawElements"); }
protected override void Renderer_Draw(RenderThread sender, FrameStageEventArgs args) { if (!sender.IsMainThread() && !sender.Asynchronous) { throw new InvalidOperationException("Draw operation initiated from secondary thread when supposed to run in Sync mode."); } float cellX = sender.InternalResolution.Width / (float)ConsoleSize.Width; float cellY = sender.InternalResolution.Height / (float)ConsoleSize.Height; List <float> vertices = new List <float>(4096); List <uint> indices = new List <uint>(4096); float[] db = ColorToFloatArray(DefaultBackColor); float[] df = ColorToFloatArray(DefaultForeColor); int vertexCount = 0; for (int xi = 0; xi < ConsoleSize.Width; xi++) { float x = xi * cellX; for (int yi = 0; yi < ConsoleSize.Height; yi++) { RenderGlyph glyphData = GetGlyph(xi, yi); if (ShowCursor && xi == Cursor.X && yi == Cursor.Y && glyphData == null) { int val = (int)((args.CurrentTime.TotalRuntime / 1000.0f) / BlinkInterval); if (val % 2 == 0 || BlinkInterval == 0) { glyphData = new RenderGlyph('_'); } } float y = yi * cellY; Rectangle texRec = Rectangle.Empty; int glyphId = (int)(glyphData?.Glyph ?? ' '); if (fontAtlas.ContainsId(glyphId)) { texRec = fontAtlas.GetPointerById(glyphId).Bounds; } else if (fontAtlas.ContainsId(0x558)) { texRec = fontAtlas.GetPointerById(0x558).Bounds; } else { texRec = fontAtlas.GetPointerById((int)'?').Bounds; } float[] b = glyphData == null || !glyphData.Background.HasValue ? db : ColorToFloatArray(glyphData.Background.Value); float[] f = glyphData == null || !glyphData.Foreground.HasValue ? df : ColorToFloatArray(glyphData.Foreground.Value); int qi = vertexCount; vertices.AddRange(new float[] { // Add vertices x, y, // 0,0 (A) texRec.X, texRec.Y, // Texture X,Y b[0], b[1], b[2], b[3], // Back f[0], f[1], f[2], f[3], // Fore x + cellX, y, // 1,0 (B) texRec.Right, texRec.Y, // Texture X,Y b[0], b[1], b[2], b[3], // Back f[0], f[1], f[2], f[3], // Fore x + cellX, y + cellY, // 1,1 (C) texRec.Right, texRec.Bottom, // Texture X,Y b[0], b[1], b[2], b[3], // Back f[0], f[1], f[2], f[3], // Fore x, y + cellY, //0,1 (D) texRec.X, texRec.Bottom, // Texture X,Y b[0], b[1], b[2], b[3], // Back f[0], f[1], f[2], f[3], // Fore }); indices.AddRange(new uint[] { (uint)(qi + 1), // B (uint)(qi + 3), // D (uint)(qi), // A (uint)(qi + 1), // B (uint)(qi + 2), // C (uint)(qi + 3), // D }); vertexCount += 4; } } Gl.BindVertexArray(VAO); Gl.BindBuffer(BufferTarget.ArrayBuffer, VBO); float[] fvertices = vertices.ToArray(); vertices.Clear(); uint[] iindices = indices.ToArray(); indices.Clear(); CheckGlErrors("pre-vab"); GCHandle buffAddress = GCHandle.Alloc(fvertices, GCHandleType.Pinned); Gl.BufferData(BufferTarget.ArrayBuffer, fvertices.Length * sizeof(float), buffAddress.AddrOfPinnedObject(), BufferUsageHint.StreamDraw); buffAddress.Free(); CheckGlErrors("pre-eab"); buffAddress = GCHandle.Alloc(iindices, GCHandleType.Pinned); Gl.BufferData(BufferTarget.ElementArrayBuffer, iindices.Length * sizeof(float), buffAddress.AddrOfPinnedObject(), BufferUsageHint.StreamDraw); buffAddress.Free(); CheckGlErrors("predraw"); Gl.DrawElements(BeginMode.Triangles, iindices.Length, DrawElementsType.UnsignedInt, 0); CheckGlErrors("final"); Gl.BindVertexArray(0); CheckGlErrors("unbind"); }