投射投影過程數學推導


Perspective Projection

頂點數據經過模型變換、相機變換轉換到觀察空間,之后渲染系統引入視椎體的概念,並通過投影變換將視椎體轉換到統一設備坐標系中,方便剪裁和后續窗口映射工作。

投影變換其實就是將不同對的視錐體映射到標准設備坐標的過程,投影變換過程中實際上並未實際計算頂點的NDC坐標,而是在后面齊次除法中進行,不過投影變換的整個過程與之息息相關,應該說是作為一個目標。
mark

1 視錐體

一般而言,常用的視錐體有兩種, 如下圖所示。視錐體一般由6個剪裁平面決定,包括近剪裁面和遠剪裁面
mark

2 統一設備坐標系 NDC

可以理解為一個立方體,中心點在中間,\(x,y,z\)方向的范圍\([-1,1]\)(OpenGL中,在有些文檔中描述為CVV,傻傻的分不清楚了,但是表達的意思是相同的),注意的是不同的API定義的NDC不盡相同,DirectX定義\(z\)范圍為\([0,1]\),本文主要使用OpenGl的NDC坐標范圍,不過整個推導過程相同。
|center|

3 設定

  1. 轉換過程推導以OpenGl為准,也就是采用右手坐標系,觀察方向位沿Z軸負方向
  2. 涉及的符號為不帶符號數,比如下文中近鄰面\(z\)坐標\(n\)大於遠鄰面\(f\)

4.平行投影

設觀察空間中,視椎體的為\([l,r]\times[b,t]\times[f,n]\) ,其中$l < r \quad and \quad b < t \quad and \quad f < n \( ![|center|](http://ohzzlljrf.bkt.clouddn.com/blog/20161213/231230467.png) 平行視椎體 和NDC都是立方體,所以可以通過平移\)T(t)\(和縮放\)S(s)$ 實現 , 其過程如下圖所示
\(T(t)\)將視椎體中心移動到坐標系中心,平移矩陣如下:

\[ T(t) = \begin{bmatrix} 1 & 0 & 0 &-\frac{l+r}{2}\\ 0 & 1 & 0 &- \frac{t+b}{2} \\ 0&0& 1& -\frac{n+f}{2} \\ 0&0&0&1 \end{bmatrix} \]

\(S(s)\) 將平移后視椎體的\((x,y,z)\)轉換到\([-1,1]\)區間,

\[ S(s) = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & 0\\ 0 & \frac{2 }{t-b} & 0 & 0 \\ 0&0& \frac{2}{n-f}& 0 \\ 0&0&0&1 \end{bmatrix} \]

所以轉換矩陣

\[M_{oth} = S(s) T(t) \\ \\ = \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & \frac{r+l}{r-l} \\ 0 & \frac{2 }{t-b} & 0 &\frac{t+b }{t-b} \\ 0&0& \frac{2}{n-f}& \frac{n+f}{n-f} \\ 0&0&0&1 \end{bmatrix} \]

5.透視投影

透視投影的特征就是投影線都會經過視點,也就是攝像機中心,一般在計算中會將視椎體的近平面\(z = n\)作為成像平面。投影矩陣可以直接通過投影關系以及視錐體和NDC區間的關系建立方程求教獲得,可以參考Mathematics for 3D Game Programming and Computer Graphics 第五章 。不過這里采用另外一種方式,先將透視投影的視椎體轉換為平面投影的視椎體,然后再利用平行投影的視椎體獲得透視投影矩陣

5.1 透視關系

mark
假設空間中一點的坐標為\(P(p_x,p_y,p_z)\) ,其在$z = n \(上的投影點位\)q(q_x , q_y,n)$ , 根據比例關系可知:
$$
\left {
\begin{array}{lr}
q_x = \frac {n} {p_z} p_x \
q_y = \frac {n} {p_z} p_y \
q_z = n
\end{array}
\right.
$$

5.2 深度關系

上述過程可以實現將空間中點轉換到2D圖像中,但點\(q(q_x , q_y,n)\)\(z\) 保持為\(n\) , 實際上\(z\) 應該保持\([n,f]\)的區間,另一方面在光柵化過程中對\(\frac{1}{z}\)進行插值,所以\(z\)的變換函數應該是\(\frac{1}{z}\)的線性函數,假設\(z\)的變換函數為

\[q_z = \frac{a}{p_z} + b \]

\(z\)的區間映射關系\([n,f] \rightarrow [n,f]\)以得:

\[ \left \{ \begin{array}{lr} n = \frac{a}{n} + b \\ f = \frac{a}{f} + b \end{array} \right. \]

計算可得:

\[\left \{ \begin{array}{lr} a = -nf \\ b = n + f \end{array} \\ \right. \]

也就是說轉換函數為

\[q_z = -\frac{nf}{p_z} + (n+f) \]

5.3 透視視錐體轉換到平行視錐體

通過上面的推導,透視投影視椎體轉換為平行投影視椎體的過程可以表達為:
$$
\left {
\begin{array}{lr}
q_x p_z = n p_x \
q_y p_z = n p_y \
q_z p_z = (n+f)p_z - nf \
p_z = p_z
\end{array}
\right.
$$
用齊次坐標表達以及轉換過程:

\[\begin{bmatrix} q_x p_z \\ q_y p_z \\q_z p_z\\p_z \end{bmatrix} = \begin{bmatrix} q_x \\ q_y \\q_z \\1 \end{bmatrix} = \begin{bmatrix} np_x \\ np_y \\(n+f)p_z - nf \\ p_z \end{bmatrix} = \\ \begin{bmatrix} n & 0 & 0 & 0 \\ 0 & n & 0 & 0 \\ 0 & 0 &n+f & -fn \\ 0 & 0 & 1 & 0 \end{bmatrix} \begin{bmatrix} p_x \\ p_y \\p_z\\1 \end{bmatrix} \\ = M_{per \rightarrow oth} \begin{bmatrix} p_x \\ p_y \\p_z\\1 \end{bmatrix} \]

結合平行投影轉換矩陣,獲得透視投影轉換矩陣:

\[M_{pre} = M_{oth}M_{per \rightarrow oth} \]

即:

\[ M_{pre} = \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \\ 0 & \frac{2 n}{t-b} &\frac{t+b }{t-b} & 0 \\ 0&0& \frac{n+f}{n-f}& \frac{2nf}{n-f} \\ 0&0&1&0 \end{bmatrix} \]

總結

上文即筆者總結的透視變換的數學推導過程,畢業后第一次寫這樣的文章,無非是想把這個過程完全理清楚是怎么回事。之前看的時候感覺沒什么問題啊,但是在寫的時候還是遇到一些問題,比如:

  1. Canonical view volume(CVV) 與 Normalized device Coordinaate(NDC)的關系,參考了幾本書中的描述,其實都有點混淆,包括RTR中也會同時出現這兩個概念,不過最終還是沒弄明白怎么個區分方法,暫且當做一個概念吧
  2. \(z\)投影前后的計算公式,好幾本書都是直接給出結論的,最后還是在Mathematics for 3D Game Programming and Computer Graphics中找到具體的流程,也可以參考另外一篇PPT

總之,本文會有很多描述不清晰或者弄錯的地方,遇到的請幫忙指教。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM