• 検索結果がありません。

iOS用OpenGL ESプログラミングガイド (TP )

N/A
N/A
Protected

Academic year: 2021

シェア "iOS用OpenGL ESプログラミングガイド (TP )"

Copied!
155
0
0

読み込み中.... (全文を見る)

全文

(1)

iOS

OpenGL ES

(2)

目次

OpenGL ESについて

10 はじめに 10 OpenGL ESはiOSにおけるプラットフォームに依存しないAPI 11 GLKitによる描画サーフェスとアニメーションサポートの提供 11 iOSでの代替レンダリング対象のサポート 12 アプリケーションに必要な追加のパフォーマンスチューニング 12 バックグラウンドアプリケーションでOpenGL ESを使用できない可能性について 13 OpenGL ESによるマルチスレッドアプリケーションへのその他の制約事項 13 この文書の使い方 13 必要事項 14 関連項目 14

OpenGL ESを組み込んでiOSアプリケーションを構築するためのチェックリスト

15 サポートするOpenGL ESバージョンの選択 15 OpenGL ESの機能の検証 16 レンダリング先の選択 17 iOSとの一体化 17 レンダリングエンジンの実装 18 デバッグとプロファイル 18

OpenGL ESコンテキストの設定

19 EAGLとはOpenGL ESレンダリングコンテキストのiOSにおける実装 19 現在のコンテキストはOpenGL ES関数呼び出しのターゲット 19 どのコンテキストもOpenGL ESの特定のバージョンをターゲットにする 20 EAGL sharegroupはコンテキストのOpenGL ESオブジェクトを管理 21

OpenGL ESおよびGLKitによる描画

24

GLKit ViewはOpenGL ESコンテンツをオンデマンドで描画する 24 GLKit Viewの作成と設定 25

GLKit Viewの描画 26

デリゲートオブジェクトを使用したレンダリング 28

GLKit View ControllerがOpenGL ESコンテンツをアニメーション化する 29 アニメーションループについて 29

(3)

GLKitを使用したレンダラの開発 32 ベクトルと行列の数値演算の処理 32 OpenGL ES 1.1の固定機能パイプラインからの移行 32 テクスチャデータの読み込み 33

その他のレンダリング先への描画

34 フレームバッファオブジェクトの生成 34 オフスクリーンフレームバッファオブジェクトの作成 35 フレームバッファオブジェクトを使用したテクスチャへのレンダリング 36 Core Animationレイヤへのレンダリング 37 フレームバッファオブジェクトへの描画 39 オンデマンドまたはアニメーションループでのレンダリング 39 フレームのレンダリング 41 マルチサンプル機能の使用による画像品質の向上 43

マルチタスク、高解像度、iOSのその他の機能

47 マルチタスク対応OpenGL ESアプリケーションの実装 47 バックグラウンドのアプリケーションはグラフィックスハードウェアのコマンドを実行しない場 合がある 47 作成し直したリソースをバックグラウンドに移動する前に簡単に削除 48 高解像度ディスプレイのサポート 49 デバイスの向きに応じた調整 51 外部ディスプレイへのOpenGL ESコンテンツの表示 51

OpenGL ES設計ガイドライン

52 OpenGL ESを視覚化する方法 52 クライアント/サーバアーキテクチャとしてのOpenGL ES 52 グラフィックスパイプラインとしてのOpenGL ES 53 OpenGL ESの版とレンダラのアーキテクチャ 54 OpenGL ES 3.0 54 OpenGL ES 2.0 59 OpenGL ES 1.1 59 高パフォーマンスなOpenGL ESアプリケーションの設計 59 同期とフラッシュの操作の回避 62 glFlushの効果的な使用 62 OpenGL ESの状態照会の回避 63 OpenGL ESを使用したリソースの管理 63 ダブルバッファリングによるリソースの競合の回避 63 OpenGL ESの状態に注意を払う 65 OpenGL ESのオブジェクトで状態をカプセル化する 66

(4)

描画関数の呼び出しを整理して状態変化を最小限に抑える 66

OpenGL ESアプリケーションのチューニング

68 XcodeやInstrumentsで、アプリケーションをデバッグ、プロファイリングする 68 XcodeやInstrumentsでOpenGL ESのエラーを監視する 69 情報提供のデバッグおよびプロファイル用に、OpenGL ESのコードに注釈を付ける 70 パフォーマンスのための一般的な推奨事項 71 シーンのデータが変更された場合のみシーンを再描画する 71 使用しないOpenGL ES機能を無効にする 72 ライティングモデルを簡素化する 72 タイルベースの遅延レンダリングを効率的に使う 72 論理バッファの読み込みや格納を避ける 73 隠面除去を効率的に使う 74 OpenGL ESコマンドをグループ化して効率的にリソースを管理する 75 描画コマンドの数を最小限に抑える 76 インスタンス描画法により描画関数の呼び出し回数を減らす 76 OpenGL ESのメモリ消費を最小限に抑える 79 Core Animation合成のパフォーマンスに注意する 79

頂点データを扱うためのベストプラクティス

81 モデルの簡素化 82 属性の配列に定数を格納するのを避ける 83 属性には可能な限り最小の型を使用する 83 インターリーブされた頂点データを使用する 84 ずれた頂点データを避ける 85 三角形ストリップを使用して頂点データを一括処理する 85 頂点バッファオブジェクトの使用による頂点データのコピーの管理 87 バッファの使用に関するヒント 89 頂点配列オブジェクトの使用による頂点配列状態の変化の整理統合 92 バッファをクライアント側メモリにマップして高速に更新する 94

テクスチャデータを扱うためのベストプラクティス

97 初期化中にテクスチャをロードする 97 GLKitフレームワークを使用したテクスチャデータの読み込み 97 テクスチャのメモリ使用量を削減する 99 テクスチャの圧縮 99 低精度のカラーフォーマットを使用する 99 適切なサイズのテクスチャを使用する 100 複数のテクスチャをテクスチャアトラスにまとめる 100 ミップマップを使用してメモリの帯域幅の使用を削減する 101

(5)

マルチパスの代わりにマルチテクスチャリングを使用する 101

シェーダのベストプラクティス

103 初期化中にシェーダをコンパイルおよびリンクする 103 デバッグ時のシェーダプログラムエラーのチェック 103 コンパイルとリンクを高速化するために別々のシェーダオブジェクトを使用する 104 シェーダに関するハードウェア制限に従う 106 精度ヒントを使用する 106 ベクトル計算の時間のかかる実行 107 シェーダ内での計算の代わりにuniformまたはconstantを使用する 108 分岐命令は注意して使う 108 ループをなくす 109 シェーダにおける配列インデックスの計算を避ける 109 動的なテクスチャ検索に注意する 109 プログラマブルブレンディング用にフレームバッファのデータを取得する 110 フレームバッファを取得する(GLSL ES 1.0の場合) 112 フレームバッファを取得する(GLSL ES 3.0の場合) 113 頂点シェーダで、より大容量のメモリバッファとしてテクスチャを使う 113

並列処理とOpenGL ES

115 並列処理のメリットがあるかどうか判断する 115 OpenGL ESは各コンテキストを単一スレッドに制限 116 OpenGL ESアプリケーションに並列処理を実装する方法 117 マルチスレッド化したOpenGL ES 118 ワーカータスクにおけるOpenGL ES演算の実行 118 複数のOpenGL ESコンテキストの使用 119 OpenGL ESアプリケーションのスレッド化に関するガイドライン 120

OpenGL ES 3.0への移行

121 OpenGL ES 3.0に移行するためのチェックリスト 121 拡張機能のコードを改訂する 122 拡張機能の接尾辞を除去する 122 拡張機能APIの使い方を修正する 122 他の拡張機能も、多くはOpenGL ES 3.0でもそのまま利用できる 124 OpenGL ESシェーディング言語の第3.0版に移行する 124

Xcodeに付属するOpenGL ES用ツールの概要

126 「FPS Debug Gauge」および「GPU Report」の使い方 126 OpenGL ESのフレームを取り込んで分析する 128

(6)

ナビゲータ領域 132 エディタ領域 133 デバッグ領域 139

