當前位置:編程學習大全網 - 編程語言 - OpenGL-渲染流程

OpenGL-渲染流程

在OpenGL中,任何事物都處於 3D 空間中,而屏幕和窗口卻都是 2D 像素數組,這就導致了OpenGL大部分工作都是關於把3D坐標轉變為適配妳屏幕的2D像素,3D坐標轉為2D坐標的處理過程是由OpenGL的 圖形渲染管線 (指的是壹堆原始圖形數據途經壹個輸送管道,期間經過各種變化處理最終出現在屏幕的過程)管理的。

圖形渲染管線接受壹組3D坐標,然後把它們轉變為妳屏幕上的有色2D像素輸出。圖形渲染管線可以被劃分為幾個階段,每個階段將會把前壹個階段的輸出作為輸入。所有這些階段都是高度專門化的(它們都有壹個特定的函數),並且很容易並行執行。正是由於它們具有並行執行的特性,當今大多數顯卡都有成千上萬的小處理核心,它們在GPU上為每壹個(渲染管線)階段運行各自的小程序,從而在圖形渲染管線中快速處理妳的數據。這些小程序叫做 著色器 (Shader)。

下圖是圖形渲染管線的每個階段的抽象展示。要註意藍色部分代表的是我們可以註入自定義的著色器的部分。

首先,我們以數組的形式傳遞3個3D坐標作為圖形渲染管線的輸入,用來表示壹個三角形,這個數組叫做頂點數據(Vertex Data);頂點數據是壹系列頂點的集合。壹個頂點(Vertex)是壹個3D坐標的數據的集合。而頂點數據是用頂點屬性(Vertex Attribute)表示的,它可以包含任何我們想用的數據。

圖形渲染管線的第壹個部分是 頂點著色器 (Vertex Shader),它把壹個單獨的頂點作為輸入。頂點著色器主要的目的是把3D坐標轉為另壹種3D坐標(後面會解釋),同時頂點著色器允許我們對頂點屬性進行壹些基本處理。

圖元裝配 (Primitive Assembly)階段將頂點著色器輸出的所有頂點作為輸入(如果是GL_POINTS,那麽就是壹個頂點),並所有的點裝配成指定圖元的形狀;本節例子中是壹個三角形。

圖元裝配階段的輸出會傳遞給 幾何著色器 (Geometry Shader)。幾何著色器把圖元形式的壹系列頂點的集合作為輸入,它可以通過產生新頂點構造出新的(或是其它的)圖元來生成其他形狀。例子中,它生成了另壹個三角形。

幾何著色器的輸出會被傳入 光柵化階段 (Rasterization Stage),這裏它會把圖元映射為最終屏幕上相應的像素,生成供片段著色器(Fragment Shader)使用的片段(Fragment)。在片段著色器運行之前會執行 裁切 (Clipping)。裁切會丟棄超出妳的視圖以外的所有像素,用來提升執行效率。

片段著色器 的主要目的是計算壹個像素的最終顏色,這也是所有OpenGL高級效果產生的地方。通常,片段著色器包含3D場景的數據(比如光照、陰影、光的顏色等等),這些數據可以被用來計算最終像素的顏色。

在所有對應顏色值確定以後,最終的對象將會被傳到最後壹個階段,我們叫做 Alpha測試 和 混合 (Blending)階段。這個階段檢測片段的對應的深度(和模板(Stencil))值,用它們來判斷這個像素是其它物體的前面還是後面,決定是否應該丟棄。這個階段也會檢查 alpha 值(alpha值定義了壹個物體的透明度)並對物體進行 混合 (Blend)。所以,即使在片段著色器中計算出來了壹個像素輸出的顏色,在渲染多個三角形的時候最後的像素顏色也可能完全不同。

可以看到,圖形渲染管線非常復雜,它包含很多可配置的部分。然而,對於大多數場合,我們只需要配置頂點和片段著色器就行了。幾何著色器是可選的,通常使用它默認的著色器就行了。

在現代OpenGL中,我們必須定義至少壹個頂點著色器和壹個片段著色器(因為GPU中沒有默認的頂點/片段著色器)。

OpenGL 首先接收用戶提供的 幾何數據 (頂點和幾何圖元),並且將它輸入到壹系列 著色器階段 中進行處理,包括:頂點著色、細分著色(它本身包含兩個著色器),以及最後的幾何著色,然後它將被送入 光柵化單元(rasterizer) 。光柵化單元負責對所有 剪切區域(clipping region) 內的圖元生成 片元數據 ,然後對每個生成的片元都執行壹個 片元著色器 。

沒必要每次繪圖時都復制頂點數據,而是在 圖形內存中緩存 這些數據,這樣可以顯著改善渲染性能,也可以降低內存帶寬和電力消耗需求。這就是 頂點緩沖區 對象發揮作用的地方

頂點數組對象 :Vertex Array Object,VAO 保存緩存以及頂點屬性狀態信息。

頂點緩沖對象 :Vertex Buffer Object,VBO 用於分配內存,保存頂點數據 給圖形卡使用的壹種緩存對象。

索引緩沖對象 :Element Buffer Object,EBO或Index Buffer Object,IBO 保存頂點索引的壹種緩存對象。

在定義好頂點數據以後,需要在內存中存儲這些頂點,我們通過 頂點緩沖對象(Vertex Buffer Objects, VBO) 管理這個內存,它會在GPU內存(通常被稱為顯存)中儲存大量頂點。使用這些緩沖對象的好處是我們可以壹次性的發送壹大批數據到顯卡上,而不是每個頂點發送壹次。從CPU把數據發送到顯卡相對較慢,所以只要可能我們都要嘗試盡量壹次性發送盡可能多的數據。當數據發送至顯卡的內存中後,頂點著色器幾乎能立即訪問頂點,這是個非常快的過程。

下面是壹個生成頂點緩沖區的例子

glGenBuffers(GLsizei n, GLuint * buffers) :分配n個緩沖區對象名稱,並在buffers中返回它們。

glBindBuffer 用於指定當前緩沖區對象。第壹次通過調用

glBindBuffer 綁定緩沖區對象名稱時,緩沖區對象可以默認狀態分配;如果分配成功,則分配的對象綁定微目標的當前緩沖區對象。

glBufferData 用於創建和初始化頂點數組或元素數組。

簡而言之,光柵化階段繪制對應的圖元(點、線、三角形),將 圖元 轉化為壹組 二維數組 的過程,然後傳遞給 片元著色器 處理。這些二維數組代表屏幕上繪制的 像素

片元著色器主要是對 光柵化 處理後生成的片元 逐個進行 處理(並行)。接收頂點著色器輸出的值,需要傳入的數據,以及它經過變換矩陣後輸出值存儲位置。

關於混合可以參考 這篇文章

拓展閱讀:

iOS 渲染原理解析

  • 上一篇:模具最高級工種是什麽?
  • 下一篇:墨菲定律等五大定律
  • copyright 2024編程學習大全網