數學對於計算機圖形學的重要性是不言而喻的。在學習Shader之前,首先就要打好數學基礎,好在入門Unity Shader所需的數學知識都是線性代數中很基礎的的內容。按部就班的來,第一篇文章記錄總結的是坐標系,點,矢量等概念以及簡單的運算。本文主要源自《Unity Shader入門精要》一書的讀書筆記。
如果有小伙伴對Shader着色器相關的概念還不了解的話,可以先看下這篇文章一篇文章搞懂到底什么是渲染流水線
坐標系
在三維笛卡爾坐標系中,我們需要定義3個坐標軸和一個原點。這3個坐標軸被稱為該坐標系的基矢量,相互垂直且長度為1的基矢量被稱為標准正交基,相互垂直但長度不為1的基矢量被稱為正交基
左手坐標系與右手坐標系
我們可以利用雙手來判斷一個坐標系的旋向性。請讀者舉起你的左手,用食指和大拇指擺出一個“L”的手勢,並且讓你的食指向上,大拇指向右。現在伸出你的中指,它將指向你的前方。此時你已經得到了一個左手坐標系。你的大拇指,食指,中指分別對應了+x,+y,+z軸。如下圖所示。
讀者可以通過右手得到一個右手坐標系。舉起你的右手,這次食指仍然向上,中指指向前方,不同的是,大拇指將指向左側。如下圖所示。
左手法則與右手法則
左手坐標系和右手坐標系對於正向旋轉的定義也不同,分別取決於左手法則和右手法則。在左手坐標系中,請舉起你的左手,握拳,伸出大拇指讓它指向旋轉軸的正方向,那么旋轉的正方向就是剩下4個手指的彎曲方向。在右手坐標系中,使用右手法則對旋轉正方向的判斷類似。
Unity使用的坐標系
對於模型空間和世界空間,Unity使用的是左手坐標系。
對於觀察空間,Unity使用的是右手坐標系。觀察空間通俗來講就是以攝像機為原點的坐標系,攝像機的前向是z軸的負方向,也就是說,z軸坐標的減少意味着場景深度的增加。
點和矢量
點是n維空間中的一個位置。
矢量是指n維空間中一種包含了模和方向的有向線段。而標量只有模沒有方向。
具體來講:
- 矢量的模指的是矢量的長度
- 矢量的方向則描述了這個矢量在空間中的指向
- 一個矢量通常由一個箭頭來表示。矢量的頭就是指它的箭頭處,尾指的是另一個端點處
通常矢量被用於表示相對於某個點的偏移,也就是說只要矢量的模和方向不變,無論放在哪里,都是同一個矢量。
點和矢量的區別
矢量可以用於表示相對於另一個點的位置,此時矢量的尾是一個位置,那么矢量的頭就可以表示另一個位置了。如果我們把矢量的尾固定在坐標系原點,那么這個矢量的表示就和點的表示重合了。盡管點和矢量在數學表達式上都是一樣的,但區分點和矢量之間的不同是非常重要的。可以這樣理解,任何一個點都可以表示成一個從原點位置出發的矢量。
矢量的運算
矢量和標量乘法/除法
我們不能把矢量和標量進行相加/相減的運算(想象一下,你會把矢量速度和標量距離相加嗎)。
對矢量和標量進行乘法運算,會得到一個不同長度且可能方向相反的新的矢量。
公式
注意:對於乘法來說,矢量和標量的位置可以互換。但對於除法來說,只能是矢量除以標量,而不能是標量除以矢量,這是沒有意義的。
幾何意義
把一個矢量和一個標量相乘,意味着對矢量進行一個大小為標量的縮放。例如,如果想把一個矢量放大兩倍,就乘以2,。當標量小於0時,矢量的方向也會相反。
矢量的加法/減法
我們可以對兩個矢量進行相加或相減,其結果是一個相同維度的新矢量
需要注意的是,一個矢量不可以和一個標量相加或相減,也不能和不同維度的矢量進行運算。
公式
幾何意義
在圖形學中矢量通常用於描述位置偏移(簡稱位移)。對於加法,我們可以把矢量a的頭連接到矢量b的尾,然后畫一條從a的尾到b的頭的矢量,來得到a和b相加的矢量。也就是說,如果我們從一個起點進行了一個位置偏移a,然后進行了一個位置偏移b,那么就等同於進行了一個a+b的位置偏移。矢量的減法也是類似的。
假設,空間內有兩點a和b。我們可以用矢量a和b來表示它們相對於原點的位移。如果我們想要計算點b相對於a的位移,就可以通過把b和a相減得到。
矢量的模
矢量的模是一個標量,可以理解為是矢量在空間中的長度。
矢量的表示符號通常是在矢量兩旁分別加上一條垂直線
公式
幾何意義
從幾何意義上來理解二維矢量,我們可以對任意矢量構建一個三角形,如下圖所示。可以看出,其實就是使用了勾股定理,矢量的兩個分量的絕對值對應了三角形兩個直角邊的長度,而斜邊的長度就是矢量的模。
單位矢量
在很多情況下,我們只關心矢量的方向而不是模。在這些情況下,我們就需要計算單位矢量。
單位矢量指的是模為1的矢量。單位矢量也被稱為歸一化的矢量。對任何給定的非零矢量,把它轉換成單位矢量的過程被稱為歸一化。
公式
為了求解單位矢量,我們可以用矢量除以該矢量的模得到。
零矢量(每個分量都是0的矢量)是不可以被歸一化的。這是因為做除法運算時分母不能為0.
幾何意義
對於二維空間來說,我們可以畫一個單位圓(半徑為1),那么單位矢量就可以是從圓心出發到圓邊界的矢量。在三維空間中,單位矢量就是從一個單位球的球心出發,到達球面的矢量。
矢量的點積
矢量之間也可以進行乘法,矢量的乘法有兩種最常用的種類:點積(內積)和叉積(外積)。矢量的點積結果是一個標量
公式
公式1,兩個三維矢量的點積是把兩個矢量分別對應分量相乘后再取和
公式2,矢量的點積等於兩個矢量的模乘以cosθ(θ表示兩個矢量的夾角)
公式2的推導,如下所示。
重點是為什么等於cosθ,如下圖所示,紅色線段就是|b|*cosθ = cosθ
幾何意義
點積的幾何意義很重要,因為點積幾乎應用到了圖形學的各個方面。其中一個幾何意義就是投影。
投影是什么意思?假如現在有一個光源,它發出的光線是垂直於單位矢量a方向的,那么矢量b在a方向上的投影就是b在a方向上的影子。
投影結果的正負號與a和b的方向有關:當它們的方向相反(夾角大於90°)時,結果小於0。當它們的方向相同(夾角小於90°)時,結果大於0。當它們互相垂直(夾角為90°)時,結果等於0。這一點利用公式2也可以看出來,結果的正負取決於cosθ。
那么如果a(前面所說的投影都要求a是單位矢量)不是一個單位矢量會如何呢,很簡單,任何兩個矢量的點積a·b等同於b在a方向上的投影,再乘以a的模。
點積的性質
-
點積滿足交換律,即 a·b = b·a
-
點積可以結合標量乘法
-
點積可結合矢量加法/減法
-
一個矢量和本身進行點積的結果,是該矢量模的平方。這意味着,如果我們需要比較兩個矢量模的大小,可以直接計算兩個矢量與自身的點積來進行比較。省去了開平方的操作。
-
點積的符號可以讓我們知道兩個矢量的方向關系
-
利用公式2,可以計算兩個矢量之間的夾角
矢量的叉積
與點積不同的是,矢量叉積的結果仍是一個矢量,而非標量。
公式
需要注意的是叉積不滿足交換律,但是滿足反交換律。即a×b = -(b×a)
幾何意義
對兩個矢量進行叉積的結果會得到一個同時垂直於這兩個矢量的新矢量
叉積最常見的一個應用就是計算得到垂直於一個平面,三角形的矢量。
新矢量的模等於a和b的模的乘積再乘以它們之間夾角的正弦值,計算公式如下:
這和平行四邊形的面積計算公式是一樣的,即底乘以高,可以認為新矢量的模是兩個矢量圍成的四邊形的面積。
新矢量的方向,就是和兩個矢量垂直的方向,但實際上我們有兩個方向可以選擇。具體如何選擇,需要依據左手坐標系或右手坐標系來判斷。
以右手坐標系為例,使用右手法則來判斷。先把手心放在a和b的尾的交點處,然后張開手掌讓手掌的方向和a的方向重合,再彎曲四指讓它們向b的方向靠攏,最后伸出大拇指,大拇指的指向就是a×b的方向。對於左手坐標系使用左手法則來判斷也是類似的。