texturetoolを使用したテクスチャの圧縮

143 texturetoolのパラメータ 143

書類の改訂履歴

149

用語解説

151

(7)

図、リスト

OpenGL ESコンテキストの設定

19 図 2-1 2つのコンテキストによるOpenGL ESオブジェクトの共有 22 リスト 2-1 同じアプリケーションでの複数バージョンのOpenGL ESのサポート 20 リスト 2-2 共通のsharegroupを持つ2つのコンテキストの作成 22

OpenGL ESおよびGLKitによる描画

24

図 3-1 GLKit ViewでのOpenGL ESコンテンツのレンダリング 25 図 3-2 アニメーションループ 29

リスト 3-1 GLKit Viewの設定 26

リスト 3-2 GLKit Viewの描画メソッドの例 26

リスト 3-3 ハードウェアの機能に基づいたレンダラクラスの選択 28

リスト 3-4 GLKit ViewおよびView Controllerを使用した、OpenGL ESコンテンツの描画とアニメーショ ン化 30

その他のレンダリング先への描画

34

図 4-1 色と深度のレンダバッファを持つフレームバッファ 34 図 4-2 Core AnimationとOpenGL ESとのレンダバッファの共有 37 図 4-3 iOSにおけるOpenGLのレンダリング手順 41 図 4-4 マルチサンプル機能の仕組み 44 リスト 4-1 ディスプレイリンクの作成と開始 40 リスト 4-2 フレームバッファアタッチメントの消去 41 リスト 4-3 深度フレームバッファの破棄 43 リスト 4-4 レンダリングの完了したフレームの表示 43 リスト 4-5 マルチサンプルバッファの作成 44

OpenGL ES設計ガイドライン

52 図 6-1 OpenGL ESのクライアント/サーバアーキテクチャ 52 図 6-2 OpenGL ESグラフィックスパイプライン 53 図 6-3 フラグメントシェーダが多重レンダターゲットに出力する様子 55 図 6-4 パーティクル系アニメーションの概要 57 図 6-5 変換のフィードバック機能を利用するグラフィックスパイプラインの構成例 58 図 6-6 リソース管理のためのアプリケーションモデル 60 図 6-7 単一のバッファに格納されたテクスチャデータ 64 図 6-8 ダブルバッファリングされたテクスチャデータ 65

(8)

リスト 6-1 多重レンダターゲットを用意するコード例 55

リスト 6-2 多重レンダターゲットに出力するフラグメントシェーダのコード例 56

OpenGL ESアプリケーションのチューニング

68

図 7-1 デバッグマーカグループの追加前と追加後のXcode Frame Debugger 70 図 7-2 透明なオブジェクトをトリミングしてフラグメント処理を減らす様子 75 リスト 7-1 デバッグマーカを使って描画コマンドに注釈をつけるコード例 71 リスト 7-2 デバッグラベルを利用してOpenGL ESオブジェクトに注釈をつけるコード例 71 リスト 7-3 インスタンス描画法によらずに、よく似たオブジェクトを多数描画するコード例 77 リスト 7-4 OpenGL ES 3.0の頂点シェーダが、gl_InstanceIDをもとに、インスタンスによって異な る値を計算するコード例 77 リスト 7-5 インスタンスごとに異なる情報を頂点属性に格納するコード例 78 リスト 7-6 インスタンス配列を参照して動作するOpenGL ES 3.0の頂点シェーダ 78

頂点データを扱うためのベストプラクティス

81 図 8-1 シェーダ変数への属性データの変換 81 図 8-2 インターリーブされたメモリ構造では、ある頂点に関するすべてのデータがまとめてメ モリに配置されます。 84 図 8-3 一部のデータの使われ方が異なる場合に複数の頂点構造体を使用する 84 図 8-4 追加の処理を避けるために頂点データを揃える 85 図 8-5 三角形ストリップ 85 図 8-6 縮退三角形を使用して三角形ストリップをマージする 86 図 8-7 頂点配列オブジェクトの設定 93 リスト 8-1 OpenGL ES 3.0でのプリミティブスタートの使用 86 リスト 8-2 シェーダプログラムへの頂点データの送信 87 リスト 8-3 頂点バッファオブジェクトを生成するコード例 88 リスト 8-4 頂点バッファオブジェクトを使って描画するコード例 89 リスト 8-5 複数の頂点バッファオブジェクトの使用によるモデルの描画 90 リスト 8-6 頂点配列オブジェクトの設定 93 リスト 8-7 手動同期により頂点バッファを動的に更新するコード例 95

テクスチャデータを扱うためのベストプラクティス

97 リスト 9-1 ファイルからの2次元テクスチャの読み込み 98

シェーダのベストプラクティス

103 図 10-1 従来型の固定機能ブレンディング 110 図 10-2 プログラマブルブレンディングとフレームバッファのデータ取得 111 リスト 10-1 開発ビルドでのみシェーダのコンパイル/リンクログを読み込む 103 リスト 10-2 独立したシェーダオブジェクトをコンパイル、使用するコード例 104 リスト 10-3 フラグメントの色に低精度を使用する 106

(9)

リスト 10-4 ベクトル演算をうまく活用していない 107 リスト 10-5 ベクトル演算の適切な使用 107 リスト 10-6 書き込みマスクの指定 108 リスト 10-7 従属テクスチャ読み込み 110 リスト 10-8 プログラマブルブレンディングをおこなうフラグメントシェーダの、GLSL ES 1.0による 実装例 112 リスト 10-9 色の後処理を施すフラグメントシェーダの、GLSL ES 3.0による実装例 113 リスト 10-10 高さマップからレンダリングする頂点シェーダ 114

Xcodeに付属するOpenGL ES用ツールの概要

126

図 B-1 「FPS Debug Gauge」および「GPU Report」の画面 126 図 B-2 「Debug」バーと「Capture OpenGL ES Frame」ボタン 129

図 B-3 フレームデバッガに描画関数呼び出しとリソースの状況が表示されている様子 131 図 B-4 フレームデバッガにシェーダプログラムの処理性能や分析結果が表示されている様子

132

図 B-5 ナビゲータの「View Frame By」ポップアップメニュー 132 図 B-6 フレームバッファ情報ポップオーバー 134 図 B-7 フレームバッファ設定ポップオーバー 135 図 B-8 GLSLシェーダのソースエディタと更新ボタン 136 図 B-9 アシスタントエディタに配列バッファの内容を表示している様子 137 図 B-10 アシスタントエディタに頂点配列オブジェクトがプレビュー表示されている様子 137 図 B-11 アシスタントエディタにキューブマップテクスチャをプレビュー表示している様子138 図 B-12 OpenGL ESのデバッグバー 139 図 B-13 デバッグ領域に「GL Context」ビューと「Bound GL Objects」ビューが表示されている様 子 140 図 B-14 デバッグ領域に「Auto」ビューと「Context Info」ビューが現れている様子 141

texturetoolを使用したテクスチャの圧縮

143 リスト C-1 エンコードオプション 144 リスト C-2 画像をPVRTC圧縮フォーマットにエンコードする。 147 リスト C-3 プレビューを作成するとともに画像をPVRTC圧縮フォーマットにエンコードする 147

(10)

Open Graphics Library(OpenGL)は、2Dおよび3Dのデータを視覚化するために使用します。OpenGL は、オープンスタンダードに基づいた多用途のグラフィックスライブラリで、2Dおよび3Dのデジタ ルコンテンツ作成、機械設計および建築設計、仮想プロトタイピング、フライトシミュレーション、 ビデオゲームなどのアプリケーションをサポートします。OpenGLを使用して、3Dグラフィックスパ イプラインを設定し、そのパイプラインにデータを送信します。頂点は、変形およびライティングさ れ、プリミティブとして組み立てられ、ラスタ化されて2D画像が作成されます。OpenGLは関数呼び 出しを、基盤となるグラフィックスハードウェアに送信可能なグラフィックスコマンドに変換するた めに設計されています。この基盤ハードウェアはグラフィックスコマンドの処理専用のため、OpenGL による描画は一般に非常に高速です。

