08.描画の高速化(頂点バッファオブジェクトの利用)
07.で作成したモデルビューアの描画処理は、頂点配列を用いた描画処理でした。
頂点配列を用いた描画処理では、glDrawArrays や glDrawElements の呼び出しのたびに、頂点データが、クライアントメモリからグラフィックスメモリへコピーされます。
頂点バッファオブジェクト ( Vertex Buffer Object : VBO ) を用いた描画処理では、頂点データを、事前にクライアントメモリからグラフィックスメモリにコピーしておき、glDrawArrays
や glDrawElements の呼び出しのときには、コピー済みの頂点データを用いて描画します。
頂点バッファオブジェクト ( Vertex Buffer Object : VBO ) を用いた描画処理は、頂点配列を用いた描画処理よりも高速に描画されます。
解説
頂点バッファオブジェクト ( Vertex Buffer Object : VBO ) を用いた描画を行うためには、構築処理と、描画処理と、破棄処理を作成する必要があります。
構築処理では、頂点バッファオブジェクトの作成、頂点データのクライアントメモリからグラフィックスメモリへのコピー、を行います。
- glGenBuffer関数で、頂点バッファオブジェクトを作成します。
- glBindBuffer関数で、作成した頂点バッファオブジェクトをバインドします。
- glBufferData関数で、データをクライアントメモリからグラフィックスメモリにコピーします。
描画処理では、頂点バッファオブジェクトをバインドし、バインドした頂点バッファオブジェクトを用いて描画を行います。
- glBindBuffer関数で、作成した頂点バッファをバインドします。
- これまで、配列データのアドレスを渡して使用していた、glVertexPointer関数、glNormalPointer関数、glDrawElements関数は、頂点バッファオブジェクトを使用するときには、GL11の関数を使用し、配列データのアドレスを渡す代わりに、データのオフセット量を渡します。
破棄処理では、頂点バッファオブジェクトの削除を行います。
- glDeleteBuffer関数で、作成した頂点バッファを削除します。
実装
プロジェクトを開く
07.で作成したモデルビューアプロジェクトを開きます。
モデルデータ構造クラスの変更
モデルデータ構造クラスに、頂点バッファオブジェクトの構築処理と、破棄処理を追加します。
float型、short型のバイトサイズに関するメンバ定数を追加します。
頂点バッファオブジェクトを識別する頂点バッファオブジェクトID配列変数をメンバー変数として追加します。
頂点バッファオブジェクトのIDのゲッター関数を追加します。
VBO構築処理関数を追加し、頂点バッファオブジェクトの作成、作成した頂点バッファオブジェクトをバインド、データをクライアントメモリからグラフィックスメモリにコピー、の処理を記述します。
VBO破棄処理関数を追加し、頂点バッファを削除する処理を記述します。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
VBOの構築処理、破棄処理付きのモデルセット関数の追加
モデルが置き換わった際には、古いモデルに関して、VBOの破棄処理を実施し、新しいモデルに関して、VBOの構築処理を実施するモデルセット関数を、モデルビューアレンダラクラスに、オーバーライド関数として追加します。
また、VBOの構築関数、破棄関数を追加し、モデルに関するVBO処理およびピック処理用の要素番号色に関するVBO処理を追加します。
また、BYTE型のバイトサイズに関するメンバ定数を追加します。
また、ピック処理用の要素番号色バッファオブジェクトを識別するバッファオブジェクトID配列変数をメンバー変数として追加します。
モデルセット関数の呼び出し側は、UIスレッドで動作しています。
モデルセット関数の呼び出され側には、レンダリングスレッドで動作しているOpenGLに関する処理(OpenGLのgl~関数を使用する処理)の呼び出しがあります。
OpenGLに関する処理(OpenGLのgl~関数を使用する処理)をUIスレッドから呼び出すので、モデルセット関数の呼び出しをイベントキューイングします。
モデルビューアビューの loadModelFile関数のモデルセット関数の呼び出しをイベントキューイングします。
無名関数で使用するmodel変数を、final変数にします。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
描画処理をVBOを利用した処理に変更
描画処理をVBOを利用した処理に変更します。
モデルビューアレンダラクラスに、short型のバイトサイズに関するメンバ定数を追加します。
モデルビューアレンダラクラスのrenderModel関数を以下のようにします。
「Cannot resolve symbol」エラーは、「Alt + Enter」で、必要なクラスをimportします。
OpengGL描画コンテキストの消失と再作成に対応する
OpenGL描画コンテキストの消失と再作成に対応します。
アクティビティの一時停止と復帰が行われたときに、OpenGL描画コンテキストの消失と再作成が行われます。
OpenGL描画コンテキストが消失すると、グラフィックスメモリ上の頂点バッファオブジェクトのデータは消失します。OpenGL描画コンテキストの再作成が行われても、グラフィックスメモリ上の頂点バッファオブジェクトの再作成は、自動では行われません。
グラフィックスメモリ上に頂点バッファオブジェクトはないにもかかわらず、グラフィックスメモリ上に頂点バッファオブジェクトがあるものとして描画処理等を行うと、プログラムがクラッシュすることもあります。
OpenGL描画コンテキストが消失されようとするときには、VBOの破棄処理を実施するようにします。
モデルビューアレンダラクラスの、preSurfaceDestroy関数に、VBO破棄関数の呼び出しを追加します。
OpenGL描画コンテキストが再作成されたときには、VBOの構築処理を実施するようにします。
モデルビューアレンダラクラスの、onSurfaceCreated関数に、VBO構築関数の呼び出しを追加します。
リビルドし、エラー、警告がないことを確認します。
実行
Android端末にて、動作確認。
実行し、07.で作成したモデルビューアと、描画速度を比較します。
- fps
- frame per second : 1秒間に描画できる回数を表します。数値が大きいほど、描画速度は速いことになります。
- spf
- second per frame : 1回の描画に要する時間を表します。数値が小さいほど、描画速度は速いことになります。
CUBECUBE.stlファイルの読み込み
08.で作成したモデルビューアの描画速度:500[fps]前後(数値はAndroidデバイスの性能に依存します)
07.で作成したモデルビューアの描画速度:333[fps]前後(数値はAndroidデバイスの性能に依存します)
ダウンロード
サンプルプロジェクト
(github.com上のダウンロードページ)
サンプルモデル(CUBECUBE.stl)
関連ページ
前項目:07.描画速度の計測
次項目:09.光源の効果の利用