OpenGL ES

Android は、Open Graphics Library(OpenGL®)、特に OpenGL ES API による高性能 2D および 3D グラフィックをサポートしています。OpenGL は、3D グラフィック処理ハードウェアの標準ソフトウェア インターフェースを指定するクロス プラットフォームのグラフィック API です。OpenGL ES は、組み込みデバイス向けの OpenGL 仕様の一種です。Android は、OpenGL ES API の複数のバージョンをサポートしています。

  • OpenGL ES 2.0 - この API 仕様は Android 2.2(API レベル 8)以降でサポートされています。
  • OpenGL ES 3.0 - この API 仕様は Android 4.3(API レベル 18)以降でサポートされています。
  • OpenGL ES 3.1 - この API 仕様は Android 5.0(API レベル 21)以降でサポートされています。
  • OpenGL ES 3.2 - この API 仕様は Android 7.0(API レベル 24)以降でサポートされています。

注意: Android プラットフォームのバージョンに関係なく、デバイス メーカーがこのグラフィック パイプラインの実装を提供していない限り、デバイスで OpenGL ES 3.0 API をサポートすることはできません。OpenGL ES 3.0 が必須であることをマニフェストで指定すると、そのバージョンがデバイスに存在することを確認できます。下位レベルのバージョンが必要であると指定したが、3.0 の機能が利用可能な場合はその機能を使用したい場合は、デバイスがサポートする OpenGL のバージョンを実行時にチェックする必要があります。これを行う方法については、OpenGL ES バージョンの確認をご覧ください。

注: Android は OpenGL ES 1.0 と 1.1 をサポートしていますが、これらのバージョンの API は非推奨であるため、最新のアプリでは使用しないでください。

注: Android フレームワークによって提供される特定の API は、J2ME JSR239 OpenGL ES API と類似していますが、同一ではありません。J2ME JSR239 仕様に精通している場合は、そのバリエーションに注意してください。

参照

基本情報

Android は、フレームワーク API とネイティブ開発キット(NDK)の両方で OpenGL をサポートしています。このトピックでは、Android フレームワーク インターフェースに焦点を当てて説明します。NDK の詳細については、Android NDK をご覧ください。

Android フレームワークには、OpenGL ES API を使用してグラフィックを作成および操作できる、GLSurfaceViewGLSurfaceView.Renderer の 2 つの基本クラスがあります。Android アプリで OpenGL を使用することが目標の場合は、これらのクラスをアクティビティに実装する方法を理解することを第一の目標にする必要があります。

GLSurfaceView
このクラスは、OpenGL API 呼び出しを使用してオブジェクトを描画および操作できる View であり、機能的には SurfaceView と似ています。このクラスを使用するには、GLSurfaceView のインスタンスを作成して Renderer を追加します。ただし、タッチ スクリーン イベントをキャプチャする場合は、OpenGL トレーニング レッスンのタッチイベントへの応答で説明されているように、GLSurfaceView クラスを拡張してタッチリスナーを実装する必要があります。
GLSurfaceView.Renderer
このインターフェースは、GLSurfaceView でグラフィックを描画するために必要なメソッドを定義します。このインターフェースの実装を別のクラスとして提供し、GLSurfaceView.setRenderer() を使用して GLSurfaceView インスタンスに接続する必要があります。

GLSurfaceView.Renderer インターフェースには、次のメソッドを実装する必要があります。

  • onSurfaceCreated(): GLSurfaceView の作成時に、このメソッドが 1 回呼び出されます。OpenGL 環境パラメータの設定や OpenGL グラフィック オブジェクトの初期化など、1 回だけ実行する必要があるアクションを実行するには、このメソッドを使用します。
  • onDrawFrame(): GLSurfaceView が再描画されるごとに、システムがこのメソッドを呼び出します。このメソッドは、グラフィック オブジェクトの描画(および再描画)を行う際の主な実行ポイントとして使用します。
  • onSurfaceChanged(): GLSurfaceView のサイズやデバイス画面の向きの変更など、GLSurfaceView ジオメトリが変更されたときに、システムがこのメソッドを呼び出します。たとえば、デバイスが縦向きから横向きに変わると、このメソッドが呼び出されます。GLSurfaceView コンテナの変更に対応するには、このメソッドを使用します。

OpenGL ES パッケージ

