Ray Tracing with Area Light Sources

Casey Smith

For the third project, I implemented a ray-tracer from scratch. Originally, I inteded to use it to sample the BRDF to create radiosity-like images, but I found that simply implementing what I have was quite a task. The image still looks pretty good, though, because of the use of sampled area light sources to get soft shadows. The model in the image is a reddish hexahedron (a pair of stacked three-sided trianglular pyramids) in a room with a blue, reflective floor and ceiling, and green not-so-reflective walls. The light source is positioned just below the ceiling, but above the peak of the hexahedron. The simple and point light source images below rendered very quickly (less than 5 seconds). The larger supersampled image with area light sources took a bit longer--about an hour and a half.

The basic ray tracer

I started out by implementing a basic ray tracer. I decided to only use triangles because anything can be made from triangles, and they make most computations (except possibly ray intersections) very easy. They can't be concave or non-planar, for instance. The basic ray tracer shoots a rays into the image from the center of projection through the view plane, returning the color of the closest intersecting polygon. In order to determine polygon intersections, I first determine the intersection of the ray with the plane defined by the polygon (having stored the normal of the triangle at creation, determining the plane equation is trivial). Then, to deterimine if the intersection point was within the polygon, I drop the X, Y, or Z coordinate of the polygon and intersection point, depending on what produces an acceptable (the vertices of the triangle aren't colinear) projection. Then, I take the 2D dot product of each vector from each vertex to the intersection point with a corresponding edge direciton. If all the dot products have the same sign, the point must be within the polygon.

Adding Shadows

Next, I added point light sources, shadows, and reflections. Now the color at a ray intersection is determined by the Lambertian reflection from the light source plus the color of the reflection weighted by the specular coefficient of the triangle. Here, the floor and ceiling reflect quite a bit while the hexahedron and the walls do not reflect much at all.

Shadows were determined by checking ot see if there was a triangle intersection closer than the light source. If there was something in the way, the lambertian reflection was zero. In order to keep all parts of the image at least partially lit, an ambient term was added.

Area Light Sources

Finally, area light sources were added. In order to determine how much of a light source an intersection point could see, the light source was sampled with shadow rays using a jittered Halton series. A sample point on the light surface was determined as a linear combination of the vertices weighted with the Halton numbers and a small random value. The fraction of the unblocked shadow rays determined how much of the light sources' light a point recieves. For the image below, each of the two light sources (two triangles make a square) were sampled with 40 points. Finally, supersampling was implemented such that each pixel recieves several rays which pass through a random point within the pixel. The sampling rays' colors are averaged to determine the color of the pixel.

In the image below, notice the green hue on the floor directly below the hexahedron. If you look in the image above, you will notice that that part of the image is in shadow from the hexahedron. Thus, it is being lit almost exclusively by reflected light from the green wall.




My color scheme for this image was insulted, so here's a perhaps better one (or perhaps not).

Possible Future Work

It could be very interesting to use this environment to implement instant radiosity. Using the point light sources and shadows, Instant radiosity should be fairly straightforward to implement. However, it won't be instant because ray tracers take longer to run than scanline renderers.
Also, it would be nice to implement brdf sampling. The main barrier to that is determining a good parameterization for sampling rays. I would like to have a way to divide the hemisphere into equal-sized "bins," sending off at least one ray through each bin. Certain areas, like the light sources, should be sampled more densely. Bins with more than one ray would be averaged before the weighted averaging of the brdf was performed in order to avoid having the weighting skewed by the sampling density.