Lighting

The proper lighting of a scene is one of the most important yet under-utilized techniques for adding a sense of immersion and realism in a 3D scene. A single directional light source exerts a powerful influence over wayfinding (navigation) in animals and should be incorporated into any virtual environment in which navigation is critical.

A great deal of current research in 3D graphics is centered around developing new lighting algorithms. The entire research enterprise is mathematically intense and relies on a knowledge of physics. However, proper use of lighting can be learned by getting a basic understanding of the basic forms of lighting and then doing experimentation to get the desired effect.

Java 3D Lighting Model

Only a reduced lighting model is currently practical for use with interactive graphics anyway. These limitations will be discussed shortly. For now, consider that Java 3D supports four fundamental lighting types (listed in Table 11.7).

Table 11.7. Basic Lighting Available in Java 3D
Light Class Usage
AmbientLight Light without a concentrated source; provides equal illumination throughout the environment.
DirectionalLight A light with a specified direction; source is modeled as infinitely far away.
PointLight An attenuated light source at a fixed point in space; radiates in all directions.
SpotLight An attenuated light source at a fixed point in space; radiates in a specified direction.

All these classes are subclasses of the common parent Light. Light serves as a node to contain parameters that are common to all four of these subclasses (and others that can be created through extension). The common parameters shared by all light in Java 3D are color, enable/disable, region of influence, and scope.

Java 3D's lighting model is based on three key vector values pointing from a vertex on the object and pointing to 1) the viewer's eye, 2) back in the direction of the light, and 3) along the surface normal. These three vectors provide an important subset of the information necessary to render object shadings in Java 3D.

Three basic reflections are calculated in Java 3D: ambient, diffuse, and specular. Refer to Chapter 10 for a description of these from a more general computer graphics standpoint.

Implementing Java 3D's Lighting Model

Beginning to use lighting in Java 3D presents some potential pitfalls that you must be cautious to avoid. These pitfalls are related to not having the appropriate objects in the scene in order to see the effects of lighting.

First and foremost, you must remember that without objects in a scene, you cannot see a light. Lights are only visible when they interact with 3D surfaces.

The second prerequisite for implementing lighting effects is that all objects to be shaded must have surface normals and material properties.

AmbientLight

Because an ambient light source projects light uniformly throughout the environment, it is impossible to determine the origin of the source. For this reason, the AmbientLight node is the simplest light to use because you don't have to specify the direction of light. To create an instance of an AmbientLight, use on the following three constructors:

public AmbientLight()
public AmbientLight(Color3f color)
public AmbientLight(Boolean lighton, Color3f color)

It is possible to change the color of the light or turn it on or off using setColor() and setEnable(). Note that as with many other scene elements, it is necessary to set the proper capability bits in order to make post-instantiation changes to lights.

DirectionalLight

As mentioned previously, one of the strongest spatial cues that is used by animals for navigation is the perception of a directional light. Given that Virtual Reality is a perceptually degraded form of navigation, it is highly recommended that at least one directional light be placed in any environment.

Instantiating a DirectionalLight is similar to instantiating an AmbientLight with one additional step. When specifying a DirectionalLight, it is necessary to add a directional vector indicating the source and target locations of the light.

Vector3f light = new Vector3f(3.f, 3.f, 3.f);

PointLight

A PointLight is basically like a light bulb in the real world; it radiates in all directions and attenuates with distance from the source. In Java 3D, the programmer must specify the attenuation through three parameters that contribute to the calculation of the falloff from the PointLight. The attenuation parameters can be set dynamically (given that the programmer has set the proper capability bits) or specified at the time of instantiation using the following constructors:

public PointLight()
public PointLight(Boolean lightOn, Color3f color, Point3f position, Point3f attenuation)
public PointLight(Color3f color, Point3f position, Point3f attenuation)

To set the attenuation during runtime, use the setAttenuation() method.

Note that the attenuation is specified as a Point3f in which the three coordinates represent color, linear, and quadratic attenuation parameters, respectively.

SpotLight

A SpotLight is similar to a DirectionalLight except that it radiates from a point inside a cone. The diameter of the cone can be specified in order to control whether the light is wide or narrow. In addition, the programmer can set the focus from sharp to soft in a range of 128.f to 0.f. Instantiation is the same as for a PointLight with two additional parameters for controlling the spread and focus of the light. Use the following constructors to create a SpotLight:

