持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情
本文标题:WebGL第四十二课:3D前置知识点之Perspective矩阵
友情提示
这篇文章是WebGL课程专栏的第42篇,强烈建议从前面开始看起。因为花了大量的工夫来讲解向量的概念和矩阵运算。这些基础知识会影响你的思维。
矩阵的作用
一般来说,在程序里或者在公式里,矩阵的作用可以看成是一个输入输出系统。
这个系统的输入是一个向量,输出是另一个向量,像下图这样:

研究某一个特定矩阵的效果,就要看,这个输出向量和输入向量的关系。
这十分类似于程序里的函数。
举个特定的例子来说明,比如说我们有一个2D的旋转矩阵,作用是逆时针旋转30°,那么对于任意输入向量来说,得到的输出向量,皆是该输入向量逆时针旋转30°的结果,如下图:

我们这里注意一下,一个矩阵的输入向量,必须是该维度内,任意的向量。
比如说上述的旋转矩阵,那么对于任意2D的输入向量,必须都能完成这个旋转效果才行。
这一点需要留个心眼,下面会再次提及。
用穷举法获取矩阵效果
既然这里把矩阵看做一个输入输出系统,我们不妨这样来研究某个特定矩阵的效果:
大量穷举输入向量,去观测相应的输出向量,总结输出向量与输入向量的关系,即可。
意思就是,如果我们不清楚一个矩阵的效果是什么,我们就可以随便找几个输入向量,然后计算出输出向量,然后观察一下效果,然后试图总结一下整个矩阵的效果。
穷举法示例1
有一个2D的矩阵:[2003], 试着总结一下这个矩阵的效果。
我们用三个输入向量来实验一下:
-
[2003] * (10) = (20)
-
[2003] * (0.50.5) = (11.5)
-
[2003] * (01) = (03)
我们来总结一下规律,该矩阵可能的效果是:
- 将输入向量的x分量变成原来的2倍
- 将输入向量的y分量变成原来的3倍
我们再列一个任意向量,来验证一下我们的总结是否正确:
- [2003] * (56) = (1018)
验证了一下,确实是这个效果,那么大概率我们总结的效果就是正确的了。
穷举法示例2
看这个矩阵: [1000]
列举如下:
-
[1000] * (10) = (10)
-
[1000] * (0.50.5) = (0.50)
-
[1000] * (01) = (00)
总结规律:
保留输入向量的x分量,让y分量变成0。
穷举画图
总结规律最好的办法就是在坐标系中画出输入输出向量坐标,能更加清晰的找到规律。
比如说旋转矩阵,我们只要列出几个向量,然后画出输出向量,非常容易得知,输出向量是由输入向量旋转得来。
开始分析Perspective矩阵
对输入向量进行约束
我们先把上文中的一个重要注意点放到这里:
一个矩阵的输入向量,必须是该维度内,任意的向量。
由于该Perspective矩阵是4D的,那么根据这个注意点,得出一个东西:
输入向量必须是任意4D向量。
但是很明显,对于Perspective矩阵来说,这个输入向量不能是任意的4D向量。
这是由于齐次空间的原因,如果对于齐次空间不理解的读者,可以先看WebGL第四十一课:3D前置知识点之齐次空间 - 掘金 (juejin.cn)。
对于Perspective矩阵来说,这里给出输入向量必须满足的条件:
形如:xyz1.0的向量,即可作为Perspective矩阵的输入。
也就是说,前面三个分量无所谓,最后一个分量必须是1.0。
这里做这样的约束,并不是因为,矩阵本身不能接受任意4D向量,而是我们图形学应用的时候,第四个分量只会是1.0,这样能大大缩减我们穷举时的数据量,能够更快分析出来规律。
先给出Perspective的数学形式
想要生成一个Perspective矩阵,我们一般有几个参数:
- 近面 near
- 远面 far
- 宽高比 whr
- 视场角 fov
根据以上参数,可以得出一个Perspective矩阵:
whr∗tan(fov/2)10000tan(fov/2)10000−far−nearfar+near−100near−far2∗far∗near0
我们剩下来的事情就是要研究,对于任意 xyz1.0向量,经过这个矩阵运算之后,输出向量会是什么。
根据矩阵乘法的相关性质(WebGL第十四课:从向量到矩阵 - 掘金 (juejin.cn)),我们可以立即得出一个结论:
输出向量的 w=−z, 也就是说:
whr∗tan(fov/2)10000tan(fov/2)10000−far−nearfar+near−100near−far2∗far∗near0 * xyz1.0 = ???−z
前面三个分量暂时处于未知状态。
研究一个图形学中矩阵的效果,一定要看输入向量的物理意义是什么。
看下图:

提出一个问题:
Perspective矩阵的输入向量,是图中的
到底是哪一个?
很明显是绿色的向量,因为Perspective矩阵是MVP矩阵中,最后进行运算的矩阵。
在经过View矩阵的时候,已经将黑色向量转成了绿色向量了。
在这里再提一个额外的知识:
View矩阵不仅仅是将黑色向量变成绿色向量,并且连带坐标系,也一并变换了,就是说,这个View矩阵有两个效果:
-
- 将黑色向量变成绿色向量
-
- 将绿色向量用相机的三个轴形成的坐标系,输出到结果
重点:Perspective矩阵的输入,正是上面两步之后的结果。
也就是说,我们此时考虑的坐标系,就应该是Camera坐标系,而非世界坐标系。
接下来,我们在Camera坐标系中,将 near far whr fov 画出来,这就是我们常见的视椎体:

