General Implementation Details
Ignis is a flexible path tracer for the CPU. It supports a variety of different surface types, including Lambertian diffuse, Oren-Nayar diffuse, refractive, reflective and glossy surfaces. The ray tracer can operate as either a single-branch or multi-branch integrator. The most functional mode is to run it as a plain path tracer, however I have added some support for bidirectional path tracing as well. In the first version of Ignis I experimented with Metropolis Light Transport, however I haven’t revisited it yet.
The render code can scale to an arbitrary number of threads by breaking the render region into a set of tiles and distributing the tiles amongst active threads. There’s no support for GPU acceleration at the time, but it is one of the areas I’d like to explore at some point.
The original version of Ignis only supported spheres, boxes and planes. Recently I’ve been bulking up the library of primitive objects to include various quadric surface, such as a ellipsoids, cones and cylinders. I’ve also added a generic quadratic solver, so more exotic surfaces such as paraboloids and hyperboloids are also possible. Although it’s slower than explicitly defined primitives, the solver can handle any second order surface specific as a set of 10 coefficients. A few examples of different surfaces can be seen below (click for larger sizes):
In my first version of Ignis, I added basic triangle mesh collision support, however proper KD-tree acceleration structures weren’t included. This made trimesh collisions slow and impractical for complex scenes. I’ve yet to add any trimesh support to my latest iteration of Ignis since I’d like to do it properly and spend a decent amount of time researching and optimizing the code. A render from the old trimesh implementation:
While working on Ignis, I’ve tried to experiment with a wide range of optical effects. Accurate simulation of the behavior of light is needed to produce realistic renders, especially when refractive surfaces are involved. Ignis is able to account for several optical properties such as dispersion, absorption and depth of field.
Camera rays in the ray tracer can be emitted from two different camera types. The first is orthogonal projection camera that always emits focused, parallel rays. The second is perspective camera that can be configured with various lense settings, By default the aperture has of 0, thus simulating a pinhole camera with infinite focus. Increasing the aperture size to a non-zero value allows the camera to operate in more realistic manner. The number of blades in the aperture and the focal length of the lense system are also exposed as settings. These properties inherently cause the ray tracer to exhibit the effects of depth of field and produce bokeh when bright regions are defocused.
Dispersion is the phenomenon that occurs different wavelengths of light have different refractive indices in a medium like glass. Spectral rendering is needed to properly produce this effect. Ignis supports a basic spectral rendering implementation that can can process up to 6 different wavelengths of light. Spectral rendering can also be combined with the depth of field settings to create chromatic aberration in the camera lense itself.
Finally, any transmissive volume can specify an absorption factor, which applied uniformly to the volume using the Beer-Lambert law. For thin panes of glass or water absorption isn’t very noticeable, but for darker and denser materials the effect is more prominent. Absorption can be seen in the doubled cone image shown previously.
The last effect I’ve been working on is sky and background rendering. I implemented the Hosek-Wilkie algorithm and dataset for sky light simulation. I haven’t quite added support for sun disc sampling, so the sky only provides global illumination and doesn’t directly cast shadows. A sample render that uses the sky light as the main source of illumination for the scene: