Xamarin 中的 OpenTK 简介Introduction to OpenTK in Xamarin.Mac

OpenTK (开放工具包)是一种高级的低级别C#库,可让你更轻松地使用 OpenGL、OpenCL 和 OpenAL。OpenTK (The Open Toolkit) is an advanced, low-level C# library that makes working with OpenGL, OpenCL and OpenAL easier. OpenTK 可用于需要3D 图形、音频或计算功能的游戏、科学应用程序或其他项目。OpenTK can be used for games, scientific applications or other projects that require 3D graphics, audio or computational functionality. 本文简要介绍了如何在 Xamarin 应用程序中使用 OpenTK。This article gives a brief introduction to using OpenTK in a Xamarin.Mac app.

本文介绍了 Xamarin OpenTK 应用程序中的基础知识。In this article, we'll cover the basics of OpenTK in a Xamarin.Mac application. 强烈建议您先完成Hello,Mac一文,特别是Xcode 和 Interface Builder输出口和操作部分的简介,因为它涵盖了我们将在本文。It is highly suggested that you work through the Hello, Mac article first, specifically the Introduction to Xcode and Interface Builder and Outlets and Actions sections, as it covers key concepts and techniques that we'll be using in this article.

你可能想要查看Xamarin示例文档的 " C# 公开C#类/方法到目标-c " 部分,并说明用于将类连接到目标的RegisterExport命令-c对象和 UI 元素。You may want to take a look at the Exposing C# classes / methods to Objective-C section of the Xamarin.Mac Internals document as well, it explains the Register and Export commands used to wire-up your C# classes to Objective-C objects and UI Elements.

关于 OpenTKAbout OpenTK

如上所述,OpenTK (开放工具包)是一种高级的低级别C#库,可让你更轻松地使用 OpenGL、OpenCL 和 OpenAL。As stated above, OpenTK (The Open Toolkit) is an advanced, low-level C# library that makes working with OpenGL, OpenCL and OpenAL easier. 在 Xamarin 应用程序中使用 OpenTK 提供以下功能:Using OpenTK in a Xamarin.Mac app provides the following features:

  • 快速开发-OpenTK 提供了强大的数据类型和内联文档,可提高编码工作流并更快地捕获错误。Rapid Development - OpenTK provides strong data types and inline documentation to improve your coding workflow and catch errors easier and sooner.
  • 轻松集成-OpenTK 旨在与 .net 应用程序轻松集成。Easy Integration - OpenTK was designed to easily integrate with .NET applications.
  • 许可的许可-OPENTK 在 MIT/X11 许可证下分发,完全免费。Permissive License - OpenTK is distributed under the MIT/X11 Licenses and is totally free.
  • 丰富的类型安全绑定-OpenTK 支持最新版本的 OpenGL、OPENGL | ES、OpenAL 和 OpenCL 和自动扩展加载、错误检查和内联文档。Rich, Type-Safe Bindings - OpenTK supports the latest versions of OpenGL, OpenGL|ES, OpenAL and OpenCL with automatic extension loading, error checking and inline documentation.
  • 灵活的 GUI 选项-OpenTK 提供专为游戏和 Xamarin 设计的本机、高性能游戏窗口。Flexible GUI Options - OpenTK provides the native, high-performance Game Window designed specifically for games and Xamarin.Mac.
  • 完全托管的符合 CLS 的代码OpenTK 支持32位和64位版本的 macOS,不包含非托管库。Fully Managed, CLS-Compliant Code - OpenTK supports 32-bit and 64-bit versions of macOS with no unmanaged libraries.
  • 3D 数学工具包OpenTK 通过其3D 数学工具包提供 VectorMatrixQuaternionBezier 结构。3D Math Toolkit OpenTK supplies Vector, Matrix, Quaternion and Bezier structs via its 3D Math Toolkit.

OpenTK 可用于需要3D 图形、音频或计算功能的游戏、科学应用程序或其他项目。OpenTK can be used for games, scientific applications or other projects that require 3D graphics, audio or computational functionality.

有关详细信息,请参阅开放工具包网站。For more information, please see The Open Toolkit website.

OpenTK 快速入门OpenTK Quickstart

作为在 Xamarin 应用程序中使用 OpenTK 的快速介绍,我们将创建一个简单的应用程序,用于打开游戏视图,在该视图中呈现简单的三角形,并将游戏视图 attachs 到 Mac 应用程序的主窗口,以向用户显示三角形。As a quick introduction to using OpenTK in a Xamarin.Mac app, we are going to create a simple application that opens a Game View, renders a simple triangle in that view and attachs the Game View to the Mac app's Main Window to display the triangle to the user.

启动新项目Starting a New Project

