【Unity Shader 笔记】一些数学基础

使用书籍《Unity Shader 入门精要》,冯乐乐著。

1. 笛卡尔坐标系

部分术语如下

  • 基矢量(basis vector),三维坐标系的三个轴
  • 标准正交基(orthonormal basis),三维坐标系的三个相互垂直,且长度为 1,这样的基矢量被称为标准正交基
  • 正交基(orthogonal basis),在一些坐标系中坐标轴之间相互垂直但长度不为 1

2. 点和矢量

  • 单位矢量与归一化
    使矢量的模为 1。零矢量是不能被归一化的
  • 矢量的点积(dot product)
    公式一:
    a ⋅ b = ( a x , a y , a z ) ⋅ ( b x , b y , b z ) = a x b x + a y b y + a z b z \bf a⋅b=\it (a_x,a_y,a_z )⋅(b_x,b_y,b_z )=a_x b_x+a_y b_y+a_z b_z ab=(ax,ay,az)(bx,by,bz)=axbx+ayby+azbz
    公式二:
    a ⋅ b = ∣ a ∣ ∣ b ∣ c o s ⁡ θ \bf a⋅b=|a||b|\it cos⁡θ ab=abcosθ
  • 矢量的叉积(cross product)
    公式一:
    a × b = ( a x , a y , a z ) × ( b x , b y , b z ) = ( a y b z − a z b y ,   a z b x − a x b z ,   a x b y − a y b x ) \bf a×b=\it (a_x,a_y,a_z )×(b_x,b_y,b_z )=(a_y b_z−a_z b_y,~a_z b_x−a_x b_z,~a_x b_y−a_y b_x) a×b=(ax,ay,az)×(bx,by,bz)=(aybzazby, azbxaxbz, axbyaybx)
    公式二:
    ∣ a × b ∣ = ∣ a ∣ ∣ b ∣ s i n ⁡ θ \bf |a×b|=|a||b|\it sin⁡θ a×b=absinθ
    关于叉积的方向:使用右手,手掌的四指指向方向 a,然后向方向 b 弯曲。此时大拇指指向叉积方向。

3. 矩阵

M = [ m 11 m 12 m 13 m 21 m 22 m 23 m 31 m 32 m 33 ] \bf M=\begin{bmatrix} {m_{11}}&{m_{12}}&{m_{13}}\\ {m_{21}}&{m_{22}}&{m_{23}}\\ {m_{31}}&{m_{32}}&{m_{33}}\\ \end{bmatrix} M=m11m21m31m12m22m32m13m23m33

  • 方块矩阵(square matrix)
    行列元素数量相同的矩阵
  • 对角矩阵(diagonal matrix)
    除了对角线上的元素,其余所有元素都是 0 的矩阵
  • 单位矩阵(identity matrix)
    一种对角矩阵,对角线上的元素都为 1.用 I n \rm I_n In 表示
  • 转置矩阵(transposed matrix)
    对原矩阵 M \rm M M 进行转置(就是翻转,行列互换),得到 M T \rm M^{\it T} MT
  • 逆矩阵(inverse matrix)
    原矩阵 M \rm M M 的转置用 M − 1 \rm M^{\it -1} M1 表示。逆矩阵满足 M M − 1 = M − 1 M = I \rm MM^{\it -1}=\rm M^{\it -1}M=I MM1=M1M=I

    如果一个矩阵有对应的逆矩阵,就说这个矩阵是 可逆的(invertible)非奇异的(nonsingular),否则说是 不可逆的(noninvertible)奇异的(singular)

  • 正交矩阵(orthogonal matrix)
    如果一个矩阵 M \rm M M 和它的转置 M − 1 \rm M^{\it -1} M1 的乘积是单位矩阵 I \rm I I 的话( M M − 1 = I \rm MM^{\it -1}=I MM1=I),就说这个矩阵是正交的。
    即, M T = M − 1 \rm M^{\it T}=\rm M^{\it -1} MT=M1

3.1. 矩阵运算

  • 矩阵与矩阵的乘法
    A 和 B 分别为两个矩阵。若乘式 AB 成立,AB 表达的含义是:A 的第 i 所有元素,与 B 的第 j 的所有元素,分别相乘,并相加,构成 AB 结果矩阵的第 i 行第 j 列的元素。

  • unity 中的矩阵运算惯例
    使用列矩阵,从右往左运算
    C B A v \rm CBAv CBAv,相当于 ( C ( C ( A v ) ) ) \rm (C(C(Av))) (C(C(Av)))
    又如 v A T B T C T \rm vA^{\it T}B^{\it T}C^{\it T} vATBTCT,相当于 ( ( ( v A T ) B T ) C T ) \rm (((vA^{\it T})B^{\it T})C^{\it T}) (((vAT)BT)CT)

3.2. 齐次坐标

使用 N+1 个数来表示 N 维坐标。

一个三维坐标,其 w w w 分量设为 1;一个三维矢量,其 w w w 分量设为 0。

3.3. 矩阵变换

使用 4×4 的矩阵来表示平移、旋转和缩放。 一个基础变换矩阵可以分成 4 个部分:

[ M 3 × 3 t 3 × 1 0 1 × 3 1 ] \begin{bmatrix} {\bf M_{\rm 3×3}}&{\bf t_{\rm 3×1}}\\ {\bf 0_{\rm 1×3}}&{1}\\ \end{bmatrix} [M3×301×3t3×11]

其中, M 3 × 3 \bf M_{\rm 3×3} M3×3 表示缩放和旋转, t 3 × 1 \bf t_{\rm 3×1} t3×1 表示平移, 0 1 × 3 \bf 0_{\rm 1×3} 01×3 表示零矩阵, 1 1 1 就是标量 1。

3.3.1. 平移矩阵

平移一个位置:

[ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] [ x y z 1 ] = [ x + t x y + t y z + t z 1 ] \begin{bmatrix} {1}&{0}&{0}&{t_x}\\ {0}&{1}&{0}&{t_y}\\ {0}&{0}&{1}&{t_z}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} \begin{bmatrix} x\\y\\z\\1 \end{bmatrix}= \begin{bmatrix} x+t_x\\y+t_y\\z+t_z\\1 \end{bmatrix} 100001000010txtytz1xyz1=x+txy+tyz+tz1

平移一个矢量,不会对矢量产生任何影响:

[ 1 0 0 t x 0 1 0 t y 0 0 1 t z 0 0 0 1 ] [ x y z 0 ] = [ x y z 0 ] \begin{bmatrix} {1}&{0}&{0}&{t_x}\\ {0}&{1}&{0}&{t_y}\\ {0}&{0}&{1}&{t_z}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} \begin{bmatrix} x\\y\\z\\0 \end{bmatrix}= \begin{bmatrix} x\\y\\z\\0 \end{bmatrix} 100001000010txtytz1xyz0=xyz0

  • 平移矩阵的逆矩阵就是反向平移的矩阵
  • 平移矩阵不是正交矩阵
3.3.2. 缩放矩阵

缩放一个位置:

[ k x 0 0 0 0 k y 0 0 0 0 k z 0 0 0 0 1 ] [ x y z 1 ] = [ k x x k y y k z z 1 ] \begin{bmatrix} {k_x}&{0}&{0}&{0}\\ {0}&{k_y}&{0}&{0}\\ {0}&{0}&{k_z}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} \begin{bmatrix} x\\y\\z\\1 \end{bmatrix}= \begin{bmatrix} k_xx\\k_yy\\k_zz\\1 \end{bmatrix} kx0000ky0000kz00001xyz1=kxxkyykzz1

缩放一个矢量:

[ k x 0 0 0 0 k y 0 0 0 0 k z 0 0 0 0 1 ] [ x y z 0 ] = [ k x x k y y k z z 0 ] \begin{bmatrix} {k_x}&{0}&{0}&{0}\\ {0}&{k_y}&{0}&{0}\\ {0}&{0}&{k_z}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} \begin{bmatrix} x\\y\\z\\0 \end{bmatrix}= \begin{bmatrix} k_xx\\k_yy\\k_zz\\0 \end{bmatrix} kx0000ky0000kz00001xyz0=kxxkyykzz0

  • k x = k y = k z k_x=k_y=k_z kx=ky=kz,这样的缩放称为统一缩放(uniform sccale),否则称为非统一缩放(nonuniform scale)
  • 缩放矩阵的逆矩阵意为缩放到原系数的倒数
  • 这样只能沿着坐标轴方向进行缩放。若希望在任意方向上进行缩放,需要使用复合变换
3.3.3. 旋转矩阵

令点绕着 x x x 轴旋转 θ θ θ 度:

R x ( θ ) = [ 1 0 0 0 0 c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 ] \bf R_{\it x}(θ)=\begin{bmatrix} {1}&{0}&{0}&{0}\\ {0}&{\rm cos\it θ}&{\rm -sin\it θ}&{0}\\ {0}&{\rm sin\it θ}&{\rm cos\it θ}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} Rx(θ)=10000cosθsinθ00sinθcosθ00001

令点绕着 y y y 轴旋转 θ θ θ 度:

R y ( θ ) = [ c o s θ 0 s i n θ 0 0 1 0 0 − s i n θ 0 c o s θ 0 0 0 0 1 ] \bf R_{\it y}(θ)=\begin{bmatrix} {\rm cos\it θ}&{0}&{\rm sin\it θ}&{0}\\ {0}&{1}&{0}&{0}\\ {\rm -sin\it θ}&{0}&{\rm cos\it θ}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} Ry(θ)=cosθ0sinθ00100sinθ0cosθ00001

