Microsoft DirectX 8.1 (C++)

Step 2: Setting up Material and Light

To use lighting in Microsoft® Direct3D®, you must create one or more lights. To determine which color a geometric object reflects, a material is created that is used to render geometric objects. Before rendering the scene, the Lights sample project calls SetupLights, an application-defined function that sets up one material and one directional light.

Creating a Material

A material defines the color that is reflected off the surface of a geometric object when a light hits it. The following code fragment uses the D3DMATERIAL8 structure to create a material that is yellow.

D3DMATERIAL8 mtrl;
ZeroMemory( &mtrl, sizeof(D3DMATERIAL8) );
mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
g_pd3dDevice->SetMaterial( &mtrl );

The diffuse color and ambient color for the material are set to yellow. The call to the IDirect3DDevice8::SetMaterial method applies the material to the Microsoft® Direct3D® device used to render the scene. The only parameter that SetMaterial accepts is the address of the material to set. After this call is made, every primitive will be rendered with this material until another call is made to SetMaterial that specifies a different material.

Now that material has been applied to the scene, the next step is to create a light.

Creating a Light

There are three types of lights available in Microsoft® Direct3D®: point lights, directional lights, and spotlights. The sample code creates a directional light, which is a light that goes in one direction, and it oscillates the direction of the light.

The following code fragment uses the D3DLIGHT8 structure to create a directional light.

D3DXVECTOR3 vecDir;
D3DLIGHT8 light;
ZeroMemory( &light, sizeof(D3DLIGHT8) );
light.Type = D3DLIGHT_DIRECTIONAL;

The following code fragment sets the diffuse color for this light to white.

light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;

The following code fragment rotates the direction of the light around in a circle.

vecDir = D3DXVECTOR3(cosf(timeGetTime()/360.0f),
                     0.0f,
                     sinf(timeGetTime()/360.0f) );
D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );

The call to D3DXVec3Normalize normalizes the direction vector used to determine the direction of the light.

A range can be specified to tell Direct3D how far the light will have an effect. This member does not affect directional lights. The following code fragment assigns a range of 1000 units to this light.

light.Range = 1000.0f;

The following code fragment assigns the light to the Direct3D device by calling IDirect3DDevice8::SetLight.

g_pd3dDevice->SetLight( 0, &light );

The first parameter that SetLight accepts is the index that this light will be assigned to. Note that if a light already exists at that location, it will be overwritten by the new light. The second parameter is a pointer to the light structure that defines the light. The Lights sample project places this light at index 0.

The following code fragment enables the light by calling IDirect3DDevice8::LightEnable.

g_pd3dDevice->LightEnable( 0, TRUE);

The first parameter that LightEnable accepts is the index of the light to enable. The second parameter is a Boolean value that tells whether to turn the light on (TRUE) or off (FALSE). In the sample code above, the light at index 0 is turned on.

The following code fragment tells Direct3D to render lights by calling IDirect3DDevice8::SetRenderState.

g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

The first two parameters that SetRenderState accepts is which device state variable to modify and what value to set it to. This code sample sets the D3DRS_LIGHTING device variable to TRUE, which has the effect of enabling the rendering of lights.

The final step in this code sample is to turn on ambient lighting by again calling SetRenderState.

g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );

The preceding code fragment sets the D3DRS_AMBIENT device variable to a light gray color (0x00202020). Ambient lighting will light up all objects by the given color.

For more information on lighting and materials, see Lights and Materials.

This tutorial has shown you how to use lights and materials. Tutorial 5: Using Texture Maps shows you how to add texture to surfaces.