Android OpenGL ES 2.0 初次體驗

本文目錄


一. OpenGL ES是什么?
二. OpenGL ES的版本
三. EGL是什么棍丐?
四. 需要知道的兩個方法
五. 在Android中使用OpenGL ES的步驟
六. 例子1:簡單的程序+修改背景顏色

OpenGL ES是什么?

  • OpenGL(Open Graphics Library): 是用于渲染2D、3D矢量圖形的跨語言绍填、跨平臺的應(yīng)用程序編程接口(API),使簡單的圖形構(gòu)建出復(fù)雜的三維景象栖疑。
  • OpenGL ES(OpenGl for Embedded System):是 OpenGL三維圖形 API 的子集讨永,針對手機、PDA和游戲主機等嵌入式設(shè)備而設(shè)計遇革,簡單來說就是OpenGL在移動端的閹割版卿闹。
image.png

OpenGL ES 的版本

OpenGL ES版本 Android版本 描述
OpenGL ES1.0 Android 1.0+ OpenGL ES 1.x是針對固定硬件管線(Fixed Pipeline)的揭糕,通過它內(nèi)建的functions來設(shè)置諸如燈光、vertexes(圖形的頂點數(shù))锻霎、顏色和camera著角。
OpenGL ES2.0 Android 2.2(API 8)+ OpenGL ES 2.x是針對可編程硬件管線(Programmable Pipeline)的,不兼容OpenGL ES 1.x旋恼,需要自己動手編寫任何功能吏口。2.0相比于1.0更具靈活性,功能也更強大冰更〔玻可以自定義頂點和像素計算,可以讓表現(xiàn)方式更加準(zhǔn)確蜀细。
OpenGL ES3.0 Android 4.3(API 18)+ 向下兼容OpenGL ES 2.x舟铜,是OpenGL ES2.0的擴展,支持許多新的渲染技術(shù)奠衔、優(yōu)化和顯示質(zhì)量改進谆刨,包括引入了紋理相關(guān)的新功能,對著色語言進行了重大更新和支持著色器新功能的API特性归斤,引入了與幾何形狀規(guī)范和圖元渲染控制相關(guān)的新功能痴荐,引入了新的緩沖區(qū)對象,增添了許多與屏幕外渲染到幀緩沖區(qū)對象相關(guān)的新功能官册。
OpenGL ES3.x Android 5.0 (API 21)+ 向下兼容OpenGL ES3.0/2.0生兆,Android 5.0(API 21)和更高的版本支持這個API規(guī)范。

EGL是什么膝宁?

  • EGL (Embedded Graphics Library):EGL 是連接 OpenGL ES 和本地窗口系統(tǒng)的接口鸦难,由于OpenGL ES是跨平臺的,引入EGL就是為了屏蔽不同平臺上的區(qū)別员淫。

另外合蔽,EGL定義了控制 DisplaysContexts 以及 Surfaces 的統(tǒng)一的平臺接口介返,但一般情況在 Android 平臺上開發(fā) OpenGL ES 應(yīng)用拴事,無需直接使用javax.microedition.khronos.egl 包中的類按照EGL步驟來使用OpenGL ES繪制圖形,因為在Android平臺中提供了一個android.opengl 包圣蝎,GLSurfaceView類提供了對Display刃宵、Surface 和 Context 的管理,大大簡化了 OpenGL ES 的程序框架徘公,對應(yīng)大部分 OpenGL ES開發(fā)牲证,只需調(diào)用一個方法來設(shè)置 OpenGLView 需要的GLSurfaceView.Renderer 即可。

EGL

EGL提供如下機制

  • 與設(shè)備的原生窗口系統(tǒng)通信
  • 查詢繪圖表面的可用類型和配置
  • 創(chuàng)建繪圖表面
  • 在OpenGL ES 和其他圖形渲染API之間同步渲染
  • 管理紋理貼圖等渲染資源
  • 為了讓OpenGL ES能夠繪制在當(dāng)前設(shè)備上关面,我們需要EGL作為OpenGL ES與設(shè)備的橋梁坦袍。

需要知道的兩個方法

  • GLSurfaceView:渲染表面類(android.opengl.GLSurfaceView)十厢,自動負(fù)責(zé)管理EGL執(zhí)行步驟,但用戶需要確定針對渲染表面 OpenGL ES 的版本捂齐,即調(diào)用 setEGLContextClientVersion(int version) 方法蛮放。隨后調(diào)用 setRenderer() 方法來為OpenGLES配置渲染表面。此外還有其他的 setEGL* 方法去配置上下文環(huán)境奠宜,例如渲染表面的 RGB 顏色分量的位深筛武。

  • GLSurfaceView.Renderer:渲染器類(android.opengl.GLSurfaceView.Renderer),GLSurfaceView 需要通過渲染器對象完成實際的渲染操作挎塌,自定義渲染器對象需要繼承 Renderer 接口類,并實現(xiàn)三個方法:onSurfaceCreated()内边、onSurfaceChanged()和onDrawFrame()榴都。