开始 Visual Studio for Mac 并创建新的 Xamarin Mac 解决方案。Start Visual Studio for Mac and create a new Xamarin.Mac solution. 选择Mac > 应用 > 常规 > Cocoa 应用Select Mac > App > General > Cocoa App:

输入项目名称MacOpenTKEnter MacOpenTK for the Project Name:

单击 "创建" 按钮以生成新项目。Click the Create button to build the new project.

包括 OpenTKIncluding OpenTK

你需要包含对 OpenTK 程序集的引用,然后才能在 Xamarin Mac 应用程序中使用 Open TK。Before you can use Open TK in a Xamarin.Mac application, you need to include a reference to the OpenTK assembly. 解决方案资源管理器中,右键单击 "引用" 文件夹,然后选择 "编辑引用 ... "。In the Solution Explorer, right-click the References folder and select Edit References....

勾选 "OpenTK",然后单击 "确定" 按钮:Place a check by OpenTK and click the OK button:

使用 OpenTKUsing OpenTK

创建新项目后,双击解决方案资源管理器中的 MainWindow.cs 文件,将其打开进行编辑。With the new project created, double-click the MainWindow.cs file in the Solution Explorer to open it for editing. 使 MainWindow 类如下所示:Make the MainWindow class look like the following:

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;

            // 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
    }
}

接下来,我们将详细介绍以下代码。Let's go over this code in detail below.

必需的 ApiRequired APIs

若要在 Xamarin 类中使用 OpenTK,需要多个引用。Several references are required to use OpenTK in a Xamarin.Mac class. 在定义开始时,我们包含以下 using 语句:At the start of the definition we have included the following using statements:

using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Platform.MacOS;
using Foundation;
using CoreGraphics;

使用 OpenTK 的任何类都需要这一最小集。This minimal set will be required for any class using OpenTK.

添加游戏视图Adding the Game View

接下来,我们需要创建一个游戏视图来包含与 OpenTK 的所有交互,并显示结果。Next we need to create a Game View to contain all of our interaction with OpenTK and display the results. 我们使用了以下代码:We used the following code:

public MonoMacGameView Game { get; set; }
...

// Create new Game View and replace the window content with it
Game = new MonoMacGameView(ContentView.Frame);
ContentView = Game;

在这里,我们使游戏视图与主 Mac 窗口的大小相同,并将该窗口的内容视图替换为新的 MonoMacGameViewHere we've made the Game View the same size as our Main Mac Window and replaced the Content View of the window with the new MonoMacGameView. 由于我们替换了现有的窗口内容,因此当调整主窗口大小时,将自动调整我们的视图大小。Because we replaced the existing window content, our Gave View will be automatically resized when the Main Windows is resized.

对事件作出响应Responding to Events

每个游戏视图都应响应多个默认事件。There are several default events that each Game View should respond to. 本部分将介绍所需的主要事件。In this section will cover the main events required.

Load 事件The Load Event

Load 事件是从磁盘(如图像、纹理或音乐)加载资源的位置。The Load event is the place to load resources from disk such as images, textures or music. 对于简单的测试应用程序,我们没有使用 Load 事件,但包含它以供参考:For our simple, test app, we are not using the Load event, but have included it for reference:

Game.Load += (sender, e) =>
{
    // TODO: Initialize settings, load textures and sounds here
};

Resize 事件The Resize Event

每次调整游戏视图大小时,都应调用 Resize 事件。The Resize event should be called every time the Game View is resized. 对于我们的示例应用程序,我们要使 GL 视区的大小与游戏视图(通过 Mac 主窗口自动调整大小)相同,并具有以下代码:For our sample app, we are making the GL Viewport the same size as our Game View (which is be auto resized by the Mac Main Window) with the following code:

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 事件The UpdateFrame Event

UpdateFrame 事件用于处理用户输入、更新对象位置、运行物理学或 AI 计算。The UpdateFrame event is used to handle user input, update object positions, run physics or AI calculations. 对于简单的测试应用程序,我们没有使用 UpdateFrame 事件,但包含它以供参考:For our simple, test app, we are not using the UpdateFrame event, but have included it for reference:

Game.UpdateFrame += (sender, e) =>
{
    // TODO: Add any game logic or physics
};

重要

OpenTK 的 Xamarin 实现不包含 Input API,因此你将需要使用 Apple 提供的 Api 来添加键盘和鼠标支持。The Xamarin.Mac implementation of OpenTK does not include the Input API, so you will need to use the Apple provided APIs to add keyboard and Mouse support. (可选)可以创建 MonoMacGameView 的自定义实例,并重写 KeyDownKeyUp 方法。Optionally you can create a custom instance of the MonoMacGameView and override the KeyDown and KeyUp methods.

RenderFrame 事件The RenderFrame Event

