国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑

這篇具有很好參考價(jià)值的文章主要介紹了【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括:

  • 書(shū)本中句子照抄 + 個(gè)人批注
  • 項(xiàng)目源碼
  • 一堆新手會(huì)犯的錯(cuò)誤
  • 潛在的太監(jiān)斷更,有始無(wú)終

總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。



(該系列筆記中大多數(shù)都會(huì)復(fù)習(xí)前文的知識(shí),特別是前文知識(shí)非常重要的時(shí)候,這是為了鞏固記憶,諸位可以直接通過(guò)目錄跳轉(zhuǎn))

復(fù)習(xí)

知識(shí)點(diǎn)復(fù)習(xí)

坐標(biāo)空間的轉(zhuǎn)換

上節(jié)課中,我們介紹了從頂點(diǎn)到屏幕的渲染流水線的幾何階段中發(fā)生的坐標(biāo)空間變換。從模型空間到世界空間再到齊次裁剪空間,然后轉(zhuǎn)換到NDC,再轉(zhuǎn)換到觀察空間,最后轉(zhuǎn)為屏幕空間。我們之所以使用如此之多的空間變換,是由于某些概念和描述只有在其特定空間之下才有意義。例如Unity場(chǎng)景中的坐標(biāo)描述只能相對(duì)于世界空間,而片元裁剪則是只能在齊次裁剪空間進(jìn)行等等。

一個(gè)坐標(biāo)空間中必須包含的就是其原點(diǎn)位置和坐標(biāo)系。但是不同空間的原點(diǎn)位置也是不一樣的,因此想要描述從一個(gè)空間轉(zhuǎn)換到另一個(gè)空間,常常需要以其中一個(gè)空間為坐標(biāo)參考。因此,坐標(biāo)空間之間也就存在了層級(jí)關(guān)系,我們將作為參考系的坐標(biāo)空間稱為父空間 ,以父空間 為參考的稱為子空間

因此,每個(gè)坐標(biāo)空間都可以描述為另一個(gè)坐標(biāo)空間(父空間)的子空間。對(duì)坐標(biāo)空間的變換實(shí)質(zhì)上就是在父空間和子空間之間對(duì)點(diǎn)和向量進(jìn)行變換 。由于不同空間的點(diǎn)和向量在坐標(biāo)上的描述一定是唯一對(duì)應(yīng)的,我們也將其稱之為空間映射關(guān)系。

那么空間到空間的這種變換函數(shù)關(guān)系,我們可以用上節(jié)學(xué)習(xí)的四階矩陣來(lái)進(jìn)行描述。設(shè) 父空間為 P ,子空間為 C 父空間為P,子空間為C 父空間為P,子空間為C,那么 P → C P \to C PC的映射矩陣就是 T P → C T_{P\to C} TPC?,反之 C → P C \to P CP的映射矩陣就是 T C → P T_{C \to P} TCP?

A P = T P → C A C A_P = T_{P\to C}A_C AP?=TPC?AC?
B C = T C → P B P B_C = T_{C \to P}B_P BC?=TCP?BP?

空間映射關(guān)系其實(shí)就是應(yīng)用了一次齊次變換矩陣。


頂點(diǎn)的坐標(biāo)空間變換

頂點(diǎn)著色器中,一個(gè)頂點(diǎn)究竟是如何變換到最終的屏幕空間的:它要經(jīng)歷以下幾個(gè)空間變換

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
上述空間轉(zhuǎn)換過(guò)程被我們稱為一個(gè)MVP變換,M代表model,V代表view,P代表projection投影。

頂點(diǎn)著色器最基本的任務(wù)就是將頂點(diǎn)從模型空間轉(zhuǎn)換到裁剪空間,也就是需要在頂點(diǎn)著色器中實(shí)現(xiàn)MVP變換。


模型空間

模型空間(model space) 代表了模型自身所處的坐標(biāo)空間,或者我們也可以稱其為對(duì)象空間(object space)或者局部空間(local space) ,每個(gè)模型都有屬于自己的獨(dú)立的模型空間,當(dāng)模型發(fā)生變換時(shí),其模型空間也隨之發(fā)生變換。
【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
模型中的頂點(diǎn)坐標(biāo)是四維的,需要被拓展到齊次坐標(biāo)系下。不過(guò)由于我們?cè)赨nity中描述某點(diǎn)都是以世界空間為基準(zhǔn),因此模型空間我們不大關(guān)心。

世界空間

世界空間(world space) 用于描述模型的絕對(duì)位置,即在Unity場(chǎng)景中的世界坐標(biāo)系位置,世界空間的原點(diǎn)就是游戲場(chǎng)景的中心。

