| OpenGL4.0發(fā)布了Tessellation shader(Control + Evaluation shader)。到OpenGL4.* 為止,現(xiàn)在OpenGL已經(jīng)支持了5種不同類型的shader。 1.Vertex Shader,簡稱VS 2.TESS Control Shader (D3D11 叫Hull shader),簡稱TCS 3.TESS Evaluation Shader (D3D叫Domain shader),簡稱TES 4.Geometry Shader ,簡稱GS 5.Fragment Shader(D3D叫Pixel Shader),簡稱PS 
 我將根據(jù)他們的“主要”輸入與輸出,以及其基本功能進(jìn)行對比。這樣我們就可以很好的了解他們在OpenGL Pipeline里面的作用和區(qū)別。 以下順序是他們在OpenGL Pipeline里面的執(zhí)行順序。 
 1.Vertex Shader 輸入:頂點坐標(biāo)(Position),該坐標(biāo)值是由glVertex* 或者是glDraw*傳入的。 輸出:頂點坐標(biāo),這個是經(jīng)過幾何變換后的坐標(biāo)。 功能:簡單的說就是把輸入的頂點坐標(biāo)乘以(一系列)幾何變換矩陣。每輸入一個頂點(也就是glVertex*每調(diào)用一次),Vertex shader都會被調(diào)用一次。Vertex Shader只知道處理頂點,它不知道這些頂點是做什么用的,也就是不知道這些頂點將來會被裝配成什么圖元。(因為Vertex shader后面才會有圖元裝配的過程) 當(dāng)然,VS還可以接收顏色,紋理坐標(biāo),霧坐標(biāo)等屬性,并在內(nèi)部對他們做一點點變化,然后再輸出。 
 2.TESS Control Shader 輸入:Patch,一個Patch可以看成是多個頂點的集合。它包括每個頂點的屬性(坐標(biāo),顏色,紋理坐標(biāo)等等)。用戶可以指定一個patch里面要包含幾個頂點。同時,一個patch還可以用自己的屬性,該屬性被它內(nèi)部的所有頂點共有,即這些頂點只有一套patch屬性,而不是每個頂點擁有一個自己的patch屬性。(懂了嗎?) 輸出:Patch , gl_TessLevelOuter , gl_TessLevelInner。 功能:TCS會根據(jù)需求把Patch自己的屬性以及它內(nèi)部的頂點屬性做一些修改。然后輸出Patch。當(dāng)然,它也可以不做任何修改,直接傳給后面的shader。我們知道Tessellation的作用就是把一個圖元分割成很多圖元,比如把一個三角形分割成很多更小的三角形。因此,在分割的時候我們得要知道這個三角形的每個邊要被分割成多少段,然后在三角形內(nèi)部,我們還要怎么繼續(xù)分割,這兩個紫色的內(nèi)容就是存儲在 gl_TessLevelOuter 和gl_TessLevelInner。TCS可以根據(jù)需要設(shè)置這兩個值。 所以,TCS的主要作用是設(shè)置Patch以及它內(nèi)部頂點的屬性。同時也是最重要的,設(shè)置圖元接下來被細(xì)分的度。(TCS不做分割動作) 下面貼了個三角形分割的圖片。 
 注意:用TCS的話,glBegin函數(shù)的參數(shù)必須是GL_PATCHES,而不是以前那種傳統(tǒng)的圖元(點,線,三角形等)。 glPatchParameteri可以指定每個Patch包含幾個頂點。在VS與TCS直接有個圖元裝配的過程,它就是把VS輸出的頂點封裝一個Patch,然后傳給TCS。 
 3.TESS
 Evaluation Shader 輸入:一系列頂點。這些頂點是三角形被分割后產(chǎn)生的新頂點。下面是每個TES程序都必須有的一段代碼: layout(
 triangles, fractional_odd_spacing, ccw ) in; 它表示TES的輸入是三角形(當(dāng)然你也可以寫成其他類型的圖元),至于 fractional_odd_spacing,和ccw是什么意思,大家看spec吧,很簡單,我怕我解釋不清楚而誤解大家。最后的那個“in”進(jìn)一步說明了這是TES的輸入。 輸出:也是一系列頂點。 功能:其實在TCS與TES之間有個過程叫Tessellation Primitive Generator(簡稱TGP),它首先會去查看TES的輸入是什么,哦,它要三角形。那么,TGP就會把TCS傳入的Patch內(nèi)部的頂點看成是若干個三角形(注意Patch內(nèi)部的頂點不一定只有三個)。然后,TGP每次從當(dāng)前Patch里面取出三個頂點做一個三角形的分割,直到Patch里面的頂點全部被取出。 每個三角形具體怎么被分割呢? 其實,gl_TessLevelOuter 和gl_TessLevelInner會被傳入給TGP。它們的作用就被體現(xiàn)出來。這就是為什么我前面說的TCS不做分割,只計算分割的度。(注意TGP不是shader,它只是pipeline里面的一個狀態(tài)而已) 現(xiàn)在開始講TES的功能吧。其實TGP傳入的頂點的坐標(biāo)值并不是世界坐標(biāo)值,而是一個三角形內(nèi)部的坐標(biāo)表示形式,大家看到上面的圖了吧,三角形頂點上有坐標(biāo)的,TGP然后根據(jù)這個坐標(biāo)去計算內(nèi)部新成立的頂點在該局部坐標(biāo)系內(nèi)部的坐標(biāo)。因此,TES就是要把每個頂點的局部坐標(biāo)變換成世界坐標(biāo),以及把頂點相應(yīng)屬性(顏色,紋理坐標(biāo)等)轉(zhuǎn)換成真正且有效的屬性值。每處理一個頂點就輸出一個頂點。 注意:TES并不知道這些頂點會被組成什么圖元,它只要求TGP把patch內(nèi)部的頂點當(dāng)成什么圖元去分割。TES和VS一樣,輸入是頂點,輸出也是頂點。在TES后面有個圖元裝配的過程,它會根據(jù)TES的輸入(看上面的那行代碼),轉(zhuǎn)換成相應(yīng)的圖元。這里圖元裝配器會把TES輸出的頂點裝配成一個一個的三角形。 
 4.Geometry
 Shader 輸入:一個圖元 輸出:一個或者多個圖元 功能:無論是否有VS,TCS或者TES,在GS前面都會有一個圖元裝配的過程,也就是說,傳給GS的是圖元,而不是頂點。 GS可以做什么呢? 根據(jù)新圖元生成新一個或者多個圖元。下面兩會代碼也是每個GS都必須有的: layout(
 triangles ) in; 它表示GS輸入的圖元是三角形。如果當(dāng)前圖元不是三角形,該GS將不會被調(diào)用。該GS的輸出是三角形帶,每個三角形帶最多包括三個頂點。其實這個GS的輸入和輸出可以看成是一樣,沒做太多的事情。呵呵。如果最大頂點數(shù)超過3,那么GS實際上是把多個三角形拼成了一個三角形帶。具體怎么拼,根據(jù)需要自己去寫程序吧。 具體GS能夠做什么呢? 舉個簡單的例子吧。我們可以用GS畫Bezier曲線。Bezier曲線是有幾個控制點生成的,我們可以把這些控制點假裝當(dāng)成圖元(點,線,線帶)傳個GS。然后GS在內(nèi)部通過Bezier曲線算法算出跟多的Bezier曲線上面的頂點。算出來的點當(dāng)成線帶輸出,這樣就由控制點計算出了新圖元(Bezier曲線)。懂了嗎? 這里有很多GS的例子:http://blog.csdn.net/jackers679/article/details/7472317 
 下班了,下次寫FS。 | 
|  |