DirectX12 3D 游戲開發與實戰第五章內容


渲染流水線

學習目標:

  1. 了解用於在2D圖像中表現出場景立體感和空間深度感等真實效果的關鍵因素
  2. 探索如何用Direct3D表示3D對象
  3. 學習如何建立虛擬攝像機
  4. 理解渲染流水線,根據給定的3D場景的幾何描述,生成其2D圖像的流程

5.1 3D視覺即錯覺?

1、從視覺觀察效果來看,平行線最終會相交於一點(消失點,又稱為滅點),因此我們可以得出結論:隨着深度(z方向)的增加,物體會顯得越來越小、(dx是左手坐標系,OpenGL是右手坐標系)。

2、我們都知道物體重疊,這是一個重要的概念,即不透明的物體可以遮擋住其后側物體的局部或整體,它傳達了不同物體在場景中的深度順序關系

3、光照和陰影的處理在刻畫3D物體的實體形狀和立體感中扮演着至關重要的角色,其中陰影擔負着兩個重要的任務,即暗示了光源在場景中的相對位置和物體相對於某物的大概位置。

5.2 模型的表示

實際上,實體3D對象是借助三角形網格來近似表示的,三角形是3D物體建模的基石,我們可以用三角形網格模擬出任何真實世界中的3D物體。當然,點和線也是必不可少的,例如,我們可以用一系列寬度為1像素的線段繪制出一條近似曲線。

在游戲開發的過程中,我們一般都不會自己手動列出三角形來模擬3D物體,這樣太累了,一般來說,除了最簡單的模型,我們大部分模型都是在3D建模工具(3D )中完成。在游戲開發中流行的建模軟件有:3D Studio Max、LightWave 3D、Maya、Softimage和Blender。

5.3 計算機色彩基礎

計算機顯示器中每一個像素發出的顏色都是紅綠藍三色混合光,當混合的光線進入觀察者眼中,照射到視網膜的特定區域時,視錐細胞便受到刺激產生神經沖動,並通過視神經傳到大腦,大腦繼而解釋傳來的信號並感知顏色。因為混合光的變化各異,所以細胞受到的刺激也不盡相同,所以我們就能感知到不同顏色間的差異了

每款顯示器能發出的紅綠藍三種顏色的強度是有限的,為了便於描述光的強度,我們通常將它量化為范圍在0-1歸一化區間中的值,0代表無強度,1代表最強的強度,由此我們可以使用3D向量(r,g,b)來表示顏色,這三個分量分別表示紅綠藍三色光在混合光中的強度

5.3.1 顏色運算

5.3.2 128位顏色

事實上,我們通常會使用到一種名為alpha分量(alpha component)的顏色分量,alpha分量常用於表示顏色的不透明度(0.0表示完全透明,1.0表示完全不透明),它在混合技術中將會起到至關重要的作用。加上這個分量之后,我們便可以使用4D向量(r,g,b,a)來表示每一種顏色

為了使用128位數據來表示一種顏色,每一個分量都要使用浮點值。由於每一種顏色都可以使用4D向量來表示,所以我們在代碼中可以使用XMVECTIR類型來描述他們,然后通過DriectXMath向量函數來進行顏色運算。因此我們也可以借助SIMD技術加快數據的處理速度。

5.3.3 32位顏色

為了用32位數據表示一種顏色,每一個分量盡可以分配到一個字節,因此每一個占用8位字節的顏色分量就可以分別描述256中不同的顏色強度(0代表無強度,256代表最強強度),這樣四個顏色分量一共可以產生255的四次方種顏色,在DirectXMath庫中提供了XMCOLOR結構體來存儲32位顏色。

128位顏色和32位顏色之間是可以相互轉換的,只要將32位顏色向量的每一個分量值/255就可以得到對應的128位顏色向量。由於在XMCOLOR中通常將4個8位顏色分量封裝成一個32位整數值(例如一個unsigned int類型的值),因此在32位顏色和128位顏色之間的轉換通常要進行一些額外的運算,對此,DirectXMath庫提供了一個獲取XMCOLOR類型實例並且返回對應的XMVECTOR類型值的函數:

