圖形學 坐標系空間變換

3D物體從三維坐標映射到2D屏幕上,要經過一系列的坐標系變換,這些坐標系如下:

  1. model
    物體本身(local)的坐標系,是相對坐標。
    比如一個3D人物模型,頭部某個點的坐標為(0,0,20),這是相對該模型的中心點(0,0,0)說的。當模型向前移動了5個單位,其中心點依舊是(0,0,0),頭部那個點依舊是(0,0,20)
  2. world
    世界坐標系,即物體放在世界里的坐標,也就是大家最能理解的那個坐標。
    還是上面的例子,他沿Z軸移動了5個單位后,中心點在世界坐標里變成了(0,0,5),頭部那個點變成了(0,0,25)。
    物體的位移,縮放,旋轉會改變它的世界坐標,不會改變它的model坐標。
  3. image
    相機坐標系。
    相機也是世界里的一個物體,相機坐標就是以相機位置為坐標原點,相機的朝向為Z軸方向的坐標系。因為我們在電腦里看到的物體其實都是“相機”幫助我們看的,“相機”就是我們的眼睛,所以要以相機為標準進行坐標轉換。
    在model,world,image坐標系下,X,Y,Z的范圍都是無窮大,只是坐標系的基準不一樣而已。
  4. perspective (NDC, Normalized Device Coords)
    透視坐標系。
    這一步是將三維坐標向二維平面進行映射,經過透視變換之后,(x, y)的范圍在[-1, 1],z的范圍在[0, 1]
    可能有點難以理解,本文后面會有專門解釋。
  5. screen
    屏幕坐標系。
    因為屏幕是有分辨率的,比如1920×1080,所以還要再進行一次變換。
    該坐標系的原點在屏幕左上角,x軸朝右,y軸朝下。x的范圍在[0, xres-1],y的范圍在[0, yres-1],即x是[0, 1920),y是[0, 1080)。
    z值是[0, MAXINT],z=0就是屏幕那個平面,z=MAXINT就是無窮遠。

經過這5個坐標系空間的變換,3維物體才最終投影到2維電腦平面上。

坐標系的變換矩陣

不清楚什么是變換矩陣,以及不清楚四維坐標的請看我之前的文章
1. 從model變到world
從模型本身的相對坐標變換到世界坐標,就是平移,旋轉,縮放。

2. 從world變到image(相機坐標)
這一步是將物體在世界的坐標轉換為相對相機的坐標。
相機也是世界里的物體,我們假定相機的中心點在世界里的位置是C(Cx, Cy, Cz)
相機正在看著某個方向,我們假定相機正在看的點的位置是I(Ix, Iy, Iz)
那么,相機的Z軸就是它看的方向的向量,即CI向量,也就是I - C = (Ix-Cx, Iy-Cy, Iz-Cz),我們將其標準化(即讓它的模為1),得到Z軸單位向量。
然后我們取世界坐標系里的up向量(0,1,0)


得到Z軸后求X, Y軸有兩個方法:
方法1:
通過up叉乘Z(注意順序),我們可以得到一個向量X1,將X1標準化(即使其模為1),我們就得到了X軸的單位向量。
在通過Z軸的單位向量與X軸的單位向量叉乘,即Z×X(注意順序),我們就得到了Y軸的單位向量。
方法2:
up' = up - (up·Z)Z
注意:(Z的模是1)
將up'標準化得到Y,Y×Z = X

然后我們就可以構造Xiw這么一個將世界坐標系投影到相機坐標系的變換矩陣了。
如何構造?
1)世界坐標系中,相機原點為(Cx, Cy, Cz),在相機坐標系中為(0,0,0)
所以,(0, 0, 0) = Xiw*(Cx, Cy, Cz)
2)世界坐標系中,相機的三個軸為X+C(Xx+Cx, Xy+Cy, Xz+Cz), Y+C(Yx+Cx, Yy+Cy, Yz+Cz), Z+C(Zx+Cx, Zy+Cy, Zz+Cz),但在相機坐標系下為(1,0,0),(0,1,0),(0,0,1)
所以
(1, 0, 0) = Xiw*(Xx+Cx, Xy+Cy, Xz+Cz)
(0, 1, 0) = Xiw*(Yx+Cx, Yy+Cy, Yz+Cz)
(0, 0, 1) = Xiw*(Zx+Cx, Zy+Cy, Zz+Cz)

