最近在重温计算机图形学的基础知识,期望能做到温故知新,加深对其的理解,以便能从容应对工作中各种情况。
小弟水平有限,若有不正确之处,欢迎大家批评指正。
投影分为正交投影和透视投影。
正交投影会保留场景原始的画面,平行的线仍然平行;
透视投影会产生近大远小的效果,平行的线不再平行。
投影矩阵将相机空间的顶点全部转换到裁剪空间。裁剪空间的点x、y和z的坐标都被映射在[-1, 1]。
注意,裁剪空间中的点还是齐次坐标。齐次坐标转换到笛卡尔坐标,需要进行如下的转换:
(
x
y
z
w
)
正交投影的视景体如下图所示:

该视景体是一个立方体,在
x
y
z
xyz
xyz 组成的的相机空间中;
l 代表视景体左截面x坐标,r 代表视景体右截面x坐标;
b 代表视景体底截面y坐标,t 代表视景体上截面y坐标;
n 代表视景体近截面z坐标,f 代表视景体远截面z坐标;
视景体中,l 一定小于 r,b 一定小于 t。相机空间中,可视点的 z 值一定小于0,所以 n 一定大于 f。
正交投影变换包含两个步骤:
① 将视景体中心平移到原点;
② 执行缩放,使 xyz的范围为[-1, 1]。

上述变换要分别使用平移矩阵
M
T
M_{T}
MT 和缩放矩阵
M
S
M_{S}
MS。
平移矩阵如下:
M
T
M_{T}
MT =
(
1
0
0
−
(
l
+
r
)
2
0
1
0
−
(
b
+
t
)
2
0
0
1
−
(
n
+
f
)
2
0
0
0
1
)
缩放矩阵如下:
M
S
M_{S}
MS =
(
2
r
−
l
0
0
0
0
2
t
−
b
0
0
0
0
2
n
−
f
0
0
0
0
1
)
现以 x 为例来推导缩放因子。
平移视景体中心到原点后,由于视景体是对称的立方体,所以
−
n
<
x
<
n
-n < x < n
−n<x<n,其中n > 0,且 n =
r
−
l
+
r
2
r - \frac{l+r}{2}
r−2l+r =
r
−
l
2
\frac{r-l}{2}
2r−l。
为了让
−
1
<
x
<
1
-1 < x < 1
−1<x<1,因此需要乘以系数
1
n
\frac{1}{n}
n1,即
2
r
−
l
\frac{2}{r-l}
r−l2。
其他两个维度的推导也是如此。
综上,正交投影矩阵
M
O
r
t
h
o
M_{Ortho}
MOrtho =
M
S
M_{S}
MS
M
T
M_{T}
MT。
注意,如果视景体的aspect ratio != 1,经过正交变换后,图像会被拉伸。最后,会通过视口变换进行纠正。
透视投影是应用最广泛的投影,它能产生近大远小的效果,平行线经过透视投影后不再平行。

同正交投影一样,透视投影也有自己的l、r、b、t、n、f。不同的是,各个截面会相交于相机空间的原点。
视椎体中的顶点被投影到近平面上,从而被渲染到屏幕。
视椎体由如下因素决定:① field of view;② aspect ration;③ near 和 far。

视椎体是个对称的平截头体,现以侧面YZ平面来分析:

现在已知fovY、apsect ratio =
w
i
d
t
h
h
e
i
g
h
t
\frac{width}{height}
heightwidth、near和far,视椎体是一个对称平截头体,且规则地放在
−
Z
-Z
−Z轴上。
根据正切定理,有 t =
t
a
n
(
f
o
v
Y
2
)
tan(\frac{fovY}{2})
tan(2fovY) *
∣
n
∣
|n|
∣n∣;又根据对称性,得到 -t = b;
又根据 aspect ratio =
r
t
\frac{r}{t}
tr =
w
i
d
t
h
h
e
i
g
h
t
\frac{width}{height}
heightwidth,因此 r = aspect ratio * t;又因为对称性,所以有 -r = l。
综上,可根据fovY、aspect ration、near 和 far可求得 l、r、b 和 t。
以侧面 YZ 面来进行分析:

由相似三角形,点投影到近平面后,其
y
′
y'
y′ =
∣
n
∣
∣
z
∣
\frac{|n|}{|z|}
∣z∣∣n∣ *
y
y
y;
同理,该点的x轴坐标为
x
′
x'
x′ =
∣
n
∣
∣
z
∣
\frac{|n|}{|z|}
∣z∣∣n∣ *
x
x
x。
在OpenGL中,通常near和far必须指定为大于0,因此,由于
z
<
0
z < 0
z<0,有:
x
′
x'
x′ =
−
n
z
-\frac{n}{z}
−zn *
x
x
x,
y
′
y'
y′ =
−
n
z
-\frac{n}{z}
−zn *
y
y
y。
x x x 经过投影后成为 x ′ x' x′, x ′ x' x′在近平面上,因此有: l < x ′ < r l < x' < r l<x′<r;
减去 l,有: 0 < x ′ − l < r − l 0 < x' - l < r - l 0<x′−l<r−l;
除以 r − l r - l r−l,有: 0 < x ′ − l r − l < 1 0 < \frac{x' - l}{r - l} < 1 0<r−lx′−l<1;
乘以2,有: 0 < 2 x ′ − l r − l < 2 0 < 2\frac{x' - l}{r - l} < 2 0<2r−lx′−l<2;
减去1,有: − 1 < 2 x ′ − l r − l − 1 < 1 -1 < 2\frac{x' - l}{r - l} - 1< 1 −1<2r−lx′−l−1<1;
将上述等式优化,有: − 1 < 2 x ′ − 2 l r − l − r − l r − l < 1 -1 < \frac{2x' - 2l}{r - l} - \frac{r-l}{r-l}< 1 −1<r−l2x′−2l−r−lr−l<1;
有: − 1 < 2 x ′ − l − r r − l < 1 -1 < \frac{2x' - l - r}{r - l}< 1 −1<r−l2x′−l−r<1;
有: − 1 < 2 x ′ r − l − r + l r − l < 1 -1 < \frac{2x'}{r - l} - \frac{r+l}{r-l}< 1 −1<r−l2x′−r−lr+l<1;
将上述 x ′ x' x′ 替换为 x x x(相机空间坐标点),有: − 1 < − 2 n x z ( r − l ) − r + l r − l < 1 -1 < \frac{-2nx}{z(r - l)} - \frac{r+l}{r-l}< 1 −1<z(r−l)−2nx−r−lr+l<1; (等式①)
因此,若将下述矩阵作为透视变换矩阵,有:
M
P
e
r
s
p
e
c
t
M_{Perspect}
MPerspect =
(
2
n
r
−
l
0
r
+
l
r
−
l
0
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
0
0
−
1
0
)
现求取
x
x
x分量进行验证,
M
P
e
r
s
p
e
c
t
M_{Perspect}
MPerspect x
(
x
y
z
w
)
该结果的 w w w 分量(齐次坐标)为: 0 ∗ x 0 * x 0∗x + 0 ∗ y 0 * y 0∗y + ( − 1 ∗ z ) (-1 * z) (−1∗z) + 0 ∗ w 0 * w 0∗w = − z -z −z;
齐次坐标转换为笛卡尔坐标需要除以 w w w,故上述 x x x 分量转换到笛卡尔坐标后为: 2 n x − z ( r − l ) \frac{2nx}{-z(r-l)} −z(r−l)2nx - r + l r − l \frac{r+l}{r-l} r−lr+l。该值和前述推导等式①一致。
综上,透视投影矩阵的第一行元素就确定下来了。
同理,可以确定透视投影的第二行元素,其推导方法和前述一致,只是把
r
r
r 和
l
l
l 分别替换为
t
t
t 和
b
b
b。
M
P
e
r
s
p
e
c
t
M_{Perspect}
MPerspect =
(
2
n
r
−
l
0
r
+
l
r
−
l
0
0
2
n
t
−
b
t
+
b
t
−
b
0
.
.
.
.
.
.
.
.
.
.
.
.
0
0
−
1
0
)
投影后的点在近平面上, x x x 和 y y y 不会对 z z z 有影响,那么设透视投影矩阵为:
M
P
e
r
s
p
e
c
t
M_{Perspect}
MPerspect =
(
2
n
r
−
l
0
r
+
l
r
−
l
0
0
2
n
t
−
b
t
+
b
t
−
b
0
0
0
A
B
0
0
−
1
0
)
其中 A 和 B 是待求解的未知数。
有: z ′ z' z′ = ( A z + B w Az + Bw Az+Bw) / ( − z -z −z)
当相机空间的点在近平面时,
z
′
z'
z′ 需要被投影为-1,且此时
z
z
z = -near;
当相机空间的点在远平面时,
z
′
z'
z′ 需要被投影为1,且此时
z
z
z = -far;
因此,可以列出两个方程:
① − 1 -1 −1 = − n A + B n \frac{-nA + B}{n} n−nA+B;
② 1 1 1 = − f A + B f \frac{-fA + B}{f} f−fA+B;
两个方程,两个未知数,解得 A A A = − f + n f − n -\frac{f+n}{f-n} −f−nf+n, B B B = − 2 f n f − n -\frac{2fn}{f-n} −f−n2fn。
综上,透视投影的方程如下:
M
P
e
r
s
p
e
c
t
M_{Perspect}
MPerspect =
(
2
n
r
−
l
0
r
+
l
r
−
l
0
0
2
n
t
−
b
t
+
b
t
−
b
0
0
0
−
f
+
n
f
−
n
−
2
f
n
f
−
n
0
0
−
1
0
)