OpenGL ES

Android 支援使用 Open Graphics Library 顯示高效能 2D 和 3D 圖形 (OpenGL®),特別是 OpenGL ES API。OpenGL 是一種跨平台圖形 API 會指定 是 3D 圖形處理硬體的標準軟體介面。OpenGL ES 是 OpenGL 的變種版本 或其他適用於內嵌裝置的規格Android 支援多個版本的 OpenGL ES API:

  • OpenGL ES 2.0:Android 2.2 (API 級別 8) 以上版本支援此 API 規格。
  • OpenGL ES 3.0:Android 4.3 (API 級別 18) 以上版本支援此 API 規格。
  • OpenGL ES 3.1 - Android 5.0 (API 級別 21) 以上版本支援此 API 規格。
  • OpenGL ES 3.2:Android 7.0 (API 級別 24) 以上版本支援此 API 規格。

注意: 無論 Android 平台版本為何,裝置都無法支援 OpenGL ES 3.0 API,除非裝置製造商提供 這個圖形管線的實作過程如果您在資訊清單中指定 OpenGL ES 3.0 為必要版本,從 2014 年開始 應用程式。如果您指定必須使用較低層級的版本 若想使用 3.0 版功能,請在執行期間進行 ,查看該裝置支援的 OpenGL 版本。如要瞭解如何 請參閱檢查 OpenGL ES 版本

注意: Android 支援 OpenGL ES 1.0 和 1.1,但這些版本的 API 已淘汰,不應由現代應用程式使用。

注意: Android 架構提供的特定 API 與 J2ME JSR239 OpenGL ES API 類似。 並非完全相同如果您熟悉 J2ME JSR239 規格,請發出以下快訊: 變化版本。

亦請參閱

基本概念

Android 透過架構 API 和原生開發支援 OpenGL Kit (NDK)。本主題著重於 Android 架構介面。如要進一步瞭解 NDK,請參閱 Android NDK

Android 架構提供兩種基礎類別,可讓您建立及操控 支援 OpenGL ES API 的圖形:GLSurfaceViewGLSurfaceView.Renderer。如果您的目標是在 Android 應用程式中使用 OpenGL, 您應該先瞭解如何在活動中實作這些類別,做為您的首要目標。

GLSurfaceView
此類別為 View,可讓您使用 OpenGL API 呼叫,且與 SurfaceView 的函式類似。別擔心!您可以使用 方法是建立 GLSurfaceView 的執行個體並新增 Renderer。不過,如果您要擷取 觸控螢幕事件,您應將 GLSurfaceView 類別擴充為 實作觸控事件監聽器,如 OpenGL 訓練課程所示 回應觸控事件
GLSurfaceView.Renderer
這個介面定義在 GLSurfaceView 中繪製圖形所需的方法。您必須以 分隔類別,並將該類別附加至 GLSurfaceView 例項 GLSurfaceView.setRenderer()

GLSurfaceView.Renderer 介面會要求您實作 方法如下:

  • onSurfaceCreated():系統會稱之為 方法 (在建立 GLSurfaceView 時)。使用這個方法 例如設定 OpenGL 環境參數 初始化 OpenGL 圖形物件
  • 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 套件

如要立即開始使用 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 功能 則支援這個 API如需進一步瞭解如何檢查 裝置,請參閱檢查 OpenGL ES 版本

  • 紋理壓縮要求 - 如果應用程式使用紋理 壓縮格式,您必須在資訊清單檔案中宣告應用程式支援的格式。 使用 <supports-gl-texture>。 進一步瞭解可用的紋理壓縮 格式,請參閱「紋理壓縮支援」一文。

    在資訊清單中宣告紋理壓縮要求,會讓使用者看不到您的應用程式 表示裝置不支援至少一種已宣告壓縮類型。如要 如要瞭解 Google Play 篩選功能如何進行紋理壓縮,請參閱 <supports-gl-texture>說明文件中的 Google Play 和紋理壓縮篩選功能一節。

繪製物件的對應座標

在 Android 裝置上顯示圖像的基本問題之一,就是螢幕可以 大小和形狀都不同OpenGL 會假設是正方形的統一座標系統,且預設為幸福 將這些座標繪製在通常非正方形的畫面上,就像是完全正方形一樣。

圖 1. 對應至一般 Android 的預設 OpenGL 座標系統 (左側) 裝置螢幕 (右側)。

上圖顯示了 以及這些座標如何對應到橫向的典型裝置螢幕 符合條件後,系統會傳送自訂電子郵件 當中包含畫面右側「說明文件」區的內容如要解決這個問題,您可將 OpenGL 投影模式和相機檢視套用於 轉換座標,讓圖像物件在任何顯示螢幕上都能有正確比例。

如要套用投影和相機檢視畫面,請建立投影矩陣和相機檢視畫面 矩陣,並套用至 OpenGL 轉譯管道。投影矩陣會重新計算 圖像的座標,讓這些圖像能正確對應到 Android 裝置螢幕。相機檢視畫面 矩陣會建立一個轉換,以從特定眼睛位置算繪物件。

