Learn to Program using Alice

Understanding Lighting in Alice 2.0

Baldwin shows you how to use emissive color, ambient light, the default light, a directional light, a light bulb, and a spot light to illuminate your Alice world.  He also shows you how to use shading, color, and specular reflection in your illumination scheme, as well as how to create shadows.

Published:  November 8, 2007
By Richard G. Baldwin

Alice Programming Notes # 200


Preface

General

Creating scenes that appear to be three-dimensional on a flat two-dimensional screen is all about creating optical illusions.  There are many important aspects to creating these optical illusions in 3D programming, not the least of which is lighting and illumination.

This document presents a relatively brief explanation of how to use the lighting and illumination features that are available in Alice.  For a much more extensive discussion of lighting and illumination issues in 3D programming, see the document titled Understanding Lighting in the Java 3D API in Resources.

Viewing tip

I recommend that you open another copy of this document in a separate browser window and use the following links to easily find and view the figures and listings while you are reading about them.

Figures

Listings

Supplementary material

Once you have mastered Alice, I recommend that you also study the other lessons in my extensive collection of online programming tutorials.  You will find a consolidated index at www.DickBaldwin.com.

General background information

No documentation available

As of the date of this writing, there is essentially no documentation available for Alice 2.0 except for commercial textbooks and the online tutorials that I have published (see Resources).  Therefore, everything in this document is based on my experimentation with Alice 2.0.

Illumination of objects

With one exception, the illumination of objects in 3D programming is usually based on code that models:

The use of emissiveColor

The exception mentioned above is often called emissive light or emissiveColor.  This is self-illumination that is generated by an object in the absence of other light sources.  An example might be an object that glows in the dark such as a pumpkin (Halloween decoration) or a paper bag (Christmas decoration) containing a candle.

Figure 1 shows an IceSkater object illuminated only by green emissive light.

Figure 1. An IceSkater object illuminated only by green emissive light.

Not a source of light

Generally speaking, even though emissive light will cause an object to self-illuminate and to be visible in an otherwise dark environment, 3D programs usually don't allow emissive light to illuminate other nearby objects.  (That contradicts my pumpkin and paper bag analogies above, which may illuminate other nearby objects.)  I will demonstrate this characteristic of emissive light later.

Reflection of light from an object

The manner in which light is reflected from an object can be quite complex involving many attributes of the object's surface.  I discuss some of these issues in detail in the earlier document, and will show you how to deal with some of them using Alice in this lesson.

Six types of light sources in Alice

