教程 4:创建和使用灯光

Direct3D 灯光为 3D 对象添加了更多的真实感。 使用时,场景中的每个几何对象都将根据使用的灯光的位置和类型进行照明。 本教程中的示例代码介绍了灯光和材质的主题。

本教程包含以下步骤来创建材质和灯光。

脚步

  • 第 1 步 - 初始化场景几何
  • 第 2 步 - 设置材质和灯光

Note

Lights 示例项目的路径是:
(SDK 根目录)\Samples\C++\Direct3D\Tutorials\Tut04_Lights

Lights 项目中的示例代码与 Matrices 项目中的示例代码几乎相同。 创建和使用灯光教程只关注创建和使用灯光的独特代码,不包括设置 Direct3D、处理 Windows 消息、渲染或关闭。 有关这些任务的信息,请参阅教程 1:创建设备。

本教程使用自定义顶点和顶点缓冲区来显示几何图形。 有关选择自定义顶点类型和实现顶点缓冲区的更多信息,请参阅教程 2:渲染顶点。

本教程使用矩阵来变换几何。 有关矩阵和转换的更多信息,请参阅教程 3:使用矩阵。

第 1 步 - 初始化场景几何

使用灯光的要求之一是每个表面都有一个法线。 为此,Lights 示例项目使用了不同的自定义顶点类型。 新的自定义顶点格式具有 3D 位置和曲面法线。 表面法线由 Direct3D 在内部用于照明计算。

struct CUSTOMVERTEX
{
    D3DXVECTOR3 position; // The 3D position for the vertex.
    D3DXVECTOR3 normal;   // The surface normal for the vertex.
};
// Custom flexible vertex format (FVF).
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)

现在定义了正确的矢量格式,Lights 示例项目调用 InitGeometry,这是一个创建圆柱体的应用程序定义函数。 第一步是创建一个顶点缓冲区来存储圆柱体的点,如以下示例代码所示。

// Create the vertex buffer.
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX),
                                           0 /*Usage*/, D3DFVF_CUSTOMVERTEX,
                                           D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    return E_FAIL;

 下一步是用圆柱体的点填充顶点缓冲区。 请注意,在以下示例代码中,每个点都由位置和法线定义。

CUSTOMVERTEX* pVertices;
if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) ) return E_FAIL;

for( DWORD i=0; i<50; i++ )
{
    FLOAT theta = (2*D3DX_PI*i)/(50-1);
    pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) );
    pVertices[2*i+0].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
    pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) );
    pVertices[2*i+1].normal   = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) );
}

在前面的示例代码用圆柱体的顶点填充顶点缓冲区之后,顶点缓冲区就可以进行渲染了。 但首先,必须在渲染圆柱体之前设置此场景的材质和灯光。 这在第 2 步 - 设置材质和灯光中进行了描述。

第 2 步 - 设置材质和灯光

要在 Direct3D 中使用光照,您必须创建一个或多个光照。 为了确定几何对象反射的颜色,创建了一种用于渲染几何对象的材质。 在渲染场景之前,Lights 示例项目调用 SetupLights,这是一个应用程序定义的函数,用于设置一种材质和一种定向光。

  • 创建材质
  • 创建灯光

1.创建材质

材质定义了光线照射到几何对象表面时反射的颜色。 以下代码片段使用 D3DMATERIAL9 结构创建黄色材质。

D3DMATERIAL9 mtrl;
ZeroMemory( &mtrl, sizeof(mtrl) );
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 );

材质的漫反射颜色和环境颜色设置为黄色。 对 IDirect3DDevice9::SetMaterial 方法的调用将材质应用于用于渲染场景的 Direct3D 设备。 IDirect3DDevice9::SetMaterial 接受的唯一参数是要设置的材质的地址。 进行此调用后,将使用此材质渲染每个图元,直到对指定不同材质的 IDirect3DDevice9::SetMaterial 进行另一个调用。

现在已经将材质应用到场景中,下一步是创建灯光。

2.创建灯光

Direct3D 中有三种类型的灯光可用:

  • 点灯
  • 定向灯
  • 聚光灯

示例代码创建了一个定向光,它是一种沿一个方向行进的光。 该代码还会振荡光的方向。

以下代码片段使用 D3DLIGHT9 结构来创建定向光。

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

以下代码片段将此灯光的漫反射颜色设置为白色。

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

下面的代码片段将光的方向旋转一圈。

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

对 D3DXVec3Normalize 的调用对用于确定光方向的方向向量进行归一化。

可以指定一个范围来告诉 Direct3D 灯光会产生多远的效果。 该成员不影响定向灯。 以下代码片段为该灯分配了 1000 个单位的范围。

light.Range = 1000.0f;

以下代码片段通过调用 IDirect3DDevice9::SetLight 将灯光分配给 Direct3D 设备。

g_pd3dDevice->SetLight( 0, &light );

IDirect3DDevice9::SetLight 接受的第一个参数是这个灯光将被分配到的索引。 请注意,如果该位置已经存在灯光,它将被新灯光覆盖。 第二个参数是指向定义灯光的灯光结构的指针。 灯光示例项目将此灯光放置在索引 0 处。

以下代码片段通过调用 IDirect3DDevice9::LightEnable 启用灯光。

g_pd3dDevice->LightEnable( 0, TRUE);

IDirect3DDevice9::LightEnable 接受的第一个参数是要启用的灯光的索引。 第二个参数是一个布尔值,指示是打开灯 (TRUE) 还是关闭灯 (FALSE)。 在上面的示例代码中,索引 0 处的灯被打开。

下面的代码片段告诉 Direct3D 通过调用 IDirect3DDevice9::SetRenderState 来渲染灯光。

g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );

IDirect3DDevice9::SetRenderState 接受的前两个参数是要修改哪个设备状态变量以及将其设置为什么值。 此代码示例将 D3DRS_LIGHTING 设备变量设置为 TRUE,这具有启用灯光渲染的效果。

此代码示例的最后一步是通过再次调用 IDirect3DDevice9::SetRenderState 打开环境照明。

g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );

前面的代码片段将 D3DRS_AMBIENT 设备变量设置为浅灰色 (0x00202020)。 环境照明将通过给定的颜色照亮所有对象。

有关照明和材质的详细信息,请参阅灯光和材质 (Direct3D 9)。

本教程向您展示了如何使用灯光和材质。 教程 5:使用纹理贴图向您展示如何向表面添加纹理。

运行效果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值