opengl4.0發布了tessellation shader(control + evaluation shader)。到opengl4.* 為止,現在opengl已經支援了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
我將根據他們的「主要」輸入與輸出,以及其基本功能進行對比。這樣我們就可以很好的了解他們在opengl pipeline裡面的作用和區別。
以下順序是他們在opengl pipeline裡面的執行順序。
1.vertex shader
輸入:頂點座標(position),該座標值是由glvertex* 或者是gldraw*傳入的。
輸出:頂點座標,這個是經過幾何變換後的座標。
功能:簡單的說就是把輸入的頂點座標乘以(一系列)幾何變換矩陣。每輸入乙個頂點(也就是glvertex*每呼叫一次),vertex shader都會被呼叫一次。vertex shader只知道處理頂點,它不知道這些頂點是做什麼用的,也就是不知道這些頂點將來會被裝配成什麼圖元。(因為vertex shader後面才會有圖元裝配的過程)
當然,vs還可以接收顏色,紋理座標,霧座標等屬性,並在內部對他們做一點點變化,然後再輸出。
2.tess control shader
輸入:patch,乙個patch可以看成是多個頂點的集合。它包括每個頂點的屬性(座標,顏色,紋理座標等等)。使用者可以指定乙個patch裡面要包含幾個頂點。同時,乙個patch還可以用自己的屬性,該屬性被它內部的所有頂點共有,即這些頂點只有一套patch屬性,而不是每個頂點擁有乙個自己的patch屬性。(懂了嗎?)
輸出:patch , gl_tesslevelouter , gl_tesslevelinner。
功能:tcs會根據需求把patch自己的屬性以及它內部的頂點屬性做一些修改。然後輸出patch。當然,它也可以不做任何修改,直接傳給後面的shader。我們知道tessellation的作用就是把乙個圖元分割成很多圖元,比如把乙個三角形分割成很多更小的三角形。因此,在分割的時候我們得要知道這個三角形的每個邊要被分割成多少段,然後在三角形內部,我們還要怎麼繼續分割,這兩個紫色的內容就是儲存在
gl_tesslevelouter 和
gl_tesslevelinner。tcs可以根據需要設定這兩個值。
所以,tcs的主要作用是設定patch以及它內部頂點的屬性。同時也是最重要的,設定圖元接下來被細分的度。(tcs不做分割動作)
下面貼了個三角形分割的。
注意:用tcs的話,glbegin函式的引數必須是gl_patches,而不是以前那種傳統的圖元(點,線,三角形等)。glpatchparameteri可以指定每個patch包含幾個頂點。在vs與tcs直接有個圖元裝配的過程,它就是把vs輸出的頂點封裝乙個patch,然後傳給tcs。
3.tess evaluation shader
輸入:一系列頂點。這些頂點是三角形被分割後產生的
新頂點。下面是每個tes程式都必須有的一段**:
layout( ********s, fractional_odd_spacing, ccw ) in;
它表示tes的輸入是三角形(當然你也可以寫成其他型別的圖元),至於fractional_odd_spacing,和ccw是什麼意思,大家看spec吧,很簡單,我怕我解釋不清楚而誤解大家。最後的那個「in」進一步說明了這是tes的輸入。
輸出:也是一系列頂點。
功能:其實在tcs與tes之間有個過程叫tessellation primitive generator(簡稱tgp),它首先會去檢視tes的輸入是什麼,哦,它要三角形。那麼,tgp就會把tcs傳入的patch內部的頂點看成是若干個三角形(注意patch內部的頂點不一定只有三個)。然後,tgp每次從當前patch裡面取出三個頂點做乙個三角形的分割,直到patch裡面的頂點全部被取出。
每個三角形具體怎麼被分割呢?
其實,gl_tesslevelouter 和
gl_tesslevelinner會被傳入給tgp。它們的作用就被體現出來。這就是為什麼我前面說的tcs不做分割,只計算分割的度。(注意tgp不是shader,它只是pipeline裡面的乙個狀態而已)
現在開始講tes的功能吧。其實tgp傳入的頂點的座標值並不是世界座標值,而是乙個三角形內部的座標表示形式,大家看到上面的圖了吧,三角形頂點上有座標的,tgp然後根據這個座標去計算內部新成立的頂點在該區域性座標系內部的座標。因此,tes就是要把每個頂點的區域性座標變換成世界座標,以及把頂點相應屬性(顏色,紋理座標等)轉換成真正且有效的屬性值。每處理乙個頂點就輸出乙個頂點。
注意:tes並不知道這些頂點會被組成什麼圖元,它只要求tgp把patch內部的頂點當成什麼圖元去分割。tes和vs一樣,輸入是頂點,輸出也是頂點。在tes後面有個圖元裝配的過程,它會根據tes的輸入(看上面的那行**),轉換成相應的圖元。這裡圖元裝配器會把tes輸出的頂點裝配成乙個乙個的三角形。
4.geometry shader
輸入:乙個圖元
輸出:乙個或者多個圖元
功能:無論是否有vs,tcs或者tes,在gs前面都會有乙個圖元裝配的過程,也就是說,傳給gs的是圖元,而不是頂點。
gs可以做什麼呢?
根據新圖元生成新乙個或者多個圖元。下面***碼也是每個gs都必須有的:
layout( ********s ) in;
layout( ********_strip, max_vertices = 3 ) out;
它表示gs輸入的圖元是三角形。
如果當前圖元不是三角形,該gs將不會被呼叫
。該gs的輸出是三角形帶,每個三角形帶最多包括三個頂點。其實這個gs的輸入和輸出可以看成是一樣,沒做太多的事情。呵呵。如果最大頂點數超過3,那麼gs實際上是把多個三角形拼成了乙個三角形帶。具體怎麼
拼,根據需要自己去寫程式吧。
具體gs能夠做什麼呢?
舉個簡單的例子吧。我們可以用gs畫bezier曲線。bezier曲線是有幾個控制點生成的,我們可以把這些控制點假裝當成圖元(點,線,線帶)傳個gs。然後gs在內部通過bezier曲線演算法算出跟多的bezier曲線上面的頂點。算出來的點當成線帶輸出,這樣就由控制點計算出了新圖元(bezier曲線)。懂了嗎?
這裡有很多gs的例子:
下班了,下次寫fs。
OpenGL中VBO如何與shader聯絡起來
關鍵函式 glvertexattribpointer 0,3,gl float,gl false,3 sizeof float void 0 第乙個引數 指定我們要配置的頂點屬性。第二個引數 指定頂點屬性的大小。如頂點屬性是乙個vec3,它由3個值組成,所以大小是3。第三個引數 指定資料的型別,這裡...
Shader著色器基礎 OpenGL程式設計筆記2
頂點著色器 vertex shader 每個頂點都要執行一次vertex shader。它的功能就是把每個頂點在虛擬空間中的三維座標變換為可以在 螢幕上顯示的二維座標,並帶有用於z buffer的深度資訊。可操作屬性 位置 顏色 紋理座標,但是不能建立新的頂點。主要完成以下工作 attribute可...
opengl各個座標系理解與轉換公式
1 標準化裝置座標 normalized device coordinates,ndc 頂點座標已經在頂點著色器中處理過,它們就應該是標準化裝置座標了,標準化裝置座標是乙個x y和z值在 1.0到1.0的一小段空間。任何落在範圍外的座標都會被丟棄 裁剪,不會顯示在你的螢幕上。2 uv座標系 uv座標...