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();
    }
}

运行效果

image

 

posted on 2026-08-10 05:04  dalgleish  阅读(0)  评论(0)    收藏  举报