Many of the ray tracing features can be enabled independent of other features. By activating an option new parameters will be available to the user.
First of all, you can choose between four different render modes:
The first one, Scanline, is straightforward implemented and renders one pixel after another, line by line. The Tile renderer splits the image that is about to be rendered into tiles each of them being up to 32 pixels wide and up to 32 pixels high. These tiles are than rendered one by one. This render mode is up to 10 percent faster than the Scanline renderer due to the exploitation of the cache coherence that is caused by the fact that pixels that are lying close together are rendered using almost the same geometry and texture data. After rendering a pixel the geometry and texture data are likely to be already in the processor's cache hence the number of cache hits increases when the other pixels of the same tile are rendered.
When you are working with scenes that are very large or using settings that will occupy the ray tracer for hours it may be necessary to get a quick preview that is progressively refined until every pixel has been rendered. Such a Preview mode is also implemented but it should only be used if it is absolutely inevitable. Due to its almost randomly access to geometry and texture data the cache coherence, as stated above for the tile renderer, can't be exploited to such a great extend. That causes a drastic performance drop by up to 15 percent compared with the tile renderer.
The preview renderer in action. It should only be used when setting up the correct ray tracing parameters for very complex scenes, i.e. configuring the final gathering. The model for this test scene was created by Marko Dabrovic.
The forth render mode, called Single Pass, is different to the other three modes in that way that it performs ray tracing and anti-aliasing in one pass whereas the other render modes must perform these actions in two consecutive passes. Single Pass is based on the algorithm of the already described tile renderer but with the difference that each tile is sub-divided in four smaller tiles with a size of 16x16 pixels. That modification to the original tile render algorithm exploits the cache coherence much better during anti-aliasing.
All render modes are thread-safe implemented – a precondition for multi-thread applications. This ray tracer can activate up to 16 threads (tries to assign them to different processors, if possible) and distributes the work to them. In the modes Scanline, Tile, and Preview the work is distributed pixel by pixel to the threads. When the mode Single Pass is chosen the work is tile-wise distributed. Note, that the work for anti-aliasing is always tile-wise distributed.
Choosing a large number of threads can also help to compensate paging stalls when working with scenes that don't fit into memory. In that case, a thread that is waiting for data that must be loaded from disk into memory first, is sent into sleep mode allowing other threads to continue their own work until they cause a paging stall or the operating system gives execution time to another thread.
The ray tracing algorithm is recursively implemented. So it can call itself when a ray encounters a surface where it is reflected or refracted. Since every recursive algorithm needs at least one termination criteria, that has to be met to avoid further recursive calls for one particular ray, the ray tracing algorithm makes no exception. Here, the termination criteria is the Trace Depth. As soon as the ray tracing algorithm has called itself so often for one particular ray as the user has chosen from the list deeper recursive calls are omitted even if it would improve the image quality by adding more details.
In many 3D graphics packages you can choose the number of recursive calls for reflection and refraction, too. The maximum trace depth is then calculated by adding up both values.
I chose a different approach for my ray tracer. Since the maximum trace depth can barely be estimated it will differ greatly from one to 15 or even more. And that all in one image. Because I didn't want to bother finding a good value for the maximum trace depth I let the decision almost completely handle by the ray tracer or more precisely: by the Adaptive Depth Control(ADC). The ADC allows it to use high values for the trace depth and let the ADC decide if a new recursive call to the ray trace method would probably contribute enough information to the already computed pixel color value or if the call should be omitted.
The value for the maximum trace depth is still a valid termination criteria and you can select the number of recursive calls due to reflection and refraction independently. But very often the decision made by the ADC is more suitable. To ensure that the termination criteria "Maximum trace depth reached" is not met and only the ADC algorithm's termination criteria is considered the value for the maximum trace depth should be set very high.
Using the ADC algorithm improves ray tracing performance by a factor of two and more but only in scenes with reflective and transmissive surfaces. Scenes that contain only diffuse surfaces are not affected by the ADC.
Ray tracing algorithms
Older versions of the ray tracer had up to four different ray tracing algorithms implemented:
classic ray tracing
distributed ray tracing
distributed ray tracing including photon mapping
distributed ray tracing including photon mapping and spectral rendering
This ray tracer, in its latest version, has only two ray tracing algorithms (identical with the items 1. and 4. in the list above). However, for easier handling, you don't have to choose the algorithm directly anymore. Instead, you select the features that have to be rendered and the ray tracer selects itself the correct ray tracing algorithm. The classic ray tracing algorithm is enabled by default.
Distributed ray tracing must be enabled to use features such as soft shadows, glossy reflection/transmission, and depth of field. Photon mapping and spectral rendering can be enabled independently of each other, because photon mapping is not necessary to perform spectral rendering, even though it will improve the quality of the rendered images considerably.
Spectral rendering comes in two versions. The first one uses just three spectral samples identical with the wavelength of red, green, and blue per subpixel and avoids any computational expensive calculations to transform spectral sample values into RGB color space. The second method Full Spectrum uses between 8 and 40 spectral samples per subpixel for carefully chosen wavelengths rendering wavelength-dependent material properties more precisely.
Global Render Flags
Some other features can be enabled using the global render flags. These flags allowed me an easier testing of the algorithms and disabling some of the flags can speed-up the rendering process significantly. Note that these flags override settings made in the material shaders.
You can choose the features that have to be rendered as well as the ray tracing algorithm and the number of threads to perform the rendering task in the ray tracing settings.
Some of the global render flags enable options on other configuration pages of the ray tracer, i.e. soft shadows, glossy reflection/transmission, depth of field, photon mapping, subsurface scattering.