We ve Got Camera and Action

We've Got Camera and Action; What About Lights?

Now that we've got our single triangle drawn and spinning around, what else could make it even better? Why, lights of course! We mentioned lights briefly before, when our triangle turned completely black after we first moved over to our nontransformed triangles. Actually, we completely turned the lighting off in our scene. The first thing we need to do is to turn that back on, so change the lighting member back to true:

 device.RenderState.Lighting = true; 

You could just delete the line entirely since the default behavior for the device is to have lighting on; we'll just leave it as true for the sake of clarity. Running the application now, we see we're back to the black triangle again; it's just spinning around now. Maybe we should go ahead and define a light, and turn it on. You'll notice the device class has a lights array attached to it, with each member of the array holding the various light properties. We want to define the first light in the scene and turn it on, so let's add the following code into our OnPaint method just after our triangle definition code:

 device.Lights[0].Type = LightType.Point; device.Lights[0].Position = new Vector3(); device.Lights[0].Diffuse = System.Drawing.Color.White; device.Lights[0].Attenuation0 = 0.2f; device.Lights[0].Range = 10000.0f; device.Lights[0].Commit(); device.Lights[0].Enabled = true; 

So, what exactly do all those lines of code do? First, we define what type of light we want to display. We've picked a point light, which is a light that radiates light in all directions equally, much like a light bulb would. There are also directional lights that travel in a given direction infinitely. You could think of the sun as a directional light (yes, in reality the sun would be a point light since it does give off light in all directions; however, from our perspective on Earth, it behaves more like a directional light). Directional lights are only affected by the direction and color of the light and ignore all other light factors (such as attenuation and range), so they are the least computationally expensive light to use. The last light type would be the spot light, which like its name is used to define a spot light, much like you would see at a concert, highlighting the person on stage. Given the large number of factors in making up the spot light (position, direction, cone angle, and so on), they are the most computationally expensive lights in the system.

With that brief discussion on light types out of the way, we'll continue. Next we want to set the position of our point light source. Since the center of our triangle is at 0, 0, 0, we may as well position our light there as well. The parameterless constructor of Vector3 does this. We set the diffuse component of the light to a white color, so it will light the surface normally. We set the first attenuation property, which governs how the light intensity changes over distance. The range of the light is the maximum distance the light has any effect. Our range far exceeds our needs in this case. You can see the DirectX SDK (included on the CD) for more information on the mathematics of lights.

Finally, we commit this light to the device, and enable it. If you look at the properties of a light, you will notice one of them is a Boolean value called "Deferred". By default, this value is false, and you are therefore required to call Commit on the light before it is ready to be used. Setting this value to true will eliminate the need to call Commit, but does so at a performance penalty. Always make sure your light is enabled and committed before expecting to see any results from it.

Well, if you've run your application once more, you'll notice that even though we've got our light defined in the scene now, the triangle is still black. If our light is on, yet we see no light, Direct3D must not be lighting our triangle, and in actuality, it isn't. Well, why not? Lighting calculations can only be done if each face in your geometry has a normal, which currently we don't have. What exactly is a normal, though? A normal is a perpendicular vector pointing away from the front side of a face; see Figure 1.5.

Figure 1.5. Vertex normals.

graphics/01fig05.gif

Knowing this, let's add a normal to our triangle so we can see the light in our scene. The easiest way to do this would be to change our vertex format type to something that includes a normal. There just so happens to be a structure built in for this as well. Change your triangle creation code to the following:

 CustomVertex.PositionNormalColored[] verts=new CustomVertex.PositionNormalColored[3]; verts[0].SetPosition(new Vector3(0.0f, 1.0f, 1.0f)); verts[0].SetNormal(new Vector3(0.0f, 0.0f, -1.0f)); verts[0].Color = System.Drawing.Color.White.ToArgb(); verts[1].SetPosition(new Vector3(-1.0f, -1.0f, 1.0f)); verts[1].SetNormal(new Vector3(0.0f, 0.0f, -1.0f)); verts[1].Color = System.Drawing.Color. White.ToArgb(); verts[2].SetPosition(new Vector3(1.0f, -1.0f, 1.0f)); verts[2].SetNormal(new Vector3(0.0f, 0.0f, -1.0f)); verts[2].Color = System.Drawing.Color. White.ToArgb(); 

Plus we'll need to change the vertex format to accommodate our new data, so update the following as well:

 device.VertexFormat = CustomVertex.PositionNormalColored.Format; 

The only big change between this set of data and the last one is the addition of the normal and the fact that the color of each vertex is white. As you can see, we've defined a single normal vector for each vertex that points directly away from the front of the vertex. Since our vertices are all on the same z plane (1.0f), with varying coordinates on the x and y planes, the perpendicular vector would be facing the negative z axis alone. Running our application now, you will see our triangle is back, and appears lit. Try changing the color of the diffuse component to other values to see how the light affects the scene. Notice that if you set the color to red, the triangle appears red. Try playing with this member to see various ways the light changes.

One thing to remember is that the light is calculated per vertex, so with low polygon models (such as our single triangle), the lighting looks less than realistic. We will discuss more advanced lighting techniques, such as per pixel lighting, in later chapters. These lights produce a much more realistic scene.



Managed DirectX 9 Graphics and Game Programming, Kick Start
Managed DirectX 9 Kick Start: Graphics and Game Programming
ISBN: B003D7JUW6
EAN: N/A
Year: 2002
Pages: 180
Authors: Tom Miller

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net