建立 OpenGL ES 環境

為了在 Android 應用程式中使用 OpenGL ES 繪製圖形,您必須為這些模組建立檢視容器。其中一個更直接的方法就是實作 GLSurfaceViewGLSurfaceView.RendererGLSurfaceView 是使用 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 系統會呼叫轉譯器中的三種方法:

  • onSurfaceCreated() - 會呼叫一次,以設定檢視畫面的 OpenGL ES 環境。
  • 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);
    }
}

就是這麼簡單!上述程式碼範例建立簡單的 Android 應用程式,使用 OpenGL 顯示黑色畫面。雖然這個程式碼沒有任何功能,但透過建立這些類別,您已奠定基礎,開始使用 OpenGL 繪製圖形元素。

注意:使用 OpengGL ES 2.0 API 時,您可能會好奇這些方法具有 GL10 參數的原因。這些方法簽章只會重複用於 2.0 API,讓 Android 架構程式碼更簡潔。

如果您熟悉 OpenGL ES API,您現在應該可以在應用程式中設定 OpenGL ES 環境並開始繪圖。不過,如果您需要更多有關開始使用 OpenGL 的協助,請前往下一堂課程,看看我們還有哪些提示。