透视投影
通过将对象沿会聚到投影中心的路径投影到观察平面的方式,如下图的平面示意图
投影后的坐标计算
通过三角形相似,很容易得到物品投影到投影面上的横纵坐标
x
′
=
x
⋅
z
v
z
x' = x·\frac{z_v}{z}
x′=x⋅zzv
y
′
=
y
⋅
z
v
z
y' = y·\frac{z_v}{z}
y′=y⋅zzv
但要作为转换矩阵的模式,转化矩阵中的元素应该只和投影的参数相关,与物体无关,因此必须去除分母中的z。
为了计算方便,通常会额外引入一个维度w,而该维度的大小只有1(代表点)或者0(代表向量)。因此可以考虑利用第四个维度来存储额外的z数值,以达到在转换矩阵与物体的z向量无关的目的。
那么取其次坐标
x
h
=
h
x
′
=
z
⋅
x
′
=
x
⋅
z
v
x_h = hx' = z·x' = x·z_v
xh=hx′=z⋅x′=x⋅zv
y
h
=
h
x
′
=
z
⋅
y
′
=
y
⋅
z
v
y_h = hx' = z·y' = y·z_v
yh=hx′=z⋅y′=y⋅zv
h
=
z
h = z
h=z
对此写成矩阵形式为
[
x
h
y
h
z
h
h
]
=
[
z
v
0
0
0
0
z
v
0
0
0
0
s
z
t
z
0
0
1
0
]
[
x
y
z
1
]
\begin{bmatrix} x_h \\ y_h \\ z_h \\ h \end{bmatrix}=\begin{bmatrix} z_v&0&0&0\\ 0&z_v&0&0\\ 0&0&s_z&t_z\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
⎣⎢⎢⎡xhyhzhh⎦⎥⎥⎤=⎣⎢⎢⎡zv0000zv0000sz100tz0⎦⎥⎥⎤⎣⎢⎢⎡xyz1⎦⎥⎥⎤
其中
s
z
和
t
z
s_z和t_z
sz和tz为两个待定参数。
对于投影面来说,x,y轴的值确定了物体投影后的位置,z轴的值代表了物体的远近信息,而这个数值主要影响物体前后的遮挡关系。因此z轴的数值本身无任何意义,只要转换过后能够保持原有的顺序即可。因此矩阵中的
s
z
和
t
z
s_z和t_z
sz和tz可根据计算方便来选取,而物体的远近关系不会受到x,y轴的值的影响,因此矩阵第三行前两列都为0。
如此,转换矩阵的值与物体位置无关了,z的值通过w分量保存下来了,后续处理时,将坐标统一除以h即可得到所需的投影坐标值。
规范化透视投影
一般来说,投影的物体范围是有限的,因此会圈定一个范围作为观察体,在观察体内的物体才绘制在屏幕上,而观察体外的将舍弃。对于透视投影,一般取一个棱台作为观察体,如下图所示。
对于最终输出的坐标一般要求规范在一个[-1,1]的正方体内,对于计算出的坐标结果在此外围外的元素都将剔除。
棱台观察体主要由近平面和远平面定义,这两个平面分别限制了屏幕能够显示的物体最近的位置和最远的位置。假设近平面的位置为
z
n
e
a
r
z_{near}
znear,远平面的位置为
z
f
a
r
z_{far}
zfar,近平面的宽度为
w
n
e
a
r
w_{near}
wnear和
h
n
e
a
r
h_{near}
hnear,而且取近平面为投影面。
因此规范化后的坐标为
x
n
′
=
x
′
2
w
n
e
a
r
=
x
h
h
2
w
n
e
a
r
x'_n = x'\frac{2}{w_{near}} = \frac{x_h}{h}\frac{2}{w_{near}}
xn′=x′wnear2=hxhwnear2
y
n
′
=
y
′
2
h
n
e
a
r
=
y
h
h
2
h
n
e
a
r
y'_n = y'\frac{2}{h_{near}} = \frac{y_h}{h}\frac{2}{h_{near}}
yn′=y′hnear2=hyhhnear2
规范化坐标以之前同样的方式进行齐次化处理,可以得到
[
x
n
h
y
n
h
z
n
h
h
]
=
[
2
w
n
e
a
r
0
0
0
0
2
h
n
e
a
r
0
0
0
0
1
0
0
0
0
1
]
[
x
h
y
h
z
h
h
]
=
[
2
w
n
e
a
r
0
0
0
0
2
h
n
e
a
r
0
0
0
0
1
0
0
0
0
1
]
[
z
n
e
a
r
0
0
0
0
z
n
e
a
r
0
0
0
0
s
z
t
z
0
0
1
0
]
[
x
h
y
h
z
h
h
]
=
[
2
z
n
e
a
r
w
n
e
a
r
0
0
0
0
2
z
n
e
a
r
h
n
e
a
r
0
0
0
0
s
z
t
z
0
0
1
0
]
[
x
y
z
1
]
\begin{bmatrix} x_{nh} \\ y_{nh} \\ z_{nh} \\ h \end{bmatrix}=\begin{bmatrix} \frac{2}{w_{near}}&0&0&0\\ 0&\frac{2}{h_{near}}&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{bmatrix} \begin{bmatrix} x_h \\ y_h \\ z_h \\ h \end{bmatrix} \\ =\begin{bmatrix} \frac{2}{w_{near}}&0&0&0\\ 0&\frac{2}{h_{near}}&0&0\\ 0&0&1&0\\ 0&0&0&1 \end{bmatrix}\begin{bmatrix} z_{near}&0&0&0\\ 0&z_{near}&0&0\\ 0&0&s_z&t_z\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} x_h \\ y_h \\ z_h \\ h \end{bmatrix}\\ =\begin{bmatrix} \frac{2z_{near}}{w_{near}}&0&0&0\\ 0&\frac{2z_{near}}{h_{near}}&0&0\\ 0&0&s_z&t_z\\ 0&0&1&0 \end{bmatrix} \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}
⎣⎢⎢⎡xnhynhznhh⎦⎥⎥⎤=⎣⎢⎢⎡wnear20000hnear20000100001⎦⎥⎥⎤⎣⎢⎢⎡xhyhzhh⎦⎥⎥⎤=⎣⎢⎢⎡wnear20000hnear20000100001⎦⎥⎥⎤⎣⎢⎢⎡znear0000znear0000sz100tz0⎦⎥⎥⎤⎣⎢⎢⎡xhyhzhh⎦⎥⎥⎤=⎣⎢⎢⎡wnear2znear0000hnear2znear0000sz100tz0⎦⎥⎥⎤⎣⎢⎢⎡xyz1⎦⎥⎥⎤
现在确定
s
z
和
t
z
s_z和t_z
sz和tz两个参数
当
z
=
z
n
e
a
r
z=z_{near}
z=znear时,
z
n
h
=
−
z
n
e
a
r
z_{nh}=-z_{near}
znh=−znear, 当
z
=
z
f
a
r
z=z_{far}
z=zfar时,
z
n
h
=
z
f
a
r
z_{nh}=z_{far}
znh=zfar,由此,有
z
n
e
a
r
s
z
+
t
z
=
−
z
n
e
a
r
z
f
a
r
s
z
+
t
z
=
z
f
a
r
z_{near}s_z+t_z = -z_{near} \\ z_{far}s_z + t_z = z_{far}
znearsz+tz=−znearzfarsz+tz=zfar
可解得
s
z
=
z
f
a
r
+
z
n
e
a
r
z
f
a
r
−
z
n
e
a
r
s_z = \frac{z_{far}+z_{near}}{z_{far}-z_{near}}
sz=zfar−znearzfar+znear
t
z
=
−
2
z
f
a
r
z
n
e
a
r
z
f
a
r
−
z
n
e
a
r
t_z = -\frac{2z_{far}z_{near}}{z_{far}-z_{near}}
tz=−zfar−znear2zfarznear
在游戏引擎中,一般不直接定义
w
n
e
a
r
和
h
n
e
a
r
w_{near}和h_{near}
wnear和hnear,而是通过设置视角的上下张角
θ
θ
θ和屏幕的长宽比
a
s
p
e
c
t
aspect
aspect来实现。
c
o
t
θ
2
=
2
z
n
e
a
r
h
n
e
a
r
cot\frac{\theta}{2} = \frac{2z_{near}}{h_{near}}
cot2θ=hnear2znear
a
s
p
e
c
t
=
w
n
e
a
r
h
n
e
a
r
aspect = \frac{w_{near}}{h_{near}}
aspect=hnearwnear
因此最终的将摄像机坐标下的物体转换到规范化坐标下的转换矩阵为
M
n
h
=
[
c
o
t
θ
2
a
s
p
e
c
t
0
0
0
0
c
o
t
θ
2
0
0
0
0
z
f
a
r
+
z
n
e
a
r
z
f
a
r
−
z
n
e
a
r
−
2
z
f
a
r
z
n
e
a
r
z
f
a
r
−
z
n
e
a
r
0
0
1
0
]
M_{nh} = \begin{bmatrix} \frac{cot\frac{\theta}{2}}{aspect }&0&0&0\\ 0&cot\frac{\theta}{2}&0&0\\ 0&0&\frac{z_{far}+z_{near}}{z_{far}-z_{near}}&-\frac{2z_{far}z_{near}}{z_{far}-z_{near}}\\ 0&0&1&0 \end{bmatrix}
Mnh=⎣⎢⎢⎢⎡aspectcot2θ0000cot2θ0000zfar−znearzfar+znear100−zfar−znear2zfarznear0⎦⎥⎥⎥⎤
参考文献
[1] Donald Hearn, M.Pauline Baker, Warren R. Carithers.《计算机图形学(第四版)》
[2] 冯乐乐.《UnityShader入门精要》