OpenGL ES
Android包含支持高性能2D和3D圖形繪制開源庫(OpenGL)哈蝇,尤其是OpenGL ES API. OpenGL是一個跨平臺的圖形API宗收,它為硬件處理3D圖形指定了一個標(biāo)準(zhǔn)的軟件接口。OpenGL ES是一種用于嵌入式設(shè)備的OpenGL規(guī)范。Android支持多個版本的OpenGL ES接口:
- OpenGL ES 1.0和1.1 - Android 1.0或更高版本所支持的API規(guī)范。
- OpenGL ES 2.0 - Android 2.2(API 8)或更高版本所支持的API規(guī)范牛曹。
- OpenGL ES 3.0 - Android 4.3(API 18)或更高版本所支持的API規(guī)范。
- OpenGL ES 3.1 - Android 5.0(API 21)或更高版本所支持的API規(guī)范醇滥。
注意:設(shè)備支持OpenGL ES 3.0 API需要設(shè)備制造商提供圖形管道的實現(xiàn)黎比。有些運行Android 4.3或更高版本的設(shè)備可能不支持OpenGL ES 3.0 API。獲取關(guān)于運行時檢查設(shè)備所支持的OpenGL版本的信息鸳玩,請繼續(xù)閱讀下文阅虫。
基礎(chǔ)(The Basics)
Android框架API和原生開發(fā)工具(NDK)都支持OpenGL。本文重點講Android框架關(guān)于OpenGL的接口不跟。獲取更多關(guān)于NDK的信息颓帝,參看Android NDK。
Android framework有兩個基礎(chǔ)類可以讓你通過OpenGL ES API創(chuàng)建和操作圖形:GLSurfaceView 和GLSurfaceView.Renderer窝革。如果想在你的Android應(yīng)用程序中使用OpenGL购城,了解如何在Activity中實現(xiàn)這些類是你的第一個目標(biāo)。
GLSurfaceView
這是一個可以使用OpenGL API方法來繪制和操作對象的View虐译,功能類似SurfaceView瘪板。你可以通過創(chuàng)建GLSurfaceView的實例并向其添加渲染器Renderer來使用這個類。但是漆诽,如果你想捕獲觸屏事件侮攀,你得將繼承GLSurfaceView類并實現(xiàn)觸摸監(jiān)聽器。OpenGL實現(xiàn)監(jiān)聽器的示例,Responding to Touch Events.
GLSurfaceView.Renderer
這個接口定義了在GLSurfaceView上繪圖所需的方法厢拭。你得在一個單獨的類提供接口的實現(xiàn)兰英,并調(diào)用GLSurfaceView.setRenderer()將其綁定到GLSurfaceView實例中。
GLSurfaceView.Renderer接口需要實現(xiàn)如下方法:
onSurfaceCreated():當(dāng)創(chuàng)建GLSurfaceView時供鸠,系統(tǒng)立即調(diào)用這個方法畦贸。通過這個方法實現(xiàn)一些需要馬上處理的事,如設(shè)置OpenGL的環(huán)境參數(shù)或初始化OpenGL繪圖對象回季。
onDrawFrame(): GLSurfaceView每次重繪時系統(tǒng)就調(diào)用這方法家制。使用此方法作為繪制(和重繪)圖形對象的主要執(zhí)行步驟。
onSurfaceChanged():當(dāng)GLSurfaceView發(fā)生幾何改變時調(diào)用這方法泡一,包括GLSurfaceView的大小或設(shè)備屏幕方向的改變。比如觅廓,當(dāng)設(shè)備從豎直方向變成水平方向時會調(diào)用這方法鼻忠。在GLSurfaceView容器中使用該方法來響應(yīng)改變。
OpenGL ES包(OpenGL ES packages)
一旦使用GLSurfaceView和GLSurfaceView.Renderer為OpenGL ES創(chuàng)建了視圖容器,你就可以開始使用如下的類調(diào)用OpenGL API:
-
OpenGL ES 1.0/1.1 API Packages
- android.opengl - 這個包為OpenGL ES1.0/1.1提供了一個比javax.microedition.khronos包更好性能靜態(tài)接口類帖蔓。
- GLES10
- GLES10Ext
- GLES11
- GLES11Ext
- javax.microedition.khronos.opengles - 這個類提供了OpenGL ES 1.0/1.1的標(biāo)準(zhǔn)實現(xiàn)矮瘟。
- GL10
- GL10Ext
- GL11
- GL11Ext
- GL11ExtensionPack
- android.opengl - 這個包為OpenGL ES1.0/1.1提供了一個比javax.microedition.khronos包更好性能靜態(tài)接口類帖蔓。
-
OpenGL ES 2.0 API Class
- android.opengl.GLES20 - 這個包為OpenGL ES 2.0提供了一些接口,Android 2.2(API 8)或更高版支持塑娇。
-
OpenGL ES 3.0/3.1 API Packages
-
android.opengl - 這個包為OpenGL ES 3.0/3.1提供了一些接口類澈侠,其中3.0版本從Android4.3(API 18)開始支持。3.1版本從Android 5.0(API 21)開始支持埋酬。
- GLES30
- GLES31
- GLES31Ext (Android Extension Pack)
如果你想用OpenGL ES馬上開始編寫一個app哨啃,請參考Displaying Graphics with OpenGL ES 類。
-
聲明OpenGL的條件(Declaring OpenGL Requirements)
如果你想在應(yīng)用程序中使用并非所有設(shè)備都有效的OpenGL特性写妥。你得在AndroidManifest.xml文件中包含這些條件拳球。這里有最常見的OpenGL聲明:
- OpenGL ES 版本條件 - 如果你的應(yīng)用程序需要一個指定版本的OpenGL ES,你必須通過在清單文件中添加如下設(shè)置來聲明這個條件:
為OpenGL ES 2.0
<!-- Tell the system this app requires OpenGL ES 2.0. -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
為OpenGL ES 3.0
<!-- Tell the system this app requires OpenGL ES 3.1. -->
<uses-feature android:glEsVersion="0x00030001" 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.x API 向后兼容2.0 API珍特,這意味著在你的應(yīng)用程序中OpenGL的實現(xiàn)可以更靈活祝峻。通過在清單文件中聲明OpenGL ES 2.0 API條件后,你可以默認(rèn)使用這個API版本扎筒,同時可以在程序運行時檢查設(shè)備是否支持Open GL ES 3.x的特性莱找,如果支持就使用OpenGL ES 3.0的特性。
- 紋理壓縮條件 - 如果你的應(yīng)用程序使用了紋理壓縮格式嗜桌,你得在清單文件中使用<supports-gl-texture>supports-gl-texture>聲明應(yīng)用程序所支持壓縮的格式奥溺。獲取更多關(guān)于紋理壓縮格式的信息,請查看本篇下文的Texture compression support.
繪制對象的映射坐標(biāo)(Mapping Coordinates For Drawn Objects)
Android設(shè)備顯示圖形的一個問題是屏幕會顯示不同的尺寸和形狀症脂。OpenGL假設(shè)一個正方形在默認(rèn)的統(tǒng)一坐標(biāo)系中谚赎,將正方形的坐標(biāo)繪制到典型的非方形屏幕上,并假使它是完全正方形的诱篷。
圖1.左邊是默認(rèn)的OpenGL坐標(biāo)系統(tǒng)壶唤,右邊用來映射的典型設(shè)備屏幕。
上圖左邊顯示OpenGL假設(shè)的統(tǒng)一坐標(biāo)棕所,右邊顯示這些坐標(biāo)如何真正的映射到水平放置的設(shè)備上闸盔。為了解決這個問題,你可以應(yīng)用OpenGL的投影模式和相機(jī)視圖轉(zhuǎn)換坐標(biāo)來使你的圖形對象在任何顯示器上都具有正確的比例琳省。
為了應(yīng)用投影和相機(jī)視圖迎吵,你可以創(chuàng)建一個投影矩陣和相機(jī)矩陣,并將它們應(yīng)用到OpenGL的渲染管道中针贬。投影矩陣通過重新計算圖形的坐標(biāo)來實現(xiàn)Android屏幕設(shè)備的正確顯示击费。相機(jī)視圖矩陣創(chuàng)建一個轉(zhuǎn)換器并根據(jù)眼睛所看到的位置渲染對象。
OpenGL ES 1.0 的投影和相機(jī)視圖(Projection and camera view in OpenGL ES 1.0)
在ES 1.0 API中桦他,你可以通過創(chuàng)建投影矩陣和相機(jī)視圖矩陣并將它們添加到OpenGL環(huán)境中來應(yīng)用投影和相機(jī)蔫巩。
1.投影矩陣 - 使用設(shè)備屏幕的幾何形狀創(chuàng)建投影矩陣,以便重新計算并以正確比例繪制對象坐標(biāo)。下面的示例代碼展示如何修改GLSurfaceView.Renderer實現(xiàn)的onSurfaceChanged()方法圆仔,實現(xiàn)根據(jù)屏幕的寬高比創(chuàng)建投影矩陣垃瞧,并將其應(yīng)用于OpenGL渲染環(huán)境中。
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
// make adjustments for screen ratio
float ratio = (float) width / height;
gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode
gl.glLoadIdentity(); // reset the matrix to its default state
gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection matrix
}
2.相機(jī)轉(zhuǎn)換矩陣 - 一旦使用投影矩陣調(diào)整好坐標(biāo)系統(tǒng)后坪郭,你還得應(yīng)用相機(jī)視圖个从。下面的示例代碼展示如何修改 GLSurfaceView.Renderer實現(xiàn)的onDrawFrame()方法,以便應(yīng)用一個視圖模型和使用GLU.gluLookAt()工具創(chuàng)建模擬相機(jī)位置的視圖轉(zhuǎn)換器歪沃。
public void onDrawFrame(GL10 gl) {
...
// Set GL_MODELVIEW transformation mode
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity(); // reset the matrix to its default state
// When using GL_MODELVIEW, you must set the camera view
GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
...
}
OpenGL ES 2.0或更高版本的投影和相機(jī)視圖
在ES 2.0 和3.0 API中嗦锐,使用投影和相機(jī)視圖,你得先添加一個矩陣成員到圖形對象的頂點著色器上绸罗。添加矩陣成員后意推,你就可以使用投影和相機(jī)視圖矩陣到你的對象了。
1.添加矩陣到頂點著色器 - 為投影矩陣創(chuàng)建一個作為著色器位置乘數(shù)的變量珊蟀。下面是頂點著色器的示例代碼菊值,其中包括允許讓你應(yīng)用投影和相機(jī)視圖矩陣到使用著色器的對象坐標(biāo)上的uMVPMatrix成員。
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";
Note:上面的示例在定點著色器中定義了一個單一的轉(zhuǎn)換矩陣成員育灸,可以將其結(jié)合投影矩陣和相機(jī)視圖矩陣應(yīng)用腻窒。取決于你的應(yīng)用程序所需,你可能想單獨地在頂點著色器中聲明投影矩陣和相機(jī)視圖矩陣成員磅崭,以便可以獨立的改變它們儿子。
2.訪問著色器矩陣 - 在頂點著色器創(chuàng)建一個hook(一個變量)之后,你就可以訪問這個變量來應(yīng)用投影和相機(jī)視圖矩陣砸喻。下面的示例代碼展示如何修改 GLSurfaceView.Renderer實現(xiàn)的onSurfaceCreated()方法柔逼,來訪問如上定義在頂點著色器中矩陣變量。
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
...
muMVPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
...
}
3.創(chuàng)建投影和相機(jī)視圖矩陣 - 生成投影和應(yīng)用于圖形對象的視圖矩陣割岛。下面的示例代碼展示如何修改 GLSurfaceView.Renderer實現(xiàn)的onSurfaceCreated()方法和onSurfaceChanged()方法愉适,實現(xiàn)創(chuàng)建相機(jī)視圖矩陣和基于設(shè)備屏幕寬高比的投影矩陣。
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
...
// Create a camera view matrix
Matrix.setLookAtM(mVMatrix, 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(mProjMatrix, 0, -ratio, ratio, -1, 1, 3, 7);
}
4.應(yīng)用投影和相機(jī)視圖矩陣 - 為了應(yīng)用投影和相機(jī)視圖轉(zhuǎn)換癣漆,將兩個矩陣相乘维咸,然后將它們設(shè)置給頂點著色器。下面的示例代碼展示如何修GLSurfaceView.Renderer實現(xiàn)的onDrawFrame()方法惠爽,來實現(xiàn)結(jié)合投影矩陣和上述代碼所創(chuàng)建的相機(jī)視圖癌蓖,然后將它們應(yīng)用于OpenGL渲染的圖形對象。
public void onDrawFrame(GL10 unused) {
...
// Combine the projection and camera view matrices
Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mVMatrix, 0);
// Apply the combined projection and camera view transformations
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);
// Draw objects
...
}
獲取OpenGL ES 2.0應(yīng)用投影和相機(jī)視圖的完整代碼婚肆,參看: Displaying Graphics with OpenGL ES類租副。
形狀面和環(huán)繞(Shape Faces and Winding)
在OpenGL中,形狀的表面由三維空間的三個點或以上定義而成较性。一組三個或以上的三維點(在OpenGL中稱為頂點)具有正面和背面附井。如何知道哪一面是正面哪一面是背面呢讨越?這是一個不錯的問題两残。答案不得不用環(huán)繞或你定義形狀的點的方向來回答永毅。
圖1.圖文的坐標(biāo)列表按逆時針繪制。
在例子中人弓,三角形的點被定義在一個逆時針方向繪制的順序中沼死。繪制這些坐標(biāo)的順序定義了形狀的環(huán)繞方向。在OpenGL中崔赌,默認(rèn)逆時針繪制的面是正面意蛀。圖1你所看到的OpenGL渲染出來的形狀是正面,其他面是背面健芭。
為什么了解哪一面是正面如此重要呢县钥?這個回答得用OpenGL常用的特性--面剔除來解釋。面剔除是OpenGL環(huán)境允許你忽略圖形背面(不需要計算和繪制背面)渲染管道慈迈,節(jié)省時間若贮、內(nèi)存還有處理周期的選項。
// enable face culling feature
gl.glEnable(GL10.GL_CULL_FACE);
// specify which faces to not draw
gl.glCullFace(GL10.GL_BACK);
如果你在不知道正面背面的情況下就使用面剔除的特性痒留,OpenGL圖形看起來可能會變形谴麦,也可能全部不顯示。所以伸头,總是以逆時針繪制順序定義你的OpenGL形狀的坐標(biāo)匾效。
Note:將OpenGL環(huán)境的順時針方向作為正面也是存在的,但是這么做會導(dǎo)致需要額外更多的代碼恤磷,以及你在需要尋求幫助的時候會讓你搞混OpenGL的開發(fā)面哼。所以不推薦這么做。
OpenGL的版本和設(shè)備兼容性
Android從1.0就支持OpenGL ES 1.0和1.1 API規(guī)范扫步。從Android 2.2(API 8)開始魔策,框架支持OpenGL ES 2.0 API規(guī)范。OpenGL ES 2.0支持大多數(shù)Android設(shè)備锌妻,所以比較推薦使用這版本開發(fā)應(yīng)用程序代乃。Android 4.3(API 18)或更高版本支持OpenGL ES 3.0 API。獲取關(guān)于Android設(shè)備支持指定版本的OpenGL ES的信息仿粹,請參閱OpenGL ES版本儀表板搁吓。
使用OpenGL ES 1.0/1.1 API與使用2.0或更高版本API開發(fā)圖形程序是非常不一樣的。1.x版本的API有更多簡便的方法和穩(wěn)定的圖形管道吭历,而OpenGL ES 2.0和3.0 API提供更多使用OpenGL取色器直接控制管道的方法堕仔。你應(yīng)該仔細(xì)考慮圖形的需求,然后選擇最適合應(yīng)用程序的API版本晌区。
OpenGL ES 3.0 API 相比2.0 API摩骨,提供了更多特性以及更好的性能表現(xiàn)通贞,同時也向后兼容。這意味著你可以編寫針對OpenGL ES 2.0的應(yīng)用程序恼五,并有條件地包括OpenGL ES 3.0圖形特性(如果可用的話)昌罩。
支持紋理壓縮(Texture compression support)
紋理壓縮通過減少內(nèi)存的使用和提高內(nèi)存帶寬使用效益來提升OpenGL應(yīng)用程序的性能。Android框架提供ETC1壓縮格式作為標(biāo)準(zhǔn)的特性灾馒,包括ETC1Util工具類和etc1tool壓縮工具(存放于本地Android SDK的tool/目錄下)茎用。
注意:ETC1格式雖然是大多數(shù)Android設(shè)備支持的格式,但是并不能保證它是有效的睬罗。通過調(diào)用 ETC1Util.isETC1Supported()方法來檢查應(yīng)用程序是否支持ETC1.
Note:ETC1紋理壓縮格式不支持透明度紋理的壓縮轨功。如果你的應(yīng)用程序有用到透明度的部分,你應(yīng)該檢查設(shè)備是否有其他的紋理壓縮格式容达。
ETC2/EAC紋理壓縮格式在OpenGL ES 3.0 API中就能保證它的有效性古涧。這種格式提供更高視覺質(zhì)量的壓縮比率,同時也支持壓縮透明度花盐。
在ETC之后羡滑,Android設(shè)備基于GPU芯片和OpenGL的實現(xiàn)實現(xiàn)了支持各種紋理壓縮格式篙骡。你應(yīng)該檢索設(shè)備所支持的紋理壓縮類型以便決定選出應(yīng)用程序應(yīng)該使用的壓縮類型本砰。為了決定你設(shè)備所支持的格式之众,您必須查詢設(shè)備并查看OpenGL擴(kuò)展名许昨,這些名稱標(biāo)識設(shè)備支持哪些紋理壓縮格式(以及其他OpenGL功能)胚吁。一些常見支持的紋理壓縮格式如下:
ATITC (ATC) - ATI紋理壓縮 (ATITC or ATC) 普遍設(shè)備有效麦撵,在沒有透明度通道的條件下琅束,支持穩(wěn)定的RGB紋理壓縮速率科展。OpenGL擴(kuò)展名表示如下:
GL_AMD_compressed_ATC_texture
GL_ATI_texture_compression_atitc
PVRTC - PowerVR 紋理壓縮 (PVRTC)普遍設(shè)備有效诈嘿,在沒有透明度通道的條件下堪旧,支持2位和4位單位像素紋理。OpenGL擴(kuò)展名表示如下:
GL_IMG_texture_compression_pvrtc
S3TC (DXTn/DXTC) - S3 紋理壓縮 (S3TC) 有幾種格式的變化 (DXT1 to DXT5) 奖亚,不太普遍. 支持有透明度管道的4位或8位紋理壓縮淳梦。OpenGL擴(kuò)展名表示如下:
-
GL_EXT_texture_compression_s3tc
一些設(shè)備只支持 DXT1格式,OpenGL擴(kuò)展名表示如下:
GL_EXT_texture_compression_dxt1
3DC - 3DC 紋理壓縮 (3DC) 不太普遍昔字,支持有透明度管道的RGB紋理. OpenGL擴(kuò)展名表示如下:
- GL_AMD_compressed_3DC_texture
注意:紋理壓縮格式并非所有設(shè)備都支持爆袍。支持這些壓縮格式因手機(jī)廠商而異。獲取關(guān)于如何在特殊設(shè)備上決定使用哪種紋理壓縮格式作郭,請繼續(xù)閱讀下文陨囊。
Note:一旦決定了你的應(yīng)用程序所要支持的紋理壓縮格式,確保在清單文件中使用<<supports-gl-texture>supports-gl-texture>來聲明它們夹攒。使用這些聲明并通過外部服務(wù)如Google Play來啟動過濾工作蜘醋,以便app只安裝到你聲明且被支持的設(shè)備上。
決定OpenGL的擴(kuò)展名(Determing OpenGL entensions)
OpenGL的實現(xiàn)在Android設(shè)備上支持的OpenGL ES API的擴(kuò)展方面有所不同咏尝。這些擴(kuò)展包含紋理壓縮压语,也包含其他OpenGL特性設(shè)置的擴(kuò)展啸罢。
要確定特定設(shè)備上支持什么紋理壓縮格式和其他OpenGL擴(kuò)展:
1.在目標(biāo)設(shè)備上運行以下代碼以確定支持哪些紋理壓縮格式:
String extensions = javax.microedition.khronos.opengles.GL10.glGetString(
GL10.GL_EXTENSIONS);
注意:這個返回結(jié)果因設(shè)備而異。你得運行在多種設(shè)備上以便獲取哪種壓縮類型是最常見的胎食。
2.回顧方法返回的結(jié)果以便確定設(shè)備支持哪種OpenGL擴(kuò)展名扰才。
Android擴(kuò)展包(AEP)
AEP確保你的應(yīng)用程序支持一套標(biāo)準(zhǔn)化的OpenGL擴(kuò)展以及一套上下文所描述的OpenGL 3.1規(guī)范。建議將一些功能一致的擴(kuò)展集成到一起來跨平臺使用斥季,這樣可以讓開發(fā)者充分使用移動設(shè)備的GPU训桶。
AEP還改進(jìn)了對圖像,著色器存儲緩沖區(qū)和片段著色器中的原子計數(shù)器的支持酣倾。
為了app使用AEP,你得在應(yīng)用程序的清單文件添加一些AEP需要的條件谤专。另外躁锡,還要對應(yīng)的平臺版本支持對它的使用。
清單文件所需對AEP的聲明如下:
<uses feature android:name="android.hardware.opengles.aep"
android:required="true" />
將FEATURE_OPENGLES_EXTENSION_PACK作為參數(shù)傳入hasSystemFeature(String)方法置侍,來確認(rèn)平臺是否支持AEP映之。如下代碼片段的演示:
boolean deviceSupportsAEP = getPackageManager().hasSystemFeature
(PackageManager.FEATURE_OPENGLES_EXTENSION_PACK);
如果方法返回true,則表明設(shè)備支持AEP。
獲取更多AEP信息蜡坊,參考 Khronos OpenGL ES Registry.
檢查OpenGL ES的版本
Android設(shè)備有幾種有效的OpenGL ES版本杠输。你可以在應(yīng)用程序的清單文件中指定最小的API版本,但是有可能你也想使用最新版本的API特性秕衙。比如蠢甲,OpenGL ES 3.0 API向后兼容2.0版本的API,所以你可以使用OpenGL ES 3.0的特性來編寫應(yīng)用程序据忘。如果3.0 API不能使用鹦牛,再繼續(xù)使用2.0的API。
在使用一個更高版本的OpenGL ES特性之前勇吊,你得在應(yīng)用程序上檢查這個版本的API是否在這個設(shè)備上有效曼追。可以有兩種方式檢查:
1.嘗試創(chuàng)建一個高版本的OpenGL ES的上下文(EGLContext)然后檢查結(jié)果汉规。
2.創(chuàng)建最低支持的OpenGL上下文并檢查版本的值礼殊。
下面的示例代碼通過創(chuàng)建EGLContext并檢查結(jié)果來檢查是否3.0 OpenGL ES版本有效。
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针史,你應(yīng)該在代碼中創(chuàng)建OpenGL ES 2.0的上下文來替代3.0然后使用這個API晶伦。
下面的代碼示例如何先通過創(chuàng)建最低支持的上下文來檢測OpenGL ES版本,然后檢查版本的字符串:
// Create a minimum supported OpenGL ES context, then check:
String version = javax.microedition.khronos.opengles.GL10.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.
使用這種方式悟民,如果你發(fā)現(xiàn)設(shè)備支持更高版本的API坝辫,你得先銷毀低版本的OpenGL ES的上下文,然后使用所支持的高版本的API創(chuàng)建一個新的上下文射亏。
選擇OpenGL API版本(Choosing an OpenGL API Version)
OpenGL ES 1.0 API 版本(以及1.1的擴(kuò)展)近忙,2.0版本以及3.0版本都為創(chuàng)建3D游戲竭业,可視化UI提供了高性能的圖形繪制接口。OpenGL ES 2.0和3.0的圖形編程有很大的相似之處及舍,3.0版本其實就是多了一些特性的2.0 版本集合庫未辆。OpenGL ES1.0/1.1的編程與OpenGL ES 2.0和3.0就相當(dāng)?shù)牟煌耍蚤_發(fā)者在開始使用這些APIs開發(fā)之前應(yīng)該仔細(xì)認(rèn)真考慮如下的因素:
性能- 通常OpenGL ES 2.0和3.0都提供了比ES 1.0/1.1更快的圖形性能锯玛。然而咐柜,由于不同的硬件廠商對OpenGL ES圖形管道的實現(xiàn),性能也因你運行OpenGL應(yīng)用程序的Android設(shè)備而異攘残。
設(shè)備兼容 - 開發(fā)者應(yīng)該考慮設(shè)備的類型拙友,Android的版本以及OpenGL ES的版本是否在他們的目標(biāo)用戶上有效。獲取更多關(guān)于OpenGL跨設(shè)備兼容的內(nèi)容歼郭,可參看上文遗契。
代碼的簡便性 - OpenGL ES 1.0/1.1 API提供了穩(wěn)定的功能管道和便利的功能,不過這些功能在OpenGL ES 2.0病曾、3.0 APIs已經(jīng)失效了牍蜂。對OpenGL ES新手的開發(fā)人員可能會發(fā)現(xiàn)版本1.0 / 1.1的編碼更快,更方便泰涂。
圖形控制 - OpenGL ES 2.0和3.0 API通過使用著色器提供完全可編程的管道來提供更高程度的控制鲫竞。通過更直接地控制圖形處理管道,開發(fā)人員可以創(chuàng)建1.0 / 1.1 API很難生成的效果逼蒙。
紋理支持 - OpenGL ES 3.0 API 擁有最好的紋理壓縮支持从绘,因為它保證了支持透明度的ETC2壓縮格式的有效性。1.x和2.0 API的實現(xiàn)通常包含ETC1的支持其做,然而顶考,紋理格式不支持透明度,所以你得針對設(shè)備提供的其他壓縮格式資源妖泄。
當(dāng)性能驹沿,兼容性,簡便性蹈胡,圖形控制以及其他因素影響了你的選擇渊季,你就應(yīng)該基于什么才是最好的用戶體驗的思想去選擇一個OpenGL API版本。
原文鏈接:https://developer.android.google.cn/guide/topics/graphics/opengl.html