XMVECTOR XM_CALLONV PackedVector::XMLoadColor(const XMCOLOR* pSource);

除此之外,DirectXMath庫還提供了一個可以將XMVECTOR類型值轉換成XMCOLOR類型值的函數:

void XM_CALLCONV PackedVector::XMStoreColor(XMCOLOR pDestination, FXMVECTOR V);

128位顏色通常用於高精度的顏色運算,例如位於像素着色器內的各種運算。不過最終存儲在后台緩沖區中的顏色一般都是32位顏色。

5.4 渲染流水線概述

渲染流水線:若給出某一個3D場景的幾何描述,並在其中放置一台具有確定位置和朝向的虛擬攝像機,那么渲染流水線則是以此攝像機為觀察視角而生成的2D圖像的一系列步驟

先上圖:

圖片為手機拍攝,望見諒(圖片來源:DirectX 12 3D 游戲開發實戰)

上圖中左側表示的是組成渲染流水線的所有階段,右側則是顯存資源,從資源內存池指向渲染目標流水線階段的箭頭表示該階段可以讀取資源並可以以資源作為輸入,從渲染流水線指向資源內存池的箭頭則表示該階段可以向GPU資源寫入數據。接下來我們將詳細介紹渲染流水線每一個階段。如我們所見,大多數階段可以進行讀取資源的操作,但是只有少部分階段才可以對GPU資源進行寫操作。(渲染流水線中每一個階段所輸出的數據往往都是下一個階段的輸入)

  1. 輸入裝配器階段(從顯存讀取資源,然后將資源裝配成幾何圖元)
  2. 頂點着色器階段(處理裝配完畢的圖元的頂點數據)
  3. 外殼着色器階段(略)
  4. 曲面細分階段(增加三角形網格數量,該階段為可選階段)
  5. 域着色器階段(略)
  6. 幾何着色器階段(后續再進行介紹,該階段為可選階段)
  7. 流輸出階段(略)
  8. 光柵化階段(計算三角形對應的像素顏色)
  9. 像素着色器階段(根據光柵化階段計算的結果(即頂點屬性插值)為每一個像素添加顏色)
  10. 輸出合並階段(對像素片段進行篩選,然后把像素片段寫入后台緩沖區)

5.5 輸入裝配階段

輸入裝配器會從顯存中讀取幾何數據(頂點和索引(vertex and index)),再將它們裝配成幾何圖元。這些概念我們將會在后面陸續進行介紹

5.5.1 頂點

在數學上,三角形的頂點是兩條邊的交點,線段的頂點是它的兩個端點,對於單個的點來說,它本身就是一個頂點

在Direct3D中,頂點不僅可以用來表示位置信息,還可以包含其他的信息。例如:我們將在第八章為頂點添加法向量依次來實現光照效果,在第九章中我們會為頂點添加紋理坐標從而實現紋理貼圖。Direct3D為用戶自定義頂點格式提供了很高的靈活性,在第六章我們會講解一些和頂點有關的代碼

5.5.2 圖元拓撲

在Direct3D中,我們要通過一種名為頂點緩沖區的特殊數據結構來將頂點和渲染流水安綁定在一起,頂點緩沖區利用連續的內存來存儲一系列頂點,但是僅憑頂點緩沖區是無法說明這些頂點將如何組成幾何圖元,因此我們需要指定圖元拓撲(primitive topology)來告知Direct3D要以何種方式來表示幾何圖元。

void ID3D12GraphicsCommandList::IASetPrimitiveTopology{
D3D_PRIMITIVE_TOPOLOGY PrimitiveTopology
};

