With the default lighting model (Phong), a scene graph also needs at least one light before you can view its objects. During a rendering action, traversing a light node in the scene graph turns that light on. The position of the light node in the scene graph determines two things:
- *What the light illuminates—*a light illuminates everything that follows it in the scene graph. (The light is part of the traversal state, described in Nodes and Groups. Use a SoSeparator node to isolate the effects of a particular light from the rest of the scene graph.)
- *Where the light is located in 3D space—*certain light-source nodes (for example, SoPointLight) have a location field. The current geometric transformation affects this light location. Other light-source nodes have a specified direction (for example, SoDirectionalLight), which is also affected by the current geometric transformation. Note that the lights from all light-source nodes accumulate. Each time you add a light to the scene graph, the scene appears brighter. The maximum number of active lights depends on the OpenGL implementation.
(Advanced) In some cases, you may want to separate the position of the light in the scene graph from what it illuminates. Example 4-2 uses the SoTransformSeparator node to move only the position of the light. You can also use sensors and engines to change a light's behavior. For example, you can attach a sensor to a sphere object; when the sphere position changes, the sensor can change the light position as well. Or, you can use an engine that finds the path to a given object to change the location of the light that illuminates that object (see SoComputeBoundingBox in the Open Inventor C++ Reference Manual).
SoLight
All lights are derived from the abstract base class SoLight. This class adds no new methods to SoNode. Its fields are as follows:
| |
on (SoSFBool) | whether the light is on. |
intensity (SoSFFloat) | brightness of the light. Values range from 0.0 (no illumination) to 1.0 (maximum illumination). |
color (SoSFColor) | color of the light. |
Subclasses of SoLight
The SoLight class contains four subclasses, as shown in Light-Node Classes :
Light-Node Classes
Light-Node Examples shows the effects of each of these light types. The left side of the figure shows the direction of the light rays, and the right side shows the same scene rendered with each light type. The gray manipulators show the placement and orientation (when relevant) of the lights.
Light-Node Examples
Directional lights are typically faster than point lights for rendering. Both are typically faster than spotlights. To increase rendering speed, use fewer and simpler lights.
SoPointLight
A light of class SoPointLight, like a star, radiates light equally in all directions from a given location in 3D space. An SoPointLight node has one additional field:
| |
location (SoSFVec3f) | 3D location of a point light source. (This location is affected by the current geometric transformation.) |
SoDirectionalLight
A light of class SoDirectionalLight illuminates uniformly along a particular direction. Since it is infinitely far away, it has no location in 3D space. An SoDirectionalLight node has one additional field:
| |
direction (SoSFVec3f) | specifies the direction of the rays from a directional light source. (This direction is affected by the current geometric transformation.) |
SoSpotLight
A light of class SoSpotLight illuminates from a point in space along a primary direction. Like a theatrical spotlight, its illumination is a cone of light diverging from the light's position. An SoSpotLight node has four additional fields (see Fields for SoSpotLight Node ):
| |
location (SoSFVec3f) | 3D location of a spotlight source. (This location is affected by the current geometric transformation.) |
direction (SoSFVec3f) | primary direction of the illumination. |
dropOffRate (SoSFFloat) | rate at which the light intensity drops off from the primary direction (0.0 = constant intensity, 1.0 = sharpest drop-off). |
cutOffAngle (SoSFFloat) | angle, in radians, outside of which the light intensity is 0.0. This angle is measured from one edge of the cone to the other. |
SoQuadAreaLight
A light of class SoQuadAreaLight defines a light source that covers a rectangular area. An SoQuadAreaLight node has five additional fields:
| |
location (SoSFVec3f) | 3D location of a SoQuadAreaLight source. (This location is affected by the current geometric transformation.) |
orientation (SoSFRotation) | primary orientation of the illumination. |
width (SoSFFloat) | Width of the area. |
height (SoSFFloat) | Height of the area. |
twoSided (SoSFBool) | Two-Sided illumination. When TRUE, this enables illumination on both sides of the area. |
Using Multiple Lights
You can now experiment by adding different lights to a scene. Using Different Types of Lights contains two light sources: a stationary red directional light and a green point light that is moved back and forth by an SoShuttle node (see Engines). Scene Graph for Light Example shows the scene graph created by this example.
Fields for SoSpotLight Node
Example : Using Different Types of Lights
C++ :
#include <Inventor/SoDB.h>
#include <Inventor/Xt/SoXt.h>
#include <Inventor/Xt/viewers/SoXtExaminerViewer.h>
#include <Inventor/nodes/SoCone.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoPointLight.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoShuttle.h>
#include <Inventor/nodes/SoTransformSeparator.h>
main( int, char** argv )
{
// Initialize Inventor and Xt
Widget myWindow = SoXt::init( argv[0] );
if ( myWindow == NULL )
exit( 1 );
SoSeparator* root = new SoSeparator;
root->ref();
// Add a directional light
SoDirectionalLight* myDirLight = new SoDirectionalLight;
myDirLight->direction.setValue( 0, -1, -1 );
myDirLight->color.setValue( 1, 0, 0 );
root->addChild( myDirLight );
// Put the shuttle and the light below a transform separator.
// A transform separator pushes and pops the transformation
// just like a separator node, but other aspects of the state
// are not pushed and popped. So the shuttle's translation
// will affect only the light. But the light will shine on
// the rest of the scene.
SoTransformSeparator* myTransformSeparator = new SoTransformSeparator;
root->addChild( myTransformSeparator );
// A shuttle node translates back and forth between the two
// fields translation0 and translation1.
// This moves the light.
SoShuttle* myShuttle = new SoShuttle;
myTransformSeparator->addChild( myShuttle );
myShuttle->translation0.setValue( -2, -1, 3 );
myShuttle->translation1.setValue( 1, 2, -3 );
// Add the point light below the transformSeparator
SoPointLight* myPointLight = new SoPointLight;
myTransformSeparator->addChild( myPointLight );
myPointLight->color.setValue( 0, 1, 0 );
C# :
using System.Windows.Forms;
using OIV.Inventor.Nodes;
using OIV.Inventor.Win.Viewers;
namespace _04_2_Lights {
public partial class MainForm : Form
{
SoWinExaminerViewer myViewer;
public MainForm()
{
InitializeComponent();
CreateSample();
}
public void CreateSample()
{
SoSeparator root = new SoSeparator();
// Add a directional light
SoDirectionalLight myDirLight = new SoDirectionalLight();
myDirLight.direction.SetValue( 0, -1, -1 );
myDirLight.color.SetValue( 1, 0, 0 );
root.AddChild( myDirLight );
// Put the shuttle and the light below a transform separator.
// A transform separator pushes and pops the transformation
// just like a separator node, but other aspects of the state
// are not pushed and popped. So the shuttle's translation
// will affect only the light. But the light will shine on
// the rest of the scene.
SoTransformSeparator myTransformSeparator = new SoTransformSeparator();
root.AddChild( myTransformSeparator );
// A shuttle node translates back and forth between the two
// fields translation0 and translation1.
// This moves the light.
SoShuttle myShuttle = new SoShuttle();
myTransformSeparator.AddChild( myShuttle );
myShuttle.translation0.SetValue( -2, -1, 3 );
myShuttle.translation1.SetValue( 1, 2, -3 );
// Add the point light below the transformSeparator
SoPointLight myPointLight = new SoPointLight();
myTransformSeparator.AddChild( myPointLight );
myPointLight.color.SetValue( 0, 1, 0 );
root.AddChild( new SoCone() );
myViewer = new SoWinExaminerViewer( this, "", true, SoWinFullViewer.BuildFlags.BUILD_ALL, SoWinViewer.Types.BROWSER );
myViewer.SetSceneGraph( root );
myViewer.SetTitle( "Lights" );
myViewer.SetHeadlight( false );
}
}
} // namespace _04_2_Lights
Java :
package inventor.mentor.lights;
import tools.*;
import com.openinventor.inventor.nodes.*;
import com.openinventor.inventor.awt.*;
import java.awt.*;
public class Main extends DemoInventor
{
public static void main( String[] args )
{
Main applet = new Main();
DemoInventor.isAnApplet = false;
applet.start();
demoMain( applet, "Lights" );
}
public void start()
{
super.start();
// Add a directional light
SoDirectionalLight myDirLight = new SoDirectionalLight();
myDirLight.direction.setValue( 0, -1, -1 );
myDirLight.color.setValue( 1, 0, 0 );
// Put the shuttle and the light below a transform separator.
// A transform separator pushes and pops the transformation
// just like a separator node, but other aspects of the state
// are not pushed and popped. So the shuttle's translation
// will affect only the light. But the light will shine on
// the rest of the scene.
SoTransformSeparator myTransformSeparator = new SoTransformSeparator();
// A shuttle node translates back and forth between the two
// fields translation0 and translation1.
// This moves the light.
SoShuttle myShuttle = new SoShuttle();
myTransformSeparator.addChild( myShuttle );
myShuttle.translation0.setValue( -2, -1, 3 );
myShuttle.translation1.setValue( 1, 2, -3 );
// Add the point light below the transformSeparator
SoPointLight myPointLight = new SoPointLight();
myTransformSeparator.addChild( myPointLight );
myPointLight.color.setValue( 0, 1, 0 );
*
Scene Graph for Light Example
C++ :
root->addChild( new SoCone );
SoXtExaminerViewer* myViewer = new SoXtExaminerViewer( myWindow );
myViewer->setSceneGraph( root );
myViewer->setTitle( "Lights" );
myViewer->setHeadlight( FALSE );
myViewer->show();
SoXt::show( myWindow );
SoXt::mainLoop();
C# :
root.AddChild( new SoCone() );
myViewer = new SoWinExaminerViewer( this, "", true, SoWinFullViewer.BuildFlags.BUILD_ALL, SoWinViewer.Types.BROWSER );
myViewer.SetSceneGraph( root );
myViewer.SetTitle( "Lights" );
myViewer.SetHeadlight( false );
Java :
SoSeparator root = new SoSeparator();
{ // Assemble scene graph
root.addChild( myDirLight );
root.addChild( myTransformSeparator );
root.addChild( new SoCone() );
}
SwSimpleViewer myViewer = new SwSimpleViewer();
myViewer.setSceneGraph( root );
setLayout( new BorderLayout() );
add( myViewer, BorderLayout.CENTER );