Extensible multi-threaded raytracer in Haskell.
The architecture is inpired by NVIDIA's OptiX raytracer.
Functional programming style amazingly fits the core concept of raytracing: cast individual independent rays, mutate the data using arbitrary functions and return the result. So let's take advantage of it!
The raytracer consists of several different kinds of functions:
Initial Ray Generation
Starts the whole raytracing process. Returned rays are traced against the scene one by one.
Intersection
Checks if a ray intersects the geometry and computes an intersection point and normal.
Bounding Volume
For a given geometry returns a container that encloses it.
Examples: AABB, Bounding Sphere
Closest Hit (a.k.a. Shading)
Takes the first intersection along the ray and returns one of the following:
Any Hit (a.k.a. Masking)
Takes the first intersection along the ray and returns one of the following:
The raytracer is executed on a scene with context.
The scene is represented as a set of separate objects with functions assigned to them:
Context holds different raytracer parameters such as:
Each time a set of rays is created, a context is assigned to them and passed to all the consequent functions.