Intro to VR

Week Seven Lecture Materials

Basic Three-Point Lighting and Viewpoint Placement

Lighting Background

Watch any movie, and I will bet you will recognize classic Hollywood lighting. This is called three-point lighting, and you will see it in use (with minor variations) on television, in movies, and in virtual reality spaces.

Three-point lighting uses three lights (surprise). They are known as the:

  1. Key Light
  2. Fill Light
  3. Back Light

Lighting Details

The process of setting up three-point lighting for a scene in virtual reality is similar to but slightly different than the problem of setting it up for a static 3D rendering (for a still picture). Let us start with setup for 3D rendering. There are four (4) baasic steps to set this up:

  1. start in darkness
  2. add your key light
  3. add your fill light(s)
  4. add your back light
1. Start in Darkness

In xVRML the root node is an instance of a World element, and the World element has an attribute named headlight of type boolean which defaults to true. The same will be true for any Inlined xVRML. You should make sure you start out with the headlight explicitly set to false. You want to start out in darnkness.

2. Add your Key Light

This is how the main illumination for your main subject-of-interest is created. Remember to start out thinking about where you wish to draw the attention of your user. How you place your key light will determine what is most visible to visitors, and you can think of it as like the Sun or the light on the ceiling in an office: it points to the dominant influence in a scene.

Which of the lighting types you choose to use for your scene depends upon the mood you wish to set and how focused you wish the user attention to be on one thing or area. For generalized lighting of an outdoor scene, I would recommend using an instance of the DirectionalLight node. DirectionalLights are computationally cheap to use. DirectionalLights act as though their light is parallel rays arriving from an infinite distance away, just as the rays of real light from the real Sun seem to arrive in the real outdoors.. Same idea, right? The main light on your scene is the key light, and for this example we will use a DirectionalLight.

Viewed from the top, move the key light so it is offset 15° to 45° to the side (left or right) of the opening camera shot (or Viewpoint node in xVRML). Now turn the light so it is pointed towards the main subject. Turn the light in the right direction by changing the DirectionalLight attribute named direction to something other than the default value of 0.0 0.0 -1.0 (pointing straight down the negative-Z axis).

At this point, a rendering of your file might look like this: avatar with one light in place

And the code might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<World xmlns="http://www.xvrml.net/schemas/core"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.xvrml.net/schemas/core 
  http://www.xvrml.net/schemas/xVRML.xsd" headlight="false">
  <children>
    <Viewpoint name="openingShot" position="0.0 0.0 2.0"/>
    <DirectionalLight intensity="1.0" name="rightHighKey" 
            direction="-0.5 -0.5 -0.5" on="true">
      <color red="1.0" green="1.0" blue="1.0" alpha="1.0"/>
    </DirectionalLight>
    <Inline url="http://www.xvrml.net/vrmLab/Warehouse/avatars/girl2.xwrl"/>
  </children>
</World>

The key light is the brightest illuminating the front of the main subject, and it is the main light for making shadows seem to happen. This simple one light scene (with just the key light) should have good contrast between light and dark. It should look almost like the final version, except that it has very harsh contrast and seems to have deep shadows.

3. Add your Fill Light(s)

The fill light softens and extends the illumination from the key light, and it makes more of the subject clearly visible. It can simulate light from the sky, a secondary light like a table lamp, or reflected light in the scene. Again, use a nice, cheap DirectionalLight.

From the top, a fill light should seem to come from a generally opposite angle than the key light. If the Key is on the right (as in our code example), then the fill should be on the left. Do not make all of your lighting symmetrical. Raise the fill to the subject's height, but keep it lower than the key. The fill should be about one-eighth to one-half as bright as your key. The greater the contrast between the two (fill lower, key higher), the more the environment seems shadowy. Change the fill color to match colors the environment to simulate reflected light.

At this point, a rendering of your file might look like this: avatar with two lights in place

And the code might look like this:

