OpenGL學習之著色器與渲染管線

OpenGL學習之著色器與渲染管線

看此篇之前請看http://www.itdecent.cn/p/68ee05d6106a

著色器與渲染管線

渲染管線一般是有顯示芯片(GPU)內部處理圖形信號的并行處理單元組成。這些并行處理單元兩兩之間是相互獨立的,在不同型號的硬件上獨立處理單元的數(shù)量也有很大的差異。

圖中陰影部分是可編程的部分

enter image description here
  1. 基本處理
    該階段設定3D空間中物體的頂點坐標,頂點對應的顏色,頂點的紋理坐標等屬性,并且指定繪制方式。

  2. 頂點著色器
    頂點著色器是一個可編程的處理單元,功能為執(zhí)行頂點的變換,光照,材質的應用于計算等頂點的相關操作。工作過程為首先將原始的頂點幾何信息及其他屬性傳送到頂點著色器中,經過自己開發(fā)的頂點著色器處理后產生紋理坐標,顏色,點位置等后繼流程需要的各項頂點屬性信息,然后將其傳遞給圖元裝配階段。
    頂點著色器的輸入主要為待處理頂點相應的attribute變量,uniform變量,采樣器以及臨時變量;輸出主要為經過頂點著色器生成的varying變量及一些內建輸出變量。

頂點著色器的輸入數(shù)據(jù)由下面組成:
Attributes:使用頂點數(shù)組封裝每個頂點的數(shù)據(jù),一般用于每個頂點都各不相同的變量,如頂點位置、顏色等。
Uniforms:頂點著色器使用的常量數(shù)據(jù),不能被著色器修改,一般用于對同一組頂點組成的單個3D物體中所有頂點都相同的變量,如當前光源的位置。
Samplers:這個是可選的,一種特殊的uniforms,表示頂點著色器使用的紋理。
Shader program:頂點著色器的源碼或可執(zhí)行文件,描述了將對頂點執(zhí)行的操作。

輸出變量-易變比那里在頂點著色器賦值后并不是將賦的值送入后后繼的片元著色器中,而是在光柵化階段由管線根據(jù)片元所屬頂點對應的頂點著色器對此易變變量的賦值情況及片元與各項頂點的位置插值產生。

enter image description here

下面是一個用opengl es著色器語言編寫的頂點著色器源碼,這個頂點著色器使用一個position和跟它相關聯(lián)的color數(shù)據(jù)作為輸入數(shù)據(jù),通過一個4×4矩陣變換位置,然后輸出變換后的位置和顏色數(shù)據(jù)。

 // uniforms used by the vertex shader
 uniform mat4 u_mvpMatrix; // matrix to convert P from model
 // space to normalized device space.
 
 // attributes input to the vertex shader
 attribute vec4 a_position; // position value
 attribute vec4 a_color; // input vertex color

 // varying variables – input to the fragment shader
 varying vec4 v_color; // output vertex color
 void main() {
 v_color = a_color;
 gl_Position = u_mvpMatrix * a_position;
 }
  1. 圖元裝配(primitive assembly)
    頂點著色器之后,渲染管線的下一個階段是圖元裝配,圖元是一個能用OpenGL ES繪圖命令繪制的幾何體,繪圖命令指定了一組頂點屬性,描述了圖元的集合形狀和圖元類型。頂點著色器使用這些頂點屬性計算頂點的位置,顏色以及紋理坐標,這樣才能傳到片元著色器。
    這個階段主要有兩個任務,一個是圖元組裝,另一個是圖元處理。
    圖元組裝是指頂點數(shù)據(jù)根據(jù)設置的繪制方式被結合成完整的圖元,例如,點繪制方式下僅需要一個單獨的頂點,每個頂點為一個圖元;線段繪制方式則需要兩個頂點,每兩個頂點構成一個圖元。
    圖元處理最重要的工作是剪裁,對于每個圖元,必須確定它是否位于視椎體內(3維空間顯示在屏幕上的可見區(qū)域),如果圖元部分在視椎體中,需要進行裁剪,如果圖元全部在視椎體外,則直接丟棄圖元。裁剪之后,頂點位置轉換成了屏幕坐標。背面剔除操作也會執(zhí)行,它根據(jù)圖元是正面還是背面,如果是背面則丟棄該圖元。經過裁剪和背面剔除操作后,就進入渲染流水線的下一個階段:光柵化。

  2. 光柵化(Rasterization)
    光柵化階段把圖元轉換成片元集合,之后會提交給片元著色器處理,這些片元集合表示可以被繪制到屏幕的像素。如下圖所示:

