天天看點

透視矩陣的推導(最直覺、最深入、最還原,看完請點贊。)

由參數l,r,b,t,n,f定義的透視投影矩陣的推導困惑了我差不多一個多禮拜,這幾天幾乎是天天都在思考這個問題,昨天晚上3點多鐘我突然醒了,然後我又開始想這個問題,結果終于讓我給想通了,于是我趕緊起床把這個思路記在了草稿紙上,還專門照了張照片作證。

透視矩陣的推導(最直覺、最深入、最還原,看完請點贊。)

為了解決這個問題,前幾天我專門發了兩篇文章求答案,結果知網上的竟然沉掉了。而在csdn上也沒有得到答案(質疑有關透視投影矩陣的推導)。幸虧我自己還是解決了這個問題。

下面推導的是OpenGL中的透視投影矩陣。

已經知道由參數fovy,aspect,n,f定義的透視投影矩陣為:(有關這塊的推導可見《3d graphics for game programming》 2.4.3 derivation of projection matrix,講得非常詳細)

POpenGL= ⎛⎝⎜⎜⎜⎜⎜⎜⎜cot(fovy2)aspect0000cot(fovy2)0000−f+nf−n−100−2nff−n0⎞⎠⎟⎟⎟⎟⎟⎟⎟

那麼再看另一種投影參數l,r,b,t,n,f,上面矩陣中:

cot(fovy2)aspect=cot(fovx2)=2nr−l,

cot(fovy2)=2nt−b.

因為參數l,r是對應視見空間中x軸的坐标,b,t對應視見空間中y軸的坐标,如果l=-r并且b=-t,那麼由這種參數定義的透視投影矩陣就是:

P′OpenGL= ⎛⎝⎜⎜⎜⎜⎜2nr−l00002nt−b0000−f+nf−n−100−2nff−n0⎞⎠⎟⎟⎟⎟⎟

而官方的透視投影矩陣是:

POpenGL= ⎛⎝⎜⎜⎜⎜⎜⎜2nr−l00002nt−b00r+lr−lt+bt−b−f+nf−n−100−2nff−n0⎞⎠⎟⎟⎟⎟⎟⎟

實際上這個矩陣是由兩步轉換完成的,第一步是進行矩陣P′OpenGL變換,然後進行了平移操作,如下:

POpenGL=T×P′OpenGL=⎛⎝⎜⎜⎜⎜⎜⎜⎜100001000010−r+lr−l−t+bt−b01⎞⎠⎟⎟⎟⎟⎟⎟⎟×⎛⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜2nr−l00002nt−b0000−f+nf−n−100−2nff−n0⎞⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟=⎛⎝⎜⎜⎜⎜⎜⎜⎜⎜⎜2nr−l00002nt−b00r+lr−lt+bt−b−f+nf−n−100−2nff−n0⎞⎠⎟⎟⎟⎟⎟⎟⎟⎟⎟

那些說這個透視投影沒有做平移這一步操作,我可以100%跟你說你是錯的!

下面我來解釋為什麼進行了平移操作。

來張示意圖:

透視矩陣的推導(最直覺、最深入、最還原,看完請點贊。)

這個是視見空間中的示意圖,因為存在l≠-r或b≠-t的情況,是以這裡我故意沒把近裁剪平面中心畫在z軸上。 示意圖上由紅線繪制的立方體才是由l,r,b,t,n,f參數定義的視錐體,其中遠裁剪平面上的四個點分别對應原點eye經過近裁剪平面上四個點的延長線與z=-f平面的交點,注意這個視錐體是不規則的!然後圖中的标注l’, r’是近裁剪平面點(l,b,-n)和點(r,b,-n)x軸上的分量在 z=−cot(fovx2) 上的投影, l′=2lr−l , r′=2rr−l ,l’和r’的中心值是 r+lr−l ,同理近裁剪平面上點(r,b,-n)和點(r,t,-n)y軸上的分量在 z=−cot(fovy2) 上的投影, b′=2bt−b , t′=2tt−b ,b’和t’的中心值是 t+bt−b 。 圖中的視錐體通過 P′OpenGL 透視變換之後得到的是規則的正方體(左下角頂點 (2lr−l,2bt−b,1) ,右上角頂點 (2rr−l,2tt−b,−1)) ,最終要把它轉換成cvv(canonical view volume,正規可視化空間),則需要進行T平移轉換,也就是平移 (−r+lr−l,−t+bt−b,0) 。得證。

繼續閱讀