Android OpenGL 的基本使用

由于本人現(xiàn)在在公司做Android上的OpenGL圖像處理相關(guān)功能累奈,以前沒有搞過這方面的知識,所以一切只能從頭開始搞起丐膝,接下來將會慢慢分享其他方面的內(nèi)容绍赛,先用這篇比較基礎(chǔ)的文章來開頭。

一鸣个、OpenGL的作用

剛才我們談到圖像處理羞反,在做圖像處理我們不是可以用Canvas來繪制嗎,怎么還要用OpenGL那么陌生的東西來搞囤萤?為什么要用OpenGL昼窗,肯定有它的好處。

  • OpenGL的好處:手機(jī)上做圖像處理有很多方式涛舍,但是目前為止最高效的方法是有效地使用圖形處理單元澄惊,或者叫 GPU;GPU 可以集中來處理好一件事情富雅,就是并行地做浮點(diǎn)運(yùn)算掸驱。事實(shí)上,圖像處理和渲染就是在將要渲染到窗口上的像素上做許許多多的浮點(diǎn)運(yùn)算没佑。也就是說用GPU來分擔(dān)CPU的工作毕贼,提高工作效率。

二蛤奢、初始化OpenGL項(xiàng)目

接下來我們會來講解如何在Android項(xiàng)目開發(fā)過程中加入OpenGL鬼癣,在開始前我們先了解同OpenGL ES密切相關(guān)的載體:GLSurfaceView:

  • GLSurfaceView會處理OpenGL初始化過程中比較基礎(chǔ)的操作,可以配置顯示設(shè)備以及在后臺線程中渲染啤贩。渲染是在surface的特定區(qū)域中完成的扣溺,也稱為視口。

GLSurfaceView實(shí)際上為它自己創(chuàng)建一個(gè)Window瓜晤,可以當(dāng)做是在視圖層里打穿一個(gè)洞锥余,底層的OpenGL surface顯示出來,但是痢掠,它沒有動(dòng)畫或者變形特效驱犹。

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

要用OpenGL繪制嘲恍,首先要有GLSurfaceVie的實(shí)例

    private GLSurfaceView glSurfaceView;
    private boolean rendererSet = false;
    
     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        glSurfaceView = new GLSurfaceView(this);
        setContentView(glSurfaceView);
    }

2.檢查系統(tǒng)是否支持OpenGL ES 2.0

現(xiàn)在OpenGL ES版本已經(jīng)到3.0了,Android平臺上目前有1.0和2.0雄驹,我們使用的是2.0佃牛,在使用前在onCreate()方法中檢查是否支持2.0的版本并且確定使用2.0

        
        ActivityManager activityManager = 
            (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        ConfigurationInfo configurationInfo = activityManager
            .getDeviceConfigurationInfo();
       
        final boolean supportsEs2 =
            configurationInfo.reqGlEsVersion >= 0x20000
                || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1 
                 && (Build.FINGERPRINT.startsWith("generic")
                  || Build.FINGERPRINT.startsWith("unknown")
                  || Build.MODEL.contains("google_sdk") 
                  || Build.MODEL.contains("Emulator")
                  || Build.MODEL.contains("Android SDK built for x86")));

        if (supportsEs2) {
            glSurfaceView.setEGLContextClientVersion(2);            
            glSurfaceView.setRenderer(new AirHockeyRenderer(this));
            rendererSet = true;
        } else {
            Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
                Toast.LENGTH_LONG).show();
            return;
        }
        

一般我們只需要使用“configurationInfo.reqGlEsVersion >= 0x20000”,至于加后面主要是用于模擬器檢查医舆,假定模擬器支持2.0俘侠。

3.為OpenGL ES 2.0配置渲染表面

前面說到GLSurfaceView挖了一個(gè)洞,就是為了看見下面的渲染表面蔬将,同樣實(shí)在onCreate()方法中

        if (supportsEs2) {
            // Request an OpenGL ES 2.0 compatible context.
            glSurfaceView.setEGLContextClientVersion(2);

            // Assign our renderer.
            glSurfaceView.setRenderer(new FirstOpenGLProjectRenderer());
            rendererSet = true;
        } else {
            Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
                Toast.LENGTH_LONG).show();
            return;
        }        

通過setEGLContextClientVersion()方法配置surface視圖爷速,設(shè)定好使用的OpenGL版本,然后調(diào)用setRenderer()傳進(jìn)有自定義Renderer類的新實(shí)例霞怀。當(dāng)Surface創(chuàng)建或者發(fā)生變化的時(shí)候惫东,以及繪制一幅新幀時(shí),渲染器都會被GLSurfaceView調(diào)用毙石。

4.處理Android Activity生命周期的事件

GLSurfaceView的生命周期要協(xié)同好Activity的生命周期廉沮,避免造成內(nèi)存泄漏。

    @Override
    protected void onPause() {
        super.onPause();
        
        if (rendererSet) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        
        if (rendererSet) {
            glSurfaceView.onResume();
        }
    }