令点绕着 z z z 轴旋转 θ θ θ 度:

R z ( θ ) = [ c o s θ − s i n θ 0 0 s i n θ c o s θ 0 0 0 0 1 0 0 0 0 1 ] \bf R_{\it z}(θ)=\begin{bmatrix} {\rm cos\it θ}&{\rm -sin\it θ}&{0}&{0}\\ {\rm sin\it θ}&{\rm cos\it θ}&{0}&{0}\\ {0}&{0}&{1}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} Rz(θ)=cosθsinθ00sinθcosθ0000100001

  • 旋转矩阵的逆矩阵意为旋转相反角度
  • 旋转矩阵是正交矩阵,并且多个旋转矩阵串联也是正交的
3.3.4. 复合变换

可以把平移、旋转和缩放进行组合。式子如下,注意列矩阵的从右到左顺序。

p n e w = M t r a n s l a t i o n M r o t a t i o n M s c a l e p o l d \bf p_{\it new}=\bf M_{\it translation}M_{\it rotation}M_{\it scale}p_{\it old} pnew=MtranslationMrotationMscalepold

  • 约定的变换顺序是 “缩放、旋转、平移”。
  • 对于旋转的变换顺序,unity 中顺序是 “z轴、x轴、y轴”——在此时请在矩阵乘法中按 “yxz” 的顺序进行,因为旋转会同时转动轴

4. 坐标变换

使用矩阵进行坐标变换。

进行变换的矩阵被称为过渡矩阵。因为坐标是用一维列向量表示的,因此过度矩阵应左乘上去,得到转换结果。

若想从坐标空间 C 转换为坐标空间 P,需要先用坐标空间 P 表示坐标空间 C 下的 x、y、z 轴,用三个三维列向量 x c \bf x_{\it c} xc y c \bf y_{\it c} yc z c \bf z_{\it c} zc 表示,以及原点的相对位置 O c \bf O_{\it c} Oc
对于一个坐标空间 C 下的坐标 A c = [ a b c ] T \bf A_{\it c}=\begin{bmatrix}a&b&c\end{bmatrix}^{\it T} Ac=[abc]T,在坐标空间 P 下的坐标为:
A p = O c + a x c + b y c + c z c \bf A_{\it p}=O_{\it c}+\it a\bf x_{\it c}+\it b\bf y_{\it c}+\it c\bf z_{\it c} Ap=Oc+axc+byc+czc
然后使用矩阵进行表示——

转换一个位置:
A p = [ x c y c z c O c ] [ a b c 1 ] T \bf A_{\it p}= \begin{bmatrix}\bf x_{\it c}&\bf y_{\it c}&\bf z_{\it c}&\bf O_{\it c}\end{bmatrix} \begin{bmatrix}a&b&c&1\end{bmatrix}^{\it T} Ap=[xcyczcOc][abc1]T

转换一个矢量:
A p = [ x c y c z c ] [ a b c ] T \bf A_{\it p}= \begin{bmatrix}\bf x_{\it c}&\bf y_{\it c}&\bf z_{\it c}\end{bmatrix} \begin{bmatrix}a&b&c\end{bmatrix}^{\it T} Ap=[xcyczc][abc]T

4.1. 观察空间(view space)

也称为摄像机空间(camera space)。它不是最终的屏幕空间,而是一个三维空间。

这里有个坐标变换的特殊地方。

与其他空间不同,摄像机的观察空间的正前方指向的是 -z 轴方向,是反过来的。若需要对过度矩阵进行 z 轴取反,可以左乘以下这个矩阵:

[ 1 0 0 0 0 1 0 0 0 0 − 1 0 0 0 0 1 ] \begin{bmatrix} {1}&{0}&{0}&{0}\\ {0}&{1}&{0}&{0}\\ {0}&{0}&{-1}&{0}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} 1000010000100001

4.2. 裁剪空间(clip space)

使用裁剪矩阵(clip matrix),将顶点从观察空间转换到裁剪空间(也称为齐次裁剪空间)。

使用视锥体(view frustum) 决定裁剪空间。视锥体由六个裁剪平面(clip planes) 包围而成。视锥体有两种类型:正交投影透视投影
处于这块空间内部的图元会被保留,完全位于这块空间外部的图元将会被剔除,在空间边界相交的部分会被裁剪

4.2.1. 透视投影(perspective projection)

裁剪空间由 6 个裁剪平面组成。其中有两个特殊的裁剪平面:近裁剪平面(near clip plane)远裁剪平面(far clip plane)。它们共同决定了摄像机可以看到的深度范围。

Unity 中的 Camera 组件,通过 Field of View(简称 FOV)属性改变视锥体的张开角度;在 Clipping Planes 中的 Near Far 属性可以分别设置近裁剪平面远裁剪平面距离摄像机的距离。

