One of the most computationally expensive things a ray tracer does is find the intersections between a ray and an object, and what makes things even worse is that it has to do this repeatedly for every pixel. To render a scene of ten objects to a small 200×200 canvas, your ray tracer must perform at least 400,000 intersection tests, plus however many additional intersections are needed to generate shadows, reflections, and refraction. Adding insult to injury, the majority of those rays won’t even come close to most of the objects in a typical scene.
What a waste, right? If only you could test just the objects that were reasonably close to any given ray…
The good news is that there are a variety of different techniques for teaching your ray tracer how to do this. They’re all a bit beyond the scope of this book, but let’s take a quick look at one of the least complicated: bounding boxes.
If that term seems familiar, it’s probably because you saw it used back in Chapter 12, Cubes, when the cubes were called axis-aligned bounding boxes (AABB). The idea behind this optimization is to use these cubes, or bounding boxes, to contain a group of other objects. Then, when intersecting the group with a ray, you first test the ray against the bounding box. If the ray misses, testing anything inside the box is pointless, because it would have to miss them as well.
The following figure illustrates this with a bounding box that contains three shapes. Since ray A misses the bounding box, there’s no need to see if it intersects any of the shapes inside it. However, because ray B does intersect the box, you’d need to try that ray against the shapes it contains.
I won’t walk you through this one, but give it a try anyway. Although implementing this definitely has some fiddly bits, I have faith in you! Here’s a basic outline of what you’ll need to do:
As an example of how much this technique can help, I put together the following scene of more than 280 marbles with glass and metallic textures:
Rendered without bounding boxes at 1200x600 pixels, this image required more than 1.8 billion intersection tests, of which only 1% ever actually hit anything. By using sixteen bounding boxes, though, and arranging them in a 4x4 grid so that all the marbles were covered, the render required only a bit more than 180 million intersection tests, with 10% hitting something. That’s an order of magnitude better, just by adding bounding boxes!
Here’s the caveat, though: as with any optimization, it’s not a guaranteed win in every situation. Not every scene will benefit from bounding boxes, and some might even see worse performance (depending on the objects in the scene and how you organize them).
Still, it’s a useful optimization, and it will earn its keep in the next chapter, Chapter 15, Triangles. Give it a shot!
18.223.106.100