配置 OpenGL ES 的環(huán)境

本篇文章屬于 使用 OpenGL ES 進(jìn)行圖形繪制 這個(gè)系列的第一篇文章拳魁,主要內(nèi)容是介紹在 Android 應(yīng)用使用 OpenGL ES 時(shí)需要配置的開發(fā)環(huán)境和整體流程說明京革。

要在 Android 應(yīng)用中使用 OpenGL ES 繪制圖像栈源,我們必須為它們創(chuàng)建一個(gè) View 容器合是。一種比較直接的方法是實(shí)現(xiàn) GLSurfaceView 類和 GLSurfaceView.Renderer 類厨诸。其中 GLSurfaceView 是一個(gè)視圖容器身诺,它用來存放使用 OpenGL 繪制的圖形蜜托,而 GLSurfaceView.Renderer 則用來控制在該視圖內(nèi)容的繪制(渲染器)。關(guān)于這兩個(gè)類的更多信息霉赡,可以閱讀 OpenGL ES 開發(fā)手冊(cè)橄务。

Note: GLSurfaceView 是一個(gè) View container,用來存放繪制的圖像穴亏。
GLSurfaceView.Renderer 是用來控制 View 中繪制的內(nèi)容的渲染器蜂挪。

使用 GLSurfaceView 是一種將 OpenGL ES 集成到應(yīng)用中的方法之一。對(duì)于一個(gè)全屏的或者接近全屏的圖形 View嗓化,使用它是一個(gè)理想的選擇棠涮。開發(fā)者如果希望把 OpenGL ES 的圖形集成在布局的一小部分里面,那么可以考慮使用 TextureView刺覆。對(duì)于喜歡自己動(dòng)手實(shí)現(xiàn)的開發(fā)者來說严肪,還可以通過使用
SurfaceView 搭建一個(gè) OpenGL ES View,但這將需要編寫更多的代碼。

下面將展示如何在一個(gè) Activity 中完成 GLSurfaceViewGLSurfaceView.Renderer 的最簡(jiǎn)單直接的實(shí)現(xiàn)驳糯。

1. 1 在 Manifest 配置文件中聲明使用 OpenGL ES

為了讓應(yīng)用能夠使用 OpenGL ES 2.0 接口篇梭,我們必須將下列聲明添加到 Manifest 配置文件當(dāng)中:

<!--0x00020000 代表使用 OpenGL ES 2.0 接口-->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />

如果應(yīng)用要使用紋理壓縮(Texture Compression),則必須聲明對(duì)紋理壓縮格式的支持酝枢,這樣確保應(yīng)用僅安裝在可以兼容的設(shè)備上:

<!--紋理壓縮格式格式聲明-->
<supports-gl-texture android:name="GL_OES_compressed_ETC1_RGB8_texture" />
<supports-gl-texture android:name="GL_OES_compressed_paletted_texture" />

紋理壓縮通過減少內(nèi)存需求并更有效地利用內(nèi)存帶寬恬偷,可以顯著提高 OpenGL 應(yīng)用程序的性能。更多關(guān)于紋理壓縮的內(nèi)容可以閱讀 OpenGL 開發(fā)手冊(cè) 帘睦。

1.2 為 OpenGL ES 圖形創(chuàng)建一個(gè) Activity

使用 OpenGL ES 的 Android 應(yīng)用跟其它類型的應(yīng)用主要的區(qū)別體現(xiàn)在 Activity 布局內(nèi)容上的差異袍患。通常我們會(huì)使用 TextViewButton等已經(jīng)封裝好的控件官脓。而如果使用 OpenGL ES 的我們就得依賴 GLSurfaceView 來自己實(shí)現(xiàn)了协怒。

所以最簡(jiǎn)單的使用方式是直接創(chuàng)建一個(gè) GLSurfaceView 實(shí)例,并把它作為 ContentView 設(shè)置到 Activity 中卑笨。

public class OpenGLSample01Activity extends AppCompatActivity {

    GLSurfaceView mGLSurfaceView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle("OpenGLSample01");

        // Create a GLSurfaceView instance and set it
        // as the ContentView for this Activity.
        mGLSurfaceView = new MyGLSurfaceView(this);
        setContentView(mGLSurfaceView);
    }
}

OpenGL ES 2.0 需要Android 2.2(API Level 8)或更高版本的系統(tǒng)孕暇,所以確保你的Android項(xiàng)目的 API 版本滿足該要求。

1.3 構(gòu)建一個(gè) GLSurfaceView 對(duì)象

GLSurfaceView 是一種比較特殊的 View赤兴,我們可以在該 View 中繪制 OpenGL ES 圖形妖滔,不過它自己并不做太多和繪制圖形相關(guān)的任務(wù)。繪制對(duì)象的任務(wù)是由你在該 View 中配置的 GLSurfaceView.Renderer 所控制的桶良。因此在實(shí)際開發(fā)中不建議直接使用 GLSurfaceView 來創(chuàng)建實(shí)例座舍。

事實(shí)上,GLSurfaceView 的核心代碼非常簡(jiǎn)短陨帆,你可能會(huì)直接創(chuàng)建一個(gè)未經(jīng)修改的 GLSurfaceView 實(shí)例曲秉,不過請(qǐng)不要這么做,因?yàn)槲覀冃枰^承該類來捕捉觸控事件疲牵,這方面知識(shí)會(huì)在 響應(yīng)觸摸事件 中做進(jìn)一步的介紹承二。

class MyGLSurfaceView extends GLSurfaceView {

    private final MyGLRenderer mRenderer;

