圖形API簡介
OpenGL(Open Graphics Library)
是一個跨編程語言锻梳、跨平臺的編程圖形程序接口,它將計算機的資源抽象稱為一個個OpenGL的對象侧但,對這些資源的操作抽象為一個個的OpenGL指令OpenGL ES(OpenGL for Embedded Systems)
是 OpenGL 三維圖形 API 的子集露久,針對手機、PDA和游戲主機等嵌入式設(shè)備而設(shè)計朴恳,去除了許多不必要和性能較低的API接口抄罕。-
DirectX
:是由很多API組成的,DirectX并不是一個單純的圖形API. 最重要的是DirectX是屬于Windows上一個多媒體處理API.并不支持Windows以外的平臺,所以不是跨平臺框架. 按照性質(zhì)分類于颖,可以分為四大部分呆贿,顯示部分、聲音部分森渐、輸入部分和網(wǎng)絡(luò)部分.顯示部分擔(dān)任圖形處理的關(guān)鍵做入,分為DirectDraw(DDraw)和 Direct3D(D3D),前者主要負(fù)責(zé)2D圖像加速同衣。后者則主要負(fù)責(zé)3D效果的顯示竟块,比如CS中的場景和人物、FIFA中的人物等等乳怎,都是使用了DirectX的Direct3D彩郊。
聲音部分中最主要的API是DirectSound,除了播放聲音和處理混音之外蚪缀,還加強了3d音效秫逝,并提供了錄音功能
Metal
: Apple為游戲開發(fā)者推出了新的平臺技術(shù) Metal,該技術(shù)能夠為 3D 圖像提高 10 倍的渲染性能.Metal 是Apple為了解決3D渲染而推出的框架,在2014年以前蘋果一直沿用OpenGL ES 來解決底層渲染.而后開始慢慢將自身的底層框架的依賴從OpenGL ES遷移到Metal.但其核心的處理思想還是源于OpenGL ES.對于適應(yīng)于OpenGL ES的開發(fā)者而言并沒有太大的改變.
圖形API目的是解決什么問題
簡單來說就是實現(xiàn)圖形的底層渲染.
比如在游戲開發(fā)中,對于游戲場景/游戲人物的渲染
比如在音視頻開發(fā)中,對于視頻解碼后的數(shù)據(jù)渲染
比如在地圖引擎,對于地圖上的數(shù)據(jù)渲染
比如在動畫中,實現(xiàn)動畫的繪制
比如在視頻處理中,對于視頻加上濾鏡效果
等等....
OpenGL 專業(yè)名詞解析
-
OpenGL 上下文(context)
在應(yīng)用程序調(diào)用任何OpenGL的指令之前询枚,需要安排首先創(chuàng)建一個OpenGL的上下文违帆。這個上下文是一個非常龐大的狀態(tài)機,保存了OpenGL中的各種狀態(tài)金蜀,這也是OpenGL指令執(zhí)行的基礎(chǔ)刷后。
OpenGL的函數(shù)不管在哪個語言中,都是類似C語言一樣的面向過程的函數(shù)渊抄,本質(zhì)上都是對OpenGL上下文這個龐大的狀態(tài)機中的某個狀態(tài)或者對象進行操作尝胆,當(dāng)然你得首先把這個對象設(shè)置為當(dāng)前對象。因此护桦,通過對OpenGL指令的封裝含衔,是可以將OpenGL的相關(guān)調(diào)用封裝成為一個面向?qū)ο蟮膱D形API的。
由于OpenGL上下文是一個巨大的狀態(tài)機,切換上下文往往會產(chǎn)生較大的開銷贪染,但是不同的繪制模塊缓呛,可能需要使用完全獨立的狀態(tài)管理。因此杭隙,可以在應(yīng)用程序中分別創(chuàng)建多個不同的上下文哟绊,在不同線程中使用不同的上下文,上下文之間共享紋理痰憎、緩沖區(qū)等資源票髓。這樣的方案,會比反復(fù)切換上下文铣耘,或者大量修改渲染狀態(tài)炬称,更加合理高效的。
-
OpenGL 狀態(tài)機
狀態(tài)機是理論上的一種機器.這個非常難以理解.所以我們把這個狀態(tài)機這么理解.狀態(tài)機描述了一個對象在其生命周期內(nèi)所經(jīng)歷的各種狀態(tài)涡拘,狀態(tài)間的轉(zhuǎn)變玲躯,發(fā)生轉(zhuǎn)變的動因,條件及轉(zhuǎn)變中所執(zhí)行的活動鳄乏□纬担或者說,狀態(tài)機是一種行為橱野,說明對象在其生命周期中響應(yīng)事件所經(jīng)歷的狀態(tài)序列以及對那些狀態(tài)事件的響應(yīng)朽缴。因此具有以下特點:
- 有記憶功能,能記住其當(dāng)前的狀態(tài)水援;
- 可以接收輸入密强,根據(jù)輸入的內(nèi)容和自己的原先狀態(tài),修改自己當(dāng)前狀態(tài)蜗元,并且可以有對應(yīng)輸出或渤;
- 當(dāng)進入特殊狀態(tài)(停機狀態(tài))的時候,變不再接收輸入奕扣,停止工作薪鹦;
類推到OpenGL 中來,可以這么理解:
OpenGL可以記錄自己的狀態(tài)(如當(dāng)前所使用的顏色、是否開啟了混合功能等)惯豆;
OpenGL可以接收輸入(當(dāng)調(diào)用OpenGL函數(shù)的時候池磁,實際上可以看成OpenGL在接收我們的輸入),如我們調(diào)用glColor3f楷兽,則OpenGL接收到這個輸入后會修改自己的“當(dāng)前顏色”這個狀態(tài)地熄;
OpenGL可以進入停止?fàn)顟B(tài),不再接收輸入芯杀。在程序退出前端考,OpenGL總會先停止工作的银舱。
可以使用glColor*
函數(shù)來選擇一種顏色,以后繪制的所有物體都是這種顏色跛梗,除非再次使用glColor*函數(shù)
重新設(shè)定。
可以使用glTexCoord*
函數(shù)來設(shè)置一個紋理坐標(biāo)棋弥,以后繪制的所有物體都是采用這種紋理坐標(biāo)核偿,除非再次使用glTexCoord*函數(shù)
重新設(shè)置。
可以使用glBlendFunc函數(shù)
來指定混合功能的源因子和目標(biāo)因子顽染,以后繪制的所有物體都是采用這個源因子和目標(biāo)因子漾岳,除非再次使用glBlendFunc函數(shù)
重新指定。
可以使用glLight*函數(shù)
來指定光源的位置粉寞、顏色尼荆,以后繪制的所有物體都是采用這個光源的位置、顏色唧垦,除非再次使用glBlendFunc函數(shù)
重新指定捅儒。
OpenGL是一個狀態(tài)機,它保持自身的狀態(tài)振亮,除非用戶輸入一條命令讓它改變狀態(tài)巧还。
例如:
//獲取是否深度測試/混合
glIsEnabled(GL_DEPTH_TEST);
glIsEnabled(GL_BLEND);
//開啟深度測試/混合
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
//關(guān)閉深度測試/混合
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
-
渲染
將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像操作叫做渲染(Rendering).
-
頂點數(shù)組(VertexArray)和頂點緩沖區(qū)(VertexBuffer)
畫圖一般是先畫好圖像的骨架,然后再往骨架里面填充顏色坊秸,這對于OpenGL也是一樣的麸祷。頂點數(shù)據(jù)就是要畫的圖像的骨架,和現(xiàn)實中不同的是褒搔,OpenGL中的圖像都是由圖元組成阶牍。在OpenGLES中,有3種類型的圖元:點星瘾、線走孽、三角形。那這些頂點數(shù)據(jù)最終是存儲在哪里的呢琳状?開發(fā)者可以選擇設(shè)定函數(shù)指針融求,在調(diào)用繪制方法的時候,直接由內(nèi)存?zhèn)魅腠旤c數(shù)據(jù)算撮,也就是說這部分?jǐn)?shù)據(jù)之前是存儲在內(nèi)存當(dāng)中的生宛,被稱為頂點數(shù)組。而性能更高的做法是肮柜,提前分配一塊顯存陷舅,將頂點數(shù)據(jù)預(yù)先傳入到顯存當(dāng)中。這部分的顯存审洞,就被稱為頂點緩沖區(qū)莱睁。
頂點指的是我們在繪制一個圖形時,它的頂點位置數(shù)據(jù).而這個數(shù)據(jù)可以直接存儲在數(shù)組中或者將其緩存到GPU內(nèi)存中.
-
管線
在OpenGL 下渲染圖形,就會有經(jīng)歷一個一個節(jié)點.而這樣的操作可以理解管線.大家可以想象成流水線.每個任務(wù)類似流水線般執(zhí)行.任務(wù)之間有先后順序. 管線是一個抽象的概念待讳,之所以稱之為管線是因為顯卡在處理數(shù)據(jù)的時候是按照一個固定的順序來的,而且嚴(yán)格按照這個順序仰剿。就像水從一根管子的一端流到另一端创淡,這個順序是不能打破的
-
固定管線/存儲著色器
在早期的OpenGL 版本,它封裝了很多種著色器程序塊內(nèi)置的一段包含了光照、坐標(biāo)變換南吮、裁剪等等諸多功能的固定shader程序來完成,來幫助開發(fā)者來完成圖形的渲染. 而開發(fā)者只需要傳入相應(yīng)的參數(shù),就能快速完成圖形的渲染. 類似于iOS開發(fā)會封裝很多API,而我們只需要調(diào)用,就可以實現(xiàn)功能.不需要關(guān)注底層實現(xiàn)原理.
但是由于OpenGL 的使用場景非常豐富,固定管線或存儲著色器無法完成每一個業(yè)務(wù).這時將相關(guān)部分開放成可編程.
-
著色器程序Shader
就全面的將固定渲染管線架構(gòu)變?yōu)榱丝删幊啼秩竟芫€琳彩。因此,OpenGL在實際調(diào)用繪制函數(shù)之前部凑,還需要指定一個由shader編譯成的著色器程序露乏。常見的著色器主要有頂點著色器(VertexShader),片段著色器(FragmentShader)涂邀,像素著色器(PixelShader)瘟仿,幾何著色器(GeometryShader),曲面細(xì)分著色器(TessellationShader)比勉。片段著色器和像素著色器只是在OpenGL和DX中的不同叫法而已劳较。可惜的是浩聋,直到OpenGLES 3.0兴想,依然只支持了頂點著色器和片段著色器這兩個最基礎(chǔ)的著色器。
OpenGL在處理shader時赡勘,和其他編譯器一樣嫂便。通過編譯、鏈接等步驟闸与,生成了著色器程序(glProgram)毙替,著色器程序同時包含了頂點著色器和片段著色器的運算邏輯。在OpenGL進行繪制的時候践樱,首先由頂點著色器對傳入的頂點數(shù)據(jù)進行運算厂画。再通過圖元裝配,將頂點轉(zhuǎn)換為圖元拷邢。然后進行光柵化袱院,將圖元這種矢量圖形,轉(zhuǎn)換為柵格化數(shù)據(jù)瞭稼。最后忽洛,將柵格化數(shù)據(jù)傳入片段著色器中進行運算。片段著色器會對柵格化數(shù)據(jù)中的每一個像素進行運算环肘,并決定像素的顏色
-
頂點著色器VertexShader
一般用來處理圖形每個頂點變換(旋轉(zhuǎn)/平移/投影等)
頂點著色器是OpenGL中用于計算頂點屬性的程序欲虚。頂點著色器是逐頂點運算的程序,也就是說每個頂點數(shù)據(jù)都會執(zhí)行一次頂點著色器悔雹,當(dāng)然這是并行的复哆,并且頂點著色器運算過程中無法訪問其他頂點的數(shù)據(jù)欣喧。
一般來說典型的需要計算的頂點屬性主要包括頂點坐標(biāo)變換、逐頂點光照運算等等梯找。頂點坐標(biāo)由自身坐標(biāo)系轉(zhuǎn)換到歸一化坐標(biāo)系的運算唆阿,就是在這里發(fā)生的。
-
片元著色器程序FragmentShader
一般用來處理圖形中每個像素點顏色計算和填充
片段著色器是OpenGL中用于計算片段(像素)顏色的程序锈锤。片段著色器是逐像素運算的程序驯鳖,也就是說每個像素都會執(zhí)行一次片段著色器,當(dāng)然也是并行的牙咏。 -
GLSL(OpenGL Shading Language)
OpenGL著色語言(OpenGL Shading Language)是用來在OpenGL中著色編程的語言,也即開發(fā)人員寫的短小的自定義程序嘹裂,他們是在圖形卡的GPU (Graphic Processor Unit圖形處理單元)上執(zhí)行的妄壶,代替了固定的渲染管線的一部分,使渲染管線中不同層次具有可編程性寄狼。比如:視圖轉(zhuǎn)換丁寄、投影轉(zhuǎn)換等。GLSL(GL Shading Language)的著色器代碼分成2個部分:Vertex Shader(頂點著色器)和Fragment(片斷著色器)泊愧。
-
光柵化Rasterization
是把頂點數(shù)據(jù)轉(zhuǎn)換為片元的過程伊磺,具有將圖轉(zhuǎn)化為一個個柵格組成的圖象的作用,特點是每個元素對應(yīng)幀緩沖區(qū)中的一像素删咱。
光柵化就是把頂點數(shù)據(jù)轉(zhuǎn)換為片元的過程屑埋。片元中的每一個元素對應(yīng)于幀緩沖區(qū)中的一個像素。
光柵化其實是一種將幾何圖元變?yōu)槎S圖像的過程痰滋。該過程包含了兩部分的工作摘能。第一部分工作:決定窗口坐標(biāo)中的哪些整型柵格區(qū)域被基本圖元占用;第二部分工作:分配一個顏色值和一個深度值到各個區(qū)域敲街。光柵化過程產(chǎn)生的是片元团搞。
把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏色信息轉(zhuǎn)換為屏幕上用于對應(yīng)位置的像素及用于填充像素的顏色,這個過程稱為光柵化多艇,這是一個將模擬信號轉(zhuǎn)化為離散信號的過程逻恐。
-
紋理
紋理可以理解為圖片. 大家在渲染圖形時需要在其編碼填充圖片,為了使得場景更加逼真.而這里使用的圖片,就是常說的紋理.但是在OpenGL,我們更加習(xí)慣叫紋理,而不是圖片.
-
混合(Blending)
在測試階段之后,如果像素依然沒有被剔除峻黍,那么像素的顏色將會和幀緩沖區(qū)中顏色附著上的顏色進行混合复隆,混合的算法可以通過OpenGL的函數(shù)進行指定。但是OpenGL提供的混合算法是有限的姆涩,如果需要更加復(fù)雜的混合算法昏名,一般可以通過像素著色器進行實現(xiàn),當(dāng)然性能會比原生的混合算法差一些阵面。
-
變換矩陣(Transformation)
例如圖形想發(fā)生平移,縮放,旋轉(zhuǎn)變換.就需要使用變換矩陣.
-
投影矩陣Projection
用于將3D坐標(biāo)轉(zhuǎn)換為二維屏幕坐標(biāo),實際線條也將在二維坐標(biāo)下進行繪制.
-
渲染上屏/交換緩沖區(qū)(SwapBuffer)
渲染緩沖區(qū)一般映射的是系統(tǒng)的資源比如窗口轻局。如果將圖像直接渲染到窗口對應(yīng)的渲染緩沖區(qū)洪鸭,則可以將圖像顯示到屏幕上。
但是仑扑,值得注意的是览爵,如果每個窗口只有一個緩沖區(qū),那么在繪制過程中屏幕進行了刷新镇饮,窗口可能顯示出不完整的圖像蜓竹。
為了解決這個問題,常規(guī)的OpenGL程序至少都會有兩個緩沖區(qū)储藐。顯示在屏幕上的稱為屏幕緩沖區(qū)俱济,沒有顯示的稱為離屏緩沖區(qū)。在一個緩沖區(qū)渲染完成之后钙勃,通過將屏幕緩沖區(qū)和離屏緩沖區(qū)交換蛛碌,實現(xiàn)圖像在屏幕上的顯示。
由于顯示器的刷新一般是逐行進行的辖源,因此為了防止交換緩沖區(qū)的時候屏幕上下區(qū)域的圖像分屬于兩個不同的幀蔚携,因此交換一般會等待顯示器刷新完成的信號,在顯示器兩次刷新的間隔中進行交換克饶,這個信號就被稱為垂直同步信號酝蜒,這個技術(shù)被稱為垂直同步。
使用了雙緩沖區(qū)和垂直同步技術(shù)之后矾湃,由于總是要等待緩沖區(qū)交換之后再進行下一幀的渲染亡脑,使得幀率無法完全達到硬件允許的最高水平。為了解決這個問題邀跃,引入了三緩沖區(qū)技術(shù)远豺,在等待垂直同步時,來回交替渲染兩個離屏的緩沖區(qū)坞嘀,而垂直同步發(fā)生時躯护,屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)交換,實現(xiàn)充分利用硬件性能的目的丽涩。