CS348b - Programming Assignment #3 Ray Tracer Extensions Sean Treichler I implemented two main extensions to my ray tracer, adaptive stochastic supersampling, and thin-film interference effects. In order to get the thin-film effects to look right, the ray tracer was also modified to use spectral power distributions rather than simple RGB values for light rays. * Spectral Power Distributions - The use of SPDs is pretty much essential to good thin-film interference effects (or any wavelength-dependent effect). The general idea is to store power at various points in the light spectrum. Rather than doing some sort of adaptive silliness to break up the spectrum into interesting and boring parts, I simply chopped the spectrum up into bins, one for every 5 nm between 380 nm and 780 nm. (The actual choice of values were dictated by the CIE data I could find - more about that in a sec.) Going from this fixed subdivision to an adaptive subdivision technique would have been possible, but it would have required interpolation of the color-matching data, and would have provided minimal benefit in the resulting image (we're averaging everything back down to RGB in the end, which throws away a WHOLE lot of information). Unfortunately, most of the graphics world still thinks in terms of R, G, and B, so I had to come up with ways to back between RGB and SPD values. The mapping from SPD values into RGB is a problem that has been pretty much solved for quite some time. Back in 1931, the CIE wrote down values for color-matching functions to convert SPDs into their XYZ color space. The only remaining problem in this area is finding those values. After poking around the Web for quite a while, I finally found a table that started at 380 nm and contained values for every 5 nm up to 780 nm. (Sound familiar?) The mapping from XYZ to RGB is technically monitor-dependent, but I went with the numbers that NTSC developed for the "standard" (whatever that is) monitor. Mapping from RGB values into SPD values was tougher. Due to metamers, and the simple fact that an SPD contains much more information than an RGB tuple, no single mapping from RGB to SPD exists. Even worse, the only mappings that are actually inverses of the CIE color matching functions look really wrong. (They tend to consist of very large spikes at particular wavelengths.) As a result, I chose the simple approach of declaring the R->SPD mapping to be a box of unit height from 580 nm to 780 nm, G->SPD being a box from 500 nm to 580 nm, and B->SPD being a box from 380 nm to 500 nm. After making the somewhat arbitrary choice, I tested some mappings from RGB into SPD and back again. The results were pretty good, although there was some bleeding of green into red and blue, so most of the lights I used had about 20% more green than they should have. * Thin-Film Interference - Lots of people think me a freak when I say things like this, but I really like E&M. I've studied thin-film interference at several different levels over the years, and it was fun to teach a computer to model it. I started at the very basics (ha!) of reflectance of EM waves at medium boundaries, made a few simplifying assumptions (parallel surfaces and identical media on both sides of the film), and came up with power reflectance and transmittance equations dependent on the indices of refractions of the two media, the thickness of the film, and the angle (actually the cosine of the angle) of incidence of the ray on the film. The equations actually differ slightly based on how the incident ray is polarized, but I decided that modelling polarized light was too much, so I assume all of my light somehow gets perpendicularly polarized right before it hits the film. It's not perfectly physically correct, which I find a little distasteful, but it looks ok, and I didn't have the time to do it completely right. At this point, the only real trick to getting good soap bubbles is finding good indices of refraction and the right thickness. A final trick is that no soap bubble is of uniform thickness, so I borrowed the fractal Brownian noise function from CS248 to perturb the thickness of the soap film in a way that actually looks pretty darn realistic. I played for a while with trying to actually model the movement of fluid in a soap bubble, but none of my simplistic models looked at all realistic, so I opted for the noise function instead. Again, I would have liked to do it right, but I'd probably have to take a fluid mechanics class or two before that. Interfacing this with the ray tracer was simple. Whenever a ray strikes an object that's tagged as a thin film, the standard lighting equations are thrown out. The reflectance (and therefore transmittance - they add up to 1 always) of the film at that point and angle for every 5 nm is calculated. Two rays are fired, one continuing in the original direction, and one in the reflection direction. Their colors are effectively blended using the reflectance/transmittance data. Lights only contribute specular highlights, which are also multiplied by the reflectance data. Shadow calculation is also modified slightly, with the wavelength-dependent reflectance data being used upon intersection of a ray cast toward a light with a thin film. This achieves the "dark on the outside, light on the inside" look of a soap bubble's shadow. The images show the pretty pictures you can get from soap bubbles. The main image depicts three soap bubbles above a gray surface, under a mostly overcast sky. It wasn't my original intent to use a "mostly overcast sky" as my lighting conditions, but soap bubbles at their very best still don't reflect much light, so it takes a large amount of light to show the pretty colors, and since I didn't model area lights, I had to use ambient lighting and wide specular highlights to fake it. The other problem with soap bubbles is that the colors tend to pack closely, and it takes a very high resolution rendering to keep the anti-aliasing from just turning everything gray. To help show this, I chose a small sub-section (see if you can figure out which - it isn't hard) and rendered it at a much higher resolution. The results were pretty darn cool.