概述
這是一個系列的Android平台下OpenGl ES介紹,從最基本的使用最終到VR圖的展示的實作,屬于基礎篇。(後面針對VR視訊會再有幾篇文章,屬于進階篇)
OpenGL ES之一——概念掃盲
OpenGL ES之二——Android中的OpenGL ES概述
OpenGL ES之三——繪制純色背景
OpenGL ES之四——繪制點,線,三角形
OpenGL ES之五——相機和投影,繪制等腰三角形
OpenGL ES之六——繪制矩形和圓形
OpenGL ES之七——着色器語言GLSL
OpenGL ES之八——GLES20類和Matrix類
OpenGL ES之九——相機和投影
OpenGL ES之十——紋理貼圖(展示一張圖檔)
OpenGL ES之十一——繪制3D圖形
OpenGL ES之十二——地球儀和VR圖
本篇概述
上一篇主要想要脫離Android平台介紹一下OpenGL和OpenGL ES到底是什麼,從本篇起開始從零開始搭建自己的Android平台下OpenGL ES知識體系。
本篇的内容是Android平台中的OpenGL ES
。
一.Android基本架構中OpenGL ES
1.1 OpenGL ES在Android的基本架構中位置
如下圖,我們從Android的基本架構中找到OpenGL ES的位置。