typedef enum D3D_PRIMITIVE_TOPOLOGY {
	D3D_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
	D3D_PRIMITIVE_TOPOLOGY_POINTLIST = 1,
	D3D_PRIMITIVE_TOPOLOGY_LINELIST = 2,
	D3D_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,
	D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 4,
	D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5,
	D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10,
	D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11,
	D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 12,
	D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 13,
	.
	.
	.
	D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64,
}D3D_PRIMITIVE_TOPOLOGY;

在用戶通過命令列表修改圖元拓撲之前,所有的繪制調用都會沿用當前設置的圖元拓撲,下面將舉一個通過命令列表對圖元拓撲進行修改的代碼示例:

//通過三角形列表的方式來繪制對象
mCommandList->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

5.2.2.1 點列表

通過枚舉項D3D_PRIMITIVE_TOPOLOGY_POINTLIST來指定點列表,當使用該圖元拓撲時,所有的頂點都將在繪制過程中繪制成一個單獨的點

5.2.2.2 線條帶

通過枚舉項D3D_PRIMITIVE_TOPOLOGY_LINESTRIP來指定線條帶,當使用該圖元拓撲時,頂點將會在繪制調用的過程中被繪制成一系列連續的線段,所以在這種模式下,n + 1個頂點就會生成n條線段

5.2.2.3 線列表

通過枚舉項D3D_PRIMITIVE_TOPOLOGY_LINELIST來指定線列表,當使用該圖元拓撲時,頂點在繪制調用時會被繪制成一系列單獨的線段,所以在這種模式下,2n個頂點就會生成n條線段

5.2.2.4 三角形帶

通過枚舉項D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP來指定三角形帶,當使用該圖元拓撲時,頂點在繪制調用時會被繪制成一系列連續的三角形,所以在這種模式下,n個頂點可以生成n - 2個三角形(三角形帶的繞序為為順時針方向)

5.2.2.5 三角形列表

通過枚舉項D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST來指定三角形列表,當使用該圖元拓撲時,頂點在繪制調用時會被繪制成一系列獨立的三角形,所以在這種模式下,3n個頂點就會生成n個三角形

5.2.2.6 具有鄰接數據的圖元拓撲

5.2.2.7 控制點面片列表

D3D_PRIMITIVE_TOPOLOGY_N_CONTROL_POINT_PATCHLIST拓撲類型表示:將頂點數據解釋為具有N個控制點(control point)的面片列表,(此圖元常用與渲染流水線的曲面細分階段,此階段為可選階段),這種圖元拓撲類型我們將會在第十四章再次進行討論

5.5.3 索引

在前面我們提到過,三角形是3D實體對象的基本組成部分,所以為三角形指定頂點順序是十分重要的工作,我們把這個順序稱之為繞序。

構成3D物體的不同三角形之間會共用許多頂點,比如一個四邊形,從數學上來看它只有四個頂點,但是在Direct3D中,繪制一個四邊形必須要使用兩個三角形,即有六個頂點,如果不重復利用頂點數據,那么我們需要創建六個頂點(其中有兩個頂點數據是重復的)來繪制一個四邊形,這明顯不是我們希望看到的結果,所以我們一般都會借助三角形帶或者是索引來解決這個問題

三角形帶:借助三角形帶可以改善頂點數據的重復創建問題,因為三角形帶圖元拓撲可以使頂點在繪制調用的過程中繪制成一系列連續的三角形。但如果想使用三角形帶改善這個問題,前提是這些幾何體必須是能夠組織成帶狀的

索引:這是我們推薦的解決方法,整個工作流程是這樣的:

  1. 先創建一個頂點列表和索引列表
  2. 在頂點列表中收錄一份所有獨立的頂點,並在索引列表中存儲頂點列表的索引值
  3. 這些索引定義了頂點列表中的頂點是如何組合在一起的,從而構成三角形

通過以上的操作,我們就把“復用的頂點數據”轉換為索引列表了,這樣便可以對一個頂點數據進行多次調用。

5.6 頂點着色器階段

