計算機圖形學中MVP變換的理論推導
課程地址:Computing the Pixel Coordinates of a 3D Point
知識鋪墊:矩陣的真實內涵
矩陣的每一列/行(左乘和右乘的區別)代表了新坐標系的基向量在原基向量構成的坐標系中的坐標,這些新基向量(單位軸)構成新坐標系(用矩陣表示)
如果此時用這個矩陣乘一個向量,則向量中每個元素的含義是新坐標系中每個軸的對應分量,三個軸分量線性組合得到一個新坐標,這個坐標就是用這個新坐標系描述的
例如:矩陣A乘以向量d得到一個新向量f,矩陣A中的每一列代表用原坐標系(標準正交基)中的新向量作為新坐標系的基向量,向量d表示新坐標系中三個軸的對應分量,這些分量線性組合得到新向量f,整個過程可以描述為矩陣A將向量d變換到向量f
總之,矩陣的每一列或行元素代表在原坐標系 ( 1 , 0 , 0 ) 、 ( 0 , 1 , 0 ) 、 ( 0 , 0 , 1 ) (1,0,0)、(0,1,0)、(0,0,1) (1,0,0)、(0,1,0)、(0,0,1)中找三個正交向量作為新基向量(坐標系的軸),之后矩陣乘別的向量就是用這個新基向量線性組合得到新向量
世界坐標系
世界坐標系描述了一切,包括相機的位置、物體的頂點等等,為了能夠讓我們看見世界坐標系中的物體,我們就需要將世界坐標系中的頂點轉到相機視角下,這樣才能讓我們看到某個視角下的物體
我們假設世界坐標系為identity matrix,即
( 1 , 0 , 0 0 , 1 , 0 0 , 0 , 1 ) \begin{pmatrix} 1,0,0\\ 0,1,0\\ 0,0,1 \end{pmatrix} ?1,0,00,1,00,0,1? ?
我們可以定義一個模型,比如這里的立方體,我可以假想一個坐標系(原點(0,0,0)+三個互相垂直的軸),我可以在這個假想的坐標系中直接寫出立方體的每個頂點的坐標
p 1 = [ ? 0.5 , ? 0.5 , 0.5 ] p 2 = [ ? 0.5 , 0.5 , 0.5 ] p 3 = [ ? 0.5 , 0.5 , ? 0.5 ] … … p_1=[-0.5, -0.5, 0.5]\\ p_2=[-0.5, 0.5, 0.5]\\ p_3=[-0.5, 0.5, -0.5]\\ ~\\ …… p1?=[?0.5,?0.5,0.5]p2?=[?0.5,0.5,0.5]p3?=[?0.5,0.5,?0.5]?……
其實這些坐標都是我們在想象的一個空間坐標系(并非真的用代碼實現了一個坐標系)內描述的這些頂點,該坐標系原點為 [ 0 , 0 , 0 ] [0,0,0] [0,0,0],三個軸互相垂直
重點!!!務必理解,我們并非明確地變換坐標系;而是平移、縮放和旋轉對象(頂點)完成所謂坐標系的轉換。一個 4x4 矩陣表示這些變換,并且該矩陣可以被視為一個坐標系,也就是說我們對這些頂點乘以一個變換矩陣就相當于換了一個坐標系
世界坐標系到相機坐標系的變換(相機外參矩陣)
相機外參矩陣的結構
每個相機的初始位置其實是與我們想象的“世界坐標系”重合的,我們需要將這些定義在世界坐標系的頂點乘以一個矩陣(本質是變換,看作一個新坐標系)轉換到用其他坐標系表示,這個矩陣就是world_to_camera矩陣(相機外參矩陣),這個矩陣的構成:
齊次坐標:在三維空間中,為了能用矩陣同時表示旋轉和平移,引入四維齊次坐標,將三維點 ( x , y , z ) (x,y,z) (x,y,z)表示為 ( x , y , z , 1 ) (x,y,z,1) (x,y,z,1)
矩陣結構:4×4 矩陣可分為兩部分:
左上 3×3 子矩陣 𝑅:表示旋轉,用于對齊世界坐標系的軸到相機坐標系的軸(即相機的方向基向量)
右上 3×1 向量 𝑡:表示平移,用于將世界原點“搬到”相機原點的位置(注意是逆變換,所以常帶負號)
將旋轉和平移整合到一個矩陣中就是這里所說的相機外參矩陣M
相機外參矩陣中的平移向量
相機外參矩陣中的旋轉矩陣
知識鋪墊:
旋轉一共三個自由度,繞 x , y , z x,y,z x,y,z旋轉,如果分別繞x、y、z軸旋轉可以得到三個方向上的旋轉矩陣 R x 、 R y 、 R z R_x、R_y、R_z Rx?、Ry?、Rz?,而相機外參矩陣中的旋轉矩陣是這三者的乘積
R = R x ? R y ? R z R=R_x*R_y*R_z R=Rx??Ry??Rz?
下圖來自:TEK5030 - Computer Vision
推導 R x 、 R y 、 R z R_x、R_y、R_z Rx?、Ry?、Rz?,頂點 P w P_w Pw?原先用坐標系 X w Y w Z w X_wY_wZ_w Xw?Yw?Zw?表示,現在用新坐標系 X c Y c Z c X_cY_cZ_c Xc?Yc?Zc?表示,也就是說頂點 P w P_w Pw?原先用坐標系 X w Y w Z w X_wY_wZ_w Xw?Yw?Zw?的三個基向量線性組合而成,現在想要用新坐標系 X c Y c Z c X_cY_cZ_c Xc?Yc?Zc?基向量線性組合表示頂點 P w P_w Pw?重新命名為 P c P_c Pc?
下圖來自:計算機視覺之— 相機內參與外參
相機外參矩陣中的旋轉矩陣是三個單純繞軸旋轉矩陣的乘積
R = R x ? R y ? R z R=R_x*R_y*R_z R=Rx??Ry??Rz?
先對世界坐標系描述的頂點做旋轉R,之后再進行平移 t 得到了用新坐標系(相機坐標系)描述的頂點
向量與點的區別
(1)向量(如基向量)只關心起點到終點的方向與長度,通常被視為從原點出發的箭頭;它們本身不附帶“起點位置”的信息。
(2)點 才有“坐標位置”,平移才會改變它。
旋轉(R):將世界坐標系的向量或點圍繞原點旋轉到相機坐標系方向。
平移(t):將旋轉后的點平移到相機中心位置。
向量 只經過旋轉,不經歷步驟 平移;
而 點 則經歷旋轉+平移,最終同時擁有新的方向和位置
世界坐標系與相機坐標系互轉的應用場景
(1)從相機坐標系轉到世界坐標系(相機外參矩陣的逆c2w)應用場景
在多視圖立體重建或 SLAM(同步定位與建圖)等應用中,每臺相機先以其自身坐標系表示重建出的三維點,為了融合這些不同相機獲得的數據,需要將它們變換到同一世界坐標系。
將來自多臺相機或多時刻的點統一到全球參照系,用于點云拼接、稠密建圖和地圖創建等
三維模型點未知,僅知道模型在相機坐標系下點的坐標(模型的一部分點),這時候我們想要得到三維模型的所有點,就需要把每幀相機坐標系下的點都統一轉換到世界坐標系下
P w = P c ? M c 2 w P_w=P_c*M_{c2w} Pw?=Pc??Mc2w?
P w . x = P c . x ? M 00 + P c . y ? M 10 + P c . z ? M 20 + M 30 P w . y = P c . x ? M 01 + P c . y ? M 11 + P c . z ? M 21 + M 31 P w . z = P c . x ? M 02 + P c . y ? M 12 + P c . z ? M 22 + M 32 P_w.x=P_c.x*M_{00}+P_c.y*M_{10}+P_c.z*M_{20}+M_{30}\\ ~\\ P_w.y=P_c.x*M_{01}+P_c.y*M_{11}+P_c.z*M_{21}+M_{31}\\ ~\\ P_w.z=P_c.x*M_{02}+P_c.y*M_{12}+P_c.z*M_{22}+M_{32} Pw?.x=Pc?.x?M00?+Pc?.y?M10?+Pc?.z?M20?+M30??Pw?.y=Pc?.x?M01?+Pc?.y?M11?+Pc?.z?M21?+M31??Pw?.z=Pc?.x?M02?+Pc?.y?M12?+Pc?.z?M22?+M32?
(2)從世界坐標系轉到相機坐標系(相機外參矩陣w2c)應用場景
在渲染、投影或相機標定(Camera Calibration)過程中,需要將已知的三維模型點映射到相機坐標系下,以便進一步投影到圖像平面
M w 2 c = M c 2 w ? 1 P c = P w ? M w 2 c M_{w2c}=M_{c2w}^{-1}\\ ~\\ P_c=P_w*M_{w2c} Mw2c?=Mc2w?1??Pc?=Pw??Mw2c?
P c . x = P w . x ? M 00 + P w . y ? M 10 + P w . z ? M 20 + M 30 P c . y = P w . x ? M 01 + P w . y ? M 11 + P w . z ? M 21 + M 31 P c . z = P w . x ? M 02 + P w . y ? M 12 + P w . z ? M 22 + M 32 P_c.x=P_w.x*M_{00}+P_w.y*M_{10}+P_w.z*M_{20}+M_{30}\\ ~\\ P_c.y=P_w.x*M_{01}+P_w.y*M_{11}+P_w.z*M_{21}+M_{31}\\ ~\\ P_c.z=P_w.x*M_{02}+P_w.y*M_{12}+P_w.z*M_{22}+M_{32} Pc?.x=Pw?.x?M00?+Pw?.y?M10?+Pw?.z?M20?+M30??Pc?.y=Pw?.x?M01?+Pw?.y?M11?+Pw?.z?M21?+M31??Pc?.z=Pw?.x?M02?+Pw?.y?M12?+Pw?.z?M22?+M32?
相機空間到裁剪空間(投影變換矩陣)
投影變換矩陣 = 透視投影 + 正交投影 投影變換矩陣=透視投影+正交投影 投影變換矩陣=透視投影+正交投影
在 OpenGL/DirectX 等渲染管線中,投影變換矩陣(GL_PROJECTION)把相機空間(View Space)頂點變換到裁剪空間(Clip Space)
( x c , y c , z c , w c ) ? > ( x c w c , y c w c , z c w c ) (x_c,y_c,z_c,w_c)->(\frac{x_c}{w_c},\frac{y_c}{w_c},\frac{z_c}{w_c}) (xc?,yc?,zc?,wc?)?>(wc?xc??,wc?yc??,wc?zc??)
1.應用視椎體裁剪(Frustum Clipping)參數(近裁剪面、遠裁剪面、左右上下邊界)
2.內置寬高比(Aspect Ratio)與視場角(FOV)
3.保留深度信息以便后續深度測試
投影變換矩陣 M perp M_{\text{perp}} Mperp?的推導過程:
相機視錐體如下圖所示
透視投影矩陣推導
利用變換前后的不變關系求解未知部分
由以上兩個等式關系求解方程組
由此得到透視投影(視錐體壓縮)矩陣 M perp->ortho M_{\text{perp->ortho}} Mperp->ortho?
正交投影矩陣推導
接下來推導正交投影矩陣(將長方體壓縮邊長為2的正方體)
即將長方體盒子 [ l , r ] × [ b , t ] × [ n , f ] [l,r]×[b,t]×[n,f] [l,r]×[b,t]×[n,f]壓縮到標準立方體 [ ? 1 , 1 ] 3 [-1,1]^3 [?1,1]3
第一步:把視錐盒子平移,讓視錐盒子(長方體)中心對齊到相機坐標系原點
注意:視錐盒子(長方體)做了平移
第二步:把長方體盒子壓縮到標準立方體
如果不把長方體盒子中心移動到相機坐標系原點而直接壓縮就不會得到標準立方體
注意z軸反向了
由此我們得到正交投影矩陣 M ortho M_{\text{ortho}} Mortho?
視錐體壓縮為長方體,為什么要將長方體中心移動到相機坐標系原點?長方體變為標準立方體,為什么要將z軸反向?
這樣做能保證線性變換中心對齊、方向一致,最終以簡潔統一的方式進行裁剪與插值。
視場角的作用
用于構建透視投影矩陣
在透視投影中,Fovy 和 Fovx 是計算投影矩陣的重要參數,具體過程如下:
1.假設已知近裁剪平面距離為 n,垂直視場角為 Fovy,則近裁剪平面的垂直高度 h = 2 n t a n ( F o v y 2 ) h=2n tan(\frac{Fovy}{2}) h=2ntan(2Fovy?)
2.結合畫面的寬高比 a s p e c t = w h aspect=\frac{w}{h} aspect=hw?(w為水平寬度),可以計算出近裁面的水平寬度 w = a s p e c t × h w=aspect×h w=aspect×h
3.這些尺寸參數(w、h、n)進一步用于推導透視投影矩陣的具體元素,確保三維場景按正確的透視關系(近大遠小)映射到二維屏幕。
同理,若給定水平視場角Fovx和近裁面距離n,可計算出水平寬度 w = 2 n t a n ( F o v x 2 ) w=2ntan(\frac{Fovx}{2}) w=2ntan(2Fovx?),再結合寬高比得到垂直高度 h = w a s p e c t h=\frac{w}{aspect} h=aspectw?
相機坐標系中齊次坐標經過投影變換矩陣轉換到齊次裁剪空間
齊次裁剪空間到NDC空間
裁剪操作(齊次裁剪空間即單位立方體中執行)
透視除法
透視除法是計算機圖形學中實現真實感透視效果的核心機制,通過將頂點坐標除以其深度信息(存儲在 w 分量中),實現了近大遠小的視覺效果,并將坐標統一到標準化設備空間,為后續的視口變換和光柵化提供了基礎。這一步驟是透視投影矩陣與最終屏幕顯示之間的橋梁,直接決定了三維場景在二維屏幕上的呈現效果。
NDC空間到屏幕空間(視口變換)
在計算機圖形學中,視口變換(Viewport Transformation) 是圖形管線的最后階段,負責將標準化設備坐標(NDC)轉換為屏幕上的像素坐標。這一步驟決定了三維場景如何最終顯示在二維顯示器上
下圖來自:計算機圖形管線 13.視口變換