Xamarin.Mac 中的 OpenTK 简介
OpenTK (Open Toolkit) 是高级的低级别 C# 库,可更轻松地使用 OpenGL、OpenCL 和 OpenAL。 OpenTK 可用于需要 3D 图形、音频或计算功能的游戏、科学应用程序或其他项目。 本文将简要介绍如何在 Xamarin.Mac 应用中使用 OpenTK。
本文将介绍在 Xamarin.Mac 应用程序中使用 OpenTK 的基础知识。 强烈建议先阅读了解 Mac 一文,特别是 Xcode 和 Interface Builder 简介和输出口和操作部分,因为其中介绍了我们将在本文中使用的关键概念和技术。
你可能还需要查看 Xamarin.Mac 内部机制文档的向 Objective-C 公开 C# 类/方法部分,因为其中介绍了用于将 C# 类连接到 Objective-C 对象和 UI 元素的 Register
和 Export
命令。
关于 OpenTK
如上所述,OpenTK (Open Toolkit) 是高级的低级别 C# 库,可更轻松地使用 OpenGL、OpenCL 和 OpenAL。 在 Xamarin.Mac 应用中使用 OpenTK 可提供以下功能:
- 快速开发 - OpenTK 提供强大的数据类型和内联文档,有助于改进编码工作流并更轻松、更快地捕获错误。
- 轻松集成 - OpenTK 旨在轻松与 .NET 应用程序集成。
- 宽松式许可证 - OpenTK 根据 MIT/X11 许可证进行分发,并且完全免费。
- 丰富的类型安全绑定 - OpenTK 支持最新版本的 OpenGL、OpenGL|ES、OpenAL 和 OpenCL 以及自动扩展加载、错误检查和内联文档。
- 灵活的 GUI 选项 - OpenTK 提供专为游戏和 Xamarin.Mac 设计的本机高性能游戏窗口。
- 完全托管、符合 CLS 的代码 - OpenTK 支持 32 位和 64 位版本的 macOS,没有非托管库。
- 3D 数学工具包 - OpenTK 通过其 3D 数学工具包提供
Vector
、Matrix
、Quaternion
和Bezier
结构。
OpenTK 可用于需要 3D 图形、音频或计算功能的游戏、科学应用程序或其他项目。
有关详细信息,请参阅 Open Toolkit 网站。
OpenTK 快速入门
为简要介绍如何在 Xamarin.Mac 应用中使用 OpenTK,我们将创建一个简单的应用程序,可在其中打开“游戏视图”,在该视图中渲染一个简单的三角形,并将“游戏视图”附加到 Mac 应用的“主窗口”以向用户显示该三角形。
启动一个新项目
启动 Visual Studio for Mac 并创建新的 Xamarin.Mac 解决方案。 选择 Mac >“应用”>“常规”>“Cocoa 应用”:
在“项目名称”中输入 MacOpenTK
:
单击“创建”按钮以生成新项目。
包括 OpenTK
必须在 Xamarin.Mac 应用程序中包括对 OpenTK 程序集的引用,才能在其中使用 Open TK。 在 Solution Pad 中,右键单击 References 文件夹,然后选择“编辑首选项...”。
通过 OpenTK
进行检查,然后单击“确定”按钮:
使用 OpenTK
创建新项目后,在“解决方案资源管理器”中,双击打开 MainWindow.cs
文件进行编辑。 使 MainWindow
类如下所示:
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform.MacOS;
using Foundation;
using AppKit;
using CoreGraphics;
namespace MacOpenTK
{
public partial class MainWindow : NSWindow
{
#region Computed Properties
public MonoMacGameView Game { get; set; }
#endregion
#region Constructors
public MainWindow (IntPtr handle) : base (handle)
{
}
[Export ("initWithCoder:")]
public MainWindow (NSCoder coder) : base (coder)
{
}
#endregion
#region Override Methods
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Create new Game View and replace the window content with it
Game = new MonoMacGameView(ContentView.Frame);
ContentView = Game;
Game.OpenGLContext.View = Game;
// Wire-up any required Game events
Game.Load += (sender, e) =>
{
// TODO: Initialize settings, load textures and sounds here
};
Game.Resize += (sender, e) =>
{
// Adjust the GL view to be the same size as the window
GL.Viewport(0, 0, Game.Size.Width, Game.Size.Height);
};
Game.UpdateFrame += (sender, e) =>
{
// TODO: Add any game logic or physics
};
Game.RenderFrame += (sender, e) =>
{
// Setup buffer
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Projection);
// Draw a simple triangle
GL.LoadIdentity();
GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0);
GL.Begin(BeginMode.Triangles);
GL.Color3(Color.MidnightBlue);
GL.Vertex2(-1.0f, 1.0f);
GL.Color3(Color.SpringGreen);
GL.Vertex2(0.0f, -1.0f);
GL.Color3(Color.Ivory);
GL.Vertex2(1.0f, 1.0f);
GL.End();
};
// Run the game at 60 updates per second
Game.Run(60.0);
}
#endregion
}
}
下面让我们详细讨论一下这段代码。
必需的 API
在 Xamarin.Mac 类中使用 OpenTK 需要几个引用。 在定义的开头部分,我们已包含以下 using
语句:
using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform.MacOS;
using Foundation;
using CoreGraphics;
使用 OpenTK 的任何类都需要此最小集。
添加游戏视图
接下来,我们需要创建一个游戏视图,以包含与 OpenTK 的所有交互并显示结果。 我们采用的代码如下:
public MonoMacGameView Game { get; set; }
...
// Create new Game View and replace the window content with it
Game = new MonoMacGameView(ContentView.Frame);
ContentView = Game;
在这里,我们使游戏视图的大小与 Mac 主窗口相同,并将窗口的内容视图替换为了新的 MonoMacGameView
。 由于我们替换了现有窗口内容,因此在调整主窗口大小时,将自动调整游戏视图的大小。
对事件作出响应
每个游戏视图应响应多个默认事件。 本部分将介绍所需的主要事件。
Load 事件
Load
事件是从磁盘(如图像、纹理或音乐)加载资源的位置。 在简单的测试应用中,我们不会使用 Load
事件,但已包含它以供参考:
Game.Load += (sender, e) =>
{
// TODO: Initialize settings, load textures and sounds here
};
Resize 事件
每次调整游戏视图大小时都应调用 Resize
事件。 在示例应用中,我们使用以下代码将 GL 视区的大小设置为与游戏视图相同的大小(由 Mac 主窗口自动调整大小):
Game.Resize += (sender, e) =>
{
// Adjust the GL view to be the same size as the window
GL.Viewport(0, 0, Game.Size.Width, Game.Size.Height);
};
UpdateFrame 事件
UpdateFrame
事件用于处理用户输入、更新对象位置、运行物理或 AI 计算。 在简单的测试应用中,我们不会使用 UpdateFrame
事件,但已包含它以供参考:
Game.UpdateFrame += (sender, e) =>
{
// TODO: Add any game logic or physics
};
重要
OpenTK 的 Xamarin.Mac 实现不包括 Input API
,因此需要使用 Apple 提供的 API 添加键盘和鼠标支持。 (可选)可以创建 MonoMacGameView
的自定义实例,并替代 KeyDown
和 KeyUp
方法。
RenderFrame 事件
RenderFrame
事件包含用于渲染(绘制)图形的代码。 在示例应用中,我们将用一个简单的三角形填充游戏视图:
Game.RenderFrame += (sender, e) =>
{
// Setup buffer
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.MatrixMode(MatrixMode.Projection);
// Draw a simple triangle
GL.LoadIdentity();
GL.Ortho(-1.0, 1.0, -1.0, 1.0, 0.0, 4.0);
GL.Begin(BeginMode.Triangles);
GL.Color3(Color.MidnightBlue);
GL.Vertex2(-1.0f, 1.0f);
GL.Color3(Color.SpringGreen);
GL.Vertex2(0.0f, -1.0f);
GL.Color3(Color.Ivory);
GL.Vertex2(1.0f, 1.0f);
GL.End();
};
通常,渲染代码将调用 GL.Clear
以在绘制新元素之前删除任何现有元素。
重要
对于 OpenTK 的 Xamarin.Mac 版本,请勿在渲染代码末尾调用 MonoMacGameView
实例的 SwapBuffers
方法。 否则将导致游戏视图快速闪烁,而不是显示渲染的视图。
运行游戏视图
定义了所有必需的事件并将游戏视图附加到应用的 Mac 主窗口后,接下来即可运行游戏视图并显示图形。 使用以下代码:
// Run the game at 60 updates per second
Game.Run(60.0);
我们传入游戏视图更新时所需的帧速率,在我们的示例中,我们选择了每秒 60
帧(与普通电视的刷新率相同)。
运行应用并查看输出:
如果我们调整窗口大小,游戏视图也将驻留,三角形也将进行大小调整并实时更新。
接下来怎么做?
完成在 Xamarin.mac 应用程序中使用 OpenTk 的基础知识后,接下来可以尝试进行以下操作:
- 尝试在
Load
和RenderFrame
事件中更改三角形的颜色和游戏视图的背景色。 - 使三角形在用户在
UpdateFrame
和RenderFrame
事件中按某个键或创建自己的自定义MonoMacGameView
类并重写KeyUp
和KeyDown
方法时能够改变颜色。 - 使用
UpdateFrame
事件中的感知键在屏幕上移动三角形。 提示:使用Matrix4.CreateTranslation
方法创建平移矩阵,并调用GL.LoadMatrix
方法将其加载到RenderFrame
事件中。 - 使用
for
循环在RenderFrame
事件中渲染多个三角形。 - 旋转相机以在 3D 空间中提供三角形的不同视图。 提示:使用
Matrix4.CreateTranslation
方法创建平移矩阵并调用GL.LoadMatrix
方法加载它。 还可以将Vector2
、Vector3
、Vector4
和Matrix4
类用于相机操作。
有关更多示例,请参阅 OpenTK 示例 GitHub 存储库。 它包含使用 OpenTK 的示例的官方列表。 必须改编这些示例,以便与 Xamarin.Mac 版本的 OpenTK 一起使用。
总结
本文简要介绍了如何在 Xamarin.Mac 应用程序中使用 OpenTK。 我们了解了如何创建游戏窗口、如何将游戏窗口附加到 Mac 窗口以及如何在游戏窗口中渲染简单形状。