在上一篇OpenGL 下的坐標(biāo)系的最后部分跨琳,我們已經(jīng)了解了著色器渲染的流程。下面就來學(xué)習(xí)一下基礎(chǔ)圖形渲染管線祟峦。
OpenGL基礎(chǔ)圖形渲染管線
在OpenGL中窃页,無論是使用可編程管線,還是使用固定管線郑什,那么它的渲染管線流程都是一樣的府喳。
1.客戶端--服務(wù)端
管線分為上下2部分,上部分是Client客戶端蘑拯,下半部分則是Server服務(wù)端钝满。
這里的客戶端并非是我們在平時(shí)開發(fā)中說的iOS客戶端、Android客戶端强胰。這里的客戶端指的是在CPU上所存儲(chǔ)的代碼舱沧,比如OpenGL的API和C/C++的代碼。這里的Server端調(diào)用的是GPU芯片偶洋,然后不斷從客戶端把數(shù)據(jù)(顏色)傳遞到服務(wù)端來執(zhí)行熟吏。
專業(yè)解釋為:客戶端是存儲(chǔ)在CPU存儲(chǔ)器中的,并且在應(yīng)用程序中執(zhí)行玄窝,或者在主系統(tǒng)內(nèi)存的驅(qū)動(dòng)程序中執(zhí)?牵寺。驅(qū)動(dòng)程序會(huì)將渲染命令和數(shù)據(jù)組合起來,發(fā)送給服務(wù)器執(zhí)?恩脂。
客戶端和服務(wù)端在功能上也是異步的帽氓。 它們是各自獨(dú)立的軟件塊或硬 件塊×┛椋客戶端不不斷的把數(shù)據(jù)塊和命令塊組合在一起輸送到緩沖區(qū)黎休,然后緩沖區(qū)就會(huì)發(fā)送到服務(wù)器執(zhí)?。
2.著色器
著?器是使?用GLSL編寫的程序玉凯,看起來與C語??常類似势腮。 著?器 須從源代碼中編譯和鏈接在一起。最終準(zhǔn)備就緒的著?器程序漫仆。
四種著色器:頂點(diǎn)著色器(必要)捎拯、細(xì)分著色器(可選)、幾何著色器(可選)盲厌、片元著色器(必要)署照。頂點(diǎn)著色器和片元著色器 是每個(gè)OpenGL程序必不可少的部分祸泪,下面著重介紹一下。
頂點(diǎn)著色器:處理從客戶機(jī)輸?的數(shù)據(jù)建芙、應(yīng)?用變換没隘、進(jìn)行其他的類型的數(shù)學(xué)運(yùn)算來計(jì)算關(guān)照效果、位移禁荸、顏?值等等升略,在渲染時(shí)有幾個(gè)頂點(diǎn),頂點(diǎn)著色器執(zhí)行幾次屡限,而且對(duì)每個(gè)點(diǎn)的執(zhí)行是同時(shí)的品嚣。
片元著色器:這是管線最后一部分,用來處理OpenGL 光柵化之后生成的單獨(dú)片元钧大,在這個(gè)階段里面翰撑,計(jì)算一個(gè)偏遠(yuǎn)的顏色和深度值,然后傳遞到管線的片元測試和混合的模塊啊央。
如果說頂點(diǎn)著色器決定了一個(gè)圖元應(yīng)該位于屏幕的什么位置眶诈,那么片元著色器就是決定片元的顏色。
3.向OpenGL 著色器傳遞渲染數(shù)據(jù)的三種通道
Attributes屬性:用來表示一個(gè)頂點(diǎn)的數(shù)據(jù)瓜饥,并且這個(gè)數(shù)據(jù)可能會(huì)不斷地改變逝撬,比如:顏色數(shù)據(jù),頂點(diǎn)數(shù)據(jù)乓土,紋理坐標(biāo)宪潮,光照法線等;而且屬性可以是浮點(diǎn)型趣苏,整型狡相,布爾型等等;
實(shí)際上食磕,頂點(diǎn)位置本身 就是一個(gè)屬性尽棕,而且,屬性總是以四維向量的形式進(jìn)行內(nèi)部存儲(chǔ)的彬伦,即使我們不會(huì)使?所有的 4個(gè)分量滔悉。?個(gè)頂點(diǎn)位置可能存儲(chǔ)(x,y,z),將占有4個(gè)分量中的3個(gè)单绑。
Uniform:uniform變量是外部程序傳遞給頂點(diǎn)著色器和片元著色器的變量回官。uniform傳入的是一個(gè)比較統(tǒng)一的數(shù)據(jù),用于圖元(圖元:OpenGL 中的圖元只不過是頂點(diǎn)的集合以預(yù)定義的方式結(jié)合在一起罷了询张。)的批次處理孙乖,而不是每個(gè)頂點(diǎn)改變一次浙炼。比如:在頂點(diǎn)渲染中變換矩陣份氧,光照參數(shù)和顏色空間轉(zhuǎn)換等信息唯袄。
Uniform變量實(shí)際上可以無數(shù)次限制地使用,設(shè)置一個(gè)應(yīng)用于整個(gè)表面的單個(gè)顏色值蜗帜,還可以設(shè)置一 個(gè)時(shí)間值恋拷。在每次渲染某種類型的頂點(diǎn)動(dòng)畫時(shí)修改它。
Texture Data紋理數(shù)據(jù):紋理最通常的作用是裝飾我們的物體模型厅缺,使得物體表面擁有圖案蔬顾。但在OpenGL中,紋理的作用不單單表現(xiàn)在圖形上湘捎,它也可以用來存儲(chǔ)大量的數(shù)據(jù)诀豁,一個(gè)典型的例子就是利用紋理存儲(chǔ)地形信息。
Attributes屬性數(shù)據(jù)可以直接傳遞到頂點(diǎn)著色器窥妇,不可以直接傳遞到片元著色器舷胜,可以通過頂點(diǎn)著色器間接傳遞到片元著色器,(在設(shè)計(jì)Attributes時(shí)就設(shè)計(jì)成了只給頂點(diǎn)著色器使用)活翩。
Uniform數(shù)據(jù)是可以直接傳遞到頂點(diǎn)著色器和片元著色器的烹骨。
Texture Data紋理數(shù)據(jù)也是可以直接傳遞到頂點(diǎn)著色器和片元著色器,(在頂點(diǎn)著?器材泄、?元著?器中都可以對(duì)紋理數(shù)據(jù)進(jìn)?采樣和篩選沮焕。)不過,一般情況下拉宗,紋理單元數(shù)據(jù)傳入頂點(diǎn)著色器是沒有必要的峦树。(不過要根據(jù)場景來看,如果說有個(gè)應(yīng)用場景是需要把紋理坐標(biāo)放大旦事,那么這是是就可以在頂點(diǎn)著色器完成空入,也可以在片元著色器完成。)
4.使用存儲(chǔ)著色器
在OpenGL 3.0以前的版本族檬,OpenGL包含一個(gè)固定管線歪赢,它可以在不使用著色器的環(huán)境下處理幾何與像素?cái)?shù)據(jù)。從3.1版本開始单料,固定管線從核心模式中去除埋凯,因此我們必須使用著色器來完成工作。現(xiàn)代OpenGL渲染管線嚴(yán)重依賴著色器來處理傳入的數(shù)據(jù)扫尖,我們一般會(huì)使用GLSL(OpenGL Shading Language)編寫著色器程序白对,GLSL語法類似于C語言,GLSL編譯以后運(yùn)行在GPU端换怖。下面我們就先來介紹著色器
4.1 存儲(chǔ)著色器
存儲(chǔ)著色器可以由GLTools的C++類GLShaderManager進(jìn)行管理甩恼,GLShaderManager中的函數(shù)UseStockShader會(huì)選擇一個(gè)存儲(chǔ)著色器并提供這個(gè)著色器的Uniform值,該函數(shù)完成的東西就是對(duì)我們的頂點(diǎn)數(shù)據(jù)進(jìn)一步的加工,比如設(shè)置頂點(diǎn)顏色条摸,設(shè)置頂點(diǎn)光照的強(qiáng)度悦污,設(shè)置頂點(diǎn)紋理等。
4.2 存儲(chǔ)著色器的使用
(1)GLShaderManager 的初始化
GLShaderManager shaderManager;
shaderManager.InitializeStockShaders();
(2)GLShaderManager 的屬性存儲(chǔ)著?色器為每?個(gè)變量都使用?致的內(nèi)部變量命名規(guī)則和相同的屬性槽钉蒲。
(3)GLShanderManager 的 uniform值
一般情況下切端,要對(duì)幾何圖形進(jìn)行渲染,我們需要給對(duì)象遞交屬性矩陣顷啼,?先要綁定我們想要使?用的著色程序上踏枣,并提供程序的uniform值。但是GLShanderManager類可以暫時(shí)的為我們來工作钙蒙,利用useStockShader函數(shù)茵瀑,選擇一個(gè)存儲(chǔ)著色器并提供這個(gè)存儲(chǔ)著色器的Uniform的值。
GLShaderManager::UserStockShader(GLeunm shader...);
4.3 單元著色器(Identity)
GLShaderManager::UserStockShader(GLT_ATTRIBUTE_VERTEX,GLfloat vColor[4]);
單元著?器:只是簡單地使用默認(rèn)笛卡爾坐標(biāo)系(坐標(biāo)范圍(-1.0躬厌, 1.0))瘾婿。所有的片段都應(yīng)用同一種顏色,?何圖形為實(shí)?和未渲染的烤咧。
需要設(shè)置存儲(chǔ)著?器?個(gè)屬性:GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量)
vColor[4] :表示需要設(shè)置的顏色
4.4 平面著色器(Flat)
GLShaderManager::UserStockShader(GLT_SHADER_FLAT,GLfloat mvp[16],GLfloat vColor[4]);
平面著色器:平面著色器將統(tǒng)一著色器進(jìn)行了渲染偏陪,允許為幾何圖形變換指定一個(gè)4x4的變換矩陣,經(jīng)常被稱為"模型視圖投影矩陣"; 在繪制圖形時(shí)煮嫌,可以應(yīng)用變換(模型/投影變化)笛谦。
參數(shù)GLT_SHADER_FLAT:表示平面著色器
參數(shù)GLfloat mvp[16]:表示允許變化的4x4矩陣
參數(shù)GLfloat vColor[4]:表示需要設(shè)置的顏色
4.5 上色著色器(Shaded)
GLShaderManager::UserStockShader(GLT_SHADER_SHADED,GLfloat mvp[16]);
上色著色器:在?何圖形中應(yīng)用的變換矩陣。
需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_COLOR(顏?分量) 2個(gè)屬性昌阿。顏?值將被平滑地插入頂點(diǎn)之間(稱之為平滑著色)饥脑,
參數(shù)GLT_SHADER_SHADED:表示上色著色器
參數(shù)GLfloat mvp[16]:表示需要設(shè)置的顏色
4.6 默認(rèn)光源著色器(Light)
GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vColor[4]);
默認(rèn)光源著色器:默認(rèn)光源著?器,會(huì)使繪制的圖形產(chǎn)生陰影和關(guān)照的效果懦冰。 需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_NORMAL(表面法線)
可以把默認(rèn)光源想象成太陽
參數(shù)GLT_SHADER_DEFAULT_LIGHT:表示默認(rèn)光源著色器
參數(shù)GLfloat mvMatrix[16]:模型視圖矩陣4x4
參數(shù)GLfloat pMatrix[16]:投影矩陣4x4
參數(shù)GLfloat vColor[4]:顏色值
4.7 點(diǎn)光源著?器(Light_Dife)
GLShaderManager::UserStockShader(GLT_SHADER_DEFAULT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vColor[4]);
點(diǎn)光源著色器:點(diǎn)光源著?器和默認(rèn)光源著?器很相似灶轰,區(qū)別在于: 光源位置是特定的。同樣會(huì)使繪制的圖形產(chǎn)生陰影和光照效果刷钢, 同樣需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_NORMAL(表?法線)笋颤。
參數(shù)GLT_SHADER_DEFAULT_LIGHT_DIEF: 表示點(diǎn)光源著?色器
參數(shù)GLfloat mvMatrix[16]: 模型視圖矩陣 4x4
參數(shù)GLfloat pMatrix[16]: 投影矩陣 4x4
參數(shù)GLfloat vLightPos[3]: 視點(diǎn)坐標(biāo)光源位置
參數(shù)GLfloat vColor[4]: 漫反射的顏?值
4.8 紋理替換矩陣著色器(Replace)
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_REPLACE,GLfloat mvMatrix[16],GLint nTextureUnit);
著?器通過給定的模型視圖投影矩陣,使?綁定到 nTextureUnit (紋理單元) 指定紋理單元的紋理對(duì)幾何圖形進(jìn)行變化内地。
?段顏色:是直接從紋理樣本中直接獲取的伴澄。
需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_NORMAL(表面法線)
參數(shù)GLT_SHADER_TEXTURE_REPLACE:紋理替換矩陣著色器
參數(shù)GLfloat mvMatrix[16]:模型視圖矩陣4x4
參數(shù)GLint nTextureUnit:紋理單元
4.9 紋理調(diào)整著?器
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,G
Lfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);
將一個(gè)紋理通過漫反射照明計(jì)算機(jī)進(jìn)行調(diào)整(相乘)。光線在視覺空間中的位置是給定的阱缓。
需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))非凌、GLT_ATTRIBUTE_NORMAL(表?法線)
參數(shù)GLT_SHADER_TEXTURE_MODULATE:紋理調(diào)整著?器
參數(shù)GLfloat mvMatrix[16]:模型視圖矩陣4x4
參數(shù)GLfloat vColor[4]:漫反射的顏?值
參數(shù)GLint nTextureUnit:紋理單元
4.10 紋理光源著?器
GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vBaseColor[4],GLint nTextureUnit);
這種著色器將?個(gè)紋理通過漫反射照明計(jì)算機(jī)進(jìn)行調(diào)整(相乘)。光線在視覺空間中的位置是給定的荆针。需要設(shè)置存儲(chǔ)著?器的 GLT_ATTRIBUTE_VERTEX(頂點(diǎn)分量) 和
GLT_ATTRIBUTE_TEXTURE0(紋理坐標(biāo))敞嗡、GLT_ATTRIBUTE_NORMAL(表?法線)
參數(shù)GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF:表示紋理光源著?器
參數(shù)GLfloat mvMatrix[16]:模型矩陣4x4
參數(shù)GLfloat pMatrix[16]:投影矩陣4x4
參數(shù)GLfloat vLightPos[3]:視覺空間中點(diǎn)光源位置
參數(shù)GLfloat vBaseColor[4]:顏色值(幾何圖形的基本色)
參數(shù)GLint nTextureUnit:紋理單元