Wed Aug 21 2013

## FSharp Raytracer Part 2 - Spheres

If our naive plan for raytracing is simply "find the intersection of each object with our ray" we still need to write a function that intersects a ray with a sphere. One very valuable compilation of intersection algorithms is the Real-time Rendering website (which has a very excellent companion book).

A Sphere is all the points that are some distance R away from a center point. A ray is the locus of points `origin + t * direction` for all `t > 0`. Thus, we can substitute the ray equation (`point(t) = ray.origin + t * ray.direction`) into the circle equation (`| point - center | = radius`) to get `|rayOrigin - center + t * rayDirection| = radius`. This produces a quadratic equation in `t` that we can use the quadratic formula to solve.

``````// solving for t after expanding combined ray and circle equations.
A = |rayDirection|^2
B = 2 * (rayDirection . (rayOrigin - center))
C = |(rayOrigin - center)|^2 - radius ^ 2
A * t^2 + B * t + C = 0
``````

Full intersection code:

``````let raysphere pos, r, ray =
let RC = ray.Pos - pos
let A = ray.Dir.LengthSquared
let B = dot (2.0f * ray.Dir) RC
let C = RC.LengthSquared - r * r
let disc = B*B - 4.0f * A * C
if disc < 0.0f then None // no intersection
else
// we only take the negative root here so we only take the near (front) point
let t = (-B-sqrt(disc))/2.0f/A
if t < 0.0f then None // sphere is behind camera
else
let point = t * ray.Dir + ray.Pos
let normal = Vector3.Normalize(point - pos)
Some({ time = t; point = point; normal = normal; shape = this })
``````

Now that we have a good way of detecting intersections, we need to figure out a good way to decide what color the intersection point should be rendered as. For the next post, I'll talk about one of the most popular and simple shaders out there: Phong shading. For now, we can write a dummy shader that just dumps a random color based on the hash of the object:

``````let dummyShade intersection =
let n = intersection.shape.GetHashCode()
Vector3(n / 100.f % 1.f, n / 1000.f % 1.f, n / 10000.f % 1.f)
``````

And here is the result, in all its glory: Full code for this section

Up next: Phong shading! So our spheres look a little bit more 3D.