待圖元被裝配完畢之后,其頂點會被送到頂點着色器階段(vertex shader state),我們可以把頂點着色器看成一種輸入數據和輸出數據都是單個頂點的函數,每一個要被繪制的頂點都必須要經過頂點着色器的處理之后才可以送往后續階段。事實上,我們可以認為在硬件中執行的是下列處理操作

for (UINT i = 0; i < numVertices; ++i)
{
	outputVertex[i] = VertexShader(intputVertex[i]);
}

其中的頂點着色器函數(VertexShader)就是我們要實現的部分,由於這個階段的操作是由GPU完成的,所以一般速度都會很快

在后續的章節中,我們會看到各種不同的頂點着色器示例,所以在學習完本書之后,我們應該要對頂點着色器可以時間的具體功能有一個深刻的認識。接下來,我們將介紹幾種常用的空間變換

5.6.1 局部空間和世界空間

設想:如果我們正在拍一部電影,我們所在的團隊需要為一些特效鏡頭打造一個和火車有關的微縮場景,其中我們的具體任務是制作一架袖珍小橋,當然,我們不會把小橋直接搭建在場景之中,否則我們便需要在一個極其復雜的環境中小心翼翼的工作,以防止破壞場景中的其他物體,一旦失手便會功虧一簣,相對來講,我們更加願意在遠離場景的工作室內制作這個袖珍小橋,等制作完成之后在將它以恰當的角度放在場景中合適的位置

3D美工在工作的時候也和上述設想一樣,他們不會直接在世界坐標系(世界空間)中直接構建物體的幾何形狀,而是選擇在相對於局部坐標系(局部空間)來創建物體。只要在局部空間定義了3D模型的各頂點,我們就能將它變換到世界空間中,為了做到這一點,我們必須要定義局部空間和世界空間兩者之間的聯系。具體的做法是:根據物體的位置和朝向,指定其局部空間坐標系的原點和每個坐標軸相對於世界坐標系的坐標,再運用坐標變換即可將物體從局部空間轉換到世界空間了。將局部坐標系內的坐標轉換到世界坐標系中的過程稱為世界變換,所使用的矩陣稱為世界矩陣,由於場景中,每一個物體的朝向和位置都可以各不相同,因此它們都會有屬於自己特定的世界矩陣。

在每一個3D模型各自的局部坐標系中的優點如下:
1、易於使用,在局部坐標系中定義物體可以很輕松的確定各個頂點的坐標

2、物體應該要可以跨越多個場景重復使用,如果將物體坐標相對於某一個特定場景進行硬編碼則會多出很多麻煩

3、我們有時候需要在同一場景中繪制多個同一物體,但是它們的位置、方向和大小不一樣,將物體繪制在局部空間可以解決這個問題。(我們通常將存儲一份幾何體相對於其局部空間的副本,接着按需求次數來繪制該物體,並使用不同的世界矩陣來指定物體在世界空間中的位置、大小和方向,這種方法稱為實例化)

一般來說,為了構建一個世界矩陣,我們必須要弄清局部空間中原點和各坐標軸相對於世界空間的坐標關系,但實際上,獲取這個關系並不容易而且也不直觀,所以我們一般采用一種更直觀的方式:定義一系列的變換組合W,即W = SRT;

S:縮放矩陣,將物體縮放到世界空間

R:旋轉矩陣,用來定義物體在局部空間相對於世界空間的朝向

T:平移矩陣,定義的是物體在局部空間相對於世界空間的位置

通過定義一系列的變換組合W,便可以在不指明局部空間的原點以及各坐標軸相對於世界空間的齊次坐標的情況下,直接通過復合一系列簡單的變換來建立世界矩陣

5.6.2 觀察空間

為了構建場景的2D圖像,我們必須在場景中架設一台虛擬攝像機,該攝像機確定了觀察者可以見到的視野,也就是生成2D圖像所需要的場景空間范圍,所以我們要為該攝像機賦予一個局部坐標系,該坐標系稱為觀察坐標系,也稱為觀察空間。虛擬攝像機會位於觀察坐標系的原點,並且朝z軸的正方向進行觀察,y軸位於攝像機的上方,x軸位於攝像機的右側(dx使用左手坐標系,OpenGL使用右手坐標系)。觀察空間用於在渲染流水線后續階段描述這些頂點相對於觀察坐標系的位置,由世界空間到觀察空間的坐標變換稱之為觀察變換(視圖變換),所使用的矩陣稱為觀察矩陣

