OpenGL中投影變換矩陣的反向推導

在OpenGL中有兩個重要的投影變換:正交投影(Orthographic Projection)和透視投影(Perspective Projection),兩者各有對應的變換矩陣。初學者比較難理解這兩個矩陣是怎麼來的。本文從數學角度來反向推導兩個投影矩陣。ide

推導的思路

正交投影和透視投影的做用都是把用戶座標映射到OpenGL的可視區域。若是咱們能根據兩者的變換矩陣來推出最終通過映射的座標範圍剛好是OpenGL的可視區域,也就是反向推導出了這兩個投影矩陣。函數

OpenGL的可視區域的座標範圍是一個邊長爲2的立方體。每一個維度上的大小是2,範圍是[-1,+1]。通過各類變換以後的座標超出[-1,+1]範圍的部分將不會顯示到屏幕上。3d

正交投影

變換效果

正交投影在OpenGL中的做用是調整屏幕寬高比,並將實際定義的座標轉換成[-1,+1]範圍內的對應的座標。code

矩陣定義

下圖是正交投影矩陣。cdn

-w400
https://cdn.wxdut.com/ 參數解釋以下:

-w400

只考慮x軸和y軸,則:blog

在定義物體的座標的時候,座標範圍爲:數學

\begin{cases}
x \in [left, right]& \text{}\\
y \in [top, bottom]& \text{}
\end{cases}

經過上面那個矩陣,就能夠轉換成[-1,+1]範圍內的對應的座標。下面對此進行證實。it

數學推導

① 假設物體上的一個座標爲(x,y,z,1),其中,x的範圍爲[left, right],y的範圍爲[top, bottom],z的範圍爲[near, far]io

則,矩陣*向量class

\left[ \begin{array}{cccc}
\frac{2}{right-left} & 0 & 0 & -\frac{right+left}{right-left}\\
0 & \frac{2}{top-bottom} & 0 & -\frac{top+bottom}{top-bottom}\\
0 & 0 & \frac{-2}{far-near} & -\frac{far+near}{far-near}\\
0 & 0 & 0 & 1
\end{array} 
\right]×
\left[ \begin{array}{c}
x\\
y\\
z\\
1
\end{array} 
\right]=
\left[ \begin{array}{c}
\frac{2x-left-right}{right-left}\\
\frac{2y-top-bottom}{bottom-top}\\
\frac{2z-near-far}{far-near}\\
1
\end{array} 
\right ]

即,

x1=\frac{2x-left-right}{right-left}
y1=\frac{2y-top-bottom}{bottom-top}
z1=\frac{2z-near-far}{far-near}
w1=1

② 考慮到perspective divide的存在,此時w=1,因此:

x1=\frac{2x-left-right}{(right-left)w1}=\frac{2x-left-right}{right-left}
y1=\frac{2y-top-bottom}{(bottom-top)w1}=\frac{2y-top-bottom}{bottom-top}
z1=\frac{2z-near-far}{(far-near)w1}=\frac{2z-near-far}{far-near}

② 先證實x軸確實落在了[-1, +1]的範圍。

很明顯,x1是關於x的一元一次線性函數。

x1=f(x)=\frac{2*x-left-right}{right-left}

因此x=right的時候,f(x)最大,x=left的時候,f(x)最小。

代入方程,獲得:

f(x)=\begin{cases}
f(x) = -1,& \text{x=left}\\
f(x) = 1,& \text{x=right}
\end{cases}

③ 因此

x1=f(x)\in [-1, +1]

同理,y1和z1的範圍也是[-1, +1]。

證實結束。

小結

正交變換是將物體的座標轉換成OpenGL的座標。

變換前的範圍爲:

\begin{cases}
x \in [left, right],& \text{}\\
y \in [bottom, top],& \text{}\\
z \in [near, far],& \text{}
\end{cases}

變換後的範圍爲:

\begin{cases}
x \in [-1, 1],& \text{}\\
y \in [-1, 1],& \text{}\\
z \in [-1, 1],& \text{}
\end{cases}

透視投影

變換效果