OpenGL for Embedded Systems(OpenGL ES)は、OpenGLの冗長な機能を取り除いた簡略版で、OpenGL よりも覚えやすく、モバイルグラフィックスハードウェアに実装しやすいライブラリを提供します。

はじめに

OpenGL ESを使用すると、基盤となるグラフィックスプロセッサの機能をアプリケーションが利用で きます。iOSデバイスのGPUは、洗練された2Dおよび3D描画のほか、最終画像のすべてのピクセルで 複雑なシェーディング計算を実行できます。OpenGL ESを使用すべきなのは、アプリケーションの設 計要件でGPUハードウェアに対して可能な最も直接的かつ包括的なアクセスが必要とされる場合で す。OpenGL ESの一般的なクライアントとして、3Dグラフィックスを表示するビデオゲームやシミュ レーションがあります。 OpenGL ESは、低レベルでハードウェアに焦点を合わせたAPIです。最も高機能で柔軟なグラフィック ス処理ツールではありますが、学習曲線が急で、アプリケーションの設計全体に対して重大な影響が あります。特殊なユーザのために高性能なグラフィックスが必要なアプリケーションに対して、iOS はいくつかのより高レベルなフレームワークを提供します。

OpenGL ESについて

(11)

Sprite Kitフレームワークは、2Dゲームの作成に対して最適化された、ハードウェアで加速するア

ニメーションシステムを提供します。(Sprite Kit Programming Guide を参照。)

Core Imageフレームワークは、静止画と動画に対してリアルタイムのフィルタと分析を行います。

(Core Image Programming Guide を参照。)

Core Animationは、ハードウェアで加速するグラフィックスレンダリングと、すべてのiOSアプリ

ケーションのためのアニメーションインフラストラクチャのほか、洗練されたユーザインター フェイスのアニメーションを簡単に実装できるようにする、簡単な宣言型プログラミングモデル も備えています。(Core Animation Programming Guide を参照。)

UIKitフレームワークの機能を使用して、Cocoa Touchユーザインターフェイスに対して、アニメー

ション、物理ベースのダイナミクス、およびその他の特殊効果を追加できます。

OpenGL ESはiOSにおけるプラットフォームに依存しないAPI

OpenGL ESはC言語ベースのAPIであるため、移植性が非常に高く、幅広くサポートされています。 OpenGL ESは、C言語のAPIとして、Objective-CのCocoa Touchアプリケーションとシームレスに統合し ます。OpenGL ESの仕様はウインドウレイヤを定義しておらず、ホストオペレーティングシステムが OpenGL ESレンダリングコンテキスト(コマンド受理)とフレームバッファ(描画コマンドの結果の 書き込み先)を作成する関数を提供しなければなりません。iOS上でOpenGL ESを使用する場合は、iOS クラスを使用して描画サーフェスを設定および表示し、プラットフォームに依存しないAPIを使用し てそのコンテンツをレンダリングします。 関連する章: “OpenGL ESを組み込んでiOSアプリケーションを構築するためのチェックリス ト” (15 ページ)、“OpenGL ESコンテキストの設定” (19 ページ)

GLKitによる描画サーフェスとアニメーションサポートの提供

UIKitフレームワークによって定義された、ViewおよびView Controllerにより、iOS上でビジュアルコン テンツの表示が制御されます。GLKitフレームワークは、これらのクラスのOpenGL ES対応バージョン を提供します。OpenGL ESアプリケーションの開発時に、GLKViewオブジェクトを使用してOpenGL ES

コンテンツをレンダリングします。GLKViewControllerオブジェクトを使用して、ビューを管理し

たり、そのコンテンツのアニメーション化をサポートしたりすることもできます。

(12)

関連する章: “OpenGL ESおよびGLKitによる描画” (24 ページ)

iOSでの代替レンダリング対象のサポート

画面全体またはビュー階層の一部を占める描画コンテンツ以外に、他のレンダリング方法にOpenGL ES フレームバッファオブジェクトも使用できます。iOSは、標準的なOpenGL ESフレームバッファオブ ジェクトを実装します。これは、オフスクリーンバッファやOpenGL ESシーンの他の部分で使用する テクスチャへのレンダリングに使用できます。さらに、iOS上のOpenGL ESは、Core Animationレイヤ (CAEAGLLayerクラス)へのレンダリングをサポートします。このレイヤを他のレイヤと結合して、 アプリケーションのユーザインターフェイスまたはその他の視覚的表示を構築することができます。 関連する章: “その他のレンダリング先への描画” (34 ページ)

アプリケーションに必要な追加のパフォーマンスチューニング

グラフィックスプロセッサは、グラフィックス操作向けに最適化された並行処理デバイスです。アプ リケーションに優れたパフォーマンスを発揮させるには、グラフィックスハードウェアがアプリケー ションと並行で動作するよう、アプリケーションを注意深く設計してデータとコマンドをOpenGL ES に供給しなければなりません。チューニングが十分でないアプリケーションは、一方がコマンドの処 理を完了するまでCPUまたはGPUのどちらかを待機させることになります。 OpenGL ES APIを効率よく使用してアプリケーションを設計してください。アプリケーションのビルド が完了したら、Instrumentsを使用してアプリケーションのパフォーマンスを微調整します。OpenGL ES内でアプリケーションのボトルネックが発生している場合は、このガイドの情報を使用してアプリ ケーションのパフォーマンスを最適化してください。

Xcode は、OpenGL ESアプリケーションのパフォーマンスを向上する新しいツールを提供します。

(13)

関連する章: “OpenGL ES設計ガイドライン” (52 ページ)、“頂点データを扱うためのベス トプラクティス” (81 ページ)、“テクスチャデータを扱うためのベストプラクティ ス” (97 ページ)、“シェーダのベストプラクティス” (103 ページ)、“OpenGL ESアプリケー ションのチューニング” (68 ページ)

バックグラウンドアプリケーションでOpenGL ESを使用できない可能性に

ついて

バックグラウンドで実行されるアプリケーションはOpenGL ES関数を呼び出さない場合があります。 アプリケーションがバックグラウンド時にグラフィックスプロセッサにアクセスすると、iOSがアプ リケーションを自動的に終了します。これを回避するには、バックグラウンドへの移行前にOpenGL ES に送信された未処理のコマンドをフラッシュし、アプリケーションがフォアグラウンドに戻るまでの 間OpenGL ESを呼び出さないようにする必要があります。 関連する章: “マルチタスク、高解像度、iOSのその他の機能” (47 ページ)

OpenGL ESによるマルチスレッドアプリケーションへのその他の制約事項

並列処理を利用するようアプリケーションを設計することは、アプリケーションパフォーマンスの向 上に役立つ可能性があります。OpenGL ESアプリケーションに並列処理を追加する場合は、アプリケー ションが、異なる2つのスレッドから同じコンテキストに同時にアクセスしないようにしなければな りません。 関連する章: “並列処理とOpenGL ES” (115 ページ)

この文書の使い方

まず、“OpenGL ESを組み込んでiOSアプリケーションを構築するためのチェックリスト” (15 ペー ジ)、“OpenGL ESコンテキストの設定” (19 ページ)、“OpenGL ESおよびGLKitによる描画” (24 ペー ジ)の3章を読んでください。ここでは、OpenGL ESがiOSに統合されている様子を概観した後、この ライブラリを活用する初めてのアプリケーションを実装し、iOSデバイス上で実行するために必要な 事項を詳しく解説します。

iOSでOpenGL ESを使うための基本事項を理解したところで、プラットフォームに特有の重要なガイド ラインを述べた、“その他のレンダリング先への描画” (34 ページ)、“マルチタスク、高解像度、iOS のその他の機能” (47 ページ)の2章に目を通してください。iOS 5.0以前でOpenGL ESを使ったことが ある開発者向けに、“OpenGL ESおよびGLKitによる描画” (24 ページ)で、開発効率の向上に資する 新機能を紹介しています。

(14)

