【Unity Shader入門精要學(xué)習(xí)】數(shù)學(xué)基礎(chǔ)(四)

頂點(diǎn)的坐標(biāo)空間變換過程(都是以Unity中的坐標(biāo)空間為準(zhǔn))

1、模型空間(model space)

模型空間有時(shí)也被稱為對象空間(object space),或局部空間(local space),是模型本身自己的坐標(biāo)空間,這個(gè)是在美術(shù)人員建模的時(shí)候決定好的,如模型的中心點(diǎn)

2、世界空間(world space)(左手坐標(biāo)系)

世界空間被用于描述絕對位置。
頂點(diǎn)變換的第一步就是將頂點(diǎn)從模型空間變換到世界空間,這一步變換通常叫做模型變換(model transform),一般是經(jīng)過縮放,旋轉(zhuǎn),平移這幾步,將模型轉(zhuǎn)換到世界坐標(biāo)系下。(TRS)

3、觀察空間(view space)(右手坐標(biāo)系)

觀察空間也被稱為攝像機(jī)空間(camera space)。攝像機(jī)決定了游戲渲染使用的視角。在觀察空間中,攝像機(jī)位于原點(diǎn),+Z軸指向的是攝像機(jī)的后方。
頂點(diǎn)的第二步變換就是將頂點(diǎn)從世界空間變換到觀察空間,這一步變換通常叫做觀察變換(view transform)
因?yàn)?strong>世界空間(world space)和觀察空間(view space)是兩個(gè)不同的坐標(biāo)系,所以就涉及到坐標(biāo)系的轉(zhuǎn)換。有兩種方法,一是利用之前我們說過的坐標(biāo)系轉(zhuǎn)換,求出世界空間到觀察空間的矩陣(先求得觀察空間到世界空間的矩陣,然后求其逆矩陣,因?yàn)槲覀兊弥獢z像機(jī)在世界坐標(biāo)空間下的原點(diǎn)位置以及坐標(biāo)軸的表示)。第二種方法就是通過平移整個(gè)觀察空間,我們可以現(xiàn)將攝像機(jī)看作是一個(gè)在世界空間下的一個(gè)物體,通常需要經(jīng)過縮放,旋轉(zhuǎn),平移將物體轉(zhuǎn)換到世界空間下,那么我們就通過逆向操作,即平移,旋轉(zhuǎn),縮放,求得矩陣。
例如:
坐世界空間下,攝像機(jī)的pos(0,10,-10),rotate(30,0,0),那么我們就可以通過pos(0,-10,10),rotate(-30,0,0)來求得矩陣。因?yàn)槭悄嫦虿僮?,所以是先平移,然后旋轉(zhuǎn),因?yàn)樵谟^察空間下使用了右手坐標(biāo)系,所以最后求得的矩陣中還要將Z值取反。

空間變換

Z軸取反

最后求得的矩陣就可以用來將世界空間下的點(diǎn)轉(zhuǎn)換到觀察空間下。

4、裁剪空間(clip space)

裁剪空間也被稱為齊次裁剪空間,這個(gè)用于轉(zhuǎn)換的矩陣叫做裁剪矩陣(clip matrix),也被稱為投影矩陣(projection matrix)
裁剪空間存在的目的就是就快速的對要渲染的圖元進(jìn)行裁剪:完全位于裁剪空間內(nèi)的會被保留,完全在裁剪空間外的會被裁剪掉,與裁剪空間重疊的會被裁剪掉。
如何決定這個(gè)裁剪空間視椎體(view frustum)
視椎體由六個(gè)裁剪平面(clip plane)包圍而成,視椎體有兩種類型:透視投影(perspective projection),正交投影(orthographic projection)。
在視椎體中,有兩個(gè)面比較特殊:近裁剪平面(near clip plane),遠(yuǎn)裁剪平面(far clip plane),這兩個(gè)面決定了攝像機(jī)能看見到的深度范圍。