<?xml  version="1.0"  encoding="UTF-8"?>
<World  xmlns="http://www.xvrml.net/schemas/core"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.xvrml.net/schemas/core  
    http://www.xvrml.net/schemas/xVRML.xsd"  headlight="false">
  <children>
    <Viewpoint  name="openingShot"  position="0.0  0.0  2.0"/>
    <DirectionalLight  intensity="1.0"  name="rightHighKey"  
            direction="-0.5  -0.5  -0.5"  on="true">
      <color  red="1.0"  green="1.0"  blue="1.0"  alpha="1.0"/>
    </DirectionalLight>
    <DirectionalLight  intensity="0.25"  name="leftHighFill"  
            direction="0.5  -0.5  -0.5"  on="true">
      <color  red="0.8"  green="1.0"  blue="0.8"  alpha="1.0"/>
    </DirectionalLight>
    <Inline  url="http://www.xvrml.net/vrmLab/Warehouse/avatars/girl2.xwrl"/>
  </children>
</World>
4. Add Back Light

The back light helps visually separate the subject from the background. Again, from the top view add a DirectionalLight, and position it behind your subject. Put it opposite the camera, pointing back at the camera. From the right view, position it above your subject and pointing down somewhat. This should give you a rim of light, highlighting the top or side edge of your subject. The back light can be as bright as you wish.

At this point, a rendering of your file might look like this: avatar with three lights in place

And the code might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<World xmlns="http://www.xvrml.net/schemas/core"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.xvrml.net/schemas/core 
    http://www.xvrml.net/schemas/xVRML.xsd" headlight="false">
  <children>
    <Viewpoint name="openingShot" position="0.0 0.0 2.0"/>
    <DirectionalLight intensity="1.0" name="rightHighKey" 
            direction="-0.5 -0.5 -0.5" on="true">
      <color red="1.0" green="1.0" blue="1.0" alpha="1.0"/>
    </DirectionalLight>
    <DirectionalLight intensity="0.25" name="leftHighFill" 
            direction="0.5 -0.5 -0.5" on="true">
      <color red="0.8" green="1.0" blue="0.8" alpha="1.0"/>
    </DirectionalLight>
    <DirectionalLight intensity="1.0" name="centeredBackLight" 
            direction="0.0 0.0 1.0" on="true">
      <color red="0.8" green="0.8" blue="1.0" alpha="1.0"/>
    </DirectionalLight>
    <Inline url="http://www.xvrml.net/vrmLab/Warehouse/avatars/girl2.xwrl"/>
  </children>
</World>

three-point lighting animation

Lighting Problem: Virtual Reality Users Can Move Anywhere

Okay, so you have the lighting looking good from your initial camera position. But we are lighting a VR world, within which a user may move anywhere. What happens when the user moves to a vantage-point which does not look so good with your initial lighting?

This problem is why I recommend the general, scene-wide lighting be DirectionalLight nodes. Put them at the top of the World node children and you should end up with lighting that works most of the time from most vantages. Constrict the user positions with an interior scene with walls and hallways and so on, and your lighting problems become a bit simpler. "First-Person Shooter" games often use this technique of restricting the possible user viewing positions to make the lighting problem easier, and so they are able to pre-compute much/most of the lighting and save that information into the download. General purpose VR viewers do not allow for such pre-computation of lighting, so the problem is more delicate.

Viewpoint Background

In xVRML, the analog of a camera is known as a Viewpoint node. You can place many Viewpoints in a scene, or you may place none and let the default Viewpoint be the only one. The default Viewpoint starts out located at 0.0 0.0 10.0. Viewer applications like Carina generally allow one to walk through the Viewpoints by hitting the PageUp or PageDown keys. Currently, Carina only supports the Viewpoint node attribute named jump being set to true. When false is implemented for the jump attribute of the Viewpoint node, the user will be smoothly interpolated between Viewpoints (seeming to fly) when PageUp or PageDown are hit. For now, the user seems to be teleported instantaneously from one Viewpoint to the next in response to PageUp or PageDown being struck.

Use the Viewpoint node attribute named rotation to turn the camera around from the default of 0.0 0.0 1.0 0.0 (pointing straight down the negative-Z). Use the Viewpoint node attribute named position to move the Viewpoint into the initial position desired (from the default of 0.0 0.0 10.0), or put it inside a Transform node and move it into place along with other things in that Transform.