在Android中使用OpenGL ES的步驟:

  1. 創(chuàng)建GLSurfaceView組件,使用 Activity 來顯示 GLSurfaceView 組件漠其。
  2. 為 GLSurfaceView 配置渲染類GLSurfaceView.Renderer嘴高,實現(xiàn)GLSurfaceView.Renderer接口并重寫3個方法。
    • onSurfaceCreated():當(dāng)Surface被第一次創(chuàng)建或從其他Activity切換回來都會調(diào)用此方法和屎,方法中還可以初始化OpenGLES圖形(背景色)拴驮。
    • onSurfaceChanged():在Surface被創(chuàng)建后,每次Surface尺寸變化柴信,還有屏幕橫豎切換都會調(diào)用此方法套啤。
    • onDrawFrame():每繪制一幀都會調(diào)用此方法,在這個方法中必須繪制點什么随常,即使只是清空屏幕潜沦。因為如果什么都沒畫,會導(dǎo)致屏幕不斷閃爍绪氛。重點:此方法是繪制圖形的主要執(zhí)行點唆鸡。
  3. 調(diào)用GLSurfaceView組件的setRenderer()方法指定Renderer對象,該Renderer對象會完成GLSurfaceView里的3D圖形的繪制枣察。

例子1:簡單的程序+修改背景顏色 OpenGLESVersion

  1. 創(chuàng)建GLSurfaceView實例争占,檢查設(shè)備版本,Activity生命周期序目,配置上下文臂痕。
  2. 創(chuàng)建Renderer類,實現(xiàn)渲染方法猿涨。
  3. 效果展示刻蟹。

1.創(chuàng)建GLSurfaceView實例

我們通過 GLSurfaceView 來初始化 OpenGLES,如配置顯示設(shè)備 Display 以及在后臺線程中渲染嘿辟。在此之前舆瘪,我們需要對設(shè)備的進行版本檢查片效,以及在 Android Activity 生命周期的維護、渲染請求方式進行配置英古。最后才會配置這個 Surface 視圖和傳入自定義 Renderer 類淀衣。

public class VersionActivity extends AppCompatActivity {

    private GLSurfaceView surfaceView;
    private boolean rendererSet = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //檢查OpenGl ES版本
        final ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();

        //獲取版本號
        int VersionNum = configurationInfo.reqGlEsVersion;

        //輸出196608 16進制=0x30000 3.0版本
        if (VersionNum >= 196608) {
            Toast.makeText(this, "OpenGLES version is 3.0 or more", Toast.LENGTH_SHORT).show();
            rendererSet = true;
            //執(zhí)行3.0版本的方法
        }
        //輸出131072 16進制=0x20000 2.0版本
        else if (VersionNum >= 131072 && VersionNum < 196608) {
            Toast.makeText(this, "OpenGLES version is 2.0", Toast.LENGTH_SHORT).show();
            rendererSet = true;
            //執(zhí)行2.0版本的方法, 配置ES 2.0的上下文
            surfaceView = new GLSurfaceView(this);
            //確定針對渲染表面 OpenGL ES 的版本
            surfaceView.setEGLContextClientVersion(2);
            //1.連續(xù)刷新頻率不停渲染召调,0.按請求來渲染
            surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
            surfaceView.setRenderer(new GLES20Renderer());

            setContentView(surfaceView);
        } else {
            Toast.makeText(this, "Current devices do not support OpenGLES", Toast.LENGTH_SHORT).show();
            return;
        }
    }
    @Override
    protected void onPause() {
        super.onPause();
        if (rendererSet) {
            surfaceView.onPause();
        }
    }
    @Override
    protected void onResume() {
        super.onResume();
        if (rendererSet) {
            surfaceView.onResume();
        }
    }
}

注意:渲染線程方式setRenderMode:
1.RENDERMODE_CONTINUOUSLY按設(shè)備刷新頻率不斷地渲染膨桥。
0.RENDERMODE_WHEN_DIRTY按請求方式來渲染。

2.創(chuàng)建Renderer類

在GLSurfaceView中傳入了一個自定義Renderer類唠叛,那么Renderer是一個渲染器只嚣,他需要重寫3個方法來實現(xiàn)渲染的整個過程。