視椎體

因?yàn)橹苯邮褂靡曌刁w定義的空間不是很方便進(jìn)行裁剪,所以就需要把頂點(diǎn)轉(zhuǎn)換到裁剪空間,即使用投影矩陣
什么是投影:就是一個(gè)降維的操作,如將三維空間轉(zhuǎn)換到二維空間坐標(biāo)下。
投影矩陣的作用:
(1)首先是為投影做準(zhǔn)備,雖然叫做投影矩陣,但實(shí)際是沒有進(jìn)行投影操作的,真正的投影操作是經(jīng)過齊次除法(homogeneous division)。而經(jīng)過投影矩陣變換之后,頂點(diǎn)的w分量具有特殊意義。
(2)其次是對x,y,z分量進(jìn)行縮放,因?yàn)橹苯邮褂靡曌刁w的六個(gè)平面進(jìn)行裁剪比較麻煩,所以經(jīng)過投影的縮放之后,就可以直接使用w分量作為一個(gè)范圍值,只要x,y,z都在這個(gè)范圍內(nèi),就說明這個(gè)點(diǎn)位于裁剪空間內(nèi)。
所以w分量經(jīng)過投影矩陣之后會有更豐富的含義。
透視投影:
(1)透視投影的6個(gè)裁剪平面由近、遠(yuǎn)裁剪平面,F(xiàn)OV(field of view),視口縱橫比(aspect)決定,即視口寬高比。在Unity中縱橫比由Game視圖的縱橫比和Viewport Rect中的W,H共同決定。
image.png

近、遠(yuǎn)裁剪平面高度

(2)然后根據(jù)Near,Far,FOV,Aspect可以確定投影矩陣
投影矩陣

注:此為Unity下的坐標(biāo)系,觀察坐標(biāo)為右手坐標(biāo)系,使用列矩陣在矩陣右側(cè)相乘,變換之后的W分量范圍在[-W,W]之間。
(3)一個(gè)頂點(diǎn)和投影矩陣相乘之后,就可以有觀察空間變換到裁剪空間
頂點(diǎn)變換

從相乘的結(jié)果來看,其實(shí)就是對X,Y,Z分量分別進(jìn)行了縮放,Z分量還進(jìn)行了位移??s放的目的是為了方便裁剪,此時(shí)W分量不在是1,而是Z分量取反之后的結(jié)果。
現(xiàn)在就可以對頂點(diǎn)就行裁剪了:
不等式

只要相乘之后的結(jié)果滿足上述不等式,則說明此頂點(diǎn)不會被裁剪。
image.png

也可以發(fā)現(xiàn),裁剪矩陣改變了空間的旋向性,空間的Z坐標(biāo)方向反過來了,變換成了左手坐標(biāo)系,z值越大離攝像機(jī)越遠(yuǎn)。
正交投影
(1)使用正交投影變換之后的頂點(diǎn),W分量仍然是1,因?yàn)檎煌队熬仃嚭屯敢曂队熬仃嚨淖詈笠恍胁灰粯?br>
正交投影

正交投影變換

所以頂點(diǎn)變換的第三步就是從觀察空間變換到裁剪空間
第四步進(jìn)行裁剪

4、屏幕空間(screen space)

在裁剪空間進(jìn)行完所有裁剪之后,就是要進(jìn)行真正的投影操作了,即把視椎體投影到屏幕空間中。經(jīng)過真正的投影變換,得到的結(jié)果就是屏幕中真正的像素位置。
屏幕空間是一個(gè)二維空間,為了把頂點(diǎn)從裁剪空間投影到屏幕空間(生成對應(yīng)的2D坐標(biāo)),我們需要經(jīng)過兩個(gè)步驟:
(1)齊次除法(homogeneous division),也叫透視除法(perspective division),即用齊次坐標(biāo)系下的x,y,z分量除以w分量,這一步得到的坐標(biāo)叫做歸一化的設(shè)備坐標(biāo)(Normalized Device Coordinates,NDC)(OpenGL)。經(jīng)過齊次除法(透視除法),裁剪空間被轉(zhuǎn)換到NDC中,就是一個(gè)立方體內(nèi)。在OpenGL中,這個(gè)立方體的x,y,z分量范圍都是[-1,1]。

