1. 程式人生 > >[OpenGL]概念--渲染管線

[OpenGL]概念--渲染管線

在OpenGL中任何事物都在3D空間中,但是螢幕和視窗是一個2D畫素陣列,所以OpenGL的大部分工作都是關於如何把3D座標轉變為適應你螢幕的2D畫素。3D座標轉為2D座標的處理過程是由OpenGL的圖形渲染管線完成的。影象渲染管線可以被劃分為兩個主要部分:第一個部分把你的3D座標轉換為2D座標,第二部分是把2D座標轉變為實際的有顏色的畫素

渲染管線接收一組3D座標,然後把它們轉變為你螢幕上的有色2D畫素。渲染管線可以被劃分為幾個階段,每個階段需要把前一階段的輸出作為輸入。所有這些階段都是高度專門化的,它們能簡單地並行執行。由於它們的並行執行的特徵,當今大多數顯示卡都有成千上萬的小處理核心GPU,在GPU上為每一個階段執行各自的小程式,從而在圖形輸送管道中快速處理你的資料。這些小程式叫做著色器。有些著色器允許開發者自己配置,用我們自己寫的著色器替換預設存在的。

這樣我們就可以更細緻地控制渲染管線的特定部分,因為它們執行在GPU上,所以它們也會節約寶貴的CPU時間。著色器是用OpenGL著色器語言(OpenGL Shading Language)GLSL寫成的。

渲染管線中各個階段主要完成的工作, 藍色部分代表的是我們可以定義自己的著色器


在上圖中,我們以陣列的形式傳遞3個3D座標作為渲染管線的輸入,用它來表示一個三角形,這個陣列叫做頂點資料(Vertex Data);這裡頂點資料是幾個頂點的集合。每個頂點是用頂點屬性(vertex attributes)表示的,它可以包含任何我們希望用的資料,下面我們來看看渲染管線中各個階段主要完成的工作:

  1. 渲染管線的第一個部分是頂點著色器(vertex shader),它把一個單獨的頂點作為輸入。頂點著色器主要的目的是把3D座標轉為另一種3D座標(投影座標),同時頂點著色器允許我們對頂點屬性進行一些基本處理。
  2. 圖元組裝(primitive assembly)階段把頂點著色器的表示為基本圖形的所有頂點作為輸入,把所有點組裝為特定的基本圖形的形狀;上圖中是一個三角形。
  3. 圖元組裝階段的輸出會傳遞給幾何著色器(geometry shader)。幾何著色器把基本圖形形成的一系列頂點的集合作為輸入,它可以通過產生新頂點構造出新的(或是其他的)基本圖形來生成其他形狀
  4. 細分著色器(tessellation shaders)
    擁有把給定基本圖形細分為更多小基本圖形的能力。這樣我們就能在物體更接近玩家的時候通過建立更多的三角形的方式創建出更加平滑的視覺效果。
  5. 細分著色器的輸出會進入光柵化(rasterization)階段,這裡它會把基本圖形對映為螢幕上相應的畫素,生成供畫素著色器(fragment shader)使用的fragment(OpenGL中的一個fragment是OpenGL渲染一個獨立畫素所需的所有資料)。在畫素著色器執行之前,會執行裁切(clipping)。裁切會丟棄超出你的檢視以外的那些畫素,來提升執行效率。
  6. Fragment Shader(片元著色器,又叫畫素著色器)的主要目的是計算一個畫素的最終顏色,這也是OpenGL高階效果產生的地方。通常,畫素著色器包含用來計算畫素最終顏色的3D場景的一些資料(比如光照、陰影、光的顏色等等)。
  7. 在所有相應顏色值確定以後,最終它會傳到另一個階段,我們叫做alpha測試和混合(blending)階段。這個階段檢測畫素的相應的深度(和stencil)值,使用這些來檢查這個畫素是否在另一個物體的前面或後面,如此做到相應取捨。這個階段也會檢視alpha值(alpha值是一個物體的透明度值)和物體之間的混合(blend)。所以即使在畫素著色器中計算出來了一個畫素所輸出的顏色,最後的畫素顏色在渲染多個三角形的時候也可能完全不同。

雖然渲染管線有多個階段,每個階段都需要對應的著色器,但其實對於大多數場合,我們必須做的只是頂點和畫素著色器,幾何著色器和細分著色器是可選的,通常使用預設的著色器就行了。現在的OpenGL中,我們必須定義至少一個頂點著色器和一個畫素著色器(因為GPU中沒有預設的頂點/畫素著色器)。

渲染管線簡要流程

二維頂點畫素化