Always make sure the scene is in front of the camera. Don't normalize if you don't have to. Negative signs suck. And above all: rendering takes forever.
For our final project, we decided to extend the raytracer from assignment 11. The specific extensions we implemented were:
Our code includes support for two-dimensional quadrilaterals and three-dimensional prisms. To incorporate these into the scene, open the scene.txt file and begin a new section with the header "QUAD" or "PRISM". When defining the four points of a quadrilateral, be sure to include them in the following order:
For a prism, you should define the points in the following order:
To implement prisms, we first tried using a polygon intersection algorithm that we found in a raytracer textbook. [1] Unfortunately, after several hours of trying to get it to work, we gave up on this approach, and decided instead to build upon what we already knew how to do: triangles. We represented a quadrilateral as two triangles; building upon that, we represented a prism as six quadrilaterals. Although this representation worked, it slowed down rendering by a noticeable amount.
Our next extension to the raytracer was to implement transparency and refraction. We modeled transparency similarly to how we implemented reflection earlier: by shooting off another ray once the ray casted from our camera hit a surface. This meant we had to include a transparency coefficient (between 0 and 1) for each surface. This coefficient gets specified in the scene.txt file.
Refraction was implemented in the way we shot off the secondary ray from a transparent surface. We calculated the trajectory of the secondary ray according to Snell's Law, an equation that governs the refractive properties of objects. By taking into account the index of refraction of the surface, as well as the angle of incidence of the casted ray, we are able to find the appropriate refracted ray. [2]
There were some headaches in the implementation, but we finally got refraction working, as can be seen in the example below:
We implemented soft shadows with distributed ray tracing. A "size" attribute was added to the light structure, allowing lights to become area light sources. (Setting the size to 0 creates a point light source.) In the ShadeLight function, in addition to the point->light ray, 24 additional rays are created from the point to various points uniformly spaced on the light source. The occlusion test is run on all the rays and the fraction of rays that are occluded by an object correspond to the darkness of the shadow at that point. For example, if all the rays are occluded, the point is in full shadow. However, if only 12 of them are, the point is colored halfway between its unshaded color and black.
Rendering with 24 rays was very slow, so we used a 12-ray version for most our renderings. To enable 24-ray rendering, find the appropriate commented section in 'raycast.h' and uncomment it. You can recompile the code after making changes with 'make re'.
Anti-aliasing works similarly to soft shadows. Instead of shooting multiple rays from a surface's point, we shoot several rays from the camera to the scene. By sampling spots close to the original point, we can average the detected colors minimize jagged edges, smoothing out the image. Due to the increase in calculations, rendering was exceedingly slow and our process was killed on multiple attempts. By reducing the number of extra samples to 3, we were finally able to render the following image:
The sample points were probably too far apart, as parts of the image are too blurry. This effect is especially noticeable on the shadows. However, anti-aliasing was somewhat effective on the edges of the sphere.
One final note: in our submitted code, anti-aliasing has been commented out of the code for the purposes of allowing it to run faster. To enable it, simple uncomment the appropriately marked code in 'raycast.h'. You can recompile the code after making changes with 'make re'.
[1] Glassner, Andrew S., ed. An Introduction to Ray Tracing. San Diego: Academic Press Limited, 1997. 53-57.
[2] Yoon, Sung-Eui. "Ray Tracing (Shadow, Reflection and Refraction)." Team Gamma, UNC.
[3] Waters, Zack. "Realistic Raytracing." Dept. of CS, Worcester Polytechnic Institute.
[4] Cooksey, Chris. "Antialiasing and Raytracing." University of Western Australia.