GLSurfaceViewGLSurfaceView.Renderer を使用して OpenGL ES のコンテナビューを確立したら、次のクラスを使用して OpenGL API の呼び出しを開始できます。

  • OpenGL ES 2.0 API クラス
    • android.opengl.GLES20 - このパッケージは OpenGL ES 2.0 へのインターフェースを提供し、Android 2.2(API レベル 8)以降で使用できます。
  • OpenGL ES 3.0/3.1/3.2 API パッケージ
    • android.opengl - このパッケージは、OpenGL ES 3.0/3.1 クラスへのインターフェースを提供します。バージョン 3.0 は Android 4.3(API レベル 18)以降で使用できます。バージョン 3.1 は Android 5.0(API レベル 21)以降で使用できます。バージョン 3.2 は Android 7.0(API レベル 24)以降で使用できます。

OpenGL ES でアプリの作成をすぐに開始する場合は、OpenGL ES でグラフィックを表示するをご覧ください。

OpenGL の要件の宣言

すべてのデバイスでは使用できない OpenGL 機能をアプリケーションで使用する場合は、これらの要件を AndroidManifest.xml ファイルに含める必要があります。ここでは、一般的な OpenGL マニフェストの宣言を示します。

  • OpenGL ES バージョンの要件 - アプリが特定のバージョンの OpenGL ES を必要とする場合は、以下の設定をマニフェストに追加して、その要件を宣言する必要があります。

    OpenGL ES 2.0 の場合:

    <!-- Tell the system this app requires OpenGL ES 2.0. -->
    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
    

    この宣言を追加すると、Google Play は OpenGL ES 2.0 をサポートしていないデバイスへのアプリのインストールを制限します。アプリが OpenGL ES 3.0 をサポートするデバイス専用の場合は、マニフェストで次のように指定することもできます。

    OpenGL ES 3.0 の場合:

    <!-- Tell the system this app requires OpenGL ES 3.0. -->
    <uses-feature android:glEsVersion="0x00030000" android:required="true" />
    

    OpenGL ES 3.1 の場合:

    <!-- Tell the system this app requires OpenGL ES 3.1. -->
    <uses-feature android:glEsVersion="0x00030001" android:required="true" />
    

    OpenGL ES 3.2 の場合:

    <!-- Tell the system this app requires OpenGL ES 3.2. -->
    <uses-feature android:glEsVersion="0x00030002" android:required="true" />
    

    注: OpenGL ES 3.x API には 2.0 API との下位互換性があるため、アプリケーションでの OpenGL ES の実装により柔軟に対応できます。マニフェストで OpenGL ES 2.0 API を要件として宣言すると、その API バージョンをデフォルトとして使用し、実行時に 3.x API を使用できるかどうかをチェックして、デバイスでサポートされている場合は OpenGL ES 3.x の機能を使用できます。デバイスでサポートされている OpenGL ES バージョンの確認について詳しくは、OpenGL ES バージョンの確認をご覧ください。

  • テクスチャ圧縮の要件 - アプリでテクスチャ圧縮形式を使用する場合は、<supports-gl-texture> を使用して、アプリがサポートする形式をマニフェスト ファイルで宣言する必要があります。利用可能なテクスチャ圧縮形式について詳しくは、テクスチャ圧縮のサポートをご覧ください。

    マニフェストでテクスチャ圧縮要件を宣言すると、宣言した圧縮タイプの少なくとも 1 つをサポートしていないデバイスを使用しているユーザーには、アプリが表示されなくなります。テクスチャ圧縮に対する Google Play フィルタリングの仕組みについては、<supports-gl-texture> ドキュメントの Google Play とテクスチャ圧縮フィルタリングのセクションをご覧ください。

描画オブジェクトの座標のマッピング

Android デバイスでグラフィックを表示する際の基本的な問題の 1 つは、画面のサイズや形状が異なる可能性があることです。OpenGL は正方形の均一な座標系を想定しており、デフォルトでは、正方形ではない画面にこれらの座標を完全な正方形であるかのように描画します。

図 1. デフォルトの OpenGL 座標系(左)を一般的な Android デバイスの画面にマッピング(右)。

上の図は、左側の OpenGL フレームで想定される均一座標系と、右側の横向きの典型的なデバイス画面にこれらの座標が実際にどのようにマッピングされるかを示しています。この問題を解決するには、OpenGL 投影モードとカメラビューを適用して座標を変換し、どのディスプレイでもグラフィック オブジェクトが適切な比率になるようにします。