enter image description here
  1. 片元著色器
    片元著色器是用于處理片元值及相關數(shù)據(jù)的可編程單元,其可以執(zhí)行紋理的采樣,顏色的匯總,計算霧顏色等操作。片元著色器主要功能為通過重復執(zhí)行(每片元一次)將3D物體中的圖元光柵化后產生的每個片元的顏色等屬性計算出來送入后繼階段;
    片元著色器對光柵化階段產生的每個片元進行操作,需要的輸入數(shù)據(jù)如下:
    • Varying variables:頂點著色器輸出的varying變量經過光柵化插值計算后產生的作用于每個片元的值。
    • Uniforms:片元著色器使用的常量數(shù)據(jù)
    • Samplers:一種特殊的uniforms,表示片元著色器使用的紋理。
    • Shader program:片元著色器的源碼或可執(zhí)行文件,描述了將對片元執(zhí)行的操作。

片元著色器也可以丟棄片元或者為片元生成一個顏色值,保存到內置變量gl_FragColor。光柵化階段產生的顏色、深度、模板和屏幕坐標(Xw, Yw)成為流水線中pre-fragment階段(FragmentShader之后)的輸入。如下圖:

enter image description here
  • Varting0~n值的是從頂點著色器傳遞到片元活色器的易變數(shù)據(jù)變量,它是由系統(tǒng)在頂點著色器后的光柵化階段自動插值產生,其個數(shù)不一定。

  • gl_FragColor值的是計算后此片元的顏色。一般在片元著色器的最后都需要對gl_FragColor進行賦值。

    下面是一個簡單的片元著色器源碼,可以跟上面的頂點著色器源碼結合繪制一個高洛德著色的三角形。

    precision mediump float;
    varying vec4 v_color; // input vertex color from vertex shader
    void main(void) {
    gl_FragColor = v_color;
    }

  1. 追個片元操作階段(Per-Fragment Operations)
    片元著色器之后就是追個片元操作階段,包括一系列的測試階段。一個光柵化階段產生的具有屏幕坐標(x,y)的片元,只能修改framebuffer(幀緩沖)中位置在(x,y)的像素。下圖是Opengl es 2.0逐片元操作的過程:
enter image description here

Pixel ownership test:像素所有權測試,決定framebuffer中某一個(Xw, Yw)位置的像素是否屬于當前Opengl ES的context,比如:如果一個Opengl ES幀緩沖窗口被其他窗口遮住了,窗口系統(tǒng)將決定被遮住的像素不屬于當前Opengl ES的context,因此也就不會被顯示。
Scissor test:裁剪測試,決定位置為(Xw, Yw)的片元是否位于裁剪矩形內,如果不在,則被丟棄。
Stencil and depth tests:模板和深度測試,傳入片元的模板和深度值,決定是否丟棄片元。
Blending:將新產生的片元顏色值和framebuffer中某個(Xw, Yw)位置存儲的顏色值進行混合。
Dithering:抖動,可以用來最大限度的減少使用有限精度存儲顏色值到framebuffer的工件。
逐片元操作之后,片元要么被丟棄,要么一個片元的顏色,深度或者模板值被寫入到framebuffer的(Xw, Yw)位置,不過是否真的會寫入還得依賴于write masks啟用與否。write masks能更好的控制顏色、深度和模板值寫入到合適的緩沖區(qū)。例如:顏色緩沖區(qū)中的write mask可以被設置成沒有紅色值寫入到顏色緩沖區(qū)。另外,Opengl ES 2.0提供從framebuffer中獲取像素的接口,不過需要記住的是像素只能從顏色緩沖區(qū)讀回,深度和模板值不能讀回。

注意:Opengl ES 2.0 的Per-Fragment Operations已經不再支持Alpha test 和 LogicOp了,這兩個步驟在 OpenGL 2.0 和 OpenGL ES 1.x中是存在的。Alpha test 階段不再需要的原因是片元著色器可以丟棄片元,所以可以在片元著色器中執(zhí)行Alpha test。 LogicOp因為很少使用,所以不再支持了。

  1. 幀緩沖
    OpeGL ES中的物體繪制并不是直接在屏幕上進行的,而是預先在幀緩沖區(qū)中進行繪制,每繪制玩一幀再將繪制的結果交換到屏幕上。因此,在每次繪制新的一幀時都需要清除緩沖區(qū)中的相關數(shù)據(jù),否則有可能產生不正確的繪制效果。
    同時,微課應對不同方面的需要,幀緩沖是由一套組件組成的,主要包括顏色緩沖,深度緩沖以及模板緩沖
    • 顏色緩沖用于存儲每個片元的顏色值,每個顏色值包括RGBA 4個色彩通道,應用程序運行時在屏幕上看到的就是顏色緩沖中的內容。
    • 深度緩沖用來存儲每個片元的深度值,所謂深度值是指以特定的內部格式表示的從片元處到觀察點(攝像機)的距離。在啟用深度測試的情況下,新片元想進入幀緩沖時需要將自己的深度值與幀緩沖中對應位置的片元的深度值進行比較,若結果小于才可能進行緩沖,否則丟棄。
    • 模板緩沖用來存儲每個片元的模板值,供模板測試使用。
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容