[Unity3D]Shader學習筆記之渲染流水線

  渲染流水線的最終目的是在於生成或者說是渲染一張二維紋理,Shader僅僅只是其中的一個環節。

流水線的概念

  生產一個產品需要三個步驟ABC,每個步驟用一個單位時間,且每個步驟只能在前一個步驟完成後才能繼續進行,這樣生產一個產品需要三個單位時間。

Created with Raphaël 2.1.0非流水線AABBCC111

  如果引進流水線,那麼當A交給B後將不必等待C的完成,而繼續A的下一次生產,這樣生產過程近乎於並行的,所以生產一個產品需要一個單位時間。如果每個步驟的耗時不同的話,生產一個產品的時間則爲耗時最長的步驟所用的時間。

Created with Raphaël 2.1.0流水線AABBCC1122

渲染流水線

應用階段 (Application Stage)

  通常由CPU負責實現,這一階段最重要的是輸出渲染所需的信息,即渲染圖元(Rendering primitives)
最要有三個步驟:
1. 準備場景數據:使用了哪些模型及光源等。
2. 然後剔除(Culling):爲了提高性能,剔除不可見的物體。
3. 最後設置每個模型的渲染狀態:材質、紋理、Shader等。

幾何階段 (Geometry Stage)

  通常由GPU負責實現,負責和每個渲染圖元打交道,進行逐頂點、逐多邊行的操作。最重要的是把頂點座標變換到屏幕空間中。最後將輸出屏幕控件的二維頂點座標、每個頂點對應的深度值、着色器等相關信息。

光柵化階段 (Rasterizer Stage)

  通常由GPU負責實現,使用上一個階段傳遞的數據來產生屏幕上的像素。主要任務是決定每個渲染圖元中的哪些像素應該被繪製到屏幕上。它需要對上一個階段得到的逐頂點數據(例如紋理座標、頂點顏色等)進行差值,然後進行逐像素處理。

CPU和GPU之間的通信

  渲染流水線的起點是CPU,即應用階段。應用階段大致可分爲下面3個階段:

  1. 把數據加載到顯存中。
  2. 設置渲染狀態。
  3. 調用Draw Call。

  把渲染所需的數據加載到顯存中:顯卡對於顯存的訪問速度更快,而且大多數顯卡對於RAM沒有訪問權限。

Created with Raphaël 2.1.0硬盤HDD內存RAM顯存VRAM

  設置渲染狀態:狀態定義了場景中的網格是怎樣被渲染的。如果沒有更改渲染狀態,那麼所有的網格都將使用同一中渲染狀態。
  調用Draw Call:CPU通過調用Draw Call來告訴GPU開始進行一個渲染過程。一個Draw Call會指向本次調用需要渲染的圖元(Primitives)列表,而不會包含任何材質信息。 當給定了一個Draw Call時,GPU就會根據渲染狀態(例如材質、紋理、着色器等)和所有輸入的頂點數據來進行計算,最終輸出成屏幕上顯示的像素。

GPU流水線

  CPU通過Draw Call來命令GPU進行渲染,GPU的渲染過程就是GPU流水線。

Created with Raphaël 2.1.0頂點數據曲面細分着色器幾何着色器剪裁屏幕映射三角型設置三角形遍歷片元着色器逐片元操作屏幕圖像

幾何階段

  1. 頂點着色器(Vertex Shader):完全可編程的,通常用於實現頂點的空間變換、頂點着色等功能。
  2. 曲面細分着色器(Tessellation Shader):可選的着色器,用於細分圖元。
  3. 幾何着色器(Geometry Shader):可選着色器,用於執行逐圖元(Per-Primitive)的着色操作,或着被用與產生更多的圖元。
  4. 剪裁(Clipping):可配置的,將那些不在攝像機視野內的頂點剪裁掉,並剔除某些三角圖元的面片。
  5. 屏幕映射(Screen Mapping):不可編程和配置的,負責把每個圖元的座標轉換到屏幕座標系中。

頂點着色器

  1. 是流水線的第一個階段,它的輸入來自CPU。
  2. 處理單位是頂點,輸入進來的每個頂點都會調用一次頂點着色器。
  3. 頂點着色器本身不可以創建或者銷燬任何頂點,而且無法得到頂點與頂點之間的關係。
  4. 主要工作是座標變換和逐頂點光照。
    座標變換:把頂點座標從模型空間轉換到齊次剪裁空間。可改變頂點的位置,頂點動畫等。

剪裁

  1. 圖元和攝像機的關係:
    完全在視野內:傳遞給下一個流水線階段
    部分在視野內:不會繼續傳遞,不需要被渲染
    完全在視野外:進行剪裁,視野外的頂點應該使用一個新的頂點來代替,這個新的頂點位於邊界的交點處,原先不可見的頂點則會被捨棄。
  2. 是不可編程的。

屏幕映射

  1. 任務是把每個圖元的x和y座標轉換到屏幕座標(Screen Coordinates)。
  2. 屏幕座標系和z座標一起構成了一個座標系,叫做窗口座標系(Window Coordinates)。
  3. 屏幕座標系差異:
    OpenGL:左下角爲(0,0)
    Direct3D:左上角爲(0,0)

光柵化階段

  1. 三角形設置(Triangle Setup)和三角形遍歷(Triangle Traversal):固定函數(Fixed-Function)階段。
  2. 片元着色器(Fragment Shader):完全可編程的,用於實現逐片元(Per-Fragment)的着色操作。
  3. 逐片元操作(Per-Fragment):不是可編程的,但有很高的可配置性,負責執行很多重要的操作,如修改顏色、深度緩衝、進行混合等。

三角形設置

  1. 計算光柵化一個三角網絡所需的信息。
  2. 目標是計算每個圖元覆蓋了哪些像素,以及爲這些像素計算它們的顏色。

三角形遍歷

  1. 檢查每個像素是否被一個三角網絡所覆蓋,如果被覆蓋的就生成一個片元(Fragment),這個過程也稱爲掃描變換(Scan Conversion)。
  2. 輸出的到片元序列。一個片元不是真正意義上的像素,而是包含了許多狀態的集合,這些狀態用於計算每個像素的最終顏色。

片元着色器

  1. 非常重要的可編程着色器階段。在DirectX中又被稱爲像素着色器(Pixel shader)
  2. 這一階段可以完成許多重要的渲染技術,如紋理採樣。
  3. 輸入是上一個階段對頂點信息插值得到的結果,輸出是一個或多個顏色值

逐片元操作

  1. 逐片元操作是OpenGL中的說法,在DirectX中稱爲輸出合併階段(Output-Merger)
  2. 這一階段主要任務:
    • 決定每個片元的可見性。這涉及到許多測試工作,例如深度測試、模版測試等。
    • 如果一個片元通過了所有的測試,就需要把這個片元的顏色值和已經存儲在顏色緩衝區中的顏色進行合併,或者說是混合。
Created with Raphaël 2.1.0片元模版測試深度測試混合顏色緩衝區

模版測試 (Stencil Test)

  如果開啓了模板測試,GPU會首先讀取(使用讀取掩碼)模版緩衝區中該片元位置的模版值,然後將該值和讀取(使用讀取掩碼)到的參考值(Reference value)進行比較,這個比較函數可以是由開發者指定的。如果這個片元沒有通過這個測試,該片元就要會被捨棄。

深度測試 (Depth Test)

  如果開啓了深度測試,GPU會把該片元的深度值和已經存在於深度緩衝區中的深度值進行比較。如果這個片元沒有通過這個測試,該片元就要會被捨棄。

混合 (Blend)

  對於不透明的物體可以關閉混合,這樣片元着色器計算的到的值就可以直接覆蓋掉顏色緩衝區的像素值。
  但對於半透明物體需要開啓混合。如果開啓了混合,GPU會取出源顏色和目標顏色,將兩種顏色進行混合。源顏色指的是片元着色器的到的顏色值,而目標顏色則是已經存在於顏色緩衝區中的顏色值。之後就會使用一個混合函數來進行混合操作,這個混合函數通常和透明通道相關。

雙重緩衝 (Double Buffering)

  當模型的圖元經過了層層計算和測試後,就會顯示在屏幕上。屏幕顯示的就是顏色緩衝區中的顏色值。但是爲了避免看到那些正在進行光柵化的圖元,GPU會使用雙重緩衝的策略。
  這意味着,對場景的渲染是在幕後發生的,即在後置緩衝(Back Buffer)中。一旦場景已經被渲染到了後置緩衝中,GPU就會交換後置緩衝區和前置緩衝(Front Buffer)中的內容,而前置緩衝區是之前顯示在屏幕上的圖像。由此保證了看到的圖像總是連續的。

這裏寫圖片描述

發佈了48 篇原創文章 · 獲贊 9 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章