Surfaces and polyhedra can be rendered in color, using a combination of colored light sources and (in the case of surfaces) surface coloration.
The surface coloration is controlled by a submenu of the Action menu. This allows the user to paint each point of the surface with an arbitrary color, specifying the colors as a function of the surface parameters u,v. The first several options are of the form "Hue = f(u,v)", and sets the Hue of a point on the surface with parameter values u,v to f(u,v). (For these options, the Saturation is set to one and the Lightness to one-half. See below for a discussion of Hue, Saturation, and Lightness.) There is also a "User Defined..." option that brings up a dialog from which a user can specify the Hue, Saturation, and Lightness as functions of u, v.
There are five "light sources", called Source0, Source1, Source2, Source3, and AmbientSource, and all five can have their colors set by the user. The light rays from AmbientSource are "omni-directional". The light rays of Source0 emanate from the ViewPoint and travel in the direction of the point being illuminated, while for each of the remaining three sources, Source1, Source2, and Source3, there is a direction associated with the source (that can be set by the user), and all light rays emenating from the source are parallel to that direction---as if the source were "at infinity". These directions, and the colors of the five sources are all set using the Custom... item of the Set Light Sources submenu of the Settings menu.
Of course, in order to use these color options effectively it is necessary to understand the meaning of the color parameters, and the algorithm by which the surface coloration and the direction and color of the light sources interact to define the color of each patch. This is a fairly complex matter, and to keep this discussion to an acceptable length we will leave some details a little sketchy.
Initially we will explain things entirely within the so-called Red-Green-Blue (or RGB) color model. This description of color corresponds closely to the realities of color monitor hardware (and apparently also to the color "hardware" of the human eye) but more to the point it is the model in which it is easiest to explain the algorithm for coloring a patch. But we will also consider the so-called Hue-Saturation-Lightness (HSL) color model. This model is more closely related to the psychological sensation of color, and for that reason it is the model the program uses to describe the surface coloration function.
In both the RGB model an the HSL model, a color is a vector in the unit cube, i.e., a triple of real numbers each between zero and one inclusive. The difference lies in the interpretation of these three components. For an RGB color c, the three components will be labelled c.r, c.g, and c.b, and represent respectively the intensities of red, green, and blue light in the color, while for an HSL color k, the components are labelled k.h, k.s, and k.l, and represent the hue, saturation and lightness (or brightness) of the color.
A good way to get a feeling for the meaning of RGB color is to examine how a color monitor works. The monitor screen is covered with three lattices of "pixelets": tiny bits of phosphors that glow with either a red or green or blue light when irradiated by an electron beam The brightness of each pixelet is proportional to the flux (i.e., number per second) of electrons passing through it, varying from a minimum of zero to a maximum that is scaled to be one. These pixelets are tiny and very close together, and an actual pixel consists of many pixelets of all three varieties. To make a pixel a pure red, the hardware sees to it that none of the blue or green pixelets within it are irradiated, while all the red pixelets are irradiated with some fixed intensity between zero (giving black) and one (giving the brightest pure red). Of course pure green and pure blue are created analagously. Gray is also easy to understand in the RGB model: if all the red, green, and blue pixelets are "turned on" with the same intensity t, (0 < t < 1), then the pixel appears gray, varying from black to white as t varies from zero to one. The colors of the pixelet phosphors were not chosen arbitrarily. They correspond respectively to three pigments in the retina of the human eye that are responsible for the sensation of color vision. Each phosphor emits wavelengths in the range to which one of the retinal pigments is most sensitive. See the excellent discussion in chapters 35 and 36 of the "Feynman Lectures on Physics" for further details on the physics and physiology of color vision.
Next we describe the algorithm for determining the RGB components of a surface patch, given the surface coloration function and the color and direction of the light sources.
Evaluating the functions Hue(u,v), Saturation(u,v), Lightness(u,v) at one of the vertices of the patch associates an HSL color (k.h,k.s,k.l) with the patch. Using the "transformation of coordinates" explained below, this corresponds to an RGB color we will call s=(s.r,s.g,s.b). (Intuitively, we imagine the whole patch as painted with a paint that reflects a fraction s.r of the rays of red light falling on it, and similarly for green and blue.) Pixels in the patch are colored an RGB color c=(c.r,c.g,c.b) and we will explain how the red component c.r is defined, the others being analagous. In fact c.r is the product of s.r with the sum of five terms, corresponding to the five light sources:
c.r = s.r*(c0*S0.r + c1*S1.r + c2*S2.r + c3*S3.r + SA.r) Here S0.r is the red component of the color of Source0, etc., SA.r is the red component of the color of AmbientSource, and c0 is the absolute value of the cosine of the angle between the normal to the patch and the direction of the light rays from Source0, etc.
There are two small corrections to this formula---and one big one. First the small ones: the result may well be greater than one, in which case it is truncated to one. And second, if the surface is oriented, and the patch is on the back side, then the result (after truncation) is multiplied by 0.6.
The major correction is that the above formula only considers the "diffuse" component of light reflected from a surface, and completely ignores the "specular" component. A discussion of the specular component will be found below in the section on "Phong Shading", the name of the shading model used by the program. Phong shading has provisions for both diffuse and specular components. Here we shall mention only that there are two parameters that control the specular component, which we call the "specular exponent" and "specular ratio" respectively. The first of these determines just how mirror-like a surface behaves with regard to the specular component. (Specular is from the Latin word "speculum", meaning mirror.) If it is equal to zero, then the specular component, like the diffuse component, is independent of the viewing direction, while if the exponent is very large then the surface approximates a perfect reflector, with the specular component only being visible when the viewing direction is close to the direction given by The Law of Reflection (i.e., the Viewing direction and the direction from the light source to the surface make nearly equal angles with the surface normal). On the other hand, the specular ratio determines the relative intensities of the diffuse and specular components. Both of these parameters can be adjusted using the dialog brought up by choosing the Custom... item in the Set Light Sources submenu of the Settings menu. The default values of 30 and 0.4 give subdued highlights, while with values around 60 and 0.6 the highlights are quite concentrated giving the surface a somewhat metallic look when color is used, and an appearance of polished ivory when stereo vision is on.
We finally explain the relation of the HSL coordinates to the RGB coordinates. The Saturation of an RGB color with components (r,g,b) is easiest to define. Let M denote the maximum of r, g, and b, and m their minimum. If M=0, i.e., the color is Black, then the Saturation is defined to be zero. Otherwise let l=(M+m)/2. Then if l < 1/2 the Saturation is defined to be (M-m)/(M+m), while if l > 1/2 the Saturation is defined to be (M-m)/(2-M-m). The Hue and Lightness are somewhat more difficult, and I will give a "geometric" explanation. To follow the discussion, I strongly recommend that the reader draw a large diagram of the unit cube in RGB space and add labels to various vertices and edges as they are named in what follows. Also, to get a better understanding of the RGB-HSL relationship, it is helpful to play with the standard Macintosh Color Picker dialog, since that not only allows one to define a color using one model and then see its coordinates in the other model, but also it displays the actual color on the monitor screen. (The Color Picker dialog can be activated by choosing Set Light Sources... from the Settings menu and then clicking on one of the Set... buttons in the resulting dialog. One thing to be wary of is that, in older versions of the Color Picker the color components are given as the numerator of a fraction whose denominator is 65535.)
We will label the eight vertices of the RGB color cube with color names. The origin O=(0,0,0) is called Black, W=(1,1,1) is White, R=(1,0,0) is Red, G=(0,1,0) is Green, and B=(0,0,1) is Blue. The remaining vertices have one zero component and two components equal to one. They are Y=(1,1,0) the Yellow vertex, C= (0,1,1) the Cyan vertex , and M=(1,0,1) the Magenta vertex. The six vertices R,Y,G,C,B, and M (i.e., all except Black and White) define a (non-planar) hexagon P with the six directed edges RY, YG, GC, CB, BM, and MR. We call this the pure (or saturated) color hexagon. Clearly P consists of all points of the RGB cube having at least one components equal to zero and another equal to one. For points on P it is easy to specify the HSL coordinates. Namely, a point of P has Saturation equal to one, Lightness equal to one-half, and Hue equal to its fraction of the way around the hexagon (starting from Red). So the Red vertex, R, has Hue equal to zero (and also one), Y, has Hue 1/6, G has Hue 1/3, C has Hue 1/2, B has Hue 2/3, and M has Hue 5/6. A point on the Green-Cyan edge GC has coordinates of the form (0,1-t,1) with t between zero and one, and has Hue equal to 1/2 + t/6.
Next consider any point q of the RGB cube with at least one zero component. If all the components of q are zero (i.e., q is Black) then we define its Hue and Lightness to be zero. Otherwise, letting t denote the largest component of q, we can write q=tp for a unique p in P. For such a q we define its Hue to be that of the point p, and its Lightness to be t/2. Note that if t=1 so q=p is on P, we get Lightness one-half, and these definitions reduce to the earlier ones.
Finally, consider an arbitrary point Q of the RGB cube. Let a denote its minimum component, and let J denote the gray color with RGB components (a,a,a). Define q=Q-J. By the choice of a, q is again a point of the RGB unit cube, and moreover it clearly has a zero component. If q is Black then Q=J, so Q is gray, and we define its Hue and Saturation to be zero and its Lightness to be a. If not then, by the previous paragraph, q is uniquely of the form tp for a unique p in P and 0 < t < 1, so we have Q=tp+J. In this case we define the Lightness of Q to be a+(t/2), (i.e., the sum of the Lighness of tp and that of J) and we again define the Hue of Q to be the Hue of p.
We note that it follows that a Lightness of one gives White, independent of Hue and Saturation.
A word should be said about how color behaves during the creation of a rotation or oscillation filmstrip. As we have said elsewhere, a 3D object remains fixed, and we create the illusion of its rotating by rotating the viewpoint in the opposite direction. A moments thought will show that this means the directions of all the light sources should co-rotate with the viewing direction. (Of course, the surface coloration is "painted" onto the surface and so stays fixed relative to the object.)