MAKE · WRITE · SHARE

Base-矩阵和向量

这篇需要常复习。

1. 坐标系

笛卡尔坐标系

2D 坐标系

2D 坐标系:原研究示意与实现细节

3D 坐标系

1. 左手坐标系

Unity的左手坐标系,y上z前x右
左手坐标系:Unity的左手坐标系,y上z前x右

UE的左手坐标系,z上y右x前,相当于untiy的坐标系翻了一下,但仍然是左手。
左手坐标系:UE的左手坐标系,z上y右x前,相当于untiy的坐标系翻了一下,但仍然是左手。

2. 右手坐标系

y上z后x右
右手坐标系:y上z后x右

OpenGL:右手

DX:左手

3. 疑问:

Q:左手坐标系如何转换右手?

—-A:z取负即可

Q:左右手坐标系,和矩阵使用行列向量是否有关系?

—-A:没有关系,UE使用行向量,Unity使用列向量,但都是左手

极坐标系

极坐标系:原研究示意与实现细节

笛卡尔——>极坐标系

笛卡尔——>极坐标系:原研究示意与实现细节

极坐标系——>笛卡尔

极坐标系——>笛卡尔:原研究示意与实现细节

3D极坐标系

3d的极坐标系之前也接触过,做IK旋转的时候,正常笛卡尔无法做角度Lerp,转换到极坐标系进行角度的Lerp。

基本和2d的一样,找一下wiki里的公式转换就行。

2. 向量

Position

比如在一个3d坐标空间,通常使用一个float3(x,y,z)表示这个点的位置Position。

这里直接也引入齐次坐标,如果表示一个点位置,它此时齐次坐标为

float4(x,y,z,1) w=1

转换为非齐次:
float3(x/1,y/1,z/1)

Vector

比如在一个3d坐标空间,使用一个float3(x,y,z)表示一个方向Vector。

这里也引入齐次坐标,如果表示一个方向,齐次坐标为

float4(x,y,z,0) w=0

vector和position的运算

vector和pos经常是有运算的,一般我们也是按照位置和方向区分,但是Games101这个图带来个新的震撼。

虽然point + point这个日常没使用过,但是数学概念是中点。

vector和position的运算:虽然point + point这个日常没使用过,但是数学概念是中点。

向量的运算

向量的大小:模

向量的大小:模:原研究示意与实现细节

两点之间距离

两个点之间的距离是一个标量。实际上求模。

A(a,b,c) B(x,y,z)

AB之间距离为:B-A这个向量的模。

向量的加减

[a,b,c] + [x,y,z] = [a+x,b+y,c+z]

[a,b,c] - [x,y,z] = [a-x,b-y,c-z]
向量的加减:(a,b,c) - (x,y,z) = (a-x,b-y,c-z)

一个点到另一个点的向量

A(a,b,c) B(x,y,z)

(x-a,y-b,z-c) ——-> [x-a,y-b,z-c]

向量点乘Dot

Vector * 标量 = Vector

Vector * Vector = 结果为标量,值的意义一般是看Cos<A,B>

A(a,b,c) * B(x,y,z)

(a,b,c) · (x,y,z) = ax+by+cz

A · B = |A| |B| cos<A,B>

– – –
Dot>0 0°<= <a,b> <=90° a和b方向基本相同
Dot=0 <a,b>=90° a和b垂直
Dot<0 90°<= <a,b> <=180° a和b方向基本相反

向量投影

b在a上的投影
向量投影:b在a上的投影

向量叉乘Cross

vector x vector = vector 结果为向量,垂直于AB所在平面

A(x1,y1,z1) x B(x2,y2,z2) =

(y1z2-z1y2 , z1x2-x1z2 ,x1y2-y1x2)

–如果Cross结果为零向量,说明AB平行。

–判断AxB结果与AB平面的方向

在左手坐标系中,a和b顺时针,那a×b指向屏幕外;逆时针则指向屏幕内;

右手 坐标系相反;
向量叉乘Cross:右手 坐标系相反;

判断一个点是否在三角形内?

使用Cross运算,三条边与三个点到目标点的向量叉乘,同为正或同为负则在三角形内。

AB x AP

BC x BP

