1. 圖形API簡(jiǎn)介
OpenGL(Open Graphics Library)是?個(gè)跨編程語(yǔ)?言靶溜、跨平臺(tái)的編程圖形程序接?口原探,它將計(jì)算機(jī)的資源抽象稱(chēng)為?個(gè)OpenGL的對(duì)象,對(duì)這些資源的操作抽象為?個(gè)的OpenGL指令将饺。
OpenGL ES (OpenGL for Embedded Systems)是 OpenGL三維圖形 API 的?子集舰讹,針對(duì)?手機(jī)娃承、 PDA和游戲主機(jī)等嵌?入式設(shè)備?而設(shè)計(jì),去除了了許多不不必要和性能較低的API接?口桩匪。
DirectX 是由很多API組成的打瘪,DirectX并不不是?個(gè)單純的圖形API. 最重要的是DirectX是屬于 Windows上?個(gè)多媒體處理理API。并不支持Windows以外的平臺(tái)吸祟,所以不是跨平臺(tái)框架瑟慈, 按照性 質(zhì)分類(lèi),可以分為四?大部分屋匕,顯示部分葛碧、聲?音部分、輸?入部分和?網(wǎng)絡(luò)部分过吻。
Metal : Apple為游戲開(kāi)發(fā)者推出了了新的平臺(tái)技術(shù)Metal进泼,該技術(shù)能夠?yàn)?3D 圖像提?高 10 倍的渲染性能蔗衡。Metal是Apple為了了解決3D渲染?而推出的框架。
2. 圖形API?的是解決什么問(wèn)題
OpenGL /OpenGL ES/ Metal 在任何項(xiàng)?中解決問(wèn)題的本質(zhì)就是利?GPU芯?來(lái)?效渲染圖形圖像. 而圖形API 是iOS開(kāi)發(fā)者唯?接近GPU的?式.
3. OpenGL 里的一些專(zhuān)業(yè)名詞
3.1 OpenGL狀態(tài)機(jī)
狀態(tài)機(jī)可以理解為一臺(tái)機(jī)器乳绕,這臺(tái)機(jī)器可以記錄保存各種狀態(tài)绞惦、狀態(tài)之間的轉(zhuǎn)變及其原因,并根據(jù)當(dāng)前狀態(tài)進(jìn)行相應(yīng)響應(yīng)輸出洋措。
核心要點(diǎn):
1.記憶功能济蝉,保存當(dāng)前狀態(tài)
2.接收輸入,根據(jù)輸入修改當(dāng)前狀態(tài)菠发,并且可以有對(duì)應(yīng)輸出
3.當(dāng)進(jìn)?特殊狀態(tài)(停機(jī)狀態(tài))時(shí)王滤,就不再接收輸?,停?工作
3.2 OpenGL 上下? ( context )
在應(yīng)?程序調(diào)?任何OpenGL的指令之前滓鸠,需要安排?先創(chuàng)建?個(gè)OpenGL的上下?雁乡。這個(gè)上下?是?個(gè)?常龐?的狀態(tài)機(jī),保存了OpenGL中的各種狀態(tài)糜俗,這也是OpenGL指令執(zhí)?的基礎(chǔ)踱稍。
OpenGL的函數(shù)不管在哪個(gè)語(yǔ)?中,都是類(lèi)似C語(yǔ)??樣的?向過(guò)程的函數(shù)悠抹,本質(zhì)上都是對(duì)OpenGL上下?這個(gè)龐?的狀態(tài)機(jī)中的某個(gè)狀態(tài)或者對(duì)象進(jìn)?操作珠月,當(dāng)然你得?先把這個(gè)對(duì)象設(shè)置為當(dāng)前對(duì)象。因此楔敌,通過(guò)對(duì)OpenGL指令的封裝桥温,是可以將OpenGL的相關(guān)調(diào)?封裝成為?個(gè)?向?qū)ο蟮膱D形API的。
由于OpenGL上下?是?個(gè)巨?的狀態(tài)機(jī)梁丘,切換上下?往往會(huì)產(chǎn)?較?的開(kāi)銷(xiāo),但是不同的繪制模塊旺韭,可能需要使?完全獨(dú)?的狀態(tài)管理氛谜。因此,可以在應(yīng)?程序中分別創(chuàng)建多個(gè)不同的上下?区端,在不同線程中使?不同的上下?值漫,上下?之間共享紋理、緩沖區(qū)等資源织盼。這樣的?案杨何,會(huì)?反復(fù)切換上下?,或者?量修改渲染狀態(tài)沥邻,更加合理?效的危虱。
核心要點(diǎn):
1.context是OpenGL指令執(zhí)?的基礎(chǔ),其就是?個(gè)?常龐?的狀態(tài)機(jī)唐全。
2.OpenGL的函數(shù)是類(lèi)似C語(yǔ)??樣的?向過(guò)程的埃跷,可以把相關(guān)的調(diào)用封裝為面向?qū)ο蟮膱D形API蕊玷。
3.OpenGL上下文切換開(kāi)銷(xiāo)大。雖然可能使用多個(gè)上下文弥雹,但上下文之間可以通過(guò)共享紋理垃帅、緩沖區(qū)等資源,從而更加合理高效剪勿。
3.3 渲染
將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像操作叫做渲染(Rendering)贸诚。
簡(jiǎn)單來(lái)說(shuō)就是把圖?/按鈕/視頻等顯示繪制到屏幕的過(guò)程。
3.4 頂點(diǎn)數(shù)組( VertexArray ) 和 頂點(diǎn)緩沖區(qū)( VertexBuffer )
畫(huà)圖?般是先畫(huà)好圖像的?架厕吉,然后再往?架??填充顏?酱固,這對(duì)于OpenGL也是?樣的。頂點(diǎn)數(shù)據(jù)就是要畫(huà)的圖像的?架赴涵,和現(xiàn)實(shí)中不同的是媒怯,OpenGL中的圖像都是由圖元組成。在OpenGL ES中髓窜,有3種類(lèi)型的圖元:點(diǎn)扇苞、線、三?形寄纵。那這些頂點(diǎn)數(shù)據(jù)最終是存儲(chǔ)在哪?的呢鳖敷?開(kāi)發(fā)者可以選擇設(shè)定函數(shù)指針,在調(diào)?繪制?法的時(shí)候程拭,直接由內(nèi)存?zhèn)?頂點(diǎn)數(shù)據(jù)定踱,也就是說(shuō)這部分?jǐn)?shù)據(jù)之前是存儲(chǔ)在內(nèi)存當(dāng)中的,被稱(chēng)為頂點(diǎn)數(shù)組( VertexArray )恃鞋。
性能更?的做法是崖媚,提前分配?塊顯存,將頂點(diǎn)數(shù)據(jù)預(yù)先傳?到顯存當(dāng)中恤浪。這部分的顯存畅哑,就被稱(chēng)為頂點(diǎn)緩沖區(qū)( VertexBuffer )。
核心要點(diǎn):
1.頂點(diǎn)數(shù)據(jù)就是圖像的輪廓
2.共有3種類(lèi)型的圖元:點(diǎn)水由、線荠呐、三?形。
3.頂點(diǎn)數(shù)組(VertexArray)在內(nèi)存中砂客。
4.頂點(diǎn)緩沖區(qū)(VertexBuffer)在顯存中泥张。
3.5 管線
在OpenGL 下渲染圖形,就會(huì)有經(jīng)歷?個(gè)?個(gè)節(jié)點(diǎn).?這樣的操作可以理解管線.?家可以想象成流?線.每個(gè)任務(wù)類(lèi)似流?線般執(zhí)?.任務(wù)之間有先后順序. 管線是?個(gè)抽象的概念,之所以稱(chēng)之為管線是因?yàn)轱@卡在處理數(shù)據(jù)的時(shí)候是按照?個(gè)固定的順序來(lái)的鞠值,?且嚴(yán)格按照這個(gè)順序媚创。就像?從?根管?的?端流到另?端,這個(gè)順序是不能打破的
核心要點(diǎn):
任務(wù)嚴(yán)格按順序依次執(zhí)行
3.6 固定管線/存儲(chǔ)著色器
在早期的OpenGL版本彤恶,封裝了多種著色器程序塊筝野,內(nèi)置了一段包含了光照晌姚、坐標(biāo)變換、裁剪等諸多功能的固定shader程序來(lái)完成歇竟。來(lái)幫助開(kāi)發(fā)者來(lái)完成圖形的渲染挥唠。開(kāi)發(fā)者只需要傳入相應(yīng)的參數(shù),就能快速完成圖形的渲染焕议。類(lèi)似于iOS開(kāi)發(fā)會(huì)封裝很多API宝磨,而我們只需要調(diào)?,就可以實(shí)現(xiàn)功能盅安,不需要關(guān)注底層實(shí)現(xiàn)原理唤锉。
但是由于OpenGL的使?場(chǎng)景?常豐富,固定管線或存儲(chǔ)著?器?法完成每一 個(gè)業(yè)務(wù)别瞭,這時(shí)將相關(guān)部分開(kāi)放成可編程窿祥。
核心要點(diǎn):
固定管線只能提供有限的場(chǎng)景使用。由于提供的功能有限蝙寨,后期變成了可編程的形式晒衩。
3.7 著?器程序(Shader)
將固定渲染管線架構(gòu)變?yōu)榱丝删幊啼秩竟芫€。
OpenGL在實(shí)際調(diào)?繪制函數(shù)之前墙歪,還需要指定?個(gè)由shader編譯成的著色器程序听系。常見(jiàn)的著?器主要有頂點(diǎn)著?器(VertexShader),?段著?器(FragmentShader)/像素著?器(PixelShader)虹菲,幾何著?(GeometryShader)靠胜,曲?細(xì)分著?器(TessellationShader)。片段著?器和像素著?器只是在OpenGL和DX中的不同叫法而已毕源±四可惜的是,直到OpenGL ES 3.0霎褐,OpenGL ES依然只?持頂點(diǎn)著?器和片段著?器這兩個(gè)最基礎(chǔ)的著?器郑藏。
OpenGL在處理shader時(shí),和其他編譯器一樣瘩欺。通過(guò)編譯、鏈接等步驟拌牲,?成了著?器程序(glProgram)俱饿,著?器程序同時(shí)包含了頂點(diǎn)著?器和?段著?器的運(yùn)算邏輯。在OpenGL進(jìn)行繪制的時(shí)候塌忽,?先由頂點(diǎn)著?器對(duì)傳?的頂點(diǎn)數(shù)據(jù)進(jìn)?運(yùn)算拍埠。再通過(guò)圖元裝配,將頂點(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):
1.將固定渲染管線架構(gòu)變?yōu)榱丝删幊啼秩竟芫€胎围。
2.常見(jiàn)的著?器主要有頂點(diǎn)著?器,?段著?器/像素著?器德召,幾何著?白魂,曲?細(xì)分著?器。
3.OpenGL ES只?持頂點(diǎn)著?器和片段著?器上岗。
4.OpenGL通過(guò)編譯福荸、鏈接等步驟,將?成著?器程序肴掷。
5.在OpenGL進(jìn)行繪制的時(shí)候敬锐,由頂點(diǎn)著?器對(duì)傳?的頂點(diǎn)數(shù)據(jù)進(jìn)?運(yùn)算。再通過(guò)圖元裝配捆等,將頂點(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)算买窟,并決定像素的顏?。
3.7.1 頂點(diǎn)著?器 VertexShader
1.?般?來(lái)處理圖形每個(gè)頂點(diǎn)變換(旋轉(zhuǎn)/平移/投影等)
2.頂點(diǎn)著?器是OpenGL中?于計(jì)算頂點(diǎn)屬性的程序薯定。頂點(diǎn)著?器是逐頂點(diǎn)運(yùn)算的程序始绍,也就是說(shuō)每個(gè)頂點(diǎn)數(shù)據(jù)都會(huì)執(zhí)??次頂點(diǎn)著?器,當(dāng)然這是并?的话侄,并且頂點(diǎn)著?器運(yùn)算過(guò)程中?法訪問(wèn)其他頂點(diǎn)的數(shù)據(jù)
3.?般來(lái)說(shuō)典型的需要計(jì)算的頂點(diǎn)屬性主要包括頂點(diǎn)坐標(biāo)變換亏推、逐頂點(diǎn)光照運(yùn)算等等。頂點(diǎn)坐標(biāo)由?身坐標(biāo)系轉(zhuǎn)換到歸一化坐標(biāo)系的運(yùn)算年堆,就是在這里發(fā)?的吞杭。
3.7.2 ?段著?器 FragmentShader
1.?般?來(lái)處理圖形中每個(gè)像素點(diǎn)顏?計(jì)算和填充
2.?段著?器是OpenGL中?于計(jì)算?段(像素)顏?的程序。?段著?器是逐像素運(yùn)算的程序变丧,也就是說(shuō)每個(gè)像素都會(huì)執(zhí)??次?段著?器芽狗,當(dāng)然也是并?的。
3.8 GLSL(OpenGL Shading Language)
OpenGL著?語(yǔ)?(OpenGL Shading Language)是?來(lái)在OpenGL中著?編程的語(yǔ)?痒蓬,也即開(kāi)發(fā)?員寫(xiě)的短?的?定義程序童擎,他們是在圖形卡的GPU(Graphic Processor Unit圖形處理單元)上執(zhí)?的滴劲,代替了固定的渲染管線的?部分,使渲染管線中不同層次具有可編程性顾复。?如:視圖轉(zhuǎn)換班挖、投影轉(zhuǎn)換等。GLSL(GL Shading Language)的著?器代碼分成2個(gè)部分:Vertex Shader(頂點(diǎn)著?器)和Fragment(?元著?器)捕透。
3.9 光柵化Rasterization
是把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為?元的過(guò)程聪姿,具有將圖轉(zhuǎn)化為?個(gè)個(gè)柵格組成的圖象的作?,特點(diǎn)是每個(gè)元素對(duì)應(yīng)幀緩沖區(qū)中的?像素乙嘀。
光柵化就是把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為?元的過(guò)程末购。?元中的每?個(gè)元素對(duì)應(yīng)于幀緩沖區(qū)中的?個(gè)像素。
光柵化其實(shí)是?種將?何圖元變?yōu)?維圖像的過(guò)程虎谢。該過(guò)程包含了兩部分的?作盟榴。第?部分?作:決定窗?坐標(biāo)中的哪些整型柵格區(qū)域被基本圖元占?;第?部分?作:分配?個(gè)顏?值和?個(gè)深度值到各個(gè)區(qū)域婴噩。光柵化過(guò)程產(chǎn)?的是?元擎场。
把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏?信息轉(zhuǎn)換為屏幕上?于對(duì)應(yīng)位置的像素及?于填充像素的顏?,這個(gè)過(guò)程稱(chēng)為光柵化几莽,這是?個(gè)將模擬信號(hào)轉(zhuǎn)化為離散信號(hào)的過(guò)程迅办。
3.10 紋理
紋理可以理解為圖?. ?家在渲染圖形時(shí)需要在其編碼填充圖?,為了使得場(chǎng)景更加逼真.?這?使?的圖?,就是常說(shuō)的紋理.但是在OpenGL,我們更加習(xí)慣叫紋理,?不是圖?。
3.11 混合(Blending)
在測(cè)試階段之后章蚣,如果像素依然沒(méi)有被剔除站欺,那么像素的顏?將會(huì)和幀緩沖區(qū)中顏?附著上的顏色進(jìn)?混合,混合的算法可以通過(guò)OpenGL的函數(shù)進(jìn)行指定纤垂。但是OpenGL提供的混合算法有限矾策。如果需要更加復(fù)雜的混合算法,一般可以通過(guò)片段著?器進(jìn)?實(shí)現(xiàn)峭沦,當(dāng)然性能會(huì)?原?的混合算法差?些贾虽。
3.12 矩陣
3.12.1 變換矩陣(Transformation)
例如圖形想發(fā)?平移、縮放吼鱼、旋轉(zhuǎn)等變換蓬豁,就需要使用變換矩陣。
3.12.2 投影矩陣(Projection)
?于將3D坐標(biāo)轉(zhuǎn)換為?維屏幕坐標(biāo)菇肃,實(shí)際線條也將在二維坐標(biāo)下進(jìn)行繪制地粪。
3.13 渲染上屏/交換緩沖區(qū)(SwapBuffer)
渲染緩沖區(qū)?般映射的是系統(tǒng)的資源?如窗?。如果將圖像直接渲染到窗?對(duì)應(yīng)的渲染緩沖區(qū)巷送,則可以將圖像顯示到屏幕上。
但是矛辕,值得注意的是笑跛,如果每個(gè)窗?只有?個(gè)緩沖區(qū)付魔,那么在繪制過(guò)程中屏幕進(jìn)?了刷新,窗?可能顯示出不完整的圖像飞蹂。
為了解決這個(gè)問(wèn)題几苍,常規(guī)的OpenGL程序?少都會(huì)有兩個(gè)緩沖區(qū)。顯示在屏幕上的稱(chēng)為屏幕緩沖區(qū)陈哑,沒(méi)有顯示的稱(chēng)為離屏緩沖區(qū)妻坝。在?個(gè)緩沖區(qū)渲染完成之后,通過(guò)將屏幕緩沖區(qū)和離屏緩沖區(qū)交換惊窖,實(shí)現(xiàn)圖像在屏幕上的顯示刽宪。
由于顯示器的刷新?般是逐?進(jìn)?的,因此為了防?交換緩沖區(qū)的時(shí)候屏幕上下區(qū)域的圖像分屬于兩個(gè)不同的幀界酒,因此交換?般會(huì)等待顯示器刷新完成的信號(hào)圣拄,在顯示器兩次刷新的間隔中進(jìn)?交換,這個(gè)信
號(hào)就被稱(chēng)為垂直同步信號(hào)毁欣,這個(gè)技術(shù)被稱(chēng)為垂直同步庇谆。
使?了雙緩沖區(qū)和垂直同步技術(shù)之后,由于總是要等待緩沖區(qū)交換之后再進(jìn)?下?幀的渲染凭疮,使得幀率?法完全達(dá)到硬件允許的最??平饭耳。為了解決這個(gè)問(wèn)題,引?了三緩沖區(qū)技術(shù)执解,在等待垂直同步時(shí)寞肖,來(lái)回交替渲染兩個(gè)離屏的緩沖區(qū),?垂直同步發(fā)?時(shí)材鹦,屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)交換逝淹,實(shí)現(xiàn)充分利?硬件性能的?的。