【Ray Tracing in One Weekend 超详解】 光芒追踪1-9 景深


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

 

 

本日我们来学末了一章

 

 Chapter11:Defocus Blur

 

 

 Preface

散焦隐约 也称 景深

 

起首,我们来相识一下散焦隐约,我们在实在相机中散焦隐约的缘由是由于它们须要一个大圈(而不仅仅是一个针孔)来聚光。这会使统统东西都散焦,然则若是用小孔的话,那末经由历程前后调解相机镜头,就会使得统统景致都邑聚焦到相机镜头中,也就是会会聚到谁人孔内。物体聚焦的谁人平面的间隔由镜头和胶片/传感器之间的间隔掌握。这就是为何当你转变核心时能够看到镜头相对相机挪动的缘由。

光圈是一个能够有用掌握镜头巨细的孔。关于真正的相机,若是你须要更多光芒,你能够使光圈更大,同时也会取得更多的散焦隐约。关于我们的假造相机,我们也须要一个光圈

真正的相机具有庞杂的复合镜头。关于我们的代码,我们能够模仿递次:传感器,然后是镜头,然后是光圈,并找出发送光芒的地位并在盘算后翻转图象(图象在胶片上颠倒投影)。人们一般运用薄透镜模仿近似。

援用书上一张图(相机聚焦成像)

我们不须要这么庞杂,我们一般从镜头外面最先射线,并将它们发送到假造胶片平面,要领是找到胶片在核心平面上的投影(在间隔focus_dist处)。

 

 正文

前面说了一大堆,看着比较庞杂,实在并没有那末难

媒介说了三件事变:

第一点,生涯中的相机成像分为两个局部,inside和outside,触及3个物:film(胶片)、lens(镜片)、focusPlane(核心平面),而我们只须要outside局部

其次第二点,我们的眼睛(或许相机)不再是一个点而是眼睛地点的四周圆盘上的随机点,由于现实的相机是有摄像镜头的,摄像镜头是一个大光圈(很大一个镜片),并非针孔类的东东,以是,我们要模仿镜头,就要随机采针孔四周的光圈点。

能够有人不明白这里,能够归去看看1-3

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-

看一下这张图

这是之前我们讲的光芒追踪的成像历程,从eye最先发射视线,这个扫描屏幕中的每一个点,若是中央被物体遮挡,那末盘算,盘算以后的像素值为屏幕上该点的像素值,若是没有遮挡,那末屏幕上谁人点的像素值就是配景对应的值

我们这里只不过是把eye变成四周单元圈内的随机点,仅此模仿现实相机镜头

第三点,这个应该是上一章节提到的题目:

上一章节我们说了,为了轻易,上一章节假定成像平面位于z = -1(或许是-w平面,按w基向量算)

以是 tan(theta/2) = (h/2) / dis ,个中dis为1

而这一章,我们使dis真正变成了一个变量,即:焦距(镜片到成像平面之间的间隔)

(图片来自百度百科:)

 随之,我们的成像平面也就到了z = -focus,或许是-focus * w平面(按w基向量算)

 

以是,组织函数,我们就须要加两个参数,改两行行便可

 

另有就是单元圆盘取随机点函数

const rtvec random_unit_disk()            //find a random point in unit_disk
    {
        rtvec p;
        do
        {
            p = 2.0*rtvec(rtrand01(), rtrand01(), rtrand01()) - rtvec(1, 1, 0);
        } while (dot(p, p) >= 1.0);
        return p;
    }

 

下面是统统的camera类

/// camera.h

// -----------------------------------------------------
// [author]        lv
// [begin ]        2019.1
// [brief ]        the camera-class for the ray-tracing project
//                from the 《ray tracing in one week》
// -----------------------------------------------------

#ifndef CAMERA_H
#define CAMERA_H

#include "ray.h"

namespace rt
{

class camera
    {
public:
    camera(rtvec lookfrom, rtvec lookat, rtvec vup, rtvar vfov, rtvar aspect, rtvar aperture, rtvar focus)
        :_eye(lookfrom)
        ,_lens_radius(aperture/2)
    {
        rtvar theta = vfov * π / 180;
        rtvar half_height = tan(theta / 2) * focus;        //tan(theta/2) = (height/2) / 焦距
        rtvar half_width = aspect * half_height;
        _w = (lookfrom - lookat).ret_unitization();
        _u = cross(vup, _w).ret_unitization();
        _v = cross(_w, _u);

        //向量运算
        _start = _eye - half_width * _u - half_height * _v - focus * _w;//高和宽都乘了焦距,w也要乘,否则公式是错的
        _horizontal = 2 * half_width * _u;
        _vertical = 2 * half_height * _v;
    }

    inline const ray get_ray(const rtvar u,const rtvar v)const
        {
            rtvec rd = _lens_radius * random_unit_disk();
            rtvec offset = _u * rd.x()   _v * rd.y();
            return ray{ _eye   offset, _start   u*_horizontal   v*_vertical - (_eye   offset) };
        }

    inline const ray get_ray(const lvgm::vec2<rtvar>& para)const
        {    return get_ray(para.u(), para.v());    }

    inline const rtvec& eye()const { return _eye; }

    inline const rtvec& start()const { return _start; }

    inline const rtvec& horizontal()const { return _horizontal; }

    inline const rtvec& vertical()const { return _vertical; }

    inline const rtvec& u()const { return _u; }

    inline const rtvec& v()const { return _v; }

    inline const rtvec& w()const { return _w; }

    inline const rtvar lens_r()const { return _lens_radius; }

private:
    rtvec _u;

    rtvec _v;

    rtvec _w;

    rtvec _eye;

    rtvec _start;        //left-bottom

    rtvec _horizontal;

    rtvec _vertical;

    rtvar _lens_radius;  //the radius of lens

    };

}

#endif
camera.h

 

以是,我们用上一章的球体设置,把相机改一下,衬着一把

 

衬着结果就是开篇那张图

 

 晚安

 

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。