3d模型經過世界坐標變換、相機坐標變換后,下一步需要投影變換。投影變換的目的就是要把相機空間轉換到標准視圖空間,在這個空間的坐標都是正規化的,也就是坐標范圍都在[-1,1]之間,之所以轉換到這個空間是為了后續操作更方便。
下面的討論都是以列向量來表示,這樣在變換操作時,采用的是矩陣左乘法,如果采用的是行向量的話,那就相反,矩陣右乘法即是向量在左邊乘以變換矩陣。采用哪種表示並不影響結果,只需要把該種表示下得出的變換矩陣轉置一下,就是采用另外一種表示模式需要的結果。
常見的投影有兩種,正交投影和透視投影,正交投影相對來說更簡單,所以先來看看正交投影。
最簡單的正交變換矩陣
1 0 0 0
0 1 0 0
0 0 0 1
這個正交變換是不可逆變換,變換后x和y保留,z變成了0,在實際應用中,更常見的情況是限定x、y、z在一定的范圍內的進行投影變換,比如x[l,r],y[b,t],z[n,f]。那么要把這段空間中的點變換到-1和1之間,只要完成兩個變換,首先把坐標軸移到中心,然后進行縮放就可以了。采用列向量的話,那就是縮放矩陣乘以平移矩陣。
2/(r-l) 0 0 0 1 0 0 -(r+l)/2 2/(r-l) 0 0 -(r+l)/(r-l)
0 2/(t-b) 0 0 x 0 1 0 -(b+t)/2 = 0 2/(t-b) 0 -(t+b)/(t-b)
0 0 2/(f-n) 0 0 0 1 -(n+f)/2 0 0 2/(f-n) -(f+n)/(f-n)
0 0 0 1 0 0 0 1 0 0 0 1
透視投影類比於我們人眼系統,看一個物體,會有遠小近大的效果。在轉換到相機空間后,相機是這個空間的原點,和正交投影體是一個長方體或者立方體不同,透視投影體是一個錐體被近平面截取掉頭部剩下的空間。假定仍然采用上面的坐標表示。在透視投影下,空間上面的任何一點P投影到近平面上某點q,通過三角幾何學我們可以得到 qx=px*n/pz ,y點同理。假定直接投影到近平面,則該矩陣很簡單,用Ma表示下面的矩陣
1 0 0 0
0 1 0 0
0 0 1 0
0 0 1/n 0
則齊次空間某點(x,y,z ,1)被該矩陣轉換后變成了 (x ,y z, z/n) ,除以z/n,則變成了(nx/z,ny/z,n ,1) 正好吻合上面的公式。
但是我們知道投影變換需要把坐標變換到-1和1之間,假定先不考慮z軸的變換,在x軸和y軸上面經過上述變換后,已經投影在近平面了,假設近平面xy在[l,r] 和[b,t]之間了,因此只需要和上面的正交投影一樣,進行平移和縮放操作就可以了,平移矩陣Mb為
1 0 0 -(l+r)/2
0 1 0 -(t+p)/2
0 0 1 -(f+n)/2
0 0 0 1
以及縮放矩陣Mc
2/(r-l) 0 0 0
0 2/(t-b) 0 0
0 0 2/(f-n) 0
0 0 0 1
McXMbXMa
得到的矩陣為
2/(r-l) 0 -(r+l)/(n*(r-l)) 0
0 2/(t-b) -(t+b)/(n*(t-b)) 0
0 0 j k
0 0 1/n 0
j k 為未知數,這個矩陣也可以同時乘以n,則變為
2n/(r-l) 0 -(r+l)/(r-l) 0
0 2n/(t-b) -(t+b)/(t-b) 0
0 0 j k
0 0 1 0
為了求解 J k,我們需要把z變換到-1 和1
因此當z=n時為-1, z=f時 為1
(j*n+k)/n= j+k/n=-1;
同理 j+k/f=1;
得到 k=2f*n/(n-f)
j=-(n+f)/(n-f)
代入上面的矩陣,就得出通用的正交變換矩陣。
而且在一般情況下 r=-l ,b=-t
因此上述矩陣可以簡化為
n/r 0 0 0
0 n/t 0 0
0 0 -(n+f)/(n-f) 2f*n/(n-f)
0 0 1 0
n/r 和 n/t可以進一步簡化成水平半視角和垂直半視角的三角函數來表示,而水平視角和垂直視角和透視窗口的寬高比有是成正比的,最終上面兩行可以用寬高比和某個半視角的余切來表示。
這是在列向量情況下得出的投影矩陣,如果采用行向量,只需要把上面的矩陣轉置一下即可。