投影ビューとカメラビューを適用するには、投影行列とカメラビュー マトリックスを作成し、OpenGL レンダリング パイプラインに適用します。投影行列はグラフィックの座標を再計算して、Android デバイスの画面に正しくマッピングされるようにします。カメラビュー マトリックスにより、特定の目の位置からオブジェクトをレンダリングする変換が作成されます。

OpenGL ES 2.0 以降での投影とカメラビュー

ES 2.0 API と ES 3.0 API では、まずグラフィック オブジェクトの頂点シェーダーにマトリックス メンバーを追加して、投影とカメラビューを適用します。このマトリックス メンバーを追加すると、投影行列とカメラ表示行列を生成してオブジェクトに適用できます。

  1. 頂点シェーダーに行列を追加する - ビュー射影行列の変数を作成し、シェーダーの位置の乗数として追加します。次の頂点シェーダーのコード例では、含まれている uMVPMatrix メンバーを使用して、このシェーダーを使用するオブジェクトの座標に投影行列とカメラ表示行列を適用できます。

    Kotlin

    private val vertexShaderCode =
    
        // This matrix member variable provides a hook to manipulate
        // the coordinates of objects that use this vertex shader.
        "uniform mat4 uMVPMatrix;   \n" +
    
        "attribute vec4 vPosition;  \n" +
        "void main(){               \n" +
        // The matrix must be included as part of gl_Position
        // Note that the uMVPMatrix factor *must be first* in order
        // for the matrix multiplication product to be correct.
        " gl_Position = uMVPMatrix * vPosition; \n" +
    
        "}  \n"
    

    Java

    private final String vertexShaderCode =
    
        // This matrix member variable provides a hook to manipulate
        // the coordinates of objects that use this vertex shader.
        "uniform mat4 uMVPMatrix;   \n" +
    
        "attribute vec4 vPosition;  \n" +
        "void main(){               \n" +
        // The matrix must be included as part of gl_Position
        // Note that the uMVPMatrix factor *must be first* in order
        // for the matrix multiplication product to be correct.
        " gl_Position = uMVPMatrix * vPosition; \n" +
    
        "}  \n";
    

    注: 上記の例では、投影行列とカメラビュー行列を組み合わせた単一の変換行列メンバーを、頂点シェーダーで定義しています。アプリケーションの要件に応じて、頂点シェーダーで投影行列とカメラ表示行列の各メンバーを別々に定義し、個別に変更することができます。

  2. シェーダー マトリックスにアクセスする - 頂点シェーダーでフックを作成して投影とカメラビューを適用すると、その変数にアクセスして投影行列とカメラ表示行列を適用できます。次のコードは、GLSurfaceView.Renderer 実装の onSurfaceCreated() メソッドを変更して、上記の頂点シェーダーで定義された行列変数にアクセスする方法を示しています。

    Kotlin

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix")
        ...
    }
    

    Java

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
        ...
    }
    
  3. 投影行列とカメラ表示行列を作成する - グラフィック オブジェクトに適用する投影行列と表示行列を生成します。次のサンプルコードは、GLSurfaceView.Renderer 実装の onSurfaceCreated() メソッドと onSurfaceChanged() メソッドを変更して、デバイスの画面アスペクト比に基づいてカメラビュー マトリックスと投影マトリックスを作成する方法を示しています。

    Kotlin

    override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
        ...
        // Create a camera view matrix
        Matrix.setLookAtM(vMatrix, 0, 0f, 0f, -3f, 0f, 0f, 0f, 0f, 1.0f, 0.0f)
    }
    
    override fun onSurfaceChanged(gl: GL10, width: Int, height: Int) {
        GLES20.glViewport(0, 0, width, height)
    
        val ratio: Float = width.toFloat() / height.toFloat()
    
        // create a projection matrix from device screen geometry
        Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1f, 1f, 3f, 7f)
    }
    

    Java

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        ...
        // Create a camera view matrix
        Matrix.setLookAtM(vMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
    }
    
    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    
        float ratio = (float) width / height;
    
        // create a projection matrix from device screen geometry
        Matrix.frustumM(projMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
    }
    
  4. 投影行列とカメラビュー行列を適用する - 投影変換とカメラビュー変換を適用するには、行列を乗算して、頂点シェーダーに設定します。次のサンプルコードは、GLSurfaceView.Renderer 実装の onDrawFrame() メソッドを変更して、上記のコードで作成した投影行列とカメラビューを結合し、OpenGL によってレンダリングされるグラフィック オブジェクトに適用する方法を示しています。

    Kotlin

    override fun onDrawFrame(gl: GL10) {
        ...
        // Combine the projection and camera view matrices
        Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0)
    
        // Apply the combined projection and camera view transformations
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0)
    
        // Draw objects
        ...
    }
    

    Java

    public void onDrawFrame(GL10 unused) {
        ...
        // Combine the projection and camera view matrices
        Matrix.multiplyMM(vPMatrix, 0, projMatrix, 0, vMatrix, 0);
    
        // Apply the combined projection and camera view transformations
        GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, vPMatrix, 0);
    
        // Draw objects
        ...
    }
    

