投影矩阵概述
在得到相机坐标后,就相当于得到了人眼观察世界中物体的坐标,但是我们需要把物体映射到一个二维平面上用于显示,投影矩阵就起到把三维坐标映射到二维坐标的作用,同时因为三维空间有深度的概念,因此把Z轴转化成深度。W作为一个系数,用于检测是否超出窗口范围。
投影变换最终的效果是把各个坐标映射到 [ − 1 , 1 ] [-1,1] [−1,1]之间,然后再乘以相应的屏幕高度和宽度,得到最终的屏幕坐标。 [ − 1 , 1 ] [-1,1] [−1,1]的坐标又成为NDC坐标
推导过程参照:http://www.songho.ca/opengl/gl_transform.html ,一般直接套公式使用即可。
透视投影
M
p
r
o
j
e
c
t
i
o
n
=
[
2
n
r
−
l
0
r
+
l
r
−
l
0
0
2
n
t
+
b
t
−
b
0
0
0
−
f
+
n
f
−
n
−
2
f
n
f
−
n
0
0
−
1
0
]
\bf{M}_{projection}= \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0\\ 0 & \frac{2}{n} & \frac{t+b}{t-b} & 0 \\ 0 & 0 & -\frac{f+n}{f-n} & -\frac{2fn}{f-n} \\ 0 & 0 & -1 & 0 \end{bmatrix}
Mprojection=⎣⎢⎢⎡r−l2n0000n200r−lr+lt−bt+b−f−nf+n−100−f−n2fn0⎦⎥⎥⎤
n是近平面距离,f是远平面距离。l、r、t、b分别是左右上下
此时变换完成后,还不是NDC坐标,需要每个坐标乘以
w
w
w分量才行,下面的操作:
[
x
c
l
i
p
y
c
l
i
p
z
c
l
i
p
w
c
l
i
p
]
=
M
p
r
o
j
e
c
t
i
o
n
[
x
e
y
e
y
e
y
e
z
e
y
e
w
e
y
e
]
\begin{bmatrix} x_{clip}\\y_{clip}\\z_{clip}\\w_{clip} \end{bmatrix}=\bf{M}_{projection}\begin{bmatrix} x_{eye}\\y_{eye}\\z_{eye}\\w_{eye} \end{bmatrix}
⎣⎢⎢⎡xclipyclipzclipwclip⎦⎥⎥⎤=Mprojection⎣⎢⎢⎡xeyeyeyezeyeweye⎦⎥⎥⎤
其中,eye表示相机坐标,clip表示初步映射的坐标。
之后,再除以
w
w
w分量,得到NDC坐标:
[
x
n
d
c
y
n
d
c
z
n
d
c
]
=
[
x
c
l
i
p
/
w
c
l
i
p
y
c
l
i
p
/
w
c
l
i
p
z
c
l
i
p
/
w
c
l
i
p
]
\begin{bmatrix} x_{ndc}\\y_{ndc}\\z_{ndc} \end{bmatrix}= \begin{bmatrix} x_{clip}/w_{clip}\\y_{clip}/w_{clip}\\z_{clip}/w_{clip} \end{bmatrix}
⎣⎡xndcyndczndc⎦⎤=⎣⎡xclip/wclipyclip/wclipzclip/wclip⎦⎤
如果NDC不在[-1,1],表示超出屏幕范围,不能显示。
正交投影
正交投影的基本步骤是一致的,只是变换矩阵不同:
[
2
r
−
l
0
0
−
r
+
l
r
−
l
0
2
t
−
b
0
−
t
+
b
t
−
b
0
0
−
2
f
−
n
−
f
+
n
f
−
n
0
0
0
1
]
\begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & -\frac{2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix}
⎣⎢⎢⎡r−l20000t−b20000−f−n20−r−lr+l−t−bt+b−f−nf+n1⎦⎥⎥⎤