Ray Tracing Redux
19 Jan 2021 ∞
I’ve been meaning to revisit my ray tracing system for a while, but never really had the motivation to dive back in. The way I’d built it was fragile and prone to infinite loops. The infinite loops are what finally got me to take another look: recent changes I’d made caused several sketches to never resolve.
My original ray tracing system simply collected line segments from each object it intersected. One of the big "improvements" I made was allowing objects to be reevaluated so a single ray could interact with the same object multiple times. Unfortunately I accomplished this with a recursive method. The closest intersection was found, then the method would be called on the next object. All of the intersections would be collected at the bottom of the stack and passed back up when the ray finished its journey. If it finished its journey.
A Formal Ray
For the second (major) attempt I switched over to a real Ray
object to keep track of intersections. Another part of the code I updated was how a ray could be modified. A new RayTracable
protocol gives an object the chance to modify a Ray
directly, with the default to simply terminate it.
Once the new Ray
was set up I began testing and quickly noticed that my circle intersections were wrong. The point of deflection wasn’t actually on the perimeter of the circle. I eventually discovered that I hadn’t understood the t
value, which is used to find the point of intersection on the ray, correctly. I found an article which explained what I was missing and managed to fix the method.
Each time I conformed a shape to RayTracable
I’d find similar issues. After a spot of pest control I finally had a system that behaved correctly.
Putting it All Together
Once the math was taken care of I revisited my largest ray tracing sketch. I’d never set out to necessarily make a performant ray tracer, but it was exceptionally slow. Looking into the drawing code I found I was generating the paths for each drawn layer. A quick change to separate the calculations and the on-screen drawing helped a lot.
The final tweak I made was how I was rendering the layers. Before I’d updated the drawing code I ended up with a particularly nice sample render where the rays would pool into bright spots, which I then accidentally "fixed" and couldn’t replicate. Eventually I figured out the correct blend mode and drawing order to be able to control the effect to great success.