CA x CP
判断一个点是否在三角形内?:CA x CP

3. 矩阵

矩阵的表示

向量是标量的数组。

矩阵是向量的数组。

矩阵的表示就是一组向量。

转置矩阵、逆矩阵、正交矩阵

转置矩阵

把行向量转换为列向量。

2x3矩阵的转置矩阵就是3x2矩阵。
转置矩阵:2x3矩阵的转置矩阵就是3x2矩阵。

逆矩阵

设A是一个n阶矩阵,若存在另一个n阶矩阵B,使得: AB=BA=E(E为单位矩阵)

并不是所有矩阵都可逆。

正交矩阵

转置和逆矩阵一样的矩阵。

矩阵的运算

矩阵乘法

一个m×n矩阵A只能和n×c矩阵B相乘,得到m×c矩阵C;

一个2×3矩阵A和3×2矩阵B相乘,得到2×2矩阵C;
矩阵乘法:一个2×3矩阵A和3×2矩阵B相乘,得到2×2矩阵C;

但是还是方阵乘法用的最多。

向量和矩阵乘法

向量能和矩阵乘,实际上把向量当成了一个维度是1的矩阵。

比如 1x3的向量可以乘 3x3 的矩阵 = 1x3向量。 (最常见的一种了把,实际上是线性变换)

常见的数学表示,行优先(UE引擎):
向量和矩阵乘法:常见的数学表示,行优先(UE引擎):

列优先,矩阵表示,(Unity引擎):
向量和矩阵乘法:列优先,矩阵表示,(Unity引擎):

方阵与线性变换

平时用到最多的就是方阵,它可以表示线性变换(旋转、缩放、投影、镜像、仿射 主要是中心不变)。

从一个坐标系转换到另一个坐标系(用三个XYZ基向量表示)。

这个矩阵就是表示线性变换的矩阵,把向量转换到新的坐标系。新的坐标系的3个基向量的表示按照原坐标计算。

方阵与线性变换:这个矩阵就是表示线性变换的矩阵,把向量转换到新的坐标系。新的坐标系的3个基向量的表示按照原坐标计

矩阵的推导

前面知道了线性变换时,矩阵其实就是3个基向量,那么来推导几个矩阵。

推导就是按照当前坐标系,算出目标坐标系的三个基向量。

下面都是按照Unity里的列优先矩阵写的。

旋转矩阵

旋转矩阵:原研究示意与实现细节

缩放矩阵

缩放矩阵:原研究示意与实现细节

投影矩阵

投影可降低表示维度,例如投到某坐标平面;图形管线的投影矩阵还会保留深度供裁剪与遮挡,不能统一解释为直接丢掉 Z。
投影矩阵:投影可降低表示维度,例如投到某坐标平面;图形管线的投影矩阵还会保留深度供裁剪与遮挡,不能统一解释

切变矩阵

一种坐标系的扭曲变换,非均匀拉伸;切变角度会发生改变,面积和体积不变;

基本思想:将某一坐标的乘积加到其他坐标上;

如:2D中,将y乘以某个因子a后加到x上,x’ = x+ay y’ = y
切变矩阵:如:2D中,将y乘以某个因子a后加到x上,x' = x+ay  y' = y

齐次矩阵

正常的3x3矩阵无法表示3d空间的平移,所以引入了齐次矩阵。

加入一个维度w,position的w默认为1,vector的w默认为0。

所以在齐次坐标表示的情况下,实际的3D点被认为是w=1的时候。
也就是(x/w, y/w, z/w, 1) w=1

在引擎里,MVP之后的齐次空间,w是不为1的,就可以表示出近大远小的感觉。

平移矩阵

Unity里写法
平移矩阵:Unity里写法

UE里写法
平移矩阵:UE里写法

投影

齐次空间投影,如(x,y,z,w)向z = d投影

数学表示(右乘):
投影:数学表示(右乘):

透视和正交投影在后面坐标空间写。

4. 方位和角位移

用矩阵和四元数来表示 “角位移”,用欧拉角表示“方位”。

矩阵表示

旋转矩阵同样是常见表示,便于组合变换;四元数与矩阵各有存储、插值和计算方面的取舍。

欧拉角

