This is a small extension to the previous post. We will add a depth of field simulation to our path tracer project. I ran across this algorithm at this site. Below is a render of our path tracer with the depth of field extension.

Essentially, we will define the distance to the focal plane and a blur radius. For each primary ray we find its intersection with the focal plane, \(\vec{p}\), and jitter the ray origin by an amount, \(\vec{d}\). We then define the new ray direction as \(\vec{r}=\vec{p}-\vec{d}\). Consequently, objects on the focal plane will appear in focus. Below is the addendum to the kernel() function.
__vector dir = __vector(x - width / 2, -y + height / 2, 0 + width) + offset;
__ray ray = { __vector(0, 0, 0), dir.unit() };
u1 = rand_device[i*width*height*3+index+1];
u2 = rand_device[i*width*height*3+index+2];
r1 = 2 * M_PI * u1;
r2 = u2;
offset = __vector(cos(r1)*r2, sin(r1)*r2, 0.0) * blur_radius;
__vector p = ray.origin + dir * (focal_distance / width);
ray.origin = ray.origin + offset;
ray.direction = (p - ray.origin).unit();
Again, don't forget to update the Makefile to reference the proper locations for the libcudart.so and libcurand.so libraries.
Download the updated project: pathtracer_dof.tar.bz2


