齊次坐標(biāo)在計(jì)算機(jī)圖形中的應(yīng)用

原文: CC老師
著作所屬權(quán)歸該作者所有,任何形式轉(zhuǎn)載請聯(lián)系作者并注明原文出處.

提示: 齊次坐標(biāo)是在學(xué)習(xí)OpenGL ES 初期百思不得其解的地方. 希望這篇文章能夠給你幫助.此文將蘋果由CoreAnimation 透視投影為引子.為什么需要用4*4矩陣來描述坐標(biāo)變換?

核心動畫蘋果文檔-透視投影效果的設(shè)置

The sublayerTransform property defines additional transformations that apply only to the sublayers and is used most commonly to add a perspective visual effect to the contents of a scene.

Transforms work by multiplying coordinate values through a matrix of numbers to get new coordinates that represent the transformed versions of the original points. Because Core Animation values can be specified in three dimensions, each coordinate point has four values that must be multiplied through a four-by-four matrix, as shown in Figure 1-7. In Core Animation, the transform in the figure is represented by the CATransform3D type. Fortunately, you do not have to modify the fields of this structure directly to perform standard transformations. Core Animation provides a comprehensive set of functions for creating scale, translation, and rotation matrices and for doing matrix comparisons. In addition to manipulating transforms using functions, Core Animation extends key-value coding support to allow you to modify a transform using key paths. For a list of key paths you can modify, see CATransform3D Key Paths.

SublayerTransform屬性定義了僅應(yīng)用于子層的其他轉(zhuǎn)換,并且最常用于向場景內(nèi)容添加透視視覺效果。
轉(zhuǎn)換的工作原理是將坐標(biāo)值乘以一個數(shù)字矩陣,得到表示原始點(diǎn)轉(zhuǎn)換版本的新坐標(biāo)。因?yàn)楹诵膭赢嬛悼梢栽谌S中指定,所以每個坐標(biāo)點(diǎn)有四個值,必須通過一個四乘四的矩陣相乘,如圖1-7所示。在核心動畫中,圖形中的變換由CatTransform3D類型表示。幸運(yùn)的是,您不必直接修改這個結(jié)構(gòu)的字段來執(zhí)行標(biāo)準(zhǔn)轉(zhuǎn)換。核心動畫為創(chuàng)建比例、平移和旋轉(zhuǎn)矩陣以及進(jìn)行矩陣比較提供了一套全面的功能。除了使用函數(shù)操縱變換之外,核心動畫還擴(kuò)展了關(guān)鍵值編碼支持,允許您使用關(guān)鍵路徑修改變換。有關(guān)可以修改的關(guān)鍵路徑列表,請參見CatTransform3D關(guān)鍵路徑。

透視投影
  • 蘋果文檔關(guān)于單元矩陣,平移,縮放,圍繞x,y,z軸旋轉(zhuǎn)的矩陣


    矩陣變化

注意觀察,你會發(fā)現(xiàn)為什么透視投影中3D場景,x,y,z需要W分量了? 接下來我們帶著這疑惑看看蘋果官方文檔遺留下的問題進(jìn)行探討.

透視投影:


透視投影

為什么要將3D的笛卡爾坐標(biāo)轉(zhuǎn)換成四維齊次坐標(biāo),這樣有2個主要好處:

  1. 進(jìn)一步完成透徹變換
  2. 這樣可以使用線性變換來實(shí)現(xiàn)模型的平移.

如果使用四維坐標(biāo)系統(tǒng),就可以通過矩陣乘法完成所有的旋轉(zhuǎn),平移,縮放和投影的變換操作.

什么是齊次坐標(biāo)?

三維數(shù)據(jù)可以通過三維向量與3*3矩陣的乘法操作,來完成縮放和旋轉(zhuǎn)的線性變換.

在大多數(shù)3D工作中,我們參照的依據(jù)是幾何學(xué)中的三維空間(X, Y, Z)。
但在某些情況下,參照投影幾何更適用,除了 X, Y, Z 分量外,增加一個 W 分量,這個四維空間叫做“投影空間”,在四維空間中的坐標(biāo)叫“齊次坐標(biāo)”。為了達(dá)到3D軟件的目的,“投影的” 和 “齊次的” 可以理解為 "4D"。

注意: 四元數(shù)和齊次坐標(biāo)非常類似,都是四維向量.通常也是通過(x,y,z,w)來表示,但是四元坐標(biāo)和齊次坐標(biāo)是不同的概念,并且適用領(lǐng)域也不一樣. 簡單說,四元數(shù)與齊次坐標(biāo)沒有任何關(guān)系.

  • 齊次坐標(biāo)是計(jì)算機(jī)圖形學(xué)的重要手段之一,它既能夠用來明確區(qū)分向量和點(diǎn),同時也更易用于進(jìn)行仿射(線性)幾何變換.
  • 四元數(shù)本質(zhì)上是一種高階復(fù)數(shù),是一個四維空間,相對于復(fù)數(shù)的二維空間。

