為了在 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 系統會呼叫轉譯器中的三種方法:
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 的協助,請前往下一堂課程,看看我們還有哪些提示。