然后,我们将注意力集中在这个视椎体内部的点与Camera位置连线所形成的一堆向量上。
先研究输出向量的z分量
先把得到的向量写出来:
whr∗tan(fov/2)10000tan(fov/2)10000−far−nearfar+near−100near−far2∗far∗near0 * xyz1.0 = ??zout−z
zout=−z∗far−nearfar+near+n−f2∗far∗near
结论一:可以看出,far 和 near 都是常量,随着z的变化,zout是线性变化的。
我们不妨取
- 输入z = -near
- 输入z = -far
两个极端情况来代入试试:
当输入 z=-near 时,zout = -near // 很简单的中学化简得到的结果
当输入 z=-far 时,zout = far
又由于,这个变换过程是线性的,我们可以得知,
当输入的z在[ -near, -far]间变化时,输出的zout就会在[ -near, far]之间线性变化。
再研究输出向量的x分量
从矩阵乘法算式中可以一眼看出:
输出向量xout=whr∗tan(fov/2)x
这仅仅是输入向量x带了一个乘积系数而已,非常简单的关系。
输出向量的y分量与x分量类似
输出向量yout=tan(for/2)y
也仅仅是输入向量y带了一个乘积系数。
疑团
从网上的资料中,我们知道,Perspective 矩阵可以将视椎体内的向量,变到NDC的范围中去。也就是xyz个分量的范围都应该是[-1,1]。
但上面我们看出,zout的范围似乎不是[-1,1], 而是[-near, far]。
这是为啥?
这里就要再次提一下齐次空间了WebGL第四十一课:3D前置知识点之齐次空间 - 掘金 (juejin.cn)。
输出向量的xyz最终都要除以w,也就是说:
最终得到的结果是一个3D的向量:
wxoutwyoutwzout
研究这个式子:
zout/w = zout/(−z) = far−nearfar+near+(near−far)(−z)2∗far∗near
这就很明显了,
- 将z=-near代入,得到 zout/w = -1
- 将z=-far代入,得到 zout/w = 1
并且,观察式子,z处于一个分母的位置,很明显,随着z的变化,最终得到的结果不是一个线性的,而是呈下图的样子:

在z靠近-near的时候,变化极其剧烈
在z靠近-far的时候,变化极其平缓。
最终的xy
我们不妨来观察一下xout/w这个式子:
xout/w = xout/(−z) = whr∗tan(fov/2)∗(−z)x
我们将式子中的常量写成一个整体系数,得到 −zC∗x
那么输入向量x在[Cz,C−z]之间取值的时候,最终的结果就会是[-1,1]之间。
我们发现,输入向量z越小,我们输入向量x就必须更大,才能更靠近[-1, 1]。
这不就是透视效果吗!!!
y的分析与x一样,就不赘述了。
总结
本篇从数值角度分析了Perspective矩阵的效果和相关特性,希望对诸位有帮助。
以下是deepseek对这篇文章的总结,非常好,复制过来
分步解释:Perspective矩阵的作用与原理
1. 矩阵的基本作用
矩阵在图形学中用于坐标变换。Perspective矩阵属于投影矩阵的一种,负责将3D相机空间中的点投影到2D屏幕,同时保持透视效果(近大远小)。
2. 输入向量的约束
- 形式:输入向量为齐次坐标 xyz1.0,表示3D空间中的点。
- 来源:经过模型矩阵(Model)和视图矩阵(View)变换后,点已位于相机坐标系,此时应用Perspective矩阵。
3. Perspective矩阵的结构
矩阵参数:
- near:近裁剪面距离(正值)。
- far:远裁剪面距离(正值)。
- fov:垂直视场角(决定视野高度)。
- whr:宽高比(视图宽度/高度)。
矩阵形式:
M=whr∗tan(fov/2)10000tan(fov/2)10000−far−nearfar+near−100near−far2∗far∗near0
4. 输出向量计算
输入向量 xyz1.0 经过矩阵乘法:
x′y′z′1.0=M⋅xyz1.0
具体分量:
-
x':whr⋅tan(fov/2)x
-
y':tan(fov/2)y
-
z':−far−nearfar+near⋅z+near−far2⋅far⋅near
-
w':(-z)
5. 透视除法(关键步骤)
将齐次坐标转换为3D标准化设备坐标(NDC):
NDC=(w′x′,w′y′,w′z′)
-
x和y分量:
w′x′=−whr⋅tan(fov/2)⋅zx
w′y′=−tan(fov/2)⋅zy
这实现了近大远小:当 (z) 增大(远离相机),分母增大,坐标值缩小。
-
z分量:
w′z′=−z−far−nearfar+near⋅z+near−far2⋅far⋅near
化简后:
w′z′=far−nearfar+near+z⋅(near−far)2⋅far⋅near
- 当 z=−near(近裁剪面),结果为 −1;
- 当 z=−far(远裁剪面),结果为 1。非线性映射优化了深度缓冲的精度分布。
6. 视椎体到NDC的映射
- x和y:被缩放并受z影响,确保视椎体内的点映射到NDC的[−1,1]范围。
- z:非线性映射到[−1,1],保证深度测试正确性。
7. 参数影响
- fov:角度越大,视野越广,物体显得更小。
- near/far:决定可见深度范围,影响深度精度和裁剪。
8. 总结
Perspective矩阵通过缩放和平移,将相机空间的视椎体转换为NDC立方体,再通过视口变换映射到屏幕。关键步骤是矩阵乘法后的透视除法,实现了3D到2D的投影及深度处理。