I believe that there are six types of light sources that can be brought to bear in an Alice 2.0 program (but there may be others that I haven't discovered yet).  Three of these types are classes in the gallery.  Multiple objects can be created these three classes allowing for a very large number of actual light source objects.  The six types are:

Visual manifestation

Note that although the default light, the ambient light, and the DirectionalLight have the ability to illuminate other objects, they have no visual manifestation in their own right.  While it is possible to expose the bounding box and the axes for the default light and the DirectionalLight, they are always invisible.  (There is no bounding box and axes associated with the ambient light.)

The ambient light can be thought of as being analogous to the light that exists outside on a very overcast day.  It appears to come from everywhere simultaneously and it illuminates every exposed surface on all visible objects.

Objects of the classes LightBulb and StageSpotLight

Objects instantiated from the LightBulb and StageSpotLight classes do have a visible manifestation.  Each object created from these two classes actually consists of two objects, a main object and a sub-object, which is a child of the main object.  The main object can be thought of as a visible housing for the light source and the sub-object can be thought of as an invisible source of light inside the housing.

The housing for a LightBulb object resembles a common incandescent light bulb.  The housing for a StageSpotLight object resembles the lights that you sometimes see hanging above a stage in a theatre.  The visible manifestations of objects of these two classes are shown in Figure 2.

Figure 2. Visual manifestation of LightBulb and StageSpotLight objects.

The color and brightness properties of a light source

You can control the color of all six light sources including the emissive light.  You can control the brightness of all but the emissive light.  You can control various other properties (such as range and attenuation) of the default light, the DirectionalLight, the LightBulb, and the StageSpotLight.

DirectionalLight and default light may be the same type

An object of the DirectionalLight class seems to produce illumination that is very similar to the default light.  It may be that the default light is simply an object of the DirectionalLight class that is automatically created when you create a new world.

The pointOfView of a light source

You can control the pointOfView (position and orientation) of all of the light sources other than the ambient light and the emissive light.  However, an object of the LightBulb class appears to transmit light equally in all directions, so modifying the orientation aspect of the pointOfView has no impact on the way that a LightBulb object illuminates other objects.

Similarly, the light emitted by the default light and the DirectionalLight seems to behave as if the source is so far out in space that the light rays are parallel (similar to the sun in our solar system).  Consequently, it doesn't seem to matter how far you position those two light sources away from the object being illuminated.  The illumination doesn't seem to change as a function of distance to the source.  Both of these sources have a range property that would lead one to believe that there is a maximum allowable distance between the light source and the object being illuminated.  However, this property doesn't seem to have any impact on the manner in which the light illuminates the object, so I don't know what it is used for.

The directional light sources

The default light, the DirectionalLight, and the StageSpotLight are all directional lights.  You have more control over the beam width and other aspects of the light from a StageSpotLight than from the other two directional lights.  If you really want to set up some fancy lighting in your scene, you may want to consider the use of one or more objects of the StageSpotLight class.

Shadows

Alice objects do not cast shadows on other objects.  If you want it to appear that an object is casting a shadow, you must construct the shadow as a separate object as shown by the black elliptical circle on the ground in Figure 13.  Creating a shadow for a sphere as shown in Figure 13 is a relatively easy task.  However, creating a shadow for a more complex object, such as an object of the Bunny class, would be a more difficult task.

Reflection of light from objects

The properties of an Alice object that appear to have the greatest impact on the light reflected from the object are:

The effect of the color property

Assuming that emissive light is turned off, the appearance of an illuminated object (from the viewpoint of color) depends on the interaction of the original color in which the artist painted the model, the color property of the object, and the color properties of the light sources that are illuminating the object.

Color displays
I doubt that there are many electronic display devices that can reliably display sixteen million colors.

Sixteen million colors

The original color of every object and the value of the color property of every object in Alice are some combination of various amounts of red, green, and blue (the primary colors).  The amount of each primary color can range from a value of zero to a value of 255.  Theoretically, it is possible to generate more than sixteen million unique colors, one for each unique combination of the 256 values of each primary color.

There are several available ways to specify a color, ranging from simply clicking on a color that you like to adjusting sliders in order to specify the values of the red, green, and blue components of the desired color.

A serious limitation

Note, however, that as near as I have been able to determine, you cannot write code to set the red, green, and blue component values at runtime to values that you did not establish when you wrote the program.  For example, I have found no way to use an integer value obtained from a random number generator to set the value of the red component of a color property, or a variable of type color at runtime.

White and black

The color white contains the maximum amount of all three primary colors.  The color black contains no amount of any of the three primary colors.

The reflection color

The visible color of the object results from an interaction of the original color provided by the artist, the value of the color property of the object, and the color property of the light that illuminates the object.

An object reflects the primary color components contained in a light source in direct proportion to the amounts of the corresponding primary color components in the color of the object.

For example, if the color of an object contains only the primary color red, and a light source contains only the primary colors green and/or blue, an attempt to illuminate the object with the light source will result in a black object.  This is because the primary color components of the object are absent from the primary color components of the light source.

As another example, if an object is yellow, (consisting of equal amounts of red and green), illuminating the object with a red light source will make it appear to be red.  Illuminating the object with a green light source will make it appear to be green.  Illuminating it with a light source that contains equal amounts of red and green (yellow or white) will make it appear to be yellow.  However, illuminating it with a blue light will make it appear to be black.

The visible color of an object

It is important to realize that in most cases, the visible color of an object is not completely determined by the interaction of the color property of the object and the color property of the light source.  The artist who created the 3D model will normally have used various different colors to paint the different parts of the model.

When the value of the color property of the object is anything other than white, the visible colors of the different parts of the object are determined by an interaction between the value of the color property of the object, the color property of the light source, and the colors that the artist used to paint the model.  However, I cannot explain in detail how that interaction is implemented.

Some examples

The effect of the color used by the artist is not an issue in those cases where the artist elected to paint the model white, as is the case for most of the classes in the Shapes thumbnail.  When the artist painted the model white, its visible color is completely determined by the interaction between the color property of the object and the color property of the light source. 

If the color property of the object is white, the visible color of the object will be determined by the color property of the light source and the colors that were used by the artist to paint the model.

If the color property of the object is black, the visible color of the object will be black regardless of the color property of the light source and the colors used by the artist to paint the object.

A word of caution

When experimenting with lights and colors, it is important to remember that by default, the scene is illuminated by the ambient light of the world (colored gray) and the default light object.  Don't forget to set the brightness property of one of these sources to zero while experimenting with the other source.  Otherwise, things can seem to be very confusing.

The effect of specular reflection

Many Alice objects have the following properties, which have an important impact on the object's appearance when it is illuminated by a light source other than emissive light or ambient light.

What is specular reflection?

One good way to understand specular reflection is to contrast it with diffuse reflection.  Here is part of what Wikipedia has to say on the topic:

"Specular reflection is the perfect, mirror-like reflection of light ... from a surface, in which light from a single incoming direction is reflected into a single outgoing direction. Such behaviour is described by the law of reflection, which states that the direction of outgoing reflected light and the direction of incoming light make the same angle with respect to the surface normal; this is commonly stated as θi = θr.

This is in contrast to diffuse reflection, where incoming light is reflected in a broad range of directions. The most familiar example of the distinction between specular and diffuse reflection would be matte and glossy paints. While both exhibit a combination of specular and diffuse reflection, matte paints have a higher proportion of diffuse reflection and glossy paints have a greater proportion of specular reflection. Very highly polished surfaces, such as high quality mirrors, can exhibit almost perfect specular reflection."

Note that Alice does not provide direct control over diffuse reflection, but the specularHighlightExponent property makes it possible to simulate the effects of diffuse reflection.  Specifying lower values for this property makes the reflection appear to be more diffuse.

I will show you an example of specular reflection later in this lesson (see Figure 12).

The effect of the shadingStyle property

The 3D optical illusion is mainly created by shading different parts of a 3D object to indicate the extent to which each part is illuminated by a given source of light.  This is illustrated by the large yellow sphere in Figure 13, and is also illustrated by the dark gray housing on the spotlight in Figure 2.

Intersecting polygons and the shadingStyle property

Each 3D object in Alice (and many other programs that use 3D models) is modeled as a set of intersecting flat polygons.  (Intersecting triangles are often used for this purpose.)  The shadingStyle property determines how each of the polygons is colored, which in turn determines the overall appearance of the 3D object.  The shadingStyle property can be given any of the following three values:

SMOOTH shading

The 3D effect produced by shading is accomplished by varying the color of each polygon in relation to the extent to which it is illuminated.  The extent to which the polygon is illuminated is determined by the angle between the incident rays from the light source and the plane of the polygon.  When the direction to the light source is perpendicular to the plane of the polygon, the illumination is maximum.  As the angle decreases, the illumination also decreases.  When the light rays are parallel to the plane of the polygon, the polygon is not illuminated.

For example, a polygon that is positioned on an object such that the plane of the polygon is parallel to the light rays, or a polygon on the back side of an object that is hidden from the light source will often be colored black or dark gray.  A polygon whose plane is perpendicular to the light rays and is fully illuminated will be a bright version of the color originally applied to that polygon by the artist who created the 3D model.

Color varies across each polygon

When SMOOTH shading is used, the actual color of each polygon will vary over the surface of the polygon in such a way that the colors of the intersecting edges of two adjacent polygons are nearly the same.  The effect is to prevent the intersections of the polygons from being obvious and to give the object a smooth overall 3D appearance even though it is constructed from intersecting flat polygons.

There are several approaches to smooth shading, some of which are more effective than others.  Also, some of them place a greater computational load on the computer than others.  I explain some of the different approaches in the earlier document on lighting using Java3D.

SMOOTH shading on an IceSkater object

Figure 3 shows three IceSkater objects that were rendered using SMOOTH shading.  The orientation of each object relative to the position of the light source is different, causing the polygons that make up the model to be colored differently in each of the three cases.

Figure 3. SMOOTH shading on an IceSkater object.

Polygons are not obvious

Although there are some apparent discontinuities at the knee and shoulder joints, the polygons that make up this model are not obvious.  Contrast this with the image in Figure 4 where the use of FLAT shading causes the polygons to be very obvious.

The objects in Figure 3 were illuminated by the default dark gray ambient light source plus the default white directional light source.

FLAT shading

When FLAT shading is used, the color of each polygon is constant over the entire surface of the polygon.  Adjacent polygons are often different colors.  This usually causes it to be visually obvious that the object is constructed from flat polygons.  While this often results in a less pleasing appearance than smooth shading, it is worth noting that for most systems, this will also reduce the computational load that shading imposes on the computer.

Figure 4 shows the same three IceSkater objects as were shown in Figure 3.  However, whereas the objects in Figure 3 were rendered using SMOOTH shading, the objects in Figure 4 were rendered using FLAT shading.

Figure 4. FLAT shading on an IceSkater object.

Comparing Figure 4 with Figure 3 should give you some idea how the polygon colors in Figure 4 were smoothed into one another to produce smooth color gradients in Figure 3.

As in Figure 3, the objects in Figure 4 were illuminated by the default dark gray ambient light source plus the default white directional light source.

NONE shading

When a shading value of NONE is used to render the object, the polygons aren't shaded at all.  Assuming that the object is illuminated with white light, each polygon is displayed in the color originally given to that polygon by the artist who created the model.  Typically, this will destroy the 3D optical illusion causing the object to appear to be a flat drawing.

Figure 5 shows one example of each of the three types of shading available in Alice.

Figure 5. FLAT, SMOOTH, and NONE shading on an IceSkater object.

The IceSkater object in the center was rendered using SMOOTH shading.  The object on the left was rendered using FLAT shading.  The object on the right was rendered using a shading value of NONE.  The default gray ambient light was turned off in Figure 5.  This caused the objects to be illuminated by the single default directional white light source.  This had the effect of causing the shading to be more pronounced than in Figure 3 and Figure 4.

The main point in Figure 5 is that the 3D optical illusion has been lost for the object with no shading on the right.

Preview

This lesson will present and explain four Alice programs that illustrate the concepts discussed above.  The program named Lights03 illustrates the use of emissiveColor to self-illuminate an object, and to show that it doesn't illuminate nearby objects.

The program named Lights02 illustrates the interaction between the color property of an object and the color property of the light illuminating the object.

The program named Lights04 illustrates specular reflection.

The program named Lights05:

Discussion and sample code

The program named Lights03

Figures 6 through 9 show screen shots taken from the program named Lights03.  A complete listing of this program is shown in Listing 1.  Figure 6 shows a screen shot from the program at startup.

Figure 6. Screen shot from Lights03 at startup.

Illumination by default light source only

As the text in Figure 6 indicates, the scene in Figure 6 is being illuminated solely by the default light source.  The ambient light has been turned off.  The emissive light is off, and no other light sources have been added to the scene.

Also as shown in the code in Listing 1, the color property for the sphere and each of the cones was set to red.

Emissive light turned on

Figure 7 shows a screen shot after the emissiveColor property for the sphere has been set to yellow.  The scene in Figure 7 is still being eliminated solely by the default light.

Figure 7. Screen shot from Lights03 with emissiveColor property for the sphere set to yellow. 

Turn default light off

Figure 8 shows a screen shot after the default light has been turned off.  This leaves only the emissiveColor for the sphere turned on.

Figure 8. Screen shot from Lights03 with only emissiveColor turned on.

The two cones are not illuminated

The important thing to note in Figure 8 is that even though the two cones are still next to the sphere, the emissiveColor light from the sphere does not eliminate the cones.

Turn the ambient light on

Figure 9 shows a screen shot of the same scene with the scene being illuminated by white ambient light and by emissiveColor light from the sphere.  (The default light is still turned off.)

Figure 9. Screen shot from Lights03 with white ambient light turned on.

The ambient light causes the ground as well as the two cones to be illuminated.  The sphere and the two cones appear to be flat two-dimensional drawings because there is no shading of the polygons.  The red color of the cones is not affected by the yellow emissiveColor light from the sphere.

The program named Lights02

A complete listing of this program is provided in Listing 2.

This program illustrates the interaction between the color property of an object and the color property of the light illuminating the object as explained earlier.  In this case, the objects of interest are spheres from the Shapes thumbnail, which were originally painted white by the artist.

The program begins by arranging and coloring seven spheres as shown in Figure 10.

Figure 10. Arrangement and colors of the spheres in Lights02.

The color property values for the spheres

The spheres in Figure 10 were illuminated by a single source of white light.  Thus, the colors shown in Figure 10 represent the color property values of the spheres:

The numbers in parentheses in the above list represent the amounts of red, green, and blue respectively in each color property value.  The names of the secondary colors (yellow, aqua, and magenta) came from the web page titled RGB to Color Name Mapping (see Resources).

Illuminate the spheres

Once the spheres were arranged and their color property values were set, they were illuminated by a single default light.  The color property value of the light was cycled through each of the color values shown in the above list.  The appearance of the spheres for a white light is shown in Figure 10.  The appearance of the spheres for each of the remaining six colors of light is shown in Figure 11.

Figure 11. Appearance of the spheres for six different light colors.

The spheres reflect different colors of light

The six images going from left to right, top to bottom in Figure 11 show the appearance of the seven spheres for light colors beginning with red and progressing through magenta in the order shown above.

As shown in the upper left corner of Figure 11, when the spheres were illuminated with pure red light, three of the spheres disappeared into the black background.  The four spheres with the following color property values were visible and appeared to be red:

These four spheres were visible because the color property value of each of these spheres contains a red component at a full intensity value of 255.

Illuminate with a yellow light

As shown in the upper right corner of Figure 11, when the spheres were illuminated with a yellow light, only one sphere disappeared into the black background.  The magenta and red spheres appeared to be red.  The white and yellow spheres appeared to be yellow and the aqua and green spheres appeared to be green.

This occurred because:

Similar color patterns occurred for each of the six illumination colors.

Different colors for each sphere

The white sphere in the center of the arrangement in Figure 10 was always visible exhibiting the same color as the light.

Starting with the red sphere in Figure 10 (sphere0) and going counter-clockwise around the arrangement, the six outer spheres took on the following colors in Figure 11:

It is important to note that at no time did the actual color property of any of the spheres change during this sequence.  Once the color property of a sphere was set, it was never changed.  Only the color property of the illuminating light changed.  Thus, it is possible to make it appear that objects change colors simply by changing the color of the light source that is being used to illuminate the objects.  This might be a useful technique for simulating the lights on a space ship.

The program named Lights04

A complete listing of this program is provided in Listing 3.  This program illustrates specular reflection as described earlier.

Figure 12 (left to right, top to bottom) shows four snapshot renderings of a sphere as the light source circled the sphere disappearing behind the sphere on the left side and emerging from behind the sphere on the right side.  Each image shows a specular reflection.

Figure 12. Illustration of specular reflection in Lights04.

The ambient light was turned off and the ground was made invisible in Figure 12.  The color property of the sphere was white and the color property of the light was red.  Hence, the sphere appeared to be red.

Effect of the polygons
To see the impact of the polygons on the specular reflection more clearly, change the shadingStyle property of the sphere from SMOOTH to FLAT and rerun the program.

The specular reflection property values

The specularHighlightColor property of the sphere was set to red and the specularHighlightExponent value was set to 1000.  Up to a point, the higher the value of the specularHighlightExponent property, the shinier will be the object and the smaller will be the size of the specular reflection.  However, the minimum size of the specular reflection is limited by the size of the intersecting polygons that make up the surface of the object, so increasing the value beyond 1000 in this case made very little difference.

I recommend that you experiment with these property values in order to understand their impact on the rendered output.

Behavior of the program

Once the stage was set, a statement in the main method caused the light to make one complete revolution around the sphere with the light beam aimed at the sphere at all times.  This in turn caused the specular reflection to move around the sphere from right to left, disappearing behind the sphere on the left and re-emerging from behind the sphere on the right.

The program named Lights05

Screen shots from this program are shown in Figure 13.  A complete listing of the program is provided in Listing 4.

The purpose of this program is to:

Illuminating the scene

Figure 13 shows eight screen shots from two successive runs the program taken while each of the light sources listed above was the only source of illumination for the scene.  The small red sphere in the right side of each image shows the position of the light source.

The position of the light sources

The position of each light source was relatively far from the surface of the large yellow sphere in the images in the left column of Figure 13.  The position of each light source was very close to the surface of the large yellow sphere in the images in the right column.

Figure 13. Screen shots from the program named Lights05.

The small red sphere

The purpose of the small red sphere was to mark the position of the light sources.  The emissive color of the small sphere was set to red so that it would always be visible, even when it wasn't being illuminated by one of the light sources.

The shadow

The shadow was constructed by positioning a black circle shape on the ground slightly to the left of and slightly behind the large yellow sphere.  As mentioned earlier, it was relatively easy to create an artificial shadow for a sphere.  It would be much more difficult to create an artificial shadow for a more complex object such as an IceSkater.

The shadow is fairly realistic for the default light and the directionalLight.  However, it is completely unrealistic for the lightBulb and the stageSpotLight.

The ambient light

The world's ambientLightBrightness property was set to 0 to ensure that the only illumination in the scene at any particular time was produced by one of the four light sources listed earlier.

Controlling the light sources

The brightness property of each light source was initially set to 0.  Each light source was moved, (one at a time), to the position of the red sphere and pointed at the center of the large yellow sphere.  Following that, the light source was turned on slowly, by setting the value of the brightness property to 1.5 with a duration of three seconds.  Then a two-second pause was inserted to make it possible to capture a screen shot of the scene.  Then the light source was turned off slowly by setting the value of the brightness property to 0 with a duration of three seconds.

The lightBulb is non-directional

Because the lightBulb source is not directional, it was not pointed at the sphere after being moved into position.

The stageSpotLight has other control parameters

In addition to the brightness property, the stageSpotLight has an innerBeamAngle property and an outerBeamAngle property.  These properties are used to control the width of the light beam emitted by the spot light.  These two properties were set to 0.3 and 0.6 radians respectively.  I recommend that you experiment with these parameters to get a feel for how they affect the manner in which this source will illuminate an object.

Changing the position of the light sources

The program code in Listing 4 shows that the position of each light source as well as the position of the small red sphere was controlled by a single statement that sets the value of a variable named lightPosition.  The different results shown in the left and right columns of Figure 13 were achieved by changing the literal values in this statement and re-running the program.

The default light and directionalLight sources

Consider the four images at the top of Figure 13.  Because the manner in which the two light sources illuminate an object, we can conclude that the default light that appears whenever you create a new world is probably an object of the directionalLight class in the gallery.  If we need additional light sources having those characteristics, we can instantiate them using the class from the gallery.

We can also conclude that the manner in which either the default light or an object of the directionalLight class illuminates an object is independent of the distance from the light source to the surface of the object being illuminated.  It appears that regardless of that distance, the illumination appears to be from a source very far out in space (similar to our sun).  Note, for example, that even though the light source was positioned at the location of the small red sphere, the upper right side of the small red sphere was illuminated in the same way that the upper right side of the large yellow sphere was illuminated.  This could only happen if the true position of the light source was further from the yellow sphere than the position of the red sphere.

Thus, the manner in which an object is illuminated depends on the orientation angle of the light, but is independent of the distance to the light.  Even knowing that, however, it is sometimes difficult to predict how one of these two light sources will illuminate an object.  You should experiment with the position and orientation of the default light or an object of the directionalLight class.

The lightBulb source

Consider the two images in the third row in Figure 13 where the source of illumination is identified as a lightBulb.  The manner in which an object is illuminated by a lightBulb source seems to be fairly consistent with what we would expect.  All objects near to the source appear to be illuminated independent of the direction from the light source to the object.  The illuminated area on the sphere decreases as the source moves closer to the sphere.  Although it is not shown here, the intensity with which an object is illuminated appears to decrease as the distance from the object to the source increases, but that effect is not nearly as pronounced as might be expected.

Note that the simulated shadow in Figure 13 is totally unrealistic for a lightBulb source.  The size of the shadow remains constant regardless of the relative positions of the yellow sphere and the light.  In reality, the size of the shadow should increase as the lightBulb gets closer to the sphere.

The stageSpotLight source

The stageSpotLight source is the most versatile of all of the available light sources.  The light emitted by this source is a directional cone.  The width of the cone is controlled by two properties, each of which is specified by an angle in Radians:  innerBeamAngle and outerBeamAngle.  Since there is no documentation, the exact purpose of these two properties and the relationship between them isn't exactly clear.  However, it is easy to show that the width of the cone increases when the specified width of the outerBeamAngle increases.

The bottom two images in Figure 13 show the effect of the illuminating cone.  The illuminated area on the surface of the sphere is the size of the area described by the intersection of the surface and the cone.  When the spot light source is very close to the surface of the sphere, the illuminated area is very small.  When the source is further from the sphere, the illuminated area is larger.

Run the programs

Executable versions of the programs that I explained in this lesson are available for downloading (see Resources).  I encourage you to either download those programs, or copy the code from Listings 1 through 4 into your Alice development environment and play it.  Experiment with it, making changes to the various property values, and observing the results of your changes.  In particular, you might want to experiment with the range, attenuation, angles, and etc. properties.

Summary

In this lesson, I taught you how to use emissive color, ambient light, the default light, a directional light, a light bulb, and a spot light to illuminate your Alice world.  I also taught you how to use shading, color, and specular reflection in your illumination scheme, as well as how to create shadows.

Resources

General resources

Resources from earlier lessons in the series titled "Learn to Program using Alice"

Downloads

Complete program listings

Complete listings of the programs discussed in this lesson are shown in Listings 1 through 4 below.

Listing 1. The program named Lights03.

Lights03's Code

Created by: Dick Baldwin

world

Events

When the world starts
Do:
world.main ( );


 

Methods

  public void main ( ) {
    
       world.setTheStage ( );
  sphere .say( Default light on, Ambient light off, Emissive color off ); duration = 5 seconds fontSize = 15
  world.controlLights ( );
  }


 
  public void setTheStage ( ) {
    
       doInOrder {
       world .set( ambientLightColor , (1, 1, 1) ); duration = 0 seconds
  world .set( atmosphereColor , (0, 0, 0) ); duration = 0 seconds
  world .set( ambientLightBrightness , 0 ); duration = 0 seconds
  ground .setPointOfView( world ); duration = 0 seconds
  sphere .setPointOfView( ground ); duration = 0 seconds
  sphere .set( color , (1, 0, 0) ); duration = 0 seconds
  camera .moveTo( world ); ( getVector( right = 0 , up = 2 , forward = -10 ) ) duration = 0 seconds
  camera .pointAt( sphere ); duration = 0 seconds
  camera .turn( BACKWARD , .03 revolutions ); duration = 0 seconds
  light .moveTo( world ); ( getVector( right = 0 , up = 2 , forward = -10 ) ) duration = 0 seconds
  light .pointAt( sphere ); duration = 0 seconds
  }
  doInOrder {
       cone1 .set( color , (1, 0, 0) ); duration = 0 seconds
  cone1 .setPointOfView( ground ); duration = 0 seconds
  cone1 .move( RIGHT , ( ( ( ( ( subject = sphere .getWidth() ) / 2 ) ) * 1.1 ) ) ); duration = 0 seconds
  cone1 .turn( FORWARD , 0.5 revolutions ); duration = 0 seconds
  cone1 .move( UP , ( ( ( subject = cone1 .getHeight() ) / 2 ) ) ); asSeenBy = ground duration = 0 seconds
  }
  doInOrder {
       cone2 .set( color , (1, 0, 0) ); duration = 0 seconds
  cone2 .setPointOfView( ground ); duration = 0 seconds
  cone2 .move( LEFT , ( ( ( ( ( subject = sphere .getWidth() ) / 2 ) ) * 1.1 ) ) ); duration = 0 seconds
  cone2 .turn( FORWARD , 0.5 revolutions ); duration = 0 seconds
  cone2 .move( UP , ( ( ( subject = cone1 .getHeight() ) / 2 ) ) ); asSeenBy = ground duration = 0 seconds
  }
  }


 
  public void controlLights ( ) {
    
       doInOrder {
       // Turn emissive light on
  doTogether {
       sphere .say( Turn emissive color on ); duration = 5 seconds fontSize = 15
  sphere .set( emissiveColor , (1, 1, 0) ); duration = 3 seconds
  }
  // Turn default light off. Emissive light does not illuminate cones.
  doTogether {
       sphere .say( Turn default light off ); duration = 5 seconds fontSize = 15
  light .set( brightness , 0 ); duration = 3 seconds
  }
  doTogether {
       sphere .say( Turn white ambient light on ); duration = 5 seconds fontSize = 15
  world .set( ambientLightBrightness , 3 );
  }
  }
  }

 

Listing 2. The program named Lights02.

Lights02's Code

Created by: Dick Baldwin

world

Events

When the world starts
Do:
world.main ( );


 

Methods

  public void main ( ) {
    
       // Note: All seven spheres were manually set to a diameter of 1 meter.
  // Illustrates interaction between the color property of the light
  // and the color properties of seven different objects.
  world.setTheStage ( );
  world.cycleLightColor ( );
  }


 
  public void setTheStage ( ) {
    
       // Set the background environment.
  doInOrder {
       world .set( atmosphereColor , (0, 0, 0) ); duration = 0 seconds
  world .set( ambientLightColor , (0, 0, 0) ); duration = 0 seconds
  world .set( ambientLightBrightness , 0 ); duration = 0 seconds
  ground .set( color , (0, 0, 0) ); duration = 0 seconds
  }
  // Position the camera and the light.
  doInOrder {
       camera .moveTo( world ); ( getVector( right = 0 , up = 0 , forward = -10 ) ) duration = 0 seconds
  camera .pointAt( sphere0 ); duration = 0 seconds
  light .moveTo( world ); ( getVector( right = 0 , up = 0 , forward = -10 ) ) duration = 0 seconds
  light .pointAt( sphere0 ); duration = 0 seconds
  }
  // Position the spheres.
  doInOrder {
       sphere0 .moveTo( world ); ( getVector( right = 0 , up = 0 , forward = 0 ) ) duration = 0 seconds
  sphere1 .moveTo( world ); ( getVector( right = 0.5 , up = 0.87 , forward = 0 ) ) duration = 0 seconds
  sphere2 .moveTo( world ); ( getVector( right = 1 , up = 0 , forward = 0 ) ) duration = 0 seconds
  sphere3 .moveTo( world ); ( getVector( right = 0.5 , up = -0.87 , forward = 0 ) ) duration = 0 seconds
  sphere4 .moveTo( world ); ( getVector( right = -0.5 , up = -0.87 , forward = 0 ) ) duration = 0 seconds
  sphere5 .moveTo( world ); ( getVector( right = -1 , up = 0 , forward = 0 ) ) duration = 0 seconds
  sphere6 .moveTo( world ); ( getVector( right = -0.5 , up = 0.87 , forward = 0 ) ) duration = 0 seconds
  }
  // Set the color properties of the spheres to the three.
  // primary colors and the three secondary colors plus white.
  doInOrder {
       sphere0 .set( color , (1, 1, 1) ); duration = 0 seconds
  sphere1 .set( color , (1, 0, 0) ); duration = 0 seconds
  sphere2 .set( color , (1, 1, 0) ); duration = 0 seconds
  sphere3 .set( color , (0, 1, 0) ); duration = 0 seconds
  sphere4 .set( color , (0, 1, 1) ); duration = 0 seconds
  sphere5 .set( color , (0, 0, 1) ); duration = 0 seconds
  sphere6 .set( color , (1, 0, 1) ); duration = 0 seconds
  wait( 2 seconds );
  }
  }


 
  public void cycleLightColor ( ) {
    
       // Cycle the color property of the light through white,
  // all of the primary colors, and all of the secondary colors.
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  light .set( color , (1, 0, 0) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  // yellow per http://web.njit.edu/~kevin/rgb.txt.html
  light .set( color , (1, 1, 0) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  light .set( color , (0, 1, 0) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  // aqua per http://web.njit.edu/~kevin/rgb.txt.html
  light .set( color , (0, 1, 1) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  light .set( color , (0, 0, 1) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  // magenta per http://web.njit.edu/~kevin/rgb.txt.html
  light .set( color , (1, 0, 1) ); duration = 3 seconds
  light .set( color , (1, 1, 1) ); duration = 3 seconds
  }

 

Listing 3. The program named Lights04.

Lights04's Code

Created by: Dick Baldwin

world

Events

When the world starts
Do:
world.main ( );


 

Methods

  public void main ( ) {
    
       // Illustrates specular reflection.
  world.setTheStage ( );
  wait( 2 seconds );
  light .turn( RIGHT , 1 revolution ); asSeenBy = sphere duration = 5 seconds
  }


 
  public void setTheStage ( ) {
    
       // Set the environment.
  doInOrder {
       world .set( ambientLightColor , BLACK ); duration = 0 seconds
  world .set( ambientLightBrightness , 0 ); duration = 0 seconds
  ground .set( isShowing , false ); duration = 0 seconds
  }
  // Position the camera
  doInOrder {
       camera .moveTo( world ); ( getVector( right = 0 , up = 0 , forward = -5 ) ) duration = 0 seconds
  camera .pointAt( sphere ); duration = 0 seconds
  }
  // Initialize the light
  doInOrder {
       light .moveTo( world ); ( getVector( right = 0 , up = 3 , forward = -5 ) ) duration = 0 seconds
  light .pointAt( sphere ); duration = 0 seconds
  light .turn( LEFT , 1/8 revolutions ); asSeenBy = sphere duration = 0 seconds
  light .set( color , RED ); duration = 0 seconds
  }
  // Set specular reflection on the sphere.
  doInOrder {
       sphere .set( specularHighlightColor , RED ); duration = 0 seconds
  sphere .set( specularHighlightExponent , 1000 ); duration = 0 seconds
  }
  }

 

Listing 4. The program named Lights05.

Lights05's Code

Created by: Dick Baldwin

world

Events

When the world starts
Do:
world.main ( );


 

Methods

  public void main ( ) {
    Posistion lightPosition = Vector3( 0, 0, 0 ) ;
       world.setTheStage ( );
  doTogether {
       // Establish and mark the position of the lights.
  lightPosition .set( value , ( getVector( right = 2 , up = 3 , forward = -2 ) ) ); duration = 0 seconds
  lightPosition .set( value , ( getVector( right = 0.71 , up = 1.71 , forward = -0.71 ) ) ); duration = 0 seconds
  // This little sphere marks the position of the lights
  sphere2 .set( emissiveColor , (1, 0, 0) ); duration = 0 seconds
  sphere2 .moveTo( world ); position of = lightPosition duration = 0 seconds
  sphere2 .set( isShowing , true ); duration = 0 seconds
  // Create the shadow
  circle .move( LEFT , ( ( ( ( ( subject = circle .getWidth() ) / 2 ) ) * 0.71 ) ) ); duration = 0 seconds
  circle .move( FORWARD , ( ( ( ( ( subject = circle .getWidth() ) / 2 ) ) * 0.71 ) ) ); duration = 0 seconds
  }
  doTogether {
       sphere1 .say( Default light ); duration = 6 seconds
  doInOrder {
       defaultLight .moveTo( world ); position of = lightPosition duration = 0 seconds
  defaultLight .pointAt( sphere1 ); duration = 0 seconds
  // Turn the default light on slowly.
  defaultLight .set( brightness , 1.5 ); duration = 3 seconds
  wait( 2 seconds );
  // Turn the default light off slowly.
  defaultLight .set( brightness , 0 ); duration = 3 seconds
  }
  }
  doTogether {
       sphere1 .say( directionalLight ); duration = 6 seconds
  doInOrder {
       directionalLight .moveTo( world ); position of = lightPosition duration = 0 seconds
  directionalLight .pointAt( sphere1 ); duration = 0 seconds
  directionalLight .set( brightness , 1.5 ); duration = 3 seconds
  wait( 2 seconds );
  directionalLight .set( brightness , 0 ); duration = 3 seconds
  }
  }
  doTogether {
       sphere1 .say( lightBulb ); duration = 6 seconds
  doInOrder {
       lightBulb.pointLight .moveTo( world ); position of = lightPosition duration = 0 seconds
  // The light bulb is non directional.
  lightBulb.pointLight .pointAt( sphere1 ); duration = 0 seconds
  lightBulb.pointLight .set( brightness , 1.5 ); duration = 3 seconds
  wait( 2 seconds );
  lightBulb.pointLight .set( brightness , 0 ); duration = 3 seconds
  }
  }
  doTogether {
       sphere1 .say( stageSpotLight ); duration = 6 seconds
  doInOrder {
       stageSpotLight.spotLight .moveTo( world ); position of = lightPosition duration = 0 seconds
  stageSpotLight.spotLight .pointAt( sphere1 ); duration = 0 seconds
  // Adjust spot light parameters
  stageSpotLight.spotLight .set( innerBeamAngle , 0.3 radians ); duration = 0 seconds
  stageSpotLight.spotLight .set( outerBeamAngle , 0.6 radians ); duration = 0 seconds
  stageSpotLight.spotLight .set( brightness , 1.5 ); duration = 3 seconds
  wait( 2 seconds );
  stageSpotLight.spotLight .set( brightness , 0 ); duration = 3 seconds
  }
  }
  }


 
  public void setTheStage ( ) {
    
       doInOrder {
       // Turn all light sources off
  defaultLight .set( brightness , 0 ); duration = 0 seconds
  directionalLight .set( brightness , 0 ); duration = 0 seconds
  lightBulb.pointLight .set( brightness , 0 ); duration = 0 seconds
  stageSpotLight.spotLight .set( brightness , 0 ); duration = 0 seconds
  world .set( atmosphereColor , (0, 0, 0) ); duration = 0 seconds
  world .set( ambientLightBrightness , 0 ); duration = 0 seconds
  // Position the objects
  ground .setPointOfView( world ); duration = 0 seconds
  sphere1 .setPointOfView( ground ); duration = 0 seconds
  sphere1 .move( UP , ( ( ( subject = sphere1 .getHeight() ) / 2 ) ) ); duration = 0 seconds
  sphere1 .set( isShowing , true ); duration = 0 seconds
  camera .setPointOfView( ground ); duration = 0 seconds
  camera .move( BACKWARD , 10 meters ); duration = 0 seconds
  camera .move( UP , 2 meters ); duration = 0 seconds
  // Use the circle to create a shadow.
  circle .setPointOfView( ground ); duration = 0 seconds
  // This is a very small upward movement to cause the
  // shadow to show on top of the ground.
  circle .move( UP , 0 meters ); duration = 0 seconds
  circle .resize( ( ( ( subject = sphere1 .getWidth() ) / ( subject = circle .getWidth() ) ) ) ); duration = 0 seconds
  circle .set( color , (0.251, 0.251, 0.251) ); duration = 0 seconds
  // Use sphere2 to mark the position of the lights.
  sphere2 .resize( 0.1 ); duration = 0 seconds
  sphere2 .setPointOfView( world ); duration = 0 seconds
  }
  }

 


Copyright

Copyright 2007, Richard G. Baldwin.  Faculty and staff of public and private non-profit educational institutions are granted a license to reproduce and to use this material for purposes consistent with the teaching process.  This license does not extend to commercial ventures.  Otherwise, reproduction in whole or in part in any form or medium without express written permission from Richard Baldwin is prohibited.

About the author

Richard Baldwin is a college professor (at Austin Community College in Austin, TX) and private consultant whose primary focus is a combination of Java, C#, and XML. In addition to the many platform and/or language independent benefits of Java and C# applications, he believes that a combination of Java, C#, and XML will become the primary driving force in the delivery of structured information on the Web.

Richard has participated in numerous consulting projects and he frequently provides onsite training at the high-tech companies located in and around Austin, Texas.  He is the author of Baldwin's Programming Tutorials, which have gained a worldwide following among experienced and aspiring programmers. He has also published articles in JavaPro magazine.

In addition to his programming expertise, Richard has many years of practical experience in Digital Signal Processing (DSP).  His first job after he earned his Bachelor's degree was doing DSP in the Seismic Research Department of Texas Instruments.  (TI is still a world leader in DSP.)  In the following years, he applied his programming and DSP expertise to other interesting areas including sonar and underwater acoustics.

Richard holds an MSEE degree from Southern Methodist University and has many years of experience in the application of computer technology to real-world problems.

Baldwin@DickBaldwin.com

-end-