計算機圖形:三維觀察之投影變換

明明1109發表於2024-04-24

目錄
  • 投影變換
  • 正投影
    • 軸測、等軸測正投影
    • 正投影座標系
    • 裁剪視窗、正投影觀察體
    • 正投影的規範化變換
  • 斜投影
    • 斜*行投影
    • 斜等測、斜二測*行投影
    • 斜*行投影變換
  • 透視投影
    • 投影參考點與觀察原點
    • 座標變換
    • 特殊透視投影
    • 滅點
      • 滅點與投影參考點
    • 透視投影觀察體
    • 透視投影變換矩陣
    • 對稱透視投影椎體
    • 斜透視投影稜臺
    • 透視投影的規範化變換

投影變換

img

將物件描述從世界座標系變換到觀察座標系後,要將其投影到觀察*面,即投影變換。有2種投影方式:

  1. *行投影(parallel projection),座標位置沿*行線變換到觀察*面。保持物件的比例不變,常用於輔助繪圖、設計生成工程圖。獲取物件*行檢視的方法有2種:1)沿垂直於觀察*面的直線投影;2)沿某傾斜角度投影到觀察*面。

  2. 透視投影(perspective projection),物件位置沿會聚到觀察*面後的一點(即投影參考點/投影中心)的直線,變換到投影座標系。透視投影不會保持物件比例,但真實感更好。

注意:概念上,投影變換指將物件變換到觀察*面;實際應用中,投影變換除了指將物件變換到觀察*面,還包括規範化變換。

線段\(P_1P_2\)的*行投影、透視投影示意圖:

img

正投影

物件沿與投影*面法向量N*行的方向,到投影*面上的變換N稱為正投影(orthogonal projection)或正交投影(orthographic projection)。

正投影:特殊的*行投影,投影線//投影*面法向量N。常用於生成物件的前檢視、側檢視、頂檢視,可用於建築和工程繪圖。

img

軸測、等軸測正投影

軸測正投影:

生成顯示物件多個側面的正投影,這些檢視稱為軸測(axonometric)正投影。

等軸測投影:

等軸測(isometric)投影是特殊軸測投影,其投影*面與每個座標軸的交點到原點距離相等。

常見等軸測投影:多個投影*面形成一個立方體,立方體8個頂點分佈在觀察座標系的8分象限。

img

正投影座標系

觀察座標系\(x_{view}y_{view}z_{view}\)下,如果投影方向//\(z_{view}\)軸,則任意點\((x,y,z)\)的投影座標\((x_p,y_p,z_p)\)

\[\tag{6} x_p=x, y_p=y, z_p=z_{vp} \]

其中,\(z_{vp}\)為觀察*面位置(觀察*面⊥\(z_{view}\)軸)。\(z_p\)值被儲存,用於可見性檢測。

任一點到觀察*面的正交投影:

img

裁剪視窗、正投影觀察體

常用矩形裁剪視窗來模擬照相機的鏡頭,用於確定有多少場景要顯示。
OpenGL中,裁剪視窗位於觀察*面上,位置、大小由矩形左下角+右上角確定,其邊與觀察座標系\(x_{view}, y_{view}\)軸*行,即\(x_{view}y_{view}\)*面的正則矩形。裁剪視窗邊界限定了要顯示的場景內容的x、y範圍。

觀察*面上用觀察座標指定裁剪視窗:

img

∵正投影的投影線⊥觀察*面
∴裁剪視窗的4個邊界的投影線⊥觀察*面
此時,裁剪視窗的4個邊界的投影線形成一個無限的裁剪區域,即沒有頭尾的長方體,如下圖:

img

