Avalonia 跨平台框架中如何以正确的姿势使用 OpenGL ES 渲染。

时间:2024-02-29 17:39:55

前言

这是一篇很水的文章,没有任何技术含量,在 Github 已经有很多人对 AvaloniaOpenGL ES 支持进行了讨论,但是我还是想写一篇文章来记录一下我是如何在 Avalonia 中使用 OpenGL ES 的。

介绍

在介绍 AvaloniaOpenGL ES 之前,我们先来了解一下什么是 AvaloniaOpenGL ES 以及 Avalonia 是如何支持 OpenGL ES 的。

Angle 和 OpenGL ES

ANGLE 是一个开源的项目,它的目标是将 OpenGL ES 2.0、3.03.1 应用程序转换为 Direct3D 11VulkanMetalOpenGL 3.0+ 应用程序。

ANGLE 通过将 OpenGL ES API 调用转换为 Direct3DVulkanMetal API 调用来实现这一目标。

ANGLE 也提供了一个实现 OpenGL ES 2.0、3.03.1 的库,这样就可以在不支持 OpenGL ES 的平台上运行 OpenGL ES 应用程序。

以下是摘自 ANGLE 项目的介绍:

Level of OpenGL ES support via backing renderers
Direct3D 9 Direct3D 11 Desktop GL GL ES Vulkan Metal
OpenGL ES 2.0 complete complete complete complete complete complete
OpenGL ES 3.0 complete complete complete complete complete
OpenGL ES 3.1 [incomplete][ES31OnD3D] complete complete complete
OpenGL ES 3.2 in progress in progress complete
Platform support via backing renderers
Direct3D 9 Direct3D 11 Desktop GL GL ES Vulkan Metal
Windows complete complete complete complete complete
Linux complete complete
Mac OS X complete complete [1]
iOS complete [2]
Chrome OS complete planned
Android complete complete
GGP (Stadia) complete
Fuchsia complete

ANGLE 项目的地址:https://github.com/google/angle

Avalonia

Avalonia 是一个 .NET 平台的 XAMLC#UI 框架,它的目标是创建一个跨平台的 UI 框架,支持 WindowsLinuxMacOS。(摘自 Avalonia 官网)

Avalonia 渲染 API 的实现是基于 SkiaSharp 的,SkiaSharpGoogleSkia 图形库的 .NET 实现。
为了实现硬件加速 SkiaSharp 是支持 OpenGLOpenGL ES 渲染的,为了统一平台,Avalonia 选择了 ANGLE 作为 OpenGL ES 的实现。

Avalonia 项目的地址:https://github.com/AvaloniaUI/Avalonia

如何使用 OpenGL ES

Avalonia 中的 OpenGL ES 是通过 ANGLE 来实现的,在 Avalonia 项目中已经集成了 ANGLE,所以我们不需要再去关心 ANGLE 的集成问题。

在该框架中使用 OpenGL ES 的方式是通过 Avalonia 提供的 OpenGlControlBase 控件来实现的,我们只需要集成 OpenGlControlBase 控件并重写 OnOpenGlInit 方法就可以获取到 OpenGL ESContext 以及函数指针了。

Avalonia 中使用 OpenGL ES 的步骤如下:(我这边使用的是 Silk.NET 来调用 OpenGL ES 的函数)

using Silk.NET.OpenGLES;

namespace GraphicsHostApp.Graphics.OpenGL;

public class Renderer : OpenGlControlBase, IGraphicsHost<GL>
{
	private GL _gl;

	protected override void OnOpenGlInit(GlInterface gl)
	{
		// 获取 OpenGL ES 的 函数指针。
		_gl ??= GL.GetApi(gl.GetProcAddress);

		// 后续初始化操作。
	}

	protected override void OnOpenGlDeinit(GlInterface gl)
	{
		// 释放 OpenGL ES 的资源。
		Code ...

		// 释放函数指针。
		_gl.Dispose();
		_gl = null;
	}

	protected override void OnOpenGlRender(GlInterface gl, int fb)
	{
		// 更新操作。
		Code ...

		// 渲染操作。 注:这里需要注意的是,父类代码并没有更新视口,所以需要手动更新视口。gl.Viewport(0, 0, Width, Height);
		Code ...

		// 提交渲染到主循环中。
		Dispatcher.UIThread.Post(RequestNextFrameRendering, DispatcherPriority.Render);
	}
}

结语

Avalonia 是一个很不错的 UI 框架,它的 OpenGL ES 支持也是很完善的,但是在使用 OpenGL ES 的时候需要注意的是 OpenGL ESContext 是在 OpenGlControlBaseOnOpenGlInit 方法中创建的,所以在 OnOpenGlRender 方法中使用 OpenGL ES 的函数指针的时候需要注意 Context 是否已经创建了。

其次,OpenGL ESContext 是线程相关的,所以在使用 OpenGL ES 的时候需要注意 Context 的线程问题。

在使用 OpenGL ES 扩展的时候要注意 ANGLE 是否支持该扩展,如果不支持的话需要自己去实现。

演示项目

  • GraphicsHostAppAvaloniaOpenGL ES 的演示项目,介绍了如何使用 C#C++ 来实现 OpenGL ES 渲染。)

参考

  • ANGLE
  • Avalonia
  • Avalonia-Silk.NET-Example