【Ray-Tracing In One Weekend】第10章 定义相机

【简介与代码下载】

本节在上一节的基础上定义了相机,可以定义视点、朝向等。效果如下:

【Ray-Tracing In One Weekend】第10章 定义相机

代码下载:

链接:https://pan.baidu.com/s/1kh7HxWxuxhuti-Xo5OZPfQ 
提取码:ak4x 
 

【相机实现】

对于相机来说,有几个变量来确定,一个是相机的位置lookfrom,也叫eye,一个是相机朝哪里看是lookat,也叫center,一个是像机向上的角度up,比如虽然你眼睛看向一个方向,此时eye, center都确定了,但是你还可以沿着鼻子转动脑袋。这就是由up来决定的。正常的情况下我们可以定义up是向上的,也即(0, 1, 0),也可以定义成其它的。

对于相机还有个参数是长宽比率aspect,是相机视域的长与宽的比,还一个参数是角度fov,相当于你眼睛慢慢闭,角度就越来越小,看的范围就小了。

理想了相机的这么多的定义之后我们来看图:

【Ray-Tracing In One Weekend】第10章 定义相机

我们现在要求出相机的局部坐标的正交基,也即其局部坐标系的UVW,W很好求,eye-center就有了。其次UP和V以及W都在同一个平面上,因此W好求,UP已知,两个求cross就得出了U,然后U再与Wcross就得到了V。

有了正交基我们就确定了相机的左、右、前方向。那么相机的视域怎么求呢,

【Ray-Tracing In One Weekend】第10章 定义相机

蓝色的线就是眼睛睁多大,角度是【Ray-Tracing In One Weekend】第10章 定义相机,对于方向性的东西来说,距离是无所谓的,默认为1,因此float half_height = tan(theta / 2);而长宽比已知float half_width = aspect * half_height;。

视点的位置减去半宽*U, 半高*V就是左下角,再拉开个距离W就是视平面了。

具体代码如下:

class camera
{
    public:
        camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect)
        {
            vec3 u, v, w;
            float theta = float(vfov * M_PI / 180);
            float half_height = tan(theta / 2);
            float half_width = aspect * half_height;
            origin = lookfrom;
            w = unit_vector(lookfrom - lookat);
            u = unit_vector(cross(vup, w));
            v = cross(w, u);
            lower_left_corner = origin - half_width * u - half_height * v - w;
            horizontal = 2 * half_width*u;
            vertical = 2 * half_height * v;
        }

        ray get_ray(float u, float v)
        {
            return ray(origin, unit_vector(lower_left_corner + u*horizontal + v*vertical - origin));
        }
        
        vec3 origin;
        vec3 lower_left_corner;
        vec3 horizontal;
        vec3 vertical;
};

构造camera我们可以使用如下语句:

camera cam(vec3(-1.5f, 1.5f, 0.5f), vec3(0, 0, -1), vec3(0, 1, 0), 60, float(nx)/float(ny));