選擇1個或2個邊界*面(//觀察*面),為該(無限裁剪)區域\(z_{view}\)方向限定邊界,該區域稱為正交觀察體(orthographic view volume),這2個*面稱為*-遠裁剪*面(near-far clipping plane)或前-後裁剪*面(front-back clipping plane)。正交觀察體外的場景物件會被排除,不會顯示。觀察方向沿\(-z_{view}\)軸,有\(z_{far} < z_{near}\)

由遠、*裁剪*面形成的正交投影觀察體:

img

正投影的規範化變換

觀察座標系下,任一點\((x,y,z)\)到觀察*面的正交投影位置\((x,y)\)。觀察體內的物件,經規範化變換到規範化立方體,直接對映到規範化觀察體(normalized view volume/canonical view volume)。

\[觀察座標系(右手系)內一點\xrightarrow{正交投影}正投影觀察體(右手系)\xrightarrow{規範化變換}規範化觀察體(左手系) \]

規範化觀察體有兩種:
1)單位立方體:限制x、y、z範圍為0~1;
2)對稱立方體:限制x、y、z範圍為-1~1。

因為螢幕座標系常用左手系,所以規範化觀察體也用左手系。觀察方向正距離,代表距離螢幕(觀察*面)的距離。

左手螢幕座標系:

img

  • 規範化變換

設**面、遠*面:\(z=z_{near},z=z_{far}, z_{far}<z_{near}<0\);規範化變換對映:\((xw_{min},yw_{min},z_{near})\to(-1,-1,-1)\)\((xw_{max},yw_{max},z_{far})\to(1,1,1)\)

正交投影的規範化變換示意圖:

img

正交投影規範化變換有兩種推導方法:

方法一:分解法,將變換分解為三步:
1)*移:將觀察體中心*移到規範化座標系原點;
2)反射:以z軸為反射軸,將觀察體進行反射;
2)縮放:將x、y、z座標放縮到-1~1範圍.

*移矩陣:

\[\begin{aligned} T&=T(-{xw_{min}+xw_{max}\over 2},-{yw_{min}+yw_{max}\over 2},-{z_{near}+z_{far}\over 2})\\ &=\begin{pmatrix} 1&0&0&-{xw_{min}+xw_{max}\over 2}\\ 0&1&0&-{yw_{min}+yw_{max}\over 2}\\ 0&0&1&-{z_{near}+z_{far}\over 2}\\ 0&0&0&1 \end{pmatrix} \end{aligned} \]

\(z_{norm}\)軸與\(z_{view}\)軸反向
∴反射矩陣(參見計算機圖形:特殊幾何變換):

\[Reflect_z=\begin{pmatrix} 1&0&0&0\\ 0&1&0&0\\ 0&0&-1&0\\ 0&0&0&1 \end{pmatrix} \]

放縮矩陣:

\[\begin{aligned} S&=S({2\over xw_{max}-xw_{min}},{2\over yw_{max}-yw_{min}},{2\over z_{near}-z_{far}})\\ &=\begin{pmatrix} {2\over xw_{max}-xw_{min}}&0&0&0\\ 0&{2\over yw_{max}-yw_{min}}&0&0\\ 0&0&{2\over z_{near}-z_{far}}&0\\ 0&0&0&1 \end{pmatrix} \end{aligned} \]

複合變換矩陣:

\[\tag{7} \begin{aligned} M_{ortho,norm}&=S\cdot Reflect_z\cdot T\\ &=\begin{bmatrix} {2\over xw_{max}-xw_{min}} & 0 & 0 & -{xw_{min}+xw_{max}\over xw_{max}-xw_{min}}\\ 0 & {2\over yw_{max}-yw_{min}} & 0 & -{yw_{min}+yw_{max}\over yw_{max}-yw_{min}}\\ 0 & 0 & {-2\over z_{near}-z_{far}} & {z_{near}+z_{far}\over z_{near}-z_{far}}\\ 0 & 0 & 0 & 1 \end{bmatrix} \end{aligned} \]

方法二:座標變換法

以z軸為例:

img

變換遵循原則:z座標在變換前後,到起點的距離與z軸跨度的比例保持不變。即:

\[\begin{aligned} &\frac{z-z_{near}}{z_{far}-z_{near}}=\frac{z_c-(-1)}{1-(-1)}\\ \implies &z_c=\frac{-2}{z_{far}-z_{near}}z+\frac{z_{near}+z_{far}}{z_{near}-z_{far}}\\ \end{aligned} \]

其中,*、遠*面為:\(z=z_{near},z=z_{far},z_{far}<z_{near}<0\)

同理,

