1 簡(jiǎn)介
OpenGL(Open Graphics Library)是一個(gè)跨編程語言、跨平臺(tái)的圖形編程程序接口区宇,它將計(jì)算機(jī)的資源抽象成一個(gè)個(gè)OpenGL對(duì)象
,將對(duì)這些資源的操作抽象成一個(gè)個(gè)OpenGL指令
。
OpenGL ES(OpenGL for Embedded System)是OpenGL
三維圖形API的子集偶惠,針對(duì)手機(jī)、PDA和游戲主機(jī)等嵌入式設(shè)備而設(shè)計(jì)光坝,去除了很多不必要的和性能較低的API接口尸诽。
1.1 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è)語言中商蕴,都是類似C語言一樣面向過程的函數(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)移迫,更加合理高效。
1.2 OpenGL狀態(tài)機(jī)
- 具有記憶功能管行,能夠記錄當(dāng)前的狀態(tài)
- 可以接收輸入厨埋,根據(jù)輸入的信息修改自己當(dāng)前的狀態(tài),并支持輸出
- 當(dāng)進(jìn)入停機(jī)狀態(tài)時(shí)捐顷,便不再接收輸入信息荡陷,停止工作。
在程序退出前迅涮,OpenGL
總會(huì)先停止工作的废赞。
2 著色器的渲染流程
(1)
頂點(diǎn)數(shù)據(jù)
(2)頂點(diǎn)著色器
【必要】:接收頂點(diǎn)數(shù)據(jù),單獨(dú)處理每個(gè)頂點(diǎn)
(3)細(xì)分著色器
【可選】:描述物體的形狀,在管線中?生成新的幾何體處理(平順)模型 生成最終狀態(tài)
(名稱: 細(xì)分控制著?器/細(xì)分計(jì)算著?器叮姑,對(duì)所有的圖像進(jìn)行修改幾何圖元類型或者放棄所有的凸緣)
(4)幾何著色器
(5)圖元設(shè)置
(6)剪切
:剪切視口之外的繪制
(7)光柵化
:輸入圖元的數(shù)學(xué)描述唉地,轉(zhuǎn)化為與屏幕對(duì)應(yīng)位置的像素片元据悔,簡(jiǎn)稱光柵化
(8)片元著色器
【必選】:片元顏色以及深度值,然后傳遞到片元測(cè)試和混合模塊
(9) 顯示效果
2.1 渲染
將圖形/圖像數(shù)據(jù)轉(zhuǎn)換成2D空間圖像操作叫渲染
(Rendering)
在渲染過程中耘沼,必須存儲(chǔ)2中著色器极颓,分別是頂點(diǎn)著色器和片元著色器。頂點(diǎn)著色器是第一個(gè)群嗤,片元著色器是最后一個(gè)菠隆。頂點(diǎn)著色器中處理頂點(diǎn),片元著色器處理像素顏色狂秘。
2.2 頂點(diǎn)數(shù)組(VertexArray)和頂點(diǎn)緩沖區(qū)(VertexBuffer)
- 畫圖一般是先畫好圖像的骨架骇径,然后再往骨架中填充顏色,
OpenGL
也是一樣的者春,頂點(diǎn)數(shù)據(jù)就是要畫的圖像的骨架破衔,和現(xiàn)實(shí)中不同的是,OpenGL
中的圖像都是由圖元
組成钱烟。在OpenGL ES
中晰筛,有三種類型的圖元
:點(diǎn)、線忠售、三角形传惠。開發(fā)者可以選擇設(shè)定函數(shù)指針迄沫,在調(diào)用繪制方法的時(shí)候稻扬,直接由內(nèi)存?zhèn)魅?code>頂點(diǎn)數(shù)組。而性能更高的做法是羊瘩,提前分配一塊顯存泰佳,將頂點(diǎn)數(shù)據(jù)預(yù)先傳入到顯存當(dāng)中。這部分顯存尘吗,就被稱為頂點(diǎn)緩沖區(qū)
逝她。 - 頂點(diǎn)指的是我們?cè)诶L制一個(gè)圖形的時(shí)候,他的頂點(diǎn)位置數(shù)據(jù)睬捶,這個(gè)數(shù)據(jù)可以直接存儲(chǔ)在數(shù)組中或者將其直接緩存到GPU內(nèi)存中
2.3 著色器程序(Shader)
- 就全面的將
固定渲染管線
架構(gòu)變?yōu)榱?code>可編程渲染管線黔宛。因此OpenGL
在實(shí)際調(diào)用繪制函數(shù)之前,還需要指定一個(gè)由shader
編譯成的著色器程序
擒贸。常見的著色器主要有頂點(diǎn)著色器(VertexShader)
臀晃,片段著色器(FragmentShader)
/像素著色器(PixelShader)
,幾何著色器(GeometryShader)
,曲面細(xì)分著色器(TessellationShader)
介劫。片段著色器
和像素著色器
只是在OpenGL
和DX
中的不同叫法而已徽惋。可惜的是座韵,直到OpenGL ES 3.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)算,并決定像素的顏色铡买。
2.4 管線
在OpenGL下渲染圖形更鲁,就會(huì)有經(jīng)歷一個(gè)一個(gè)節(jié)點(diǎn),這樣的操作可以理解為管線
奇钞。就像流水線一樣澡为,每個(gè)任務(wù)類似流水線一般執(zhí)行,任務(wù)之間有先后順序景埃。管線是一個(gè)抽象概念媒至,之所以稱之為管線,是因?yàn)轱@卡在處理數(shù)據(jù)的時(shí)候是按照一個(gè)固定的順序來的谷徙,而且嚴(yán)格按照這個(gè)順序拒啰,這個(gè)順序是不能被打破的。
2.5 固定管線/存儲(chǔ)著色器
- 在早期的OpenGL版本完慧,它封裝了很多種著色器程序塊內(nèi)置的?一段包含了光照谋旦、坐標(biāo)變換、裁剪等等諸多功能的固定shader程序來完成,來幫助開發(fā)者 來完成圖形的渲染屈尼。而開發(fā)者只需要傳入相應(yīng)的參數(shù),就能快速完成圖形的渲染册着。
- 但是由于OpenGL的使用場(chǎng)景非常豐富,
固定管線
或存儲(chǔ)著色器
無法完成每一個(gè)業(yè)務(wù)鸿染。這時(shí)將相關(guān)部分開放成可編程管線
指蚜。
2.6 頂點(diǎn)著色器(VertexShader)
- ?般?來處理圖形每個(gè)頂點(diǎn)變換(旋轉(zhuǎn)/平移/投影等)
-
頂點(diǎn)著色器
是OpenGL中用于計(jì)算頂點(diǎn)屬性的程序。頂點(diǎn)著?器
是逐頂點(diǎn)運(yùn)算的程序涨椒,也就是說每個(gè)頂點(diǎn)數(shù)據(jù)都會(huì)執(zhí)?一次頂點(diǎn)著色器摊鸡,當(dāng)然這是并?的绽媒,并且頂點(diǎn)著色器運(yùn)算過程中無法訪問其他頂點(diǎn)的數(shù)據(jù)。
2.7 片元著色器(FragmentShader)
- ?般用來處理圖形中每個(gè)像素點(diǎn)顏色計(jì)算和填充
-
片段著色器
是OpenGL中用于計(jì)算片段(像素)顏色的程序免猾。片段著色器
是逐像素運(yùn)算的程序是辕,也就是說每個(gè)像素都會(huì)執(zhí)?一次片段著色器,當(dāng)然也是并?的
2.8 GLSL(OpenGL Shading Language)
-
OpenGL著?語言(OpenGL Shading Language)
是用來在OpenGL中著色編程的語?猎提,即開發(fā)人員寫的短小的自定義程序获三,他們是在圖形卡的GPU(Graphic Processor Unit圖形處理單元)上執(zhí)行的,代替了固定的渲染管線的一部分锨苏,使渲染管線中不同層次具有可編程性疙教。比如:視圖轉(zhuǎn)換、投影轉(zhuǎn)換等伞租。GLSL(GL Shading Language)
的著?器代碼分成2個(gè)部分:Vertex Shader(頂點(diǎn)著?器)
和Fragment(片元著色器)
2.9 光柵化(Rasterization)
- 是把
頂點(diǎn)數(shù)據(jù)
轉(zhuǎn)換為片元
的過程贞谓,具有將圖轉(zhuǎn)化為一個(gè)個(gè)柵格組成的圖象的作用,特點(diǎn)是每個(gè)元素對(duì)應(yīng)幀緩沖區(qū)中的一像素葵诈。 - 光柵化其實(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)的過程
2.10 紋理
-
紋理
可以理解為圖片窖贤。 大家在渲染圖形時(shí)需要在其編碼填充圖片,為了使得場(chǎng)景更加逼真暇矫。而這里使用的圖片主之,就是常說的紋理择吊。但是在OpenGL李根,我們更加習(xí)慣叫紋理,而不是圖片
2.11 混合(Blending)
- 在測(cè)試階段之后几睛,如果像素依然沒有被剔除房轿,那么像素的顏色將會(huì)和
幀緩沖區(qū)
中顏色附著上的顏色進(jìn)?混合
,混合
的算法可以通過OpenGL的函數(shù)進(jìn)行指定所森。但是OpenGL提供的混合算法是有限的囱持,如果需要更加復(fù)雜的混合算法,一般可以通過像素著色器進(jìn)行實(shí)現(xiàn)焕济,當(dāng)然性能會(huì)比原生的混合算法差一些纷妆。
3 矩陣
3.1 變換矩陣(Transformation)
- 例如圖形想發(fā)生平移,縮放啥刻,旋轉(zhuǎn)變換进萄。就需要使用變換矩陣。
3.2 投影矩陣(Projection)
- ?于將3D坐標(biāo)轉(zhuǎn)換為二維屏幕坐標(biāo)驰唬,實(shí)際線條也將在二維坐標(biāo)下進(jìn)行繪制际邻。
4 渲染上屏/交換緩沖區(qū)(SwapBuffer)
-
渲染緩沖區(qū)
?般映射的是系統(tǒng)的資源比如窗?芯丧。如果將圖像直接渲染到窗口對(duì)應(yīng)的渲染緩沖區(qū),則可以將圖像顯示到屏幕上世曾。 - 但是缨恒,值得注意的是,如果每個(gè)窗口只有一個(gè)緩沖區(qū)轮听,那么在繪制過程中屏幕進(jìn)行了刷新骗露,窗口可能顯示出不完整的圖像
- 為了解決這個(gè)問題,常規(guī)的OpenGL程序至少都會(huì)有兩個(gè)緩沖區(qū)血巍。顯示在屏幕上的稱為屏幕緩沖區(qū)椒袍,沒有顯示的稱為離屏緩沖區(qū)。在一個(gè)緩沖區(qū)渲染完成之后藻茂,通過將屏幕緩沖區(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)行下一幀的渲染不恭,使得幀率無法完全達(dá)到硬件允許的最高水平叶雹。為了解決這個(gè)問題,引入了三緩沖區(qū)
技術(shù)换吧,在等待垂直同步時(shí)折晦,來 回交替渲染兩個(gè)離屏的緩沖區(qū),而垂直同步發(fā)生時(shí)沾瓦,屏幕緩沖區(qū)和最近渲染完成的離屏緩沖區(qū)交換满着,實(shí) 現(xiàn)充分利用硬件性能的目的
轉(zhuǎn)載請(qǐng)備注原文出處,不得用于商業(yè)傳播-H.Ekko
最后我們通過下面這個(gè)圖再來看一下整個(gè)渲染流程
轉(zhuǎn)載請(qǐng)備注原文出處贯莺,不得用于商業(yè)傳播-H.Ekko