從零開(kāi)始學(xué)習(xí)OpenGL ES(1)--基礎(chǔ)概念

這篇文章主要學(xué)習(xí),如何用OpenGL ES來(lái)渲染一張圖片桐磁。

準(zhǔn)備資料

OpenGL(Open Graphics Library) 是 Khronos Group (一個(gè)圖形軟硬件行業(yè)協(xié)會(huì),該協(xié)會(huì)主要關(guān)注圖形和多媒體方面的開(kāi)放標(biāo)準(zhǔn))開(kāi)發(fā)維護(hù)的一個(gè)規(guī)范竞端,它是硬件無(wú)關(guān)的铣焊。它主要為我們定義了用來(lái)操作圖形和圖片的一系列函數(shù)的 API拢蛋,OpenGL 本身并非 API楞遏。

OpenGL ES(OpenGL for Embedded Systems) 是 OpenGL 的子集,針對(duì)手機(jī)塌碌、PDA 和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)渊胸。該規(guī)范也是由 Khronos Group 開(kāi)發(fā)維護(hù)旬盯。

OpenGL ES 去除了四邊形(GL_QUADS)台妆、多邊形(GL_POLYGONS) 等復(fù)雜圖元,以及許多非絕對(duì)必要的特性胖翰,剩下最核心有用的部分接剩。可以理解成是一個(gè)在移動(dòng)平臺(tái)上能夠支持 OpenGL 最基本功能的精簡(jiǎn)規(guī)范萨咳。

一懊缺、基本概念

1. 緩存


OpenGL ES一部分運(yùn)行在CPU上, 一部分運(yùn)行在GPU上, 為了協(xié)調(diào)這兩部分的數(shù)據(jù)交換, 定義了Buffers(緩存)的概念. CPU和GPU都有獨(dú)自控制的內(nèi)存區(qū)域, 緩存可以避免數(shù)據(jù)在這兩塊區(qū)域之間進(jìn)行復(fù)制, 提高效率

2. 紋理、渲染和紋理渲染


紋理是一個(gè)用來(lái)保存圖像顏色的元素值的緩存,
渲染是指將數(shù)據(jù)生成圖像的過(guò)程;
紋理渲染就是將保存在內(nèi)存中的顏色值等數(shù)據(jù), 生成圖像的過(guò)程

3. 坐標(biāo)系


3.1 OpenGL ES中的坐標(biāo)系

OpenGL ES中的坐標(biāo)系

OpenGL ES中的坐標(biāo)系是一個(gè)三維坐標(biāo)系, 用x,y,z來(lái)表示, 坐標(biāo)系的范圍是-1~1.
z軸的正方向指向屏幕外. 如果不考慮z軸, 左下角坐標(biāo)應(yīng)該為(-1, -1, 0), 右上角坐標(biāo)為(1,1,0).

3.2 紋理坐標(biāo)系

紋理坐標(biāo)系

紋理坐標(biāo)系是一個(gè)二維坐標(biāo)系,用s,t軸來(lái)表示, t軸為數(shù)軸., s軸為橫軸 范圍是0~1.
在坐標(biāo)系中, 點(diǎn)的橫坐標(biāo)一般用u來(lái)表示, 點(diǎn)的縱坐標(biāo)一般用v來(lái)表示. 左下角坐標(biāo)為(0, 0), 右上角坐標(biāo)為(1, 1). 在UIKit中, 左下角為(0, 1), 右上角為(1. 0)

