问题二十八:ray tracing中的散焦模糊(defocus blur)

来源:互联网 发布:华为云数据 编辑:程序博客网 时间:2024/05/15 02:06

 “散焦模糊”在摄影上又称“景深”。

在现实的相机中,我们需要做“散焦模糊”的原因是:我们需要一个更大的孔来收集光线增加图片的亮度(而不是“针孔”)。我们称“更大的孔”为“光圈”。

For a real camera, if you need more light,you make the aperture bigger, and will get more defocus blur.

For our virtual camera, we can have aperfect sensor and never need more light, so we only have an aperture when wewant defocus blur.

 

光圈的增大,导致图片出现散焦而模糊。

但是我们可以调节成像的位置,改变图片的清晰度,使图片在当前光圈条件下尽可能清晰。

 

所以,接下来,我们会引入两个参数:aperture(光圈)和focus_dist(成像位置)。

 

关于成像位置,

在原点的标准正交基e1 = (1, 0, 0), e2 = (0, 1, 0), e3 = (0, 0, 1)的坐标系,成像位置之前被设置在- e3平面(即z=-1的平面);

在任意点的标准正交基u,v,w的坐标系,成像位置之前被设置在-w平面。

引入参数focus_dist之后,成像位置将会是-focus_dist* e3 或者-focus_dist*w平面。图片的高宽都需要乘以参数focus_dist.


关于光圈,


看code的改变吧:

----------------------------------------------camera.h------------------------------------------

camera.h

#ifndef CAMERA_H#define CAMERA_H#include "ray.h"vec3 random_in_unit_disk();class camera{    public:        camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist) { // vfov is top to bottom in degrees            lens_radius = aperture / 2;            float theta = 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*focus_dist*u - half_height*focus_dist*v -focus_dist*w;            horizontal = 2*half_width*focus_dist*u;            vertical = 2*half_height*focus_dist*v;        }        ray get_ray(float s, float t) {            vec3 rd = lens_radius*random_in_unit_disk();            vec3 offset = u * rd.x() + v * rd.y();            return ray(origin + offset, lower_left_corner + s*horizontal + t*vertical - origin - offset);        }        vec3 origin;        vec3 lower_left_corner;        vec3 horizontal;        vec3 vertical;        vec3 u, v, w;        float lens_radius;};#endif // CAMERA_H


----------------------------------------------camera.cpp------------------------------------------

camera.cpp


#include "camera.h"vec3 random_in_unit_disk() {/*在z=0平面上产生一个“起点在原点,长度小于1,方向随机”的向量。为什么是z=0平面,这个和相机的倾斜方向有关。(相机的倾斜方向为view up (简称vup,一般设置为(0,1,0)))*/    vec3 p;    do {        p = 2.0*vec3((rand()%(100)/(float)(100)), (rand()%(100)/(float)(100)), 0) - vec3(1,1,0);    } while (dot(p,p) >= 1.0);    return p;}

贴一张书上产生的图片。

----------------------------------------------main.cpp------------------------------------------

main.cpp

        hitable *list[5];        list[0] = new sphere(vec3(0,0,-1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5)));        list[1] = new sphere(vec3(0,-100.5,-1), 100, new lambertian(vec3(0.8, 0.8, 0.0)));        list[2] = new sphere(vec3(1,0,-1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0));        list[3] = new sphere(vec3(-1,0,-1), 0.5, new dielectric(1.5));        list[4] = new sphere(vec3(-1,0,-1), -0.45, new dielectric(1.5));        hitable *world = new hitable_list(list,5);        vec3 lookfrom(3,3,2);        vec3 lookat(0,0,-1);        float dist_to_focus = (lookfrom - lookat).length();        float aperture = 2.0;        camera cam(lookfrom, lookat, vec3(0,1,0), 20, float(nx)/float(ny), aperture, dist_to_focus);

结果图片如下:




4 0
原创粉丝点击