This is my little real time ray tracer in ActionScript 3. You can download the AS3 source. I also ported this code to Mac OS X / OpenGL (it runs quite a bit faster in C++ than Flash). This is my second attempt at writing a ray tracer in AS3. The first one
rendered a similar scene at around 4 frames per second. It is interesting to consider the optimizations that I applied to get it to 30 fps. Here's a partial list of the things I tried:
The final code simply calls setPixel once for each pixel. I tried an alternate approach where in the main rendering loop, it writes pixel data
to a ByteArray, then calls copyPixels once at the end, but that was slower than calling setPixel many times.
The first version stored the scene as an Array of Objects, with each object having all of the properties that describe a sphere (center, radius, color, etc). In the second version
there is one Array of Numbers for each property; objects, classes and dictionaries are not used to store scene data.
The first version of the code used a 3d vector class with functions for vector addition, subtraction, dot product, etc. To remove the overhead of these function calls, I eliminated this class,
and all vector operations are performed inline. This was fairly tedious to code, but yielded a major speed increase.
The first version used the customary approach in ray tracing of recusrively calling a trace ray function to handle shadows and reflections. In the second version, these calls are
unrolled, and specialized. There are 3 similar, but slightly different versions of the ray-sphere intersection code: One version is for primary rays. It assumes that the camera is at the
origin, and uses this fact to slightly simplify the ray-sphere intersection calculation. Another version, for shadow rays, stops if it finds any intersection (rather than looking
for the closest intersection). It doesn't go through the full calculation of finding the distance to the intersection point for shadow rays. Finally the reflection ray is handled
like a normal, fully general ray (i.e. I don't fix its origin to 0,0,0). Only one level of reflection is used, and shadows are not computed for reflections.
After removing all function calls to 3d vector operations and recursive ray tracing, the only function calls in the entire draw loop are to Math.sqrt(). I tried a few variants of fast replacements for this, but with no good results.
For each sphere, I tried projecting its center coordinate onto the screen, and construct a bounding circle for it.
Then, for each particular pixel, I only trace primary rays against spheres who's bounding circle contains that pixel. This test is fairly quick, since checking if a pixel is inside of the bounding circle can be done using only a couple
of additions and multiplications. I was able to tune this optimization to this particular scene and get a few more FPS out of it. However, if I changed the scene a little bit, the bounding circles were too small and the scene didn't render correctly. If I made the circles much bigger, the performance benefit was lost. So this optimization is commented out in the code.
Note that a 3D raytraced sphere does not look like a circle on the screen- it looks like an elipse, so it is not possible to construct a perfect bounding circle.