3D數學基礎
寫在前面
此文並非是學術類文章,只是對於3D數學基礎做出的整理和思考,其中有大量的內容並沒有很非常正確和完整的解釋出來,但仍舊不妨礙學習後對於shader的編寫有很好的幫助,也請讀者在評論區留言指認文中的錯誤,學習愉快。
------------------------------------------------------------------------------
1.笛卡爾
常用的DCC工具和Unity的坐標有一些相同或者不同,用三維坐標系的圖解來表示之前先看看同樣的物體運動的軸向變化
經過試驗變化,可以發現軸向的變化類似一種縮放,例如這樣:
左圖是在Unity中的坐標系,右圖是在DCC工具中的坐標系
可以通過運動的物體進一步發現,其實兩個坐標系的轉換類似一種X軸的縮放,亦或者是一種負向量的轉換。
這種空間的轉換是Unity對FBX文件的一種強制轉換,在後面的內容,可能會越來越清晰的認識這一點。
------------------------------------------------------------------------------
2.學習之前
在UnityShader兩篇中已經有了很多對於公式、函數、矩陣的應用。
比如f.pos = mul(UNITY_MATRIX_MVP, v.vertex ); 我們知道這是通過了Cg的語義和Unity內置的一種矩陣轉換,來使得頂點從模型空間轉換到裁剪空間之中
再比如dot(halfDir, worldNormal) 是另一種計算反射和法向量的返回值
mul(v.normal , _World2Object) 和 mul(_World2Object , v.normal)得出的歸一值為什麼兩種結果
上述的問題以及很多很多的問題,我稱作為應用層面的問題,都可以在3D數學中找到答案
所有問題可以在我寫出筆記前總結兩點:
a.空間
b.轉換
隨之拋出的問題就是,空間是指什麼,有很多空間嗎, 轉換的意義,轉換的是什麼,
還有哪些計算在其中,我們能否將機器語言用幾何意義和想像力在美術層面設計它
---------------------------------------------
3.在光照模型中,需要計算的向量有法線、光源的方向,對於這些方向向量為了能夠更好的去理解它的幾何意義,需要一個新的、有模長的向量——單位向量:模長為1的向量
在Unity中,我們可以使用Vector3.normalized來獲得單位向量
using System.Collections;using System.Collections.Generic;using UnityEngine;public class VectorLength : MonoBehaviour { void Start () { Vector3 v = new Vector3(2, -5, 9); float length = v.magnitude; Debug.Log("向量v的模是:" + length); Vector3 v2 = v.normalized; float length2 = v2.magnitude; Debug.Log("向量v2的模是:" + length2); }}
4.那向量在Shader編寫中有什麼具體的影響呢?
4_1.先看看向量的點積(dot product)
第一個公式:a·b=(ax,ay,az)·(bx,by,bz)=axbx+ayby+azbz
上面的公式是兩個向量的內積,但是如果a=b,那麼a·a=axax+ayay+azaz (1)
再看看向量模長的公式:|v| = √vx2+vy2+vz2 |v|2 = vx2+vy2+vz2 (2)
假設a b向量後根據(1)(2)可以得出::任何兩個向量的點積a·b等於b在a方向上的投影值,再乘以a的長度。
第二個公式:a·b=|a||b|cos∠O
先看下三角函數
我們使用點積和叉積鎖涉及的幾何意義就是這2個公式而已
也有說為什麼不直接用餘弦定理:
先了解最簡單的一般反射時或者涉及到一個向量的投影問題,我們都會以一個平面為基礎,舉例蘭伯特光照模型的話,我們對於最直觀的反射是基於平面的反射。法線向量和更複雜的光照計算會在以後學習總結出來。
還有一種利用cos∠45的方法驗證,我就不寫出來了。
4_2.叉積:兩個向量的叉積等於一個新的向量,公式:|aXb|=|a||b|sin∠O
但是注意的地方是叉積僅僅支持3D向量,不能用於二維空間中。
4_3.對於Unity和shader中應用
前面說過dot返回值的意義,我們根據dot的返回值能夠
a.獲取目標的位置信息
b.判斷前後關係
c.判斷角度大小
d.計算灰度
e.計算向量長度
上述應用會在後面有時間再去一一實踐出來
5.矩陣
5_1.一個矩陣M裡面包含了mXn個標量,並且由行、列來搭配組成的網格狀數組。
比如2X3 2行3列矩陣
Mij 表示了這個標量在矩陣M的 第i行 第j列
矩陣最重要的作用便是把將向量在不同的空間裡面進行坐標轉換
5_2.矩陣和矩陣的加減
只有維度相同的矩陣才可以相加相減,即是他們相同位置的元素相加減
5_3.矩陣之間的乘法
矩陣rXn 只能和 nXc 相乘 得到 rXc
這裡注意是i行乘以j列。
5_4.轉置矩陣
簡單的說就是MijT=Mji 可以看成是一個對角線的翻折
5_5.逆矩陣
一個矩陣和它的逆矩陣相乘,結果是一個單位矩陣I(一種滿足了對角矩陣條件的情況下,m11 m22 m33值相同的矩陣)
如果說一個矩陣有它的逆矩陣就說這個矩陣是可逆的。
AA-1 =I AA-1 = A-1A =I (-1是逆矩陣符號)
而判斷一個矩陣是否可逆需要用二階或者三階的行列式來計算。
例如
如果行列式結果不為0,那就是可逆的
6.矩陣的變換
6_1.什麼是變換?
把一些數據,如點、方向向量、顏色通過某種方式進行轉換的過程。
大多數是以矩陣相乘的形式表現出來
6_2.在說變換之前需要先了解一下基向量和基矩陣的概念
如圖,如果把三個坐標軸上的向量作為i j k的正交單位向量
我們把i=a j=b k=c 並且稱這些為基向量 這個坐標就是基
a(1,0,0)
b(0,1,0)
c(0,0,1)
這樣我們可以把一個點的位置這樣表示:v = vxa + vyb + vzc
但是如果是一個向量,我們則需要減去原點:P-O = pxa+pyb+pzc P = pxa + pyb + pzc +O
用矩陣來表示的話:
然後,我們引入齊次坐標變換
6_3
點得齊次坐標(x,y,z,1)
向量的齊次坐標(x,y,z,0)
點和點得減法得到的是一個向量(也可以理解成重點減去起點) 而向量之間的加減得到的還是一個向量
為什麼點得第四個代數分量是1 而向量的是0?是因為在三維坐標系中,平移對於向量是沒有意義的,只會對點有影響。
Reference
[1] 馮樂樂UnityShader入門精要
[2] 3D數學基礎
[3] http://www.cnblogs.com/csyisong/archive/2008/12/09/1351372.html
[4] 點積叉積的幾何意義 https://blog.csdn.net/hc14519/article/details/50716299
推薦閱讀: