FART was my semester project for the Computer Science 658 class at Grand Valley State University. My goal is for FART to be a distributed, object-oriented raytracer. The name is a recursive acronym taking inspiration from LAME. It stands for Fart Ain't a RayTracer.
FART takes as input a scene-description file in an ASCII-based, hierarchical input file format. After the scene file is parsed, it will be raytraced (rendered) according to the render options. Some of these options can be specified on the command line and others can be specified in the scene description file. When a given option can be specified both places, the command-line options will override what is in the scene file.
Rendering can be done using the built-in distributed algorithm. Command-line options will be utilized to specify a “host file” which can contain a list of hosts to use while rendering the scene. The algorithm is fault-tolerant so that if one of the worker nodes goes down the work can be reorganized to complete that section of the image.
You can retrieve a copy of FART from my Git repository using the command
$ git clone git://holtrop.mooo.com/fart.git
You'll need these packages to build:
rubylibfl-devlibfreeimage-dev$ ./configure $ make
Example:
$ ./fart scenes/infinity.fart
Usage:
Usage: ./fart [options] <scene-file>
Options:
-o|--output-file <output-file-name>
-w|--width <image-width>
-h|--height <image-height>
-m|--multisample <level>
-f|--field-of-view <vertical-fov>
-d|--max-depth <max-recursion-depth>
-a|--ambient-occlusion <ambient-occlusion-level>
-p|--preview (means -w400 -h300 -m1 -d8 -a0)
--hosts <hosts-file>
See the syntax page.
I can write .bmp files but I'm not doing anything with scene data yet.
FART can intersect a ray with a sphere but doesn't have lighting/shading/material colors yet…
Cheap lighting based on implicit light source at the viewpoint
Multisampling is working (back to a flatly-shaded sphere to show the anti-aliasing effect on the edges)
Added a Plane shape type, I really need to get some better lighting working
Phong shading model working with ambient, diffuse, and specular light components
Added a Box object. No, it didn't take 45 revisions just for that. I've been working on the parser for the scene input files a lot as well.
Added a Cyl object. Cyl objects can be cones or cylinders - they have a bottom radius, a top radius, and a height.
Boolean intersections working. I had to rework the way I was returning intersections to also return a reference to the actual shape that was intersected with so that Intersect shapes would really return the child shape that produced the point.
A few bug fixes, and added Union and Subtract shape types.
More bug fixes, and reading the scene description from a file is finally working!
Material definitions working
Recursion working for transparent objects. Rays sent from surface point to each light source now intersect with other objects to produce shadows depending on the transparency of the objects between the surface point and the light source.
Added scenes/csg.fart as an example of doing CSG. Also fixed a bug in the loading of boolean objects.
Changed intersection method to also return surface normals (instead of accessing them through a separate function, getNormalAt()). This allowed Subtract objects to invert the normals obtained by the sub-object being subtracted out. This, in turn, allowed subtractions of subtractions to re-invert them, and so on and so forth…
Created from scenes/infinity.fart
Created from scenes/die.fart
Light passing through transparent objects is colored by the objects
Exposure function replaced saturation model - thanks Nick!
| |
| Before Exposure | After Exposure |
|---|
Soft shadows possible with “radius” and “jitter” keywords on light objects
Nick inspired me to add ambient occlusion
| |
| Before ambient occlusion | After ambient occlusion |
|---|
Added Extrude objects
Added shape definitions for easy shape reuse
Created from scenes/dw.fart
Added scene file scripting with variables, expressions, and control structures. Sample output showing result of a doubly-nested for() loop.
Created from scenes/for-test.fart
*** Beginning scene render ***
Parameters:
----------------------------------------
Width: 320
Height: 240
Multisample Level: 2
Ambient Occlusion Level: 0
Vertical Field of View: 60
Max Depth: 10
----------------------------------------
*** Ending scene render ***
| |
Render time: 156.877 seconds (2 minutes, 36.8771 seconds) |
|
Added if statements which can take optional elsif clauses and an optional terminating else
Created from scenes/if-test.fart
*** Beginning scene render ***
Parameters:
----------------------------------------
Width: 320
Height: 240
Multisample Level: 2
Ambient Occlusion Level: 0
Vertical Field of View: 60
Max Depth: 10
----------------------------------------
*** Ending scene render ***
| |
Render time: 17.8504 seconds |
|
More fun with for() loops… created from scenes/dw-circle.fart
I finally got around to implementing Refraction. Equations for refracted rays derived from Snell's_law.