Ray Tracing The Next Week:chapter 1:运动模糊

Ray Tracing The Next Week:chapter 1:运动模糊

文章翻译

  当你决定光线追踪时,你觉得程序运行时,视觉质量更有价值。在你的镜面模糊反射和离焦模糊中,每个像素你需要多个样本。一旦你走下了这条路,好消息是几乎所有影响都是强制性的,运动模糊当然是其中之一。在真实的相机中,遮光器打开并在一个时间间隔里保持打开状态,相机和物体可能在那段时间内移动了。相机在那段间隔里所看到的是一个平均值,这是我们想要的。在遮光器开启时,我们可以通过在一段随机时间内发送几束光线来得到随机估计。只要这些物体在那段时间在它们该在的地方,我们可以用恰好在一次时间内的射线来得到正确的平均答案,这就是随机光线追踪为什么很简单的根本原因。
  最基础的想法是,在遮光器开启的那段随机时间里产生光线,并在某时刻与模型交互。经常做的方法是,让相机和物体移动,但是在某时刻只有一束光线确切存在。用这种方法的引擎只需要确认,对于光线来说,这些物体的位置在哪,交互的内容没有太大改变。
  为了实现这个,我们将首先让光线存储时间,实现如下:

ray.h

#include "vec3.h"
#pragma once

class ray 
{
public:
    ray();
    ray(const vec3 &a, const vec3 &b, float ti = 0);
    vec3 origin() const;
    vec3 direction() const;
    vec3 piont_at_parameter(float t) const;
    float time() const;

public:
    vec3 A;
    vec3 B;
    float _time;
};

ray.cpp

#include "ray.h"
ray::ray()
{
    
}

ray::ray(const vec3 &a, const vec3 &b, float ti = 0)
{
    this->A = a;
    this->B = b;
    this->_time = ti;
}
vec3 ray::origin() const
{
    return A;
}
vec3 ray::direction() const
{
    return B;
}
vec3 ray::piont_at_parameter(float t) const
{
    return A + B * t;
}

float ray::time() const
{
    return _time;
}

  现在我们需要修改相机,让其在 time1time2 这段时间内随机产生光线,相机应该跟踪 time1time2,还是在光线创建时由相机用户决定?由疑惑的时候,如果能让函数调用变得简单,我通常让构造器变得更复杂一些,因此我将让相机保持跟踪,当然这是个人的偏好。相机不需要有太多的变动,因为它现在还不允许移动;它仅在某段时间间隔内发送光线。

camera.h

#include "ray.h"
#pragma once


class camera
{
public:
    camera();
    camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist, float t0, float t1);

    ray get_ray(float u, float v);

public:
    vec3 origin;
    vec3 lower_left_corner;
    vec3 horizontal;
    vec3 vertical;
    vec3 u, v, w;
    float time0, time1;
    float lens_radius;
};

camera.cpp

#include "camera.h"
#include "ray.h"
#define M_PI 3.14159265358979323846
#include <math.h>



camera::camera(vec3 lookfrom, vec3 lookat, vec3 vup, float vfov, float aspect, float aperture, float focus_dist, float t0, float t1)
{
    time0 = t0;
    time1 = t1;
    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 * u * focus_dist - half_height * v * focus_dist - w * focus_dist;
    horizontal = 2 * half_width * u * focus_dist;
    vertical = 2 * half_height * v * focus_dist;
}


ray camera::get_ray(float s, float t)
{
    vec3 rd = lens_radius * random_in_unit_disk();
    vec3 offset = u * rd.x() + v * rd.y();
    float time = time0 + drand48() * (time1 - time0);
    return ray(origin + offset, lower_left_corner + s * horizontal + t * vertical - origin - offset, time);
}

camera::camera()
{

}

  我们也需要一个移动中的物体,我们将创建一个球类,可以让其中心点线性地从 center0 移动到 center1,分别在 time0time1 时刻。在时间间隔之外,它会继续,所以这些时间不需要和相机光圈启闭相匹配。

moving_sphere.h

#pragma once
#include "vec3.h"
#include "material.h"


class moving_sphere:public hitable
{
public:
    moving_sphere();
    moving_sphere(vec3 cen0, vec3 cen1, float t0, float t1, float r, material *m);
    virtual bool hit(const ray &r, float tmin, float tmax, hit_record &rec) const;
    vec3 center(float time) const;

public:
    vec3 center0, center1;
    float time0, time1;
    float radius;
    material *mat_ptr;
};

moving_sphere::moving_sphere(vec3 cen0, vec3 cen1, float t0, float t1, float r, material *m)
{
    this->center0 = cen0;
    this->center1 = cen1;
    this->time0 = t0;
    this->time1 = t1;
    this->radius = r;
    this->mat_ptr = m;
}

moving_sphere::vec3 center(float time) const
{
    return center0 + ((time - time0) / (time1 - time0)) * (center1 - center0);
}

  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值