可以通过以下公式得到两个裁剪平面的高度(宽度用纵横比得到):

n e a r C l i p P l a n e H e i g h t = 2 ⋅ N e a r ⋅ t a n F O V 2 nearClipPlaneHeight=2·Near·\rm tan \it \frac {FOV}{\rm 2} nearClipPlaneHeight=2Neartan2FOV

n e a r C l i p P l a n e H e i g h t = 2 ⋅ N e a r ⋅ t a n F O V 2 nearClipPlaneHeight=2·Near·\rm tan \it \frac {FOV}{\rm 2} nearClipPlaneHeight=2Neartan2FOV

Aspect 表示摄像机的纵横比,透视投影的投影矩阵如下:

M f r u s t u m = [ c o t F O V 2 A s p e c t 0 0 0 0 c o t F O V 2 0 0 0 0 − F a r + N e a r F a r − N e a r − 2 ⋅ F a r ⋅ N e a r F a r − N e a r 0 0 − 1 0 ] \bf M_{\it frustum}=\begin{bmatrix} {\rm \frac {cot \frac{FOV}{2}}{Aspect}}&{0}&{0}&{0}\\ {0}&{\rm cot \frac {FOV}{2}}&{0}&{0}\\ {0}&{0}&{\rm -\frac {Far+Near}{Far-Near}}&{\rm -\frac {2·Far·Near}{Far-Near}}\\ {0}&{0}&{-1}&{0}\\ \end{bmatrix} Mfrustum=Aspectcot2FOV0000cot2FOV0000FarNearFar+Near100FarNear2FarNear0

把顶点乘上投影矩阵,就会这样:

M f r u s t u m [ x y z 1 ] = [ x c o t F O V 2 A s p e c t y c o t F O V 2 − z F a r + N e a r F a r − N e a r − 2 ⋅ F a r ⋅ N e a r F a r − N e a r − z ] \bf M_{\it frustum} \begin{bmatrix} x\\y\\z\\1 \end{bmatrix}= \begin{bmatrix} {x\frac {cot \frac{FOV}{2}}{Aspect}}\\ {y\rm cot \frac {FOV}{2}}\\ {-z\rm \frac {Far+Near}{Far-Near}-\rm \frac {2·Far·Near}{Far-Near}}&{}\\ {-z}\\ \end{bmatrix} Mfrustumxyz1=xAspectcot2FOVycot2FOVzFarNearFar+NearFarNear2FarNearz

可见,经过投影的顶点, w w w 分量变为了取反后的 z,意味着裁剪矩阵会改变空间的旋向性——空间从右手坐标系换到了左手坐标系。

一个顶带你在视锥体内,转换后的坐标就需要满足:

− w ≤ x ≤ w -w\leq x\leq w wxw

− w ≤ y ≤ w -w\leq y\leq w wyw

− w ≤ z ≤ w -w\leq z\leq w wzw

4.2.2. 正交投影(orthographic projection)

用 unity 的 camera 组件中的 Size 属性改变锥体竖直方向上高度的一半,正交投影的投影矩阵如下:

M o r t h o = [ 1 A s p e c t ⋅ S i z e 0 0 0 0 1 S i z e 0 0 0 0 − 2 F a r − N e a r − F a r + N e a r F a r − N e a r 0 0 0 1 ] \bf M_{\it ortho}=\begin{bmatrix} {\rm \frac {1}{Aspect·Size}}&{0}&{0}&{0}\\ {0}&{\rm \frac {1}{Size}}&{0}&{0}\\ {0}&{0}&{\rm -\frac {2}{Far-Near}}&{\rm -\frac {Far+Near}{Far-Near}}\\ {0}&{0}&{0}&{1}\\ \end{bmatrix} Mortho=AspectSize10000Size10000FarNear2000FarNearFar+Near1

使用正交投影的投影矩阵对顶点进行变换后,坐标的 w w w 分量仍然为 1。

4.3. 屏幕空间(screen space)

经过投影矩阵的变换、裁剪的操作后,就需要把视锥体投影到屏幕空间了。

4.3.1. 齐次除法(homogeneous division)

又称为透视除法(perspective division),做法是用齐次坐标系的 w w w 分量去除 x、y、z 分量,得到的坐标在 OpenGL 中被称作归一化的设备坐标(Normalized Device Coordinates, NDC)。对正交投影来说,它的裁剪空间已经是一个立方体了,齐次除法并没有实际影响。

5. 法线变换

法线(normal),又称为法矢量(normal vector)。一种方向矢量,例如用来计算光照。

需要注意转换方法。若是使用与顶点同一个变换矩阵,可能无法维持法线的垂直性。

切线(tangent),又称为切矢量(tangent vector)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值