TriangleGlView.axaml代码
<Window xmlns="https://github.com/avaloniaui"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"Height="300" Width="300"xmlns:local="using:AvaloniaUI"x:Class="AvaloniaUI.OneTriangleMesh"Title="OneTriangleMesh"><Grid Margin="5"><Border BorderBrush="Yellow" BorderThickness="1"><local:TriangleGlView/></Border></Grid> </Window>
TriangleGlView.axaml.cs代码
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Controls;
using Avalonia.Rendering;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using System;
using System.Diagnostics;
using System.Numerics;namespace AvaloniaUI;public sealed class TriangleGlView : OpenGlControlBase
{private int program;private int vao;private int vbo;protected override void OnOpenGlInit(GlInterface gl){GL.LoadBindings(new BindingsContext(gl));GL.Disable(EnableCap.DepthTest);CreateTriangle();CreateProgram();//这个版本和version 300 es对应var version = GL.GetString(StringName.Version);var sl = GL.GetString(StringName.ShadingLanguageVersion);var renderer = GL.GetString(StringName.Renderer);var vendor = GL.GetString(StringName.Vendor);Console.WriteLine($"GL_VERSION: {version}");Console.WriteLine($"GLSL: {sl}");Console.WriteLine($"Renderer: {renderer}");Console.WriteLine($"Vendor: {vendor}");}protected override void OnOpenGlDeinit(GlInterface gl){if (program != 0) GL.DeleteProgram(program);if (vbo != 0) GL.DeleteBuffer(vbo);if (vao != 0) GL.DeleteVertexArray(vao);program = 0;vbo = 0;vao = 0;}protected override void OnOpenGlRender(GlInterface gl, int fb){//RequestNextFrameRendering();var width = Math.Max(1, (int)Bounds.Width);var height = Math.Max(1, (int)Bounds.Height);GL.Viewport(0, 0, width, height);GL.ClearColor(0.5f, 0.5f, 0.5f, 1f);GL.Clear(ClearBufferMask.ColorBufferBit);GL.UseProgram(program);GL.BindVertexArray(vao);GL.DrawArrays(PrimitiveType.Triangles, 0, 3);}private void CreateTriangle(){var vertices = new[]{-0.8f, -0.6f, 0f,0.0f, 0.8f, 0f,0.8f, -0.6f, 0f};vao = GL.GenVertexArray();vbo = GL.GenBuffer();GL.BindVertexArray(vao);GL.BindBuffer(BufferTarget.ArrayBuffer, vbo);GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);GL.EnableVertexAttribArray(0);GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), 0);}private void CreateProgram(){var vsSource = """#version 300 eslayout(location=0) in vec3 aPos;void main(){gl_Position = vec4(aPos, 1.0);}""";var fsSource = """#version 300 esprecision mediump float;out vec4 FragColor;void main(){FragColor = vec4(1.0, 1.0, 0.0, 1.0);}""";var vs = CompileShader(ShaderType.VertexShader, vsSource);var fs = CompileShader(ShaderType.FragmentShader, fsSource);program = GL.CreateProgram();GL.AttachShader(program, vs);GL.AttachShader(program, fs);GL.LinkProgram(program);GL.GetProgram(program, GetProgramParameterName.LinkStatus, out var linked);if (linked == 0){var log = GL.GetProgramInfoLog(program);GL.DeleteProgram(program);program = 0;throw new InvalidOperationException($"Link failed: {log}");}GL.DetachShader(program, vs);GL.DetachShader(program, fs);GL.DeleteShader(vs);GL.DeleteShader(fs);}private static int CompileShader(ShaderType type, string source){var shader = GL.CreateShader(type);GL.ShaderSource(shader, source);GL.CompileShader(shader);GL.GetShader(shader, ShaderParameter.CompileStatus, out var ok);if (ok == 0){var log = GL.GetShaderInfoLog(shader);GL.DeleteShader(shader);throw new InvalidOperationException($"{type} compile failed: {log}");}return shader;}private sealed class BindingsContext(GlInterface gl) : IBindingsContext{public IntPtr GetProcAddress(string procName) => gl.GetProcAddress(procName);}
}
public partial class OneTriangleMesh : Window
{public OneTriangleMesh(){InitializeComponent();}
}
运行效果