在Unity中,物體有Transfrom組件的Position屬性來(lái)表示它的坐標(biāo)。這個(gè)Position表示的是物體相對(duì)于父物體(parent)為原點(diǎn)的坐標(biāo),如果一個(gè)GameObject沒(méi)有任何父節(jié)點(diǎn),則Transfrom代表了物體在世界空間中的坐標(biāo)。Transfrom的Rotation和Scale也同理。

頂點(diǎn)變換的第一步就是從模型空間變換到世界空間

對(duì)于空間的變換,我們的應(yīng)用是先縮放,在旋轉(zhuǎn),再平移,因此,模型空間到世界空間的變換矩陣為:

M m o d e l → w o r l d = M t r a n s M r o t a t e M s c a l e P w o r l d = M m o d e l → w o r l d P m o d e l M_{model \to world} = M_{trans}M_{rotate}M_{scale} \newline P_{world}=M_{model \to world} P_{model} Mmodelworld?=Mtrans?Mrotate?Mscale?Pworld?=Mmodelworld?Pmodel?

模型空間轉(zhuǎn)換到世界空間可以視為MVP轉(zhuǎn)換中由 M → V M \to V MV的準(zhǔn)備工作,因?yàn)槲覀円允澜缈臻g為父空間描述其他空間的坐標(biāo)。

觀察空間

世界空間到觀察空間代表了 M → V M \to V MV的流程,

觀察空間(view space)或者稱視圖空間是攝像頭視角下的空間坐標(biāo),也稱為攝像機(jī)空間(camera space)。

觀察空間決定了攝像機(jī)渲染游戲使用的視角。攝像機(jī)的位置代表了原點(diǎn),而我們?cè)谥爸v過(guò),觀察空間使用的是右手坐標(biāo)系,也就是屏幕到人眼的方向?yàn)檎鴺?biāo)。

現(xiàn)在我們想要將世界空間的坐標(biāo)變換到觀察空間中,這個(gè)變換稱為觀察變換(view transfrom)

想要實(shí)現(xiàn)世界空間到觀察空間的變換,只需獲得場(chǎng)景下攝像機(jī)的Tramsform信息,也就是世界空間坐標(biāo)信息,我們知道這個(gè)坐標(biāo)是觀察空間乘以變換矩陣得到的世界空間。因此找到世界空間到觀察空間的逆矩陣,就可以將模型坐標(biāo)從世界空間變換到觀察空間。
【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

以上圖為例,不難發(fā)現(xiàn)觀察空間到世界空間的逆變換就是縮放1/1倍,繞x軸旋轉(zhuǎn)-30°,最后平移(0,-10,10)。

并且注意,世界空間轉(zhuǎn)換到觀察空間,左手坐標(biāo)系變?yōu)橛沂肿鴺?biāo)系,則z軸方向翻轉(zhuǎn),所以z軸坐標(biāo)取反:
M w o r l d → v i e w = M n e g a t e ? z M v i e w → w o r l d ? 1 P v i e w = M w o r l d → v i e w P w o r l d M_{world \to view} =M_{negate\space z}M_{view \to world}^{-1} \newline P_{view}=M_{world \to view} P_{world} Mworldview?=Mnegate?z?Mviewworld?1?Pview?=Mworldview?Pworld?

裁剪空間

接下來(lái)我們要將觀察空間轉(zhuǎn)換到裁剪空間(clip space ,也被稱為齊次裁剪空間)。這個(gè)用于變換的矩陣叫做裁剪矩陣clip matrix,也叫投影矩陣(projection matrix)。

裁剪空間的目的是確定那些圖元需要被渲染,圖元如果完全在裁剪空間內(nèi)則保留;如果部分在裁剪空間內(nèi),就根據(jù)邊緣對(duì)圖元裁剪,保留空間內(nèi)的部分進(jìn)行渲染;如果圖元完全不在空間內(nèi)則被舍棄。而裁剪空間的大小則是由視錐體(view frustum) 決定。

視錐體指的是空間中的一塊區(qū)域,這塊區(qū)域決定了攝像機(jī)可以看到的空間。視錐體決定了攝像機(jī)能看到的視野范圍,視錐體是一個(gè)六面體,它的每個(gè)面被稱為裁剪平面clip planes

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

攝像機(jī)有兩者投影模式,一種是透視投影(perspective projection) ,另一種是正交投影(orthographic projection)。

透視投影模擬了正常人眼視角下的隨距離產(chǎn)生的透視效果,而正交投影則是不帶透視效果的渲染。

在視錐體的所有裁剪平面中,有兩個(gè)裁剪平面比較特殊,分別被稱為近裁剪平面(near clip plane)遠(yuǎn)裁剪平面(far clip plane) 。他們決定了攝像機(jī)可以看到的深度范圍。

