OpenGL/OpenGL ES (一) —— 專業(yè)名詞快速了解
OpenGL/OpenGL ES (二) —— 渲染架構(gòu)、圖元职恳、著色器、投影
OpenGL/OpenGL ES (三) —— 繪制甜甜圈
OpenGL/OpenGL ES (四) —— 紋理
OpenGL/OpenGL ES (五) —— 紋理翻轉(zhuǎn)策略
OpenGL/OpenGL ES (六) —— 立方體旋轉(zhuǎn)
OpenGL/OpenGL ES (七) —— 初探
OpenGL/OpenGL ES (八) —— 如何加載一張圖片
OpenGL/OpenGL ES (九) —— 光照
前言
OpenGL ES 是OpenGL三維圖形API的子集,方便集成到各個(gè)平臺(tái)奢驯。OpenGL是一個(gè)跨平臺(tái)适掰、跨語(yǔ)言的應(yīng)用程序編程API估蹄。它用于繪制從簡(jiǎn)單圖形到復(fù)雜的三維景象塑煎。PC端的圖形圖像處理Kit有DirectX,這個(gè)需要開發(fā)者自己安裝的臭蚁,而GDI和GUI是可以直接調(diào)用的最铁。
相關(guān)介紹
OpenGL ES 針對(duì)那些對(duì)內(nèi)存占用要求比較高的情景使用的,因?yàn)樗饤壛薵lBegin/glEnd垮兑,四邊形(GL_QUADS)冷尉、多邊形(GL_POLYGONS)等復(fù)雜圖元等許多非絕對(duì)必要的特性。針對(duì)于手機(jī)系枪、PDA和游戲主機(jī)等嵌入式設(shè)備設(shè)計(jì)雀哨。
該API由Khronos集團(tuán)定義推廣,Khronos是一個(gè)圖形軟硬件行業(yè)協(xié)會(huì),該協(xié)會(huì)主要關(guān)注圖形和多媒體方面的開放標(biāo)準(zhǔn)雾棺。
OpenGL ES現(xiàn)在主要有兩個(gè)版本膊夹,OpenGL ES 1.x 針對(duì)固定管線硬件的,OpenGL ES 2.x 針對(duì)可編程管線硬件垢村。
OpenGL ES 1.0 是以 OpenGL 1.3 規(guī)范為基礎(chǔ)的割疾,OpenGL ES 1.1 是以 OpenGL 1.5 規(guī)范為基礎(chǔ)的,它們分別又支持 common和 common lite兩種profile嘉栓。lite profile只支持定點(diǎn)實(shí)數(shù),而common profile既支持定點(diǎn)數(shù)又支持浮點(diǎn)數(shù)拓诸。
OpenGL ES 2.0 則是參照 OpenGL 2.0 規(guī)范定義的侵佃,common profile發(fā)布于2005-8,引入了對(duì)可編程管線的支持奠支。
OpenGL ES 還有一個(gè)safety-critical profile馋辈。
OpenGL下專業(yè)名詞解析
OpenGL上下文 context
在應(yīng)用程序調(diào)用任何OpenGL的指令之前,需要先創(chuàng)建一個(gè)OpenGL的上下文context倍谜。這個(gè)上下文是一個(gè)非常龐大的狀態(tài)機(jī)迈螟,保存了OpenGL中的各種狀態(tài),這也是OpenGL指令執(zhí)行的基礎(chǔ)
OpenGL的函數(shù)不管在哪個(gè)語(yǔ)言中尔崔,都是類似C語(yǔ)言一樣的面向過程的函數(shù)答毫,本質(zhì)上都是對(duì)OpenGL上下文這個(gè)龐大的狀態(tài)機(jī)中的某個(gè)狀態(tài)或者對(duì)象進(jìn)行操作,當(dāng)然你得首先把這個(gè)對(duì)象設(shè)置為當(dāng)前對(duì)象季春。因此洗搂,通過對(duì)OpenGL指令的封裝,是可以將OpenGL的相關(guān)調(diào)用封裝成為一個(gè)面向?qū)ο蟮膱D形API
*由于OpenGL上下文是一個(gè)巨大的狀態(tài)機(jī)载弄,切換上下文往往會(huì)產(chǎn)生較大的開銷耘拇,但是不同的繪制模塊,可能需要使用完全獨(dú)立的狀態(tài)管理宇攻。因此惫叛,可以在應(yīng)用程序中分別創(chuàng)建多個(gè)不同的上下文,在不同線程中使用不同的上下文逞刷,上下文之間共享紋理嘉涌、緩沖區(qū)等資源。這樣的方案亲桥,會(huì)比反復(fù)切換上下文洛心,或者大量修改渲染狀態(tài)更加合理高效
OpenGL 狀態(tài)機(jī)
- 狀態(tài)機(jī)理論上是一種機(jī)器,它描述了一個(gè)對(duì)象在其生命周期內(nèi)所經(jīng)歷的各種狀態(tài)题篷,狀態(tài)間的轉(zhuǎn)變词身、發(fā)送轉(zhuǎn)變的動(dòng)因、條件以及轉(zhuǎn)變中所執(zhí)行的活動(dòng)番枚》ㄑ希或者說损敷,狀態(tài)機(jī)是一種行為,即對(duì)象在其生命周期中響應(yīng)事件所經(jīng)歷的狀態(tài)序列以及對(duì)那些狀態(tài)事件的響應(yīng)深啤。具有一下特點(diǎn):
1拗馒、有記憶功能,能夠記住當(dāng)前的狀態(tài)
2溯街、可以接收輸入诱桂,根據(jù)輸入的內(nèi)容和自己的原先狀態(tài),修改自己當(dāng)前狀態(tài)呈昔,并且可以有對(duì)應(yīng)輸出
3挥等、當(dāng)進(jìn)入特殊狀態(tài)(停機(jī)狀態(tài))的時(shí)候,便不再接收輸入堤尾,即停止工作
OpenGL中肝劲,狀態(tài)機(jī)可以這么理解
1、OpenGL可以記錄自己的狀態(tài)(如當(dāng)前所使用的顏色郭宝、是否開啟了混合功能等)
2辞槐、OpenGL可以接收輸入(調(diào)用OpenGL函數(shù)時(shí),可以理解成OpenGL在接收輸入)粘室,如調(diào)用glColor3f榄檬,即OpenGL接收到這個(gè)輸入后,會(huì)修改自己的“當(dāng)前顏色”這個(gè)狀態(tài)
3育特、OpenGL可以進(jìn)入停止?fàn)顟B(tài)丙号,不再接收輸入。在程序退出前缰冤,OpenGL總會(huì)先停止工作
渲染
- 將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像操作叫做渲染(Rendering)
頂點(diǎn)數(shù)組VertexArray和頂點(diǎn)緩沖區(qū)VertexBuffer
- 頂點(diǎn): 指的是在繪制一個(gè)圖形時(shí)犬缨,它的頂點(diǎn)位置數(shù)據(jù),而這個(gè)數(shù)據(jù)可以直接存粗在數(shù)組中或者將其緩存到GPU內(nèi)存中
- OpenGL中的圖像都是由圖元組成棉浸,在OpenGL ES中怀薛,有3種類型的圖元:點(diǎn)、線迷郑、三角形枝恋。開發(fā)者可以選擇設(shè)定函數(shù)指針,在調(diào)用繪制方法的時(shí)候嗡害,直接由內(nèi)存?zhèn)魅腠旤c(diǎn)數(shù)據(jù)焚碌,也就是說這部分?jǐn)?shù)據(jù)之前是存儲(chǔ)在內(nèi)存當(dāng)中的,被稱為頂點(diǎn)數(shù)組霸妹。而性能更高的做法是提前分配一塊顯存十电,將頂點(diǎn)數(shù)據(jù)預(yù)先傳入到顯存當(dāng)中,這部分的顯存,就被稱為頂點(diǎn)緩沖區(qū)
管線
- 管線:可以理解為渲染流水線鹃骂。實(shí)際上指一堆原始圖形數(shù)據(jù)途徑一個(gè)輸送管道台盯,期間經(jīng)過各種變化處理最終出現(xiàn)在屏幕的過程。
- 在OpenGL下渲染圖形畏线,就會(huì)經(jīng)歷一個(gè)一個(gè)節(jié)點(diǎn)静盅。而這樣的操作可以理解為管線∏夼梗可以想象成流水線蒿叠,每個(gè)任務(wù)類似流水線一樣執(zhí)行,任務(wù)之間有先后順序杯矩。之所以稱之為管線是因?yàn)轱@卡在處理數(shù)據(jù)的時(shí)候是按照一個(gè)固定的順序來的栈虚,而且嚴(yán)格按照這個(gè)順序。就像水從一根管子的一端留到另一端史隆,這個(gè)順序不能打破。
- 固定管線:簡(jiǎn)單理解為渲染圖像這個(gè)過程曼验,我們只能通過調(diào)用GLShaderManager類的固定管線效果實(shí)現(xiàn)一系列的著色器處理泌射。
- 可編程管線:簡(jiǎn)單理解為在處理圖形的過程,我們能夠使用自定義頂點(diǎn)著色器和片元著色器的過程鬓照。由于OpenGL的使用場(chǎng)景非常豐富熔酷,固定管線或者存儲(chǔ)著色器無法完成每一個(gè)任務(wù),這時(shí)將相關(guān)部分開放成可編程
著色器程序Shader
- 將固定渲染管線架構(gòu)變成為可編程渲染管線豺裆。因此拒秘,OpenGL在實(shí)際調(diào)用繪制函數(shù)之前,還需要指定一個(gè)由shader編譯成的著色器程序臭猜。常見的著色器主要有頂點(diǎn)著色器(VertexShader)躺酒、片段/片元著色器(FragmentShader)/像素著色器(PixelShader)、幾何著色器(GeometryShader)蔑歌、曲面細(xì)分著色器(TessellationShader)羹应。知道OpenGL ES3.0,依然只支持了頂點(diǎn)著色器和片段著色器這兩個(gè)最基礎(chǔ)的著色器
- OpenGL在處理shader時(shí)次屠,和其他編譯器一樣园匹。通過編譯、鏈接等步驟劫灶,生成了著色器程序(glProgram)裸违,著色器程序同時(shí)包含了頂點(diǎn)著色器和片元著色器的運(yùn)算邏輯。在OpenGL進(jìn)行繪制的時(shí)候本昏,首先由頂點(diǎn)著色器對(duì)傳入的頂點(diǎn)數(shù)據(jù)進(jìn)行運(yùn)算供汛。在通過圖元裝配,將頂點(diǎn)轉(zhuǎn)換為圖元。然后進(jìn)行光柵化紊馏,將圖元這種矢量圖形料饥,轉(zhuǎn)換為柵格化數(shù)據(jù)。最后朱监,將柵格化數(shù)據(jù)傳入片元著色器中進(jìn)行運(yùn)算岸啡。片元著色器會(huì)對(duì)柵格化數(shù)據(jù)中的每一個(gè)像素進(jìn)行運(yùn)算,并決定像素的顏色赫编。
頂點(diǎn)著色器VertexShader
- 一般用來處理圖形每個(gè)頂點(diǎn)變換(旋轉(zhuǎn)/平移/投影等)
- 頂點(diǎn)著色器時(shí)OpenGL中用于計(jì)算頂點(diǎn)屬性的程序巡蘸。頂點(diǎn)著色器是逐頂點(diǎn)運(yùn)算的程序,也就是說每個(gè)頂點(diǎn)數(shù)據(jù)都會(huì)執(zhí)行一次擂送。當(dāng)然這是并行悦荒,并且頂點(diǎn)著色器運(yùn)算過程中無法訪問其他頂點(diǎn)數(shù)據(jù)
- 一般來說典型的需要計(jì)算的頂點(diǎn)屬性主要包括頂點(diǎn)坐標(biāo)變換、逐頂點(diǎn)光照運(yùn)算等等嘹吨。頂點(diǎn)坐標(biāo)由自身坐標(biāo)系轉(zhuǎn)換到規(guī)范化坐標(biāo)系的運(yùn)算搬味,就是在這里發(fā)生的
片元著色器FragmentShader
一般用來處理圖形中每個(gè)像素點(diǎn)顏色計(jì)算和填充
片元著色器是OpenGL中用于計(jì)算片段(像素)顏色的程序,片元著色器是逐像素運(yùn)算的程序蟀拷,也就說每個(gè)像素都會(huì)執(zhí)行一次片元著色器碰纬,當(dāng)然也是并行的
GLSL (OpenGL Shading Language)
- OpenGL著色語(yǔ)言是用來在OpenGL中著色編碼的語(yǔ)言,也就是開發(fā)人員寫的短小的自定義程序问芬,他們是在GPU(Graphic Processor Unit圖形處理單元)上執(zhí)行的悦析,代替了固定的渲染管線的一部分,使渲染管線中不同層次具有可編程性此衅。
- GLSL的著色器代碼分成2個(gè)部分: VertexShader(頂點(diǎn)著色器) 和 Fragment Shader(片元著色器)
光柵化 Rasterization
- 光柵化就是把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為片元的過程强戴。具有將圖轉(zhuǎn)化為一個(gè)個(gè)柵格組成的圖像的作用。片元中的每一個(gè)元素對(duì)應(yīng)于幀緩沖區(qū)的一個(gè)像素
- 光柵化其實(shí)是一種將幾何圖元變?yōu)槎S圖像的過程挡鞍。該過程包含了兩部分的工作骑歹。第一部分工作:決定窗口坐標(biāo)中的哪些整型柵格區(qū)域被基本圖元占用;第二部分工作:分配一個(gè)顏色值和一個(gè)深度值到各個(gè)區(qū)域匕累。光柵化過程產(chǎn)生的是片元
- 把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏色信息轉(zhuǎn)換為屏幕上用于對(duì)應(yīng)位置的像素以及用于填充像素的顏色陵刹,這個(gè)過程稱為光柵化,這是一個(gè)將模擬信號(hào)轉(zhuǎn)化為離散信號(hào)的過程
紋理
- 紋理可以理解為圖片欢嘿。在渲染圖形時(shí)需要在其編碼填充圖片衰琐,為了使得場(chǎng)景更加逼真,而這里使用的圖片炼蹦,就是常說的紋理羡宙。在OpenGL中,更加習(xí)慣叫紋理掐隐,而不是圖片狗热。
混合 Blending
- 在測(cè)試階段之后钞馁,如果像素依然沒有被剔除,那么像素的顏色將會(huì)和幀緩沖區(qū)中顏色附著上的顏色進(jìn)行混合匿刮∩耍混合的算法可以通過OpenGL的函數(shù)進(jìn)行指定。但是OpenGL提供的混合算法有限的熟丸,如果需要更加復(fù)雜的混合算法训措,一般可以通過像素著色器進(jìn)行實(shí)現(xiàn),當(dāng)然性能會(huì)比原聲的混合算法差一些
- 混合就是把兩種顏色混在一起光羞。具體一點(diǎn)绩鸣,就是把某一像素位置原來的顏色和將要畫上去的顏色,通過某種方式混在一起纱兑,從而達(dá)到特殊的效果
變換矩陣 Transformation
- 圖形想發(fā)生平移呀闻、縮放、旋轉(zhuǎn)變換潜慎,就需要使用變換矩陣
投影矩陣 Projection
- 用于將3D坐標(biāo)轉(zhuǎn)換為二維屏幕坐標(biāo)捡多,實(shí)際線條也將在二維坐標(biāo)下進(jìn)行繪制
渲染上屏/交換緩沖區(qū) SwapBuffer
渲染緩沖區(qū)一般映射的是系統(tǒng)的資源,比如窗口铐炫。如果將圖像直接渲染到窗口對(duì)應(yīng)的緩沖區(qū)局服,則可以將圖像顯示到屏幕上。但是驳遵,值得注意的是,如果每個(gè)窗口只有一個(gè)緩沖區(qū)山涡,那么在繪制過程中堤结,屏幕進(jìn)行了刷新,窗口可能顯示出不完整的圖像鸭丛。
常規(guī)的OpenGL程序至少都會(huì)有兩個(gè)緩沖區(qū)竞穷。顯示在屏幕上的稱為屏幕緩沖區(qū),沒有顯示的稱為離屏緩沖區(qū)鳞溉。在一個(gè)緩沖區(qū)渲染完成之后瘾带,通過將屏幕緩沖區(qū)和離屏緩沖區(qū)交換,實(shí)現(xiàn)圖像在屏幕上顯示熟菲。
因?yàn)轱@示器的刷新一般是逐行進(jìn)行的看政,因此為了防止交換緩沖區(qū)的時(shí)候,屏幕上下區(qū)域的圖像分屬于兩個(gè)不同的幀抄罕,因此交換一般會(huì)等待顯示器刷新完成的信號(hào)允蚣,在顯示器兩次刷新的間隔中進(jìn)行交換,這個(gè)信號(hào)就被稱為垂直同步信號(hào)呆贿,這個(gè)技術(shù)被稱為垂直同步
使用了雙緩沖區(qū)和垂直同步技術(shù)之后嚷兔,由于總是要等待緩沖區(qū)交換之后再進(jìn)行下一幀的渲染森渐,使得幀率無法完全達(dá)到硬件允許的最高水平,為了解決這個(gè)問題冒晰,引入了三緩沖區(qū)技術(shù)同衣,在等待垂直同步時(shí),來回交替渲染兩個(gè)離屏的緩沖區(qū)壶运,而垂直同步發(fā)生時(shí)耐齐,屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)交換,實(shí)現(xiàn)充分利用硬件性能的目的