最後に、“OpenGL ES設計ガイドライン” (52 ページ)、“OpenGL ESアプリケーションのチューニン グ” (68 ページ)の2章およびそれ以降の各章で、効率のよいOpenGL ESアプリケーションの設計法 を、深く掘り下げて解説します。 特に断りのない限り、本書のOpenGL ESコード例は、OpenGL ES 3.0を対象としています。他のバージョ ンのOpenGL ESでこのコード例を使用するには、変更を加える必要がある場合があります。

必要事項

OpenGL ESを使用してみる前に、iOSアプリケーション全体のアーキテクチャに慣れておく必要があり ます。詳細については、『Start Developing iOS Apps Today 』を参照してください。

この資料は、各種プラットフォームで動作するOpenGL ESのAPIの、詳細なチュートリアルやリファレ ンスとしては使えません。OpenGL ESについてさらに詳しくは、以下に示す資料を参照してください。

関連項目

OpenGL ESはKhronos Groupによって定義された公開標準です。OpenGL ES標準の詳細については、 http://www.khronos.org/opengles/のWebページを参照してください。

『OpenGL® ES 3.0 Programming Guide 』(Addison-Wesley刊行)は、OpenGL ESの概念についての総

合的な入門書です。

『OpenGL® Shading Language, Third Edition 』(Addison-Wesley刊行)は、OpenGL ESアプリケーショ

ンで使用可能な多くのシェーディングアルゴリズムを提供しています。これらのアルゴリズムの 一部は、モバイルグラフィックスプロセッサ上で効率よく実行するために修正が必要となる場合 があります。

OpenGL ES API Registryは、OpenGL ES仕様、OpenGL ESシェーディング言語仕様、およびOpenGL ES

拡張機能に関する文書の公式リポジトリです。

『OpenGLESFrameworkReference 』は、OpenGL ESをiOSに統合するためにAppleが提供する、プラッ

トフォーム固有の関数とクラスを解説しています。

『iOS Device Compatibility Reference 』では、アプリケーションで利用可能なハードウェアおよびソ

フトウェア機能についての詳細情報が記されています。

『GLKit Framework Reference 』は、OpenGL ES 2.0および3.0アプリケーションの開発を容易にする

ためにAppleが提供しているフレームワークを解説しています。

(15)

OpenGL ESの仕様により、GPUハードウェアを使用してグラフィックスをレンダリングするための、 プラットフォームに依存しないAPIが定義されます。OpenGL ESを実装するプラットフォームは、 OpenGL ESコマンドを実行するためのレンダリングコンテキスト、レンダリング結果を保持するフレー ムバッファ、およびフレームバッファのコンテンツを表示する1つ以上のレンダリング先を提供しま す。iOSでは、EAGLContextクラスがレンダリングコンテキストを実装します。iOSが提供するフレー

ムバッファはOpenGL ESフレームバッファオブジェクトの1種類のみで、GLKViewおよびCAEAGLLayer

クラスがレンダリング先を実装します。

iOSでOpenGL ESアプリケーションを構築する場合は、いくつかの考慮事項があります。OpenGL ESプ ログラミングに汎用的なものもあれば、iOSに固有のものもあります。以下のチェックリストとその 下の詳細な節に従って始めましょう。 1. アプリケーションに対して適切な機能セットを持つOpenGL ESのバージョンを判断し、OpenGL ES コンテキストを作成します。 2. 使用するOpenGL ESの機能がデバイスでサポートされていることを実行時に確認します。 3. OpenGL ESコンテンツのレンダリング先を選択します。 4. iOSでアプリケーションが正しく実行されていることを確認します。 5. レンダリングエンジンを実装します。

6. Use XcodeおよびInstrumentsを使用してOpenGL ESアプリケーションをデバッグし、最適なパフォー マンスが実現されるように調整します。

サポートするOpenGL ESバージョンの選択

OpenGL ES 3.0、OpenGL ES 2.0、OpenGL ES 1.1のどれをサポートするか、または複数のバージョンをサ ポートするか、を判断します。

OpenGL ES 3.0はiOS 7で新たに導入された版です。高い処理性能を実現し、さまざまな目的にGPU

計算技術を駆使するばかりでなく、従来はデスクトップ機やゲームコンソールでしか実現できな かった、より複雑な視覚効果を生み出す数々の新機能を備えています。 ● OpenGL ES 2.0はiOSデバイス用のベースラインプロファイルで、プログラマブルシェイダを基盤と する、適合性の高いグラフィックスパイプラインを提供します。

OpenGL ESを組み込んでiOSアプリケーションを

構築するためのチェックリスト

(16)

OpenGL ES 1.1はごく基本的な固定機能グラフィックスパイプラインを提供するだけであり、iOSに

今でも搭載されているのは、後方互換性の維持だけが目的です。

アプリケーションに最も関係のある機能やデバイスをサポートするOpenGL ESのバージョンを対象に する必要があります。iOSデバイスにおけるOpenGL ESの能力については、『iOS Device Compatibility

Reference 』を参照してください。

サポートする予定のOpenGL ESのバージョンのコンテキストの作成については、“OpenGL ESコンテキ ストの設定” (19 ページ)を参照してください。また、OpenGL ESのバージョンによって、利用でき るレンダリングアルゴリズムにどのような違いがあるか、“OpenGL ESの版とレンダラのアーキテク チャ” (54 ページ)で解説します。

OpenGL ESの機能の検証

iOS Device Compatibility Reference では、iOSデバイスの出荷時に用意されている機能と拡張機能の概要

を示します。ただし、アプリケーションをできるだけ多くのデバイスとiOSバージョン上で実行でき るようにするために、アプリケーションは実行時の機能について必ずOpenGL ESの実装を照会する必 要があります。 最大テクスチャサイズや頂点属性の最大数など、実装固有の制限を確認するには、そのデータ型に適 したglGet関数を使用して、対応するトークンの値を調べます(gl.hヘッダにあるMAX_TEXTURE_SIZE やMAX_VERTEX_ATTRIBSなど)。 OpenGL ES 3.0拡張機能の有無を確認するには、次のコード例のように、glGetIntegervおよび glGetStringi関数を使用します。

BOOL CheckForExtension(NSString *searchName) {

// Create a set containing all extension names.

// (For better performance, create the set only once and cache it for future use.)

int max = 0;

glGetIntegerv(GL_NUM_EXTENSIONS, &max);

NSMutableSet *extensions = [NSMutableSet set]; for (int i = 0; i < max; i++) {

[extensions addObject: @( (char *)glGetStringi(GL_EXTENSIONS, i) )]; }

return [extensions containsObject: searchName]; OpenGL ESの機能の検証

(17)

} OpenGL ES 1.1および2.0の拡張機能の有無を確認するには、glGetString(GL_EXTENSIONS)を呼び出 して、すべての拡張名のスペース区切りの一覧を取得します。

レンダリング先の選択

In iOSでは、フレームバッファオブジェクトに描画コマンドの結果が格納されます。(iOSにはウイン ドウシステム提供のフレームバッファは実装されません。)フレームバッファオブジェクトのコンテ ンツは次のような複数の方法で使用できます。 ● GLKitフレームワークは、OpenGL ESコンテンツを描画し、独自のフレームバッファオブジェクト

を管理するビュー、およびOpenGL ESコンテンツのアニメーションをサポートするView Controller を提供します。これらのクラスを使用して、全画面表示を作成するか、OpenGL ESコンテンツを UIKit View階層に収めます。これらのクラスについては、“OpenGL ESおよびGLKitによる描

画” (24 ページ)を参照してください。

CAEAGLLayerクラスは、OpenGL ESコンテンツをCore Animationレイヤ合成の一部として描画する

方法を提供します。このクラスの使用時に独自のフレームバッファオブジェクトを作成する必要 があります。 ● 他のOpenGL ES実装と同様に、オフスクリーングラフィックス処理や、グラフィックスパイプラ インの他の部分で使用するテクスチャへのレンダリングにもフレームバッファを使用できます。 OpenGL ES 3.0で、オフスクリーンバッファは複数のレンダリング対象を利用するレンダリングア ルゴリズムで使用できます。 オフスクリーンバッファ、テクスチャ、またはCore Animationレイヤへのレンダリングについては、 “その他のレンダリング先への描画” (34 ページ)を参照してください。

iOSとの一体化

