OpenGL ES 環境の構築

Android アプリで OpenGL ES を使用してグラフィックを描画するには、それらのグラフィック用のビューコンテナを作成する必要があります。最も簡単な方法の一つは、GLSurfaceViewGLSurfaceView.Renderer の両方を実装することです。GLSurfaceView は OpenGL で描画されるグラフィックのビューコンテナであり、GLSurfaceView.Renderer はそのビュー内に描画されるものを制御します。これらのクラスについて詳しくは、OpenGL ES デベロッパー ガイドをご覧ください。

GLSurfaceView は、OpenGL ES グラフィックをアプリケーションに組み込む方法の一つにすぎません。全画面表示または全画面に近いグラフィック ビューの場合、これは妥当な選択です。OpenGL ES グラフィックをレイアウトの一部に組み込むことを希望するデベロッパーは、TextureView をご覧ください。実際に自作する場合、SurfaceView を使用して OpenGL ES ビューを作成することもできますが、かなりの量の追加コードを記述する必要があります。

このレッスンでは、単純なアプリ アクティビティに GLSurfaceViewGLSurfaceView.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 アプリには、ユーザー インターフェースを備えた他のアプリと同様のアクティビティがあります。他のアプリとの主な違いは、アクティビティのレイアウトに配置するものです。多くのアプリでは TextViewButtonListView を使用できますが、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 の使い方についてさらにサポートが必要な場合は、次のレッスンに進み、その他のヒントをご覧ください。