次の方法で共有


Xamarin.Mac での OpenTK の概要

OpenTK (The Open Toolkit) は、OpenGL、OpenCL、OpenAL の操作を容易にする先進の低レベル C# ライブラリです。 OpenTK は、3D グラフィックス、オーディオ、または計算機能を必要とするゲームや科学アプリケーションなどのプロジェクトに使用できます。 この記事では、Xamarin.Mac アプリでの OpenTK の使用について簡単に説明します。

アプリの実行例

この記事では、Xamarin.Mac アプリケーションでの OpenTK の基本について説明します。 この記事で使用する主要な概念と手法については、まず Hello Mac の記事、特に「Xcode と Interface Builder の概要」および「アウトレットとアクション」のセクションを参照することを強くお勧めします。

Xamarin.Mac Internals ドキュメントの 「C# クラス/メソッドの Objective-C への公開」のセクションも参照することをお勧めします。C# クラスを Objective-C オブジェクトと UI 要素に結び付けるために使われる Register および Export コマンドについて説明されています。

OpenTK について

前述のように、OpenTK (The Open Toolkit) は、OpenGL、OpenCL、OpenAL の操作を容易にする先進の低レベル C# ライブラリです。 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 Math Toolkit OpenTK は、3D Math Toolkit を介して、VectorMatrixQuaternionBezier 構造体を提供します。

OpenTK は、3D グラフィックス、オーディオ、または計算機能を必要とするゲームや科学アプリケーションなどのプロジェクトに使用できます。

詳細については、The Open Toolkit の Web サイトを参照してください。

OpenTK クイック スタート

Xamarin.Mac アプリでの OpenTK の使用に関する簡単な紹介として、ゲーム ビューを開き、そのビューで単純な三角形をレンダリングし、ゲーム ビューを Mac アプリのメイン ウィンドウにアタッチしてユーザーに三角形を表示する単純なアプリケーションを作成します。

新しいプロジェクトの開始

Visual Studio for Mac を起動し、新しい Xamarin.Mac ソリューションを作成します。 [Mac]>[アプリ]>[全般]>[Cocoa アプリ] を選択します。

新しい Cocoa アプリの追加

[プロジェクト名]MacOpenTK を入力します。

プロジェクト名の設定

[作成] ボタンをクリックして、新しいプロジェクトをビルドします。

OpenTK の組み込み

Xamarin.Mac アプリケーションで Open TK を使用するには、事前に OpenTK アセンブリへの参照を含める必要があります。 ソリューション エクスプローラーで、[参照] フォルダーを右クリックし、[参照の編集...] を選択します。

OpenTK にチェックマークを付けて、[OK] ボタンをクリックします。

プロジェクト参照の編集

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

重要

Xamarin.Mac での OpenTK の実装には 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 を呼び出して、新しい要素を描画する前に既存の要素を削除します。

重要

Xamarin.Mac バージョンの OpenTK の場合、レンダリング コードの最後に MonoMacGameView インスタンスの SwapBuffers メソッドを呼び出さないでください。 これを行うと、レンダリングされたビューが表示されるのではなく、ゲーム ビューがすぐにストローブされます。

ゲーム ビューの実行

必要なすべてのイベントが定義され、アプリのメイン Mac ウィンドウにゲーム ビューがアタッチされた状態で、ゲーム ビューを実行してグラフィックスを表示する準備ができました。 次のコードを使用します。

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

ゲーム ビューを更新する適切なフレーム レートを渡します。この例では、1 秒あたり 60 フレーム (通常のテレビと同じリフレッシュ レート) を選択しています。

アプリを実行し、出力を確認してみましょう。

アプリの出力のサンプル

ウィンドウのサイズを変更すると、ゲーム ビューのサイズも変更され、三角形もサイズが変更され、リアルタイムで更新されます。

次の場所

Xamarin.mac アプリケーションで OpenTk を操作する基本を確認したら、次に試す内容の提案をいくつか示します。

  • LoadRenderFrame イベントで三角形の色とゲーム ビューの背景色を変えてみます。
  • ユーザーが UpdateFrameRenderFrame イベントでキーを押すときに三角形の色を変えるか、または独自のカスタム MonoMacGameView クラスを作成し、KeyUpKeyDown メソッドをオーバーライドします。
  • UpdateFrame イベントで対応キーを使用して、三角形を画面上で動かします。 ヒント: Matrix4.CreateTranslation メソッドを使用して平行移動行列を作成し、GL.LoadMatrix メソッドを呼び出して RenderFrame イベントに読み込みます。
  • for ループを使用して、RenderFrame イベントで複数の三角形をレンダリングします。
  • カメラを回転させて、3D 空間内で三角形の別のビューを表示します。 ヒント: Matrix4.CreateTranslation メソッドを使用して平行移動行列を作成し、GL.LoadMatrix メソッドを呼び出して読み込みます。 カメラの操作には Vector2Vector3Vector4、および Matrix4 のクラスを使用することもできます。

その他の例については、OpenTK Samples GitHub リポジトリを参照してください。 OpenTK の使用例の公式の一覧が記載されています。 これらの例は、Xamarin.Mac バージョンの OpenTK で使用できるように調整する必要があります。

まとめ

この記事では、Xamarin.Mac アプリケーションでの OpenTK の使用について簡単に説明しました。 ゲーム ウィンドウを作成する方法、ゲーム ウィンドウを Mac ウィンドウにアタッチする方法、ゲーム ウィンドウで単純な図形をレンダリングする方法について説明しました。