Basics
The Polyray file format is a text-based file format originally designed as input for the polyray ray tracer in the 1990s. The original format has quite a few features we won't be using, and used a parser written using lex and yacc. The subset we'll use will be enough to handle some of the SPD-generated files, and simple enough to parse with basic text file I/O.
Numeric values
Numeric values are comma-separated floats or integers. 3D points, vectors or colors are all given with a set of three comma-separated floats inside '<' and '>'. All colors are floating point with red/green/blue values in the range 0-1, so will need to be scaled by 255 before casting to unsigned char. You may also see "white", which should be interpreted as equivalent to "<1, 1, 1>". Some examples:
background <0.078, 0.361, 0.753> diffuse <1, 0.75, 0.33>, 0.8 angle 45 resolution 512, 512 ...
Background and lights
The background color should be used for any ray that doesn't hit an object. It's the keyword "background" followed by a single RGB color. The default if not specified is black.
Lights use the keyword "light" followed by a RGB color for the light and an XYZ position. There can be multiple lights, which should be added to a list.
background <0.078, 0.361, 0.753> light <0.57735, 0.57735, 0.57735>, <4, 3, 2>
Image and view
Information about the view and image are inside a "viewpoint {...}" block. Inside this block, you may see these:
- from <point>: 3D location of the eye. Default <0, 0, -1>
- at <point>: 3D location at the center of the view. Default <0, 0, 0>
- up <vector>: Vector used to align the image up direction. Does not need to be strictly aligned with the image plane. Default <0, 1, 0>
- angle float: Vertical field of view in degrees. Don't forget to convert to radians! Default 45
- aspect float: Aspect ratio. Polyray assumed a coordinate system with y pointing down, if negative (and all of ours will be negative), that means that y points up. Our default -1
- hither float: Don't consider intersections closer than this to the eye. Rather than check t>0 in your ray-intersection test to tell if the intersection is in front of the eye, check if t>hither. Default 0.001
- resolution int, int: Image width and height. Default 256, 256
For example:
viewpoint {
from <2.1, 1.3, 1.7>
at <0, 0, 0>
up <0, 0, 1>
angle 45
aspect -1
hither 0.01
resolution 512, 512
}
Surface
The surface properties (color, shininess) are defined first, then can be used for one or more objects. The definition follows this format: "define surface-name texture { surface {...} }"
Inside the surface block, expect one or more of these:
- ambient color, float: A color and scale factor to use for the ambient approximation for additional light bouncing around the scene.
- diffuse color, float: A color and scale factor for diffuse reflectance of each light from the surface.
- specular color, float: A color and scale factor for specular reflectance of each light from the surface.
- microfacet Phong float: Which shininess model to use (we're only using the Phong model), along with the numeric value saying how shiny the surface is.
- reflection color, float: A color and scale factor for mirror reflections off of the surface.
- transmission color, float, float: A color, scale factor, and index of refraction for light passing through a transparent surface.
If any of these are not provided, do not include that term, either by explicitly disabling it or using a scale factor of 0.
For example, this would be a valid surface property block:
define txt001
texture {
surface {
ambient <1, 0.75, 0.33>, 0.2
diffuse <1, 0.75, 0.33>, 0.8
}
}
Objects
All objects follow the basic format "object { type object-description surface-name }". We will only be using spheres and polygons. The sphere descripton is a center point and radius. The polygon description is a number of vertices, followed by one 3D point per vertex. For example:
object { sphere <0, 0, 0>, 0.5 txt002 }
object { polygon 3, <-1, -1, 1>, <-1, 1, -1>, <1, -1, -1> txt001 }