iOSアプリケーションはデフォルトではマルチタスクをサポートしていますが、OpenGL ESアプリケー ションでこの機能を正しく扱うには、さらに考慮が必要です。OpenGL ESを適切に使用しないと、ア プリケーションがバックグラウンドに移動したときにシステムによって強制終了される可能性があり ます。 多くのiOSデバイスには高解像度ディスプレイが含まれるため、アプリケーションは複数の表示サイ ズと解像度をサポートする必要があります。 レンダリング先の選択

(18)

これらの機能やiOSのその他の機能のサポートについては、“マルチタスク、高解像度、iOSのその他の 機能” (47 ページ)を参照してください。

レンダリングエンジンの実装

OpenGL ESの描画コードの設計には可能な方法が多数あり、その詳細はこのマニュアルの範囲を超え ています。レンダリングエンジンの設計の多くの側面は、OpenGLおよびOpenGL ESのすべての実装に 汎用的です。

iOSの開発者にとって重要な設計上の考慮事項については、“OpenGL ES設計ガイドライン” (52 ペー ジ)および“並列処理とOpenGL ES” (115 ページ)を参照してください。

デバッグとプロファイル

XcodeおよびInstrumentsは、アプリケーションにおいて、レンダリングの問題を特定し、OpenGL ESの パフォーマンスを分析する多数のツールを備えています。

OpenGL ESアプリケーションでの問題の解決とパフォーマンスの向上については、“OpenGL ESアプリ ケーションのチューニング” (68 ページ)を参照してください。

(19)

OpenGL ESのどの実装も、OpenGL ES仕様で求められる状態を管理するためのレンダリングコンテキス トを作成する手段を提供します。この状態をコンテキスト内に配置することにより、複数のアプリ ケーションが、ほかのアプリケーションの状態に干渉することなく、グラフィックスハードウェアを 容易に共有できます。 この章では、iOS上でコンテキストを作成し、設定する方法を詳しく説明します。

EAGLとはOpenGL ESレンダリングコンテキストのiOSにおける

実装

アプリケーションがOpenGL ES関数を呼び出せるようにするには、アプリケーションがEAGLContext

オブジェクトを初期化する必要があります。EAGLContextクラスも、OpenGL ESコンテンツをCore

Animationに統合するために使用する手段を提供します。

現在のコンテキストはOpenGL ES関数呼び出しのターゲット

iOSアプリケーションのすべてのスレッドには、現在のコンテキストがあります。OpenGL ES関数を呼 び出すと、これは状態が呼び出しによって変化するコンテキストとなります。 スレッドの現在のコンテキストを設定するには、そのスレッドで実行するときにEAGLContextクラス のsetCurrentContext:メソッドを呼び出します。 [EAGLContext setCurrentContext: myContext];

スレッドの現在のコンテキストを取得するには、EAGLContextクラスのcurrentContextメソッドを

呼び出します。

(20)

注意: アプリケーションが同一スレッド上の2つ以上のコンテキストをアクティブに切り替 える場合、新しいコンテキストを現在のコンテキストに設定する前に、glFlush関数を呼び

出します。これにより、事前に送信されていたコマンドは、適切なタイミングでグラフィッ クスハードウェアに配信されます。

OpenGL ESは、現在のコンテキストに対応する、EAGLContextオブジェクトの強い参照を保持します

(独自に参照カウントを実装している場合でも、OpenGL ESはこのオブジェクトを保持)。

setCurrentContext:メソッドで現在のコンテキストを変更すると、OpenGL ESは前のコンテキスト

を参照できなくなります(独自に参照カウントを実装している場合、OpenGL ESはEAGLContextオブ

ジェクトを解放)。現在のコンテキストでなくなってもEAGLContextオブジェクトが割り当て解除さ

れないようにしたければ、当該オブジェクトに対する強い参照を保持しなければなりません。

どのコンテキストもOpenGL ESの特定のバージョンをターゲッ

トにする

EAGLContextオブジェクトでは、1つのバージョンのOpenGL ESのみがサポートされます。たとえば、

OpenGL ES 1.1用に記述されたコードは、OpenGL ES 2.0または3.0のコンテキストと互換性がありませ ん。OpenGL ES 2.0のコア機能を使用したコードは、OpenGL ES 3.0のコンテキストと互換性があり、 OpenGL ES 2.0拡張機能用に設計されたコードは、多くの場合、細かな変更を行うだけでOpenGL ES 3.0 のコンテキストで使用できます。OpenGL ES 3.0の多くの新機能や強化されたハードウェア機能では、 OpenGL ES 3.0のコンテキストが必要です。 アプリケーションは、EAGLContextオブジェクトを作成し、初期化するときに、どのバージョンの

OpenGL ESをサポートするかを決定します。要求されたバージョンのOpenGL ESをデバイスがサポート していない場合、initWithAPI:メソッドはnilを返します。アプリケーションは、コンテキストが正 常に初期化されたかを確認するためコンテキストを使用する前にテストする必要があります。 アプリケーションので複数バージョンのOpenGL ESをレンダリングオプションとしてサポートするに は、まず、対象とする最新バージョンのレンダリングコンテキストの初期化を試行する必要がありま す。返されたオブジェクトがnilの場合は、古いバージョンのコンテキストを初期化します。リスト 2-1で、この方法を紹介しています。 リスト 2-1 同じアプリケーションでの複数バージョンのOpenGL ESのサポート EAGLContext* CreateBestEAGLContext() {

EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];

(21)

if (context == nil) {

context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; }

return context; }

コンテキストのAPIプロパティは、コンテキストがサポートするOpenGL ESのバージョンを示します。

アプリケーションは、コンテキストのAPIプロパティをテストし、そのプロパティを使用して正しい

レンダリングパスを選びます。これを実装する一般的なパターンは、各レンダリングパスについてク ラスを作成するというものです。アプリケーションは、初期化時にコンテキストをテストし、一度レ ンダラを作成します。

EAGL sharegroupはコンテキストのOpenGL ESオブジェクトを管

コンテキストはOpenGL ESの状態を保持しますが、OpenGL ESオブジェクトを直接管理するわけではあ りません。OpenGL ESオブジェクトは、EAGLSharegroupオブジェクトによって作成され、維持され

ます。どのコンテキストにもオブジェクトの作成をデリゲートするEAGLSharegroupオブジェクトが 含まれます。 sharegroupの利点は、2つ以上のコンテキストが同じsharegroupを参照する場合に明らかになってきま す(図 2-1を参照)。複数のコンテキストが共通のsharegroupに接続されている場合、何らかのコン テキストで作成したOpenGL ESオブジェクトはすべてのコンテキスト上で利用できます。オブジェク トを作成したコンテキストではなく、別のコンテキスト上で同じオブジェクト識別子にバインドする と、同じ OpenGL ESオブジェクトを参照します。リソースは、モバイルデバイスでは希少な場合が少 なくありません。複数のコンテキストにおいて同じコンテンツのコピーを複数作成するのは非効率的 です。共通のリソースを共有することで、デバイス上のグラフィックスリソースの空きをより効果的 に利用できます。

(22)

sharegroupは不透明なオブジェクトです。呼び出すことができるメソッドやプロパティはありませ ん。sharegroupオブジェクトが使用されるコンテキストでは、それに対する強参照が保持されます。 図 2-1 2つのコンテキストによるOpenGL ESオブジェクトの共有 sharegroupは、次に示す2つの具体的シナリオで最も有用です。 ● コンテキスト間で共有されているリソースのほとんどが変更されない場合。 ● レンダラのメインスレッド以外のスレッド上に、アプリケーションが新たなOpenGL ESオブジェ クトを作成できるようにしたい場合。この場合、2つ目のコンテキストは独立したスレッド上で 実行され、データのフェッチとリソースの作成に充てられます。リソースがロードされた後、最 初のコンテキストはオブジェクトにバインドしてすぐに使用できます。GLKTextureLoaderクラ スは、このパターンを使用して、テクスチャの非同期読み込みを実行します。 同じsharegroupを参照する複数のコンテキストを作成するには、最初のコンテキストをinitWithAPI: を呼び出して初期化します。sharegroupはそのコンテキストに対して自動的に作成されます。2つ目 以降のコンテキストは、initWithAPI:sharegroup:メソッドを呼び出すことにより、最初のコンテ キストのsharegroupを使用するよう初期化されます。リスト 2-2では、この仕組みについて説明して います最初のコンテキストは、リスト 2-1 (20 ページ)で定義される、簡易関数を使用して作成さ れます。2つ目のコンテキストは、最初のコンテキストからAPIのバージョンとsharegroupを抽出して 作成されます。 Important: 同じsharegroupに関連付けられたすべてのコンテキストは、初期コンテキストと同じ バージョンのOpenGL ES APIを使用する必要があります。 リスト 2-2 共通のsharegroupを持つ2つのコンテキストの作成

