【Ray-Tracing In One Weekend】第11章 景深

【简介与代码】

本文将实现景深的效果,也即给相机定义一个焦距,在这个焦距范围外的就模糊,在这个焦距处就清晰。

效果如下:

代码使用VS2015编译从如下下载:

链接:https://pan.baidu.com/s/1807dLqlfisxJO3Q9mNNdBQ 
提取码:xwbw 
 

【实现原理】

首先一改之前的由eye发出射线精准求交的方式:

这样求出来的光线非常准确。那么我们对光线的生成模拟相机的操作改成如下形式:

这里要好好的解释一下,对于一个像素实施光线追踪,为了反走样随机生成了100条光线然后求平均(在main函数里定义的100条光线),最终和到一个像素的值。那么这100条光线的走点我们让它随机分布在一个直径为aperture的圆上,聚焦点在离光线起点dist_to_focus的面上。那么我们可以得到如上图一样的结果,所以的光线在成像平面处交于一点。假如物体在呈像平面处,则会很精晰,假如靠前或靠后,都会模糊,因为100条光线与物体交的五花八门,而不是精确于一点了。假如物体在焦距处,则就是精确于一点的。这一点好好理解才能理解景深的光线生成代码:

        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, unit_vector(lower_left_corner + s*horizontal + t*vertical - origin-offset));
        }

这里是关键,假如无法理解,可以在下方留言。

随着dist_to_focus焦距的拉长,我们生成画面的范围也在扩大,这是在定义视域范围的时候定义的:

        camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist)
        {
            //光圈半径
            lens_radius = aperture / 2;

            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 *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;
        }

注意lower_left_color的生成方式,长宽都乘了个focus_dist。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值