DirectX SDK (August 2008).Direct3D 9.官方指导教程 (四)

Tutorial 4: 创建和使用光照(Creating and Using Lights)


Direct3D光照使3D模型更真实,当使用时第一个场景中的几何图形将会根据位置和它的光照类型被照亮。此教程的主题是介绍光照和材质。
使用如下步骤进行材质(Material)和光照(Light)的创建
Steps
Step 1 – 初始化场景几何图形(Initializing Scene Geometry)
Ste 2 - 建立材质和光照(Setting up material and light)
在Light工程中的代码和Matrices工程是一致的。这里主要讲述光照系统而不涉及创建Direct3D、处理消息、渲染、或是关闭等操作,要查看此内容到Tutorial 1:Creating a Device
此教程使用用户顶点和顶点缓冲来显示几何图形更多关于选择用户顶点类型和打开一个顶点缓冲请看Tutorial2:Rendering Vertices
些教程还使用矩阵进行几何图形的变换,更多关于矩阵的知识请看Tutorial3:Using Matrices。
Step 1 - 初始化场景几何图形(Initializing Scene Geometry)
使用光照的首要条件是每一个面都有一条法线。要做到这些Light工程使用一种不同的用户顶点类型,新的用户顶点格式有一个3D坐标和一个表面法线,表面法线使用Direct3D内在的光照计算生成。
Struct CUSTOMVERTEX
{
D3DXVECTOR3 position;
//3d位置坐标
D3DXVECTOR3 normal;
//顶点的表面法线
};
//可变用户顶点格式(FVF)
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL )
现在正确的顶点格式已经定义了,工程调用已经定义的InitGeometry()函数创建一个圆柱。第一步是创建顶点缓存来保存圆柱体的顶点信息如下代码所示:
//创建顶点缓存
If( FAILED( g_pd3dDevice -> CreateVertexBuffer( 50*2*sizeof( CUSTOMVERTEX),
0, 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));
}
在结束了如上将圆柱体顶点信息填入顶点缓存后,顶点缓存已经准备好开始绘制了。但在在这之前此场景的光照和材质还是必须定义的,如第二步所讲述的。
Step2 – 创建材质和光照(Setting Up Material and Light)
为了在Direct3D中使用光照你必有创建一个或更多的光源。渲染几何模型体要创建材质以决定几何体表示哪种颜色。在渲染场景前Light工程调用工程内定义的函数SetupLight()来创建一种材质和一个方向光源。
创建材质(Creating a Material)
材质定义光照射到其上所能反射的颜色,下面的片段使用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()
指定一种新的不同的材质。
现在材质已经应用到了场景,下一步是创建光照。
创建光照(Creating a Light)
在Direct3D中有三种可以使用的光照类型。
点光源(Point Lights)
方向光源(Directional lights)
聚光灯光源(Spotliths )
例子中创建一个方向光源,这种光源只向一个方向照射,程序中会摆动光的照射方向。
下面的代码片段使用D3DLIGHT9结构体创建方向光源
D3DXVECTOR3 vecDir;
D3DLith9 lith;
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()/360f));
D3DXVec3Normalize(( D3DXVECTOR3*) &light.Direction, &vecDir);
调用D3DXVec3Normalize规范化方向向量来决定光照方向。
变量可以控制告诉Direct3D光照影响的范围,但这人参数不影响方向光源,下面的代码设定范围为1000个单位
下面的代码调用IDirect3DDevice9::SetLight()将光源作用到Direct3D设备环境。
g_pd3dDevice -> SetLight( 0, &light);
第一个参数是给这个光源分配的序号,注意如果一个光源已经在那里存在它将会覆盖旧光照类型,第二个参数是指向Light结构体定义的光照指针。Light工程中设定此光索引为0.
下面的代码调用IDirect3DDevice9::LightEnable()来激活光照:
g_pd3dDevice -> LightEnable(0, TRUE);
第一个参数是激活的光源索引号,第二个参数为一个布尔值告知系统TRUE打开光照FALSE关闭光照,在上面的代码中索引为0的光源被打开了。
下面通过调用DDirect3DDevice9::SetRenderState()来告诉Direct3D渲染光照。
g_pd3dDevice -> SetRenderState(D3DRS_LIGHTING, TRUE);
两个参数是系统参数修改指定相应值,设定D3DRS_LIGHTING为TRUE,使系统能够进行光照渲染。
最后一步是通过再次调用IDirect3DDevice9::SetRenderState打开环境光。
g_pd3dDevice -> SetRenderState( D3DRS_AMBIENT, 0X00202020);
以上代码设定D3DRS_AMBIENT环境光为灰色(0x00202020).环境光将会照亮用已经指定的颜色照亮所有物体。
关于更多光照和材质方面的信息查找Lights and materials(Direct3d9)
此教程展示了如何使用光照和材质,第五教程会教你如何进行纹理贴图。

posted @ 2009-09-17 12:10  Maxice  阅读(1228)  评论(0编辑  收藏  举报