    public MyGLSurfaceView(Context context){
        super(context);

        // Create an OpenGL ES 2.0 context
        setEGLContextClientVersion(2);

        mRenderer = new MyGLRenderer();

        // Set the Renderer for drawing on the GLSurfaceView
        setRenderer(mRenderer);
    }
}

另一個(gè)對(duì)于 GLSurfaceView 的可選選項(xiàng)是將渲染模式設(shè)置為:GLSurfaceView.RENDERMODE_WHEN_DIRTY,其含義是僅在你的繪制數(shù)據(jù)發(fā)生變化時(shí)才在視圖中進(jìn)行繪制操作:

// Render the view only when there is a change in the drawing data
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

如果選用這一配置選項(xiàng)纲爸,那么除非調(diào)用了 requestRender()亥鸠,否則 GLSurfaceView 不會(huì)被重新繪制,這樣做可以讓應(yīng)用的性能及效率得到提高识啦。

1.4 構(gòu)建一個(gè)渲染器類

在一個(gè)使用 OpenGL ES 的應(yīng)用中负蚊,必定少不了 GLSurfaceView.Renderer 類的實(shí)現(xiàn)。該類會(huì)控制和其相關(guān)聯(lián)的 GLSurfaceView 的繪制行為和內(nèi)容颓哮,Renderer 這個(gè)類中有三個(gè)方法會(huì)被系統(tǒng)調(diào)用家妆,所以需要實(shí)現(xiàn)下面三個(gè)方法:

  • onSurfaceCreated():調(diào)用一次,用來配置 View 的 OpenGL ES 環(huán)境冕茅。
  • onDrawFrame():每次重新繪制View時(shí)被調(diào)用伤极。
  • onSurfaceChanged():如果View的幾何形態(tài)發(fā)生變化時(shí)會(huì)被調(diào)用腰鬼,例如當(dāng)設(shè)備的屏幕方向發(fā)生改變時(shí)。

下面是一個(gè)非乘芑模基本的 OpenGL ES 渲染器的實(shí)現(xiàn),它僅僅在GLSurfaceView 中畫一個(gè)黑色的背景:

public class MyGLRenderer implements GLSurfaceView.Renderer {

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // Set the background frame color
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    }

    public void onDrawFrame(GL10 unused) {
        // Redraw background color
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
        GLES20.glViewport(0, 0, width, height);
    }
}

通過上述代碼姜挺,我們完成一個(gè)完整的 OpenGL ES 簡(jiǎn)單使用場(chǎng)景齿税,程序運(yùn)行起來會(huì)是一個(gè)黑色的背景。

下面來簡(jiǎn)單回顧一下在應(yīng)用中使用 OpenGL ES 的整個(gè)流程:

  • 在 Manifest 中對(duì)使用 OpenGL ES 進(jìn)行聲明
  • 給 OpenGL ES 繪制的圖像創(chuàng)建 Activity
  • 創(chuàng)建一個(gè) GLSurfaceView 對(duì)象并設(shè)置到 Activity 中
  • 創(chuàng)建一個(gè) Renderer 類實(shí)現(xiàn)繪制邏輯炊豪,并設(shè)置到 GLSurfaceView

文章中所有的代碼示例都已放在 Github 上凌箕,可以去項(xiàng)目 OpenGL-ES-Learning 中查看 。

通過基于上面的內(nèi)容词渤,相信你對(duì)于如何使用 OpenGL 繪制圖形有了基本的認(rèn)識(shí)和鋪墊牵舱。當(dāng)然,這些都是相當(dāng)基礎(chǔ)的知識(shí)缺虐,如果你對(duì) OpenGL ES 接口很熟悉芜壁,那么你現(xiàn)在就可以在應(yīng)用中構(gòu)建一個(gè) OpenGL ES 的環(huán)境并繪制圖形了。如果你希望獲取更多關(guān)于 OpenGL 的內(nèi)容高氮,請(qǐng)繼續(xù)看后面的內(nèi)容慧妄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末饱普,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子状共,更是在濱河造成了極大的恐慌套耕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件口芍,死亡現(xiàn)場(chǎng)離奇詭異箍铲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)鬓椭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門颠猴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人小染,你說我怎么就攤上這事翘瓮。” “怎么了裤翩?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵资盅,是天一觀的道長(zhǎng)调榄。 經(jīng)常有香客問我,道長(zhǎng)呵扛,這世上最難降的妖魔是什么每庆? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮今穿,結(jié)果婚禮上缤灵,老公的妹妹穿的比我還像新娘。我一直安慰自己蓝晒,他們只是感情好腮出,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著芝薇,像睡著了一般胚嘲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上洛二,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天馋劈,我揣著相機(jī)與錄音,去河邊找鬼灭红。 笑死侣滩,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的变擒。 我是一名探鬼主播君珠,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼娇斑!你這毒婦竟也來了策添?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤毫缆,失蹤者是張志新(化名)和其女友劉穎唯竹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體苦丁,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浸颓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了旺拉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片产上。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛾狗,靈堂內(nèi)的尸體忽然破棺而出晋涣,到底是詐尸還是另有隱情,我是刑警寧澤沉桌,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布谢鹊,位于F島的核電站算吩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏佃扼。R本人自食惡果不足惜偎巢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望兼耀。 院中可真熱鬧艘狭,春花似錦、人聲如沸翠订。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)尽超。三九已至,卻和暖如春梧躺,著一層夾襖步出監(jiān)牢的瞬間似谁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工掠哥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留巩踏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓续搀,卻偏偏與公主長(zhǎng)得像塞琼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子禁舷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

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