由于透視投影的視錐是一個(gè)金字塔形,因此如果通過(guò)點(diǎn)在空間上的位置判斷是否在視錐內(nèi)從而實(shí)現(xiàn)裁剪是相當(dāng)麻煩的。因此,我們想用一種更通用的方式來(lái)進(jìn)行裁剪,這種方式就是通過(guò)一個(gè)投影矩陣把頂點(diǎn)轉(zhuǎn)換到一個(gè)裁剪空間中。

投影矩陣的目的有兩個(gè):

  • 為投影做準(zhǔn)備,雖然投影矩陣名稱中包含了投影,但沒(méi)有真正進(jìn)行投影的工作,真正的投影發(fā)生在齊次除法過(guò)程中
  • 其次是對(duì)xyz分量進(jìn)行縮放,通過(guò)投影矩陣可以將w分量作為一個(gè)范圍值,若xyz分量都位于這個(gè)范圍中則說(shuō)明該頂點(diǎn)位于裁剪空間內(nèi)。

在之前講齊次坐標(biāo)的時(shí)候,我們使用了w分量,不過(guò)通常w分量是固定值,點(diǎn)的w分量為1,而方向向量的w分量為0,經(jīng)過(guò)投影矩陣變換后w分量可以被我們用于判斷頂點(diǎn)是否在裁剪空間內(nèi)。


投影矩陣

想要將頂點(diǎn)從觀察空間轉(zhuǎn)換到裁剪空間,則需要乘以投影矩陣,最后用齊次除法除以裁剪分量。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

投影矩陣的原理其實(shí)很簡(jiǎn)單, 本質(zhì)上來(lái)講就是將視錐轉(zhuǎn)換為NDC,就是計(jì)算出從正交立方體到NDC的這個(gè)矩陣(透視視錐的原理也相同,需要先將透視視錐的frustum映射為正交立方體再使用上述步驟)

則有:
M p e r s p = M o r t h o M p e r s p → o r t h o 正交投影: P c l i p = M o r t h o P v i e w 透視投影: P c l i p = M p e r s p P v i e w M_{persp} = M_{ortho} M_{persp \to ortho}\newline 正交投影: P_{clip}=M_{ortho} P_{view}\newline 透視投影:P_{clip}=M_{persp} P_{view} Mpersp?=Mortho?Mpersportho?正交投影:Pclip?=Mortho?Pview?透視投影:Pclip?=Mpersp?Pview?

這只是將頂點(diǎn)從觀察空間變換到四維的齊次裁剪空間,在齊次裁剪空間中進(jìn)行裁剪工作:
如果一個(gè)頂點(diǎn)在視錐內(nèi),那么滿足:

? w < = x < = w ? w < = y < = w ? w < = z < = w -w<=x<=w \newline -w<=y<=w \newline -w<=z<=w ?w<=x<=w?w<=y<=w?w<=z<=w
不滿足以上條件的頂點(diǎn)將被舍棄以完成對(duì)片元的裁剪工作。

屏幕空間

我們現(xiàn)在知道了那些頂點(diǎn)保留,那些舍棄。這樣我們就可以投影到屏幕空間了。

屏幕空間是二維空間,在此之前我們還需要將頂點(diǎn)從四維的齊次裁剪空間投射到三維的NDC空間再投射到屏幕空間。

于是從齊次裁剪空間到屏幕空間過(guò)程分為兩步:

  • 進(jìn)行標(biāo)準(zhǔn)齊次除法(homogeneous division),也稱為透視除法(perspective division)。這一步很簡(jiǎn)單,其實(shí)就是對(duì)齊次坐標(biāo)系的xyzw分量分別除以w分量,使得w分量變?yōu)?即可將其投射回三維空間,這個(gè)新得到的坐標(biāo)空間被我們稱為歸一化的設(shè)備坐標(biāo)NDC。
  • 現(xiàn)在從齊次裁剪空間轉(zhuǎn)換到了NDC,我們會(huì)得到分量在[-1,1]的單位正方體。然后我們?cè)阡秩竟芫€的幾何化階段使用這個(gè)NDC的坐標(biāo)來(lái)計(jì)算屏幕空間上的坐標(biāo)即可,只需簡(jiǎn)單縮放就可以完成。

從齊次裁剪空間投射到NDC空間(這一步代表了MVP變換中從觀察視圖轉(zhuǎn)換到投影視圖的過(guò)程) :

