A basic sphere
As someone with a nontraditional background in software engineering, I often have to do some projects to demystify terms like “ray tracing”, which I previously knew was related to ✨graphics✨ and rays.
Turns out, ray tracing is effectively an approximation technique that can be used to model how our eyes or a camera perceives a 3D world in a 2D representation. Or in simpler words, ray tracing is a technique to take a photo of a scene.
Interestingly, ray tracing runs “in reverse” of the real world. In the real world, light rays are emitted from sources like the Sun, illuminating a scene and registering a projected image through our eyes and interpreted by our minds. Ray tracing on the other hand, emits rays from the eye/camera position and fills in color as the rays hit or bounce to other objects. We could model it the same way as the real world, but the calculations required would be astronomically large - so instead of calculating for every eye/camera viewpoint, we simply focus on the one we care about.
A basic sphere, but with some rough antialiasing
If you’ve ever had a moment in your high school math classes where you questioned why you needed to learn such complex topics - I’m with you. I distinctly remember thinking rays or matrix multiplication doesn’t exist in the real world. I even remember some STEM outreach brochures that detailed the kinds of jobs that would use such knowledge, none of which I found appealing. Decades later, I’m once again refreshing myself on these formulas and calculations. It just goes to show that everything you learn always has a way of becoming useful one day.
Adding rays that bounce. Note the shadow under the sphere.
Single threaded performance
Multi threaded (8) performance
There are many optimizations for graphics but parallel processing is an important tool since we’re really just doing the same computations across each of one million pixels in our scene. In a single thread with my laptop CPU, it took ~1.6 s to render each row of the final scene. Multithreaded (8) performance went down to ~0.5 s for each row.
It’s beyond the scope of this project but another important optimization would be to reduce the search space for sphere hits. Right now it’s a horribly inefficient linear search over ~500 spheres for every ray bounce.
Adding different (reflective) color sampling behavior for ray bounces.
There’s a lot of topics to reacquaint myself with or to learn on the Rust side. So I implemented this project with Rust.
Rc
and the atomically safe Arc
.