Androidアプリ開発 OpenGL レンダーモードでonDrawFrameの呼び出しを制御

本日は、OpenGLの話題である。Androidでは、GLSurfaceViewを作って、RendererのonDrawFrameで描画処理を行う。onDrawFrameはGLSurfaceViewのスレッド上で実行される。
これまでのサンプルのように、何も考えずに、GLSurfaceViewを使うと、レンダラーのonDrawFrameは絶え間なく呼び出される
試しに、onDrawFrameでログを出力するようにしてみるとわかるが、えらい勢いでログが流れていくことがわかる。
onDrawFrameを任意のタイミングで実行させたい場合、GLSurfaceViewで以下のような設定をすればよい。レンダラーのセットの後で行う。

public SampleGLSurfaceView(Context context) {
super(context);
this.context = context;
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
renderer = new OpenGLRenderer();
setRenderer(renderer);
setRenderMode(RENDERMODE_WHEN_DIRTY);
}

setRenderModeRENDERMODE_WHEN_DIRTYを指定する。
RENDEREMODE_WHEN_DIRTYは、GLSurfaceViewで定義されているstatic finalフィールド。
その他のレンダーモードは、RENDERMODE_CONTINUOUSLYがあり、こちらがデフォルト。
で、RENDERMODE_WHEN_DIRTYにすると、最初に一回だけonDrawFrameが呼び出され描画されるが、以降は呼び出されなくなる。
描画させたいタイミングで、GLSurfaceViewのrequestRenderを呼び出す必要がある。
requestRenderは、UIスレッドから呼び出してかまわない。queueEventを使う必要はない。onDrawFrameはGLSurfaceViewのスレッドで実行されるので注意。
関連記事
Androidアプリ開発 OpenGL queueEventを使う
サンプルアプリでは、onScrollでrequestRenderを呼び出してみた。

public boolean onScroll(MotionEvent event1, MotionEvent event2, float distx, float disty) {
eyepos[0] += distx * 0.01;
eyepos[1] += disty * 0.01;
requestRender();
return true;
}

スライドさせると、onScrollが呼び出され、requestRenderされるので、onDrawFrameで描画され動くようになる。
スライドさせなければ、イベントが発生せず、onDrawFrameも呼び出されない。
onDrawFrameでドロイド君を回転をさせている。レンダーモードを変更したことにより、スライドをして再描画をかけている間でないとドロイド君が回転しなくなってしまった。まぁ、これは、別のスレッドを作るなりすれば解決しそう。
物理エンジンと組み合わせるときは、こっちのレンダーモードの方がよさそう。シミュレーションのループで、位置の計算、レンダリングのリクエストを行えばよい。
連続してフル回転で描画すればそれなりに電力も消費する。RENDERMODE_WHEN_DIRTYにして、適度にフレームレートを抑えた方が省電力であろう。
実は、AREarthroid ver 1.2.6は、連続してonDrawFrameが呼び出されフル回転状態となっている。
スマホでは、バッテリーがすぐになくなる。省電力化はけっこう大事。早速、RENDERMODE_WHEN_DIRTYに変更した。ver 1.2.7で対応している。

かんたんAndroidアプリ作成入門 (プログラミングの教科書)

かんたんAndroidアプリ作成入門 (プログラミングの教科書)

  • 作者: 朝井 淳
  • 出版社/メーカー: 技術評論社
  • 発売日: 2013/04/16
  • メディア: 単行本(ソフトカバー)

投稿者プロフィール

asai
asai
システムエンジニア
喋れる言語:日本語、C言語、SQL、JavaScript