OpenGL ES 2.0 で投影とカメラビューを適用する方法の詳細な例については、OpenGL ES でグラフィックを表示するをご覧ください。

図形の面と巻き方

OpenGL では、図形の面とは 3 次元空間内の 3 つ以上の点によって定義される面です。3 次元以上の 3 次元点(OpenGL では頂点と呼ばれます)には、前面と背面があります。どちらが前面で、どちらが背面か、どうすればわかるでしょうか。お問い合わせいただきありがとうございます。答えは、曲線、つまりシェイプのポイントを定義する方向に関係しています。

座標は三角形の頂点を基準とし

図 1. 反時計回りの描画順序に変換される座標リストのイラスト。

この例では、三角形の各点が反時計回りの方向に描画される順序で定義されています。これらの座標が描画される順序によって、シェイプの巻き方向が定義されます。OpenGL ではデフォルトで、反時計回りに描画される面が前面です。図 1 の三角形は、(OpenGL によって解釈された)図形の前面を見て、反対側が背面になるように定義されています。

図形のどちらが前面であるかを把握することが重要なのはなぜでしょうか。その答えは、フェイス カリングと呼ばれる OpenGL でよく使用される機能に関係しています。フェイス カリングは OpenGL 環境のオプションです。これにより、レンダリング パイプラインでシェイプの背面を無視(計算や描画をしない)できるようになり、時間、メモリ、処理サイクルを節約できます。

Kotlin

gl.apply {
    // enable face culling feature
    glEnable(GL10.GL_CULL_FACE)
    // specify which faces to not draw
    glCullFace(GL10.GL_BACK)
}

Java

// enable face culling feature
gl.glEnable(GL10.GL_CULL_FACE);
// specify which faces to not draw
gl.glCullFace(GL10.GL_BACK);

図形の前面と背面がわからないときにフェイス カリング機能を使用しようとすると、OpenGL グラフィックがやや薄く見えるか、まったく表示されない可能性があります。したがって、OpenGL 図形の座標は常に反時計回りの描画順序で定義してください。

注: OpenGL 環境を設定して時計回りの顔を前面として処理することもできますが、その場合はより多くのコードが必要となり、経験豊富な OpenGL 開発者にサポートを依頼すると混乱する可能性があります。そのため、これは避けてください。

OpenGL バージョンとデバイスの互換性

OpenGL ES 1.0 と 1.1 の API 仕様は Android 1.0 以降でサポートされています。 OpenGL ES 1.0/1.1 API によるグラフィック プログラミングは、2.0 以降のバージョンを使用する場合とは大きく異なります。OpenGL ES 2.0 は、Android 2.2(API レベル 8)以降のすべての Android デバイスでサポートされており、OpenGL ES で開発する新しいアプリに推奨される最も古いバージョンです。OpenGL ES 3.0 は、OpenGL ES 3.0 API の実装を提供するデバイスの Android 4.3(API レベル 18)以降でサポートされます。特定のバージョンの OpenGL ES をサポートする Android 搭載デバイスの相対数については、OpenGL ES バージョン ダッシュボードをご覧ください。

グラフィックの要件を慎重に検討し、アプリケーションに最適な API バージョンを選択する必要があります。詳しくは、OpenGL API バージョンの選択をご覧ください。