4. 紋理的相關(guān)概念


  • 紋理元素(Texel) : 簡(jiǎn)稱紋素. 當(dāng)一個(gè)圖像初始化為一個(gè)紋理緩存后, 每個(gè)像素會(huì)變成一個(gè)紋素, 紋理的坐標(biāo)范圍是0~1, 在這個(gè)單位長(zhǎng)度內(nèi), 可能包含任意多個(gè)紋素.

  • 片段(Fragment) : 視口坐標(biāo)中的顏色像素. 沒(méi)有使用紋理時(shí), 會(huì)使用對(duì)象頂點(diǎn)來(lái)計(jì)算片段的顏色; 使用紋理時(shí), 會(huì)根據(jù)紋素來(lái)計(jì)算.

  • 光柵化(Rasterizing) : 將幾何形狀數(shù)據(jù)轉(zhuǎn)換為片段的步驟.

  • 映射(Mapping) : 對(duì)齊頂點(diǎn)和紋素的方式. 即將頂點(diǎn)坐標(biāo)(x,y,z)和紋理坐標(biāo)(u,v)對(duì)應(yīng)起來(lái).

  • 取樣(Sampling) : 在頂點(diǎn)固定后, 每個(gè)片段根據(jù)計(jì)算出來(lái)的(u, v)坐標(biāo), 去找相應(yīng)的紋素的過(guò)程.

  • 幀緩存(Frame Buffer) : 一個(gè)接收渲染結(jié)果的緩沖區(qū), 為GPU指定存儲(chǔ)渲染結(jié)果的區(qū)域.

5. 緩存的使用

在實(shí)際應(yīng)用中, 我們需要用到各種緩存. 例如, 在紋理渲染之前, 會(huì)將圖像的數(shù)據(jù)初始化為一塊紋理緩存. 這塊緩存保存了圖像的數(shù)據(jù).

使用緩存可分為以下步驟:

    1. 生成(Generate) : 生成緩存標(biāo)識(shí)符, 函數(shù): glGenBuffers().
    1. 綁定(Bind) : 為接下來(lái)的操作, 綁定一個(gè)緩存. 函數(shù): glBindBuffer().
    1. 緩存數(shù)據(jù)(Buffer Data): 從CPU的內(nèi)存復(fù)制數(shù)據(jù)到緩存的內(nèi)存中. 函數(shù): glBufferData() / glBufferSubData().
    1. 啟用(Enable) / 禁用(Disable) : 設(shè)置在接下來(lái)的渲染中是否使用緩存的數(shù)據(jù). 函數(shù): glEnableVertexAttribArray() / glDisableVertexAttribArray().
    1. 設(shè)置指針(Set Pointers) : 告知緩存的數(shù)據(jù)類型, 以及相應(yīng)數(shù)據(jù)的偏移量. 函數(shù): glVertexAttribPointer().
    1. 繪圖(Draw) : 使用緩存的數(shù)據(jù)進(jìn)行繪制. 函數(shù): glDrawArrays() / glDrawElements().
    1. 刪除(Delete) : 清空緩存, 釋放內(nèi)存. 函數(shù):glDeleteBuffers().

6. OpenGL ES上下文

OpenGL ES 是一個(gè)狀態(tài)機(jī), 相關(guān)的配置信息會(huì)保存在一個(gè)上下文(context)當(dāng)中. 這些值會(huì)被一直保存, 直到被修改.
我們也可以配置多個(gè)context, 通過(guò)調(diào)用[EAGLContext setCurrentContext:context]來(lái)進(jìn)行切換當(dāng)前context.

7. OpenGL ES 中的圖元

圖元(Primitive) 是指 OpenGL ES 中支持渲染的基本圖形. OpenGL ES 只支持三種基本圖形: 頂點(diǎn), 線段三角形. 復(fù)雜的圖形需要通過(guò)渲染多個(gè)三角形來(lái)實(shí)現(xiàn).

8. 如何去渲染三角形?

OpenGL ES渲染三角形的流程

渲染流程如上圖. 在流程中, 頂點(diǎn)著色器片段著色器都是可編程的部分. 著色器(Shader) 也是一個(gè)程序, 它們運(yùn)行在GPU上, 在主程序運(yùn)行的時(shí)候, 進(jìn)行動(dòng)態(tài)編,不用寫(xiě)死在代碼中. 編寫(xiě)著色器的語(yǔ)言是GLSL(OpenGL Shading Language) .

下面具體分析一下, 途中流程每一步都做了什么:

8.1 頂點(diǎn)數(shù)據(jù)

