Part 3: Adding Primitives

Performance Template

I've been busy since the last project. While too late for the last assignment, I've implemented multithreading and an integrated image viewer to allow me to watch the progress of the renders. One evening I also played around a bit with adding a fisheye lens and an NPR material shader.

Required Image

Here is the required image:

Image #3A

Creative Image

Here is the creative image:

Image #3B

The creative image shows the sinc function height-field. Note that it has been stretched - my ray tracer scales the heightfield to the dimension of the bounding box given. On top of that is a sphere surrounded by three intersecting rings. Behind them at a distance floats a disc. The heightfield was shaded with the blurry glossy shader (set to 5 reflection samples) from last time, while the other objects are perfectly reflective. (You can even see the proper two-sided lighting under the heightfield in its reflection in the disc.) The image was rendered at 768x768 with 4x4 jittered supersampling and filtered with a 1.2 pixel wide sinc.

Design Choices

I implemented the primitives more or less as described in class. For the triangles, I used the version presented in "Real-Time Rendering", which is basically equivalent to the one in class -- just with a slightly cleaner formulation and explication (i.e. 3 pages versus a slide or two.) Interestingly, I noticed that the one in the book is based off of Möller and Trumbore's method ("Fast, Minimum Storage Ray-Triangle Intersection").

One thing I did a little differently was that I pulled the box intersection code out and made an axis aligned bounding box method. AABB's are always handy to have. The box primitive just wraps this and determines the normal based on which face was hit.

The heightfield is based directly on the traversal method given in class. For the patch intersection, I used v3 from the slides. The only real change that I made was having it use the AABB code and adding a couple of early exit tests (which were probably assumed, but still.) Namely, if t-far < 0 or t-near > the current best hit, then it early exits (The test is actually in the hit record. I added an overloaded checkhit() method to check for either a single t-value or a range of t-values as from the AABB test). Also, in addition to setting t-near to the maximum of 0 and the t-near from the bounding box, I set t-far to the minimum of t-far from the bounding box and the current best hit. This lets it exit a bit early if the traversal would carry it past a better hit from another primitive. The height-field could definitely stand some more optimization and I'd like to experiment with how the data is accessed, but I'm fairly pleased with the speed already.

The disc is just a special case of a ring with an inner radius of 0. It's ring/disc primitive is optimized a bit to use the new checkhit() method in the hit record to avoid computing the distance from the center if there's no chance of it being visible.

Extra Credit

Here's a render of a section of the Wasatch Mountains around northern Salt Lake (Fort Douglas Region). The data set is 1039x1375. I figure this is fairly close to my new home. (Salt Lake City!)

Image #3C


Last modified: Wed Feb 9 15:57:18 MST 2005