Android アプリで OpenGL ES を使用してグラフィックを描画するには、それらのグラフィック用のビューコンテナを作成する必要があります。最も簡単な方法の一つは、GLSurfaceView
と GLSurfaceView.Renderer
の両方を実装することです。GLSurfaceView
は OpenGL で描画されるグラフィックのビューコンテナであり、GLSurfaceView.Renderer
はそのビュー内に描画されるものを制御します。これらのクラスについて詳しくは、OpenGL ES デベロッパー ガイドをご覧ください。
GLSurfaceView
は、OpenGL ES グラフィックをアプリケーションに組み込む方法の一つにすぎません。全画面表示または全画面に近いグラフィック ビューの場合、これは妥当な選択です。OpenGL ES グラフィックをレイアウトの一部に組み込むことを希望するデベロッパーは、TextureView
をご覧ください。実際に自作する場合、SurfaceView
を使用して OpenGL ES ビューを作成することもできますが、かなりの量の追加コードを記述する必要があります。
このレッスンでは、単純なアプリ アクティビティに GLSurfaceView
と GLSurfaceView.Renderer
を最小限に実装する方法について説明します。
マニフェストで OpenGL ES の使用を宣言する
アプリで OpenGL ES 2.0 API を使用するには、次の宣言をマニフェストに追加する必要があります。
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
アプリでテクスチャ圧縮を使用する場合は、アプリがサポートする圧縮形式も宣言して、互換性のあるデバイスにのみインストールされるようにする必要があります。
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" /> <supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />
テクスチャ圧縮形式について詳しくは、OpenGL デベロッパー ガイドをご覧ください。
OpenGL ES グラフィックスのアクティビティを作成する
OpenGL ES を使用する Android アプリには、ユーザー インターフェースを備えた他のアプリと同様のアクティビティがあります。他のアプリとの主な違いは、アクティビティのレイアウトに配置するものです。多くのアプリでは TextView
、Button
、ListView
を使用できますが、OpenGL ES を使用するアプリでは GLSurfaceView
を追加することもできます。
次のコード例は、GLSurfaceView
をプライマリ ビューとして使用するアクティビティの最小限の実装を示しています。
Kotlin
class OpenGLES20Activity : Activity() { private lateinit var gLView: GLSurfaceView public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Create a GLSurfaceView instance and set it // as the ContentView for this Activity. gLView = MyGLSurfaceView(this) setContentView(gLView) } }
Java
public class OpenGLES20Activity extends Activity { private GLSurfaceView gLView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Create a GLSurfaceView instance and set it // as the ContentView for this Activity. gLView = new MyGLSurfaceView(this); setContentView(gLView); } }
注: OpenGL ES 2.0 には Android 2.2(API レベル 8)以降が必要であるため、Android プロジェクトでこの API 以降をターゲットにしていることを確認してください。
GLSurfaceView オブジェクトを構築する
GLSurfaceView
は、OpenGL ES グラフィックを描画できる特別なビューです。単独では十分に機能しません。オブジェクトの実際の描画は、このビューに設定した GLSurfaceView.Renderer
で制御されます。実際、このオブジェクトのコードは非常に薄いため、拡張をスキップして、変更されていない GLSurfaceView
インスタンスを作成したくなるかもしれませんが、それはしないでください。タッチイベントをキャプチャするには、このクラスを拡張する必要があります。詳細については、タッチイベントに応答するのレッスンをご覧ください。
GLSurfaceView
の基本的なコードは最小限であるため、迅速な実装では、それを使用するアクティビティ内に内部クラスを作成するのが一般的です。
Kotlin
import android.content.Context import android.opengl.GLSurfaceView class MyGLSurfaceView(context: Context) : GLSurfaceView(context) { private val renderer: MyGLRenderer init { // Create an OpenGL ES 2.0 context setEGLContextClientVersion(2) renderer = MyGLRenderer() // Set the Renderer for drawing on the GLSurfaceView setRenderer(renderer) } }
Java
import android.content.Context; import android.opengl.GLSurfaceView; class MyGLSurfaceView extends GLSurfaceView { private final MyGLRenderer renderer; public MyGLSurfaceView(Context context){ super(context); // Create an OpenGL ES 2.0 context setEGLContextClientVersion(2); renderer = new MyGLRenderer(); // Set the Renderer for drawing on the GLSurfaceView setRenderer(renderer); } }
GLSurfaceView
の実装への追加オプションとして、GLSurfaceView.RENDERMODE_WHEN_DIRTY
設定を使用して、描画データが変更された場合にのみビューを描画するようにレンダリング モードを設定するというものがあります。
Kotlin
// Render the view only when there is a change in the drawing data renderMode = GLSurfaceView.RENDERMODE_WHEN_DIRTY
Java
// Render the view only when there is a change in the drawing data setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
この設定により、requestRender()
を呼び出すまで GLSurfaceView
フレームは再描画されなくなります。これにより、このサンプルアプリでは効率が向上します。
レンダラクラスを作成する
OpenGL ES を使用するアプリ内での GLSurfaceView.Renderer
クラス(レンダラ)の実装から、事態がより顕著になります。このクラスは、関連付けられている GLSurfaceView
に描画されるものを制御します。レンダラには、GLSurfaceView
に何をどのように描画するかを把握するために Android システムによって呼び出される 3 つのメソッドがあります。
onSurfaceCreated()
- ビューの OpenGL ES 環境を設定するために 1 回呼び出されます。onDrawFrame()
- ビューの再描画ごとに呼び出されます。onSurfaceChanged()
- デバイスの画面の向きが変更されたときなど、ビューのジオメトリが変更された場合に呼び出されます。
次に OpenGL ES レンダラのごく基本的な実装を示します。これは GLSurfaceView
に黒い背景を描画するだけです。
Kotlin
import javax.microedition.khronos.egl.EGLConfig import javax.microedition.khronos.opengles.GL10 import android.opengl.GLES20 import android.opengl.GLSurfaceView class MyGLRenderer : GLSurfaceView.Renderer { override fun onSurfaceCreated(unused: GL10, config: EGLConfig) { // Set the background frame color GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f) } override fun onDrawFrame(unused: GL10) { // Redraw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT) } override fun onSurfaceChanged(unused: GL10, width: Int, height: Int) { GLES20.glViewport(0, 0, width, height) } }
Java
import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES20; import android.opengl.GLSurfaceView; public class MyGLRenderer implements GLSurfaceView.Renderer { public void onSurfaceCreated(GL10 unused, EGLConfig config) { // Set the background frame color GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); } public void onDrawFrame(GL10 unused) { // Redraw background color GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); } public void onSurfaceChanged(GL10 unused, int width, int height) { GLES20.glViewport(0, 0, width, height); } }
内容はこれだけです。上記のサンプルコードでは、OpenGL を使用して黒い画面を表示するシンプルな Android アプリを作成しています。このコードでは特に何も起こりませんが、これらのクラスを作成することで、OpenGL でグラフィック要素の描画を開始するために必要な基盤ができました。
注: OpengGL ES 2.0 API を使用している場合、これらのメソッドに GL10
パラメータがあるのはなぜか、疑問に思われるかもしれません。Android フレームワークのコードをシンプルにするため、これらのメソッド シグネチャは単に 2.0 API に再利用されます。
OpenGL ES API に精通していれば、アプリに OpenGL ES 環境をセットアップしてグラフィックの描画を開始できるはずです。OpenGL の使い方についてさらにサポートが必要な場合は、次のレッスンに進み、その他のヒントをご覧ください。