EAGLContext* firstContext = CreateBestEAGLContext();

EAGLContext* secondContext = [[EAGLContext alloc] initWithAPI:[firstContext API] sharegroup: [firstContext sharegroup]];

(23)

sharegroupが複数のコンテキストによって共有されている場合、OpenGL ESオブジェクトに生じる状 態の変化の管理はアプリケーションの役割です。変化の管理に関する規則は次のとおりです。 ● オブジェクトの修正中ではない場合、複数のコンテキストにわたって同時にそのオブジェクトに アクセスすることが可能。 ● コンテキストに送信されたコマンドによってオブジェクトが修正されている間、オブジェクトを 読み取ったり、ほかのコンテキスト上でオブジェクトを修正したりしてはならない。 ● オブジェクトが修正された後、すべてのコンテキストがオブジェクトを再バインドして変更を認 識する必要がある。オブジェクトのコンテンツは、コンテキストがバインドする前にオブジェク トを参照している場合は未定義である。 OpenGL ESオブジェクトを更新するためにアプリケーションが従う手順は次のとおりです。 1. オブジェクトを使用する可能性のあるコンテキストごとにglFlushを呼び出す。 2. オブジェクトを修正するコンテキスト上で、1つ以上のOpenGL ES関数を呼び出してオブジェクト に変更を加える。 3. 状態変更コマンドを受信するコンテキスト上でglFlushを呼び出す。 4. そのほかの各コンテキスト上で、オブジェクト識別子を再バインドする。 注意: オブジェクトを共有するもう1つの方法は、単一のレンダリングコンテキストではな く、複数のレンダリング先フレームバッファを使用することです。レンダリング時におい て、アプリケーションは適切なフレームバッファをバインドし、必要に応じてフレームをレ ンダリングします。すべてのOpenGL ESオブジェクトは単一のコンテキストから参照される ため、OpenGL ESオブジェクトは同一のOpenGL ESデータを認識しています。この方法はリ ソースはあまり使用しませんが、コンテキストの状態を細かく制御可能な単一スレッドのア プリケーションでしか有用ではありません。

(24)

GLKitフレームワークは、OpenGL ESコンテンツの描画やアニメーションに必要な設定および保守コー ドが不要なViewおよびView Controllerクラスを提供します。GLKViewクラスは、描画コードの場所を提

供するOpenGL ESインフラストラクチャを管理し、GLKViewControllerクラスはGLKit ViewでのOpenGL ES

コンテンツの滑らかなアニメーションのレンダリングループを提供します。これらのクラスにより、 ビューコンテンツの描画とビュープレゼンテーションの管理のための標準的なUIKit設計パターンが拡 張されます。結果として、OpenGL ESレンダリングコードに集中的に取り組み、短期間でアプリケー ションを稼働させることができます。GLKitフレームワークは、OpenGL ES 2.0および3.0の開発を容易 にするその他の機能も備えています。

GLKit ViewはOpenGL ESコンテンツをオンデマンドで描画する

GLKViewクラスは、標準的なUIView描画サイクルのOpenGL ESベースの等価物を提供します。UIView

インスタンスは、drawRect:実装がQuartz 2D描画コマンドのみを実行する必要があるようにグラフィッ

クコンテキストを自動的に設定し、GLKViewインスタンスは、描画メソッドがOpenGL ES描画コマン

ドのみを実行する必要があるようにそれ自体を自動的に設定します。GLKViewクラスは、OpenGL ES

描画コマンドの結果を保持し、描画メソッドが返されると結果をCore Animationに自動的に表示する フレームバッファオブジェクトを管理することによって、この機能を提供します。

標準的なUIKit Viewと同様に、GLKit Viewはそのコンテンツをオンデマンドでレンダリングします。 ビューは最初に表示されたときに描画メソッドを呼び出します。Core Animationはレンダリング出力 をキャッシュし、ビューが表示されるたびにそれを表示します。ビューのコンテンツを変更するとき は、そのsetNeedsDisplayメソッドを呼び出すと、ビューは再び描画メソッドを呼び出し、結果の画

像をキャッシュし、それを画面に表示します。この方法は、画像のレンダリングに使用するデータが

OpenGL ESおよびGLKitによる描画

(25)

あまり頻繁に変化しない場合や、ユーザのアクションに応答してのみ変化する場合に有用です。必要 なときだけ新しいビューコンテンツをレンダリングすることによって、デバイスのバッテリーが節約 され、デバイスがほかのアクションを実行する時間が長くなります。

図 3-1 GLKit ViewでのOpenGL ESコンテンツのレンダリング

GLKit Viewの作成と設定

GLKViewオブジェクトは、プログラムまたはInterface Builderを使用して作成および設定できます。描

画に使用する前に、EAGLContextオブジェクトと関連付ける必要があります(“OpenGL ESコンテキス トの設定” (19 ページ)を参照)。

● ビューをプログラムで作成するときは、最初にコンテキストを作成し、それをビューの

initWithFrame:context:メソッドに渡します。

● ストーリーボードからビューを読み込んだ後、コンテキストを作成し、ビューのcontextプロパ

ティ値として設定します。

GLKit Viewは、その独自のOpenGL ESフレームバッファオブジェクトとレンダバッファを自動的に作成 および設定します。リスト 3-1に示すように、ビューの描画可能プロパティを使用してこれらのオブ ジェクトの属性を制御します。GLKit Viewのサイズ、倍率、描画可能プロパティを変更すると、次回 のコンテンツ描画時に適切なフレームバッファオブジェクトとレンダバッファが自動的に削除および 再作成されます。

(26)

リスト 3-1 GLKit Viewの設定 - (void)viewDidLoad {

[super viewDidLoad];

// Create an OpenGL ES context and assign it to the view loaded from storyboard GLKView *view = (GLKView *)self.view;

view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

// Configure renderbuffers created by the view

view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat = GLKViewDrawableDepthFormat24; view.drawableStencilFormat = GLKViewDrawableStencilFormat8; // Enable multisampling view.drawableMultisample = GLKViewDrawableMultisample4X; } GLKViewインスタンスのマルチサンプル機能をそのdrawableMultisampleプロパティを使用して有効 にできます。マルチサンプル機能は、ギザギザのエッジを滑らかするアンチエイリアスの一種で、よ り多くのメモリとフラグメント処理時間を使用して3Dアプリケーションでの画質を向上させます。マ ルチサンプル機能を有効にする場合は、パフォーマンスが許容できる水準を維持できるよう、アプリ ケーションのパフォーマンスを必ずテストしてください。

GLKit Viewの描画

図 3-1 (25 ページ)では、OpenGL ESコンテンツを描画するための3つのステップ(OpenGL ESインフ ラストラクチャの準備、描画コマンドの発行、Core Animationへのレンダリングコンテンツの表示) の概要を説明します。GLKViewクラスは、最初のステップと3番目のステップを実装します。2番目の ステップについては、リスト 3-2の中の例のような描画メソッドを実装します。 リスト 3-2 GLKit Viewの描画メソッドの例 - (void)drawRect:(CGRect)rect {

// Clear the framebuffer

(27)

glClearColor(0.0f, 0.0f, 0.1f, 1.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Draw using previously configured texture, shader, uniforms, and vertex array glBindTexture(GL_TEXTURE_2D, _planetTexture); glUseProgram(_diffuseShading); glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, _modelViewProjectionMatrix.m); glBindVertexArrayOES(_planetMesh); glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT); } 注意: glClear関数は、既存のフレームバッファコンテンツを破棄できるというヒントを OpenGL ESに伝達し、それまでのコンテンツをメモリに読み込むという負担のかかるメモリ 操作を回避します。最適なパフォーマンスを確保するために、描画の前には必ずこの関数を 呼び出す必要があります。

