用C#一步一步构建一个完整的D3D场景(三) 灯光类

先看一下Direct3D的Light类的定义:

我们常用的属性如下:

Type——光源类型,支持三种类型的光源:1、定向光源Directional,这种光源没有位置,有一个固定的方向,所发出的光是平行的,它不会发生衰减。2、点光源Point,这种光源有自己的位置,它所发出的光会向所有方向照射,没有固定的方向。3、聚光灯光源Spot,这种光源类似于手电筒,有自己的位置和方向,同时会有一个较亮内圆锥和一个较暗的外圆锥。

Ambient,AmbientColor——光源发出的环境光颜色,Ambient以整数形式表示ARGB,AmbientColor以浮点数形式表示ARGB,下同。

Diffuse,DiffuseColor——光源发出的漫反射光颜色。

Specular,SpecularColor——光源发出的镜面光颜色。

Attenuation0, Attenuation1,Attenuation2——一组定义光强度随传播距离衰减的参数,只对点光源和聚光灯有效,如果D为指定点到光源的距离,衰减的计算公式为:

         Attenuation=\frac{1}{A0+A1*D+A2*{D^{2}}}

Direction——光的传播方向,该属性对点光源无效

Position——光源的位置,该属性对定向光源无效

Range——光线能传播的最大范围,该属性对定向光源无效

Falloff——聚光灯有效,定义光源内圆锥到外圆锥之间的强度衰减,通常设置为1.0f。

InnerConeRadio,OuterConeRadio——内外圆锥的角度,以弧度表示。

Enabled——灯光的开关状态,这里需要注意的是,只有把灯光加载到Direcr3D设备上以后才可以对该属性进行读写,否则会出现错误。

 

可以看到,Direct3D的灯光类已经很强大了,为什么我们还要写自己的灯光类呢。

第一,Direct3D设备可以加载的灯光数量是有限的,最多加载8个。一般来说已经足够用了,但是某些特殊场合可能会超过这个数量,其中有些灯光是关闭的,为了实现动态管理,我们只将已经点亮的灯光加载到设备。但是,从上面的说明可以看出,在灯光被加载到场景前,你是无法确定灯光是关闭还是打开的,所以对于未被加载的灯光我们没办法确定它的状态,需要额外为它设置一个标志。

第二,Direct3D的灯光类无法添加事件且无法对其他事件进行响应。举个例子,一个人在场景中行走,当环境光弱到一定程度的时候,他会打开随身携带的手电筒,当环境光恢复到足够强的时候他会关闭手电筒。在这个例子中,首先,人需要订阅环境光强度变化的事件,根据环境光的强度确定是否要打开或关闭手电筒,其次,手电筒要订阅人在场景中移动或转动的事件,使得手电筒的位置始终跟随人的位置,方向指向人的前方。再举个例子,人在黑暗环境中和明亮环境中的反应会不一样,所以,他可以订阅灯光的开关事件,根据灯光的开关状态作出自己不同的反应。这些功能是无法通过Direct3D自带的Light实现的。

第三,从上面Direct3D自带Light属性说明中,我们发现有些属性仅仅对某些光源有效,所以我们会从自己的D3D_Light基类中派生出三种不同的光源类,并且定义一些默认的参数,会使得光源的初始化更为简单。

由于Direct3D的Light是封闭的,所以我们无法通过继承来实现我们自己的D3D_Light类,需要在我们自己的D3D_Light类中定义一个Light对象,同时为我们的D3D_Light加上一个Enabled标志,使得我们可以随时检测或设置灯光的开关状态。同时我们的灯光类还添加了四个事件,光的强度变化事件、灯光的开关状态发生变化的事件、光源位置发生变化的事件、光源方向发生变化的事件,其他对象可以通过订阅这几个事件来作出相应的动作。最后我们给D3D_Light添加一个name的成员变量以便于我们方便的查找已经定义的灯光。

好了,说了这么多,让我们来看一下我们的D3D_Light的代码:

    public abstract class D3D_Light
    {
        public static float DefaultRatioOfAmbient = 0.5f;//缺省的环境光与漫射光的颜色比例
        public static float DefaultRatioOfSpecular = 0.3f;//缺省的镜面光与漫射光的颜色比例
        public static bool DefaultLightEnabled = false;

        public delegate void DiffuseChangedEventHandler(object sender, EventArgs e);
        public delegate void StateChangedEventHandler(object sender, EventArgs e);
        pu
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值