1、模型座標系到世界座標系:模型的每個頂點經旋轉和縮放之後平移到世界座標的位置。
2、隱藏面消除(可選):通常執行的測試爲背面消除和包圍球測試,在世界空間中進行。
2.1、包圍球測試原理:對於世界空間中的每個物體,創建一個包圍球,只對球心執行世界座標到相機座標的變換,並判斷整個球體是否位於視截體內,如果不在,則丟棄它包圍的物體。如果球體的一部分在視截體內,需要在將整個模型變換到相機座標後做其他測試。
2.1.1、包圍球:定義6個點,它們與變換到像極座標後的球心之間的連線分別平行於三個軸, 到球心的距離都等於頂點列表中距離球心最遠的點到球心的距離。爲了更加精確,可選擇包圍盒等其他幾何體代替包圍球。
2.1.2、判斷點(x, y, z)是否在視野爲90度的視截體外部:(z > far_z) || (z < near z) || (fabs(x) < z) || (fabs(y) < z)
2.2、背面測試的工作原理:以統一的方式(順時針或逆時針)對構成每個物體的所有多邊形進行標記,然後計算每個多邊形的面法線,並根據觀察向量對這條法線進行測試。如果面法線和觀察向量之間的夾角不超過90度,也就是點積大於0時,多邊形對於觀察者而言是可見的。夾角剛好爲90度時的多邊形寬度通常爲1個像素,渲染時可能帶來問題,因此排除它。
3、世界座標系到相機座標系:對所有世界座標進行平移,平移量爲負的相機的世界座標再對世界座標針對三個軸進行三次旋轉,旋轉角度爲相機對應角度的負值。若要反求世界座標,則先旋轉再平移。平移矩陣爲以相機世界座標爲平移量的矩陣的逆矩陣,旋轉矩陣爲以相機相對於對應軸旋轉矩陣的轉置矩陣。對於每一幀,只需手工計算變換矩陣一次。
4(可選)、3D裁剪:對於不完全位於視截體內部的幾何體(直線或多邊形)用視截體進行裁剪。可對視截體應用投影變換,使它變爲長方體。若不執行這一步,則執行第六步。如果願意對所有幾何體都進行投影變換,可以在投影變換之後再進行3D裁剪。
5、相機座標系到投影座標系:設視平面爲z = d(視距,視點到視平面的距離),視點爲(0,0,0),則根據相似三角形的比例關係,點(x,y,z)投影點(xp,yp)爲:xp = d * x / z,yp = d * y / z。當z = 0時,投影點的座標爲無窮大,另外z爲負時物體被倒轉,但能夠投影,這是爲什麼需要指定近裁剪面的理由之一。投影變換編碼時必須使用其次座標。
5.1、4D其次座標投影變換矩陣:
| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 1/d |
| 0 0 0 0 |
用點(x,y,z,1)驗證,結果爲(x,y,z,z / d),將x,y,z分別除以齊次座標,得到3D座標:
(x * d / z,y * d / z,z * d / z),忽略z座標,x,y爲投影點。
5.2、非正方形視口d值的確定:
d = 0.5 * 寬度 * tan(fov / 2), tan(fov / 2)= 視距 / (寬度 / 2)
xp = d * x / z yp = d * y * ar(寬高比) / z
4D其次座標投影變換矩陣:
| d 0 0 0 |
| 0 d*ar 0 0 |
| 0 0 1 1 |
| 0 0 0 0 |
6、圖像空間裁剪(若第四步不執行,則執行該步):所有要被渲染的物體被轉換爲屏幕座標後,再使用屏幕空間或視口對它們進行裁剪
7、投影座標系到屏幕座標系:
7.1、當視野爲90度,視距爲1:在投影空間中視平面座標在每個軸上被歸一化爲-1到1(方形投影),投影面爲方形時,投影變換將所有幾何體投影到一個2 * 2的虛擬視平面上(xp和yp的範圍都是 [-1,+1]);投影面不是方形時,虛擬視平面大小爲2 *(2 / ar),xp範圍爲[-1,+1],yp範圍爲[-1 / ar,+1 / ar]。
7.1.1、將上述x,y的範圍映射到屏幕:
xp -> xs @ [0,SCREEN_WIDTH - 1]
yp -> ys @ [0,SCREEN_HEIGHT - 1]
注意y軸被反轉,屏幕座標是以左上角爲原點,y軸正方向向下。
7.1.2、設a = 0.5 * SCREEN_WIDTH - 0.5,b = 0.5 * SCREEN_HEIGHT - 0.5
xs = (xp + 1)* a = xp * a + a
ys = 2 * b -(yp + 1)* b = b - yp * b
對應的4D變換矩陣:
| a 0 0 0 |
| 0 -b 0 0 |
| 0 0 1 0 |
| a b 0 1 |
對應的3D變換矩陣:
| a 0 0 |
| 0 -b 0 |
| a b 1 |
7.2、視野和視距爲任何值:
7.2.1、d值計算:d = 0.5 * viewplane_width(height) * tan(fov / 2)
設視平面與視口(屏幕)大小相同:d = 0.5 * (SCREEN_WIDTH(HEIGHT)- 1)* tan(fov / 2)
7.2.2、一次性將相機座標變換爲屏幕座標:
xs = xp + a = d * x / z + a
ys = b - yp = -d * y * ar/ z + b
變換矩陣:
| d 0 0 0 |
| 0 -d 0 0 |
| a b 1 1 |
| 0 0 0 0 |
7.2.2.1、對於使用矩陣來執行投影變換和屏幕變換,需要注意投影變換得到的是齊次座標,必須將其轉換爲3D坐
標。
7.2.2.2、將投影變換和屏幕變換合併後,寬高比被消除了。
8、其他:
8.1、在座標變換時,不要更改座標,而應使用另一個數組來存儲結果。
8.2、水平、垂直視野都是90度的視截體上下左右平面方程:|x| = z |y| = z / ar。
8.3、在得到世界座標之後和得到屏幕座標之前,必須對多邊形進行光照計算和紋理映射,本文只討論座標變換,所以忽略。