OpenGL ES概述

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
  • 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)開始支持埋酬。

聲明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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罚渐,一起剝皮案震驚了整個濱河市却汉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荷并,老刑警劉巖合砂,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異源织,居然都是意外死亡翩伪,警方通過查閱死者的電腦和手機(jī)微猖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缘屹,“玉大人凛剥,你說我怎么就攤上這事∏嶙耍” “怎么了犁珠?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長互亮。 經(jīng)常有香客問我犁享,道長,這世上最難降的妖魔是什么胳挎? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任饼疙,我火速辦了婚禮,結(jié)果婚禮上慕爬,老公的妹妹穿的比我還像新娘。我一直安慰自己屏积,他們只是感情好医窿,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著炊林,像睡著了一般姥卢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渣聚,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天独榴,我揣著相機(jī)與錄音,去河邊找鬼奕枝。 笑死棺榔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的隘道。 我是一名探鬼主播症歇,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谭梗!你這毒婦竟也來了忘晤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤激捏,失蹤者是張志新(化名)和其女友劉穎设塔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體远舅,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡闰蛔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年痕钢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钞护。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盖喷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出难咕,到底是詐尸還是另有隱情课梳,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布余佃,位于F島的核電站暮刃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏爆土。R本人自食惡果不足惜椭懊,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望步势。 院中可真熱鬧氧猬,春花似錦、人聲如沸坏瘩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倔矾。三九已至妄均,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哪自,已是汗流浹背丰包。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留壤巷,地道東北人邑彪。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像隙笆,于是被迫代替她去往敵國和親锌蓄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容