4.創(chuàng)建Renderer類

Renderer類也就是我們的渲染類了徐矩,它是通過實(shí)現(xiàn)Renderer接口來實(shí)現(xiàn)功能的滞时。

渲染器接口定義的方法:

  • onSurfaceCreated(GL10 glUnused, EGLConfig config):當(dāng)Surface被創(chuàng)建的時(shí)候,GLSurfaceView會調(diào)用這個(gè)方法滤灯,這發(fā)生在應(yīng)用程序創(chuàng)建的第一次漂洋,并且當(dāng)設(shè)備被喚醒或者用戶從其他activity切換回去時(shí),也會被調(diào)用力喷。
  • onSurfaceChanged(GL10 glUnused, int width, int height):在Surface創(chuàng)建以后刽漂,每次Surface尺寸變化后,這個(gè)方法都會調(diào)用
  • onDrawFrame(GL10 glUnused):當(dāng)繪制每一幀的時(shí)候會被調(diào)用弟孟。

GLSurfaceView會在單獨(dú)一條線程中調(diào)用渲染器的方法贝咙。默認(rèn)情況下,GLSurfaceView會顯示設(shè)備的刷新頻率不斷地渲染拂募,也可以配置按請求渲染庭猩,只需要設(shè)置GLSurfaceVIew.RENDERMODE_WHEN_DIRTY作為參數(shù)調(diào)用GLSurfaceView.setRenderMode()就可以。
GLSurfaceView在后臺線程進(jìn)行渲染陈症,而UI線程是在主線程中調(diào)用的蔼水,所以兩個(gè)線程間的通信可以使用如下方式,在主線程中的GLSurfaceView實(shí)例可以調(diào)用queueEvent()傳遞一個(gè)Runnable給后臺渲染線程录肯,渲染線程可以調(diào)用Activity的runOnUITHread()來傳遞事件給主線程

實(shí)現(xiàn)Renderer的接口方法

    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
        // Set the background clear color to red. The first component is
        // red, the second is green, the third is blue, and the last
        // component is alpha, which we don't use in this lesson.
        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
    }

首選在onSurfaceCreated()中調(diào)用glClearColor設(shè)置清空屏幕用的顏色趴腋,這里使用紅色。

    @Override
    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
        // Set the OpenGL viewport to fill the entire surface.
        glViewport(0, 0, width, height);
    }

設(shè)置視口的大小

    @Override
    public void onDrawFrame(GL10 glUnused) {
        // Clear the rendering surface.
        glClear(GL_COLOR_BUFFER_BIT);
    }

在onDrawFrame()中調(diào)用glClear(GL_COLOR_BUFFER_BIT)清空屏幕,會調(diào)用glClearColor中定義的顏色來填充整個(gè)屏幕优炬。通過這幾個(gè)步驟颁井,基本上就可以在GLSurfaceView繪制出東西了,在這里我只是簡單的用紅色繪制整個(gè)屏幕蠢护。

Skype_Picture.jpeg

OpenGL在Android上的使用基本上是這樣雅宾,但是,當(dāng)然沒那么簡單葵硕,在使用OpenGL進(jìn)行繪制算是比較繁瑣的過程眉抬,后面也會慢慢去揭曉其他使用方法,來構(gòu)造一幅一幅精美的特效靜/動(dòng)圖懈凹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蜀变,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蘸劈,更是在濱河造成了極大的恐慌,老刑警劉巖尊沸,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件威沫,死亡現(xiàn)場離奇詭異,居然都是意外死亡洼专,警方通過查閱死者的電腦和手機(jī)棒掠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屁商,“玉大人烟很,你說我怎么就攤上這事±猓” “怎么了雾袱?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長官还。 經(jīng)常有香客問我芹橡,道長,這世上最難降的妖魔是什么望伦? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任林说,我火速辦了婚禮,結(jié)果婚禮上屯伞,老公的妹妹穿的比我還像新娘腿箩。我一直安慰自己,他們只是感情好劣摇,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布珠移。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剑梳。 梳的紋絲不亂的頭發(fā)上唆貌,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天,我揣著相機(jī)與錄音垢乙,去河邊找鬼锨咙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛追逮,可吹牛的內(nèi)容都是我干的酪刀。 我是一名探鬼主播,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼钮孵,長吁一口氣:“原來是場噩夢啊……” “哼骂倘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起巴席,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤历涝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后漾唉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荧库,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年赵刑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了分衫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,163評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡般此,死狀恐怖蚪战,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情铐懊,我是刑警寧澤邀桑,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站科乎,受9級特大地震影響概漱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜喜喂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一瓤摧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧玉吁,春花似錦照弥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽悔常。三九已至,卻和暖如春给赞,著一層夾襖步出監(jiān)牢的瞬間机打,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工片迅, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留残邀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓柑蛇,卻偏偏與公主長得像芥挣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子耻台,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,925評論 2 344