Basic Raytracing: Reflection/Refraction

This project consists of two parts. First, we have been asked to model a scene, using Maya or Houdini, that can be used to test a variety of surface and displacement shaders. For the second part of this project we are to write two surface shaders. Both shaders must trace reflections and refractions. The first shader must allow an artist to switch the operation of the shader from "reflect" to "refract". The second shader must provide an artist with a slider that will control the mixing of the reflection and refraction effects.

I have decided to keep the scene as simple as possible, but still be able to convey what needs to get across. These scenes have been done in Houdini.

I have started with reflections since it seems to be easier to understand than refractions. We see relfections in the real world every day. Everytime you look in the mirror, an exact duplicate of your image is being reflected back at you.

The Law of Reflection states:

A light ray and its reflection make equal angles with the normal to the reflecting surface.

So that you get this diagram of the rays:

Where theta1 = theta2.

So with this in mind I looked into the code on Malcom's website and came up with a suitable surface shader that has full reflection. The first image it in grey tones just to show that the reflection is working, the second image is the surface shader with the ability to change the basic surface color. I also put together a short clip showing the spheres in motion to get an idea of how the shader looks in an animation.

click to enlarge

click to enlarge

With a good start on the reflection surface shader. I turned to refractions. As with reflections, we see refracted images everyday, mostly through glass. Anytime you look through a non-opaque object there will be refraction, however slight it might be. Refractions are much more difficult to calculate since the Incident Ray is not "bouncing" off the object but passing through the object and being "bent" at the same time.

The Law of Refraction, or Snell's Law (named for Willobrord Snell, who discovered the law in 1621.), states:

The angles that the incident ray and the refracted ray make with the normal to the surface at the point of refraction are based on the media through which the light rays are travelling.

With this we get this diagram:

Where n1(sin(theta1) = n2(sin(theta2)

The constants n are the indices of refraction for the corresponding media.

This is a basic table of a few indices of refraction:


Air at STP

Water at 20 C
Crown Glass
Flint Glass

Refractive index


By pluging these refractive indices into our refract() in the shader we are able to control the amount of refraction in the surface shader.

Taking all of this into consideration. I set forth to write a shader so that the artist could "swap" between the reflective or refractive properties. To be able to do this I relied on a basic IF statement that states: If swap = 0 then reflect, if not, then refract. I set up the same scene as above with a texture map on the environment sphere to show the refractive properties. These are the images that I got using "swap".

swap = 0

click to enlarge

swap = 1

click to enlarge


The refraction in the above image is based on the refractive index of crown glass, which is 1.52. I did include into the shader the ability of the artist to enter their own refractive index for the shader.

With "swap" surface shader in good condition I went to the "blend".

The idea of blending these wasn't as clear as the "swap". I decided to base the blend on the idea we explored in the first project on this website. By using the mix() function along with the reflect() and refract() function I was able to get some interesting results. I did find that the "blend" really didn't start to show until the blend was above 50%, I conclude that this is from the full reflective property of the reflective surface shader. The images below and the corresponding movie shows the ability of the artist to control and "blend" reflection and refraction.

blend = 0

click to enlarge

blend = .25

click to enlarge


blend = .50

click to enlarge

blend = .75

click to enlarge


blend = 1

click to enlarge






Once again, I have based the refractive index on crown glass, but as in the swap shader, the artist has control which index to input.

One problem that I did run into with Houdini was the use of normalize(I). For some reason Houdini tends to give better results for refraction if (I) is not normalized. So in all of the examples above, I have omitted normalize(I) for the standard (I). This is reflected also in both of the codes below.

click here for the swap code

click here for the blend code