SpotLight()
SpotLight(Boolean lightOn, Color3f color, Point3f position, Point3f
attenutation, Vector3f direction, float spreadAngle, float concentration)
SpotLight(Color3f color, Point3f position, Point3f attenutation, Vector3f direction, 
float spreadAngle, float concentration);

Specifying Scope and Influencing Bounds

It is possible to specify a scope (in terms of the scene graph) to use for lights. The scope, in this case, refers a list of Group nodes (called the scope list) that are influenced by a light. If the scope list is empty or not specified, the scope covers the entire universe. Otherwise, only those Leaf nodes that belong to the Groups in the scope list are influenced by the scoped light.

One sometimes confusing aspect of using influencing bounds is that there are two choices for specifying bounds that reflect subtle differences in how the lights are applied to the scene. The more commonly used bounds is for applying the light over the entire scene and works in light centered coordinates (that is, when the light moves, so do the bounds).

The BoundingLeaf doesn't move with the light. To move the influencing bounds, you must move the BoundingLeaf.

Listing 11.13 shows an example of two DirectionalLights with one of the lights attached to a TransformGroup and rotation Behavior. In Figure 11.10, by rotating the red light with the MouseRotate Behavior, the user can observe the different effects of mixing and influence with the static blue light.

Figure 11.10. Screen shot from DirectionLightEx.java.


Listing 11.13 DirectionalLightEx.java
import com.sun.j3d.utils.behaviors.mouse.MouseRotate;

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.geometry.Cylinder;
import com.sun.j3d.utils.geometry.Box;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class DirectionalLightEx extends Applet {

  public BranchGroup createSceneGraph(String[] args) {
    // Create the root of the branch graph
    BranchGroup objRoot = new BranchGroup();

    // Create a Transform group to scale all objects so they
    // appear in the scene.
    TransformGroup objScale = new TransformGroup();
    Transform3D t3d = new Transform3D();
    t3d.setScale(0.4);
    objScale.setTransform(t3d);
    objRoot.addChild(objScale);

    // Create the transform group node and initialize it to the
    // identity.  Enable the TRANSFORM_WRITE capability so that
    // our behavior code can modify it at runtime.
    TransformGroup objTrans = new TransformGroup();
    //read/write-enable for behaviors
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
    objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    objScale.addChild(objTrans);

    //Create a Sphere
    Sphere sphere = new Sphere(1.0f, Sphere.GENERATE_NORMALS |
                  Sphere.GENERATE_TEXTURE_COORDS, 45);

    Appearance ap = sphere.getAppearance();


    // add it to the scene graph.
    objTrans.addChild(sphere);

    BoundingSphere bounds =
      new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);

    // Create the rotate behavior node
    MouseRotate behavior = new MouseRotate(objTrans);
    objTrans.addChild(behavior);
    behavior.setSchedulingBounds(bounds);

    //Illuminate the object with two lights.
    Color3f red = new Color3f(1.f, 0.f, 0.f);
    Color3f blue = new Color3f(0.f, 0.f, 1.f);
    Vector3f reddir  = new Vector3f(0.f, 2.f, -2.f);
    Vector3f bluedir  = new Vector3f(0.0f, -2.0f, -2.0f);

    DirectionalLight redlight = new DirectionalLight(red, reddir);
    DirectionalLight bluelight = new DirectionalLight(blue, bluedir);

    redlight.setInfluencingBounds(bounds);
    bluelight.setInfluencingBounds(bounds);
   // objScale.addChild(lgt1);

    objTrans.addChild(redlight);
    objScale.addChild(bluelight);
    // Let Java 3D perform optimizations on this scene graph.
    objRoot.compile();

    return objRoot;
  }

  public DirectionalLightEx (String argv[]){
    setLayout(new BorderLayout());
    GraphicsConfiguration config =
       SimpleUniverse.getPreferredConfiguration();

    Canvas3D c = new Canvas3D(config);
    add("Center", c);

    BranchGroup scene = createSceneGraph(argv);
    SimpleUniverse u = new SimpleUniverse(c);

    // This will move the ViewPlatform back a bit so the
    // objects in the scene can be viewed.
    u.getViewingPlatform().setNominalViewingTransform();

    u.addBranchGraph(scene);
  }

. . .

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset