d3d12龍書閱讀----d3d渲染流水線
輸入裝配器階段
在輸入裝配器階段,會從視訊記憶體中讀取頂點與索引這種幾何資料,然後根據圖形基元的型別,根據索引將頂點組裝起來。
d3d中的圖形基元
我們來看看幾種常見的圖形基元型別:
typedef
enum D3D12_PRIMITIVE_TOPOLOGY_TYPE
{
D3D12_PRIMITIVE_TOPOLOGY_TYPE_UNDEFINED = 0,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT = 1,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE = 2,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE = 3,
D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH = 4
} D3D12_PRIMITIVE_TOPOLOGY_TYPE;
我們可以看到可以把圖形基元設定為未定義、點、線、三角形與控制點
索引
根據索引我們可以將頂點按照一定的順序組裝成一個個圖形基元,如上圖所示。
使用索引佔用的記憶體小,並且可以利用重複的頂點資料,大大降低了記憶體的使用,提高效率
頂點著色器階段
在硬體中頂點著色器執行的工作可用如下的虛擬碼表示:
頂點著色器 可對頂點的位置進行空間變換,也可以實現其它的特效
本章只討論了空間變換
區域性空間到世界空間
每個物體對應一個區域性座標系
當我們需要在不同的場景下繪製物體 或者在一個場景多次以不同的方式繪製同一個物體
這樣我們就可以使用不同的世界矩陣來將變換物體
世界空間到觀察空間
觀察空間 也就是攝像機對應的視椎體 從世界空間轉換到觀察空間 我們需要對座標軸進行變換:
我們需要利用攝像機的朝向得到w向量
利用世界座標系向上的向量j 叉積得到 u向量
最後再 w 與 u的叉積得到v向量 從而得到變換矩陣
d3d中也為我們完成了上述矩陣的推導函式:
觀察空間到裁剪空間
在觀察空間中 我們需要進行投影 將3d轉換為2d
我們假設視椎體的垂直視場角\(\alpha\) 縱橫比r 以及近平面n 與遠平面f
更進一步地 我們假設投影平面的高為2 這樣寬就為2r
利用相似關係 我們可以得到x y 的變換 同時我們也要保留z座標 用於深度的判斷
由於我們還需要對z座標進行歸一化 所以我們在對xy進行變換的同時 需要保留z座標的值 我們可以使用第四維w來儲存z
這樣我們分析得到的初始矩陣如下:
在d3d中,我們需要將z座標投影到0--1的範圍 在opengl中則是-1----1,所以我們可以得到兩個等式來求出上圖中未求出的A 與 B:
我們還可以對z的這種非線性變換作分析 畫出影像可知 絕大多數的深度值都被對映到較小的區域 這可能會對深度緩衝區的精度要求過高 導致無法區分兩個深度值
所以我們要儘可能的讓近平面與遠平面相差較大
裁剪空間到NDC空間
在裁剪空間完成 裁剪之後 我們進行透視除法 除以深度值 即進入NDC空間
曲面細分階段
曲面細分是在渲染過程中可選的一階段
它會將mesh中的三角形進行細分,增加三角形的數量,同時讓三角形的位置適當偏移,呈現出更多的細節。
為什麼要使用曲面細分?
首先,我們可以讓近處的三角形,也就是離攝像機更近的三角形得到更加豐富的細節,而遠處的三角形看不清則不做更改。
其次,我們在記憶體中只維護三角形數量較少的low-poly低模網格,再根據需求為其新增三角形,這樣可以節省記憶體資源
最後,我們在進行動畫與物理模擬時,使用低模網格,在進行渲染時採用高模網格。
在d3d11之前,曲面細分是在cpu端進行的,再將新的三角形上傳給gpu,而現在已經提供了一組api,可以在gpu端直接實現曲面細分。
幾何著色器階段
幾何著色器也是一個可選渲染階段
它的輸入是一個基本圖元,輸出是將該圖元擴充為其它多個圖元,或者銷燬圖元,主要起到銷燬或者建立幾何體的作用
光柵化階段
光柵化的主要目的是為投影到螢幕上三角形計算出對應的畫素顏色
視口變換
從NDC空間到螢幕空間 將xy轉換為以畫素為單位
背面剔除
觀察上述兩個三角形
如果我們假設三角形三個頂點的順序是v0,v1,v2 計算:
e1 = v1 - v0
e2 = v2 - v0
這兩個向量的叉積 如果是如上圖左邊那個三角形向外的 我們就認為是正面朝向 反之右邊則是背面朝向
而正面朝向的三角形會遮擋住背面朝向的三角形
上圖是2d情形下的遮擋 從觀察點看向該物件 背面朝向的三角形不可見
上圖是3d情形下的遮擋 左邊是完全透視情況下 右邊是實體模式 正面三個面把背面三個面擋住了
頂點屬性插值
利用透視校正插值 利用三角形三個頂點的屬性 插值得到內部畫素的屬性
畫素著色器階段
畫素著色器 是對輸入的每個畫素 根據頂點屬性插值 計算出畫素顏色 同時也能實現反射 陰影等更復雜的效果
輸出合併階段
在輸出合併階段 一些畫素可能會被丟棄 比如未透過深度測試或者模版測試 然後剩下的畫素會被寫入後臺緩衝區 在此過程中可能會經過blend操作