Step 3.2: Set Up Material and Initial Lighting States

After you create the basic 3-D rendering objects (a DirectDraw object, a rendering device, and a viewport), you've got almost all you need to render a simple scene. The next thing to do is to create and configure a material and set some initial lighting states. These can all be changed later if needed. For an introduction to these concepts, see Lighting and Materials.

The Triangle sample starts by retrieving the IDirect3D3 interface pointer for the rendering device by calling the IDirect3DDevice3::GetDirect3D method (a pointer to the rendering device, and one to the viewport are passed to the App_InitDeviceObjects function from which this code is taken). Then, it creates a material object and sets material parameters, as shown here:

    // Create the material object.
    if( FAILED( pD3D->CreateMaterial( &g_pmtrlObjectMtrl, NULL ) ) )
        return E_FAIL;
 
    // Set properties for ambient reflectance.
    D3DMATERIAL       mtrl;
    D3DMATERIALHANDLE hmtrl;
    ZeroMemory( &mtrl, sizeof(D3DMATERIAL) );
    
    // Always set the structure size!
    mtrl.dwSize       = sizeof(D3DMATERIAL);
    mtrl.dcvAmbient.r = 1.0f;
    mtrl.dcvAmbient.g = 1.0f;
    mtrl.dcvAmbient.b = 0.0f;
 
    // Commit the properties to the material.
    g_pmtrlObjectMtrl->SetMaterial( &mtrl );
 

The preceding code creates a material object, represented by the IDirect3DMaterial3 interface, by calling the IDirect3D3::CreateMaterial object. The new interface is assigned to an application-defined global variable, g_pmtrlObjectMtrl. When created, a new material has no properties and cannot be used in rendering. The code prepares material properties in a D3DMATERIAL structure to describe a material that will reflect the red and green components of ambient light, making it appear yellow in the scene. (This tutorial only uses ambient light, so it only sets an ambient reflectance property. A real-world application would use direct light as well as ambient light, and should set therefore set diffuse and specular reflectance properties as well.) After preparing the material properties, the code applies them to the material object by calling the IDirect3DMaterial3::SetMaterial method.

Note  When using textures, the object material is usually omitted or colored white.

After setting the material properties, you can retrieve the material handle that is used to select it for rendering. You retrieve a material handle by calling the IDirect3DMaterial3::GetHandle method. Once you have the material handle, you can select the current material by calling the IDirect3DDevice3::SetLightState method, passing the D3DLIGHTSTATE_MATERIAL enumerated value in the first parameter and the material handle in the second parameter. The Triangle sample does this with the following code:

    // Bind the material to the device.
    g_pmtrlObjectMtrl->GetHandle( pd3dDevice, &hmtrl );
 
    // Select the current material.
    pd3dDevice->SetLightState(  D3DLIGHTSTATE_MATERIAL, hmtrl );
 

After the current material is selected, all polygons will be rendered using this material. However, before anything in the scene will be visible you need to provide some light. The code in Triangle sets an ambient light level by calling the IDirect3DDevice3::SetLightState method to set the D3DLIGHTSTATE_AMBIENT light state for white ambient light:

    // Set up white ambient light.
    pd3dDevice->SetLightState(  D3DLIGHTSTATE_AMBIENT,  0xffffffff );
 

Now that the geometry, material, and initial lighting parameters are set, the sample moves on to setting up the transformation matrices. This is covered in Step 3.3: Prepare and Set Transformation Matrices.