OpenGL ES 3.0 API は、2.0 API よりも追加機能とパフォーマンスが向上しており、下位互換性もあります。つまり、OpenGL ES 2.0 をターゲットとするアプリを作成し、OpenGL ES 3.0 のグラフィック機能が利用可能な場合は条件付きで含めることができます。3.0 API が利用できるかどうかの確認について詳しくは、OpenGL ES バージョンの確認をご覧ください。

テクスチャ圧縮のサポート

テクスチャ圧縮は、メモリ要件を減らし、メモリ帯域幅をより効率的に使用することで、OpenGL アプリケーションのパフォーマンスを大幅に向上させることができます。Android フレームワークは、ETC1Util ユーティリティ クラスや etc1tool 圧縮ツール(<sdk>/tools/ の Android SDK にあります)などの標準機能として ETC1 圧縮形式をサポートしています。テクスチャ圧縮を使用する Android アプリの例については、Android SDK(<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/)の CompressedTextureActivity コードサンプルをご覧ください。

ETC1 形式は、OpenGL ES 2.0 以降をサポートするすべての Android デバイスでサポートされています。

注: ETC1 テクスチャ圧縮形式は、透明度(アルファ チャンネル)のあるテクスチャをサポートしていません。アプリで透明なテクスチャが必要な場合は、ターゲット デバイスで使用可能な他のテクスチャ圧縮形式を調査する必要があります。ETC1 を使用してアルファ チャネル テクスチャをレンダリングするには、2 つの ETC1 テクスチャ オブジェクトをバインドします。1 つ目は色データで、2 つ目はアルファ チャネル データでバインドしてから、フラグメント シェーダーで 2 つのテクスチャの値を結合します。

OpenGL ES 3.0 API を使用する場合は、ETC2/EAC テクスチャ圧縮形式が利用可能であることが保証されます。このテクスチャ形式は、優れた画質で優れた圧縮率を実現し、透明度(アルファ チャンネル)もサポートしています。

Android デバイスは、ETC 形式以外にも、GPU チップセットや OpenGL の実装に応じてさまざまなテクスチャ圧縮をサポートしています。ターゲットとするデバイスのテクスチャ圧縮のサポート状況を調べて、アプリがサポートする必要がある圧縮タイプを決定する必要があります。特定のデバイスでサポートされているテクスチャ形式を確認するには、デバイスにクエリを実行し、OpenGL 拡張機能名を確認する必要があります。OpenGL 拡張機能名により、デバイスでサポートされているテクスチャ圧縮形式(およびその他の OpenGL 機能)が特定されます。一般的にサポートされているテクスチャ圧縮形式は次のとおりです。

  • Adaptable Scalable Texture Compression(ASTC) - 以前の形式に優先して設計されたテクスチャ圧縮形式。さまざまなブロックサイズをサポートしているため、以前の形式よりも柔軟性が高くなっています。
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(ハイ ダイナミック レンジ)
  • S3TC(DXTn/DXTC) - S3 テクスチャ圧縮(S3TC)には形式のバリエーションが複数あり(DXT1 から DXT5)、あまり広く利用できません。この形式は、4 ビットのアルファ チャンネルまたは 8 ビットのアルファ チャンネルを持つ RGB テクスチャをサポートします。これらの形式は、次の OpenGL 拡張機能名で表されます。
    • GL_EXT_texture_compression_s3tc
    一部のデバイスでは、DXT1 形式のバリエーションのみをサポートしています。この限定的なサポートは、次の OpenGL 拡張機能名で表されます。
    • GL_EXT_texture_compression_dxt1

次のテクスチャ圧縮形式は以前の形式とみなされるため、新しいアプリでの使用は推奨されません。

  • ATITC(ATC) - ATI テクスチャ圧縮(ATITC または ATC)はさまざまなデバイスで利用でき、アルファ チャンネルの有無にかかわらず RGB テクスチャの固定レート圧縮をサポートします。この形式は、次のような複数の OpenGL 拡張機能名で表されます。
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC - PowerVR テクスチャ圧縮(PVRTC)はさまざまなデバイスで利用でき、アルファ チャンネルの有無にかかわらず、ピクセルあたり 2 ビットと 4 ビットのテクスチャをサポートします。この形式は、次の OpenGL 拡張機能名で表されます。
    • GL_IMG_texture_compression_pvrtc
  • 3DC - 3DC テクスチャ圧縮(3DC)は、アルファ チャンネルを持つ RGB テクスチャをサポートする、あまり普及していない形式です。この形式は、次の OpenGL 拡張機能名で表されます。
    • GL_AMD_compressed_3DC_texture

