Android OpenGL入門

我的CSDN博客同步發(fā)布:Android OpenGL入門

轉(zhuǎn)載請注明出處:【huachao1001的簡書:http://www.reibang.com/users/0a7e42698e4b/latest_articles】

如今VR這么火觉既,感覺有必要先把OpenGL學(xué)好,為以后轉(zhuǎn)VR奠定一些基礎(chǔ)埃唯。一年前纤掸,接觸過AndroidOpenGL,當(dāng)時(shí)是實(shí)現(xiàn)了在Android上顯示標(biāo)準(zhǔn)的3D文件(STL格式)∶潮希現(xiàn)在打算整理一下OpenGL相關(guān)知識试躏,后續(xù)會有相關(guān)的系列文章斩披。本文為后面文章鋪墊端姚,讓大家對OpenGL代碼編寫有個(gè)總體上的認(rèn)識晕粪。

1 檢測設(shè)備是否支持OpenGL

Android中,有個(gè)專門用于顯示OpenGL3D圖像ViewGLSurfaceView渐裸。GLSurfaceView會處理OpenGL初始化過程中比較基本的操作巫湘,如配置顯示設(shè)備,以及在后臺線程中渲染昏鹃。說的太正式了哈尚氛,其實(shí)不用太在乎它,就把它當(dāng)當(dāng)成是一個(gè)SurfaceView就好洞渤,因?yàn)槠鋵?shí)它的用法跟SurfaceView很像(然而阅嘶,它就是繼承自SurfaceView~)。

接下來開始創(chuàng)建GLSurfaceView载迄。在使用OpenGL時(shí)讯柔,我們首先得判斷當(dāng)前設(shè)備是否支持OpenGL(其實(shí)大部分手機(jī)都是支持的啦~)抡蛙,由于各種設(shè)備都可能支持Android系統(tǒng),其實(shí)還是有必要判斷一下磷杏。因?yàn)槲覀儸F(xiàn)在基本上用到的是OpenGL ES 2.0溜畅,我們要驗(yàn)證的是檢查系統(tǒng)是否實(shí)際支持2.0版本捏卓。

final ActivityManager activityManager=(ActivityManager)getSystemService(ACTIVITY_SERVICE);
final ConfigurationInfo configurationInfo=activityManager.getDeviceConfigurationInfo();
boolean supportsEs2=configurationInfo.reqGlEsVersion>=0x2000;

由于這段代碼不能很好的在模擬器上工作(GPU模擬部分有缺陷)极祸,得要稍微修改一下,使之能在模擬器上正常工作


boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;

boolean isEmulator = 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"));

supportsEs2 = supportsEs2 || isEmulator;

我們看看怎么使用GLSurfaceView吧~

private boolean supportsEs2;
private  GLSurfaceView glSurfaceView; 
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        checkSupported();

        if (supportsEs2) {
            glSurfaceView = new GLSurfaceView(this); 
            glSurfaceView.setRenderer(new GLRenderer()); 
            setContentView(glSurfaceView);
        } else {
            setContentView(R.layout.activity_main);
            Toast.makeText(this, "當(dāng)前設(shè)備不支持OpenGL ES 2.0!", Toast.LENGTH_SHORT).show();
        }
    }

  
private void checkSupported() {
        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
        supportsEs2 = configurationInfo.reqGlEsVersion >= 0x2000;

        boolean isEmulator = 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"));

        supportsEs2 = supportsEs2 || isEmulator;
}

什么怠晴?這么簡單遥金,難道這樣就能顯示3D模型?可是并沒有看到3D模型圖形在哪里八馓铩稿械!別著急,看看第9行代碼冲粤,有個(gè)setRenderer()函數(shù)美莫,里面需要傳入一個(gè)Renderer對象,那么什么是Renderer呢梯捕?前面提到GLSurfaceView是用于顯示3D模型的視圖厢呵,如果說GLSurfaceView是畫布,那么傀顾,光有一塊白紙是沒用的襟铭,得要在白紙上畫圖,通過什么畫圖呢短曾?就是接下來要說的Renderer寒砖。Renderer是一個(gè)接口,它主要包含3個(gè)抽象函數(shù):onSurfaceCreated嫉拐、onDrawFrame哩都、onSurfaceChanged;從名字就可以看出,分別是在SurfaceView創(chuàng)建時(shí)調(diào)用婉徘、在繪制圖形時(shí)調(diào)用以及在視圖大小發(fā)生改變時(shí)調(diào)用茅逮。看看我們的GLRenderer對象是怎么定義的:

/**
 * Package com.hc.opengl
 * Created by HuaChao on 2016/7/27.
 */
public class GLRenderer implements GLSurfaceView.Renderer {

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {

    }

