问题3-D3D Lighting

ncopy.gif

今天要学习的是dx中的光照。

问题描述:

在一个窗口中显示5个物体,在黑暗的环境中分别用点光源,直线光源,聚光源照射物体,并且照射光源每隔1秒自动变换,物体的颜色也每隔1秒自己随机变换颜色。

Lighting.jpg



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分别对应我们想要的范围的最大值和最小值。这样我们的功能就都可以实现了。

*原创内容,转载请注明出处。*


发表留言

只对管理者显示

No title

好难呀,看不懂的,呵呵……
在韩国好好的学吧。我也在学韩语的呢!
自我介绍

Author:三只熊熊
大家好,欢迎来到我的blog!
目前我正在韩国攻读游戏工学研究生,现在在虚拟现实实验室。
作为刚踏入游戏开发领域的初学者,希望大家多多帮助!

잘 부탁드립니다~ ^_^

最新文章
最新留言
最新引用
月份存档
类别
计数器
搜寻栏
RSS连结
连结
Powered By FC2博客

马上开始博客吧!!

Powered By FC2博客