Goal

I wrote this simple raytracer for the purpose of experimenting with concurrent and distributed programming in Erlang.

Source Code

The source code for this project is available in a Git repository which you can access with the following command:

git clone git://repo.or.cz/eraytracer.git

or through a web interface. You can also download the whole project in a convenient tarball.

Requirements

To run the raytracer you need a properly installed Erlang/OTP system. The code has been tested with Erlang/OTP version R12B. You can use the official binaries or you can install Erlang from your distro’s repositories.

Instructions

Instructions for running the raytracer are included in the comments at the top of the raytracer.erl file.

Status

This Erlang/raytracing experiment is almost finished. I want to implement the items on the feature list and make sure that distributed mode actually results in performance gains on a 100mbit network. Here is a log of what is going on in the project.

Screenshots

img/traced-r11-1-small.png This is a magnified image of what I saw when I got a naive ray/sphere intersection code to work. It returned the first object a ray hit, which is only correct for a scene with one object. It was an exciting time!

img/traced-r11-2-small.png img/traced-r11-3-small.png At first, I couldn’t understand what was wrong when I saw this. It turned out that outputting to a non-square image revealed a bug where I mixed up the X and Y pixel coordinates in two loops.

img/traced-r16-1-small.png Here you can see actual object colours being used and ray/sphere intersection code with proper depth detection.

img/traced-r18-1-small.png This is the output of a simple depth-based illumination function. It just shades objects based on their distance from the camera.

img/traced-r18-2-small.png img/traced-r18-5-small.png img/traced-r22-2-small.png It took me a while to figure out diffuse lighting and how to add terms in an illumination function. Additionally, I was mislead into using colour components in the rage of 0-255 instead of using percentages (0.0-1.0).

img/traced-r25-1-small.png Eventually, after reading different papers on local illumination and asking experienced people for advice I got diffuse lighting to work. Note how the colour of the blue sphere received a green tint because the light source that I used had a bit of yellow in it.

img/traced-r27-1-small.png img/traced-r27-2-small.png The addition of a specular component was a big improvement to the look, in my opinion.

img/traced-r30-1-small.png While writing the reflection code I ran into a problem of limited numerical precision. As a result, a ray reflected off of a surface would wrongly intersect with that same surface. This funky image shows what it looks like. Thankfully, I didn’t spend a lot of time on tracking this issue down because Andrew Brikett has already done that while writing his raytracer in Haskell.

img/traced-r30-2-small.png img/traced-r30-3-small.png This is the result of a working reflection code at different recursion depths. Upon close inspection, you will see that the reflections in one image are more complex than in the other because of the increased number of times the reflection rays were allowed to bounce.

img/traced-r45-1-small.png Some more results of limited numerical precision happening on the surface of an infinite plane object.

img/traced-r49-1-small.png In this image you can see a properly lit infinite plane, reflections with maximum depth of 100, and shadows cast from two light sources.

License

The source code of this project is licensed under GPL version 2 or (at your option) any later version.