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] cnblogs.com/csyisong/ar

[4] 點積叉積的幾何意義 blog.csdn.net/hc14519/a


推薦閱讀:

語料庫語言學基礎知識:矩陣(Haskell版)

TAG:unity | 向量 | 矩陣 |