This ray tracer is based on the one featured in Peter Shirley's "Ray Tracing in a Weekend", which is a great introduction to this exciting field. I decided that it would be fun to learn Swift while following along in the book. The result is wert.
There weren't many decisions to make, but I'll document the major ones that I remember here before I forget them.
- Use of stucts: I pretty much used
structfor everything by default, with the exception of materials. For most of the types this makes sense, but it made dealing withhitablea bit odd when defining the scene. I'll need to revisit this decision if/when I want to treat objects polymorphically in the same list. - A protocol for
hitable: This seems right, since it is defined as a pure virtual interface in the book. - Use of extension for
hitablelist: I found that I could extendArrayto implement thehitablelisttype from the book by using a conditional conformance. - Use of
Float: The book uses 32-bit floats and I wanted to follow this decision, even though Swift seems to preferDouble. This leads to quite a few places where conversion toFloatis required, but I like seeing the process memory hover around 1.2 MB when rendering a scene.
This type defines the needed operations for vector calculations (addition, subtraction, multiplication, division) between vectors and vectors and scalars. It stores the data in an array of Floats.
This type defines a ray with two points, A and B. A is the origin and B is the direction. You can calculate a point along the ray by giving it the parameter t, which represents the distance from the origin along the ray. Negative values of t represent the opposite direction.
This is the primary extension point for adding new geometric objects. Currently there is support for spheres and lists of hitable things, though the list of things must be of the same concrete type right now.
The protocol tests to see if a ray intersects with the geometry in a certain range, and produces a hit record. This records the point on the geometry (p), where that point lies along the ray (t), and the surface normal of the hit. It also contains an optional material reference. It returns true if a hit occurs, and false otherwise.
Materials define how the light interacts with an object when a hit occurs. It produces a ray representing which direction the incoming ray will continue, along with an attenuation which represents the intensity of the scattered ray. If the material completely absorbs incoming light this will return false. Otherwise, if it produced a scattered ray, it will return true.