Unity 的 Quaternion.Euler 文档约定按 Z、X、Y 顺序应用相关轴旋转。内旋/外旋与乘法顺序需要配套定义,不能仅列出三个字母就视为通用欧拉约定。

有万向锁问题。

四元数

四元数常用于保存与插值旋转,但 q 与 -q 表示同一空间旋转,并不具有这种意义上的唯一性。插值应注意同半球、归一化与球面插值,普通 Lerp 不自动保持单位长度。

四元数:四元数常用于保存与插值旋转,但 q 与 -q 表示同一空间旋转,并不具有这种意义上的唯一性。插值

5. 球面UV

下面示例是二维正方形到圆盘的映射,适用于约定输入范围 [-1,1] 的摇杆输入;它不是三维球面 UV 参数化。

球面UV:下面示例是二维正方形到圆盘的映射,适用于约定输入范围 (-1,1) 的摇杆输入;它不是三维球面

1
2
3
4
5
6
7
8
9
10
/// <summary>
/// 将 [-1,1] 正方形坐标映射到二维圆盘
/// </summary>
protected Vector2 SquareToCircle(Vector2 input)
{
Vector2 output;
output.x = input.x * Mathf.Sqrt(1 - (input.y * input.y) / 2);
output.y = input.y * Mathf.Sqrt(1 - (input.x * input.x) / 2);
return output;
}

6. 三角形重心坐标

算出三角形的重心坐标,满足一个公式,所以重心坐标用(α,β,γ)分别表示ABC的权重。

在同一平面内,重心坐标可对顶点属性做仿射插值;经过透视投影后,普通屏幕重心权重还需结合各顶点 clip.w 做透视校正,不能把 UV、设备深度与任意空间深度都按同一公式混用。

三角形重心坐标:在同一平面内,重心坐标可对顶点属性做仿射插值;经过透视投影后,普通屏幕重心权重还需结合各顶点 c

7. 计算反射

通过入射光和法线,求反射方向。

EB = N * |AB|cosθ = N * dot(N,AB)

DC = 2 * EB = -2 * N * dot(N, AB)

AC = AD + DC = -AB + 2 * N * dot(N,AB)
计算反射:AC = AD + DC = -AB + 2  N  dot(N,AB)

反射、折射与符号约定

设 I 为指向表面的单位入射方向,N 为单位表面法线,反射方向是 R=I-2*dot(N,I)*N。若使用表面指向光源的 L,输入应为 -L。原图中的 AB 必须先明确方向,不能混用“从表面离开”和“射向表面”的向量。

折射满足 n1*sin(theta1)=n2*sin(theta2)。从高折射率介质进入低折射率介质,不是必然没有折射;只有入射角超过临界角,才发生全反射。空气进入玻璃与玻璃离开空气,需要分别调整法线方向和折射率比。

原记录图解

折射方向受两侧折射率约束,入射角和透射角通过 Snell 定律关联

原笔记配图:折射方向受两侧折射率约束,入射角和透射角通过 Snell 定律关联。

从 Snell 定律推导透射角与全反射条件

原笔记配图:从 Snell 定律推导透射角与全反射条件;只有从高折射率介质进入低折射率介质时才可能发生全反射。

水下观察的 Snell 窗示意与照片,展示可透射方向的范围

原笔记配图:水下观察的 Snell 窗示意与照片,展示可透射方向的范围。

示例介质界面的 s、p 偏振与未偏振反射率曲线,不能把某一条的单调性推广为全部情况

原笔记配图:示例介质界面的 s、p 偏振与未偏振反射率曲线,不能把某一条的单调性推广为全部情况。

Schlick 近似及法向入射反射率 R0

原笔记配图:Schlick 近似及法向入射反射率 R0。

微表面镜面 BRDF 中的 Fresnel、遮蔽与法线分布三部分

原笔记配图:微表面镜面 BRDF 中的 Fresnel、遮蔽与法线分布三部分。

各向同性和各向异性表面法线分布,对应不同的方向响应

原笔记配图:各向同性和各向异性表面法线分布,对应不同的方向响应。

总结

向量与矩阵公式必须带着空间、方向和行列约定使用。重心插值、齐次除法、法线变换和折射边界各有前提,不能只按变量维数相同就直接运算。

参考资料