GLKViewクラスは、OpenGL ESのレンダリングプロセスの標準的な部分を管理するため、OpenGL ESの

描画のための簡単なインターフェイスを提供します。 ● 描画メソッドを呼び出す前に、ビューは次のことを行います。 ● EAGLContextオブジェクトを現在のコンテキストにする ● フレームバッファオブジェクトとレンダバッファオブジェクトを、その現在のサイズ、倍率、 および描画可能プロパティ(必要に応じて)に基づいて作成する ● フレームバッファオブジェクトを描画コマンドの現在の発行先としてバインドする ● フレームバッファサイズに一致するようにOpenGL ESビューポートを設定する ● 描画メソッドが返された後、ビューは次のことを行います。 ● マルチサンプル機能のバッファを解決する(マルチサンプル機能が有効になっている場合) ● コンテンツが不要になったレンダバッファを破棄する ● レンダリングバッファのコンテンツをキャッシュと表示のためにCore Animationに表示する

(28)

デリゲートオブジェクトを使用したレンダリング

多くのOpenGL ESアプリケーションでは、カスタムクラスにレンダリングコードが実装されています。 この方法の利点は、それぞれに対して異なるレンダリングクラス複数のレンダリングアルゴリズムを 簡単にサポートできる点です。一般的な機能を共有するレンダリングアルゴリズムは、スーパークラ スからその機能を継承できます。たとえば、OpenGL ES 2.0と3.0の両方をサポートするために、異な るレンダラクラスを使用することができます(“OpenGL ESコンテキストの設定” (19 ページ)を参 照)。または、それらを使用して、より高性能のハードウェアのデバイス上で画質を向上させるため にレンダリングをカスタマイズすることができます。 GLKitはこの方法に大変適しています。レンダラオブジェクトを標準的なGLKViewインスタンスのデリ ゲートにすることができます。GLKViewのサブクラスを定義し、drawRect:メソッドを実装する代わ りに、レンダラクラスはGLKViewDelegateプロトコルを使用し、glkView:drawInRect:メソッドを 実装します。リスト 3-3は、アプリケーションの起動時にハードウェアに機能に基づいてレンダラク ラスを選択する方法を示します。 リスト 3-3 ハードウェアの機能に基づいたレンダラクラスの選択 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Create a context so we can test for features EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

[EAGLContext setCurrentContext:context];

// Choose a rendering class based on device features GLint maxTextureSize;

glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); if (maxTextureSize > 2048)

self.renderer = [[MyBigTextureRenderer alloc] initWithContext:context]; else

self.renderer = [[MyRenderer alloc] initWithContext:context];

// Make the renderer the delegate for the view loaded from the main storyboard GLKView *view = (GLKView *)self.window.rootViewController.view;

view.delegate = self.renderer; デリゲートオブジェクトを使用したレンダリング

(29)

// Give the OpenGL ES context to the view so it can draw view.context = context;

return YES; }

GLKit View ControllerがOpenGL ESコンテンツをアニメーション

化する

GLKViewオブジェクトは、デフォルトでは、オンデマンドでそのコンテンツをレンダリングします。

とはいえ、OpenGL ESでの描画の重要な利点は、複雑なシーンの連続的なアニメーション、すなわち 静止画像を表示することがほとんどないゲームやシミュレーションなどのアプリケーションに、グラ フィックス処理ハードウェアを使用できることです。このような場合に、GLKitフレームワークは、管 理するGLKViewオブジェクトのアニメーションループを管理するView Controllerクラスを提供します。

このループは、更新と表示の2つのフェーズで、ゲームやシミュレーションで一般的な設計パターン に従います。図 3-2に、アニメーションループの簡単な例を示します。

図 3-2 アニメーションループ

アニメーションループについて

更新フェーズでは、View Controllerがその独自のupdateメソッド(またはそのデリゲートの

glkViewControllerUpdate:メソッド)を呼び出します。このメソッドでは、次のフレームを描画す

る準備をする必要があります。たとえば、ゲームでは、このメソッドを使用して、最後のフレーム以 降に受信された入力イベントに基づいて、ユーザや敵のキャラクターの位置を決定することができま す。サイエンティフィックビジュアライゼーションでは、このメソッドを使用してそのシミュレー

(30)

ションのステップを実行することができます。次のフレームのアプリケーションの状態を判断するた めにタイミング情報が必要な場合は、timeSinceLastUpdateプロパティなど、View Controllerのいず

れかのタイミングプロパティを使用します。図 3-2では、更新フェーズでangle変数が増え、それを

使用して変換行列が計算されています。

表示フェーズでは、View Controllerがそのビューのdisplayメソッドを呼び出し、今度はそれが描画メ

ソッドを呼び出します。描画メソッドでは、OpenGL ES描画コマンドをGPUに送信して、コンテンツ をレンダリングします。最適なパフォーマンスのために、アプリケーションは、新しいフレームのレ ンダリング開始時にOpenGL ESオブジェクトを修正し、その後、描画コマンドを送信する必要があり ます。図 3-2では、表示フェーズでシェーダプログラムのuniform変数が更新フェーズで計算された行 列に設定され、描画コマンドを送信して新しいコンテンツがレンダリングされています。

アニメーションループでは、これらの2つのフェーズがView ControllerのframesPerSecondプロパティ

によって指定された速度で繰り返されます。preferredFramesPerSecondプロパティを使用して、希 望のフレームレートを設定できます。View Controllerでは、現在の表示ハードウェアのパフォーマン スを最適化するために、希望の値に近い、最適なフレームレートが自動的に選択されます。 Important: 最良の結果を得るためには、アプリケーションが一貫して達成可能なフレームレート を選びます。スムーズで一貫したフレームレートは、一貫性のないフレームレートの場合よりも より快適なユーザ体験を提供します。

GLKit View Controllerの使用

リスト 3-4では、GLKViewControllerサブクラスとGLKViewインスタンスを使用して、アニメーショ

ン化されたOpenGL ESコンテンツをレンダリングするための一般的な方法を示します。

リスト 3-4 GLKit ViewおよびView Controllerを使用した、OpenGL ESコンテンツの描画とアニメーション化

@implementation PlanetViewController // subclass of GLKViewController

- (void)viewDidLoad {

[super viewDidLoad];

// Create an OpenGL ES context and assign it to the view loaded from storyboard GLKView *view = (GLKView *)self.view;

view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; GLKit View ControllerがOpenGL ESコンテンツをアニメーション化する

(31)

// Set animation frame rate

self.preferredFramesPerSecond = 60;

// Not shown: load shaders, textures and vertex arrays, set up projection matrix [self setupGL];

}

- (void)update {

_rotation += self.timeSinceLastUpdate * M_PI_2; // one quarter rotation per second

// Set up transform matrices for the rotating planet

GLKMatrix4 modelViewMatrix = GLKMatrix4MakeRotation(_rotation, 0.0f, 1.0f, 0.0f); _normalMatrix = GLKMatrix3InvertAndTranspose(GLKMatrix4GetMatrix3(modelViewMatrix), NULL); _modelViewProjectionMatrix = GLKMatrix4Multiply(_projectionMatrix, modelViewMatrix); }

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

// Clear the framebuffer

glClearColor(0.0f, 0.0f, 0.1f, 1.0f);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Set shader uniforms to values calculated in -update glUseProgram(_diffuseShading);

glUniformMatrix4fv(_uniformModelViewProjectionMatrix, 1, 0, _modelViewProjectionMatrix.m);

glUniformMatrix3fv(_uniformNormalMatrix, 1, 0, _normalMatrix.m);

// Draw using previously configured texture and vertex array glBindTexture(GL_TEXTURE_2D, _planetTexture);

glBindVertexArrayOES(_planetMesh);