RenderFrame 事件包含用于呈现(绘制)图形的代码。The RenderFrame event contains the code that is used to render (draw) your graphics. 对于我们的示例应用,我们使用简单的三角形填充游戏视图:For our example app, we are filling the Game View with a simple triangle:

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 在绘制新元素之前删除任何现有元素。Typically the render code will being with a call to GL.Clear to remove any existing elements before drawn the new elements.

重要

对于 OpenTK 版本的,在呈现代码末尾不要调用MonoMacGameView 实例的 SwapBuffers 方法。For the Xamarin.Mac version of OpenTK do not call the SwapBuffers method of your MonoMacGameView instance at the end of your rendering code. 这样做将导致游戏视图快速看起来,而不是显示呈现的视图。Doing so will cause the Game View to strobe rapidly instead of displaying your rendered view.

运行游戏视图Running the Game View

将所有必需的事件定义为,并将游戏视图附加到应用程序的主 Mac 窗口,我们将阅读运行游戏视图并显示图形。With all of the required events define and the Game View attached to the Main Mac Window of our app, we are read to run the Game View and display our graphics. 使用以下代码:Use the following code:

// Run the game at 60 updates per second
Game.Run(60.0);

我们会按所需的帧速率来更新游戏视图,对于我们的示例,我们选择了每秒 60 帧(与普通电视相同的刷新频率)。We pass in the desired frame rate that we want the Game View to update at, for our example we have chosen 60 frames per second (the same refresh rate as normal TV).

运行应用程序并查看输出:Let's run our app and see the output:

如果调整窗口的大小,则游戏视图也会随之驻留,同时也会调整三角形的大小并进行实时更新。If we resize our window, the Game View will also be reside and the triangle will be resized and updated real-time as well.

下一步是什么?Where to Next?

在 Xamarin 应用程序中使用 OpenTk 的基础知识完成后,以下是有关下一步操作的一些建议:With the basics of working with OpenTk in a Xamarin.mac application done, here are some suggestions of what to try out next:

  • 尝试更改 LoadRenderFrame 事件中的三角形颜色和游戏视图的背景色。Try changing the color of the triangle and the background color of the Game View in the Load and RenderFrame events.
  • 当用户在 UpdateFrame 中按下某个键并 RenderFrame 事件,或创建自己的自定义 MonoMacGameView 类并覆盖 KeyUpKeyDown 方法时,使三角形更改颜色。Make the triangle change color when the user press a key in the UpdateFrame and RenderFrame events or make your own custom MonoMacGameView class and override the KeyUp and KeyDown methods.
  • 使用 UpdateFrame 事件中识别的密钥,使三角形在屏幕上移动。Make the triangle move across the screen using the aware keys in the UpdateFrame event. 提示:使用 Matrix4.CreateTranslation 方法创建平移矩阵,并调用 GL.LoadMatrix 方法在 RenderFrame 事件中加载它。Hint: use the Matrix4.CreateTranslation method to create a translation matrix and call the GL.LoadMatrix method to load it in the RenderFrame event.
  • 使用 for 循环在 RenderFrame 事件中呈现几个三角形。Use a for loop to render several triangles in the RenderFrame event.
  • 旋转相机,为3D 空间中的三角形指定不同的视图。Rotate the camera to give a different view of the triangle in 3D space. 提示:使用 Matrix4.CreateTranslation 方法创建平移矩阵,并调用 GL.LoadMatrix 方法将其加载。Hint: use the Matrix4.CreateTranslation method to create a translation matrix and call the GL.LoadMatrix method to load it. 你还可以使用 Vector2Vector3Vector4Matrix4 类进行照相机操作。You can also use the Vector2, Vector3, Vector4 and Matrix4 classes for camera manipulations.

有关更多示例,请参阅OpenTK 示例 GitHub存储库。For more examples, please see the OpenTK Samples GitHub repo. 它包含使用 OpenTK 的官方示例列表。It contains an official list of examples of using OpenTK. 必须修改这些示例,以便将与 OpenTK 的 Xamarin 版本结合使用。You'll have to adapt these examples for using with the Xamarin.Mac version of OpenTK.

有关 OpenTK 实现的更复杂的 Xamarin 示例,请参阅我们的MonoMacGameView示例。For a more complex Xamarin.Mac example of an OpenTK implementation, please see our MonoMacGameView sample.

总结Summary

本文大致介绍了如何在 Xamarin. Mac 应用程序中使用 OpenTK。This article has taken a quick look at working with OpenTK in a Xamarin.Mac application. 我们了解了如何创建游戏窗口,如何将游戏窗口附加到 Mac 窗口,以及如何在游戏窗口中呈现简单的形状。We saw how to create a Game Window, how to attach the Game Window to a Mac Window and how to render a simple shape in the Game Window.