OpenGL ES 2.0 以上版本中的投影和相機檢視畫面

在 ES 2.0 和 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. 建立投影與相機視角的矩陣:產生投影與 以及檢視矩陣以套用圖形物件下列程式碼範例顯示如何修改 《onSurfaceCreated()》和 其中的 onSurfaceChanged() 種方法 GLSurfaceView.Renderer實作來建立相機檢視矩陣,以及 根據裝置螢幕長寬比算出的投影矩陣。

    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() 方法,以便進行合併 上述程式碼中建立的投影矩陣和相機檢視畫面,並套用至圖形 物件。

    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 中,形狀的表面是由 3D 以上三個點定義的表面 空白鍵。由三個或以上三個維度點 (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 版本和裝置相容性

自 Android 1.0 版開始,支援 OpenGL ES 1.0 和 1.1 API 規格。 採用 OpenGL ES 1.0/1.1 API 的圖形程式設計與 2.0 版有顯著差異 及以上版本。 從 Android 2.2 (API 級別 8) 開始,所有 Android 裝置都支援 OpenGL ES 2.0, 最好是針對使用 OpenGL ES 開發的新應用程式所建議的最早版本。 Android 4.3 (API 級別 18) 以上版本支援 OpenGL ES 3.0, OpenGL ES 3.0 API 實作。 有關相對 Android 裝置數量的資訊 支援指定版本的 OpenGL ES,請參閱 OpenGL ES 版本資訊主頁

請仔細考量圖像需求並選擇 API 找出最適合您應用程式的版本若需更多資訊,請參閲 選擇 OpenGL API 版本

OpenGL ES 3.0 API 提供比 2.0 API 更多的功能和效能更佳, 而且能回溯相容也就是說,您可以編寫應用程式指定目標 OpenGL ES 2.0,並且有條件地包括 OpenGL ES 3.0 圖形功能 (如果有的話)。適用對象 如要進一步瞭解如何檢查 API 3.0 API 的可用性,請參閱 檢查 OpenGL ES 版本

紋理壓縮支援

紋理壓縮功能可大幅提高 OpenGL 應用程式的效能, 降低記憶體需求,並提高記憶體頻寬的使用效率。Android 架構支援 ETC1 壓縮格式,做為標準功能,包括 ETC1Util 公用程式類別和 etc1tool 壓縮工具 (位於 Android SDK (位於 <sdk>/tools/)以使用 紋理壓縮,請參閱 Android SDK 中的 CompressedTextureActivity 程式碼範例 (<sdk>/samples/<version>/ApiDemos/src/com/example/android/apis/graphics/)。

支援 OpenGL ES 2.0 以上版本的 Android 裝置都支援 ETC1 格式。

注意:ETC1 紋理壓縮格式不支援含有 透明度 (Alpha 版)。如果您的應用程式需要透明的紋理,則應 調查目標裝置可用的其他紋理壓縮格式。A 罩杯 使用 ETC1 轉譯 Alpha 管道紋理的方法,是繫結兩個 ETC1 紋理物件: 其次是色彩資料,第二個使用 Alpha 通道資料,再結合兩者的值 就儲存在片段著色器中

使用 OpenGL ES 時,保證可以使用 ETC2/EAC 紋理壓縮格式 3.0 API。這種紋理格式提供優異的壓縮比例,且圖像品質良好, 格式也支援透明度 (Alpha 版)。

除了 ETC 格式,Android 裝置也根據 以及 GPU 晶片組和 OpenGL 實作項目您應調查以下項目的紋理壓縮支援: 來確定應用程式該使用哪種壓縮類型 聯絡。如要判斷特定裝置支援哪些紋理格式,您必須 查詢裝置並查看 OpenGL 擴充功能名稱, 這些物件會識別編碼器支援的紋理壓縮格式 (以及其他 OpenGL 功能) 裝置。部分常見的紋理壓縮格式如下:

  • 可調整的可擴充紋理壓縮 (ASTC) - 紋理壓縮格式 目的是取代先前的格式這種格式支援多種 區塊大小
    • GL_KHR_texture_compression_astc_ldr
    • GL_KHR_texture_compression_astc_hdr(高動態範圍)
  • S3TC (DXTn/DXTC) - S3 紋理壓縮 (S3TC) 有許多 格式變化版本 (DXT1 到 DXT5),而且無法廣泛使用。該格式支援採用 4 位元 Alpha 或 8 位元 Alpha 通道。這些格式是以下列 OpenGL 擴充功能表示 名稱:
    • GL_EXT_texture_compression_s3tc
    ,瞭解如何調查及移除這項存取權。 部分裝置僅支援 DXT1 格式變化。這項有限支援以 以下 OpenGL 擴充功能名稱:
    • GL_EXT_texture_compression_dxt1

下列紋理壓縮格式視為舊版格式,不建議使用 以便用於新的應用程式:

  • ATITC (ATC) - ATI 紋理壓縮 (ATITC 或 ATC) 適用於 多種裝置,支援固定率壓縮 (含和沒有) RGB 紋理 會有一個 Alpha 通道此格式可能以多個 OpenGL 擴充功能名稱表示,例如:
    • GL_AMD_compressed_ATC_texture
    • GL_ATI_texture_compression_atitc
  • PVRTC - PowerVR 紋理壓縮 (PVRTC) 廣泛支援 並支援 2 位元與 4 位元每個像素的紋理 (無論是否有 Alpha 通道)。 此格式的格式為以下 OpenGL 擴充功能名稱:
    • GL_IMG_texture_compression_pvrtc
  • 3DC - 3DC 紋理壓縮 (3DC) 是較不普遍使用的格式, 支援使用 Alpha 通道的 RGB 紋理。此格式如下列 OpenGL 表示 擴充功能名稱:
    • GL_AMD_compressed_3DC_texture

警告:這些紋理壓縮格式並非 支援。這些格式的支援可能因製造商和裝置而異。適用對象 如要瞭解如何判斷特定裝置上的紋理壓縮格式,請參閱 請參閱下一節的說明。

注意:在您決定好紋理壓縮格式後 應用程式將會支援,請確實在資訊清單中使用 <supports-gl-texture> 。透過這項宣告,即可依 Google Play 等外部服務進行篩選, 應用程式只安裝在支援應用程式所需格式的裝置上。詳情請參閱 OpenGL 資訊清單宣告

判斷 OpenGL 擴充功能

OpenGL 的實作方式會因 Android 裝置而異,取決於 OpenGL ES API 的擴充功能 支援的 Pod 清單這些擴充功能包含紋理壓縮,但通常也會包含其他 加入 OpenGL 功能集的擴充功能

如要判斷 a 上支援的紋理壓縮格式和其他 OpenGL 擴充功能, 特定裝置:

  1. 在目標裝置上執行以下程式碼,判斷哪種紋理壓縮 支援的格式包括:

    Kotlin

    var extensions = gl.glGetString(GL10.GL_EXTENSIONS)
    

    Java

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

    警告:這個呼叫的結果會因裝置型號而異!個人中心 必須在多部目標裝置上執行此呼叫,以便判斷常用的壓縮類型 支援。

  2. 請查看這個方法的輸出結果,確認瀏覽器支援哪些 OpenGL 擴充功能 裝置。

Android 擴充功能套件 (AEP)

AEP 可確保您的應用程式支援上述一組標準化 OpenGL 擴充功能 以及之後 OpenGL 3.1 規格說明的核心集,將這些擴充功能封裝在一起 鼓勵開發人員在各種裝置上提供一致的功能組合 。

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,請造訪 AEP 頁面: Khronos OpenGL ES Registry

檢查 OpenGL ES 版本

Android 裝置提供多種版本的 OpenGL ES。可指定的意圖包括 資訊清單中應用程式需要的 API 最低版本,不過 您也可以同時利用新版 API 的功能。例如: OpenGL ES 3.0 API 與 2.0 版的 API 具有回溯相容性,因此建議您 編寫您的應用程式,使其使用 OpenGL ES 3.0 功能;但如果使用此功能,則會改回使用 2.0 API 無法使用 3.0 API。

使用高於 應用程式資訊清單,您的應用程式應檢查裝置上可用的 API 版本。 您可以選擇以下其中一種方法:

  1. 嘗試建立較高層級的 OpenGL ES 情境 (EGLContext),並 查看結果。
  2. 建立支援的最低 OpenGL ES 結構定義,並檢查版本值。

以下程式碼範例示範如何透過建立 App Engine 檔案,檢查可用的 OpenGL ES 版本 EGLContext 並檢查結果。這個範例顯示 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() 方法傳回空值,則程式碼應建立 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 版代表超集 以及額外功能OpenGL ES 1.0/1.1 API 與 OpenGL ES 的程式設計 2.0 和 3.0 的差異很大,不建議新的應用程式使用。 開發人員在著手開發應用程式前,應審慎考量以下因素 以下 API:

  • 裝置相容性:開發人員應考量裝置類型、 客戶可用的 Android 版本和 OpenGL ES 版本。如要進一步瞭解 請參閱 OpenGL 版本及 裝置相容性一節。
  • 紋理支援 - OpenGL ES 3.0 API 充分支援紋理 。 資訊公開。2.0 API 實作項目支援 ETC1,但 這個紋理格式不支援透明度。為了執行壓縮的透明度 紋理必須使用兩個 ETC1 紋理 (在顏色和 Alpha 之間分割) 或提供資源 使用您指定裝置支援的其他壓縮格式如需更多資訊 請參閱「紋理壓縮支援」一文。

雖然相容性和材質支援可能會影響 因此,您應根據自認為提供最佳體驗的方式,挑選 OpenGL API 版本 讓使用者享有低延遲和高可用性