為了渲染一個(gè)三角形, 我們需要傳入一個(gè)包含3個(gè)三維頂點(diǎn)坐標(biāo)數(shù)組.
每個(gè)頂點(diǎn)都有對(duì)應(yīng)的頂點(diǎn)屬性, 頂點(diǎn)屬性中可以包含任何我們想要的數(shù)據(jù).

為了讓OpenGL ES知道我們需要繪制的是一個(gè)三角形, 而不是頂點(diǎn)或者線段, 我們需要在調(diào)用繪制(Draw)指令的時(shí)候, 將圖元信息傳遞給OpenGL ES

8.2 頂點(diǎn)著色器

頂點(diǎn)著色器是運(yùn)行在GPU上的一個(gè)程序, 它會(huì)對(duì)每個(gè)頂點(diǎn)執(zhí)行一次運(yùn)算. 它可以使用頂點(diǎn)數(shù)據(jù)來(lái)計(jì)算該頂點(diǎn)的顏色, 光照, 紋理, 左邊等
頂點(diǎn)著色器的一個(gè)重要任務(wù)是進(jìn)行坐標(biāo)轉(zhuǎn)換. 例如將模型的原始坐標(biāo)系(一般為三維坐標(biāo)系)轉(zhuǎn)換為屏幕坐標(biāo)系

8.3 形狀(圖元)裝配

在頂點(diǎn)著色器輸出頂點(diǎn)坐標(biāo)后, 各個(gè)頂點(diǎn)按照繪制命令中的圖元信息參數(shù), 以及頂點(diǎn)索引數(shù)組, 被組裝成一個(gè)個(gè)圖元

通過(guò)這一步, 模型中的3D圖元已經(jīng)被轉(zhuǎn)換成屏幕上的2D圖元.

8.4 幾何著色器

在OpenGL的版本中, 頂點(diǎn)著色器和片段著色器中間, 還有一個(gè)可選的著色器, 叫做幾何著色器(Geometry Shader).
幾何著色器將圖元形式的一系列頂點(diǎn)的集合作為輸入, 它可以通過(guò)產(chǎn)生新的頂點(diǎn)來(lái)構(gòu)造出新的圖元, 從而生成其他的形狀.

OpenGL ES 目前不支持幾何著色器.

8.5 光柵化

在光柵化階段, 基本圖元被轉(zhuǎn)換成供片段著色器使用的片段.
片段表示可以被渲染到屏幕上的像素, 它包含位置, 顏色值, 紋理坐標(biāo)等信息. 這些是由圖元的頂點(diǎn)信息進(jìn)行插值計(jì)算得到的.

在片段著色器運(yùn)行之前會(huì)進(jìn)行裁剪, 處于視圖以外的部分會(huì)被裁剪掉, 用來(lái)提升執(zhí)行效率.

8.6 片段著色器

片段著色器的主要作用是計(jì)算每一個(gè)片段最終的顏色值(或者是否被丟棄), 片段著色器決定了最終屏幕上每一個(gè)像素點(diǎn)的顏色值.

8.7 測(cè)試與混合

在這一步, OpenGL ES 會(huì)根據(jù)片段是否被遮擋, 視圖上是否已存在繪制好的片段等情況, 對(duì)片段進(jìn)行混合或者丟棄.
最終保留下來(lái)的片段會(huì)被寫(xiě)入幀緩存(Frame Buffer), 呈現(xiàn)在屏幕上.

9. 如何渲染多邊形?

多邊形

如圖所示培他,一個(gè)五邊形. 由于OpenGL ES 只能渲染三角形, 所以我們可以把它拆分成 3 個(gè)三角形來(lái)渲染鹃两。

渲染一個(gè)三角形,我們需要一個(gè)保存 3 個(gè)頂點(diǎn)的數(shù)組舀凛。這意味著我們渲染一個(gè)五邊形俊扳,需要用 9 個(gè)頂點(diǎn)。而且我們可以看到猛遍,其中 V0 馋记、 V2 、V3 都是重復(fù)的頂點(diǎn)懊烤,顯得有點(diǎn)冗余梯醒。

