在日常的圖形、音視頻開(kāi)發(fā)中湃望,我們都會(huì)不可避免的使用到圖形API
换衬,來(lái)實(shí)現(xiàn)圖形的底層渲染:
- 比如在游戲開(kāi)發(fā)中,對(duì)于游戲場(chǎng)景/游戲人物的渲染
- 比如在?視頻開(kāi)發(fā)中证芭,對(duì)于視頻解碼后的數(shù)據(jù)渲染
- 比如在地圖引擎瞳浦,對(duì)于地圖上的數(shù)據(jù)渲染
- 比如在動(dòng)畫(huà)中,實(shí)現(xiàn)動(dòng)畫(huà)的繪制
- 比如在視頻處理中废士,對(duì)于視頻加上濾鏡效果
常見(jiàn)的OpenGL /OpenGL ES/ Metal/ DirectX
技術(shù)的本質(zhì)就是利用GPU
芯片來(lái)高效的渲染圖形圖像叫潦。
圖形渲染的相關(guān)技術(shù)
OpenGL (Open Graphics Library)
,翻譯為開(kāi)放圖形庫(kù)或者開(kāi)放式圖形庫(kù)官硝,是用于渲染2D矗蕊、3D矢量圖形的跨語(yǔ)言、跨平臺(tái)的應(yīng)用程序編程接口(API)
氢架。常用于CAD
傻咖、虛擬現(xiàn)實(shí)、科學(xué)可視化程序和電子游戲開(kāi)發(fā)岖研。OpenGL ES (OpenGL for Embedded Systems)
是OpenGL
三維圖形API的?集卿操,針對(duì)手機(jī)、PDA和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)孙援,去除了許多不必要和性能較低的API接口害淤,比如去除了glBegin/glEnd
,四邊形(GL_QUADS)
拓售、多邊形GL_POLYGONS
等復(fù)雜圖元窥摄。DirectX (Direct eXtension,簡(jiǎn)稱DX)
是由微軟公司創(chuàng)建的多媒體編程接口邻辉,是一種應(yīng)用程序接口溪王。DirectX
可以讓以windows
為平臺(tái)的游戲或多媒體程序獲得更高的執(zhí)行效率腮鞍,加強(qiáng)3D圖形和聲音效果,并提供設(shè)計(jì)人員一個(gè)共同的硬件驅(qū)動(dòng)標(biāo)準(zhǔn)莹菱,讓游戲開(kāi)發(fā)者不必為每一品牌的硬件來(lái)寫(xiě)不同的驅(qū)動(dòng)程序移国,也降低用戶安裝及設(shè)置硬件的復(fù)雜度。按照性質(zhì)分類道伟,可以分為四大部分迹缀,顯示部分、聲音部分蜜徽、輸入部分和網(wǎng)絡(luò)部分祝懂。Metal
是Apple
為游戲開(kāi)發(fā)者推出了新的平臺(tái)技術(shù),用于為3D 圖像提高渲染性能拘鞋,它是一種低層次的渲染應(yīng)用程序編程接口砚蓬,提供了軟件所需的最低層,保證軟件可以運(yùn)行在不同的圖形芯片上盆色。
OpenGL
專業(yè)詞匯
context
OpenGL
上下文灰蛙,在應(yīng)?程序調(diào)?任何OpenGL
的指令之前,首先需要?jiǎng)?chuàng)建?個(gè)OpenGL
的上下文隔躲。這個(gè)上下?是?個(gè)?常龐?的狀態(tài)機(jī)摩梧,保存了OpenGL
中的各種狀態(tài),這也是OpenGL
指令執(zhí)?的基礎(chǔ)宣旱。
OpenGL
的函數(shù)不管在哪個(gè)語(yǔ)?中仅父,都是類似C語(yǔ)?一樣的面向過(guò)程的函數(shù)。本質(zhì)上都是對(duì)OpenGL
上下?這個(gè)龐?的狀態(tài)機(jī)中的某個(gè)狀態(tài)或者對(duì)象進(jìn)行操作浑吟。通過(guò)對(duì)OpenGL
指令的封裝笙纤,可以將OpenGL
的相關(guān)調(diào)?封裝成為?個(gè)?向?qū)ο蟮膱D形API
。
由于OpenGL
上下?是?個(gè)巨?的狀態(tài)機(jī)买置,切換上下文往往會(huì)產(chǎn)生較?的開(kāi)銷粪糙,但是不同的繪制模塊,可能需要使?完全獨(dú)立的狀態(tài)管理忿项。因此蓉冈,可以在應(yīng)?程序中分別創(chuàng)建多個(gè)不同的上下文,在不同線程中使?不同的上下文轩触,上下?之間共享紋理寞酿、緩沖區(qū)等資源。這樣的方案脱柱,會(huì)比反復(fù)切換上下?伐弹,或者?量修改渲染狀態(tài),更加合理高效榨为。
狀態(tài)機(jī)
OpenGL
狀態(tài)機(jī)描述了一個(gè)對(duì)象在其生命周期內(nèi)所經(jīng)歷的各種狀態(tài)惨好,狀態(tài)間的轉(zhuǎn)變煌茴,發(fā)生轉(zhuǎn)變的原因,條件及轉(zhuǎn)變中所執(zhí)?的活動(dòng)日川。具有以下特點(diǎn):
- 有記憶功能蔓腐,能記住當(dāng)前的狀態(tài)
- 可以接收輸入,根據(jù)輸入的內(nèi)容和?己的原先狀態(tài)龄句,修改?己當(dāng)前狀態(tài)回论,并且可以有對(duì)應(yīng)輸出
- 當(dāng)進(jìn)?特殊狀態(tài)(停機(jī)狀態(tài))的時(shí)候,不再接收輸入分歇,停?工作
render
渲染傀蓉,將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成3D空間圖像的操作。
頂點(diǎn)數(shù)組&&頂點(diǎn)緩沖區(qū)
頂點(diǎn)數(shù)據(jù)指的是我們?cè)诶L制一個(gè)圖形時(shí)职抡,它的頂點(diǎn)位置數(shù)據(jù)葬燎。而這個(gè)數(shù)據(jù)可以直接存儲(chǔ)在數(shù)組中或者將其緩存到GPU
內(nèi)存中。OpenGL
中的圖像都是由圖元組成缚甩,在OpenGL
中萨蚕,有3種類型的圖元:點(diǎn)、線蹄胰、三?角形。開(kāi)發(fā)者可以選擇設(shè)定函數(shù)指針奕翔,在調(diào)?用繪制?法的時(shí)候裕寨,直接由內(nèi)存?zhèn)魅腠旤c(diǎn)數(shù)據(jù),也就是說(shuō)這部分?jǐn)?shù)據(jù)之前是存儲(chǔ)在內(nèi)存當(dāng)中的派继,被稱為頂點(diǎn)數(shù)組宾袜。?性能更高的做法是,提前分配?塊顯存驾窟,將頂點(diǎn)數(shù)據(jù)預(yù)先傳?到顯存當(dāng)中庆猫。這部分的顯存,就被稱為頂點(diǎn)緩沖區(qū)绅络。
管線
管線(pipeline)
月培,可以理解為渲染流水線,實(shí)際上指的是一堆原始圖形數(shù)據(jù)途經(jīng)一個(gè)輸送管道恩急,期間經(jīng)過(guò)各種變化處理最終出現(xiàn)在屏幕的過(guò)程杉畜。
固定管線
在渲染圖像的過(guò)程中,只能固定管線效果實(shí)現(xiàn)著色器處理衷恭。比如說(shuō)只包含了光照此叠、坐標(biāo)變換、裁剪等功能的固定程序随珠。
著?器程序Shader
將固定渲染管線架構(gòu)變?yōu)榱丝删幊啼秩竟芫€灭袁。OpenGL
在實(shí)際調(diào)?繪制函數(shù)之前猬错,還需要指定?個(gè)由shader
編譯成的著色器程序。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)算铺呵,并決定像素的顏?裹驰。
常見(jiàn)的著?器主要有頂點(diǎn)著?器(VertexShader)
,?段著?器(FragmentShader)
/像素著?器(PixelShader)
片挂,幾何著?器(GeometryShader)
幻林,曲?細(xì)分著?器(TessellationShader)
。
頂點(diǎn)著?器VertexShader
頂點(diǎn)著?器是OpenGL
中用于計(jì)算頂點(diǎn)屬性的程序音念。頂點(diǎn)著?器是挨個(gè)頂點(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ù)整葡。一般?來(lái)處理圖形每個(gè)頂點(diǎn)變換(旋轉(zhuǎn)、平移讥脐、投影等)遭居。
?段著?器(FragmentShader)
片段著?器是OpenGL
中用于計(jì)算片段(像素)顏色的程序。?段著?器是逐像素運(yùn)算的程序攘烛,也就是說(shuō)每個(gè)像素都會(huì)執(zhí)?一次?段著?器魏滚,也是并行的。一般?來(lái)處理圖形中每個(gè)像素點(diǎn)顏?計(jì)算和填充坟漱。
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è)部分: 頂點(diǎn)著?器(VertexShader)
麻敌,?段著?器(FragmentShader)
。
光柵化Rasterization
光柵化,就是把頂點(diǎn)數(shù)據(jù)轉(zhuǎn)換為?元的過(guò)程,具有將圖轉(zhuǎn)化為?個(gè)個(gè)柵格組成的圖象的作用膝蜈,每個(gè)元素對(duì)應(yīng)幀緩沖區(qū)中一像素。也可以說(shuō)光柵化级历,就是?種將?何圖元變?yōu)?D圖像的過(guò)程。
該過(guò)程包含了兩部分的工作叭披。第一部分工作決定窗口坐標(biāo)中的哪些整型柵格區(qū)域會(huì)被基本圖元占用寥殖;第?部分工作分配一個(gè)顏?色值和一個(gè)深度值到各個(gè)區(qū)域。光柵化過(guò)程產(chǎn)生的是片元涩蜘。
把物體的數(shù)學(xué)描述以及與物體相關(guān)的顏?信息轉(zhuǎn)換為屏幕上用于對(duì)應(yīng)位置的像素及?于填充像素的顏色嚼贡,這個(gè)過(guò)程稱為光柵化,這是?個(gè)將模擬信號(hào)轉(zhuǎn)化為離散信號(hào)的過(guò)程同诫。
紋理(Texture)
OpenGL
可以在軟件如游戲顯示界面里粤策,生成各種物體,并可以賦予材質(zhì)和對(duì)物體進(jìn)行光照误窖。但物體表面過(guò)于光滑和單調(diào)掐场,看起來(lái)反而不真實(shí)。這是因?yàn)楝F(xiàn)實(shí)世界中的物體表面往往有各種紋理贩猎,即表面細(xì)節(jié)。所以就使用一張2D圖片來(lái)添加物體的細(xì)節(jié)萍膛,這張圖片就是紋理吭服。
混合(blending)
在測(cè)試階段之后,如果像素依然沒(méi)有被剔除蝗罗,那么像素的顏?將會(huì)和幀緩沖區(qū)中顏色附著上的顏色進(jìn)行混合艇棕,混合的算法可以通過(guò)OpenGL
的函數(shù)進(jìn)行指定。但是OpenGL
提供的混合算法是有限的串塑,如果需要更加復(fù)雜的混合 算法沼琉,一般可以通過(guò)像素著色器進(jìn)?實(shí)現(xiàn),當(dāng)然性能會(huì)比原?的混合算法差?些桩匪。
變換矩陣(Transformation)
圖形發(fā)?平移打瘪、縮放、旋轉(zhuǎn)等變換所需要使用的矩陣。
投影矩陣(Projection)
?于將3D坐標(biāo)轉(zhuǎn)換為2D屏幕坐標(biāo)闺骚,實(shí)際線條也將在二維坐標(biāo)下進(jìn)行繪制彩扔。
渲染上屏/交換緩沖區(qū)(SwapBuffer)
渲染緩沖區(qū)?般映射的是系統(tǒng)的資源?如窗?。如果將圖像直接渲染到窗口對(duì)應(yīng)的渲染緩沖區(qū)僻爽,則可以將圖像顯示到屏幕上虫碉。值得注意的是,如果每個(gè)窗?只有?個(gè)緩沖區(qū)胸梆,那么在繪制過(guò)程中屏幕進(jìn)?了刷新敦捧,窗?可能顯示出不完整的圖像。為了解決這個(gè)問(wèn)題碰镜,常規(guī)的OpenGL
程序?少都會(huì)有兩個(gè)緩沖區(qū)兢卵。顯示在屏幕上的稱為屏幕緩沖區(qū),沒(méi)有顯示的稱為離屏緩沖區(qū)洋措。在一個(gè)緩沖區(qū)渲染完成之后济蝉,通過(guò)將屏幕緩沖區(qū)和離屏緩沖區(qū)交換,實(shí)現(xiàn)圖像在屏幕上顯示菠发。
由于顯示器的刷新?般是逐?進(jìn)?的王滤,為了防?交換緩沖區(qū)的時(shí)候屏幕上下區(qū)域的圖像分屬于兩個(gè)不同的幀,交換一般會(huì)等待顯示器刷新完成的信號(hào)滓鸠,在顯示器器兩次刷新的間隔中進(jìn)?交換雁乡,這個(gè)信號(hào)就被稱為垂直同步信號(hào),這個(gè)技術(shù)被稱為垂直同步糜俗。
使用了雙緩沖區(qū)和垂直同步技術(shù)之后踱稍,由于總是要等待緩沖區(qū)交換之后再進(jìn)?下?幀的渲染,使得幀率無(wú)法完全達(dá)到硬件允許的最??平悠抹。為了解決這個(gè)問(wèn)題珠月,引?了三緩沖區(qū)技術(shù)。在等待垂直同步時(shí)楔敌,來(lái)回交替渲染兩個(gè)離屏的緩沖區(qū)啤挎,?垂直同步發(fā)生時(shí),屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)交換卵凑,實(shí)現(xiàn)充分利利?硬件性能的?的庆聘。