This ray tracer was written in C++ from scratch for the Computer Graphics assignment. The SDL is used for presenting the images to the user. The following primitives are supported: spheres, planes and sphereflakes (which were added to obtain reasonable comparison of the ray tracing acceleration algorithms).

As part of the assignment the following features were implemented:
  • shadows
  • reflections
  • ray tracing acceleration:
    • per object axis aligned bounding boxes (AABB)1
    • bounding volume hierarchy (BVH)



Shadows implementation

At each intersection point, a shadow ray is shot towards each light source and the contribution of this lightsource is taken into account if the shadow ray does not intersect any other objects along its path. In order to avoid surface acne (black spots on the surfaces of objects due to numerical imprecisions leading to incorrect self-shadowing) any intersections near the ray origin are discarded.





Reflections

Reflections are rendered by recursively tracing secondary rays, when an intersection with a reflective object occurs. A maximum recursion limit is used to avoid infinite recursion.





Ray tracing acceleration

Axis aligned bounding boxes are calculated for each object during initialisation. The ray-object intersection functions test the ray against the object's bounding box before calculating intersections with the object itself. Because the scenes are made out of very simple primitives which are trivial to intersect a new arbitrarily complex primitive was introduced: the sphereflake fractal. In order to further improve rendering performance, a hierarchy of axis aligned bounding boxes was constructed for the superflake.






Tests conducted

The rendering meantimes where calculated by taking 12 measurements, removing the 2 outliners and averaging the rest.

Test 1: Brute force ray tracing vs BV for primitive objects

A scene with planes and spheres was rendered with per object bounding boxes (AABB) and then without bounding boxes (brute force ray tracing).

The mean rendering times when the AABB algorithm was used were:
  • 1686 miliseconds (when 512x512 images were rendered)
  • 6728 miliseconds (when 1024x1024 images were rendered)
The mean rendering times when brute force ray tracing were used were:
  • 1729 miliseconds (when 512x512 images were rendered)
  • 6949 miliseconds (when 1024x1024 images were rendered)
Per object bounding box is marginally faster than brute force ray tracing.

Test 2: Brute force vs BV for objects with more complex primitives

A scene with planes, spheres and a sphereflake with 4 iterations (259 spheres) was rendered with per object bounding boxes and then without bounding boxes (brute force ray tracing). The render mean times where:
  • 13711 miliseconds when bounding boxes were used
  • 33454 miliseconds when brute force ray tracing was used
The test conducted by rendering 512x512 images.

Test 3: BVH vs BV

A scene with planes, spheres and a sphereflake with 4 iterations (259 spheres) was rendered with BHV and per object bounding boxes. The render mean time was:
  • 4285 miliseconds when BVH was used
  • 113711 when per object bounding boxes were used
The test conducted by rendering 512x512 images. The BVH was significally faster than per object bounding box.

Test 4: BVH vs BV for very complicated objects

The previous scene but with a sphereflake with 8 iterations (335923 spheres) was rendered.
  • BVH rendering time: 81393 miliseconds
  • BV rendering time: more than 24 hours




Code:

The code can be downloaded from here and it runs on Linux. You must specify a scene description file.



Notes:

1. An axis-aligned bounding box, or AABB for short, is a box aligned with coordinate axes and fully enclosing some object. Because the box is never rotated with respect to the axes, it can be defined by just its center and extents, or alternatively by min and max points.



Back to top