###1.三维物体的呈现过程
这里主要详细介绍投影转换及屏幕映射。
2.投影转换
当模型转换到相机空间时,便要对顶点进行裁剪处理,剔除那些不在视锥体之内的顶点。
视锥体的空间如下,包含一个近裁剪面和一个远裁剪面,以及一个视角角度Fov,视角屏幕的宽高比Aspect。
投影转换矩阵如下:
[
C
o
t
(
f
o
v
/
2
)
/
A
s
p
e
c
t
0
0
0
0
C
o
t
(
f
o
v
/
2
)
0
0
0
0
(
F
a
r
+
N
e
a
r
)
/
(
F
a
r
−
N
e
a
r
)
1
0
0
−
2
N
e
a
r
∗
F
a
r
/
(
F
a
r
−
N
e
a
r
)
0
]
\begin{bmatrix} Cot(fov/2)/Aspect&0&0&0\\ 0&Cot(fov/2)&0&0\\ 0&0&(Far+Near)/(Far-Near)&1\\ 0&0&-2Near*Far/(Far-Near)&0\end{bmatrix}
⎣⎢⎢⎡Cot(fov/2)/Aspect0000Cot(fov/2)0000(Far+Near)/(Far−Near)−2Near∗Far/(Far−Near)0010⎦⎥⎥⎤
投影转换矩阵主要是将x,y,z三个坐标规约化到[-w,w]之内,结合透视除法,将坐标转换到裁剪空间。
具体推到如下:
Y:对于坐标的y轴, t a n ( f o v / 2 ) = y / w tan(fov/2)=y/w tan(fov/2)=y/w,这里w=z;所以 − w ≤ y / t a n ( f o v / 2 ) ≤ w -w≤y/tan(fov/2)≤w −w≤y/tan(fov/2)≤w,令m21=cot(fov/2)即可。
X:根据宽高比,可以得到m11=cot(fov/2)/Aspect。
Z:对于z,可以联立方程求解
N
e
a
r
∗
m
33
+
m
43
=
−
N
e
a
r
Near*m33+m43=-Near
Near∗m33+m43=−Near
F
a
r
∗
m
33
+
m
43
=
F
a
r
Far*m33+m43=Far
Far∗m33+m43=Far
W:w用于记录z值,用作透视除法及后续纹理插值。
bool is_out_of_range(Vector3 v)
{
int check = 0;
if (v.z < -1.0f) check |= 1;
if (v.z > 1.0f) check |= 2;
if (v.x < -1.0f) check |= 4;
if (v.x > 1.0f) check |= 8;
if (v.y < -1.0f) check |= 16;
if (v.y > 1.0f) check |= 32;
return check>0;
}
完成透视除法后,根据如上算法,剔除不在视锥体内的节点。
3.屏幕映射
屏幕映射主要是将裁剪空间内的坐标映射成屏幕坐标,以显示到屏幕上。
[
w
i
d
t
h
/
2
0
0
0
0
−
h
e
i
g
h
t
/
2
0
0
0
0
1
0
w
i
d
t
h
/
2
h
e
i
g
h
t
/
2
0
1
]
\begin{bmatrix} width/2&0&0&0\\ 0&-height/2&0&0\\ 0&0&1&0\\ width/2&height/2&0&1\end{bmatrix}
⎣⎢⎢⎡width/200width/20−height/20height/200100001⎦⎥⎥⎤
由于windows中Y轴倒置,所以m22为负。
4.正方体
项目完整地址:
3DRender: https://github.com/zhanghuanzj/3DRender.git