    @Override
    public void onDrawFrame(GL10 gl) {

    }
}

這里啥也沒干判哥,所以你的屏幕上面啥都沒有~但是大致框架已經(jīng)搭建好了献雅。另外,還需要注意一點(diǎn)塌计,就是防止我們在切換程序時(shí)挺身,OpenGL還在繪制圖形導(dǎo)致程序崩潰,因此我們還需要根據(jù)Activity的生命周期針對GLSurfaceView做一些處理:

 @Override
    protected void onPause() {
        super.onPause();
        if (glSurfaceView != null) {
            glSurfaceView.onPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (glSurfaceView != null) {
            glSurfaceView.onResume();
        }
    }

ok锌仅,到目前為止章钾,這個(gè)框架算是搭建好了墙贱,接下來,讓我們把戰(zhàn)場轉(zhuǎn)移到Renderer對象上去吧贱傀!

2 Renderer顯示背景顏色

在繪制3D模型時(shí)惨撇,我們首先要對畫板的背景顏色繪制好,顏色可以隨便選府寒。glClearColor函數(shù)是設(shè)置清屏的顏色魁衙,參數(shù)分別對應(yīng)RGBA,我們設(shè)置為紅色就是glClearColor(1f, 0f, 0f, 0f);,為啥紅色是1呢株搔?而不是我們平時(shí)所熟知的255剖淀,請注意:在使用OpenGL時(shí),很多地方采用的參數(shù)變化范圍都是從0到1纤房,比如在貼紋理的時(shí)候選擇圖片區(qū)域也是[0,1]纵隔。也就是說,rgba的取值都是從0~1炮姨。然后是設(shè)置視角窗口大小glViewport捌刮,其實(shí)就是決定繪制的矩形區(qū)域的大小,當(dāng)然并不是這么簡單舒岸,后面我會詳細(xì)講绅作,目前就可以把它理解為繪制的區(qū)域,在GLSurfaceView窗口大小發(fā)生變化時(shí)我們動態(tài)改變視角窗口吁津。最后就是真正的繪制圖形啦棚蓄,我們先啥也不干,就針對畫板“刷一次油漆”碍脏,把畫板背景顏色設(shè)置為紅色梭依,glClear(GL10.GL_COLOR_BUFFER_BIT)的意思是,使用glClearColor函數(shù)所設(shè)置的顏色進(jìn)行清屏典尾。

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        gl.glClearColor(1f, 0f, 0f, 0f);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        gl.glViewport(0, 0, width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
    }

運(yùn)行一下吧役拴,是不是看到滿滿的紅色~。如果你的模擬器沒有顯示效果:請檢查“Use Host GPU”選項(xiàng)已經(jīng)勾選钾埂。如果已經(jīng)勾選河闰,那就在 glSurfaceView.setRenderer(new GLRenderer());代碼之前添加代碼:glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

設(shè)置清屏顏色

目前我們把基本框架寫好了,但是還沒有繪制模型圖像褥紫,其實(shí)姜性,我們在顯示模型時(shí),主要的工作就是集中在Renderer髓考,重寫里面的3個(gè)重要函數(shù)部念,基本上就可以把一個(gè)模型顯示出來。下一篇文章中,我們一起學(xué)習(xí)如何顯示簡單的圖形儡炼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末妓湘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子乌询,更是在濱河造成了極大的恐慌榜贴,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妹田,死亡現(xiàn)場離奇詭異唬党,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秆麸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門初嘹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來及汉,“玉大人沮趣,你說我怎么就攤上這事】浪妫” “怎么了房铭?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長温眉。 經(jīng)常有香客問我缸匪,道長,這世上最難降的妖魔是什么类溢? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任凌蔬,我火速辦了婚禮,結(jié)果婚禮上闯冷,老公的妹妹穿的比我還像新娘砂心。我一直安慰自己,他們只是感情好蛇耀,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布辩诞。 她就那樣靜靜地躺著,像睡著了一般纺涤。 火紅的嫁衣襯著肌膚如雪译暂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天撩炊,我揣著相機(jī)與錄音外永,去河邊找鬼。 笑死拧咳,一個(gè)胖子當(dāng)著我的面吹牛伯顶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼砾淌,長吁一口氣:“原來是場噩夢啊……” “哼啦撮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起汪厨,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤赃春,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后劫乱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體织中,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年衷戈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狭吼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殖妇,死狀恐怖刁笙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谦趣,我是刑警寧澤疲吸,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站前鹅,受9級特大地震影響摘悴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜舰绘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一蹂喻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捂寿,春花似錦口四、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至踱侣,卻和暖如春粪小,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背抡句。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工探膊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人待榔。 一個(gè)月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓逞壁,卻偏偏與公主長得像流济,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子腌闯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

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