Glowing Fish
Cody Rhoads
CPE 471, Spring 2016, Professor Sueda



Inspiration

This project was inspired by the following scene from the movie Life of Pi:



Program Features
Reflection and Refraction

To create the reflection, I used a mirrored version of the scene and only drew points above the y=0 plane (which is the surface of the water). I used a separate framebuffer so that I could render this new scene as a texture. I used the same technique for the refraction, though I did not mirror the scene and only drew points below the y=0 plane. After incorporating an offset to the textures (discussed in Water Distortion), I blended the two textures together to create a single texture that had both reflection and refraction. I used the fresnel effect to make the ratio between the two textures depend on the dot product of the eye vector and the normal of the surface of the water (see here for a video describing the fresnel effect). This way, looking straight into the water will show more of the refraction, while looking across the surface of the water will make the water reflection more apparent.



Water Distortion

To create the distortion of the water, I used a sample du/dv map to offset the texture coordinates of the water. I interpreted the rgb value of each point on the du/dv map as a vector, which I then added to the actual texture coordinate. To make the surface of the water have the wavy motion, I used the current time as an offset when getting the vector from the du/dv map.

Blending

To simulate depth and distance, I used blending to make the fish blend with the color of the water when deeper or farther away. I also used blending to make the horizon easier on the eyes. Without it, the boundary between the ocean and the sky was a sharp line, which I disliked.



Ray Casting

When I first inserted the boat into the scene, I realized that the water plane cut through the boat, making it look like it was taking on water:



To remedy this, I needed to discard the fragments of the water plane that were inside the boat. First, I used an axis-aligned bounding box for the boat to check if the fragment was in the general vicinity of the boat. If so, then I used ray casting to check if the fragment was actually in the boat. The method I used involved checking how many times a ray intersected the sides of a polygon. If it intersected the polygon an odd number of times, then the ray originated from inside the polygon. In my case, I had to check if a ray originating at the fragment intersected the sides of the boat an odd number of times. To do this, I made a line from the fragment to a point that I knew was outside of the boat. Using this line, I compared it to every side of the polygon representing the boat, checking if the lines were intersecting. If there were an odd number of intersections, then the fragment was inside the boat, and was discarded. For more information about this technique, look here.

Sources

Code/Concept sources Obj files sources Life of Pi picture source