\[\begin{aligned} &\frac{x-xw_{min}}{xw_{max}-xw_{min}}=\frac{x_c-(-1)}{1-(-1)}\\ &\frac{y-yw_{min}}{yw_{max}-yw_{min}}=\frac{y_c-(-1)}{1-(-1)}\\ \implies &x_c=\frac{2}{xw_{max}-xw_{min}}x-\frac{xw_{min}+xw_{max}}{xw_{max}-xw_{min}}\\ &y_c=\frac{2}{yw_{max}-yw_{min}}y-\frac{yw_{min}+yw_{max}}{yw_{max}-yw_{min}} \end{aligned} \]

根據座標變換,可以構造出正交投影變換矩陣\(M_{ortho,norm}\)(即上面式(7)),以滿足:

\[\begin{pmatrix} x_c\\y_c\\z_c\\1 \end{pmatrix} =M_{ortho,norm}\begin{pmatrix} x\\y\\z\\1 \end{pmatrix} \]

注意:有的文獻中,z軸變換會有差異,這是因為*、遠*面設定不同. 例如,令*、遠*面\(z=-z_{near},z=-z_{far},z_{far}>z_{near}>0\)
此時,

\[\begin{aligned} &\frac{z-(-z_{near})}{(-z_{far})-(-z_{near})}=\frac{z_c-(-1)}{1-(-1)}\\ \implies &z_c=\frac{2}{z_{far}-z_{near}}z+\frac{z_{near}+z_{far}}{z_{near}-z_{far}}\\ \implies &M_{ortho,norm}(3;3)=\frac{2}{z_{far}-z_{near}},\\&M_{ortho,norm}(3;4)=\frac{z_{near}+z_{far}}{z_{near}-z_{far}} \end{aligned} \]

斜投影

當*行投影的投影線與觀察*面不*行時,該對映稱為斜投影(oblique parallel projection)。

*行投影={正交投影, 斜投影}

斜*行投影

如下圖,場景中一點\(P(x,y,z)\)在觀察*面(\(z=z_{vp}\))正投影點\(P_1(x,y,z_{vp})\),斜投影點\(P_2(x_p,y_p,z_{vp})\)\(|P_1P_2|=L\)
斜*行投影用2個角度描述:
1)α,斜*行投影線與\(P_1P_2\)的夾角;
2)φ,\(P_1P_2\)\(x_{view}\)軸的夾角;
其中,α∈[0,π/2),φ∈[0,2π)

img

斜投影座標:

\[\tag{8} x_p=x+L\cos φ\\ y_p=y+L\sin φ \]

\(\vartriangle PP_1P_2\)中,求L:

\[\tag{9} \tan α={z_{vp}-z\over L}\\ \therefore L={z_{vp}-z\over \tan α}=(z_{vp}-z)\cot α \]

\(z_{vp}-z=1\)時,\(L=\cot α\)
有,

\[x_p=x+\cot α\cos φ\\ y_p=y+\cot α\sin φ \]

α=π/2時,可得正投影。

  • 斜*行投影向量