( x ′ , y ′ , z ′ ) = ( x w , y w , z w ) (x',y',z')=(\frac{x}{w},\frac{y}{w},\frac{z}{w}) (x,y,z)=(wx?,wy?,wz?)

NDC再做視口映射到屏幕坐標(biāo):
s c r e e n x = x ′ ? p i x e l W i d t h 2 + p i x e l W i d t h 2 s c r e e n y = y ′ ? p i x e l H e i g h t 2 + p i x e l H e i g h t 2 screen_x=\frac{x'·pixelWidth}{2}+\frac{pixelWidth}{2}\newline screen_y=\frac{y'·pixelHeight}{2}+\frac{pixelHeight}{2} screenx?=2x?pixelWidth?+2pixelWidth?screeny?=2y?pixelHeight?+2pixelHeight?

由于Unity中,從裁剪空間到屏幕空間的轉(zhuǎn)換是底層完成的,因此我們的頂點(diǎn)著色器只需要將頂點(diǎn)轉(zhuǎn)換到齊次裁剪空間即可。


法線變換

法線變換是一種特殊的變換。**法線(normal)**也被稱為法向量,猶原記得初中物理中學(xué)習(xí)光的反射中的關(guān)于法線的概念。法線是一種需要特殊處理的向量,在游戲中,模型的一個(gè)頂點(diǎn)往往會(huì)攜帶許多額外的信息,而頂點(diǎn)法線就是其中一種。當(dāng)我們變換一個(gè)模型的時(shí)候,不僅需要變換它的頂點(diǎn),還需要變換頂點(diǎn)法線,以便于在后續(xù)處理中(例如片元著色器)計(jì)算光照信息。

之前我們將向量變換的時(shí)候,總能用一個(gè)3x3或者4x4的矩陣實(shí)現(xiàn)從坐標(biāo)空間A到坐標(biāo)空間B的變換,然而在對(duì)法線進(jìn)行變換的時(shí)候,如果使用同一個(gè)變換矩陣,可能就無(wú)法保持法線的垂直性。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
在初中學(xué)習(xí)光的反射的時(shí)候,會(huì)用到這樣的圖片。垂直于反射平面的那條線就是法線,然而在模型中,法線是每一個(gè)頂點(diǎn)都擁有的屬性。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

關(guān)于切線空間計(jì)算的文章

在模型中,我們的切線空間一般而言是根據(jù)模型的UV方向來(lái)決定的,UV方向確定xy軸,一般U方向代表切線T,V方向代表副切線B,法線N就是正交的z軸方向(沿著面片的正面為正方向)。

當(dāng)然,由于法線是頂點(diǎn)的信息之一,法線是可以自定義方向的,這也會(huì)導(dǎo)致切線方向隨之改變。

由于切線與UV坐標(biāo)相關(guān),因此我們對(duì)其可以直接應(yīng)用3階線性變換 M A → B M_{A\to B} MAB?,將切線從原坐標(biāo)空間A變換到新坐標(biāo)空間B:

T B = M A → B T A T_B=M_{A\to B}T_A TB?=MAB?TA?

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
其實(shí)我認(rèn)為,由于法線方向可以自定義,嚴(yán)格來(lái)說(shuō)不垂直于平面的法線不算錯(cuò)誤結(jié)果,或許就是有這種需求呢?法線只需要滿足垂直于切線平面即可。

法線與切線垂直關(guān)系可以表示為內(nèi)積為0,即: T A ? N A = 0 T_A·N_A=0 TA??NA?=0,給定變換矩陣 M A ? B M_{A-B} MA?B?,已知 T B = M A ? B T A T_B=M_{A-B}T_A TB?=MA?B?TA??,F(xiàn)在想要一個(gè)變換矩陣 G G G來(lái)變換法線 N A N_A NA?,使得變換后的法線依然保持與切線垂直,即內(nèi)積為0:

T B ? N B = ( M A ? B T A ) ? ( G N A ) = 0 ( M A ? B T A ) ? ( G N A ) = ( M A ? B T A ) T ( G N A ) = T A T ( M A → B T G ) N A = 0 T_B·N_B =(M_{A-B}T_{A})·(GN_A)=0\newline (M_{A-B}T_{A})·(GN_A)=(M_{A-B}T_{A})^T(GN_A)=T^T_A(M^T_{A\to B}G)N_A=0 TB??NB?=(MA?B?TA?)?(GNA?)=0(MA?B?TA?)?(GNA?)=(MA?B?TA?)T(GNA?)=TAT?(MABT?G)NA?=0

由于 T A ? N A = 0 T_A·N_A=0 TA??NA?=0,因此如果 M A → B T G = E M^T_{A\to B}G=E MABT?G=E上式成立

所以 G = ( M A → B T ) ? 1 = ( M A → B ? 1 ) T G=(M^T_{A\to B})^{-1}=(M^{-1}_{A\to B})^T G=(MABT?)?1=(MAB?1?)T

因此只需求出 M A → B M_{A\to B} MAB?的逆矩陣的轉(zhuǎn)置即可對(duì)法線進(jìn)行正確的線性變換。且若 M A → B M_{A\to B} MAB?為正交矩陣,則逆矩陣的轉(zhuǎn)置就是它本身。

如果基礎(chǔ)變換的縮放系數(shù)是統(tǒng)一的,那么可以直接除以統(tǒng)一縮放系數(shù)k, ( M A → B T ) ? 1 = 1 k M A → B (M^{T}_{A\to B})^{-1}=\frac{1}{k}M_{A\to B} (MABT?)?1=k1?MAB?

(吐槽一下,書(shū)中 ( M A → B T ) ? 1 (M^{T}_{A\to B})^{-1} (MABT?)?1非得叫做 M A → B M_{A\to B} MAB?的逆轉(zhuǎn)置矩陣嗎?不覺(jué)得直接叫轉(zhuǎn)置矩陣的逆矩陣好一點(diǎn)嗎?逆轉(zhuǎn)置矩陣不就搞不清楚是轉(zhuǎn)置矩陣的逆矩陣還是逆矩陣的轉(zhuǎn)置矩陣了嗎?)


Unity Shader的內(nèi)置變量(數(shù)學(xué)篇)

變換矩陣變量

Unity中給出了所有內(nèi)置的可用于坐標(biāo)空間變換的矩陣:

(變量名取得好,編程沒(méi)煩惱)
變量名 描述
UNITY_MATRIX_MVP 當(dāng)前模型視圖投影矩陣,通常用于把頂點(diǎn)/方向矢量從模型空間轉(zhuǎn)換到裁剪空間(從名字可以看出是MVP復(fù)合矩陣變換)
UNITY_MATRIX_MV 當(dāng)前模型視圖矩陣,通常用于把頂點(diǎn)/方向矢量從模型空間轉(zhuǎn)換到視角(觀察)空間
UNITY_MATRIX_V 當(dāng)前視圖矩陣,通常用于把頂點(diǎn)/方向矢量從世界空間轉(zhuǎn)換到視角(觀察)空間
UNITY_MATRIX_P 當(dāng)前的投影矩陣,通常用于把頂點(diǎn)/方向矢量從視角(觀察)空間轉(zhuǎn)換到裁剪空間
UNITY_MATRIX_VP 當(dāng)前視圖投影矩陣,通常用于把頂點(diǎn)/方向矢量從世界空間轉(zhuǎn)換到裁剪空間
UNITY_MATRIX_T_MV UNITY_MATRIX_MV矩陣的轉(zhuǎn)置
UNITY_MATRIX_IT_MV 模型視圖矩陣UNITY_MATRIX_MV的轉(zhuǎn)置矩陣的逆矩陣,通常用于把法線從模型空間轉(zhuǎn)換到視角(觀察)空間 ,也可用于得到UNITY_MATRIX_MV的逆矩陣
unity_ObjectToWorld 當(dāng)前模型轉(zhuǎn)空間矩陣,通常用于把頂點(diǎn)/方向向量從模型空間轉(zhuǎn)換到世界空間
unity_WorldToObject 當(dāng)前世界轉(zhuǎn)模型矩陣,通常用于把頂點(diǎn)/方向向量從世界空間轉(zhuǎn)換到模型空間

矩陣變換變量中給出了轉(zhuǎn)置矩陣和逆矩陣的變量,由此可見(jiàn)正交矩陣的性質(zhì)對(duì)于我們的計(jì)算是非常重要的。而一般而言,我們?cè)谶@里求解的方陣 M M M M M M指四階的齊次變換矩陣的左上的三階矩陣,也就是只包含旋轉(zhuǎn)和縮放的部分),如果只包含旋轉(zhuǎn)和統(tǒng)一縮放(不平移),那么大概率就是正交的,為了滿足正交條件,還需要除以統(tǒng)一縮放倍率k,即 M = 1 k M ′ M = \frac{1}{k}M' M=k1?M,其中 M ′ M' M是正交矩陣。