在用2D屏幕展示3D場景時,會有一種近大遠小的感受。OpenGL也是利用這一原理實如今2D屏幕上的3D效果。透視投影會造成一個視椎體,在視椎體內的座標都是能夠繪製到屏幕上的,也就是說,在視椎體上的座標範圍都會被調整到[-1, +1]的區間。

-w400

矩陣定義

-w400

參數解釋以下:

-w400

透視矩陣有些特殊,並未說明x和y的範圍,下面經過推導得出這個範圍。

數學推導

① 假設物體上的一個座標爲(x,y,z,1)

則,矩陣*向量的結果爲:

\left[ \begin{array}{cccc}
\frac{a}{aspect} & 0 & 0 & 0\\
0 & a & 0 & 0\\
0 & 0 & -\frac{f+n}{f-n} & -\frac{2fn}{f-n}\\
0 & 0 & -1 & 0
\end{array} 
\right]×
\left[ \begin{array}{c}
x\\
y\\
z\\
1
\end{array} 
\right]=
\left[ \begin{array}{c}
\frac{ax}{aspect}\\
ay\\
-\frac{f+n+2fnw}{f-n}\\
-z
\end{array} 
\right ]

即,

x1=\frac{ax}{aspect}
y1=ay
z1=-\frac{(f+n)z+2fnw}{f-n}
w1=-z

② 考慮perspective divide的存在,獲得:

x2=\frac{x1}{w1}=\frac{-ax}{aspect * z}
y2=\frac{y1}{w1}=-\frac{ay}{z}
z2=\frac{z1}{w1}=\frac{(f+n)z+2fn}{(f-n)z}

③ 求:當結果落在了[-1, +1]的範圍的時候,x的範圍是多少?

很明顯,x2是關於x的一元一次線性函數。

x2=f(x)=\frac{-ax}{aspect*z}

下面推算當x2的範圍爲[-1, +1]的時候,x的範圍

x=\begin{cases}
\frac{aspect*z}{a},& \text{f(x)=-1}\\
-\frac{aspect*z}{a},& \text{f(x)=1}
\end{cases}

因此,x的範圍爲

[\frac{aspect*z}{a},-\frac{aspect*z}{a}]

這裏注意,按照習慣,z通常都是負數,因此上面的區間範圍是沒問題的,下同。

④ 求:當結果落在了[-1, +1]的範圍的時候,y的範圍是多少?

由於,

y2=f(y)=-\frac{ay}{z}

分別求y1爲1和-1時,y的值。

y=\begin{cases}
\frac{z}{a},& \text{f(y)=-1}\\
-\frac{z}{a},& \text{f(y)=1}
\end{cases}

因此,y的範圍爲

[\frac{z}{a},-\frac{z}{a}]

⑤ 求:當結果落在了[-1, +1]的範圍的時候,z的範圍是多少?

由於,

z2=f(z)=\frac{z1}{w1}=\frac{(f+n)z+2fn}{(f-n)z}

-1<=f(z)<=1

則有,

-1<=\frac{(f+n)z+2fn}{(f-n)z}<=1

解方程得,

-1<=f(z)<=1

因此,

n<=z<=f

即變換前的座標必定要在平截椎體的Z軸範圍內才能最終展現到屏幕上。

證實結束。

小結

透視變換是將物體的座標轉換成OpenGL的座標。

變換前的範圍爲:

\begin{cases}
x \in [\frac{aspect*z}{a},-\frac{aspect*z}{a}],& \text{}\\
y \in [\frac{z}{a},-\frac{z}{a}],& \text{}\\
z \in [n,f],& \text{}
\end{cases}

變換後的範圍爲:

\begin{cases}
x \in [-1, 1],& \text{}\\
y \in [-1, 1],& \text{}\\
z \in [-1, 1],& \text{}
\end{cases}

附上透視椎體的圖解:

總結

矩陣變換在OpenGL座標變換中起到了很是重要的做用。在二維圖像顯示時通常使用正交變換,在三維圖像顯示時就要用到透視變換。理解這兩個變換對應的矩陣的做用對咱們理解這兩個變換很重要。

相關文章
相關標籤/搜索