AndroidでOpenGL ES2を使ってたくさん描画する場合の注意点

かな〜り前にAndroidのOpenGL ES2を使ってテクスチャを表示する方法を書いた。今回は弾幕シューティングのように大量のオブジェクトを描画しないといけない場合の注意点を書いておこう。


描画命令は1回のみにする
描画命令(前回書いたサンプルではGLES20.glDrawArrays()を使ってる)はとても重い処理になるため、極力減らすべきである。できれば、1回で全部描画するくらいにしたい。
1回で描画するにはどうするか?予め座標データをたくさん送っておけばよいだけだ。


テクスチャは1つだけ用意し、作り直しはキリの良いタイミングで。
テクスチャ作成や、テクスチャ切り替えも重い処理に入る。そのため、できれば、1枚の大きめなテクスチャを用意し、そこから切り出して使うようにしたい。


データの転送は1回で
OpenGL ES2では、描画させるオブジェクトの頂点データをGPU側へ送る必要があるが、これを小分けにして送るとオーバーヘッドが増える。なので、1回で全部送るようにしたい。


データの転送量を極力減らす
これは当たり前の話。そのためには、floatの代わりにshortやbyteデータを送るようにするとか、工夫する。


ByteBufferには一括でデータを入れる
これはAndroid特有の話になるのだが、AndroidではGPU側にデータを渡すためにByteBuffer系のクラスを使用する必要がある。例えば、オブジェクトの頂点配列をshort で管理しているとする。GPU側へ渡すには short → ShortBuffer → 転送 の手順が必要になる。このとき、ShortBufferへshort[]のデータを突っ込むのだが、1オブジェクトずつShortBufferへ格納していると結構時間が掛かる。なるべく多くのデータを一括で格納したほうが、速くなる。


こんなところかな。あとは、最近の端末は複数コアなので、弾道計算をマルチスレッド化すると、相当数のオブジェクトが処理できる。ちなみに Nexus7でやってみたところ、6000個ぐらい処理させても60FPS出るというおっかない結果が出た。最近のタブレットすげ〜
具体的なコードは次回にする。