那么我們想復(fù)用這些重復(fù)的頂點(diǎn), OpenGL ES 有沒(méi)有提供方法呢?
有的.
OpenGL ES中, 對(duì)于三角形有三種渲染方式, 在給定的頂點(diǎn)數(shù)組相同的情況下, 我們可以指定我們想要的連接方式, 如下圖所示:


三角形的三種連接方式
9.1 GL_TRIANGLES

GL_TRIANGLES就是沒(méi)有復(fù)用頂點(diǎn)的方式, 以每個(gè)頂點(diǎn)繪制一個(gè)三角形, 第一個(gè)三角形使用 V0 、 V1 腌紧、V2 茸习,第二個(gè)使用 V3 、 V4 壁肋、V5 号胚,以此類推. 如果頂點(diǎn)的個(gè)數(shù)不是 3 的倍數(shù),那么最后的 1 個(gè)或者 2 個(gè)頂點(diǎn)會(huì)被舍棄.

9.2 GL_TRIANGLES_STRIP

GL_TRIANGLES_STRIP 在繪制三角形的時(shí)候墩划,會(huì)復(fù)用前兩個(gè)頂點(diǎn)涕刚。第一個(gè)三角形依然使用 V0 、 V1 乙帮、V2 杜漠,第二個(gè)則會(huì)使用 V1 、 V2 、V3驾茴,以此類推盼樟。第 n 個(gè)會(huì)使用 V(n-1) 、 V(n) 锈至、V(n+1) .

9.3 GL_TRIANGLES_FAN

GL_TRIANGLES_FAN 在繪制三角形的時(shí)候晨缴,會(huì)復(fù)用第一個(gè)頂點(diǎn)和前一個(gè)頂點(diǎn)。第一個(gè)三角形依然使用 V0 峡捡、 V1 击碗、V2 ,第二個(gè)則會(huì)使用 V0 们拙、 V2 稍途、V3,以此類推. 第 n 個(gè)會(huì)使用 V0 砚婆、 V(n) 械拍、V(n+1) 。這種方式看上去像是在繞著 V0 畫(huà)扇形.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末装盯,一起剝皮案震驚了整個(gè)濱河市坷虑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌埂奈,老刑警劉巖迄损,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異挥转,居然都是意外死亡海蔽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門绑谣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)党窜,“玉大人,你說(shuō)我怎么就攤上這事借宵』弦拢” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵壤玫,是天一觀的道長(zhǎng)豁护。 經(jīng)常有香客問(wèn)我,道長(zhǎng)欲间,這世上最難降的妖魔是什么楚里? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮猎贴,結(jié)果婚禮上班缎,老公的妹妹穿的比我還像新娘蝴光。我一直安慰自己,他們只是感情好达址,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布蔑祟。 她就那樣靜靜地躺著,像睡著了一般沉唠。 火紅的嫁衣襯著肌膚如雪疆虚。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
  • 那天满葛,我揣著相機(jī)與錄音径簿,去河邊找鬼。 笑死纱扭,一個(gè)胖子當(dāng)著我的面吹牛牍帚,可吹牛的內(nèi)容都是我干的儡遮。 我是一名探鬼主播乳蛾,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼鄙币!你這毒婦竟也來(lái)了肃叶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤十嘿,失蹤者是張志新(化名)和其女友劉穎因惭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绩衷,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹦魔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咳燕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勿决。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖招盲,靈堂內(nèi)的尸體忽然破棺而出低缩,到底是詐尸還是另有隱情,我是刑警寧澤曹货,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布咆繁,位于F島的核電站,受9級(jí)特大地震影響顶籽,放射性物質(zhì)發(fā)生泄漏玩般。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一礼饱、第九天 我趴在偏房一處隱蔽的房頂上張望坏为。 院中可真熱鬧设拟,春花似錦、人聲如沸久脯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)帘撰。三九已至跑慕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間摧找,已是汗流浹背核行。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蹬耘,地道東北人芝雪。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像综苔,于是被迫代替她去往敵國(guó)和親惩系。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348