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 es
layout(location=0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
""";
var fsSource = """
#version 300 es
precision 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();
}
}
运行效果

浙公网安备 33010602011771号