概述
在圖形學(xué)渲染管線中,一個(gè)頂點(diǎn)坐標(biāo),大概要經(jīng)歷局部坐標(biāo)系、世界坐標(biāo)系、相機(jī)坐標(biāo)系、裁剪坐標(biāo)系,最后到窗口坐標(biāo)系,顯示在屏幕上。

在這些過程中,從一個(gè)坐標(biāo)系到另一個(gè)坐標(biāo)系,都需要進(jìn)行一定的變換。下面,將介紹每次變換的方式。
注意,本文是針對(duì)OpenGL的。
局部空間->世界空間
這一變換過程,主要是將模型放置在世界空間中,進(jìn)行一定的縮放、旋轉(zhuǎn)或平移。這一步比較簡(jiǎn)單,只要將相應(yīng)的矩陣作用到模型的局部空間坐標(biāo)即可。
比如,對(duì)模型縮放,然后繞Z軸旋轉(zhuǎn)
度,再進(jìn)行
的平移。注意,這里的變換順序是不能變的,即要先進(jìn)行縮放,再進(jìn)行旋轉(zhuǎn),最后進(jìn)行平移。據(jù)此,我們可以構(gòu)建模型變換矩陣。
世界空間->相機(jī)空間
首先定義一下相機(jī):
坐標(biāo)為
觀察方向
向上方向
示意圖如下所示:

有一個(gè)性質(zhì)注意一下:當(dāng)相機(jī)和相機(jī)“看“到的物體一起變換時(shí),相機(jī)”看“到的內(nèi)容是不變的。這樣,可以將相機(jī)的坐標(biāo)移動(dòng)到世界坐標(biāo)的原點(diǎn),向上方向?qū)R世界坐標(biāo)的Y軸,觀察方向?qū)R世界坐標(biāo)的-Z軸。然后,對(duì)物體進(jìn)行相同的變換即可。
在數(shù)學(xué)上,這個(gè)過程大概這樣:
- 將相機(jī)移動(dòng)到坐標(biāo)原點(diǎn)
- 旋轉(zhuǎn)觀察方向
到-Z軸
- 旋轉(zhuǎn)向上方向
到Y(jié)軸
- 旋轉(zhuǎn)(
)到X軸
大體分為兩步:先位移,后旋轉(zhuǎn)。即。
平移部分:
對(duì)于旋轉(zhuǎn)部分,先補(bǔ)充一些知識(shí)點(diǎn)。對(duì)于二維空間來說:
根據(jù)定義,旋轉(zhuǎn)角度和旋轉(zhuǎn)
角度是互逆的,即:
。
所以,對(duì)于旋轉(zhuǎn)變換,可以得出旋轉(zhuǎn)矩陣的逆等于它的轉(zhuǎn)置,即:
回到上面的旋轉(zhuǎn)部分,直接求相機(jī)的坐標(biāo)軸旋轉(zhuǎn)到世界坐標(biāo)軸的矩陣不是很方便,但是反過來,求世界坐標(biāo)軸旋轉(zhuǎn)到相機(jī)的坐標(biāo)軸很容易:
根據(jù)旋轉(zhuǎn)矩陣的逆等于它的轉(zhuǎn)置,得出:
根據(jù),可以得出:
相機(jī)空間->裁剪空間
在一個(gè)頂點(diǎn)著色器運(yùn)行的最后,期望所有的坐標(biāo)都能落在一個(gè)特定的范圍內(nèi),且任何在這個(gè)范圍之外的點(diǎn)都應(yīng)該被裁剪掉(Clipped)。被裁剪掉的坐標(biāo)就會(huì)被忽略,所以剩下的坐標(biāo)就將變?yōu)槠聊簧峡梢姷钠巍_@也就是裁剪空間(Clip Space)名字的由來。
因?yàn)閷⑺锌梢姷淖鴺?biāo)都指定在-1.0到1.0的范圍內(nèi)不是很直觀,所以我們會(huì)指定自己的坐標(biāo)集(Coordinate Set)并將它變換回標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系。
由投影矩陣創(chuàng)建的觀察箱(Viewing Box)被稱為平截頭體(Frustum),每個(gè)出現(xiàn)在平截頭體范圍內(nèi)的坐標(biāo)都會(huì)最終出現(xiàn)在用戶的屏幕上。將特定范圍內(nèi)的坐標(biāo)轉(zhuǎn)化到標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系的過程(而且它很容易被映射到2D觀察空間坐標(biāo))被稱之為投影(Projection),因?yàn)槭褂猛队熬仃嚹軐?D坐標(biāo)投影(Project)到很容易映射到2D的標(biāo)準(zhǔn)化設(shè)備坐標(biāo)系中。
這里要注意一下,OpenGL是右手坐標(biāo)系的,但是在NDC中,是左手坐標(biāo)系的,這里要特別注意?。?!
相機(jī)空間轉(zhuǎn)換到裁剪空間,有需要用到投影變換。有兩種投影變換:正交投影和透視投影。下面分別介紹一下。
正交投影
我們先定義一個(gè)正交投影的視錐體(注意,n和f都是負(fù)數(shù),f是遠(yuǎn)平面,所以f<n),它是一個(gè)長(zhǎng)方體。我們需要做的,就是將正交投影的視錐體轉(zhuǎn)換到標(biāo)準(zhǔn)立方體(即標(biāo)準(zhǔn)化設(shè)備坐標(biāo),
)。注意,這里
映射到NDC中的[1,-1]。