斜投影線的方向,稱為斜*行向量(parallel-projection vector),用\(V_p\)表示。觀察座標系下,\(V_p=(V_{px},V_{py},V_{pz}), \tan φ={V_{py}\over V_{px}}\)
\(V_p//\overrightarrow{P_1P_2}\)
\(V_p,\overrightarrow{P_1P_2}\)\(x_{view},y_{view},z_{view}\)軸分量比例相同(證明見下文),即

\[\frac{(\overrightarrow{P_1P_2})_x}{(\overrightarrow{P_1P_2})_z}={x_p-x\over z_{vp}-z}={V_{px}\over V_{pz}}\\ \frac{(\overrightarrow{P_1P_2})_y}{(\overrightarrow{P_1P_2})_z}={y_p-y\over z_{vp}-z}={V_{py}\over V_{pz}} \]

於是,斜*行投影可用正交投影向量表示成:

\[\tag{10} \begin{aligned} x_p=x+(z_{vp}-z){V_{px}\over V_{pz}}\\ y_p=y+(z_{vp}-z){V_{py}\over V_{pz}} \end{aligned} \]

推論:三維空間下,*行向量\(\vec V_1(x_1,y_1,z_1),\vec V_2(x_2,y_2,z_2)\)的xyz座標分量比例相同,即

\[{x_1\over y_1}={x_2\over y_2},{x_1\over z_1}={x_2\over z_2}, {y_1\over z_1}={y_2\over z_2} \]

證明:
假設\(\vec V_1=(x_1,y_1,z_1)//\vec V_2=(x_2,y_2,z_2)\),那麼,
存在λ∈R且λ≠0,使得

\[\vec V_1=λ\vec V_2\\ \implies (x_1,y_1,z_1)=λ(x_2,y_2,z_2)\\ \implies {x_1\over x_2}={y_1\over y_2}={z_1\over z_2}=λ\\ \implies {x_1\over y_1}={x_2\over y_2},{x_1\over z_1}={x_2\over z_2}, {y_1\over z_1}={y_2\over z_2} \]

即得證。

斜等測、斜二測*行投影

φ常用π/3(60°)、π/4(45°),顯示物件前、側、頂檢視的組合(或前、側、底)。

α常用值:
1)α=45°(tan α=1),獲得檢視稱為斜等測(cavalier)投影圖,垂直於投影*面的線條投影后長度不變。

2)α≈63.4°(tan α=2),獲得檢視稱為斜二測(cabinet)投影圖,垂直於投影*面的線條投影后長度為原來一半。真實感較1)更好。

斜*行投影變換

由式(10),可得斜*行投影變換矩陣:

\[\begin{aligned} P_2&=M_{oblique}\cdot P\\ \begin{bmatrix} x_p\\ y_p\\ z_{vp}\\ 0 \end{bmatrix} &= M_{oblique} \cdot \begin{bmatrix} x\\ y\\ z\\ 0 \end{bmatrix} \end{aligned}\\ \implies \tag{11} M_{oblique}=\begin{bmatrix} 1 & 0 & -{V_{px}\over V_{pz}} & z_{vp}{V_{px}\over z_{pz}}\\ 0 & 1 & -{V_{py}\over V_{pz}} & z_{vp}{V_{py}\over V_{pz}}\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \]

透視投影

將物件沿會聚到投影參考點(projection reference point)或投影中心(center of projection)的路徑投影到觀察*面來逼*幾何光學效果,稱為透視投影

*行投影:保持物件相對比例;
透視投影:模仿人眼或照相機,具有*大遠小的真實感。

透視投影示意圖:

img

投影參考點與觀察原點

  • 投影參考點是透視投影才有的概念;觀察原點是基於觀察座標系的概念,所有投影都有。

  • 有的圖形軟體包將投影參考點設在觀察原點,即視點;有的將投影參考點作為另一觀察引數來選擇。i.e. 投影參考點可視作觀察原點,也可不同,取決於具體環境,參見下文“特殊透視投影”部分。

座標變換

場景中任一點\(P(x,y,z)\)到投影參考點\(P_{0}(x_{prp},y_{prp},z_{prp})\)的投影示意圖:

img