透視投影----齊次除法

對于正交投影,它的裁剪空間其實(shí)已經(jīng)是一個(gè)立方體了,而且w分量為1,所以齊次除法對于正交投影并不會產(chǎn)生影響。
正交投影---齊次除法

(2)屏幕映射,經(jīng)過齊次除法之后,透視投影視椎體和正交投影視椎體都變換到了一個(gè)相同的立方體內(nèi),然后就可以根據(jù)x,y值進(jìn)行屏幕映射。
在Unity中,左下角為原點(diǎn)(0,0),右上角為最大點(diǎn)(pixelW,pixelH),而變換之后的NDC下的坐標(biāo)都是在[-1,1]之間,所以要對坐標(biāo)系進(jìn)行縮放和平移,總結(jié)就是:
齊次除法+屏幕映射

(這個(gè)變換式子其實(shí)不是很好理解,我們可以提取公因式,而為什么要除以2,因?yàn)樽鴺?biāo)的范圍是[-1,1],1-(-1)=2),其實(shí)就是先變換到(0,2)之間也就是X+1,然后再乘像素寬高,因?yàn)樽儞Q到了(0,2)相當(dāng)于多加了一個(gè)寬高,所以要除以2!
而Z值一般用于深度緩沖。
在Unity中,從裁剪空間屏幕空間的轉(zhuǎn)換是由Unity完成的,我們的頂點(diǎn)著色器只需要把頂點(diǎn)轉(zhuǎn)換到裁剪空間即可

5、總體流程

總體流程

6、法線變換

法線(normal)又被稱為法矢量(normal vector),是一種需要特殊處理的方向矢量,法線用于在片元著色器中計(jì)算光照。大部分方向矢量都可以使用同一個(gè)變換矩陣從A空間變換到B空間中,但是法線可能就會在變換中產(chǎn)生錯(cuò)誤,導(dǎo)致不垂直與原來的面,如進(jìn)行了不等比例的縮放:

縮放

為了保持垂直性,我們需要通過切線(tangent),也被稱為切矢量(tangent vector),推導(dǎo)出正確的轉(zhuǎn)換法線的矩陣。切線也是模型攜帶的一種信息,通常與紋理空間對其,并且與法線方向垂直。切線由兩個(gè)點(diǎn)的插值計(jì)算得到,所以可以直接使用變換矩陣對切線變換。由于是矢量,所以平移并不會改變矢量的方向,所以只要使用3X3的矩陣就可以描述清楚矩陣的變換,根據(jù)矢量垂直性可推導(dǎo)如下公式:
image.png

其中M矩陣是正常的變換矩陣,G是變換法線N的矩陣
image.png

兩向量垂直說明兩向量點(diǎn)乘為0,我們可以把兩向量看作為一個(gè)1X3的矩陣和3X1的矩陣,得出的是一個(gè)1X1的矩陣,和實(shí)際點(diǎn)乘結(jié)果一樣,所以T的轉(zhuǎn)置乘N等于0,為了讓這個(gè)等式成立,則M的轉(zhuǎn)置乘G必須為單位矢量I才可以,所以:
image.png

image.png

從而得出對法線正確的變換矩陣。
如果變換矩陣M是正交矩陣,我們只需要使用原矩陣就能變換法線(只包含旋轉(zhuǎn)):
image.png

如果只包含旋轉(zhuǎn)和統(tǒng)一的縮放系數(shù):
image.png
、如果包含非統(tǒng)一的縮放系數(shù)則需要求解逆矩陣才可以。

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

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