OpenGL ES就在Libraries裡面,從中我們可知Android中自身是支援OpenGL ES的。下面看一下OpenGL ES各個版本在Android各個版本中的支援情況。
1.2 OpenGL ES各個版本在Android各個版本中的支援情況
- OpenGL ES1.0是基于OpenGL 1.3的,OpenGL ES1.1是基于OpenGL 1.5的。Android1.0和更高的版本支援這個API規範。OpenGL ES 1.x是針對固定硬體管線的。
- OpenGL ES2.0是基于OpenGL 2.0的,不相容OpenGL ES 1.x。Android 2.2(API 8)和更高的版本支援這個API規範。OpenGL ES 2.x是針對可程式設計硬體管線的。
- OpenGL ES3.0的技術特性幾乎完全來自OpenGL 3.x的,向下相容OpenGL ES 2.x。Android 4.3(API 18)及更高的版本支援這個API規範。
-
OpenGL ES3.1基本上可以屬于OpenGL 4.x的子集,向下相容OpenGL ES3.0/2.0。Android 5.0(API 21)和更高的版本支援這個API規範。
Android通過其架構API和Native Development Kit(NDK)支援OpenGL。
二.OpenGL ES在Android中涉及的關鍵類
Android架構中有兩個基礎類,可讓您使用OpenGL ES API建立和操作圖形:GLSurfaceView和 GLSurfaceView.Renderer。下面我們就來了解一下這倆類的用法。
2.1 GLSurfaceView
我們想在Android中使用OpenGL ES 的最簡單的方法就是将我們要顯示的圖像渲染到GLSurfaceView上。但是它隻是一個展示類,至于怎麼渲染到上面我們就要自己實作GLSurfaceView.Renderer來生成我們自己的渲染器進而完成渲染操作。
2.2 GLSurfaceView.Renderer
它是一個接口,裡面定義了我們需要實作的方法,如下面代碼,裡面各個要實作的方法已經注釋的很清楚了。
public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2 {
//-----------省略代碼------------
public interface Renderer {
//建立時,系統調用此方法一次,且僅一次,我們将初始化工作在這裡完成。例如設定OpenGL環境參數或初始化OpenGL圖形對象。
void onSurfaceCreated(GL10 gl, EGLConfig config);
//系統在GLSurfaceView中幾何圖形更改時調用此方法,例如視訊第一幀圖像建立或者橫豎屏切換。
void onSurfaceChanged(GL10 gl, int width, int height);
//完成繪制工作,每一幀圖像的渲染都要在此處完成。
void onDrawFrame(GL10 gl);
}
//-----------省略代碼------------
}
三.OpenGL ES使用環境配置
3.1 聲明OpenGL要求
第一:AndroidManifest.xml 清單檔案中我們添加如下的代碼,告訴系統我要使用OpenGL ES 2.0版本。
<!-- Tell the system this app requires OpenGL ES 2.0. -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
注意:如果我們想要使用更高版本的OpenGL ES以帶來更好更高效的運作,那麼我們可以将上面的版本号提高如下:
<!-- Tell the system this app requires OpenGL ES 3.0. -->
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
或者更高如下:
<!-- Tell the system this app requires OpenGL ES 3.1. -->
<uses-feature android:glEsVersion="0x00030001" android:required="true" />
直到最高版本。
第二:如果你的應用程式需要使用紋理壓縮,你還需要聲明你的應用程式需要支援哪種壓縮格式,以便他們安裝在相容的裝置上。執行個體代碼如下:
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />
更多關于紋理壓縮的知識請參看官網關于紋理壓縮的介紹,這裡不展開說明。
3.2 版本聲明之後的結果:
- 我們可以使用OpenGL ES的api了;
- 添加了上面的聲明之後,我們的應用可以安裝到不支援OpenGL ES 2.0更低系統版本的手機上,這樣一來在運作的時候就有可能崩潰掉。這就是相容性問題,那麼如何解決這個相容性問題呢?如下:
我們知道OpenGL ES 3.0 API向後相容2.0 API,那麼我們在清單檔案中設定OpenGL ES 2.0 API作為預設版本,在運作時檢查3.0 API的可用性,然後在裝置支援時使用OpenGL ES 3.0功能
。
我們知道OpenGL ES 3.0 API向後相容2.0 API,那麼我們在清單檔案中設定OpenGL ES 2.0 API作為預設版本,在運作時檢查3.0 API的可用性,然後在裝置支援時使用OpenGL ES 3.0功能
同時這裡我們也要同時考慮到我們的應用支援的最小系統版本(也就是minSdkVersion),如果我們的最小安裝版本都大于等于18(也就是OpenGL ES 3.0對應的最小Android系統版本)了,那麼我們也就可以放心的将OpenGL ES 版本設定為3.0了(例如我司的App就因必須引入網信辦的統計SDK隻能将最小版本提升到19)。
3.3 OpenGL ES版本和Android系統版本相容性處理
例如我們想檢測手機系統版本是否支援OpenGL ES 3.0,我們可以采用下面的兩種方式。
1.确定目标版本,嘗試建立更進階别的OpenGL ES上下文(EGLContext),建立成功了則表示支援,負責不支援;
2.直接建立OpenGL ES上下文(EGLContext),然後擷取支援的最低版本。
使用第一種方法的代碼如下
//設定目标版本
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) {
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, (int) glVersion,
EGL10.EGL_NONE };
//嘗試建立OpenGL ES 3.0的上下文(EGLContext)
EGLContext context = egl.eglCreateContext(
display, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
//建立成功了則支援3.0版本,沒成功則不支援
return context;
}
}
使用第二種方法
//簡單粗暴,直接得出最小支援版本
String version = gl.glGetString(GL10.GL_VERSION);
四 OpenGL ES 資料存儲
目的:之是以要在這裡介紹OpenGL ES 資料存儲,是為了後面做準備。後面每次操作着色器的時候都要自己手動調用 ByteBuffer
相關操作來為數組配置設定本地記憶體。(好這裡看不懂沒關系後面遇到,想起來這裡提過就好了)
ByteBuffer
android中的程式運作在虛拟機中的,OpenGL ES作為本地系統庫是運作在硬體上的
,虛拟機與OpenGL ES資料傳輸的方式有兩種,如下:
1.使用Java調用本地接口JNI的方式,當我們使用GLES20包裡的方法時,内部實作其實就是調用本地方法(這不用我們管)。
2…改變記憶體的配置設定方式,Java當中有個特殊的類(如ByteBuffer)集合,可以直接配置設定本地記憶體塊,并把Java的資料複制到本地記憶體,本地記憶體可以被本地環境存取,而不受垃圾回收器管控(後面我們會遇到,到時候可以回來看一下)。