上表也沒(méi)有給出 ( M V ) ? 1 (MV)^{-1} (MV)?1,實(shí)際上只需要對(duì)UNITY_MATRIX_IT_MV變量求轉(zhuǎn)置矩陣即可求出該逆矩陣了。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

攝像機(jī)和屏幕參數(shù)

變量名 類型 描述
_WorldSpaceCameraPos float3 相機(jī)在世界空間的位置
_ProjectionParams float4 x = 1.0(如果當(dāng)前使用翻轉(zhuǎn)投影矩陣渲染則為-1.0),y是相機(jī)的近平面y=Near,z是相機(jī)的遠(yuǎn)平面,z=Far,w是1.0 / Far +1.0(參考NDC映射公式)
_ScreenParams float4 x=width,y=height,z=1.0/width+1.0,w=1.0+1.0/height,其中width和height分別是該攝像機(jī)的渲染目標(biāo)(render target)的像素寬高(參考視口映射公式)
_ZBufferParams float4 用于線性化Z緩沖區(qū)的值。x = (1 - Far /Near),y = (Far/Near)、z = (x /Far)和w = (y /Far)
unity_OrthoParams float4 x是正交相機(jī)的寬度width,y是正交的相機(jī)的高度height,z是未使用的,為正交的相機(jī)時(shí)w為1.0,透視相機(jī)時(shí)w為0.0
unity_CameraProjection float4x4 該攝像機(jī)的投影矩陣
unity_CameraInvProjection float4x4 該攝像機(jī)投影矩陣的逆矩陣
unity_CameraWorldClipPlanes[6] float4 該攝像機(jī)的6個(gè)裁剪平面在世界空間下的等式,按如下順序:左、右、下、上、近、遠(yuǎn)裁剪平面

