Understanding Lights
The DirectX Light class represents a light source. Lights have properties that determine the type of the light, its color, and the amount of light it produces for use by ambient, diffuse, and specular illumination.
For example, if a scene contains no lights that provide specular light, then none of the objects in the scene can produce specular highlights. If a light provides green diffuse light, then objects in the scene can reflect green light through diffuse reflection. If another light provides red ambient light, then that light contributes to each object's apparent color.
Direct3D provides three kinds of lights: directional, point, and spot. All three types have ambient, diffuse, and specular components, although they have some other properties that differ.
Directional Lights
A directional light provides light rays that all travel in the same direction. You can think of it as a light that is infinitely far away. For most practical purposes, the sun's rays are all traveling in the same direction when they reach Earth so it's basically a directional light.
Directional lights have the simplest mathematics because light at every point in the scene is traveling in the same direction, which simplifies calculating the light's incident angles. Therefore, directional lights put the smallest load on the Direct3D engine, so it can render directionally lit scenes relatively quickly.
The sample
d3dLightedSphere program, which you'll find in the
downloadable code in both Visual Basic and C# versions, creates a directional light. It sets the light's type to
Directional, sets its diffuse and ambient colors, and specifies the light's direction. In this example, the light is moving in the direction
<0, -4, 1>. Finally the code enables the light so Direct3D will use it when rendering the scene:
m_Device.Lights(0).Type = LightType.Directional
m_Device.Lights(0).DiffuseColor = New ColorValue(0, 0, 256)
m_Device.Lights(0).AmbientColor = New ColorValue(10, 10, 20)
m_Device.Lights(0).Direction = New Vector3(0, -4, -1)
m_Device.Lights(0).Enabled = True
Point Lights
Point lights represent light rays that originate from a single point in space, much as a bare light bulb produces light. Because the light rays from point lights travel in different directions, this type of light makes calculating incident angles harder, and slows down rendering. For example, suppose your scene contains a huge triangle. With a directional light, every light ray hits the triangle at the same angle, so (ignoring specular reflection) the entire triangle is a single color. In contrast, with a point light Direct3D must calculate a different angle of incidence for every pixel that the light can reach.
The following code shows how
d3dLightedSphere creates a point light:
m_Device.Lights(2).Type = LightType.Point
m_Device.Lights(2).Diffuse = Color.White
m_Device.Lights(2).AmbientColor = New ColorValue(0, 1, 0)
m_Device.Lights(2).Position = New Vector3(2, 2, -2)
m_Device.Lights(2).Attenuation0 = 0
m_Device.Lights(2).Attenuation1 = 0.75
m_Device.Lights(2).Attenuation2 = 0
m_Device.Lights(2).Range = 100
m_Device.Lights(2).Specular = Color.White
m_Device.Lights(2).Enabled = True
The code sets the light's type to
Point, gives it diffuse and ambient color values, and specifies the light's position in space.
Next, the code sets three
Attenuation properties that indicate how the light's intensity diminishes over distance. These parameters are confusing and complicated; I won't describe them further here, but you can get more information
from MSDN.
The
Range parameter indicates how far the light penetrates. The value 100 used in this example is big enough so the light can reach every object. Setting it to smaller values would leave some objects in the dark, which could save some processing time for very complicated scenes. The last two lines set the light's specular color to white, and enable the light (turn it on).
Spot Lights
Spot lights are spotlights located at a point in space that project a cone of light in a particular direction. The light is brightest within an inner cone, but diminishes to lighter values in an outer cone that allows the light to fade out at the edges. Spot lights provide no light outside the outer cone. Their complex mathematics makes these lights much more complicated than directional and point lights, and your computer may not be fast enough to render complex scenes containing spot lights quickly enough for animation.
The following code shows how program
d3dLightedSphere creates a spot light:
m_Device.Lights(3).Type = LightType.Spot
m_Device.Lights(3).Diffuse = Color.Green
m_Device.Lights(3).AmbientColor = New ColorValue(0, 1, 0)
m_Device.Lights(3).Position = New Vector3(0, 0, -2)
m_Device.Lights(3).XDirection = -m_Device.Lights(3).XPosition
m_Device.Lights(3).YDirection = -m_Device.Lights(3).YPosition
m_Device.Lights(3).ZDirection = -m_Device.Lights(3).ZPosition
m_Device.Lights(3).Attenuation0 = 1
m_Device.Lights(3).Range = 100
m_Device.Lights(3).Falloff = 1
m_Device.Lights(3).InnerConeAngle = Math.PI / 8
m_Device.Lights(3).OuterConeAngle = Math.PI / 4
m_Device.Lights(3).Enabled = True
The code sets the light's type to
Spot, gives it diffuse and ambient colors, and sets the light's position. This example sets the light's direction to point back toward the origin where the sphere is located. The code then sets the light's
Attenuation and
Range parameters.
Next, the code sets the
Falloff,
InnerConeAngle, and
OuterConeAngle properties that determine the shape of the spotlight, and finishes by enabling the light.
Independent Ambient Light
Direct3D can also add ambient light to the scene that is independent of any light sources. This seems more in keeping with the concept of having ambient light that should apply to the entire scene even if no light is shining directly on an object. However, it makes sense to give your lights ambient components, too, because turning a light off then affects the amount of ambient light in the scene.
The following code shows how the
d3dLightedSphere sample program could add independent ambient light (the code is commented out in the sample program):
m_Device.RenderState.Ambient = Color.FromArgb(255, 32, 32, 32)