この記事を見ているあなたは「OpenGL ES」という単語を聞いたことがあるでしょうか? OpenGL ESは、組み込み機器で3Dを扱うためのライブラリです。ゲームやコンピュータのUIといった、主に「リアルタイムで3D空間を表示する」必要がある分野で広く利用されています*1。AndroidやiOSといったモバイル機器のほか、PlayStation3やPlayStation Vitaなどのゲーム機で採用されている、まさにマルチプラットフォームのライブラリです。

 そんな「スゴイ」ライブラリのOpenGL ESですが、泣き所はそのとっつきにくさです。筆者の周りでは、「わかりやすいなコイツ!!」「取っ付きやすいぜ、ベイビー!」とか言いながらOpenGL ESを触っている人を見たことがありません。「なんだかよくわからなさそう」「難しそう」と思われるでしょうか? いえ、そんなことはありません! むしろ、自分の書いた「コード」がダイレクトに「見た目」として反映される素晴らしい世界なのです。「OpenGL ESは難しくて歯が立たない」という巷の誤解を少しでも解き、3D CGの世界を楽しんでいただくのがこの記事の狙いです。

 OpenGL ESは幾つかのバージョンがあります。この記事では最もシンプルでなじみやすいOpenGL ES 1.0を取り上げて、Androidを対象にして解説を行います。Androidアプリケーションは無料で開発環境を構築でき、エミュレーターでの動作確認も容易です。OpenGL ESはマルチプラットフォームのライブラリですから、ここで説明していることはもちろん、iOSや他のプラットフォームにも適用可能です。理想論だけを書けば、Android NDKとOpenGL ES、iOS SDKとOpenGL ESの組み合わせを利用すれば、ほぼ書き換え無しで3Dゲームを作ることが可能です。

STEP1 OpenGL ESを初期化する

 Androidで画面上に「何か」を表示する際には、ビュー(View)と呼ばれるUI部品(クラス)を用意します。文字を表示したければ「TextView」、画像を表示したければ「ImageView」といった具合です。OpenGL ESの画面を表示するためには「GLSurfaceView」を利用します。

  Androidアプリケーションにおけるメインの処理は「UIスレッド」と呼ばれるスレッドで実行されます。UIスレッドは常にタッチや描画のイベントを受け取って処理していますが、時間のかかる処理を行うと、アプリケーションが反応しないとみなされ、エラーが発生してしまいます。

図1-1●GLSurfaceViewを利用した場合の各スレッドの動作
図1-1●GLSurfaceViewを利用した場合の各スレッドの動作
リスト1-1●プロジェクトを作成すると自動的に作られるアクティビティ(Activityクラスのサブクラスとして定義)に、赤い色を敷いた部分を追加する
リスト1-1●プロジェクトを作成すると自動的に作られるアクティビティ(Activityクラスのサブクラスとして定義)に、赤い色を敷いた部分を追加する
[画像のクリックで拡大表示]

 GLSurfaceViewの処理は、UIスレッドとは別のスレッドとして並行に動作します。このスレッドでは描画しか行いません。その代わり、どんなに重い処理を行っても、上述のエラーが発生しません。このスレッドを本記事では便宜的に「GLスレッド」と呼びます(図1-1*2

 実際のコードを見てみましょう(リスト1-1)。これだけのコードでOpenGL ESのスケルトン(最低限の実装)が完成です。結構な量のコードを追加しなければならないように見えますが、順を追って見れば、たいしたことはしていません。後はOpenGL ESの描画コマンドを覚えるだけです。

 冒頭では、OpenGL ESを使うためのimport宣言を追加しています(リスト1-1の(1))。続いて、GLSurfaceViewオブジェクトを定義して(同(2))、アクティビティが生成されたタイミングで実行されるonCreateメソッド内でGLSurfaceViewオブジェクトを作成します(同(3))。

 GLSurfaceViewは描画処理の一切を、Rendererインタフェースを実装したクラス(同(7))に任せています。このクラスを以降「レンダラー」と呼びます。GLSurfaceViewクラスのsetRendererメソッド(GLSurfaceView#setRenderer( )と書きます)でレンダラーのオブジェクトを作成して登録した後(同(4))、setContentViewでGLSurfaceViewオブジェクトをアクティビティに関連付けておきます(同(5))。これでonCreateメソッドの処理は完了です。今回は初期化するだけなので、レンダラーであるSampleRenderクラス(同(7))の実装は、空っぽのままで問題ありません。

図1-2●リスト1-1のコードの実行結果
図1-2●リスト1-1のコードの実行結果

 さらに、アクティビティが休止した場合に実行するonPauseメソッド、再開した場合に実行するonResumeメソッドもオーバーライド(上書き)しておきましょう(同(6))。これらのメソッドを記述しておかないと、別のアプリケーションを起動したりディスプレイの電源をオフにした後、OpenGL ESアプリを復帰させられません。

 このコードを実行した結果が、図1-2のスクリーンショットです。何も写ってないように見えますね。はい、その通りです。初期化しただけでは当然ながら何も写りません。このままではOpenGL ESを初期化した実感すらわきません。まずは画面になんらかの変化をつけましょう。