答疑

使用3x3還是4x4的變換矩陣

對(duì)于線性變換來(lái)說(shuō),3x3的矩陣就可以表示旋轉(zhuǎn)和縮放關(guān)系了,之所以要使用4x4的矩陣,是為了表示包含了平移的仿射變換,放在是在四維齊次坐標(biāo)空間則是線性變換,而只需將w分量設(shè)為1就不會(huì)對(duì)向量在三維的映射有影響。當(dāng)然,不設(shè)為1也可以通過(guò)齊次除法映射回三維。

Cg中的矢量和矩陣類型

UnityShader中使用Cg作為著色器編程語(yǔ)言,Cg中變量類型有很多,本書(shū)只介紹如何進(jìn)行數(shù)學(xué)運(yùn)算

float

float類型包括常見(jiàn)的float3,float4,float3x3,float4x4 ,從命名不難看出,前二者代表了向量(也可以用于表示1xn的行矩陣和nx1的列矩陣,這取決于運(yùn)算的種類和在運(yùn)算中的位置),后二者代表矩陣,而數(shù)字代表了維度。

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記
m u l ( M , v ) = = m u l ( v , t r a n p o s e ( M ) ) mul(M,v)==mul(v,tranpose(M)) mul(M,v)==mul(v,tranpose(M))實(shí)際上就是公式 M V = V T M T MV=V^TM^T MV=VTMT(之所以沒(méi)對(duì)V進(jìn)行轉(zhuǎn)置是因?yàn)閒loat4類型既可以當(dāng)作行矩陣,也可以當(dāng)作列矩陣)

通常情況下,我們對(duì)于向量float3和float4都是直接右乘的。

需要注意Cg對(duì)矩陣類型的元素的初始化和訪問(wèn)順序。在Cg中,對(duì)float4x4等類型的變量是按照行優(yōu)先的方式進(jìn)行填充的。如果我們直接使用 ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) (1,2,3,4,5,6,7,8,9) (1,2,3,4,5,6,7,8,9)去填充一個(gè)3x3的矩陣,那么則會(huì)按照次序逐行進(jìn)行填充,得到:

[ 1 2 3 4 5 6 7 8 9 ] \begin{bmatrix}1&2&3 \\ 4&5&6 \\ 7&8&9 \end{bmatrix} ?147?258?369? ?

同樣的,當(dāng)訪問(wèn)Cg中矩陣元素時(shí),也是按行來(lái)進(jìn)行索引的。
【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

在Unity的API中提供了一種矩陣類型Matrix4x4,這種矩陣是按列填充的

Unity中的屏幕坐標(biāo):ComputeScreenPos/VPOS/WPOS

在編寫(xiě)Shader的時(shí)候,我們有時(shí)候希望能夠獲得片元在屏幕上的像素位置。
在頂點(diǎn)/片元著色器中,有兩種方式來(lái)獲得片元的屏幕坐標(biāo):

  • 一種是對(duì)片元著色器的輸入聲明VPOS或者WPOS語(yǔ)義。VPOS是HLSL中對(duì)屏幕坐標(biāo)的語(yǔ)義,而WPOS是Cg中對(duì)屏幕坐標(biāo)的語(yǔ)義(那我還是推薦VPOS吧,比較Cg已經(jīng)g了),二者在Unity Shader中是等價(jià)的。我們可以在HLSL/Cg中通過(guò)語(yǔ)義的方式來(lái)定義頂點(diǎn)/片元著色器的默認(rèn)輸入,而不需要自己定義輸入輸出的數(shù)據(jù)結(jié)構(gòu)。

