Direct3D渲染管線

轉載至  Direct3D渲染管線簡介

渲染管線負責執行一系列必要的步驟從而把3D場景轉換爲可以在顯示器上顯示的2D圖像。在Direct3D中,渲染管線的步驟大致如下:

(1)局部座標系到世界座標系

假設我們在製作一款遊戲,現在,要求構建一個鐵匠鋪用來放在遊戲場景中。我們不可能在遊戲場景(世界座標系)中構建鐵匠鋪,因爲我們不知道它會被放在哪裏,大小如何,以及朝向哪裏。所以,我們在局部座標系中構建鐵匠鋪,所謂局部座標系就是以物體本身爲中心的座標系,這樣的話,我們就不用考慮鐵匠鋪在遊戲場景中的因素。下圖顯示了一個立方體在局部座標系下的描述:

一旦我們在局部座標系中構建完物體後,我們就把它放在世界座標系中,爲了完成這個步驟,我們需要構建一個世界變換矩陣,關於構建世界變換矩陣,我們可以直接使用D3DX提供的接口直接構建一個世界變換矩陣。在這裏,我將介紹另一種構建世界變換矩陣的方法,因爲後面介紹視圖變換時會用到。

先看圖:

假設Frame A是局部座標系,Frame B是世界座標系,B爲局部座標系Frame A中的一點,那麼如何將B從局部座標系轉換到世界座標系呢?很簡單,假設B在局部座標系中的座標點描述爲(x, y),同時局部座標系Frame A的兩個座標軸以及原點在世界座標系Frame B中描述爲u,v以及o,那麼由圖可知,o + xu + yv即爲B在世界座標系中的描述。轉換到3D座標系是同樣的道理,只不過多了個z軸,那麼假設z軸在世界座標系中描述爲w,那麼將局部座標系中的某個點(x, y, z)轉換到世界座標系中可以寫爲o + xu + yv + zw。

由此,我們便構建出了世界變換矩陣,假設局部座標系的原點以及3個座標軸在世界座標系中分別被描述爲p,r,u以及f,那麼世界變換矩陣可以構建如下:

(2)世界座標系到視圖座標系

所謂視圖座標系就是攝像機所處的局部座標系,我們可以把攝像機想象爲一個在3D場景中的物體。在視圖座標系中,攝像機處於座標系中心,同時朝向z軸正方向。因爲把任意位置的物體進行投影變換是十分困難和低效的,所以我們把物體變換到視圖座標系後再進行投影變換。爲什麼要說明上面的那種構建世界變換矩陣的方法呢?因爲它以3個座標軸以及原點來構建世界變換矩陣。現在,假設視圖座標系的3個座標軸以及原點在世界座標系中描述爲r,u,f以及p,那麼我們知道將視圖座標系的物體轉換到世界座標系下的世界變換矩陣是,我們只要構建出它的逆矩陣,就可以將世界座標系中的物體轉換到視圖座標系。

由於變換矩陣可以分解成平移矩陣和旋轉矩陣的乘積,因此,我們可以構建逆矩陣如下:

(3)投影變換

在3D場景最終被轉換爲2D圖像顯示在顯示器上之前,還需要經過投影變換,Direct3D期望經過投影變換後的點處於標準視域體內(x,y的範圍是[-1, 1],z的範圍是[0, 1])。

爲了進行投影變換,我們需要定義平頭截體和橫縱比。平截頭體類似於被削平的金字塔,爲此我們需要定義一個近平面n,一個遠平原f,以及一個垂直範圍的可視角度α。而橫縱比通常定義爲後臺緩衝區的寬/高的值。如圖:

那麼我們如何根據垂直範圍的可視角度α求得水平範圍的可視角度β呢?根據三角公式,我們有tan(α/2) = d/n,以及tan(β/2) = c/n,同時由於R(橫縱比) = 2c / 2d ⇒ c = Rd。於是,我們可以得到tan(β/2) = c/n = Rd/n = Rtan(α/2)。

定義完數據後,接下來,我們要進行實際的投影變換了,先變換x和y座標:

根據相似三角形理論,我們有x/x' = z/n ⇒ x' = xn/z,同理y/y' = z/n ⇒ y' = yn/z。由於x'必定位於區間[-c, c]以及y'必定位於區間[-d, d],而Direct3D期望經過投影變換後的點的x,y的範圍是[-1, 1],所以我們需要將它們規範化到區間[-1, 1]。

-c x' c -1 x'/c 1

-d y'< d -1 y'/d 1

由此我們獲得了在區間[-1, 1]的x,y座標:

接下來,我們變換z座標,Direct3D期望經過投影變換後的點的z的範圍是[0, 1],所以我們需要將它規範化到區間[0, 1]。

由於規範化的x,y座標中都包含了z座標,所以我們想要把它們乘以z,這樣的話,對於z座標就會寫成如下形式 ⇒ ,這樣的話就可以寫成矩陣的形式了。

現在問題就轉換爲如何求u和v,我們知道,近平面n經過投影變換後將轉換爲0,遠平面f經過投影變換後將轉換爲1,所以,我們有u + v/n = 0,u + v/f= 1,我們就可以求得:

u+(-un)/f =1

uf -un = f

u = f /(f -n)

v = -un = -fn/(f - n)

最後,我們得到了

然後,我們可以寫成矩陣形式了:

注意,(x, y, z, 1)經過該變換後尚未在標準視域體內,還需要進行渲染管線中的齊次變換。

(4)視口變換

視口變換負責將在標準視域體內的點轉換到後臺緩衝區(視口)。通常來說,視口是整個後臺緩衝區矩形,但也可以是後臺緩衝區的一部分。下圖顯示定義了4個視口:

定義視口還是很簡單的,只需定義視口的起始x,y座標,視口的寬和高,以及視口的最小以及最大z值。

如何將標準視域體內的點轉換到視口呢?假設視口的起始座標爲X,Y,視口的寬和高爲Width,Height,最小以及最大z值爲MinZ,MaxZ。

我們知道在標準視域體內x,y的區間爲[-1, 1],我們需要轉換到區間[X, X+Width]以及[Y, Y+Height],如下:

-1 ≤ x' ≤ 1

0 ≤ x'+1 ≤ 2

0 ≤ (x'+1)/2 ≤ 1

0 ≤ Width*(x'+1)/2 ≤ Width

X ≤ Width*(x'+1)/2 + X ≤ X+Width

X ≤ Width*x'/2 + Width/2 + X ≤ X+Width

 

y座標的轉換相同,只是需要注意由於y軸是垂直向上的,所以y的-1轉換到視口後應該爲Y+Height,如下:

-1 ≤ y' ≤ 1

-2 ≤ y'-1 ≤ 0

-1 ≤ (y'-1)/2 ≤ 0

-Height ≤ Height*(y'-1)/2 ≤ 0

(乘以-1) 0 ≤ -Height*(y'-1)/2 ≤ Height

Y ≤ -Height*(y'-1)/2 + Y ≤ Y+Height

Y ≤ -Height*y'/2 + Height/2 + Y ≤ Y+Height

 

在標準視域體內,z的區間爲[0, 1],我們需要轉換到區間[MinZ, MaxZ],如下:

0 ≤ z' ≤ 1

0 ≤ z'*(MaxZ-MinZ) ≤ MaxZ-MinZ

MinZ ≤ z'*(MaxZ-MinZ) + MinZ ≤ MaxZ

 

至此,我們構建出了視口變換矩陣:

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