PhotonLab is a raytracer that I've been working on in my spare time over the past few years. It takes an XML file that describes the render settings, camera positions and scene objects and raytraces the scene. It can operate as a simple raytracer, path tracer or photon mapper.
Some of the features are listed below:
Ray tracing is a geometrical optics technique that relies on the fact that light travels in straight lines, to trace the paths of rays as they interact with optical surfaces. When applied to computer graphics it is taken to mean the formation of an image by tracing light rays from the screen back through a scene to light sources. The aim is to produce a realistic scene that simulates many or all optical effects but in a time much shorter than would be required for a full simulation.
For instance, if we assume a 100W tungsten lightbulb emits around 550nm (it actually has a temperature around 3000K and so puts out most of it's energy around 1um which is partly why they are inefficient and get very hot), then the number of photons it emits per second is around 3×1020 (E = hf = hc/λ = 3.6×10-19 J per photon). Obviously it is impractical to simulate this many photons so raytracing tries to look for only the important ones that enter the lens.
There are various ways of doing this, each with advantages and disadvantages. The three methods I have implemented so far are described below.
Ray tracing is the simplest of the three methods but does not allow a full global illumination simulation to be performed. It involves shooting rays from an eye position through the lens and towards the scene objects. When an object is intersected shadow rays are shot at each of the light sources to calculate the direct illumination. If the object has a specular component (either reflection or transmission) a new ray(s) is created and followed along the reflection or transmission direction. The same process is then followed at any subsequent interactions making up the basis of the recursive raytracer.
This process allows raytracing to simulate LD?S*E paths (where L is a light source, D is a diffuse interaction, S a specular one, E the eye, ? none or one interactions, + is one or more, and * none or more interactions with | being one or other event). Which means it can render directly illuminated diffuse (or specular) surfaces and diffuse surfaces seen after one or more specular interactions. What it cannot draw are diffuse inter-reflections which is illumination caused by diffuse light from another surface, an example of which is the colour bleeding onto a white wall from a red carpet below. It also cannot draw caustics which are regions of (usually high intensity) focused light formed by specular objects such as lenses.
The advantages of this method are that it is reasonably fast and easy to implement and works well when there are lots of highly specular objects in the scene. The disadvantages are that it does not provide a full global illumnination solution, it does not work well with area light sources and some lens effects are very inefficient. Some of this problems can be overcome by using tricks but they are often costly in terms of processing time. Area light sources for instance can be done by sending out many shadow rays per light source to produce correct soft and depth of field, motion blur and antialiasing can be done by averaging together many samples.
An example of a raytraced image can be found here and here. The image just above was raytraced. Soft shadows have been generated by sampling over various points on the light source but there is no colour bleeding (for example onto the white wall) or caustic effects (through the glass sphere).
Path tracing is an improvement on ray tracing because it allows all global illumination effects to be produced. It simulates the paths L{S|D}*E which equates to all paths with none or more specular or diffuse bounces. It works by tracing a ray recursively into the scene and tracing it around but with changes to the algorithm. For diffuse objects, instead of calculating the direct illumination it picks a direction on the hemisphere above the intersection point and continues tracing. The intensity of a pixel is only increased when a ray strikes a light. Path tracing stochastically samples all possible light paths and makes it possible to evaluate problems that require integration such as area lights and indirect illumination.
Path tracing is a Monte Carlo technique and when combined with Russian Roulette sampling it can be very powerfull. A ray is shot into the scene an when it hits an object it's next path is determined probabilistically. The ray type is determined by using a random number to select absorbed, transmitted, specular or diffuse based on the coefficients of each, the appropriate distribution to decide the ray direction is then sampled and raytracing continues until the ray is absorbed or hits a light. To calculate a final value this process is repeated many hundreds of times to correctly sample the integrals. The Russian Roulette sampling is particularly good at speeding the process up because if we were to split each ray as raytracing does we end up having to calculate many paths even though they only contribute a small amount to the final image. The classic example is that if we have a surface that is 50% reflective and we shoot 1000 rays at it, it is equivalent (and much faster) to trace 500 rays at full power and absorb the rest than it is to trace 1000 rays at 50% power.
Path tracing is good because it allows all lighting effects and is particularly good at drawing scenes with large light souces. Conversely, path tracing is very inefficient when the scene ony contains small lights as only a few path samples actually make it to a light which produces a very noisy estimation.
Path tracing is generally much slower than raytracing but produces far superiour results. The image above shows some of the improvements. There are caustics (formed on the floor below the glass sphere), the ceiling is illuminated by diffuse light reflected of the objects and walls (it is dark in the raytraced image) and there is colour bleeding (red and green tints on the black wall). A few examples are here, here, here, here and here.
Photon mapping combines the best of both of the above methods. It uses path tracing techniques to generate caustics and other advanced effects and raytracing for direct illumination, combined with a 3D map of photons that allows indirect illumination to be quickly computed.
The photon map is a data structure that stores photons where they intersect diffuse surfaces. Photons are sent into the scene from the light sources and when they are diffusely reflected or absorbed the colour, direction and position is stored in the photon map. This occurs as an initial process before rendering starts. Often the there are two or more photon maps. The basic one stores all photon paths while an additional one, called the caustic map, only stores photon hits that have had at least one specular reflection. Photons can be selectively shot at specular objects to increase the density of photons in these cases, to enable a better estimate of the caustic illumination (since these effects often produce sharp, high intensity effects). Caution must be exercised when generating the raytracing process as biased results could be generated if some effects are accidentally added twice.
When raytracing the scene the algorithm queries the photon map. This involves finding the nearest N photons to the intersection and summing the product of the photon's colour and the dot product of the photon direction and sample ray direction.
Raytracing proceeds by tracing the ray into the scene and chosing the event by Russian Roulette. For a diffuse hit the specular map is queried to generate the caustics, direct illumination is calculated by semding feeler rays at the light sources (as raytracing above) and the ray continues on. If there has been a diffuse hit already then the global photonmap is sampled and the ray terminated. This allows directly viewed surfaces to be accurately generated but time saved when diffuse surfaces are seen after already suffering a diffuse hit. Specular events are handled in the same way as for raytracing but these paths no longer rely on hitting a light source because there is a high probability that they will be terminated through two diffuse hits which again speeds up the process.
There are many sources of information on the web about photon mapping. The idea was first proposed by Henrik Wann Jensen and he has a website and book that explains it in much greater detail.
Some examples of photon mapped images are here, here and here.