假設矩陣w為物體從觀察空間轉換到世界空間的變換矩陣,則從觀察空間轉換到世界空間的變換矩陣V = W的逆矩陣。

接下來我們將介紹一種構建觀察矩陣的直觀方法:

假設Q為攝像機的位置,T為被觀察的目標點的坐標,j表示世界空間y軸方向的單位向量,則

觀察坐標系的z軸方向的單位向量w為:(T - Q) / ||T - Q||

觀察坐標系的x軸方向的單位向量u為:(j x w) / ||j x w||

觀察坐標系的y軸方向的單位向量v為:w x v

綜上所述,只有給定攝像機的位置,觀察目標點以及世界空間中y軸方向的向量,就可以構建出該世界空間對應的觀察空間的觀察矩陣,DirectXMath庫針對上述計算觀察矩陣的方法提過了一個函數:

//輸出對應的觀察矩陣
XMMATRIX XM_CALLCONV XMMatrixLookAtLH(
	FXMVECTOR EyePosition,				//輸入虛擬攝像機的位置
	FXMVECTOR ForcusPosition,			//輸入觀察目標點的位置
	FXMVECTOR UpDriecttion				//輸入世界空間向上方向的向量
)

5.6.3 投影和齊次裁剪空間

前一節我們介紹了攝像機在世界空間的位置和朝向,除此之外,虛擬攝像機還有一個重要的組成要素,那就是攝像機可以觀測到的空間體積(volume of space),此范圍可以用一個由四棱錐截取的平截頭體(四棱台)表示。所以我們的下一個任務便是將平截頭體內的3D幾何體投影到2D投影窗口中,根據前文的透視投影的原理可知,投影必定會隨着眾平行線匯聚於消失點,其投影的尺寸也將會隨着物體3D深度的增加而變小。

圖片為手機拍攝,望見諒(圖片來源:DirectX 12 3D 游戲開發實戰)

5.6.3.1定義平截頭體

在觀察空間中,我們可以通過近平面n(near plane)、元平面f(far plane)、垂直視場角a(vertical field of view Angle)以及投影窗口的縱橫比r這四個參數來定義一個以原點為中心,並且沿z軸正方向進行觀察的平截頭體。接下來我們將介紹這四個參數的意義:

圖片為手機拍攝,望見諒(圖片來源:DirectX 12 3D 游戲開發實戰)

1、近平面n:如圖

2、遠平面f:如圖

3、垂直視場角a:如圖

4、投影窗口的縱橫比r:投影窗口實際是就是觀察空間中場景的2D圖像,由於該圖像最終將會被映射到后台緩沖區中,因此,我們希望投影窗口和后台緩沖區兩者的縱橫比保持一致,所以我們通常把投影窗口的縱橫比指定為后台緩沖區的縱橫比。假如后台緩沖區的大小為800 x 600,則投影窗口的縱橫比為800 / 600。

下面還有很多內容:略

5.6.3.2 投影頂點

5.6.3.3 規格化設備坐標

5.6.3.4用矩陣來表示投影公式

5.6.3.5 歸一化深度值

XMMatrixPerspectiveFovLH函數

我們可以利用DirectXMath庫里的XMMatrixPerSpectiveFovLH函數構建對應的投影矩陣

//構建投影矩陣
XMMATRIX XM_CALLCONV XMMatrixPerspectiveFovLH(
	float FovAngleY,			//用弧度制表示的垂直視場角
	float Aspect,				//投影窗口的縱橫比(一般都與后台緩沖區的縱橫比相等)
	float NearZ,				//虛擬攝像機的位置(觀察點)到近平面的距離
	float FarZ					//虛擬攝像機的位置(觀察點)到遠平面的距離
);