我們可以這樣寫(xiě):
【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

VPOS/WPOS的語(yǔ)義定義的輸入是一個(gè)float4類型的變量。我們知道這個(gè)聲明為VPOS的變量sp回?fù)碛衳y值,代表了屏幕空間的像素坐標(biāo)。例如屏幕分辨率為400*300,則x的范圍為[0.5,400.5],y為[0.5,300.5] ,之所以像素坐標(biāo)不是整數(shù),是因?yàn)閳D形API們認(rèn)為起點(diǎn)像素的中心值是0.5,0是邊緣值。

那么,它的z分量0和w分量1代表了什么?z=0代表了在攝像機(jī)的近裁剪平面Near處,反之z=1代表了在遠(yuǎn)裁剪平面Far處。

如果使用的是正交投影,那么w恒為1,若使用透視投影則w分量的范圍是 [ 1 N e a r , 1 F a r ] ( 根據(jù)投影矩陣變換再除以變換矩陣的 w 分量后得到 ) [\frac{1}{Near},\frac{1}{Far}](根據(jù)投影矩陣變換再除以變換矩陣的w分量后得到) [Near1?,Far1?](根據(jù)投影矩陣變換再除以變換矩陣的w分量后得到)

我們最后要把屏幕空間除以屏幕分辨率來(lái)得到視口空間(viewport space) 的坐標(biāo),視口坐標(biāo)很簡(jiǎn)單,只需要把屏幕坐標(biāo)歸一化即可,這樣屏幕左下角是(0,0),右上角是(1,1)

如果已知屏幕坐標(biāo),只需把xy值除以屏幕分辨率即可。

  • 另一種方法就是使用Unity提供的ComputeScreenPos 函數(shù)。該函數(shù)再UnityCG.cginc中被定義(有這么好的東西不早說(shuō)),通常用法是:首先再頂點(diǎn)著色器中將ComputeScreenPos的結(jié)果保存在輸出結(jié)構(gòu)體中,然后再片元著色器中進(jìn)行一個(gè)齊次除法運(yùn)算后得到視口空間下的坐標(biāo),例如:
    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

上面說(shuō)的兩種方法效果一樣,觀察上述代碼,不難發(fā)現(xiàn)其實(shí)就是先對(duì)頂點(diǎn)應(yīng)用了MVP變換得到齊次裁剪坐標(biāo),然后應(yīng)用ComputeScreenPos方法得到屏幕坐標(biāo),最后將屏幕坐標(biāo)進(jìn)行齊次除法得到視口空間坐標(biāo)。(ComputeScreenPos的方法名聽(tīng)起來(lái)是直接獲取屏幕坐標(biāo),但不是這樣,我們依舊需要進(jìn)行齊次除法)

【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑,UnityShader入門(mén)精要筆記,學(xué)習(xí),筆記

上圖就是我們這段代碼的結(jié)果,將歸一化的坐標(biāo)值映射為RGB值,x對(duì)應(yīng)R,y對(duì)應(yīng)G

Unity之所以依舊需要我們對(duì)ComputeScreenPos進(jìn)行齊次除法,而不是自己完成,是由于ComputeScreenPos是在頂點(diǎn)著色器中使用的,如果在頂點(diǎn)著色器中直接使用齊次除法會(huì)影響頂點(diǎn)信息的插值,插值結(jié)果就會(huì)不準(zhǔn)確,原因在于插值必須是線性的,而只要在齊次空間下插值才是線性的,若在投影空間中則是非線性的。

雖然我們視口坐標(biāo)是二維的,只包含了xy,但是上述代碼中,頂點(diǎn)著色器的輸出結(jié)果是自定義的vertOut結(jié)構(gòu)體,存儲(chǔ)了四維向量。因此依舊保留了z和w值。

使用該方法,同樣的,x,y的范圍在 [ 0 , 1 ] [0,1] [0,1]。

如果使用的是正交投影,z值范圍為 [ ? 1 , 1 ] [-1,1] [?1,1] ,那么w恒為1;
若使用透視投影則z值范圍為 [ ? N e a r , F a r ] [-Near,Far] [?Near,Far] , w分量的范圍是 [ 1 N e a r , 1 F a r ] ( 根據(jù)投影矩陣變換再除以變換矩陣的 w 分量后得到 ) [\frac{1}{Near},\frac{1}{Far}](根據(jù)投影矩陣變換再除以變換矩陣的w分量后得到) [Near1?,Far1?](根據(jù)投影矩陣變換再除以變換矩陣的w分量后得到)
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-792870.html