警告: これらのテクスチャ圧縮形式は、すべてのデバイスでサポートされていません。これらの形式のサポート状況は、製造元またはデバイスによって異なる場合があります。特定のデバイスでのテクスチャ圧縮形式を判別する方法については、次のセクションをご覧ください。

注: アプリがサポートするテクスチャ圧縮形式を決定したら、<supports-gl-texture> を使ってマニフェストで宣言します。この宣言を使用すると、Google Play などの外部サービスによるフィルタリングが有効になり、アプリが必要とする形式をサポートするデバイスにのみアプリがインストールされます。詳しくは、OpenGL マニフェストの宣言をご覧ください。

OpenGL 拡張機能の決定

OpenGL の実装は、サポートされている OpenGL ES API の拡張機能の点で Android デバイスによって異なります。これらの拡張機能にはテクスチャ圧縮が含まれていますが、通常は OpenGL 機能セットの他の拡張機能も含まれます。

特定のデバイスでサポートされているテクスチャ圧縮形式やその他の OpenGL 拡張機能を確認するには:

  1. 対象デバイスで次のコードを実行して、サポートされているテクスチャ圧縮形式を確認します。

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

    String extensions = gl.glGetString(GL10.GL_EXTENSIONS);
    

    警告: この呼び出しの結果は、デバイスモデルによって異なります。この呼び出しを複数のターゲット デバイスで実行して、一般的にサポートされている圧縮タイプを特定する必要があります。

  2. このメソッドの出力を確認して、デバイスでサポートされている OpenGL 拡張機能を判断します。

Android 拡張機能パック(AEP)

AEP により、アプリは OpenGL 3.1 仕様で規定されているコアセットだけでなく、OpenGL 拡張機能の標準化されたセットをサポートするようになります。これらの拡張機能をまとめてパッケージ化することで、デバイス間で一貫した機能セットが促進されるとともに、デベロッパーは最新のモバイル GPU デバイスを最大限に活用できます。

AEP では、フラグメント シェーダーの画像、シェーダー ストレージ バッファ、アトミック カウンタのサポートも改善されています。

アプリで AEP を使用できるようにするには、アプリのマニフェストで AEP が必須であることを宣言する必要があります。さらに、プラットフォームのバージョンでサポートされている必要があります。

AEP で指定されている追加機能はすべて、基本 OpenGL ES 3.2 仕様に含まれています。アプリが OpenGL ES 3.2 を必要とする場合、AEP を必須にする必要はありません。

マニフェストで AEP 要件を次のように宣言します。

<uses-feature android:name="android.hardware.opengles.aep"
              android:required="true" />

プラットフォーム バージョンが AEP をサポートしていることを確認するには、hasSystemFeature(String) メソッドを使用して、引数として FEATURE_OPENGLES_EXTENSION_PACK を渡します。次のコード スニペットは、その方法の例を示しています。

Kotlin

var deviceSupportsAEP: Boolean =
        packageManager.hasSystemFeature(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK)

Java

boolean deviceSupportsAEP = getPackageManager().hasSystemFeature
     (PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);

メソッドが true を返す場合、AEP はサポートされます。

AEP の詳細については、 Khronos OpenGL ES Registry のページをご覧ください。

OpenGL ES バージョンの確認

Android デバイスで利用可能な OpenGL ES には複数のバージョンがあります。アプリケーションに必要な API の最小バージョンはマニフェストで指定できますが、新しい API の機能を同時に利用することもできます。たとえば、OpenGL ES 3.0 API は 2.0 バージョンの API と下位互換性があるため、OpenGL ES 3.0 機能を使用し、3.0 API を使用できない場合は 2.0 API にフォールバックするようにアプリを作成することもできます。

アプリ マニフェストで必要とされる最小バージョンよりも高いバージョンから OpenGL ES 機能を使用する前に、デバイスで使用できる API のバージョンをアプリで確認する必要があります。これには次の 2 つの方法があります。

  1. 上位レベルの OpenGL ES コンテキスト(EGLContext)を作成して結果を確認します。
  2. 最低限サポートされている OpenGL ES コンテキストを作成し、バージョン値を確認する。