glDrawElements(GL_TRIANGLE_STRIP, 256, GL_UNSIGNED_SHORT, 0); GLKit View ControllerがOpenGL ESコンテンツをアニメーション化する

(32)

}

@end

この例では、PlanetViewControllerクラス(カスタムGLKViewControllerサブクラス)のインスタ

ンスが、標準的なGLKViewインスタンスとその描画可能プロパティとともに、ストーリーボードから

読み込まれます。viewDidLoadメソッドでは、OpenGL ESコンテキストが作成され、それがビューに

指定され、アニメーションループのフレームレートも設定されます。 View Controllerは自動的にそのビューのデリゲートとなるため、アニメーションループの更新フェー ズと表示フェーズの両方を実装します。updateメソッドでは、回転惑星の表示に必要な変換行列を 計算します。glkView:drawInRect:メソッドでは、シェーダプログラムにそれらの行列を指定し、 描画コマンドを送信して惑星ジオメトリをレンダリングします。

GLKitを使用したレンダラの開発

GLKitフレームワークは、ViewおよびView Controllerインフラストラクチャに加えて、iOSでのOpenGL ES開発を容易にするための他のいくつかの機能を提供します。

ベクトルと行列の数値演算の処理

OpenGL ES 2.0以降では、変換行列を作成または指定するための組み込み関数が用意されていません。 代わりに、プログラム可能なシェーダには頂点変換が用意されており、一般的なuniform変数を使用 してシェーダへの入力を指定します。GLKitフレームワークには、iOSハードウェアの高いパフォーマ ンスのために最適化された、ベクトルおよび行列タイプと関数の包括的なライブラリが含まれていま す。(GLKit Framework Reference を参照。)

OpenGL ES 1.1の固定機能パイプラインからの移行

OpenGL ES 2.0以降では、OpenGL ES 1.1の固定機能グラフィックスパイプラインに関連する機能がすべ て削除されています。GLKBaseEffectクラスは、OpenGL ES 1.1パイプラインの変換、ライティング、 シェーディング段階にObjective-Cアナログを提供し、GLKSkyboxEffectおよび GLKReflectionMapEffectクラスは一般的な視覚効果のサポートを追加します。詳細については、こ れらのクラスのリファレンスマニュアルを参照してください。 GLKitを使用したレンダラの開発

(33)

テクスチャデータの読み込み

GLKTextureLoaderクラスには、iOSでサポートされている任意の画像形式からOpenGL ESコンテキス

トにテクスチャデータを同期的または非同期的に簡単に読み込む方法が用意されています。(“GLKit フレームワークを使用したテクスチャデータの読み込み” (97 ページ)を参照してください。)

(34)

フレームバッファオブジェクトは、レンダリングコマンドの送信先です。フレームバッファオブジェ クトを作成すると、色、深度、および、ステンシルデータを正確に制御できます。このストレージを 提供するには、画像をフレームバッファにアタッチします(図 4-1を参照)。最も一般的な画像アタッ チメントはレンダバッファオブジェクトです。OpenGL ESテクスチャをフレームバッファの色アタッ チメントポイントにアタッチすることもできます。これは、描画コマンドがテクスチャにレンダリン グされることを意味します。画像がレンダリングされたテクスチャは、その後使用されるレンダリン グコマンドの入力の役割を果たすことができます。単一のレンダリングコンテキストに複数のフレー ムバッファオブジェクトを作成することもできます。これによって、同じレンダリングパイプライン とOpenGL ESリソースを複数のフレームバッファ間で共有することができます。 図 4-1 色と深度のレンダバッファを持つフレームバッファ これらのすべての方法において、OpenGL ESコンテキストのレンダリング結果を格納するフレームバッ ファオブジェクトとレンダバッファオブジェクトを手動で作成する必要があるほか、コンテンツを画 面に表示し、(必要に応じて)アニメーションループを実行するための追加コードを記述する必要が あります。

フレームバッファオブジェクトの生成

アプリケーションは、実行しようとするタスクに応じて異なるオブジェクトを設定し、フレームバッ ファオブジェクトにアタッチします。ほとんどの場合、フレームバッファの設定における違いは、フ レームバッファオブジェクトの色アタッチメントポイントにどのオブジェクトがアタッチされるかと いうことです。

その他のレンダリング先への描画

(35)

● オフスクリーンの画像処理にフレームバッファを使用するには、レンダバッファをアタッチしま す。詳細については、“オフスクリーンフレームバッファオブジェクトの作成” (35 ページ)を 参照してください。 ● フレームバッファの画像を後のレンダリング手順の入力として使用するには、テクスチャをア タッチします。詳細については、“フレームバッファオブジェクトを使用したテクスチャへのレン ダリング” (36 ページ)を参照してください。

Core Animationレイヤ合成でフレームバッファを使用するには、特別なCore Animation対応レンダ

バッファを使用してください。詳細については、“Core Animationレイヤへのレンダリング” (37 ペー ジ)を参照してください。

オフスクリーンフレームバッファオブジェクトの作成

オフスクリーンレンダリングのためのフレームバッファは、そのアタッチメントのすべてをOpenGL ES レンダバッファとして割り当てます。次のコードは、色アタッチメントおよび深度アタッチメントを 持つフレームバッファオブジェクトを割り当てます。 1. フレームバッファを作成し、それをバインドします。 GLuint framebuffer; glGenFramebuffers(1, &framebuffer); glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); 2. 色レンダバッファを作成し、それにストレージを割り当て、フレームバッファの色アタッチメン トポイントにストレージをアタッチします。 GLuint colorRenderbuffer; glGenRenderbuffers(1, &colorRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);

glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer); 3. 深度または深度/ステンシルのレンダバッファを作成し、それにストレージを割り当て、フレー ムバッファの深度アタッチメントポイントにストレージをアタッチします。 GLuint depthRenderbuffer; glGenRenderbuffers(1, &depthRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer); フレームバッファオブジェクトの生成

図 3-1 GLKit ViewでのOpenGL ESコンテンツのレンダリング 25 図 3-2 アニメーションループ 29
図 7-1 デバッグマーカグループの追加前と追加後のXcode Frame Debugger 70 図 7-2 透明なオブジェクトをトリミングしてフラグメント処理を減らす様子 75 リスト 7-1 デバッグマーカを使って描画コマンドに注釈をつけるコード例 71 リスト 7-2 デバッグラベルを利用してOpenGL ESオブジェクトに注釈をつけるコード例 71 リスト 7-3 インスタンス描画法によらずに、よく似たオブジェクトを多数描画するコード例 77 リスト 7-4 OpenGL ES 3.0の頂点シェー
図 3-1 GLKit ViewでのOpenGL ESコンテンツのレンダリング
図 3-1  (25 ページ)では、OpenGL ESコンテンツを描画するための3つのステップ(OpenGL ESインフ ラストラクチャの準備、描画コマンドの発行、Core Animationへのレンダリングコンテンツの表示) の概要を説明します。 GLKView クラスは、最初のステップと3番目のステップを実装します。2番目の ステップについては、リスト 3-2の中の例のような描画メソッドを実装します。 リスト 3-2 GLKit Viewの描画メソッドの例 - (void)drawRect:(CGRec
+7

参照

関連したドキュメント

水道水又は飲用に適する水の使用、飲用に適する水を使

テューリングは、数学者が紙と鉛筆を用いて計算を行う過程を極限まで抽象化することに よりテューリング機械の定義に到達した。

※ 硬化時 間につ いては 使用材 料によ って異 なるの で使用 材料の 特性を 十分熟 知する こと

洋上液化施設及び LNGRV 等の現状と展望を整理するとともに、浮体式 LNG 受入基地 を使用する場合について、LNGRV 等及び輸送用

注)○のあるものを使用すること。

地域の感染状況等に応じて、知事の判断により、 「入場をする者の 整理等」 「入場をする者に対するマスクの着用の周知」

わかりやすい解説により、今言われているデジタル化の変革と

A Historical Study of Playing Basketball on the Itabari Court“A Japanese Wooden Court for Playing Outdoors” (the Taisho Era to the Early Showa Era).. 及 川 佑 介 Yusuke