投影線與觀察*面交點\(P'(x_p,y_p,z_{vp})\)

投影線上任一點\((x',y',z')\)引數方程(證明見下面推論):

\[\tag{12} \begin{aligned} x'&=x-(x-x_{prp})u\\ y'&=y-(y-y_{prp})u\\ z'&=z-(z-z_{prp})u \end{aligned} \]

u=0時,代表點P(x,y,z);
u=1時,代表投影參考點\(P_0(x_{prp},y_{prp},z_{prp})\)

寫成點形式:

\[P'=(1-u)P+uP_{0},u=\frac{|PP'|}{|PP_0|}\in [0,1] \]

推論:兩點\(S_1(x_1,y_1,z_1)、S_2(x_2,y_2,z_2)\)確定直線段L,L上任一點\(S(x,y,z)\)座標方程:

\[\begin{cases} x&=ux_1+(1-u)x_2\\ y&=uy_1+(1-u)y_2 & u\in [0,1]\\ z&=uz_1+(1-u)z_2 \end{cases} \]

證明:
∵S位於直線L
\(S_1S//S_2S\)
∴存在非0實數λ,使得\(x-x_1=λ(x-x_2)\)
\(x={1\over 1-λ}x_1-{λ\over 1-λ}x_2\)
\(u={1\over 1-λ}\),有\(x=ux_1+(1-u)x_2\)
∵x線上段\(S_1S_2\)上,不妨設\(x_1\le x_2\)
\(x_1\le x\le x_2\)
\(x_1\le ux_1+(1-u)x_2\le x_2\)
\(0\le u\le 1\)

同理可證,y、z座標也成立。故得證。

證明也可參見:數學基礎:三角形重心座標插值公式的證明

  • 如何求投影變換公式?

要求投影變換公式,就需要求出P在觀察*面\(z'=z_{vp}\)上的投影點\(P'\)

img

如上圖,根據三角形相似性,可求出:

\[\tag{13} u={z_{vp}-z\over z_{prp}-z}=\frac{|PP'|}{|PP_0|} \]

於是

\[\tag{14} \begin{aligned} x_p&=(1-u)x+ux_{prp}={z_{prp}-z_{vp}\over z_{prp}-z}x+{z_{vp}-z\over z_{prp}-z}x_{prp}\\ y_p&=(1-u)y+uy_{prp}={z_{prp}-z_{vp}\over z_{prp}-z}y+{z_{vp}-z\over z_{prp}-z}y_{prp}\\ z_p&=z_{vp} \end{aligned} \]

特殊透視投影

限制投影參考點或觀察*面。

1)投影參考點限制在\(z_{view}\)軸,即\(x_{prp}=y_{prp}=0\)

\[\tag{15} x_p={z_{prp}-z_{vp}\over z_{prp}-z}x, y_p={z_{prp}-z_{vp}\over z_{prp}-z}y \]

2)將投影參考點固定在原點,即\((x_{prp},y_{prp},z_{prp})=(0,0,0)\)

\[\tag{16} x_p={z_{vp}\over z}x, y_p={z_{vp}\over z}y \]

3)觀察*面是uv*面(uvn座標系),對投影參考點位置不限制,即\(z_{vp}=0\)

\[\tag{17} \begin{aligned} x_p&={z_{prp}\over z_{prp}-z}x-{z\over z_{prp}-z}x_{prp}\\ y_p&={z_{prp}\over z_{prp}-z}y-{z\over z_{prp}-z}y_{prp} \end{aligned} \]

tips:uvn座標系下,\(u,v,n\)分別代表\(x_{view},y_{view},z_{view}\)。參見uvn觀察座標系

4)觀察*面是uv*面,投影參考點在\(z_{view}\)軸,即\(z_{vp}=0,x_{prp}=y_{prp}=0\)

\[\tag{18} \begin{aligned} x_p&={z_{prp}\over z_{prp}-z}x\\ y_p&={z_{prp}\over z_{prp}-z}y \end{aligned} \]

注意:投影參考點不能位於觀察*面\(z_{prp}\neq z_{vp}\),否則所有物件投影到觀察*面上一點。

滅點

當一個場景使用透視投影到觀察*面上時,*行於觀察*面的線條投影后仍然*行。但任何與觀察*面不*行的*行線組投影后,會成為一組會聚線條。一組投影*行線會聚的點,稱為滅點(vanishing point)。每組*行線都有自己的滅點。

主滅點(principal vanishing point):物件上*行於一個主軸的一組*行線的滅點。座標軸有3個,所以主滅點最多有3個。

透過投影*面的方向,可以控制主滅點的數量(1,2或3),對應透視投影分為一點、兩點或三點投影。

下圖是一個立方體的一點、兩點透視投影:

img

滅點與投影參考點

不同點:

  • 是否能修改

投影參考點模擬人眼或攝像機,一旦選定,不能隨意修改;滅點會隨著物件的幾何變換而改變位置。

  • 針對物件

滅點針對物件的一組*行線,可能有0個或多個;投影參考點針對所有透視投影,只有1個點。i.e. 透視投影一定存在投影參考點,而*行於觀察*面的線組不存在滅點。

透視投影觀察體

在觀察*面上指定一個矩形裁剪視窗,可得到透視投影觀察體(perspective projection view volumes),稱為視覺稜錐體(pyramid of vision)。稜錐體外的所有物件,都會被裁剪子程式消除。

視覺稜錐體:

img

注: 投影中心也是投影參考點。

新增垂直於\(z_{view}\)的遠、**面,可得到稜臺觀察體(frustum view volumes)。通常,遠、**面位於投影參考點同側(簡化版人眼/相機觀察模型),且遠*面距投影參考點更遠。

稜臺觀察體:

img

注:有些應用/模型為計算方便,將*裁剪*面設為與觀察*面重合.

透視投影變換矩陣

式(14)給出透視投影變換的一般形式,但不能直接得到變換矩陣,因為x、y係數含z(非常數)。可將其轉化成別的引數形式,然後再用三維齊次座標表示:

\[\tag{19} x_p={x_h\over h},y_p={y_h\over h} \]

其中,任一點\(P(x,y,z)\),P的投影點\(P'(x_p,y_p,z_p)\),投影參考點\(P_0(x_{prp},y_{prp},z_{prp})\),觀察*面\(z=z_{vp}\)

齊次引數:

\[\tag{20} h=z_{prp}-z \]

\(x_h,y_h\)

\[\tag{21} \begin{aligned} x_h=x(z_{prp}-z_{vp})+x_{prp}(z_{vp}-z)\\ y_h=y(z_{prp}-z_{vp})+y_{prp}(z_{vp}-z) \end{aligned} \]

用齊次座標的矩陣變換表示透視變換:

\[\tag{22} P_h=M_{pers}\cdot P \]

其中,\(P_h=(x_h,y_h,z_h,h)^T,P=(x,y,z,1)^T\)

可得一種可能的透視投影變換矩陣:

\[\tag{22} M_{pers}=\begin{bmatrix} z_{prp}-z_{vp} & 0 & -x_{prp} & x_{prp}z_{vp}\\ 0 & z_{prp}-z_{vp} & -y_{prp} & y_{prp}z_{vp}\\ 0 & 0 & s_z & t_z\\ 0 & 0 & -1 & z_{prp} \end{bmatrix} \]

其中,引數\(s_z,t_z\)是z座標投影值規範化過程中的比例和*移因子,值依賴於稜臺觀察體範圍和規範化範圍。如果不放縮、*移,則預設值分別為1, 0。

特例:如果將投影參考點限制在觀察原點,且不做規範化和*移即\(s_z=1,t_z=0\),則\((x_{prp},y_{prp},z_{prp})=(0,0,0)\). 那麼,\(h=-z\)

\[\begin{aligned} M_{pers}&=\begin{bmatrix} -z_{vp} & 0 & 0 & 0\\ 0 & -z_{vp} & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & -1 & 0 \end{bmatrix} \end{aligned} \]

對稱透視投影椎體

兩種描述方法:

1. 使用中心線

從投影參考點到裁剪視窗中心並穿過觀察體的線條,是透視投影稜臺的中心線。如下圖,如果中心線⊥投影*面,則觀察體為對稱稜臺(symmetric frustum)(相對於中心線)。

img

觀察座標系下,觀察*面\(z=z_{vp}\),投影參考點\(P_{prp}(x_{prp},y_{prp},z_{prp})\),則中心線與觀察*面交於\((x_{prp},y_{prp},z_{vp})\)。裁剪視窗寬、高分別為width、height,則裁剪視窗邊界:

\[\begin{aligned} xw_{min}&=x_{prp}-{width\over 2}, xw_{max}=x_{prp}+{width\over 2}\\ yw_{min}&=y_{prp}-{height\over 2}, yw_{max}=y_{prp}+{height\over 2} \end{aligned} \]

注意:xw/yw的w指clipping window.

因此,對於對稱透視投影錐體,可用裁剪視窗寬、高代替視窗座標。

2. 使用視場角、裁剪視窗寬高比

視場角(field-of-view angle):稜臺的上裁剪*面與下裁剪*面的夾角。對稱稜臺*似於照相機鏡頭捕獲的場景視錐,可用於度量鏡頭的尺寸。

img

視場角與裁剪視窗高度關係:

\[\tag{23} \tan ({\theta\over 2})={height/2\over z_{prp}-z_{vp}} \]

於是,裁剪視窗高度:

\[\tag{24} height=2(z_{prp}-z_{vp})\tan ({\theta\over 2}) \]

再利用裁剪視窗寬高比aspect,就能得到寬度:\(width=aspect\cdot height\)

img

對稱稜臺觀察體經透視投影變換後,變成矩形*行管道觀察體,變換後的點的範圍限制在*行管道觀察體內:

img

斜透視投影稜臺

如果透視投影觀察體的中心線不垂直於觀察*面,則得到一個斜稜臺(oblique frustum)。

斜透視投影 = 錯切 + 透視變換

斜稜臺頂檢視:

img

斜稜臺投影觀察體,可透過相對於z軸的x方向、y方向錯切(參見三維錯切)變換成對稱稜臺。

為計算方便,將投影參考點設為觀察原點,即\((x_{prp},y_{prp},z_{prp})=(0,0,0)\). 可設錯切矩陣:

\[\tag{24} \begin{aligned} M_{zshear}=\begin{bmatrix} 1 & 0 & sh_{zx} & 0\\ 0 & 1 & sh_{zy} & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{bmatrix} \end{aligned} \]

如果觀察*面 = *裁剪*面(即\(z_{vp}=z_{near}\)),則透視投影矩陣可進一步簡化。

∵錯切將裁剪視窗\((xw_{min},xw_{max},z_{near})\)中心移到觀察*面原點\((0,0,z_{near})\)

∴錯切引數\(sh_{zx},sh_{zy}\)滿足:

\[\tag{25} \begin{bmatrix} 0\\ 0\\ z_{near}\\ 1 \end{bmatrix}= M_{zshear}\cdot \begin{bmatrix} {xw_{min}+xw_{max}\over 2}\\ {yw_{min}+yw_{max}\over 2}\\ z_{near}\\ 1 \end{bmatrix} \]

∴有

\[\tag{26} \begin{aligned} sh_{zx}&=-{xw_{min}+xw_{max}\over 2z_{near}}\\ sh_{zy}&=-{yw_{min}+yw_{max}\over 2z_{near}} \end{aligned} \]

  • 簡化(對稱)透視投影矩陣

當投影參考點位於觀察原點,且*裁剪*面與觀察*面重合(OpenGL預設)時,則透視投影變換矩陣(22)可簡化為:

\[\tag{27} M_{pers}=\begin{bmatrix} -z_{near} & 0 & 0 & 0\\ 0 & -z_{near} & 0 & 0\\ 0 & 0 & s_z & t_z\\ 0 & 0 & -1 & 0 \end{bmatrix} \]

其中,z座標縮放和*移引數\(s_z, t_z\)由規範化確定。\(h=z_{prp}-z=-z\)

  • 簡化斜透視投影矩陣

將簡化後的透視矩陣(27)和錯切矩陣(24)合併,可得到將場景中座標轉換為齊次正交座標系的斜透視投影矩陣。該變換中,投影參考點是觀察原點,*裁剪*面是觀察*面:

\[\tag{28} \begin{aligned} M_{oblique\_pers}&=M_{pers}\cdot M_{zshear}\\ &=\begin{bmatrix} -z_{near} & 0 & {xw_{min}+xw_{max}\over 2} & 0\\ 0 & -z_{near} & {yw_{min}+yw_{max}\over 2} & 0\\ 0 & 0 & s_z & t_z\\ 0 & 0 & -1 & 0 \end{bmatrix} \end{aligned} \]

如果裁剪視窗關於觀察原點對稱,即\(xw_{max}=-xw_{min},yw_{max}=-yw_{min}\),則稜臺觀察體是對稱的,(28)可簡化為(27)(無需錯切,因為投影參考點位於觀察原點)。

透視投影的規範化變換

透視投影最後一步:稜臺觀察體(矩形*行管道,座標符合右手系)\(\xrightarrow{規範化}\)規範化觀察體(對稱立方體,座標符合左手系)。

透視投影規範化 = *行管道觀察體的正交投影

規範化示意圖(*裁剪*面作為觀察*面):

img

規範化變換中,矩形*行管道中心線\(z_{view}\),在x、y方向不再需要*移,只需要相對於原點的x、y縮放。xy規範化縮放矩陣:

\[\tag{29} M_{xyscale}=\begin{pmatrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix} \]

將(28)(29)合併,生成透視投影變換的規範化矩陣:

\[\tag{30} \begin{aligned} M_{norm\_pers}&=M_{xyscale}\cdot M_{oblique\_pers}\\ &=\begin{pmatrix} s_x & 0 & 0 & 0\\ 0 & s_y & 0 & 0\\ 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 1 \end{pmatrix} \begin{pmatrix} -z_{near} & 0 & {xw_{min}+xw_{max}\over 2} & 0\\ 0 & -z_{near} & {yw_{min}+yw_{max}\over 2} & 0\\ 0 & 0 & s_z & t_z\\ 0 & 0 & -1 & 0 \end{pmatrix}\\ &=\begin{pmatrix} -z_{near}s_x & 0 & \frac{xw_{min}+xw_{max}}{2}s_x & 0\\ 0 & -z_{near}s_y & \frac{yw_{min}+yw_{max}}{2}s_y & 0\\ 0 & 0 & s_z & t_z\\ 0 & 0 & -1 & 0 \end{pmatrix} \end{aligned} \]

(30)對應的規範化變換:

\[\tag{31} \begin{pmatrix} x_h\\ y_h\\ z_h\\ h \end{pmatrix} =M_{norm\_pers}\cdot \begin{pmatrix} x\\ y\\ z\\ 1 \end{pmatrix} \]

\(P(x,y,z)\)的投影座標\(P'(x_p,y_p,z_p)\)

\[\begin{aligned} x_p&=\frac{x_h}{h}=\frac{-s_xz_{near}x+s_x(xw_{min}+xw_{max})/2}{-z}\\ y_p&=\frac{y_h}{h}=\frac{-s_yz_{near}x+s_y(yw_{min}+yw_{max})/2}{-z}\\ z_p&=\frac{z_h}{h}=\frac{s_zz+t_z}{-z} \end{aligned} \]

其中,\(h=-z\)

如何確定引數\(s_x,s_y,s_z,t_z\)

座標對映:\((xw_{min},yw_{min},z_{near})\xrightarrow{}(-1,-1,-1), (xw_{max},yw_{max},z_{far})\xrightarrow{}(1,1,1)\).

\(s_x,s_y\)分別將長度\(xw_{max}-xw_{min},yw_{max}-yw_{min}\)放縮為新長度2,2

\[\begin{aligned} s_x&=\frac{2}{xw_{max}-xw_{min}},\\ s_y&=\frac{2}{yw_{max}-yw_{min}} \end{aligned} \]

\(s_z,t_z\)將輸入座標\(z_{near},z_{far}\)分別轉換為\(-1,1\)
∴需滿足

\[\begin{aligned} -1&=\frac{s_zz_{near}+t_z}{-z_{near}}\\ 1&=\frac{s_zz_{far}+t_z}{-z_{far}} \end{aligned} \]

∴有

\[\begin{aligned} s_z&=\frac{z_{near}+z_{far}}{z_{near}-z_{far}},\\ t_z&=\frac{-2z_{near}z_{far}}{z_{near}-z_{far}} \end{aligned} \]

∴代入(30)可得

\[M_{norm\_pers}=\begin{pmatrix} \frac{-2z_{near}}{xw_{max}-xw_{min}} & 0 & \frac{xw_{min}+xw_{max}}{xw_{max}-xw_{min}} & 0\\ 0 & \frac{-2z_{near}}{yw_{max}-yw_{min}} & \frac{yw_{min}+yw_{max}}{yw_{max}-yw_{min}} & 0\\ 0 & 0 & \frac{z_{near}+z_{far}}{z_{near}-z_{far}} & \frac{-2z_{near}z_{far}}{z_{near}-z_{far}}\\ 0 & 0 & -1 & 0 \end{pmatrix} \]

這就是透視投影(包括規範化)矩陣.

注意:該投影矩陣對應模型與OpenGL約定一致,包括
1)觀察座標系為右手系統,規範化座標系為左手系統;
2)投影參考點位於觀察原點,觀察*面位於*裁剪*面;
3)遠、*裁剪*面關係:\(z_{far}<z_{near}<0\)(包含符號).

相關文章