次のサンプルコードは、EGLContext を作成して結果を確認することで、利用可能な OpenGL ES バージョンを確認する方法を示しています。次の例は、OpenGL ES 3.0 バージョンを確認する方法を示しています。

Kotlin

private const val EGL_CONTEXT_CLIENT_VERSION = 0x3098
private const val glVersion = 3.0
private class ContextFactory : GLSurfaceView.EGLContextFactory {

    override fun createContext(egl: EGL10, display: EGLDisplay, eglConfig: EGLConfig): EGLContext {

        Log.w(TAG, "creating OpenGL ES $glVersion context")
        return egl.eglCreateContext(
                display,
                eglConfig,
                EGL10.EGL_NO_CONTEXT,
                intArrayOf(EGL_CONTEXT_CLIENT_VERSION, glVersion.toInt(), EGL10.EGL_NONE)
        ) // returns null if 3.0 is not supported
    }
}

Java

private static double glVersion = 3.0;

private static class ContextFactory implements GLSurfaceView.EGLContextFactory {

  private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;

  public EGLContext createContext(
          EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {

      Log.w(TAG, "creating OpenGL ES " + glVersion + " context");
      int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) glVersion,
              EGL10.EGL_NONE };
      // attempt to create a OpenGL ES 3.0 context
      EGLContext context = egl.eglCreateContext(
              display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
      return context; // returns null if 3.0 is not supported;
  }
}

上記の createContext() メソッドが null を返す場合は、代わりに OpenGL ES 2.0 コンテキストを作成し、その API のみを使用するようにフォールバックする必要があります。

次のコード例は、サポートされる最小限のコンテキストを作成してからバージョン文字列を確認することで、OpenGL ES のバージョンを確認する方法を示しています。

Kotlin

// Create a minimum supported OpenGL ES context, then check:
gl.glGetString(GL10.GL_VERSION).also {
    Log.w(TAG, "Version: $it")
}
 // The version format is displayed as: "OpenGL ES <major>.<minor>"
 // followed by optional content provided by the implementation.

Java

// Create a minimum supported OpenGL ES context, then check:
String version = gl.glGetString(GL10.GL_VERSION);
Log.w(TAG, "Version: " + version );
// The version format is displayed as: "OpenGL ES <major>.<minor>"
// followed by optional content provided by the implementation.

このアプローチでは、デバイスが上位レベルの API バージョンをサポートしていることが判明した場合、最小 OpenGL ES コンテキストを破棄し、可用性の高い API バージョンで新しいコンテキストを作成する必要があります。

OpenGL API バージョンの選択

OpenGL ES バージョン 2.0 とバージョン 3.0 はどちらも、3D ゲーム、可視化、ユーザー インターフェースを作成するための高性能なグラフィック インターフェースを備えています。OpenGL ES 2.0 と 3.0 のグラフィック プログラミングはほぼ同じですが、バージョン 3.0 は 2.0 API のスーパーセットであり、機能が追加されています。OpenGL ES 1.0/1.1 API と OpenGL ES 2.0 および 3.0 ではプログラミングが大きく異なるため、新しいアプリではおすすめしません。デベロッパーは、これらの API を使用して開発を開始する前に、次の要素を慎重に検討する必要があります。

  • デバイスの互換性 - デベロッパーは、お客様が利用できるデバイスの種類、Android のバージョン、OpenGL ES のバージョンを考慮する必要があります。デバイス間の OpenGL の互換性について詳しくは、OpenGL のバージョンとデバイスの互換性のセクションをご覧ください。
  • テクスチャのサポート - OpenGL ES 3.0 API は、透明性をサポートする ETC2 圧縮形式を保証するため、テクスチャ圧縮に最適です。API 2.0 の実装には ETC1 のサポートが含まれますが、このテクスチャ形式では透明度をサポートしていません。圧縮テクスチャを使用して透明度を実装するには、2 つの ETC1 テクスチャ(色とアルファに分割)を使用するか、ターゲットとするデバイスでサポートされている他の圧縮形式でリソースを指定する必要があります。詳細については、テクスチャ圧縮のサポートをご覧ください。

互換性やテクスチャのサポートの有無が判断に影響する可能性がありますが、最適なユーザー エクスペリエンスを提供できると思われる OpenGL API のバージョンを選択してください。