這里,分成兩個(gè)步驟:平移和縮放。正交投影的矩陣如下:
透視投影
對(duì)于透視投影,分成兩步操作:
- 首先,“壓扁”視錐體成一個(gè)長(zhǎng)方體(n->n,f->f)(
);
- 然后,做正交投影操作(
,即上面的正交投影)。

觀察下圖:

根據(jù)相似三角形的關(guān)系,可以得出:
類似的,可以得出:
由此,可以得出下面的關(guān)系:
下面,說一個(gè)齊次坐標(biāo)的性質(zhì):在3D坐標(biāo)系統(tǒng)中,,
,
都表示相同的坐標(biāo)---
。例如:
和
都表示坐標(biāo)
。
所以,有如下關(guān)系:
更進(jìn)一步的,可以得到:
現(xiàn)在,還剩下第三列是未知的。
經(jīng)過觀察上面的透視投影視錐體,可以得出以下推論:
近平面上的點(diǎn)的坐標(biāo)都不會(huì)改變;
遠(yuǎn)平面上的點(diǎn),Z坐標(biāo)不改變。
根據(jù)推論1,近平面上的點(diǎn)經(jīng)過變換后,不會(huì)改變。即:
根據(jù):
因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=n%5E%7B2%7D" alt="n^{2}" mathimg="1">與x和y都沒有關(guān)系,所以可以得出的第三列的形式是
。
根據(jù):
可以得出:
根據(jù)推論2,遠(yuǎn)平面的中心點(diǎn),經(jīng)過變換后,還是本身。如下:
所以,可以得出:
即:
到這里,可以得出方程組:
到這里,可以得出:
最終,透視投影矩陣:
裁剪空間->窗口空間
在裁剪空間的最后,所以的可見的點(diǎn)都在標(biāo)準(zhǔn)設(shè)備坐標(biāo)系(NDC)中,即坐標(biāo)坐落在范圍內(nèi)。
先不考慮Z軸的變換。
從NDC到窗口空間,需要經(jīng)過視口變換。定義一個(gè)屏幕空間:。平面左下角的坐標(biāo)位
,右上角的坐標(biāo)為
。對(duì)于X和Y坐標(biāo)的變換,即從
到
。
這里,經(jīng)過兩步變換:
將NDC的中心平移到窗口的中心;
將NDC的大小縮放到屏幕的大小。
合并到一起:
對(duì)于Z坐標(biāo),從映射到了
。這里只是簡(jiǎn)單的線性映射。假設(shè)
,當(dāng)
等于-1時(shí),
等于0;當(dāng)
等于1時(shí),
等于1??傻萌缦路匠探M:
所以,。代入上述
矩陣,可得:
參考
[3] Steve Marschner and Peter Shirley,“Fundamentals of Computer Graphics”