DKBtrace Ray-Tracer, Amiga/IBM Version 2.0 "It's free, and it's well worth the price!" This program was written by: David Buck 22C Sonnet Cres. Nepean, Ontario Canada, K2H 8W7 It has been made freely distributable. The author retains the copyright to the program but authorizes free distribution by BBS'es, networks or by magnetic media. The distributer may choose to charge for the cost of the disk but should not sell the software for profit. Non-profit organizations such as clubs may charge for the software so long as the price is reasonable (less than $5.00 more than the cost of the disk) and so long as the buyers are informed that the program is freely distributable. The images and data files generated by the raytracer are the property of the user of the software and may be used for any purpose without restriction. The author makes no guarantees or warantees with this program and claims no responsibility for any damage or loss of time caused by this program. Bug reports may be sent to the author but the author is under no obligation to provide bug fixes, features, or any support for this software. I would also like to place the following conditions on the use of this program: 1) that it should not be used as part of any commercial package without my explicit written consent. 2) if you make any neat and interesting pictures, please send them to me. 3) If you make any changes to the source code, please let me know. I'd like to see what you've done. 4) This text file should accompany the program. I can be reached on the following BBS'es ATX (613) 526-4141 OMX (613) 731-3419 Mystic (613) 731-0088 or (613) 731-6698 FidoNet 1:163/109.9 Bitnet David_Buck@Carleton.CA Section 0.1 - Recent Update History: Version 1.2 First release Version 2.0 Conversion to the IBM done by Aaron A. Collins New textures, Specular and Phong highlighting added by Aaron A. Collins Triangle, Smooth Triangle, Sphere, Plane support added by David Buck RAW, IFF and GIF image mapping added by David Buck and Aaron Collins Transparency and Fog added by David Buck GIF format file reader by Steve Bennett (used with permission) New Noise and DNoise functions by Robert Skinner (used with permission) Aaron Collins can be reached on the following BBS'es Lattice BBS (708) 916-1200 The Information Exchange BBS (708) 945-5575 Stillwaters BBS (708) 403-2826 AAC: As of July of 1990, there will be a Ray-Trace specific BBS in the (708) Area Code (Chicago suburbia) for all you Traceaholics out there. The phone number of this new BBS is (708) 358-5611. I will be Co-Sysop of that board. There is also a new Ray-Trace and Computer-Generated Art specific SIG on Compuserve, GO COMART. And now, back to the DOCS... Version 2.0 includes ANSI-C function prototyping for ALL functions, TARGA format output file capability, and a reversal of the order of writing screen data from the original DKB/QRT "RAW" file format. For IBM's, it has a crude VGA 320x200 by 256 color display rendering ability. If the image requested is larger than 320x200, every other pixel horizontally and vertically is dropped from the display to keep it all on the screen. Version 2.0 compiles under Turbo-C 2.0 on the IBM P.C. and Lattice C 5.05 on the Amiga. The only file which contains the ANSI extensions is dkbproto.h, so for non-ANSI compilers, you only need to remove the declaration of the parameters in the config.h file and the whole thing should compile. There are several example config.h files for Amiga, IBM, and Unix. The appropriate one should be copied over CONFIG.H, and the MAKEFILE should be edited for your particular system and compiler configuration before compilation. Version 2.0 has a significant difference from prior releases: Speed! The new primitives of SPHERE, PLANE, TRIANGLE, etc. greatly speed up tracing. Another significant speed-up is that world X-Y-Z values beyond 10 Million or so are ignored, and ray tracing beyond that distance will cease. This produces 2 minor peculiarities: 1) A black stripe at the horizon point of Pre-2.0 scene description .data files that have "ground" and "sky" planes defined. The planes were traced out to a much greater "infinity" so this effect was unnoticeable, prior to version 2.0. 2) Tiny black pixels in the texture, or "Surface Acne". This is usually caused by rays being refracted or reflected such that the ray does not happen to hit any object, and eventually becomes black in color as it gets too far away and gets clipped. This effect can be minimized by enclosing the scene with distant "walls", "floors", or placing "ocean floors" beneath water, etc. So far, no scenes have required placing such planes behind the camera, unless an "environment map" of sorts is desired. See SKYTEST.DAT for several examples of spurious distant planes. If your "acne" still doesn't go away, it may be due to a large pixel sample area and it's accidentally picking a point which is just inside the primitive being hit. This is a more tricky problem to solve, and anti-aliasing the image will definitely help if this sort of thing occurs. For IBM's, the program PICLAB by the Stone Soup Group offers excellent image post-processing features and has direct TARGA 16/24/32 file format compatibility, and will serve to palette map and translate the TARGA images into .GIF's, etc. The commercial application AUTODESK ANIMATOR offers a CONVERT utility that also does an excellent job of palette mapping a TARGA to .GIF format. COLORIX VGA PAINT also offers TARGA format reading and conversion facilities. Those of you with real TARGA boards can view the files directly in 16 million colors and are lucky and should know it! The Stone Soup Group also produces FRACTINT, the best fractal/Mandelbrot program available at ANY price (and it too is FREE!) for the PC. I (AAC) have borrowed their Public Domain .GIF file reading routines for the Image Map texture. Here is their Copyright Notice from the GIF Decoder module: * DECODER.C - An LZW decoder for GIF * Copyright (C) 1987, by Steven A. Bennett * * Permission is given by the author to freely redistribute and include * this code in any program as long as this credit is given where due. * * In accordance with the above, I want to credit Steve Wilhite, who * wrote the code which this is heavily inspired by... * * GIF and 'Graphics Interchange Format' are trademarks (tm) of * Compuserve, Incorporated, an H&R Block Company. Section 0.5 - Program Description: This program is a ray tracer written completely in C. It supports arbitrary quadric surfaces (spheres, ellipsoids, cones, cylinders, planes, etc.), constructive solid geometry, and various shading models (reflection, refraction, marble, wood, and many others). It also has special-case code to handle spheres, planes, triangles, and smooth triangles. By using these special primitives, the rendering can be done much more quickly than by using the more general quadrics. In order to create pictures with this program, you must describe the objects in the world. This description is a text file called ".data", and defaults to "object" if not specified. Normally, such files are difficult to write and to read. In order to make this task easier, the program contains a two-pass parser to read the data file. It allows the user to easily create complex worlds from simple components. Since the parser allows include files, the user may put the object descriptions into different files and combine them all into one final image. This manual is divided into four main sections. The first section describes the command-line parameters for the program. The second section describes the syntax and semantics of the description language. Some sample worlds and their corresponding images are provided on the disk. The third section details how to display and convert the images using various postprocesors, and section four has a collection of handy hints for using the tracer most effectively as well as some quick start procedures. Section 1 - Command Line Parameters This program is designed to be run from the CLI, although it can be run from the Workbench if desired. From the CLI, the program accepts various parameters: -wxxx width of the picture in pixels (On the Amiga, use 319 for full-sized pictures) -hxxx height of the picture in pixels (On the Amiga, use 400 for full-sized pictures) +v verbose option - print out the scan line number. -v disable verbose option +f produce an output file -f don't produce an output file If the +f option is used, the ray tracer will produce an output file of the picture. This output file describes each pixel with 24 bits (8 bits for red, 8 for green, and 8 for blue). A post processor (Amiga only) called "DumpToIFF" can convert this format to hi-res HAM format (320 x 400) making reasonable choices for the colour registers. For compati- bility, the format of the dump file is the same as the format for the QRT ray tracer. With Version 2.0, you can substitute the "t" character for the "f" character and produce output files directly in the Truevision (R) TARGA 24 format. This format is remarkably like the QRT/DKB raw format, so it was easily done, and allows for a wider range of post-processing programs to be used. The extension .TGA is normally used for such files, but any may be chosen. +d display the picture while tracing -d don't display the picture while tracing If the +d option is used, then the picture will be displayed while the program performs the ray tracing. On the Amiga, this picture is not as good as the one created by "DumpToIFF" because it does not try to make optimum choices for the colour registers. Version 2.0 will produce a display on an IBM-PS/2 compatible VGA/MCGA display in 320x200 x 256 colours if the +d option is given (Anyone for adding in SVGA resolutions??) but the same basic caveat is still applicable: A good post- processor will make better choices of the most popular colors in the image to map to the display. +p wait for prompt (beep and pause) before quitting -p finish without waiting The +p option makes the program wait for a carriage return before exiting (and closing the graphics screen). This gives you time to admire the final picture before destroying it. -ifilename set the input filename -ofilename set output filename If your input file is not "Object.data", then you can use -i to set the filename. The default output filename will be "data.display" on Amiga's, and either "data.dis" or "data.tga" on IBM's, depending on the output file format that is being used. If you want a different output file name, use the -o option. +a[xxx] anti-alias - xxx is an optional tolerance level (default 0.3) -a don't anti-alias The +a option enables adaptive anti-aliasing. The number after the +a option determines the threshold for the anti- aliasing. If the colour of a pixel differs from its neighbor (to the left or above) by more than the threshold, then the pixel is subdivided and super-sampled. The samples are jittered to introduce noise and make the pictures look better. If the anti-aliasing threshold is 0.0, then every pixel is supersampled. If the threshold is 1.0, then no anti-aliasing is done. Good values seem to be around 0.2 to 0.4. +x allow early exit by hitting any key (IBM only) -x lock in trace until finished (IBM only) On the IBM, the -e option disables the ability to abort the trace by hitting a key. If you are unusually clumsy or have CATS that stomp on your keyboard (like I do - AAC :-)), you may want to use it. If you are writing a file, the system will recognize ^C at the end of line if BREAK is on (on the IBM). If you aren't writing a file, you won't be able to abort the trace until it's done. This option was meant for big, long late-nite traces that take ALL night (or longer!), and you don't want them interrupted by anything less important than a natural disaster such as hur- ricane, fire, flood, famine, etc. -bxxx use an output file buffer of xxx kilobytes. (if 0, flush the file on every line - this is the default) The -b option allows you to assign large buffers to the output file. This reduces the amount of time spent writing to the disk and prevents unnecessary wear (especially for floppies). If this parameter is zero, then as each scanline is finished, the line is written to the file and the file is flushed. On most systems, this operation insures that the file is written to the disk so that in the event of a system crash or other catastrophic event, at least part of the picture has been stored properly on disk. -sxxx start tracing at line number xxx. -exxx end tracing at line number xxx. The -s option is provided for when some natural or unnatural catastrophe has occurred, and you want to restart the trace at a given line number after the crash. One is subtracted from the given line number if anti-aliasing is activated (the prior line's being computed is required for the anti-aliasing mech- anism to function properly). It can also be used to re-render parts of an image (perhaps with anti-aliasing turned on). A separate utility can then merge the new lines into the old file. The particularly faint of heart or weak of power supply may want to batch the image in "strips" of 10-20 lines and concatenate them later. -qx rendering quality The -q option allows you to specify the image rendering quality. The parameter can range from 0 to 9. The values correspond to the following quality levels: 0,1 Just show colours. Ambient lighting only. 2,3 Show Diffuse and Ambient light 4,5 Render shadows 6,7 Create surface textures 8,9 Compute reflected, refracted, and transmitted rays. The default is -q9 (maximum quality) if not specified. You may specify the default parameters by modifying the file "trace.def" which contains the parameters in the above format. This filename contains a complete command line as though you had typed it in, and is processed before any options supplied on the command line are recognized. Section 2 - The Object Description Language The Object Description Language allows the user to describe the world in a readable and convenient way. The language delimits comments by the left and right braces ({ and }). Nested comments are allowed, but no sane person uses them anyway, right? The language allows include files to be specified by placing the line: INCLUDE "filename" at any point in the input file (Include files may be nested). Section 2.1 - The Basic Data Types There are several basic types of data: Float Floats are represented by an optional sign (+ or -), some digits, an optional decimal point, and more digits. It does not support the "e" notation for exponents. The following are valid floats: 1.0 -2.0 -4 +34 Vector Vectors are arrays of three floats. They are bracketed by angle brackets ( < and > ), and the three terms usually represent x, y, and z. For example: < 1.0 3.2 -5.4578 > Colour A colour consists of a red component, a green component, a blue component, and possibly an alpha component. All four components are floats in the range 0.0 to 1.0. The syntax for Colours is the word "COLOUR" followed by any or all of the RED, GREEN, BLUE or ALPHA components in any order. For example: COLOUR RED 1.0 GREEN 1.0 BLUE 1.0 COLOUR BLUE 0.56 COLOUR GREEN 0.45 RED 0.3 ALPHA 0.3 Alpha is a transparency indicator. If an object's colour contains some transparency, then you can see through it. If Alpha is 0.0, the object is totally opaque. If it is 1.0, it is totally transparent. For those people who spell "Colour" the American way as "Color", the program also accepts "COLOR" as equivalent to "COLOUR" in all instances. COLOUR_MAP For wood, marble, spotted, agate, granite, and gradient texturing, the user may specify arbitrary colours to use for the texture. This is done by a colour map or "colour spline". When the object is being textured, a number between 0.0 and 1.0 is generated which is then used to form the colour of the point. A Colour map specifies the mapping used to change these numbers into colours. The syntax is as follows: COLOUR_MAP [start_value end_value colour1 colour2] [start_value end_value colour1 colour2] ... END_COLOUR_MAP The value is located in the colour map and the final colour is calculated by a linear interpolation between the two colours in the located range. Section 2.2 - The More Complex Data Types The data types used to describe the objects in the world are a bit more difficult to describe. To make this task easier, the program allows users to describe these types in two ways. The first way is to define it from first principles specifying all of the required parameters. The second way allows the user to define an object as a modification of another object (the other object is usually defined from first principles but is much simpler). Here's how it works: You can use the term DECLARE to declare a type of object with a certain description. The object is not included in the world but it can be used as a "prototype" for defining other objects, as this basic example shows: DECLARE Sphere = QUADRIC <1.0 1.0 1.0> <0.0 0.0 0.0> <0.0 0.0 0.0> -1.0 END_QUADRIC To then reference the declaration elsewhere in your source file or in another included one, and to actually include the object in the world, you would define the object using object definition syntax, like this: OBJECT QUADRIC Sphere SCALE <20.0 20.0 20.0> END_QUADRIC COLOUR White AMBIENT 0.2 DIFFUSE 0.8 END_OBJECT The real power of declaration becomes apparent when you declare several primitive types of objects and then define an object with several component shapes, using either COMPOSITE methods or the CSG methods INTERSECTION, UNION, or DIFFERENCE. More on those later. Also, using the DECLARE keyword can make several objects share a texture without the need for each object to store a duplicate copy of the same texture, for more efficient memory usage. Example: OBJECT { A Hot dog in a Hamburger Bun (?) } UNION QUADRIC Sphere SCALE <20.0, 10.0, 20.0> END_QUADRIC QUADRIC Cylinder_X SCALE <40.0, 20.0, 20.0> END_QUADRIC END_UNION END_OBJECT Viewpoint The viewpoint tells the ray tracer the location and orientation of the camera. The viewpoint is described by four vectors - Location, Direction, Up, and Right. Location determines where the camera is located. Direction determines the direction that the camera is pointed. Up determines the "up" direction of the camera. Right determines the direction to the right of the camera. A first principle's declaration of a viewpoint would look like this: VIEWPOINT LOCATION < 0.0 0.0 0.0> DIRECTION < 0.0 0.0 1.0> UP < 0.0 1.0 0.0 > RIGHT < 1.0 0.0 0.0> END_VIEWPOINT This format becomes cumbersome, however, because the vectors must be calculated by hand. This is especially difficult when the vectors are not lined up with the X, Y, and Z axes as they are in the above example. To make it easier to define the viewpoint, you can define one viewpoint, then modify the description. For example, VIEWPOINT LOCATION < 0.0 0.0 0.0> DIRECTION < 0.0 0.0 1.0> UP < 0.0 1.0 0.0 > RIGHT < 1.0 0.0 0.0 > TRANSLATE < 5.0 3.0 4.0 > ROTATE < 30.0 60.0 30.0 > END_VIEWPOINT In this example, the viewpoint is created, then translated to another point in space and rotated by 30 degrees about the X axis, 60 degrees about the Y axis, and 30 degrees about the Z axis. Unfortunately, even this is somewhat cumbersome. So, in version 2.0, you can now specify two more parameters: SKY LOOK_AT The SKY keyword tells the viewpoint where the sky is. It tries to keep the camera's UP direction aligned as closely as possible to the sky. The LOOK_AT keyword tells the camera to look at a specific point. The camera is rotated as required to point directly at that point. By changing the SKY vector, you can twist the camera while still looking at the same point. Note that a pinhole camera model is used, so no focus or depth-of-field effects are supported at this time. Version 2.0 of the raytracer includes the ability to render fog. To add fog to a scene, place the following declaration outside of any object definitions: FOG COLOUR ... the fog colour 200.0 ... the fog distance END_FOG Shapes Shapes describe the shape of an object without mentioning any surface characteristics like colour, lighting and reflectivity. The most general shape used by this system is called a Quadric Surface. Quadric Surfaces can produce shapes like spheres, cones, and cylinders. The easiest way to define these shapes is to include the standard file "BasicShapes.data" into your program and to transform these shapes (using TRANSLATE, ROTATE, and SCALE) into the ones you want. To be complete, however, I will describe the mathematical principles behind quadric surfaces. Those who are not interested in the mathematical details can skip to the next section. A quadric surface is a surface in three dimensions which satisfies the following equation: A y**2 + B y**2 + C z**2 + D xy + E xz + F yz + G x + H y + I z + J = 0 (Did you really want to know that? I didn't think so. :-) DKB) Different values of A,B,C,...J will give different shapes. So, if you take any three dimensional point and use its x, y, and z coordinates in the above equation, the answer will be 0 if the point is on the surface of the object. The answer will be negative if the point is inside the object and positive if the point is outside the object. Here are some examples: X**2 + Y**2 + Z**2 - 1 = 0 Sphere X**2 + Y**2 - 1 = 0 Cylinder along the Z axis X**2 + Y**2 + Z = 0 Cone along the Z axis General quadric surfaces can be defined as follows: QUADRIC < A B C > < D E F > < G H I > J END_QUADRIC Section 2.3 - Quadric surfaces the easy way Now that doesn't sound so hard, does it? Well, actually, it does. Only the hard-core graphics fanatic would define his objects using the QUADRIC definition directly. Even I don't do it that way and I know how it works (Well, at least I worked it out once or twice :-) - DKB). Fortunately, there is an easier way. The file "BasicShapes.data" already includes the definitions of many quadric surfaces. They are centered about the origin (0,0,0) and have a radius of 1. To use them, you can define shapes as follows: INCLUDE "BasicShapes.data" QUADRIC Cylinder_X SCALE < 50.0 50.0 50.0 > ROTATE < 30.0 10.0 45.0 > TRANSLATE < 2.0 5.0 6.0 > END_QUADRIC You may have as many transformation lines (scale, rotate, and translate) as you like in any order. Usually, however, it's easiest to do a scale first, one or more rotations, then finally a translation. Otherwise, the results may not be what you expect. (The transformations always transform the object about the origin. If you have a sphere at the origin and you translate it then rotate it, the rotation will spin the sphere around the origin like planets about the sun). Section 2.4 - Spheres Since spheres are so common in ray traced graphics, A SPHERE primitive has been added to the system. This primitive will render much more quickly than the corresponding quadric shape. The syntax is: SPHERE
radius END_SPHERE You can also add translations, rotations, and scaling to the sphere. For example, the following two objects are identical: OBJECT SPHERE < 0.0 25.0 0.0 > 10.0 END_SPHERE COLOR Blue AMBIENT 0.3 DIFFUSE 0.7 END_OBJECT OBJECT SPHERE < 0.0 0.0 0.0 > 1.0 TRANSLATE <0.0 25.0 0.0> SCALE <10.0 10.0 10.0> END_SPHERE COLOR Blue AMBIENT 0.3 DIFFUSE 0.7 END_OBJECT Note that Spheres may only be scaled uniformly. You cannot use: SCALE <10.0 5.0 2.0> on a sphere. If you need oblate spheroids such as this, use a scaled quadric "Sphere" shape instead. Section 2.5 - Planes Another primitive provided to speed up the raytracing is the PLANE. This is a flat infinite plane. To declare a PLANE, you specify the direction of the surface normal to the plane (the UP direction) and the distance from the origin of the plane to the world's origin. As with spheres, you can translate, rotate, and scale planes. Examples: PLANE <0.0 1.0 0.0> -10.0 END_PLANE { A plane in the X-Z axes 10 units below the world origin. } PLANE <0.0 1.0 0.0> 10.0 END_PLANE { A plane in the X-Z axes 10 units above the world origin. } PLANE <0.0 0.0 1.0> -10.0 END_PLANE { A plane in the X-Y axes 10 units behind the world origin.} Section 2.6 - Triangles In order to make more complex objects than the class of quadrics will permit, a new primitive shape for triangles has been added. There are two different types of triangles: flat shaded triangles and smooth shaded (Phong) triangles. Flat shaded triangles are defined by listing the three vertices of the triangle. For example: TRIANGLE < 0.0 20.0 0.0> < 20.0 0.0 0.0> <-20.0 0.0 0.0> END_TRIANGLE The smooth shaded triangles use Phong Normal Interpolation to calculate the surface normal for the triangle. This makes the triangle appear to be a smooth curved surface. In order to define a smooth triangle, however, you must supply not only the vertices, but also the surface normals at those vertices. For example: SMOOTH_TRIANGLE { points surface normals } < 0.0 30.0 0.0 > <0.0 0.7071 -0.7071> < 40.0 -20.0 0.0 > <0.0 -0.8664 -0.5 > <-50.0 -30.0 0.0 > <0.0 -0.5 -0.8664> END_SMOOTH_TRIANGLE As with the other shapes, triangles can be translated, rotated, and scaled. NOTE: Triangles cannot be used in CSG INTERSECTION or DIFFERENCE types (described next) since triangles have no clear "inside". The CSG UNION type works acceptably but with no difference from a COMPOSITE object. Section 2.7 - Constructive Solid Geometry (CSG) This ray tracer supports Constructive Solid Geometry in order to make the object definition abilities more powerful. Constructive Solid Geometry allows you to define shapes which are the union, intersection, or difference of other shapes. Unions superimpose the two shapes. This has the same effect as defining two separate objects, but is simpler to create and/or manipulate. Intersections define the space where the two surfaces meet. Differences allow you to cut one object out of another. CSG Intersections, Unions, and Differences can consist of two or more shapes. They are defined as follows: OBJECT INTERSECTION QUADRIC ... END_QUADRIC QUADRIC ... END_QUADRIC QUADRIC ... END_QUADRIC END_INTERSECTION ... END_OBJECT UNION or DIFFERENCE may be used instead of INTERSECTION. The order of the shapes doesn't matter except for the DIFFERENCE shapes. For CSG differences, the first shape is visible and the remaining shapes are cut out of the first (in reverse order from version 1.2 DIFFERENCE's). Constructive solid geometry shapes may be translated, rotated, or scaled in the same way as a Quadric surface. The quadric surfaces making up the CSG object may be individually translated, rotated, and scaled as well. When using CSG, it is often useful to invert an shape so that it's inside-out. The INVERSE keyword can be used to do this for any SPHERE, PLANE, or QUADRIC. When INVERSE is used, the "inside" of the object is flipped to be the "outside". For Planes, "inside" is defined to be "in the opposite direction to the "normal" or "up" direction. Note that performing an INTERSECTION between an shape and some other INVERSE shapes is the same as performing a DIFFERENCE. In fact, the DIFFERENCE is actually implemented in this way. Section 2.8 - Objects There is more to defining an object than just its shape. You must tell the ray tracer about the properties of the surface like colour, alpha, reflectivity, refractivity, the index of refraction, and so on. To do this, you must define Objects. A typical object definition looks something like this: OBJECT QUADRIC Sphere TRANSLATE < 40.0 40.0 60.0 > END_QUADRIC TEXTURE 0.05 END_TEXTURE AMBIENT 0.3 DIFFUSE 0.7 REFLECTION 0.3 REFRACTION 0.3 IOR 1.05 COLOUR RED 1.0 GREEN 1.0 BLUE 1.0 ALPHA 0.5 END_OBJECT The following keywords may be used when defining objects: AMBIENT value - Ambient light is light that is scattered everywhere in the room. An object lit only by ambient light will appear to have the same brightness over the entire surface. The default value is very little ambient light (0.3). The value can range from 0.0 to 1.0. DIFFUSE value - Diffuse light is light coming from a light source that is scattered in all directions. An object lit only by diffuse light looks like a rubber ball with a spot light shining on it. The value can range from 0.0 to 1.0. By default, there is mostly diffuse lighting (0.7). BRILLIANCE value - Objects can be made to appear more metallic by increasing their brilliance. This controls the tightness of the basic diffuse illumination on objects and minorly adjusts the appearance of surface shininess. The default value is 1.0. Higher values from 3.0 to about 10.0 can give objects a somewhat more shiny or metallic appearance. This is best used in concert with either SPECULAR or PHONG highlighting. REFLECTION value - By setting the reflection value to be non-zero, you can give the object a mirrored finish. It will reflect all other objects in the room. The value can range from 0.0 to 1.0. By default there is no reflection. REFRACTION value - By setting the refraction value to be non-zero, the object is made transparent. Light will be refracted through the object like a lens. The value can be set between 0.0 and 1.0. There is no refraction by default. IOR value - If the object is refracting light, then the IOR or Index of Refraction should be set. This determines how dense the object is. A value of 1.0 will give no refraction. The Index of Refraction for Air is 1.0, Water is 1.33, glass is 1.5, and diamond is 2.4. PHONG value - Controls the amount of Phong Specular Reflection highlighting on the object. Causes bright shiny spots on the object, the colour of the light source that is being reflected. The size of the spot is defined by the value given for PHONGSIZE below. PHONG's value is typically from 0.0 to 1.0, where 1.0 causes complete saturation of the object's colour to the light source's colour at the brightest area (center) of the highlight. There is no PHONG highlighting given by default. PHONGSIZE value - Controls the size of the PHONG Highlight on the object, sort of an arbitrary "glossiness" factor. Values range from 1.0 (Very Dull) to 100 (Highly Polished). Default PHONGSIZE is 40 (plastic?) if not specified. This is simulating the fact that slightly reflect- ive objects, especially metallic ones, have microscopic facets, some of which are facing in the mirror direction. The more that are facing that way, the shinier the object appears, and the tighter the specular highlights become. Phong measures the average of facets facing in the mirror direction from the light sources to the viewer. SPECULAR value - Very similar to PHONG Specular Highlighting, but a better model is used for determining light ray/object intersection, so a more credible spreading of the highlights occur near the object horizons, supposedly. PHONG is thus included for mostly academic reasons, but try them both and you decide which you like better. This effect is most obvious for light sources behind objects. The size of the spot is defined by the value given for ROUGHNESS below. Like PHONG, SPECULAR values are typically from 0.0 to 1.0 for full saturation. Default is no SPECULAR highlighting. ROUGHNESS value - Controls the size of the SPECULAR Highlight on the object, relative to the object's "roughness". Values range from 1.0 (Very Rough) to 0.001 (Very Smooth). The default value if not specified is 0.05 (Plastic?). The roughness or average directional distribution of the microfacets is facing in the same direction as the perpen- dicular surface "normal" cause the most notable reflection of the highlight to the observer. COLOUR value - The colour of an object can be set by using this option. The value is a colour or a colour constant. For example: COLOUR RED 1.0 BLUE 0.4 - or - DECLARE Yellow = COLOUR RED 1.0 GREEN 1.0 ... COLOUR Yellow TRANSLATE vector ROTATE vector SCALE vector - Objects can be translated, rotated, and scaled just like surfaces. This feature is included for consistency. LIGHT_SOURCE - If the LIGHT_SOURCE keyword is used in the definition of an object, then the object is included in the list of light sources. It can light objects and produce shadows. (You should also specify the COLOUR of the light source). Light sources have a peculiar re- striction: The light source MUST be TRANSLATED to it's final position in the scene, so the normal way to define a light source is a sphere or quadric centered about the origin, then TRANSLATED to where desired in the final scene. For example: OBJECT SPHERE <0.0 0.0 0.0> 2.0 END_SPHERE {could be a quadric, too.} TRANSLATE <100.0 120.0 40.0> LIGHT_SOURCE COLOUR RED 1.0 GREEN 1.0 BLUE 1.0 AMBIENT 1.0 DIFFUSE 0.0 END_OBJECT TEXTURE - The texture feature is an experiment into functionally based modelling. This feature allows you to assign more interesting colouring schemes to objects. Many procedural surface textures are provided, and by using different colour maps with them, nearly infinite permutations are possible. For example, you can make some object look like wood or marble, etc. The basic TEXTURE syntax is as follows: TEXTURE 0.05 WOOD TURBULENCE 0.2 TRANSLATE < 1.0 2.0 3.0 > ROTATE < 0.0 10.0 40.0 > SCALE < 10.0 10.0 10.0 > END_TEXTURE The transformations are optional. They allow you to transform the texture independent of the object itself. If you are doing animation, then the transformations should be the same as the object transformations so that the texture follows the object. The floating-point value given immediately following the texture keyword is an optional "texture randomness" value, which causes a minor random scattering of calculated colour values and produces a sort of "dithered" appearance. Instead of using WOOD, you may use MARBLE, BOZO, CHECKER, or a handful of other interesting textures. The WOOD and MARBLE textures are perturbed by a turbulence function. This makes them look more random and irregular than they would normally appear. The amount of turbulence can be changed by the TURBULENCE keyword followed by a number. Values from 0.1 to 0.3 seem to give the best results. The default is 0.0, or no turbulence. Note some of the textures given are coloration textures, such as MARBLE, WOOD CHECKER, GRANITE, and AGATE. These work with colour maps, and have default "colour maps" they resort to if none are given. The rest of the textures available are "surface perturbation" textures, and do not dir- ectly affect the colour of the object, but rather the surface's apparent orientation in space. Examples of this are WAVES, RIPPLES, DENTS, BUMPS, and WRINKLES. Note that any given texture may include up to two actual textures, one coloration and one surface perturbation choice per texture. This would allow rippled wood, or dented granite combinations, etc., but keep in mind that any transformations applied to one texture (i.e. TRANSLATE or SCALE) will also transform the other one in the same fashion. The following textures are available: CHECKER texturing gives a checker-board appearance. This option works best on planes. When using the CHECKER texturing, you must specify two colours immediately following the word CHECKER. These colours are the colours of alternate squares in the checker pattern. The default orientation of the CHECKER texture is on an X-Z plane (good for ground work, etc.) but to use it on an object which has mostly X-Y orientation (such as a sphere, for instance), you must ROTATE the texture. To rotate the CHECKER texture onto an X-Y plane: TEXTURE CHECKER COLOUR White COLOUR Red SCALE <10.0 10.0 10.0> ROTATE <-90.0 0.0 0.0> { Checkers now in the X-Y plane... } END_TEXTURE As mentioned above, for coloration textures such as WOOD, MARBLE, and BOZO, etc., you may change the colouring scheme by using a colour map. This map allows you to convert numbers from 0.0 to 1.0 (which are generated by the ray tracer) into ranges of colours. For example, the default BOZO colouring can be specified by: TEXTURE BOZO COLOUR_MAP [0.0 0.4 COLOUR White COLOUR White] [0.4 0.6 COLOUR Green COLOUR Green] [0.6 0.8 COLOUR Blue COLOUR Blue] [0.8 1.0 COLOUR Red COLOUR Red] END_COLOUR_MAP END_TEXTURE BOZO texture basically takes a noise function and maps it onto the surface of an object. This "noise" is defined for every point in space. If two points are close together, they will have noise values that are close together. If they are far apart, their noise values will be fairly random relative to each other. The easiest way to see how it works is to try it. With a good choice of colours it produces some of the most realistic looking cloudscapes you have ever seen. Try a cloud color map such as: TEXTURE BOZO TURBULENCE 1.0 { A blustery day. For a calmer one, try 0.2 } COLOUR_MAP [0.0 0.5 COLOUR RED 0.5 GREEN 0.5 BLUE 1.0 {blue to blue} COLOUR RED 0.5 GREEN 0.5 BLUE 1.0] [0.5 0.6 COLOUR RED 0.5 GREEN 0.5 BLUE 1.0 {blue to white} COLOUR RED 1.0 GREEN 1.0 BLUE 1.0] [0.6 1.001 COLOUR RED 1.0 GREEN 1.0 BLUE 1.0 {white to grey} COLOUR RED 0.5 GREEN 0.5 BLUE 0.5] END_COLOUR_MAP SCALE <800.0 800.0 800.0> TRANSLATE <200.0 400.0 100.0> END_TEXTURE (Check out sunset.dat for a really neat (but slow) sky pattern) The color map above indicates that for small values of texture, use a sky blue color solidly until about halfway turbulent, then fade through to white on a fairly narrow range. As the white clouds get more turb- ulent and solid towards the center, pull the color map toward grey to give them the appearance of holding water vapor (like typical clouds). SPOTTED - Spotted texture is a sort of swirled random spotting of the colour of the object. If you've ever seen a metal organ pipe you know about what it looks like (a galvanized garbage can is close...) Play with this one, it might render a decent cloudscape during a very stormy day (?). No extra keywords are required. Should work with colour maps. With small scaling values, looks like masonry or concrete. AGATE - this texture is similar to Marble, but uses a different turb- ulence function. The TURBULENCE keyword has no effect, and as such it is always very turbulent. GRADIENT - this is a specialized texture that uses approximate local coordinates of an object to control colour map gradients. This texture ONLY works with colour maps (one MUST be given!) and has a special triple given after the GRADIENT keyword, which specifies any (or all) axes to perform the gradient action on. (Example: a Y gradient <0.0, 1.0, 0.0> will give an "altitude colour map", along the Y axis). Values other than 0.0 are taken as 1.0 and others are meaningless. For smooth repeating gradients, you should use a nearly "circular" colour map, that is, one in which the first colour value (0.0) is the same as the last one (1.001) so it "wraps around" and will cause smooth repeating gradient patterns. Scaling the texture is normally required to achieve the number of repeating shade cycles you want. Transformation of the texture is useful to prevent a "mirroring" effect from either side of the central 0 axes. Here is an example of a gradient texture which uses a sharp "circular" color mapped gradient rather than a smooth one, and uses both X and Y gradients to get a diagonally-oriented gradient. It produces a dandy candy cane texture! TEXTURE GRADIENT < 1.0 1.0 0.0 > COLOUR_MAP [0.00 0.25 COLOUR RED 1.0 GREEN 0.0 BLUE 0.0 COLOUR RED 1.0 GREEN 0.0 BLUE 0.0] [0.25 0.75 COLOUR RED 1.0 GREEN 1.0 BLUE 1.0 COLOUR RED 1.0 GREEN 1.0 BLUE 1.0] [0.75 1.001 COLOUR RED 1.0 GREEN 0.0 BLUE 0.0 COLOUR RED 1.0 GREEN 0.0 BLUE 0.0] END_COLOUR_MAP SCALE <30.0 30.0 30.0> TRANSLATE <30.0 -30.0 0.0> END_TEXTURE You may also specify a TURBULENCE value with the gradient to give a more irregular colour gradient. This may help to do neat things like fire or coronas. GRANITE - A colouring texture. This uses a simple 1/f fractal noise function to give a pretty darn good grey granite texture. Typically used with small scaling values (2.0 to 5.0). Also looks good with a little dithering (texture randomness). Should work with colour maps, so try your hand at pink granite or alabaster! RIPPLES - As mentioned above, you may optionally specify a surface perturbation texture which can be used in conjunction with the above coloration textures. RIPPLES is one example of a surface perturbation texture. This texture makes the surface look like ripples of water. The RIPPLES option requires a value to determine how deep the ripples are: TEXTURE WOOD RIPPLES 0.3 TRANSLATE < 1.0 2.0 3.0 > ROTATE < 0.0 10.0 40.0 > SCALE < 10.0 10.0 10.0 > END_TEXTURE (In this case, the WOOD, MARBLE, or BOZO, etc. keywords are optional). If a different colouring is specified (WOOD, MARBLE, or BOZO), then the COLOUR parameter is ignored (except for light sources where it gives the light colour or when rendering with a low -q option). WAVES - Another option that you may want to experiment with is called WAVES. This works in a similar way to RIPPLES except that it makes waves with different frequencies. The effect is to make waves that look more like deep ocean waves. (I haven't done much testing on WAVES, so I can't guarantee that it works very well). Both WAVES and RIPPLES respond to a texturing option called PHASE. The PHASE option allows you to create animations in which the water seems to move. This is done by making the PHASE increment slowly between frames. The range from 0.0 to 1.0 gives one complete cycle of a wave. BUMPS - Approximately the same turbulence function as SPOTTED, but uses the derived value to perturb the surface normal. This gives the impression of a "bumpy" surface, random and irregular, sort of like an orange. After the BUMPS keyword, supply a single floating point value for the amount of surface perturbation. Values typically range from 0.0 (No Bumps) to 1.0 (Extremely Bumpy). Values beyond 1.0 may do wierd things. DENTS - Also a surface normal perturbing texture. Interesting when used with metallic textures, it gives impressions into the metal surface that look like dents. A single value is supplied after the DENTS keyword to indicate the amount of denting required. Values range from 0.0 (No Dents) to 1.0 (Fairly Dented). Use larger values at your own risk... Scale the texture to make the pitting more or less frequent. WRINKLES - This is sort of a 3-D (normal perturbing) GRANITE. It uses a similar 1/f fractal noise function to perturb the surface normal in 3D space. With ALPHA values of greater than 0.0, could look like wrinkled cellophane. Requires a single value after the WRINKLES keyword to indicate the amount of wrinkling desired. Values from 0.0 (No Wrinkles) to 1.0 (Very Wrinkled) are typical. IMAGEMAP - This is a very special coloration texture that allows you to import a bitmapped file in RAW format (the format output by the ray- tracer), IFF format or Compuserve GIF format and map that bitmap onto an object. In the texture of an object, you must give the IMAGEMAP key- word, the format, and a file name. The syntax is: IMAGEMAP [gradient] RAW "filename [ONCE]" or IMAGEMAP [gradient] IFF "filename [ONCE]" or IMAGEMAP [gradient] GIF "filename [ONCE]" The texture will then be mapped onto the object as a repeating pattern. The ONCE keyword places only one image onto the object instead of an infinitely repeating tiled pattern. When ONCE is used, the object's default colour is used as the colour outside of the image. By default, the image is mapped onto the XY plane in the range (0.0, 0.0) to (1.0, 1.0). If you would like to change this default, you may use an optional gradient vector after the word IMAGEMAP. This vector indicates which axes are to be used as the u and v (local surface X-Y) axes. The vector should contain one positive number and one negative number to indicate the u and v axes, respectively. You may translate, rotate, and scale the texture to map it onto the object's surface as desired. Here is an example: INCLUDE "BasicShapes.data" OBJECT QUADRIC Plane_XY END_QUADRIC TRANSLATE <0.0 -20.0 0.0> TEXTURE { make this texture use the x and z axes for the mapping. } IMAGEMAP <1.0 0.0 -1.0> GIF "image.gif" SCALE <40.0 40.0 40.0> END_TEXTURE END_OBJECT When I was bored with nothing to do, I decided that it would be neat to have turbulent texture maps. So, I said - "what the hell!" You can specify TURBULENCE with texture maps and it will perturb the image. It may give some bizarre results. Is this useful? I dunno. It was easy to do so I did it. Try it out and see what you get. Section 2.9 - Composite Objects Often it's useful to combine several objects together to act as a whole. A car, for example, consists of wheels, doors, a roof, etc. A composite object allows you to combine all of these pieces into one object. This has two advantages. It makes it easier to move the object as a whole and it allows you to speed up the ray tracing by defining bounding shapes that contain the objects. (Rays are first tested to see if they intersect the bounding shape. If not, the entire composite object is ignored). Composite objects are defined as follows: COMPOSITE OBJECT ... END_OBJECT OBJECT ... END_OBJECT ... SCALE < 2.0 2.0 2.0 > ROTATE < 30.0 45.0 160.0 > TRANSLATE < 100.0 20.0 40.0 > END_COMPOSITE Composite objects can contain other composite objects as well as regular objects. Composite objects cannot be light sources (although any number of their components can). This is because it is nearly impossible to determine the true "center" of the composite object, and our light sources are pinpoint ray sources from the center of the light source object, wherever that may be. Section 2.95 - Bounding Shapes Let's face it. This program is no speed demon. You can save yourself a lot of time, however, if you use bounding shapes around any complex objects. Bounding shapes tell the ray tracer that the object is totally enclosed by a simple shape. When tracing rays, the ray is first tested against the simple bounding shape. If it strikes the bounding shape, then the ray is further tested against the more complicated object inside. To use bounding shapes, you simply include the following lines into the declaration of your OBJECT or COMPOSITE_OBJECT: BOUNDED_BY a shape END_BOUND An example of a Bounding Shape: OBJECT INTERSECTION SPHERE <0.0 0.0 0.0> 2.0 END_SPHERE PLANE <0.0 1.0 0.0> 0.0 END_PLANE PLANE <1.0 0.0 0.0> 0.0 END_PLANE END_INTERSECTION BOUNDED_BY SPHERE <0.0 0.0 0.0> 2.0 END_SPHERE END_BOUND END_OBJECT The best bounding shape is a SPHERE since this shape is highly optimized. Any shape may be used, however. Section 3 - Showing the final pictures When the ray tracer draws the picture on the screen, it does not make good choices for the colour registers. Without knowing all the needed colours ahead of time, only approximate guesses can be made. A post- processor is really needed to view the final image correctly. A post- processor has been provided for the Amiga which scans the picture and chooses the best possible colour registers. It then redisplays the picture. For the Amiga, "DumpToIFF" can optionally save this picture in IFF format. The syntax for the DumpToIFF post-processor is: DumpToIFF filename where the filename is the one given in the -o parameter of the ray tracer. If you didn't specify the -o option, then use: DumpToIFF data.dis If you want to save to an IFF file, then put the name of the IFF file after the name of the data file: DumpToIFF data.dis picture This will create a file called "picture" which contains the IFF image. For the IBM, you will probably want to use the -t option and write the image out in TARGA 24 format. If you have a TARGA or compatible display adapter, you may view the picture in the full 16 million colors (that's why they still cost the big $$ bucks). If you don't, there are several post-processing programs available to convert the TARGA true-color image into a more suitable color-mapped image (such as .GIF). If you have a VGA or MCGA adapter capable of 320x200 by 256 colors, then you may use the -d option which will display the image as it generates using only approximate screen colors. No hardware test is performed, so if you don't have a VGA or MCGA, -> DON'T <- use the -d option! When displaying the image to screen, a HSV conversion method is used (hue, saturation, value). This is a convenient way of translating colors from a "true color" format (16 million) down a "colour mapped" format of something reasonable (like 256), while still approximating the color as closely as the available display hardware permits. As mentioned previously, the tracer has no way of knowing which colors will be finally used in the image, nor can it deal properly with all of the colors which will be generated (up to 16M), so only 4 shades each of 64 possible hues are mapped into the palette DAC, as well as black, white, and two grey levels. The advantage a post-processor has in choosing mapped colors is that it can throw away all the unused colors in the palette map, and thereby free up some space for making better gradient shades of the colors that are actually used. There are several available image processing programs that can do this, a public domain one that is very good is PICLAB, by the Stone Soup Group (the folks who brought you FRACTINT). The procedure is to load the TARGA file, then use the MAKEPAL command to generate a 256 color map which is the histogram-weighted average of the most-used colors in the image (You could also PLOAD a palette file from FRACTINT or one you previously had saved using PSAVE). You then MAP the palette onto the image one of two ways: 1) If the DITHER variable is OFF, a nearest-match-color-fit is used, which can sometimes produce unwanted "banding" of colored regions (called false contours). 2) If the DITHER variable is ON, then a standard dither is used to determine final color values. This is much better at blending the color bands, but can produce noise in reflections and make mirrors appear dirty or imperfect. Then you would typically SHOW the image or GSAVE it into GIF format. While the picture is still in the unmapped form (TARGA, etc.) you can perform a variety of advanced image processing transformations and conversions, so save the .TGA or .RAW files you make (in case you ever get a TARGA card, or give them to a friend who has one!). A commercial product that also does a good job of nearest-match-color- fit is the CONVERT utility of The AutoDesk Animator. However, the dither effect is not as good as that of PICLAB. To convert the file in AA's CONVERT, you LOAD TARGA, then in the CONVERT menu, go to the SCALE function and just hit RENDER. Click on the DITHER (lights up with an asterisk when on) if you want it to use it's dithering. CONVERT will scale (if asked to) and then do a histogram of total used colors like PICLAB, but then makes 7 passes on the color map and image to determine shading thresholds of each hue. This nearly eliminates the color banding (false contours) without resorting to dithering. By now you must get the feeling DITHER is a 4-letter word. If you have a low- resolution display, it is. If you have too few colors, however, it can be a saving grace. At resolutions of 640x400 or higher the "spray paint" effect of dithering and anti-aliasing is much less noticeable, and effects a much smoother blending appearance. Section 4 - Handy Hints/Quick Start - To see a quick version of your picture, use -w64 -h80 as command line parameters on the Amiga. For the IBM, try -w80 -h50. This displays the picture in a small rectangle so that you can see how it will look. - Try using the sample default files for different usages - QUICK.DEF shows a fast postage-stamp rendering (80x50, as above) to the screen only, LOCKED.DEF will display the picture with anti-aliasing on (takes forever) with no abort (do this before you go to bed...). The normal default options file TRACE.DEF is read and you can supersede this with another .DEF file by specifying it on the command line, for example: trace -iworld.dat -oworld.out quick.def - When translating light sources, translate the OBJECT, not the QUADRIC surface. The light source uses the center of the object as the origin of the light. - When animating objects with solid textures, the textures must move with the object, i.e. apply the same ROTATE or TRANSLATE functions to the texture as to the object itself. - You can declare constants for most of the data types in the program including floats and vectors. By combining this with INCLUDE files, you can easily separate the parameters for an animation into a separate file. - The amount of ambient light plus diffuse light should be less than or equal to 1.0. The program accepts any value, but may produce strange results. - When using ripples, don't make the ripples too deep or you may get strange results (the dreaded "digital zits"!). - Wood textures usually look better when they are scaled to different values in x, y, and z, and rotated to a different angle. - You can sort of dither a colour by placing a floating point number into the texture record: TEXTURE 0.05 END_TEXTURE This adds a small random value to the intensity of the diffuse light on the object. Don't make the number too big or you may get strange results. Better results can be obtained, however, by doing the dithering in a post-processor. - You can compensate for non-square aspect ratios on the monitors by making the RIGHT vector in the VIEWPOINT longer or shorter. A good value for the Amiga is about 1.333. This seems ok for IBM's too at 320x200 resolution. If your spheres and circles aren't round, try varying it. - If you are importing images from other systems, you may find that the shapes are backwards (left-to-right inverted) and no rotation can make them right. All you have to do is negate the terms in the RIGHT vector of the viewpoint to flip the camera left-to-right. - By making the DIRECTION vector in the VIEWPOINT longer, you can achieve the effect of a zoom lens. - When rendering on the Amiga, use a resolution of 319 by 400 to create a full sized HAM picture. Section 5 - Known Bugs There is a bug in the code to use Vector constants. The fix involves re-working the parser quite a bit and I don't want to do that now. Section 6 - Concluding remarks I'm sure that there are bugs in the code somewhere, but I've done my best to remove all the bugs I could find. I also think that the object description language needs to be re-worked. Its current syntax is a bit cumbersome. The system could also use a good graphical interface :-). To that end, a conversion utility is supplied which will take in a Sculpt-Animate 4-D object and map it into DKB's primitive TRIANGLES. For the IBM, we have heard, but cannot confirm, there is a utility around which will convert AUTOCAD .DXF files into Sculpt-4D files. If anybody has it or any info about it, please contact either David Buck or Aaron Collins. The IBM version is also supplied with two stand-alone TARGA-24 utilities which were written by Aaron A. Collins. These are HALFTGA, which will chop a TARGA-24 file in half in both X and Y dimensions for low- resolution systems, and another file called GLUETGA which will paste together several TARGA-24 files (of any resolution) into one. This is principally for concatenating together several partial (interrupted) trace output files into one. I would like to thank Rick Mallett from Carleton University for his help in testing this program, for his comments and suggestions, and for creating the data file for ROMAN.DATA - awesome! I would also like to thank my beta testers for all the help, bug reports, suggestions, comments, and time spent. This version of the ray tracer wouldn't have been possible without them. Thanks guys. Enjoy, David Buck