[42cursurs]Ray Tracing in One Weekend 12-Defocus Blur

이상헌·2020년 10월 26일
0
post-thumbnail

마지막 기능으로 Blur 효과를 만들어 보자. Blur는 이미지를 흐리게 하는 효과다. 원문은 반영하고자하는 현실의 카메라에서 일어나는 현상을 설명한다. 하지만 저걸 다 구현할 게 아니므로 목표인 Blur를 위해 필요한 것만 챙기자.

  1. Blur, 즉 이미지를 흐릿하게하는 효과를 구현할 거다.
  2. Blur를 구현하기 위해 현실의 카메라 구조 일부를 구현한다.

A Thin Lens Approximation

실제 카메라 모델의 이미지다. 우리는 저기서 필요한 일부만 채용한다.

Figure 17: Camera lens model
아래의 이미지처럼 구현할 거다.
Figure 18: Camera focus plane
Blur효과 자체는 결국 이미지가 흐릿하게 보이면 된다.
1. 고정되있던 광원을 lens에서 빛을 쏘는 것처럼 일정범위에서 무작위로 선정해서 광선을 쏜다.
2. 광선의 방향 벡터는 같으니 광원을 고정했을 때 닿았을 지점의 근방의 어뚱한 지점에 닿게 된다.
3. 이렇게 어뚱한 지점에 닿는 경우와 원래 닿았을 사물의 색상을 칠하는 경우가 섞이면 모자이크 처럼 이미지가 흐릿해진다.
우리는 이 아이디어로 Blur효과를 구현할 것이다.

Generating Sample Rays

Blur를 위해 무작위로 광원을 변경하는 반경이 넓을수록 Blur를 강하게 줄 수 있다.

vec3.h

vec3 random_in_unit_disk() {
    while (true) {
        auto p = vec3(random_double(-1,1), random_double(-1,1), 0);
        if (p.length_squared() >= 1) continue;
        return p;
    }
}

camera.h

class camera {
    public:
        camera(
            point3 lookfrom,
            point3 lookat,
            vec3   vup,
            double vfov, // vertical field-of-view in degrees
            double aspect_ratio,
            double aperture,
            double focus_dist
        ) {
            auto theta = degrees_to_radians(vfov);
            auto h = tan(theta/2);
            auto viewport_height = 2.0 * h;
            auto viewport_width = aspect_ratio * viewport_height;

            w = unit_vector(lookfrom - lookat);
            u = unit_vector(cross(vup, w));
            v = cross(w, u);

            origin = lookfrom;
            horizontal = focus_dist * viewport_width * u;
            vertical = focus_dist * viewport_height * v;
            lower_left_corner = origin - horizontal/2 - vertical/2 - focus_dist*w;

            lens_radius = aperture / 2;
        }


        ray get_ray(double s, double t) const {
            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
            );
        }

    private:
        point3 origin;
        point3 lower_left_corner;
        vec3 horizontal;
        vec3 vertical;
        vec3 u, v, w;
        double lens_radius;
};

main.cc

point3 lookfrom(3,3,2);
point3 lookat(0,0,-1);
vec3 vup(0,1,0);
auto dist_to_focus = (lookfrom-lookat).length();
auto aperture = 2.0;

camera cam(lookfrom, lookat, vup, 20, aspect_ratio, aperture, dist_to_focus);

아래와 같은 이미지를 출력한다. Blur효과는 뷰포트에 가까울수록 Blur효과가 약하게 난다. 사물이 뷰포트에 가까울수록 광선이 무작위로 생성된 전후에 닿은 사물의 오차가 적기 때문이다.

Image 20: Spheres with depth-of-field

profile
배고픈 개발자 sayi입니다!

0개의 댓글