到了這里,關(guān)于【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第四章(6)法線變換、內(nèi)置變量以及本章答疑

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 (該系列筆記中大多數(shù)都會(huì)復(fù)習(xí)前文的知識(shí),特別是前文知識(shí)非

    2024年01月16日
    瀏覽(22)
  • 西瓜書(shū)學(xué)習(xí)筆記---第四章 決策樹(shù)

    西瓜書(shū)學(xué)習(xí)筆記---第四章 決策樹(shù)

    目錄 一、題目要求 二、數(shù)據(jù)集介紹 ?三、決策樹(shù)模型 3.1 決策樹(shù)模型介紹 3.2?決策樹(shù)算法原理 3.2.1 決策樹(shù)的建立 3.2.2 決策樹(shù)的劃分(1)—信息增益ID3 3.2.3 決策樹(shù)的劃分(2)—Gini指數(shù)CART 3.2.4 預(yù)剪枝pre-pruning 3.2.5 后剪枝post-pruning 3.3?決策樹(shù)算法核心代碼解釋 四、運(yùn)行結(jié)果

    2024年02月04日
    瀏覽(26)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(3)章節(jié)答疑

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(3)章節(jié)答疑

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 (PS:章節(jié)答疑不是我答,是原作者對(duì)一些比較容易產(chǎn)生困惑的地

    2024年02月03日
    瀏覽(29)
  • JAVA學(xué)習(xí)筆記——第四章 運(yùn)算符

    JAVA學(xué)習(xí)筆記——第四章 運(yùn)算符

    ?? 博客主頁(yè) :?A_SHOWY ?? 系列專欄 :力扣刷題總結(jié)錄?數(shù)據(jù)結(jié)構(gòu)??云計(jì)算??數(shù)字圖像處理??力扣每日一題_?運(yùn)算符是一種特殊的符號(hào),用于表示數(shù)據(jù)的運(yùn)算、賦值和比較 取模 %的本質(zhì): a - (int)a / b * b//當(dāng)a是小數(shù)時(shí) 自增 獨(dú)立語(yǔ)句使用時(shí),++i和i++沒(méi)有區(qū)別的。但是如果作

    2024年01月20日
    瀏覽(31)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第十章 高級(jí)紋理(2)渲染紋理

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第十章 高級(jí)紋理(2)渲染紋理

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 我的GitHub倉(cāng)庫(kù) 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 攝像機(jī)的渲染結(jié)果會(huì)輸出到顏色緩沖中,并顯示到

    2024年04月25日
    瀏覽(46)
  • Rx.NET in Action 第四章學(xué)習(xí)筆記

    Rx.NET in Action 第四章學(xué)習(xí)筆記

    《Rx.NET in Action》這一部共分八章,涵蓋了Rx 關(guān)鍵模塊——**Observable(可觀察序列) 和 Observer(觀察者)**的全部功能,以及如何創(chuàng)建它們、連接它們和控制它們之間的關(guān)系。 然后,您將學(xué)習(xí)如何使用強(qiáng)大的 Rx 處理器構(gòu)建復(fù)雜的 Rx 管道。您將學(xué)習(xí)使用處理器查詢 單個(gè) Observable(可觀

    2024年02月12日
    瀏覽(23)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第六章(1)Unity中的基礎(chǔ)光照

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第六章(1)Unity中的基礎(chǔ)光照

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 一個(gè)物體為什么看起來(lái)是紅色的?從物理上解釋是因?yàn)檫@個(gè)物體

    2024年03月22日
    瀏覽(34)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第三章(1)Unity Shader介紹

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第三章(1)Unity Shader介紹

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 從本章節(jié)開(kāi)始我們要學(xué)習(xí)Shader相關(guān)的知識(shí)了,諸位看客可能有的

    2024年02月02日
    瀏覽(25)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(1)了解渲染流水線

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(1)了解渲染流水線

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 什么是流水線?書(shū)中舉了一個(gè)生產(chǎn)洋娃娃的例子。一個(gè)洋娃娃的

    2024年01月25日
    瀏覽(20)
  • 【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(2)GPU流水線

    【UnityShader入門(mén)精要學(xué)習(xí)筆記】第二章(2)GPU流水線

    本系列為作者學(xué)習(xí)UnityShader入門(mén)精要而作的筆記,內(nèi)容將包括: 書(shū)本中句子照抄 + 個(gè)人批注 項(xiàng)目源碼 一堆新手會(huì)犯的錯(cuò)誤 潛在的太監(jiān)斷更,有始無(wú)終 總之適用于同樣開(kāi)始學(xué)習(xí)Shader的同學(xué)們進(jìn)行有取舍的參考。 在上節(jié)筆記中,我們學(xué)習(xí)了圖像渲染流水線的基本過(guò)程,從應(yīng)用

    2024年02月22日
    瀏覽(25)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包