結合上面2步的四個式子,可以求出Xiw



它的幾何意義就是先把坐標系移動到相機的原點處(最后一列Cx,Cy,Cz),然后再旋轉來調整到相機的X,Y,Z軸。

3. 從image變到perspective


當x=0時,yz平面如上圖所示。
z = -d是我們的觀察點,而Z=0就是相機的膠片,或者我們的視網膜,場景要投射到Z=0這個二維平面上。
我們需要將在相機坐標系里的(0,Y,Z)這個點投到Z = 0這個平面上,即a點,a點坐標為(0,y,0)。
根據三角形相似可知:
y/d = Y/(Z+d)
y = Yd/(Z+d) = Y/[(Z/d)+1]
我們對X和Z做同樣的操作,最終,一個相機坐標系里的點(X, Y, Z)會變成
(X/[(Z/d)+1],Y/[(Z/d)+1],Z/[(Z/d)+1]),這樣就投射到了Z=0這個平面上了。

注意
我們也不一定非要投到Z=0這個平面,投到Z=1,Z=d的平面都可以,式子是一樣的。

我們可以看出來,這個變換就是將坐標除了一個(Z/d)+1。
因此,將四維坐標轉換為Perspective坐標的變換矩陣為



經過該矩陣變換之后的四維坐標為(X, Y, Z, Z/d+1),轉換為三維坐標即為(X/[(Z/d)+1],Y/[(Z/d)+1],Z/[(Z/d)+1])

Perspective矩陣的定義的X, Y的范圍在[-1,1],而X/[(Z/d)+1],Y/[(Z/d)+1]的范圍是負無窮到正無窮,所以一旦X/[(Z/d)+1],Y/[(Z/d)+1]超出[-1, 1]的范圍,就直接扔掉不顯示在屏幕上了。

Perspective矩陣定義的Z的范圍在[0,1],所以還要將Z進一步限制,所以最終的矩陣為


這樣子z的值就成了(Z/d)/[(Z/d)+1],即1/[1+d/Z],滿足[0,1]這個范圍了。
而這個d又是多少呢?

FOV (Field of View)是定義相機視錐垂直方向(y軸方向)的張角(它是個角度),該張角與Z=0這個投影平面的交點是-1和1,因為x,y的范圍是[-1,1]。
從上圖可以看出,1/d就是tan(FOV/2)

4. 從perspective變到screen
定義屏幕分辨率為xs × rs
要將透視坐標系里的點映射過來,這個變換矩陣怎么構造?(參考Xiw)
1)首先我們先構造一個4維標準矩陣,即對角線都是1,其余都是0。
2)屏幕坐標系的原點是左上角,而perspective里的原點(0,0)在屏幕中應該位于屏幕中央,即(xs/2, ys/2)。那么perspective里的原點(0,0)會映射為(xs/2, ys/2),即位移一個(xs/2, ys/2,0)。
所以4維矩陣的最后一列是(xs/2, ys/2,0,1)
3)屏幕坐標系中x的范圍是[0, xs),y的范圍是[0, ys)。而Perspective坐標系中x和y的范圍是[-1,1],所以這個映射還要滿足-1映射到0,1映射到xs或ys。
目前為止,我們的4維矩陣變成了這樣:


注意:我們可以很明顯的發現矩陣第二行第二列是負的,這是因為之前的坐標系都是y軸正方向朝上的,而屏幕坐標系是y軸正方向朝下的,是反的,所以是負號,即perspective里的-1映射到屏幕里的ys,1映射到屏幕里的0。
4)屏幕坐標系中z的范圍是[0, MAXINT],Perspective坐標系中z是[0,1],所以再對z進一步限制,即1映射到MAXINT,得到最終結果。

所以,一個3D物體顯示到電腦屏幕上,要經過4重坐標系變換。
screen Xsp perspective (NDC) Xpi image Xiw world Xwm model
在實際的渲染引擎運行中,Xsp和Xpi基本不會變,因為你的屏幕分辨率很少會變動。Xiw會在相機移動和旋轉時改變。Xwm會在物體平移,旋轉,縮放時改變。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容