마지막 기능으로 Blur 효과를 만들어 보자. Blur는 이미지를 흐리게 하는 효과다. 원문은 반영하고자하는 현실의 카메라에서 일어나는 현상을 설명한다. 하지만 저걸 다 구현할 게 아니므로 목표인 Blur를 위해 필요한 것만 챙기자.
실제 카메라 모델의 이미지다. 우리는 저기서 필요한 일부만 채용한다.
Blur를 위해 무작위로 광원을 변경하는 반경이 넓을수록 Blur를 강하게 줄 수 있다.
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;
}
}
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;
};
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효과가 약하게 난다. 사물이 뷰포트에 가까울수록 광선이 무작위로 생성된 전후에 닿은 사물의 오차가 적기 때문이다.