public class GLES20Renderer implements GLSurfaceView.Renderer {
    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //第一次創(chuàng)建或切換回來都會調(diào)用此方法
        GLES20.glClearColor(0.0f, 0.0f, 1.0f, 1);
    }
    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        //每次Surface尺寸變化艺沼,比如屏幕橫豎切換都會調(diào)用此方法
        GLES20.glViewport(0, 0, width, height);
    }
    @Override
    public void onDrawFrame(GL10 gl) {
        //每繪制一幀都會調(diào)用此方法
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }
}
  • onSurfaceCreated:其中的glClearColor是設(shè)置清空屏幕用的顏色册舞,四個參數(shù):紅綠藍(lán)透明,都是float類型障般,最大值為1调鲸,最小值為0。
  • onSurfaceChanged:其中的glViewport是設(shè)置視口的尺寸挽荡,告訴OpenGLES用來顯示Surface的大小藐石。
  • onDrawFrame:其中的glClear(GL_COLOR_BUFFER_BIT)表示清空屏幕,并會用glClearColor再次填充整個屏幕定拟。

問:參數(shù)中的GL10是什么于微?
GL10是OpenGLES 1.0的API遺留下來的。但是要編寫使用OpenGLES1.0的渲染器青自,就用這個參數(shù)角雷。但是對于OpenGLES2.0就直接通過靜態(tài)方法GLES20來直接獲取。OpenGLES3.0也是直接使用GLES30性穿。

3.結(jié)果

當(dāng)運行這個Activity的時候勺三,會看到屏幕渲染上了一層藍(lán)色背景色,這也就是我們在onSurfaceCreated中設(shè)置的glClearColor方法需曾。

運行效果圖

總結(jié)

這雖然是學(xué)習(xí)OpenGLES20的第一課吗坚,只學(xué)習(xí)了GLSurfaceView和Renderer渲染器,但有了整個程序的大體框架呆万,是最接下來的學(xué)習(xí)有著大大的幫助商源。

參考文獻(xiàn)


為什么要使用OpenGL ES

通常來說谋减,計算機系統(tǒng)中 CPU牡彻、GPU 是協(xié)同工作的。CPU 計算好顯示內(nèi)容提交到 GPU,GPU 渲染完成后將渲染結(jié)果放入幀緩沖區(qū)庄吼,隨后視頻控制器會按照 VSync 信號逐行讀取幀緩沖區(qū)的數(shù)據(jù)缎除,經(jīng)過可能的數(shù)模轉(zhuǎn)換傳遞給顯示器顯示。所以总寻,盡可能讓 CPU 和 GPU 各司其職發(fā)揮作用是提高渲染效率的關(guān)鍵器罐。

正如我們之前提到過,OpenGL 正是給我們提供了訪問 GPU 的能力渐行,不僅如此轰坊,它還引入了緩存(Buffer)這個概念,大大提高了處理效率祟印。

從一個內(nèi)存區(qū)域復(fù)制到另一個內(nèi)存區(qū)域的速度是相對較慢的肴沫,并且在內(nèi)存復(fù)制的過程中,CPU 和 GPU 都不能處理這區(qū)域內(nèi)存蕴忆,避免引起錯誤颤芬。此外,CPU / GPU 執(zhí)行計算的速度是很快的孽文,而內(nèi)存的訪問是相對較慢的,這也導(dǎo)致處理器的性能處于次優(yōu)狀態(tài)夺艰,這種狀態(tài)叫做 數(shù)據(jù)饑餓芋哭,簡單來說就是空有一身本事卻無用武之地。

針對此郁副,OpenGL 為了提升渲染的性能减牺,為兩個內(nèi)存區(qū)域間的數(shù)據(jù)交換定義了緩存。緩存是指 GPU 能夠控制和管理的連續(xù) RAM存谎。程序從 CPU 的內(nèi)存復(fù)制數(shù)據(jù)到 OpenGL ES 的緩存拔疚。通過獨占緩存,GPU 能夠盡可能以有效的方式讀寫內(nèi)存既荚。 這也意味著 GPU 使用緩存中的數(shù)據(jù)工作的同時稚失,運行在 CPU 中的程序可以繼續(xù)執(zhí)行。

來源:http://linbinghe.com/2018/b8f62c8f.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恰聘,一起剝皮案震驚了整個濱河市句各,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌晴叨,老刑警劉巖凿宾,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異兼蕊,居然都是意外死亡初厚,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門孙技,熙熙樓的掌柜王于貴愁眉苦臉地迎上來产禾,“玉大人排作,你說我怎么就攤上這事∠掠” “怎么了纽绍?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長势似。 經(jīng)常有香客問我拌夏,道長,這世上最難降的妖魔是什么履因? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任障簿,我火速辦了婚禮,結(jié)果婚禮上栅迄,老公的妹妹穿的比我還像新娘站故。我一直安慰自己,他們只是感情好毅舆,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布西篓。 她就那樣靜靜地躺著,像睡著了一般憋活。 火紅的嫁衣襯著肌膚如雪岂津。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天悦即,我揣著相機與錄音吮成,去河邊找鬼。 笑死辜梳,一個胖子當(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
  • 我被黑心中介騙來泰國打工蹬敲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留暇昂,地道東北人莺戒。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像急波,于是被迫代替她去往敵國和親从铲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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