齊次坐標(biāo)在2D場景中應(yīng)用

想象投影儀在一個屏幕上投影一張2D的圖片,這時我們就能非常快速的理解X,Y分量的意義所在.


圖1

看到這張圖,我們就可以感受到投影儀與屏幕之間的距離,而這個距離就是w分量.


圖2

w分量就是投影儀與屏幕的距離在開發(fā)者角度就是觀察者與屏幕直接的距離.

圖3

那么w分量有什么作用了?
首先我們來到這樣的場景中,如果我們移動投影儀的位置,就是調(diào)整觀察者的位置.來增加或減少w分量,那么投影出的2D圖片會發(fā)生什么變換? 是不是如果投影儀靠近屏幕,2D圖片縮小; 如果投影儀遠(yuǎn)離屏幕,2D圖片就會放大; 此時通過調(diào)整觀察者的位置,來實(shí)現(xiàn)放大與縮小的目的.W分量,會影響投影出來的圖片大小;

齊次坐標(biāo)在3D場景的應(yīng)用

在 3D 場景下的 W 分量和 2D 場景是一樣的.都是當(dāng) w 增大,坐標(biāo)被拉伸; W 縮小,則坐標(biāo)被壓縮. W 對于 3D 坐標(biāo)可以實(shí)現(xiàn)縮放變換.

通常,我們在圖形開發(fā)中,都會建議無論什么時候?qū)?D坐標(biāo)轉(zhuǎn)換為4D坐標(biāo)時,讓 w = 1; 那么為什么會給出這樣的建議了? 因?yàn)楫?dāng)縮放坐標(biāo)為1時,坐標(biāo)不會放大或者縮小.保持原有的大小;所以當(dāng)w = 1,不會影響X,Y,Z分量的值;

所以,在3D開發(fā)過程中,我們會認(rèn)為坐標(biāo)中w = 1 是正確的. 因?yàn)槿绻秩臼褂肳>1的坐標(biāo),則你的每個3D圖形都會放大,反之,W<1的坐標(biāo)中,3D物體會變小.如果渲染時,W = 0,則你的程序會崩潰,為什么? 因?yàn)橛?jì)算透視除法時,除數(shù)為0; 如果 W < 0, 則渲染的圖形會上下水平翻轉(zhuǎn).

但是在數(shù)學(xué)的角度, w = 1 不做強(qiáng)制要求. 使用齊次坐標(biāo)時,w = 1 的目的僅僅是為了用于計(jì)算計(jì)算機(jī)圖形學(xué)中的投影轉(zhuǎn)換.

所以,你可以看到蘋果文檔中,關(guān)于旋轉(zhuǎn),平移,縮放等的w = 1;


矩陣變化

數(shù)學(xué)原理

圖3

假設(shè),在屏幕3米處設(shè)置一個投影儀,投影出一個點(diǎn)(15,21)在2D圖像中,相應(yīng)的投影坐標(biāo)中的向量為(X,Y,W) = (15,21,3);

如果此時,你推動投影儀靠近屏幕,直到投影儀與屏幕之間的距離為1米;那么越靠近屏幕投影,投影的圖像越小. 投影儀靠近了3倍,因此圖像則縮小了3倍; 如果我們將x,y,w分量都除以3,則得到一個新的向量 w = 1;

圖4

圖5

此時投影出來的點(diǎn)在坐標(biāo)中的位置改變成(5,7,1);

這就是系統(tǒng)如果將坐標(biāo)從不規(guī)范的齊次坐標(biāo)轉(zhuǎn)換成一個規(guī)范齊次坐標(biāo)的方法:所有分量除以w,2D和3D場景下同樣適用.通過向量乘以W的倒數(shù),來實(shí)現(xiàn)向量的所有分量除以w.

例如,如下3D場景下的計(jì)算

圖5
  • 代碼實(shí)現(xiàn):
//齊次坐標(biāo)
vec4 vertex1(10,20,30,5);
//將坐標(biāo)規(guī)范成w = 1
vec4 vertex2 = (1.0/vertex1.w) * vertex1;

齊次坐標(biāo)在計(jì)算機(jī)圖形學(xué)的應(yīng)用

齊次坐標(biāo)實(shí)現(xiàn)3D坐標(biāo)中的轉(zhuǎn)換矩陣

三維數(shù)據(jù)可以通過三維向量與 3*3 矩陣的乘法操作,來完成縮放和旋轉(zhuǎn)的線性變換. 但是對于三維笛卡爾坐標(biāo)的平移操作是無法通過與 3*3 矩陣的乘法操作來完成. 我們還需要一個額外的向量,將(0,0,0)移動到另外一個位置,這一步叫做仿射變換(affine transformation),它不屬于線性變換. 線性變換的規(guī)則,就是它總是將(0,0,0)映射到(0,0,0).因?yàn)榧尤肓诉@個額外的運(yùn)算過程,我們將無法在利用線性變換的各種優(yōu)勢. 例如將多個變換過程合成一次變換.

所以我們找到了一個方法,就是通過線性變換來表達(dá)平移過程,就是將數(shù)據(jù)置于四維坐標(biāo)空間中,仿射變換就回歸到一種簡單的線性變換. 也就是我們可以直接使用4*4矩陣的乘法來完成模型的移動操作.

透視投影

齊次坐標(biāo)在處理矩陣變化是,第四維的W分量通常不會發(fā)生變換. 從3D轉(zhuǎn)化到4D,只需要將w = 1,并且經(jīng)過變換矩陣處理后,W 分量的值任然為1. 這意味著我們可以忽略W分量即可轉(zhuǎn)換回3D坐標(biāo). 但是需要注意的投影矩陣則會影響W 分量

齊次坐標(biāo)實(shí)現(xiàn)透視投影

在3D世界,物體距離相機(jī)越遠(yuǎn)看起來就越小,這個現(xiàn)象叫做透視. 比如下圖,在鏡頭中,如果貓距離相機(jī)足夠近,遠(yuǎn)處的大山看起來比貓小.


圖6

下面看一個透視例子,通過投影矩陣變換到齊次坐標(biāo)。


圖7

注意投影矩陣是怎樣用 Z 分量改變 W 分量的。
經(jīng)過投影矩陣透視變換后,每一個向量即經(jīng)過了“透視除法”。透視除法只是將齊次坐標(biāo)中的 W 分量轉(zhuǎn)換為1的專用名詞

繼續(xù)上面的例子,透視除法這步如下:


圖8

完成透視除法后,W分量就沒用了,我們就得到了一個完全符合3D透視投影規(guī)則的3D坐標(biāo)。

注意: 在OpenGL固定管線中通常使用gluPerspective 或 gluFrustum 方法。在 OpenGL 中,在頂點(diǎn) shader 作用了每一個頂點(diǎn)后,自動進(jìn)行透視除法。這就是頂點(diǎn) shader 中 main 方法輸出的 gl_position 變量,是4維向量,而不是3維向量。

齊次坐標(biāo)影響光照平行光

齊次坐標(biāo)中的一個屬性,是允許有一個無限遠(yuǎn)的點(diǎn)(或無限長的向量),在3D坐標(biāo)中這個是不允許的。當(dāng) W=0 時,這點(diǎn)表示無限遠(yuǎn)的一個點(diǎn)。如果你嘗試將一個 W=0 的齊次坐標(biāo)轉(zhuǎn)換為一個普通的 W=1的齊次坐標(biāo),這會導(dǎo)致4次除0操作.此時代碼會發(fā)生崩潰;

圖9

這意味著,不能將 W=0 的齊次坐標(biāo)轉(zhuǎn)換到 3D 坐標(biāo)。
那么這樣的一個屬性有什么用處了?

平行光可以認(rèn)為是一個無限遠(yuǎn)處的點(diǎn)光源。當(dāng)一個點(diǎn)光源在無限遠(yuǎn)的位置,光線就會變成平行的,并且所有光線都在同一方向,這就是平行光的基本定義。例如太陽光.

所以在傳統(tǒng)的3D圖形中,平行光可以通過改變點(diǎn)光源位置向量中的 W 分量來表示,當(dāng) W= 1時,是一個點(diǎn)光源;當(dāng) W= 0 時,是一個平行光。

例如我們在實(shí)現(xiàn)光照shader ,可以需要做如下判斷

if (lightPosition.w == 0.0) {    
  //directional light code here
} else {
  //point light code here
}

總結(jié):

齊次坐標(biāo)有一個額外的維度叫 W 分量,用來縮放X, Y, Z三個分量的值。平移和透視投影的矩陣變換只能在齊次坐標(biāo)中使用,所以在3D計(jì)算機(jī)圖形學(xué)中,當(dāng) W=1時,X, Y, Z 分量被稱為“正確的”。任何齊次坐標(biāo),只要 W 不為0,都可以通過將每一個分量除以 W 來轉(zhuǎn)換到 W=1的向量。當(dāng) W=0 時,這個坐標(biāo)表示無窮遠(yuǎn)的一個點(diǎn)(或者表示無限長的一個向量),通常用于表示平行光的方向。

文章參考于

Explaining Homogeneous Coordinates & Projective Geometry

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容