はじめに
2017年8月24日現在、iOSプログラミングに押されて、Macプログラミングの情報がかなり少なくなっています。この記事では、最新のmacOS 10.13とXcode 9を使って、OpenGLを使ったゲームを作る方法を解説します。
なお、最新のXcodeはMac App Storeから誰でも無料で入手できますので、インストールしておいてください。OpenGL用のフレームワークは、初めからmacOSに用意されていますので、Xcode以外にインストールが必要な物はありません。
1. Xcodeプロジェクトの作成
Xcodeのメニューから [File]-[New]-[Project…] を選択し、macOSのテンプレートから「Cocoa App」を選択して「Next」ボタンを押します。
次の画面では、「Product Name」に「MyGLGame」と入力し、「Organization Name」には自分の名前を、「Organization Identifier」には「mytest」と入力します。Swiftよりも、C言語/C++の記法が利用しやすいObjective-Cの方がOpenGLプログラミングに向いていると思いますので、「Language」には「Objective-C」を選択します。またその下にある**「Use Storyboard」のチェックをONにしておきます**。Storyboardを使う場合に用意されるビュー・コントローラを利用した方が、OpenGL用のビューを作成しやすいためです。「Include Unit Tests」と「Include UI Tests」のチェックは外しておきましょう。全部入力し終えたら「Next」ボタンを押します。
次の画面では、プロジェクトを作成するフォルダを指定して「Create」ボタンを押し、プロジェクトの作成を完了します。
2. フレームワークの追加
OpenGL関係のフレームワークをプロジェクトに追加します。
メインウィンドウ左側のプロジェクト名を選択し、「TARGETS」の中の「Build Phases」から「Link Binary With Libraries」を開いて、その下側にある「+」ボタンを押します。
commandキーを押しながら「GLKit.framework」と「OpenGL.framework」の2つのフレームワークを選択して、「Add」ボタンを押してフレームワークを追加します。
追加したフレームワークは「Link Binary With Libraries」に表示されます。
3. カスタムのOpenGLビューを定義する
NSOpenGLViewクラスを継承したカスタムのOpenGLビューを定義して、独自のOpenGLのオプションを設定できるようにします。
ウィンドウ左側のプロジェクト・ナビゲータからViewController.mを選択し、右クリックでコンテキストメニューを出して「New File…」を選択します。
macOSのテンプレートから「Cocoa Class」を選択して「Next」ボタンを押します。
次の画面では「Subclass of」の項目に「NSOpenGLView」と入力し、「Class」の項目に「MyGLView」と入力します。「Next」ボタンを押して、次の画面で「Create」ボタンを押して、クラスの作成を完了します。
MyGLView.hとMyGLView.mの2つのファイルができます。
4. OpenGLビューを生成するコードを書く
ViewController.mファイルを編集して、MyGLViewクラスのインスタンスを生成して追加するコードを書きます。
先頭にMyGLViewクラスの定義を読み込む#import文を追加し、viewDidLoad
メソッドの中にビューが読み込まれた直後にMyGLViewクラスのインスタンスを生成してサブビューとして追加するコードを書きます。最初から用意されているsetRepresentedObject:
メソッドはゲームでは通常使わないメソッドなので、削除しておきます。
#import "ViewController.h"
#import "MyGLView.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSRect viewFrame = [self.view frame];
MyGLView *glView = [[MyGLView alloc] initWithFrame:viewFrame];
glView.translatesAutoresizingMaskIntoConstraints = YES;
glView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[self.view addSubview:glView];
}
@end
Xcodeにおけるビューのレイアウトは、通常はStoryboardの上でグラフィカルに操作して行いますが、OpenGLのバージョンなどを細かく指定してNSOpenGLViewを作成する場合には、このようにalloc
メソッドとinitWithFrame:
メソッドの組み合わせで、明示的にビューを生成するのがもっとも確実な方法です。
translatesAutoresizingMaskIntoConstraints
プロパティを使用して、autoresizingMask
にNSViewWidthSizable
とNSViewHeightSizable
を指定することで、ウィンドウのリサイズに合わせて横方向にも縦方向にも伸縮するビューが作成できます。
なお、今回はXcode 8.3.3の「Cocoa Application」のデフォルトで作成されるプロジェクトテンプレートに合わせてStoryboardの場合について説明していますが、ウィンドウなどをXIBで管理している場合も同様のことが言えます。
XIBの場合は、インスペクタから "Prefer Coder" という設定のチェックを外せばGUI操作で貼り付けたビューの
initWithFrame:
メソッドが呼ばれるようになりますが(チェックが付いている場合にはinitWithCoder:
メソッドが呼ばれる)、明示的にalloc
してinitWithFrame:
メソッドを呼び出すと考えた方が、動作の流れが見えやすくなると思います。
5. MyGLViewクラスの実装を書く
最後に、MyGLView.mを次のように編集しましょう。OpenGL関係のヘッダファイルをインポートして、initWithFrame:
メソッドでOpenGLのバージョンなどのオプションを指定してビューの初期化を行います。OpenGLの内部的な初期化が終わった直後にはprepareOpenGL
メソッドが呼ばれますので、ここでOpenGLの描画設定を行います。
#import "MyGLView.h"
#import <OpenGL/OpenGL.h>
#import <OpenGL/gl3.h>
@implementation MyGLView
- (instancetype)initWithFrame:(NSRect)frame
{
NSOpenGLPixelFormatAttribute attrs[] =
{
NSOpenGLPFAAllowOfflineRenderers,
NSOpenGLPFAAccelerated,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 32,
NSOpenGLPFAMultisample,
NSOpenGLPFASampleBuffers, 1,
NSOpenGLPFASamples, 4,
NSOpenGLPFANoRecovery,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
0
};
NSOpenGLPixelFormat *pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
self = [super initWithFrame:frame pixelFormat:pixelFormat];
if (self) {
[self setWantsBestResolutionOpenGLSurface:YES];
}
return self;
}
- (void)prepareOpenGL
{
[super prepareOpenGL];
NSOpenGLContext *glContext = [self openGLContext];
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
[glContext flushBuffer];
}
@end
5.1. OpenGL初期化オプションの指定
initWithFrame:
メソッドの中では、様々なオプションをNSOpenGLPixelFormatAttribute
の配列として指定して、それを元にNSOpenGLPixelFormat
クラスのオブジェクトを作成します。このオプション指定の配列の中身は、基本的には、設定のキーと設定のバリューが交互に並んだ形になっています。そしてこれを親クラス (NSOpenGLViewクラス) のinitWithFrame:pixelFormat:
メソッドに渡すことで、指定した内容で初期化したOpenGLビューの作成が完了します。
とくにここでは、「NSOpenGLPFAOpenGLProfile
」をキーにして「NSOpenGLProfileVersion3_2Core
」を指定することによって、OpenGLの最新のバージョンを利用することを表しているところに着目してください。名前に「3_2Core」と付いているので、OpenGL 3.2 (Core Profile)に限定しているように見えますが、実際にはこれで最新のバージョン(筆者の環境だとOpenGL 4.1)が使用されるようになります。
なお、作成完了直後のタイミングでsetWantsBestResolutionOpenGLSurface:
メソッドをYES
を引数にして呼び出すことによって、Retinaディスプレイの解像度での描画をサポートできます。
5.2. prepareOpenGLでの処理
prepareOpenGL
メソッドでは、見慣れたglClearColor()
関数とglClear()
関数を組み合わせて、紫色をクリアカラーに指定して画面をクリアしています。画面の描画処理が終わったあとに、OpenGLのコンテキストに対してflushBuffer
メソッドを呼び出すことで、描画結果が画面に表示されるようになります。
6. まとめ
今回の記事では、Xcodeの新規プロジェクトの中でNSOpenGLViewクラスのサブクラスを作成して、最新のOpenGLのバージョンを指定してウィンドウ描画ができるようにするところまで解説しました。
ここから数回の解説を通じて、Mac上でOpenGLを利用するための基本を身につけていきましょう。
ここまでのプロジェクト:MyGLGame_step1-1.zip