下面的代碼片段為XMMatrixPerspectiveFovLH函數構建一個對應垂直視場角為45度,近平面位於z = 1.0f,遠平面位於z = 1000.0f的平截頭體的投影矩陣的用法:

XMMATRIX p = XMMatrixPerspectiveFovLH(0.25*XM_PI, AspectRatio(), 1.0f, 1000.0f);

縱橫比采用的是我們窗口的寬高比:

float D3DApp::AspectRatio()const
{
	return static_cast<float>(mClientWidth / mClientHeight);
}

5.7 曲面細分階段

曲面細分階段(tessellation stage)是利用鑲嵌化處理技術對網格中的三角形進行細分,以此來增加物體表面的三角形數量。然后將這些三角形偏移到合適的位置,就可以使網格展現出更加細膩的細節。使用曲面細分的優點主要有以下幾方面:

  1. 借此實現一種細節層次機制。我們可以使距離虛擬攝像機較近的三角形進行鑲嵌化處理,距離虛擬攝像機較遠的三角形則不進行處理
  2. 我們可以在內存中僅維護低模(低精度模型)網格,再根據需求為它動態添加三角形,以此節省內存資源
  3. 我們在處理動畫和物理模擬的時候可以使用簡單的低模網格,而僅在渲染的過程中使用經鑲嵌化處理的高模網格

曲面細分是一個可選的渲染階段,我們將在第十四章對此階段進行詳細的講解。

5.8幾何着色器階段

幾何着色器階段是一個可選的渲染階段,由於我們在第十二章才會用到它,所以我們這里只對它進行簡單的介紹。

  1. 幾何着色器接受的輸入必須是完整的圖元,假設我們正在繪制三角形列表,那么向幾何着色器輸入的一定是定義三角形的三個頂點(這三個頂點已經被頂點着色器處理過的)
  2. 幾何着色器的主要優點是可以銷毀和創建幾何體,比如說,我們可以利用幾何着色器將輸入的圖元擴展稱為一個或多個圖元,或者是根據一些條件而選擇不輸出任何圖元
  3. 頂點着色器與幾何着色器相比,頂點着色器不能創建頂點,它只能接受單個頂點的輸入,然后將處理后的單個頂點輸出。幾何着色器的拿手好戲是將一個點或者一條線擴展成一個四邊形

5.9 裁剪

完全位於視椎體(用戶在3D空間內的可視范圍,形狀類似於平截頭體,視椎體也被稱為視平截頭體)之外的幾何體需要被完全拋棄,而處於視平截頭體交界的幾何體也要接受此裁剪的操作。因此,只有在視平截頭體之內的物體對象才會被完全保留下來。

由於裁剪操作是由硬件負責完成的,我們在這里並不會進行過多的講解,如果對裁剪過程有興趣的話,可以了解一下蘇澤蘭-霍啟曼裁剪算法,這個算法的整體思路是找到平面和多邊形的所有交點,然后將這些頂點按順序組織成新的裁剪多邊形。

5.10 光柵化階段

光柵化階段(rasterization stage)的主要任務是為投影到主屏幕上的3D三角形計算出相應的像素顏色

5.10.1 視口變換

當裁剪操作完成之后,硬件會通過透視除法將物體從齊次裁剪空間變換到規格化設備坐標(NDC),一旦物體的頂點位於NDC空間之內,構成2D圖像的2D頂點x,y坐標就會被變換到后台緩沖區中稱為視口的矩形之中,此變換完成會后,這些x,y坐標都會以像素為單位進行表示。(一般來說,由於z坐標經常在深度緩沖技術里面用作為深度值,所以視口變換一般都不會影響到z坐標)

背面剔除

每一個三角形都有兩個面,在Direct3D中會采用以下約定對這兩個面進行區分,假設組成三角形順序的頂點為v1,v2,v3,那么我們會通過以下計算來得到這個三角形的法線:

