OpenGL渲染管線漫談
如果把OpenGL看做一個加工機器,它的功能就是把一系列頂點紋理數據可以在屏幕上面顯示的像素。這就如同面條機器把一定比例的面和水加工成一根根面條一樣。面條機器可以設置面條的寬度和厚度,這可以影響整個加工的面條,就相當於OpenGL可以設置紋理過濾模式,混合模式等全局狀態,可以影響到這一幀的像素輸出。從glDrawElements開始,OpenGL流水線就開始運作了,它由一系列過程串聯而成,其中有些是程序可以操作的,比如頂點片段著色器;有些戲系統根據設置的全局OpenGL狀態自動作用的,比如紋理采樣和光柵化。
頂點著色:
這個過程完全由程序掌握,它可以使用所有傳人的attribute和uniform變量。一般attribute變量包括位置,顏色,紋理,法線,uniform包括變換矩陣,燈光位置。輸出包括變換後的頂點位置,通過視圖投影變換,把位置變換為0~1之間,如果不再這個範圍內,這個點在後面的剪切過程中剪切剔除掉,並由其它新生成的點代替。很多情況下也會包括紋理坐標,某些情況也會計算頂點的光照顏色。這些輸出除了位置都是作為varying變量傳遞到下一個管線。
細分著色和集合著色:
頂點著色輸出的是各個頂點數據,這兩個過程會對頂點進行更進一步處理,比如創建更多圖元。這兩個過程在遊戲中很少用到。所以一般可從頂點著色直接跳到下一步。
圖元裝配:
前面都是對頂點的處理,這裏會把前面的頂點重新組裝稱為圖元,比如一個個三角形。組裝的原則是根據glDrawElements設置的參數,比如GL_TRIANGLES。
剪切:
在頂點著色中生成的頂點位置如果不再0~1之間,在這裏會被剪切掉,通過剪切掉不必要的圖元,會顯著降低後面流程的工作量。這個部分完全由gl操作。
光柵化:
上面所有步驟輸出的結果是一個個多邊形,而最終顯示的是一個個像素區域。這一步所做的就是把多邊形通過插值生成一個個片段,即候選像素。除了位置,還有頂點著色輸出的varying類型都會被插值,一般包括紋理坐標,法線坐標。
片段著色:
這一步計算光柵化之後每個片段的對應顏色和深度值,這是完全可編程的,也可以根據判斷丟棄本片段。
剪切測試:
如果片段在glScissor範圍之外,則直接丟棄。本過程完全由OpenGL處理。
模板測試:
可以用來實現倒影鏤空等特效。測試失敗則根據設置修改輸出幀緩沖的模板值,然後丟棄;否則進行下面的深度測試。本過程完全由OpenGL處理。
深度測試:
如果失敗則只根據設置修改模板值,然後丟棄。否則修改模板深度緩存並進行到下一步。本過程完全由OpenGL處理。
alpha混合:
混合前面計算的像素顏色和當前緩存的顏色,可用於半透明效果。本過程完全由OpenGL處理。
後面還有抖動和邏輯操作處理,但是對於一般遊戲開發來說,alpha混合之後,就相當於得到顯示到屏幕的顏色了。
這個流程完全是串行處理的,要降低後面的計算量,就要盡可能在更前面的步驟剔除掉不會最終顯示的圖元片段。程序可以操作的地方有兩個。一個是在進入OpenGL管線之前,盡可能通過場景管理剔除掉不需要的圖元;另一個是采用由近及遠的畫法,在深度測試中丟棄不會顯示的片段。可以看到場景管理尤其重要,好的場景算法可以大大降低顯卡的負擔。
OpenGL渲染管線漫談