材料(Direct3D 9)

材料描述多边形如何反射光或在 3D 场景中发出光。 材料属性详细说明了材料的漫射反射、环境反射、光发射和反射突出显示特征。 Direct3D 使用 D3DMATERIAL9 结构携带所有材料属性信息。 除了反射属性外,每个属性都描述为 RGBA 颜色,该颜色表示给定类型的光线的红色、绿色和蓝色部分的反射量,以及 alpha 混合因子。

漫射和环境反射

D3DMATERIAL9 结构的漫射和环境成员描述材料如何反射场景中的环境和漫射光。 由于大多数场景包含比环境光更多的漫射光,漫射反射在确定颜色方面起着最大的作用。 此外,由于漫射光是定向的,漫射光的发病率角度会影响反射的整体强度。 当光与顶点法线平行时,漫射反射最大。 随着角度的增加,漫射反射的影响会减弱。 反射的光量是传入光和顶点法线之间的角度余弦值,如下图所示。

反射光量图示

环境反射(如环境光)是非双向的。 环境反射对呈现对象的明显颜色的影响较小,但它确实会影响整体颜色,当材料中很少或没有漫射光反射时,它最明显。 通过使用D3DRS_AMBIENT标志调用 IDirect3DDevice9::SetRenderState 方法,材料的环境反射会受到场景的环境光设置的影响。

漫射和环境反射协同工作,以确定对象的感知颜色,并且通常是相同的值。 例如,若要呈现蓝色水晶对象,请创建仅反映漫射和环境光的蓝色成分的材料。 当用白色光放在房间里时,水晶似乎是蓝色的。 然而,在只有红光的房间里,同样的水晶看起来是黑色的,因为它的材料不会反射红光。

排放

材料可用于使呈现的对象看起来是自发光的。 D3DMATERIAL9 结构的 Emissive 成员用于描述发出的光的颜色和透明度。 发射会影响对象的颜色,例如,使深色材料更亮,并参与发出的颜色。

可以使用材料的辐射属性来添加对象发出光的错觉,而不会产生向场景添加光线的计算开销。 对于蓝色水晶,如果想要使水晶看起来亮起,但不会对场景中的其他物体投光,则发射属性非常有用。 请记住,具有辐射属性的材料不会发出可以由场景中其他对象反射的光。 若要实现这种反射光,需要在场景中放置额外的光。

反射反射

反射在对象上创建亮点,使它们显得闪亮。 D3DMATERIAL9 结构包含两个成员,用于描述反射突出显示颜色以及材料的整体闪亮度。 通过将反射成员设置为所需的 RGBA 颜色来建立反射高光的颜色 - 最常见的颜色是白色或浅灰色。 在 Power 成员中设置的值控制反射效果的锐度。

反射高光可以产生戏剧性的效果。 再次绘制蓝水晶类比:更大的权力价值创造更尖锐的反射亮点,使水晶似乎相当闪亮。 较小的值会增加效果的区域,产生沉闷的反射,使水晶看起来霜冻。 若要使对象真正哑光,请将 Power 成员设置为零,将 Specular 中的颜色设置为黑色。 试验不同的反射级别,以生成现实的外观以满足你的需求。 下图显示了两个相同的模型。 左侧的反射功率为 10:右侧的模型没有反射。

插图

设置材料属性

Direct3D 呈现设备一次可以使用一组材料属性进行呈现。

在C++应用程序中,通过准备 D3DMATERIAL9 结构来设置系统使用的材料属性,然后调用 IDirect3DDevice9::SetMaterial 方法。

若要准备要使用的 D3DMATERIAL9 结构,请在结构中设置属性信息,以便在呈现过程中创建所需的效果。 下面的代码示例为具有尖锐白色反射高光的紫色材料设置 D3DMATERIAL9 结构。

D3DMATERIAL9 mat;

// Set the RGBA for diffuse reflection.
mat.Diffuse.r = 0.5f;
mat.Diffuse.g = 0.0f;
mat.Diffuse.b = 0.5f;
mat.Diffuse.a = 1.0f;

// Set the RGBA for ambient reflection.
mat.Ambient.r = 0.5f;
mat.Ambient.g = 0.0f;
mat.Ambient.b = 0.5f;
mat.Ambient.a = 1.0f;

// Set the color and sharpness of specular highlights.
mat.Specular.r = 1.0f;
mat.Specular.g = 1.0f;
mat.Specular.b = 1.0f;
mat.Specular.a = 1.0f;
mat.Power = 50.0f;

// Set the RGBA for emissive color.
mat.Emissive.r = 0.0f;
mat.Emissive.g = 0.0f;
mat.Emissive.b = 0.0f;
mat.Emissive.a = 0.0f;

准备 D3DMATERIAL9 结构后,通过调用呈现设备的 IDirect3DDevice9::SetMaterial 方法来应用属性。 此方法接受已准备 D3DMATERIAL9 结构的地址作为其唯一参数。 可以根据需要使用新信息调用 IDirect3DDevice9::SetMaterial,以更新设备的材料属性。 下面的代码示例演示如何在代码中显示这种情况。

// This code example uses the material properties defined for 
// the mat variable earlier in this topic. The pd3dDev is assumed
// to be a valid pointer to an IDirect3DDevice9 interface.
HRESULT hr;
hr = pd3dDev->SetMaterial(&mat);
if(FAILED(hr))
{
    // Code to handle the error goes here.
}

创建 Direct3D 设备时,当前材料会自动设置为下表中显示的默认值。

成员 价值
弥漫 性 (R:0、G:0、B:0、A:0)
镜面 (R:0、G:0、B:0、A:0)
氛围 (R:0、G:0、B:0、A:0)
发射的 (R:0、G:0、B:0、A:0)
权力 (0.0)

 

检索材料属性

通过调用设备的 IDirect3DDevice9::GetMaterial 方法检索呈现设备当前正在使用的材料属性。 与 IDirect3DDevice9::SetMaterial 方法不同,IDirect3DDevice9::GetMaterial 不需要准备。 IDirect3DDevice9::GetMaterial 方法接受 D3DMATERIAL9 结构的地址,并在返回之前使用描述当前材料属性的信息填充所提供的结构。

// For this example, the pd3dDev variable is assumed to 
// be a valid pointer to an IDirect3DDevice9 interface.
HRESULT hr;
D3DMATERIAL9 mat;

hr = pd3dDev->GetMaterial(&mat);
if(FAILED(hr))
{
    // Code to handle the error goes here.
}

注意

如果应用程序未指定用于呈现的材料属性,则系统使用默认材料。 默认材料反射所有漫射光(例如白色),没有环境反射或反射反射,并且没有辐射颜色。

 

灯和材料