Shader學習第三篇:Shader中需要數(shù)學知識
在Shader的學習中,我們可能需要一些數(shù)學知識,我也是學習了一段時間,之前數(shù)學的知識都忘了,重新來一遍吧,我把學習的點分享一下。
向量:
點乘:
向量A·向量B = A向量的模 * B向量的模 * cosθ
一般用來計算向量夾角cosθ,這里可以看下Lambert (蘭伯特)光照模型這篇文章來感受下在Shader中的向量計算
叉乘: 計算兩個向量構成平面的法向量
矩陣:
矩陣相乘必須要滿足一個規(guī)則:第一個矩陣的列數(shù)要與第二個矩陣的行數(shù)相同。
而得到的結果一定為:行數(shù)為第一個矩陣的行數(shù),列數(shù)為第二個矩陣的列數(shù)。
一個m行n列的向量A與一個n行r列的向量B相乘,得到m行r列的向量C。

例如矩陣A的維度是3×2,矩陣B的維度是2×4,那么AB的維度就是3×4。如下

另外還有一個計算技巧:
C23的值是從哪計算得來呢?可以看C23的下標,是由第一個矩陣的第2行 乘以 第二個矩陣的第3列得來

矩陣乘法的一些性質
性質一:矩陣乘法不滿足交換律。
也就是說,通常情況下:AB≠BA性質二:矩陣乘法滿足結合律。
(AB)C=A(BC)
矩陣乘法的結合律可以擴展到更多矩陣的相乘。例如,ABCD=((A(BC))D)=(AB)(CD)
向量與矩陣相乘
一個向量可以用(x,y,z)表示,現(xiàn)在我們讓向量與矩陣相乘。
行向量與矩陣相乘:

列向量與矩陣相乘

注意:在Unity中,矩陣與向量運算,通常采用列向量右乘
特殊的矩陣
1、方塊矩陣
簡稱方陣,是指那些行和列數(shù)目相等的矩陣。在三維渲染里,最常使用的就是3×3和4×4的方陣
2、單位矩陣
一個特殊的對角矩陣是單位矩陣(identity matrix),任何矩陣與它相乘還是原來的矩陣。


3、轉置矩陣
直接舉例:如下圖

4、逆矩陣
不是所有的矩陣都有逆矩陣,該矩陣必須是個方陣。
逆矩陣幾何意義:我們可以通過一個矩陣表示一個變換,如何把矩陣還原呢?可以使用逆矩陣來還原這個變換。
例如:

矩陣變換
線性變換:
滿足下面條件的可以稱之為線性變換
f(x)+f(y)=f(x+y)
kf(x)=f(kx)
在 Unity 中,旋轉、縮放為線性變換
對于線性變換來說,對一個三維的矢量進行變換,使用3×3的矩陣就可以表示所有的線性變換
非線性變換:
當然是不滿足上面條件了,平移變換屬于非線性變換
而對于非線性變換,3x3的矩陣已無法滿足,既然三維空間無法滿足,那么我用更高緯度的空間,4維空間來實現(xiàn)非線性變換。
使用4x4的矩陣來做非線性變換,我們稱之為仿射變換(affine transform)。
把原來的三維矢量轉換成四維矢量,這就是我們所說的齊次坐標(homogeneous coordinate)。
齊次坐標:

對于一個點w 補1,因為點會受到平移變換的影響
對應一個方向向量 w 補0,因為向量不會受平移的影響,不管怎么平移向量是不會變的。
平移矩陣變換。
下面我們來實現(xiàn)平移矩陣變換,來感受一下
假設現(xiàn)在有一個點為(1,2,4),把該點平移(2,1,3),最后的結果是(3,3,7),那么通過矩陣是怎么運算的呢?我們使用齊次坐標空間,由于此處是點的平移那么 w 處補0

如果現(xiàn)在改為方向向量(1,2,4),平移后方向向量是不變的,還是(1,2,4),此處w補0

縮放矩陣

旋轉矩陣
沿x軸旋轉

沿y軸旋轉

沿z軸旋轉

復合變換舉例
我們把上面的平移縮放旋轉來進行復合變換,說的再多,舉一個例子可能更直觀點。
點A(2,3,4),繞z軸旋轉30度,縮放(1,2,3),平移(6,7,8),我們用矩陣來計算下

矩陣從右往乘,先旋轉,再縮放,再平移。由于矩陣相乘滿足結合律,我們可以把前面的三個矩陣相乘后得到一個變換矩陣,再于坐標點相乘

實際應用
在這里我們可以看Unity Shader的一個例子:
在Unity中需要一系列的矩陣變換才能被看到,我們來看看Unity的空間變換。
坐標空間
模型空間:物體的原始數(shù)據(jù)存儲在模型空間下,點是相對于模型空間。
當一個模型導入到Unity中后,我們可以在頂點著色器中訪問到模型的頂點信息,其中包含了每個頂點的坐標。這些坐標都是相對于模型空間中的原點(通常位于模型的重心)定義的。
在模型空間下我們看不到物體,我們需要把物體先轉換到世界空間世界空間:游戲運行時,把物體加載到場景中,會把點轉換到世界空間下
觀察空間:攝像機空間,觀察空間的原點在攝像機處,把世界空間下的點轉換到攝像機的視角空間下。
裁剪空間:到了觀察空間,我們依然無法正常顯示物體,需要進行下一步變換到裁剪空間,把攝像機外的物體裁剪掉,只有位于攝像機內(nèi)的物體才會顯示。
屏幕空間:在完成上面的操作后,我們需要把點投影到屏幕上,而屏幕時二維空間的顯示器,把點投影到屏幕空間中,計算屏幕坐標,顯示器才能正常顯示。
Shader中相對于的矩陣
1:模型空間 2:世界空間 3:觀察空間 4:裁剪空間
UNITY_MATRIX_M:從模型空間,轉換到世界空間
UNITY_MATRIX_V:從世界空間,轉換到觀察空間
UNITY_MATRIX_P:從觀察空間,轉換到裁剪空間
UNITY_MATRIX_MV:從模型空間,到觀察空間
UNITY_MATRIX_VP:從世界空間,到裁剪空間
UNITY_MATRIX_MVP:從模型空間,轉換到裁剪空間
直接上圖,看的比較清楚

在頂點著色器中,需要對頂點進行空間變換。假如模型空間下的點A=(2,2,3),向量可以用列矩陣表示。需要把該點轉為世界空間下的點,再轉為視圖空間(我理解的是攝像機的空間),再轉為裁剪空間。
UNITY_MATRIX_M x A = 世界空間下的坐標
UNITY_MATRIX_V x 世界空間下的坐標 = 觀察空間下的坐標
UNITY_MATRIX_P x 觀察空間下的坐標 = 裁剪空間下的坐標
由于矩陣時滿足結合律的,上面的空間變換我們可以用一個矩陣來表示UNITY_MATRIX_MVP,UNITY_MATRIX_MVP x A把該點從模型空間轉為世界空間
在Unity中提供了相應的方法UnityObjectToClipPos
,來進行坐標變換
一個簡單的Shader代碼