RTIOW-ch10:Positionable camera

我们的相机之前一直都是固定死的,这次让我们来做些改变,让我们使用一个可调整的视野(fov)。

先看一下我们之前是如何设置camera的:

特别需要注意的是,这是在z=-1的平面上。
当时是这么说的:已知Z=-1平面上四点的坐标,我们可以求出下面三个值。

  •        vec3 lower_left_corner(-2.0, -1.0, -1.0);
  •        vec3 horizontal(4.0, 0.0, 0.0);
  •        vec3 vertical(0.0, 2.0, 0.0);

然后,光线和平面的交点坐标可以表示为向量:lower_left_corner + u*horizontal + v*vertical。这个即为光线的方向向量。

 

我们要重新配置camera,引入张角 theta 和画面宽高比 aspect:

设整个画面的高为 height,则半高为 half_height,宽为 width,半宽为 half_width。

half_height = tan(theta/2)
half_width = aspect * half_height

所以:

在运算时,theta一般用的是弧度,而我们在给函数设置参数时使用角度更为方便。所以,引入角度vfov=theta*180/M_PI(即,theta = vfov * M_PI/180)。ofov有个专业的名称:fieldof view

 

对于任意观测点,我们称:
放相机的位置为lookfrom,我们看的点(画面中心点)为lookat,相机的倾斜方向为view up (简称vup,一般设置为(0,1,0))

有了这三个东东,我们现在就要找出相机在任意点的标准正交基(也就是相机要建立自己的坐标系,然后在自己的坐标系看之前坐标系的物体)。

w = unit_vector(lookfrom – lookat)(w相当于z)
u = unit_vector(cross(vup, w))(u相当于x)
v = cross(w, u)(v相当于y)

w为什么相当于z?这个是由放相机的位置(lookfrom)和目标点(lookat)确定的。
u为什么相当于x?因为相机倾斜方向vup和y比较接近,所以vup和w叉乘之后就是x。
v为什么相当于y?z、x都确定了,还有的选么?另外,w和u的叉乘相当于z、x的叉乘,结果也是y。

 

camera.h:

cpp:

设置fov为60度时,效果如下:

设置fov为90度时,效果如下:

 

参考链接:https://blog.csdn.net/libing_zeng/article/details/54560334

参考书籍:《Ray Tracing in One Weekend》

RTIOW系列项目地址:GitHub

RTIOW系列笔记:

RTIOW-ch1:Output an image

RTIOW-ch2:The vec3 class

RTIOW-ch3:Rays, a simple camera, and background

RTIOW-ch4:Adding a sphere

RTIOW-ch5:Surface normals and multiple objects

RTIOW-ch6:Antialiasing

RTIOW-ch7:Diffuse Materials

RTIOW-ch8:Metal

RTIOW-ch9:Dielectrics

RTIOW-ch10:Positionable camera

RTIOW-ch11:Defocus Blur

RTIOW-ch12:Where next