【Unity Shader入門】Shader基礎概念:渲染流水線
【Unity Shader入門】Shader編程基礎:ShaderLab語法
【Unity Shader入門】Shader數學基礎:向量(矢量)
【Unity Shader入門】Shader數學基礎:矩陣
【Unity Shader入門】Shader數學基礎:矩陣變換
【Unity Shader入門】Shader編程初級:Shader結構
矢量和矩陣
一個m×n的矩陣是一個由m行n列元素排列成的矩形陣列
在三維數學中,我們通常會使用矩陣來進行變換。一個矩陣可以把一個矢量從一個座標空間轉換到另一個座標空間。
我們可以用矩陣來表示矢量。實際上,矢量可以看成是n×1的列矩陣或1×n的行矩陣,其中n對應了矢量的維度。
把矢量和矩陣聯繫在一起的原因是爲了讓矢量可以像一個矩陣一樣參與矩陣的運算。
矩陣的運算
矩陣和標量的乘法
矩陣和標量相乘,結果仍然是一個相同維度的矩陣
它們之間的乘法非常簡單,就是矩陣的每個元素和該標量相乘。
公式
kM=Mk=k⎣⎡m11m21m31m12m22m32m13m23m33⎦⎤=⎣⎡km11km21km31km12km22km32km13km23km33⎦⎤
矩陣和矩陣的乘法
一個r×n的矩陣A和一個n×c的矩陣B相乘,它們的結果AB將會是一個r×c大小的矩陣。這意味着,矩陣相乘,第一個矩陣的列數必須和第二個矩陣的行數相同。
公式
設兩個矩陣A和B相乘的結果是矩陣C,那麼,C中的每一個元素Cij等於A的第i行所對應矢量和B的第j列所對應矢量的點積
cij=ai1b1j+ai2b2j+⋯+ainbnj=k=1∑naikbkj
以一個簡單的方式解釋:對於每個元素Cij,我們找到A中的第i行和B中的第j列,然後把他們的對應元素相乘後再加起來,這個和就是Cij
性質
1、矩陣乘法不滿足交換律
2、矩陣乘法滿足結合律
ABCD=((A(BC))D)E=(AB)(CD)E
特殊矩陣
方塊矩陣
方塊矩陣,簡稱方陣,是指那些行和列數目相等的矩陣。在三維渲染裏,最常使用的就是3×3和4×4的方陣
方陣的對角元素指的是行號和列號相等的元素。
如果一個矩陣除了對角元素外的所有元素都爲0,那麼這個矩陣就叫做對角矩陣
一個4×4的對角矩陣:
⎣⎢⎢⎡30000−20000100007⎦⎥⎥⎤
單位矩陣
如果一個對角矩陣的對角元素都爲1,那麼這個矩陣被稱爲單位矩陣。一個3×3的單位矩陣如下所示:
I3=⎣⎡100010001⎦⎤
任何矩陣和單位矩陣相乘的結果都還是原來的矩陣。這就跟標量中的1一樣。
MI=IM=M
轉置矩陣
轉置矩陣實際上是通過對原矩陣進行轉置運算得到的。給定一個r×c的矩陣M,它的轉置矩陣可以表示成MT,這是一個c×r的矩陣。轉置運算就是把原矩陣翻轉一下,即原矩陣的第i行變成了第j列,而第j列變成了第i行。
如果一個矩陣的轉置矩陣是其本身,則我們稱其爲對稱矩陣
公式
MijT=Mji
對於行矩陣和列矩陣來說,我們可以使用轉置運算來相互轉換:
[xyz]T=⎣⎡xyz⎦⎤
⎣⎡xyz⎦⎤T=[xyz]
性質
矩陣轉置的轉置等於原矩陣
(MT)T=M
矩陣的串接的轉置,等於反向串接各個矩陣的轉置。這個性質可以擴展到更多矩陣相乘的情況
(AB)T=BTAT
矩陣的行列式
矩陣M的行列式用|M|表示
公式
對於2×2矩陣:
D=[a11a21a12a22]=a11a22−a12a21
對於3×3矩陣,可以展開爲2×2矩陣:
A=⎣⎡adgbehcfi⎦⎤
∣A∣=a⋅[ehfi]−b⋅[dgfi]+c⋅[dgeh]
同理,對於4×4矩陣,可以展開爲3×3矩陣:
A=⎣⎢⎢⎡aeimbfjncgkodhlp⎦⎥⎥⎤
∣A∣=a⋅⎣⎡fjngiohlp⎦⎤−b⋅⎣⎡eimgkohlp⎦⎤+c⋅⎣⎡eimfjnhlp⎦⎤−d⋅⎣⎡eimfjngko⎦⎤
可以理解爲對於矩陣第一行的每個元素,都乘以去除該元素所在行和列後剩下矩陣的行列式,然後把結果按照+ -+-的規律加/減起來。
逆矩陣
給定一個方陣M,它的逆矩陣用M-1來表示。逆矩陣最重要的性質就是把M和M-1相乘,那麼它們的結果將會是一個單位矩陣
只有方陣纔有逆矩陣,且並不是所有的方陣都有逆矩陣。
如何判斷一個矩陣是否可逆:如果一個矩陣的行列式不爲0,那麼它就是可逆的。
例如所有元素都爲0的方陣就沒有逆矩陣
如果一個矩陣有對應的逆矩陣,我們就說這個矩陣是可逆的或者說是非奇異的。否則這個矩陣就是不可逆的或者說是奇異的
公式
MM−1=M−1M=I
性質
逆矩陣的逆矩陣是原矩陣本身
(M−1)−1=M
單位矩陣的逆矩陣是它本身
I−1=I
轉置矩陣的逆矩陣是逆矩陣的轉置
(MT)−1=(M−1)T
矩陣串接相乘後的逆矩陣等於反向串接各個矩陣的逆矩陣。這個性質可以擴展到更多矩陣相乘的情況
(ABCD)−1=D−1C−1B−1A−1
逆矩陣是有幾何意義的,一個矩陣可以表示一個變換,而逆矩陣允許我們還原這個變換。假設,我們使用變換矩陣M對矢量進行了一次變換,然後再使用M的逆矩陣M-1進行另一次變換,那麼我們會得到原來的矢量。
正交矩陣
如果一個方陣M和它的轉置矩陣的乘積是單位矩陣的話,我們就稱這個矩陣是正交的
再結合逆矩陣的公式,我們可以知道,如果一個矩陣是正交的,那麼它的轉置矩陣和逆矩陣是一樣的
公式
MMT=MTM=I
MT=M−1
在三維變換中,我們經常會使用逆矩陣來求解反向的變換。但逆矩陣的求解往往計算量很大,而如果我們可以確定這個矩陣是正交矩陣的話,就可以直接通過轉置矩陣得到逆矩陣。
那麼如何判斷的一個矩陣是否是正交矩陣呢,當然可以通過公式計算判斷,但這仍然需要一定的計算量,有時候我們更希望不通過計算,而根據一個矩陣的構造過程來判斷這個矩陣是否是正交矩陣
根據正交矩陣的定義可以得到:
MTM=⎣⎡−−−c1c2c3−−−⎦⎤⎣⎡∣c1∣∣c2∣∣c3∣⎦⎤
=⎣⎡c1⋅c1c2⋅c1c3⋅c1c1⋅c2c2⋅c2c3⋅c2c1⋅c3c2⋅c3c3⋅c3⎦⎤=⎣⎡100010001⎦⎤=I
這樣,我們就有個9個等式:
c1⋅c1=1c2⋅c1=0c2⋅c1=0c1⋅c2=0c2⋅c2=1c2⋅c2=1c1⋅c3=0c2⋅c3=0c2⋅c3=0
可以得到如下結論:
1、矩陣的每一行(即c1,c2,c3)都是單位矢量,因爲它們與自己的點積爲1
2、矩陣的每一行(即c1,c2,c3)都互相垂直,因爲它們互相的點積爲0(參考點積的公式|a||b|cosθ)
3、上述的兩條結論對每一列也同樣適用。因爲M是正交矩陣的話,MT也是正交矩陣
也就說如果一個矩陣滿足上面的條件,那麼它就是一個正交矩陣。
行矩陣還是列矩陣
由於一個矢量既可以轉換成一個行矩陣也可以轉換成列矩陣,雖然它們本身是沒有區別的,但當需要把它和另一個矩陣相乘時,就會出現差異,因爲矩陣的乘法是不滿足交換律的。
假設有一個矢量v=(x,y,z),轉換成行列矩陣:
行矩陣:v=[vxvyvz]列矩陣:v=⎣⎡vxvyvz⎦⎤
現在,有另一個矩陣M:
M=⎣⎡m11m21m31m12m22m32m13m23m33⎦⎤
行矩陣和M矩陣相乘:
vM=[xm11+ym21+zm31xm12+ym22+zm32xm13+ym23+zm33]
列矩陣和M矩陣相乘:
Mv=⎣⎡xm11+ym12+zm13xm21+ym22+zm23xm31+ym32+zm33⎦⎤
對比就會發現,結果矩陣除了行列矩陣的區別外,裏面的元素也是不一樣的。這就意味着, 在和矩陣相乘時選擇行矩陣還是列矩陣來表示矢量是非常重要的,因爲這決定了矩陣乘法的書寫次序和結果值。
在Unity中,常規做法是把矢量放在矩陣的右側,即把矢量轉換成列矩陣來進行計算。此時我們的閱讀順序是從右到左的。即對矢量v先使用A進行變換,再使用B進行變換,最後使用C進行變換。
CBAv=(C(B(Av)))
vATBTCT=(((vAT)BT)CT)