In this chapter, you’ll learn how to shade three-dimensional objects. Shading produces a much more realistic look and enhances the perception of three-dimensionality. The general idea is to first establish the direction of light rays impacting the object being illuminated and then determine the shading effect the light has on the object’s surface. In the case of a box, which I will discuss next, six flat planes comprise the box’s surface. The orientation of these planes relative to the direction of the light will determine the degree of shading on each plane. To simulate shading, the planes can be filled with dots or lines. Different intensities of shading can be obtained by changing the intensity of the color of the dots or lines and by color mixing.
Normally an object being plotted will appear on a white background. If a background color is used, such as in Figure 7-13, dots or lines may be used to paint the background. Recall from Chapter 1 that new dots overplot old dots and lines always overplot dots and old lines. This means that whether the object being shaded is constructed of dots or lines, they will overplot the background color if it is painted with dots. The disadvantage of using dots is it takes a lot of time to fill the background with dots. Lines are a better alternative in this regard and are preferred if the object can be constructed of lines. If you must use dots in your object, then you must use dots for your background color.
The heart of a shading program is the intensity function, which relates the shading intensity to the orientation of a plane relative to the incoming light direction. You do not specify the position of a light source; you define the direction of the light rays impacting the object from that source. For example, suppose the program calculates that the angle between a plane and the incoming light rays is 50 degrees. The intensity function converts this angle into a shading intensity, which is used to alter the color intensity of the lines or dots.
A considerable amount of research has been carried out on theories of shading in an effort to produce more lifelike computer-drawn images. These images often have a separate shading function for each primary color and take into account the reflectivity and physical characteristics of the surface material. Smooth surfaces will be highly reflective while rough, textured surfaces will scatter the incoming light, producing a higher degree of diffusivity. In your work here, you will keep it simple and use just one shading function and ignore the differences in surface features that can affect the surface’s reflectivity and diffusivity, although they could easily be introduced into the program. Also, you assume the shading of a surface is dependent on only the orientation of that surface relative to the light source and not on its orientation relative to the observer who, as usual, you take to be located in the -z direction.
7.1 Shading a Box
Looking at the top plane of the box defined by corners 0,1,2,3, you can see a unit normal vector at corner 0. This points outward from the plane. You shade the box by drawing lines, shown in blue, which extend across the width of the plane from B to E. These lines are drawn from edge 0,1 to 3,2 and then down the plane, thus shading it. The lines on each face will have an intensity that depends on the orientation of with . You get this orientation by taking the dot product of with . If is facing , the dot product will be negative and the intensity of the lines will be less, which means the tone will be lighter; if is facing away from , the dot product will be positive, the intensity will be greater, and the tone will be darker.
You have been applying your shading intensity, I, to monochrome colors. Even if you use r,g,b color mixing, it is still a monochrome shade, although not a primary color. An extension of this method would be to apply separate intensities to each of the three primary colors. For example, when an artist paints a portrait, he/she might render the light side of the face a light pink. To darken the shaded side, he/she would normally add green, the compliment of red, to the mix. If you look closely at the portraits of an accomplished artist, you will see this is usually how it is done. Rarely would one add black to the mix to darken it. In fact, many painters do not even keep a black pigment on their pallet; they achieve darker colors by mixing the hues with their compliment. The compliment of red is green; of yellow it is violet. Color mixing in painting isn’t quite that simple, of course, but that is the fundamental idea. To accomplish this in your programming, suppose you are shading a red box using an (r,g,b) color mix. Rather than applying an intensity factor to the red to increase its intensity, thus simulating a darkening, you apply the intensity factor to the green, increasing its contribution in the r,g,b mix, thus darkening the red. For the present, in Listing 7-1 you will keep thing simple and simulate shading by increasing the intensity of the color in the dark areas rather than using color mixing. This works well with a monochrome black image, although it has limitations with colored objects.
The definition of the box in Listing 7-1 is contained in the lists in lines 10, 11, and 12. Lines 14, 15, and 16 open lists for the global coordinates, which are returned by the rotation functions rotx, roty, and rotz. They have the same lengths as the x,y,z lists as specified by len(x).
Program SHADEBOX
7.2 Shading a Sphere
Nonlinear shading functions are shown as the red, green, and blue curves in Figure 7-14; the linear one is in black. The non-linear functions give more control over the shading and can produce more realistic effects. They allow you to control the shading by amplifying and extending the lighter shaded areas while more rapidly increasing the transition of intensity into the darker areas. The linear shading function is similar to the one used in Listing 7-1, except that it now starts at I=IA where IA may be greater than zero. The curves begin at I=IA and terminate at I=IB where =+1. IA and IB are parameters that can be adjusted in Listing 7-2. IA>0 will darken the lights. This is sometimes necessary since the tones, when I=0 or close to it, may not transition well to higher regions of I; discontinuities can sometimes be observed. To correct this, start the intensity function at some small value of IA greater than 0. Increasing IA can also be a technique for reducing the brightness of light areas.
Equation 7-10 is your intensity function, . You thus have three parameters with which to adjust I: IA, which regulates the intensity of the lightest areas; IB, which adjusts the darkest areas; and n, which adjusts the transition from light to dark. Higher values of n will produce a more rapid transition. Figure 7-14 shows curves for n=1, 2, 3, and 4. When n=1, the curve becomes linear. There are no definite values for n, IA, and IB; they should be adjusted by trial and error to give visually appealing results.
Regarding colors, the background shown in Figure 7-13 is 'midnightblue'. A good source for color samples is #https://matplotlib.org/examples/color/named_colors.html.
In Listing 7-2, lines 22-24 set the components of the incoming light’s unit vector. Lines 26-28 set the intensity function parameters. These values produce Figure 7-13. Lines 37-39 paint the background with dots. Lines 61-101 plot the longitudes. Note in lines 69 and 70 that dalpha and dphi have been added to alpha2 and phi2 since roundoff errors in the np.arange() function can sometimes fail to close the sphere; this assures it closes. Lines 86-92 determine the components of the at the current values of alpha and phi. Line 93 calculates the dot product ; line 94 calculates the intensity.
Program SHADESPHERE
7.3 Summary
While adding a background color can greatly enhance the visual appearance of an object, shading can also be quite effective. In this chapter, you learned techniques for shading an object. Shading implies the presence of an illuminating light source. In your model, you used the direction of the light rays coming from a source but you did not specify the position of the source. In Listing 7-1, you explored the concept of a shading function as shown in Figure 7-10 and how it determines the intensity of shading on a plane. This depends on the orientation of the plane relative to the direction of the incoming light rays, which is determined by taking the dot product of a unit vector normal to the surface, with a unit vector pointing in the direction of the light rays, . In Listing 7-2, you performed the same shading operations on a sphere. However, you improved on the shading function. Whereas in Listing 7-1 you used a simple linear relation between the shading intensity and the dot product in Listing 7-2 you used a nonlinear relation, as shown in Figure 7-14. This greatly improves the appearance of the shading.