e1 = v2 - v1;

e2 = v3 - v1;

n = (e1 x e2) / (||e1 x e2||)

法向量由正面射出,則另一面為三角形的背面。在這種約定之下,根據觀察者的視角看過去,頂點繞序為順時針方向的為正面朝向,頂點繞序為逆時針方向的位背面朝向。由於背面朝向的三角形都會被正面朝向的三角形遮擋,所以繪制背面朝向的三角形是沒有意義的,背面剔除就是用於將背面朝向的三角形從渲染流水線中剔除的流程,這種操作可以將待處理的三角形數量減少一半。

在默認的情況下,Direct3D將以觀察者的視角把順時針繞序的三角形看作是正面朝向的,把逆時針繞序的三角形視為是背面朝向的,但是,通過對Direct3D渲染狀態的設置,我們也可以把這個約定顛倒過來。

5.10.3 頂點屬性插值

回顧前文可知,我們要通過頂點來定義三角形,除了位置信息之外,我們還可以給頂點附加顏色、法向量、紋理坐標、深度值等其他屬性,經過視口變換之后,我們需要為求取三角形內每一個像素所附的屬性進行線性插值運算,為了得到屏幕空間中各個頂點的屬性插值,我們一般都會使用一種名為透視校正插值。從本質上來說,插值法即利用三角形的三個頂點屬性值計算出其內部像素的屬性值

我們無需考慮透視校正插值法處理像素屬性的數學細節,因為硬件會自動的完成相應的處理,如果有人對其中的數學細節感興趣。可以在[Eberly01]中找到相應的數學推導過程

5.11 像素着色器階段

我們編寫的像素着色器(pixel shader)是一種由GPU執行的程序,他會針對每一個像素片段進行處理(即每處理一個像素都要執行一次像素種着色器),並根據頂點的插值屬性作為輸入來計算出對應的像素顏色。像素着色器既可以返回一種單一的恆定顏色,也可以實現如逐像素光照、反射以及陰影等更為復雜的效果。

5.12 輸出合並階段

通過像素着色器生成的像素片段會被移送至渲染流水線的輸出合並階段,在此階段,一些像素片段可能會被丟棄(比如未通過深度測試或模板測試的像素片段)。而沒有被丟棄的像素片段則會被寫入后台緩沖區。

混合操作也是在輸出合並階段完成的,這項技術可以使當前處理的像素片段與后台緩沖區中原有的像素片段進行融合,而不是簡單的對后台緩沖區進行覆蓋。

小結

  1. 根據人們的生活經驗,我們可以總結一些規律用於Direct3D中:平行線會相聚於消失點、物體的尺寸受其深度的影響(近大遠小)、離觀察者近的物體會遮擋其后距觀察者遠的物體、光照和陰影的明暗對比可以刻畫出3D物體的實體形狀和體積感、陰影還暗示了光源的位置以及場景中不同物體之間的相對位置
  2. 我們用三角形網格來近似的表示3D物體對象,並通過指定三角形的3個頂點來定義三角形,在許多網格中都存在着頂點被不同三角形共用的情況,而索引列表則可以用於避免因為重復使用頂點而復制頂點數據所帶來的亢余信息
  3. 我們一般通過紅綠藍三色光的強度來描述顏色,利用三色光不同強度的相加混色,可以表示出數以千萬計種顏色。一般來說我們還會加入一種名為Alpha分量的顏色分量,這個分量用於表示顏色的不透明度,這在混合技術中是很有用的。綜上,我們可以使用4D顏色向量來表示四個顏色分量。
  4. 假設在一個場景中有一台虛擬攝像機,那么渲染流水線就是根據該虛擬攝像機的視角,生成能呈現在顯示器中對應的2D圖像的一系列完整的步驟
  5. 渲染流水線可以分為8個重要階段,分別是:輸入裝配階段、頂點着色器階段、曲面細分階段、幾何着色器階段、裁剪階段、光柵化階段、像素着色器階段、輸出合並階段。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM