很多类似的问题,实际多是对原理的理解存在偏差导致的。这里的话,主要是指坐标空间的混淆。
细心的朋友们应该发现了:作业6和作业7中的void Renderer::Render(const Scene&)中的相机光线向量dir: Vector3f有些许差别:
作业6:Vector3f dir = normalize(Vector3f(x, y, -1));
作业7:Vector3f dir = normalize(Vector3f(-x, y, 1));
不知道大家当时的情况是不是和笔者一样的:做作业6时还觉得这个给定的dir非常合理,推导后发现确实没问题;到作业7时,发现相机发出的光线方向dir有所不同——“除了y,其余都取反了”,一时半会没想清楚怎么来的,甚至觉得是提供的代码错了,但拿已经跑通的代码试的时候,发现这样的dir才是对的,因而很费解。
现在看来,这个疑惑的根源在于,我对于光线追踪原理以及相机空间的理解存在问题,这篇文章解开了我的困惑:
我把光栅化和光线追踪的部分概念弄混了:两者都可视为场景中的对象映射到2D图像各像素的函数;光栅化需要进行MVP变换,而光线追踪是在世界空间中进行计算,不需要进行P变换,且需要进行V变换的逆变换,将像素的相机坐标转变为世界坐标,M变换则通常隐含在模型文件中。观察光线追踪相关作业的代码框架,会发现没有MVP变换的代码。
我错误地认为,光线追踪过程是在相机空间中的过程。实际上,光线追踪发出的射线以及后续的追踪计算,都是相对世界坐标系而非相机坐标系而言的,而作业6、7中我们进行了从屏幕空间到相机空间的变换,进而获得了相机到某像素的向量 ( x , y , − 1 ) (x, y, -1) (x,y,−1),这一步的射线向量仍然在相机空间中,我们还需要将它转化为世界坐标系下的向量,做一个相机空间到世界空间的变换,即对相机进行旋转和平移。
我们知道,按照课程中的约定,View变换后相机的Gaze方向指向z轴负方向,Up方向指向y轴正方向,Right方向指向x轴正方向,这里所谓的z轴、y轴和x轴,即相机坐标系的轴向。之所以在此提这个,是想提醒一下Gaze方向并非相机坐标系的轴正向,所谓相机朝-z轴看去,这里的z轴是相机坐标系的z轴,而非世界坐标系。
结合上述新认识,我们现在知道:作业6和7中dir向量不相同的原因在于:相机在世界空间中的摆放不一致(包括位置和方向,这里的影响因素是方向)。我们现在已知像素中心的屏幕坐标 ( x , y ) (x,y) (x,y)对应在相机空间中的位置为 ( x , y , − 1 ) (x,y,-1) (x,y,−1),相机空间的相机位于原点 ( 0 , 0 , 0 ) (0,0,0) (0,0,0),因而相机到某像素的射线向量为 ( x , y , − 1 ) (x,y,-1) (x,y,−1),这个在相机空间中是一致的,而我们现在知道作业6中的dir向量的世界坐标为 ( x , y , − 1 ) (x,y,-1) (x,y,−1),作业7中的dir向量的世界坐标为 ( − x , y , 1 ) (-x,y,1) (−x,y,1),相当于已知输入和输出向量,我们可以反求出相机空间到世界空间的变换矩阵。
假设相机的世界坐标为 ( x e , y e , z e ) (x_e,y_e,z_e) (xe,ye,ze)。
作业6:
[
?
?
?
x
e
?
?
?
y
e
?
?
?
z
e
0
0
0
1
]
c
a
m
_
t
o
_
w
o
r
l
d
(
x
y
−
1
0
)
=
(
x
y
−
1
0
)
不难解得:
M
c
a
m
_
t
o
_
w
o
r
l
d
_
H
W
6
=
[
1
0
0
x
e
0
1
0
y
e
0
0
1
z
e
0
0
0
1
]
M_{cam\_to\_world\_HW6} =
这说明作业6中的相机LookAt方向对准世界坐标系的-z轴(注意LookAt指向相机坐标z轴的负向),Up方向对准世界坐标系的y轴,Right方向对准世界坐标系的x轴,结合作业6中相机与场景对象的位置情况(相机位置Vector3f eye_pos(-1, 5, 10);,场景对象顶点信息见.obj文件),相机向z轴负向看去,emm,合理。
作业7:
[
?
?
?
x
e
?
?
?
y
e
?
?
?
z
e
0
0
0
1
]
c
a
m
_
t
o
_
w
o
r
l
d
(
x
y
−
1
0
)
=
(
−
x
y
1
0
)
不难解得:
M
c
a
m
_
t
o
_
w
o
r
l
d
_
H
W
7
=
[
−
1
0
0
x
e
0
1
0
y
e
0
0
−
1
z
e
0
0
0
1
]
M_{cam\_to\_world\_HW7} =
这说明作业7中的相机LookAt方向对准世界坐标系的z轴,Up方向对准世界坐标系的y轴,Right方向对准世界坐标系的-x轴,结合作业7中相机与场景对象的位置情况(相机位置Vector3f eye_pos(278, 273, -800),场景对象顶点信息见.obj文件),相机向世界的z轴正向看去,emm,也合理。
由此可见,作业6和7中省略了相机射线从相机空间到世界空间的变换矩阵,直接把作用后的射线向量给出了,不过这也是因为这两次作业中相机的摆放基本和世界坐标系的轴对齐了。
但愿这篇记录能帮到你~(如有错误,欢迎各位大佬批评指正)