最近在學(xué)習(xí)一下OpenGL
方面的知識(shí)派近,寫(xiě)博客記錄一下式塌。
概念
OpenGL (Open Graphics Library)
是?個(gè)跨編程語(yǔ)?牲览、跨平臺(tái)的編程圖形程序接?盖奈,它將計(jì)算機(jī)的資源抽象稱(chēng)為?個(gè)個(gè)OpenGL
的對(duì)象,對(duì)這些資源的操作抽象為?個(gè)個(gè)的OpenGL
指令.
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),更加合理?效
OpenGL狀態(tài)機(jī)
狀態(tài)機(jī)
是理論上的?種機(jī)器.這個(gè)?常難以理解诬垂,簡(jiǎn)單理解為:狀態(tài)機(jī)描述了?個(gè)對(duì)象在其?命周期內(nèi)所經(jīng)歷的各種狀態(tài)劲室,狀態(tài)間的轉(zhuǎn)變,發(fā)?轉(zhuǎn)變的動(dòng)因结窘,條件及轉(zhuǎn)變中所執(zhí)?的活動(dòng)很洋。或者說(shuō)晦鞋,狀態(tài)機(jī)是?種?為蹲缠,說(shuō)明對(duì)象在其?命周期中響應(yīng)事件所經(jīng)歷的狀態(tài)序列以及對(duì)那些狀態(tài)事件的響應(yī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í)候斤讥,不再接收輸?,停??作
渲染
渲染:將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成2D空間圖像操作叫做渲染(Rendering)
.
頂點(diǎn)數(shù)組( VertexArray ) 和 頂點(diǎn)緩沖區(qū)( VertexBuffer )
屏幕中的所有圖形/圖像湾趾,都是由這三種圖元組合而成的
點(diǎn)
線
三角形
頂點(diǎn)數(shù)據(jù)存儲(chǔ)方式
頂點(diǎn)數(shù)組與頂點(diǎn)緩沖區(qū)的區(qū)別在于頂點(diǎn)數(shù)據(jù)的存儲(chǔ)方式不同
- 存儲(chǔ)在內(nèi)存中芭商,即
【頂點(diǎn)數(shù)組】
- 存儲(chǔ)在GPU提前分配的顯存中,即
【頂點(diǎn)緩沖區(qū)】
管線
可以理解為流水線搀缠,該流水線有一個(gè)固定順序的操作铛楣,需要按著這個(gè)順序一個(gè)個(gè)執(zhí)行
固定管線/存儲(chǔ)著色器
- 一個(gè)已經(jīng)封裝好的
Shader
程序,開(kāi)發(fā)者使用時(shí)艺普,只需要傳入相應(yīng)參數(shù)簸州,即可快速完成渲染鉴竭,類(lèi)似蘋(píng)果系統(tǒng)中封裝好的API - 當(dāng)固定管線無(wú)法完成每個(gè)業(yè)務(wù)時(shí),需要將與業(yè)務(wù)相關(guān)的部分變成可編程岸浑,用戶(hù)根據(jù)需要自定義管線來(lái)完成業(yè)務(wù)
- 目前
OpenGL
中可編程的僅有兩個(gè)程序:頂點(diǎn)著色器搏存、片元著色器
頂點(diǎn)著?器 VertexShader
- ?般?來(lái)處理圖形每個(gè)頂點(diǎn)
變換
(旋轉(zhuǎn)/平移/投影等)- 頂點(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ù)- ?般來(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ā)?的掘譬。
?元著?器程序 FragmentShader
- ?般?來(lái)處理圖形中每個(gè)像素點(diǎn)顏?計(jì)算和填充
- ?段著?器是OpenGL中?于
計(jì)算?段(像素)顏?
的程序泰演。?段著?器是逐像素運(yùn)算的程序,也就是說(shuō)每個(gè)像素都會(huì)執(zhí)??次?段著?器葱轩,當(dāng)然也是并?的
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(?元著?器)
光柵化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ò)程
紋理
紋理可以理解為圖?.
?家在渲染圖形時(shí)需要在其編碼填充圖?,為了使得場(chǎng)景更加逼真.?這?使?的圖?,就是常說(shuō)的紋理.但是在OpenGL我們更加習(xí)慣叫紋理,?不是圖?.
混合(Blending)
如果像素依然沒(méi)有被剔除,那么像素的顏?將會(huì)和幀緩沖區(qū)中顏?附著上的顏?進(jìn)?混合纫溃,混合的算法可以通過(guò)OpenGL的函數(shù)進(jìn)?指定腰涧。但是OpenGL提供的混合算法是有限的,如果需要更加復(fù)雜的混合算法紊浩,?般可以通過(guò)像素著?器進(jìn)?實(shí)現(xiàn)(性能會(huì)?原?的混合算法差?些).
變換矩陣 Transformation
用于圖形的平移窖铡、旋轉(zhuǎn)疗锐、縮放時(shí)使用
投影矩陣 Projection
將3D坐標(biāo)轉(zhuǎn)換為2D屏幕坐標(biāo)時(shí)使用
渲染上屏/交換緩沖區(qū) SwapBuffer
- 渲染緩沖區(qū):可以理解為是系統(tǒng)的資源,例如窗口
- 渲染上屏:將圖像直接渲染到窗口對(duì)應(yīng)的渲染緩沖區(qū)
總結(jié):GPU 圖形渲染流水線的具體實(shí)現(xiàn)可分為六個(gè)階段万伤,如下圖所示窒悔。
- 頂點(diǎn)著色器(Vertex Shader)
- 形狀裝配(Shape Assembly),又稱(chēng) 圖元裝配
- 幾何著色器(Geometry Shader)
- 光柵化(Rasterization)
- 片段著色器(Fragment Shader)
- 測(cè)試與混合(Tests and Blending)
第一階段敌买,頂點(diǎn)著色器简珠。該階段的輸入是 頂點(diǎn)數(shù)據(jù)(Vertex Data) 數(shù)據(jù),比如以數(shù)組的形式傳遞 3 個(gè) 3D 坐標(biāo)用來(lái)表示一個(gè)三角形虹钮。頂點(diǎn)數(shù)據(jù)是一系列頂點(diǎn)的集合聋庵。頂點(diǎn)著色器主要的目的是把 3D 坐標(biāo)轉(zhuǎn)為另一種 3D 坐標(biāo),同時(shí)頂點(diǎn)著色器可以對(duì)頂點(diǎn)屬性進(jìn)行一些基本處理芙粱。
第二階段祭玉,形狀(圖元)裝配。該階段將頂點(diǎn)著色器輸出的所有頂點(diǎn)作為輸入春畔,并將所有的點(diǎn)裝配成指定圖元的形狀脱货。圖中則是一個(gè)三角形。圖元(Primitive) 用于表示如何渲染頂點(diǎn)數(shù)據(jù)律姨,如:點(diǎn)振峻、線、三角形择份。
第三階段扣孟,幾何著色器。該階段把圖元形式的一系列頂點(diǎn)的集合作為輸入荣赶,它可以通過(guò)產(chǎn)生新頂點(diǎn)構(gòu)造出新的(或是其它的)圖元來(lái)生成其他形狀凤价。例子中,它生成了另一個(gè)三角形拔创。
第四階段利诺,光柵化。該階段會(huì)把圖元映射為最終屏幕上相應(yīng)的像素伏蚊,生成片段立轧。片段(Fragment) 是渲染一個(gè)像素所需要的所有數(shù)據(jù)。
第五階段躏吊,片段著色器氛改。該階段首先會(huì)對(duì)輸入的片段進(jìn)行 裁切(Clipping)。裁切會(huì)丟棄超出視圖以外的所有像素比伏,用來(lái)提升執(zhí)行效率胜卤。
第六階段,測(cè)試與混合赁项。該階段會(huì)檢測(cè)片段的對(duì)應(yīng)的深度值(z
坐標(biāo))葛躏,判斷這個(gè)像素位于其它物體的前面還是后面澈段,決定是否應(yīng)該丟棄。此外舰攒,該階段還會(huì)檢查 alpha
值( alpha
值定義了一個(gè)物體的透明度)败富,從而對(duì)物體進(jìn)行混合。因此摩窃,即使在片段著色器中計(jì)算出來(lái)了一個(gè)像素輸出的顏色兽叮,在渲染多個(gè)三角形的時(shí)候最后的像素顏色也可能完全不同。