《Unity Shader入門精要》筆記 #第四章 學習Shader所需的數學基礎
不懂數學者不得入內
1、笛卡爾座標系
旋向性
旋轉正方向
Unity採用的座標系
模型空間及世界空間 - 左手座標系
觀察空間 - 右手座標系
2、點和向量
點積 - 投影
叉積 - 計算垂直於一個平面、三角形的向量;判斷三角面片朝向
3、矩陣
4、矩陣變換
線性變換:縮放、旋轉、錯切、映象、正交投影,3*3
仿射變換:合併線性變換和平移變換,4*4矩陣,擴充套件到四維空間下即齊次座標空間
,M(3*3)用於旋轉縮放,t(3*1)用於表示平移,0(1*3)是零矩陣
-平移矩陣
對點:
向量平移:
平移矩陣的逆矩陣:
-縮放矩陣
沿座標軸方向進行縮放
對點:
對向量:
若k(x) = k(y) = k(z),則為統一縮放
-旋轉矩陣
繞軸旋轉
-複合變換
-先縮放,再旋轉,最後平移,由於是列矩陣,從右向左讀起
-旋轉順序,在Unity中,旋轉順序是zxy
Unity中的旋轉順序按照一種順序,所以不用從右向左讀起
5、座標空間
5.1 數學鋪墊:
問題一般化。定義座標空間需要明確原點和3個座標軸方向。這些數值相對於另一個座標空間,每個座標空間都是另一個座標空間的子空間,每個空間都有一個父座標空間。座標空間的變換是父空間和子空間之間對點和向量進行變換。
兩種需求,
對點:
的步驟:
-從座標空間的原點開始
-向x軸方向移動a個單位
-向y軸方向移動b個單位
-向z軸方向移動c個單位
-從座標空間的原點開始
已知子座標空間的原點位置
-向x軸方向移動a個單位
已知x軸矢量表示,則
-向y軸方向移動b個單位
已知y軸矢量表示,則
-向z軸方向移動c個單位
已知z軸矢量表示,則
則
擴充套件到齊次座標空間,得到
反向思維,可以從這個式子獲取子座標空間的原點和座標軸方向。eg,已知從模型空間到世界空間的4*4變換矩陣,可以提取第一列進行歸一化後得到模型空間的x軸在世界空間下的單位矢量表示。
對向量:
,對法線、光照方向進行變換
求不需要求逆矩陣的情況:本身是正交矩陣
驗證按行或是按列擺放:帶入計算
5.2 在渲染流水線中的一個頂點經過的座標空間變換
-模型空間
Unity的模型空間+x,+y,+z對應右、上、前,擴充到齊次座標系下
-世界空間
將頂點座標從模型空間變換到世界空間中,叫做模型變換
對點的模型變換矩陣:
-觀察空間
+x右方,+y上方,+z後方
將頂點座標從世界空間變換到觀察空間中,叫做觀察變換
兩種方法:計算觀察空間的3個座標軸在世界空間下的表達,再求逆;平移整個觀察空間,讓攝像機原點位於世界座標原點,座標軸與世界空間座標軸重合即可。
對點的觀察變換矩陣:但由於是右手系,需要對z分量取反
最後
-裁剪空間
用於變換的裁剪矩陣/投影矩陣。視錐體有兩種型別:正交投影和透視投影,6塊裁剪平面
投影矩陣的兩個目的:為投影做準備;對x/y/z分量進行縮放。
在裁剪空間前雖然使用齊次座標表示點和向量,點第四個分量w為1,向量第四分量為0.經過投影矩陣變換後有新含義。
透視投影
六塊裁剪平面,通過FOV和clipping plane中的near和far引數控制攝像機遠近。
近裁剪平面和遠裁剪平面高度:
假設當前攝像機的橫縱比為Aspect,則
根據已知Near、Far、FOV、Aspect值確定透視投影的投影矩陣如下(觀察空間右手座標系建立),變換後z分量範圍將在[-w,w]之間:
在頂點和上述矩陣相乘:
若變換後一個頂點位於是椎體內,則座標必須滿足,且裁剪矩陣改變空間旋向性,空間從右手座標系變換到了左手座標系,離攝像機越遠,z值越大。
正交投影
六個裁剪平面,是由Camera組建中的引數和Game檢視的橫縱比共同決定。
正交投影的視錐體是一個長方體,因此計算上相比透視投影更簡單。
攝像機橫縱比Aspect:
根據已知的Near、Far、Size和Aspect確定正交投影的裁剪矩陣:
則一個頂點和上述投影矩陣相乘的結果:
正交投影的投影矩陣對頂點進行變換後,其w分量仍為1,由於投影矩陣最後一行不同。判斷變換後頂點是否在視錐體內的不等式和透視投影一樣。裁剪矩陣改變了空間的旋向性。
-螢幕空間
齊次/透視除法,用齊次座標系的w分量除以x/y/z分量,得到的座標叫做歸一化的裝置座標。將座標從齊次裁剪座標空間轉換到NDC中,經透視投影變換後的裁剪空間經過齊次除法會變換到立方體內,.
而對於正交投影而言由於w=1,齊次除法不會對頂點產生影響。
根據變換後的x、y對映輸出視窗對應畫素座標。螢幕空間左下角畫素(0,0),右上角畫素座標(pixelWidth, pixelHeight),當前
則,
z分量用於深度緩衝。
從裁剪空間到螢幕空間轉換由Unity完成,頂點著色器只需要把頂點由模型空間轉換到裁剪空間即可。
切線空間用於法線對映
6、法線變換
頂點攜帶發現資訊,有時候不僅要變換頂點,還要變換頂點法線,以便在後續處理(如片元著色器)中計算光照。
法線變更的原因:切線是由兩個頂點間插值計算得到,可以直接使用用於變換頂點的3*3變換矩陣變換切線因為切線和法線均為向量,變換矩陣變換頂點
切線變更,在進行非統一縮放時,法線與平面不一定垂直。
由於法線和切線滿足垂直條件,,需要找到矩陣變換法線,使得其仍然垂直,即:
即,即
而若變換矩陣是正交矩陣,,則。如果變換隻包含旋轉變換,則變換矩陣為正交矩陣;若變換隻包含旋轉和統一縮放(不包含非統一縮放),則利用統一縮放係數k得到的逆轉置矩陣
7、Unity Shader的內建變數
7.1 變換矩陣
均為4*4大小
變數名 | 描述 |
UNITY_MATRIX_MVP | 模型*觀察*投影矩陣,將頂點/方向向量從模型空間變換到裁剪空間 |
UNITY_MATRIX_MV | 模型*觀察矩陣,將頂點/方向向量從模型空間變換到觀察空間 |
UNITY_MATRIX_V | 觀察矩陣,將頂點/方向向量從世界空間變換到觀察空間 |
UNITY_MATRIX_P | 投影矩陣,將頂點/方向向量從觀察空間變換到裁剪空間 |
UNITY_MATRIX_VP |
觀察*投影矩陣,將頂點/方向向量從世界空間變換到裁剪空間 |
UNITY_MATRIX_T_MV | UNITY_MATRIX_MV的轉置矩陣,若為*正交矩陣,則可以將頂點/方向向量從觀察空間變換到模型空間 |
UNITY_MATRIX_IT_MV | UNITY_MATRIX_MV的逆轉置矩陣,將法線從模型空間變換到觀察空間,也可用於得到UNITY_MATRIX_MV的逆矩陣 |
_Object2World | 模型矩陣,將頂點/方向向量從模型空間變換到世界空間 |
_World2Object | _Object2World的逆矩陣,將頂點/方向向量從模型空間變換到世界空間 |
PS:
1)提取座標空間的座標軸(轉換矩陣的前三列)
2)*幾乎為正交矩陣條件:旋轉和統一比例縮放(排除除旋轉、縮放、平移的其餘變換);若只考慮向量,就不用考慮有無平移變換,提取UNITY_MATRIC_T_MV的前三行三列將觀察空間變換到模型空間;同時可以對方向向量進行歸一化處理消除統一縮放的影響。
3)得到UNITY_MATRIX_MV的逆矩陣可以利用UNITY_MATRIX_IT_MV再求轉置
觀察空間到模型空間程式碼如下,本質一樣,利用公式檢視是等價
//方法一:對UNITY_MATRIX_IT_MV進行轉置,得到逆矩陣後進行列矩陣乘法
float4 modelPos = mul(transpose(UNITY_MATRIX_IT_MV), viewPose);
//方法二:交換mul引數的位置使用行矩陣乘法
float4 modelPos = mul(viewPose, UNITY_MATRIX_IT_MV);
7.2 攝像機和螢幕引數
變數名 | 型別 | 描述 |
_WorldSpaceCameraPos | float3 | 該攝像機在世界空間中的位置 |
_ProjectionParams | float4 | x=1.0(或-1.0,如果正在使用一個翻轉的投影矩陣進行渲染),y=Near, z=Far, w=1.0+1.0/Far,Near和Far分別為近裁剪平面和遠裁剪平面和攝像機的距離 |
_ScreenParams | float4 | x=width, y=height, z=1.0+1.0/width, w=1.0+1.0/height,其中width和height分別是該攝像機的渲染目標的畫素寬度和高度 |
_ZBufferParams | float4 | x=1-Far/Near, y=Far/Near, z=x/Far, w=y/Far,該變數用於線性化Z快取中的深度值 |
unity_OrthoParams | float | x=width, y=height, z無定義, w=1.0(攝像機是正交攝像機)或w=0.0(攝像機是透視攝像機),width和height是正交投影攝像機的寬度和高度 |
unity_CameraProjection | float4*4 | 該攝像機的投影矩陣 |
unity_CameraInvProjection | float4*4 | 該攝像機的投影矩陣的逆矩陣 |
unity_CameraWorldClipPlanes[6] | float4 | 該攝像機的6個裁剪平面在世界空間下的等式,左、右、下、上、近、遠裁剪平面 |
8、答疑
8.1 3*3 or 4*4
8.2 CG中向量和矩陣型別
8.3 Unity中的螢幕座標:ComputeScreenPos/VPOS/WPOS
VPOS-HLSL,WPOS-CG
VPOS/WPOS語義定義的輸入是一個float4型別的變數。若螢幕解析度400*300,則,Unity中VPOS/WPOS的z分量範圍是[0,1],攝像機近裁剪平面處z=0,元裁剪平面處z=1。對於透視投影,,正交投影w=1。