问题3-D3D Lighting
今天要学习的是dx中的光照。
问题描述:
在一个窗口中显示5个物体,在黑暗的环境中分别用点光源,直线光源,聚光源照射物体,并且照射光源每隔1秒自动变换,物体的颜色也每隔1秒自己随机变换颜色。
DX9供给我们三种光源:点光源(PointLight),直线光源(DirectionalLight)和聚光源(SpotLight)。点光源就是像是太阳一样,在空间一点像各个方向射出光线;直线光源就是从一个方向往另一个方向照射的光;聚光源就像一个手电筒射出的光一样。
首先,在头文件里不仅要想上次一样定义颜色,还要定义材质(Material),和光源。定义材质是为了让物体有颜色。光源可以用D3DLIGHT9这个结构体来定义,材质可以使用D3DMATERIAL9这个结构体来定义。我们来先看看这2个结构体是如何构造的,先看看D3DLIGHT9的结构
typedef struct _D3DLIGHT9 {
D3DLIGHTTYPE Type;
/*光源类型*/
D3DCOLORVALUE Diffuse;
/* 漫射光的颜色*/
D3DCOLORVALUE Specular;
/* 镜面放射光的颜色 */
D3DCOLORVALUE Ambient;
/* 环境光的颜色*/
D3DVECTOR Position;
/* 光源位置,对于直线光源来说没有意义*/
D3DVECTOR Direction;
/* 光源照射方向,对于点光源来说没有意义*/
float Range;
/* 光照射的距离,对于直线光源来说没有意义*/
float Falloff;
/* 只用来聚光源,决定聚光源圆锥形光照范围内外的强度差异,一般设置为0.1f */
float Attenuation0;
float Attenuation1;
float Attenuation2;
/*这三个主要是决定光强度的衰减程度,对于直线光源没有意义*/
float Theta;
/* 指定聚光源内圆锥形的角度*/
float Phi;
/* 指定聚光源外圆锥形的角度*/
} D3DLIGHT9;
这就是D3DLIGHT9 的结构,里面的内容很多,实际用的时候并没有这么复杂。下面是D3DMATERIAL9结构体。
typedef struct _D3DMATERIAL9 {
D3DCOLORVALUE Diffuse;
/* 漫反射光*/
D3DCOLORVALUE Ambient;
/* 环境光*/
D3DCOLORVALUE Specular;
/* 镜面反射光*/
D3DCOLORVALUE Emissive;
/* 是使物体自身放光的参数*/
float Power;
/* 镜面反射的尖锐程度*/
} D3DMATERIAL9;
这就是D3DMATERIAL9的结构,看起来要比D3DLIGHT9要简单得多。
颜色,材质,光源定义好后,就可以使用了。
Device->SetLight(0, &Light);
这里Light就是上面的D3DLIGHT9定义的结构体。使用的时候一定要打开光照:
Device->LightEnable(0, true);
设置物体材质:
Device->SetMaterial(&Mtrls);
这里Mtrls就是上面的D3DMATERIAL9定义的结构体。
光照设置过程大概就是这样的。下面说一下程序里要求的每隔1秒变换光源。其实就是定义一个Timer,在c++中,Timer是被回调函数回调的,所以Timer要写成回调函数的形式。
void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
//这里是操作代码}
调用的时候:
SetTimer(0,1,1000,TimerProc);
第一个参数是窗口句柄,第二个参数是Timer的序号,第三个参数是时间间隔,最后一个参数是回调函数。
时间间隔的问题解决了,剩下就是随机变换颜色的问题了。当然就要使用随机数的函数。为了不让每次取得的随机数相同,所以还要设置随机数种子,一般都是用系统时间来作为种子。
设置随机种子:
srand((unsigned)time(NULL));
time是取得系统时间。然后用rand()函数就可以取得随机数了。我们把材质结构体可以用一个数组的形式表示,然后用随机数来作为数组的下标就可以完成随机变换颜色的功能了。但是rand()取得随机数没有范围,所以我们还要给它设置个范围。在MSDN上查了一圈,发现了个公式:
(double)rand() / (RAND_MAX + 1) * (range_max - range_min)+ range_min;
这个公式用来返回有范围的随机数。这里RAND_MAX是个系统定义的宏,我们可以不去管它,range_max和range_min分别对应我们想要的范围的最大值和最小值。这样我们的功能就都可以实现了。
*原创内容,转载请注明出处。*


