为了增强所绘场景的真实感,我们可为场景增加光照
。光照有助于描述实体形状和立体感
使用光照时,我们无需自行指定顶点的颜色值;D3D会将顶点送入光照计算引擎,该引擎会依据光源类型、材质以及物体表面相对于光源的朝向
,计算出每个顶点的颜色值
基于某种光照模型计算出各顶点的颜色,会使绘制结果更加逼真。然后在光栅化
过程中,利用计算所得到的顶点的颜色通过指定的着色模式
为组成图元的像素着色
- 1、
光源类型
和光源所发出光线的类型
- 2、
材质的定义方式
- 3、用数学的语言描述
三角形单元的朝向
1、光照的组成
在D3D的光照模型
中,光线由三种类型的光组成:
- 1、
环境光(Ambient Light)
:该类型的光经其他表面反射到达物体表面,并照亮整个场景 - 2、
漫射光(Diffuse Light)
:该类型的光沿特定的方向传播,当它到达某一表面时,将沿各个方向均匀反射。漫射光方程(diffuse lighting equation)
- 3、
镜面光(Specular Light)
:该类型的光沿特定的方向传播,当它到达某一表面时,将严格地沿着另一个方向反射。镜面光方程(specular lighting equation)
与其他光线相比,镜面光的计算量要大得多
,因此D3D为其提供了开关选项,默认状态下是关闭的
。可通过绘制状态D3DRS_SPECULARENABLE
来更改设置
每种类型的光都可用结构D3DCOLORVALUE或D3DXCOLOR
来表示,这些类型描述了光线的颜色。在描述光线的颜色时,Alpha分量将被忽略
2、材质
在现实世界中,我们所观察到的物体的颜色是由该物体所反射的光的颜色决定的。D3D通过定义物体的材质(materials)
来模拟同样的现象
材质允许我们定义物体表面对各种类型光的不同颜色成分的反射比例
,材质用结构D3DMATERIAL9
来表示
typedef struct D3DMATERIAL9{
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float Power;
}D3DMATERIAL9, *LPD3DMATERIAL9;
顶点结构中不含有材质属性,但我们必须对当前材质
进行设定
IDirect3DDevice9::SetMaterial(const D3DMATERIAL9 *pMaterial);
3、顶点法线
面法线
是一个描述多边形朝向的向量;顶点法线
描述的是构成多边形的各个顶点的法线
顶点法线
用来确定光线到达表面时的入射角。由于光照计算是对每个顶点进行的,所以D3D需要知道表面在每个顶点处的局部朝向
光照计算是对每个顶点进行的
顶点法线和表面法线不一定相同
typedef struct Vertex{
float x, y, z;
float _nx, _ny, _nz;
static const DWORD FVF;
}Vertex;
我们将使用光照来自动计算出顶点的颜色
当用三角形单元逼近表示曲面时,将面片法向量作为构成该面片的顶点的法向量是不可能产生很平滑的效果的。一种更好的求取顶点法向量的方法是计算法向量的均值
我们可以使用d3ddev->SetRenderState(D3DRS_NORMALIZENORMALS, true);
一次性重新规范化所有的法向量
4、光源
D3D支持3种类型的光源
:
- 1、
点光源(Point lights)
:在世界坐标系中有固定位置,并向所有的方向发射光线 - 2、
方向光(Directional lights)
:没有位置信息,所发射的光线相互平行地沿某一特定方向传播 - 3、
聚光灯(Spot lights)
:有位置信息,所发射光线呈锥形沿特定方向传播,用两个角度参数来描述
光源用结构D3DLIGHT9来表示
typedef struct D3DLIGHT9{
D3DLIGHTTYPE Type;
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Ambient;
D3DVECTOR Position;
D3DVECTOR Direction;
float Range;
float Falloff;
float Attenuation0;
float Attenuation1;
float Attenuation2;
float Theta;
float Phi;
}D3DLIGHT9, *LPD3DLIGHT;
对于某一特定的光源类型,不是所有的数据成员都需要使用的
每一个光源都可以发出三种类型的光线
当光源实例初始化完毕后,我们需要在D3D所维护的一个光源内部列表
中对所要使用的光源进行注册
;一旦光源注册成功,我们就可对其开关状态进行控制
d3ddev->SetLight(0, &light);
d3ddev->LightEnable(0, true);
为一个场景添加光照的分为四步:
- 1、启用光照
- 2、为物体创建一种材质
- 3、创建光源,并启用
- 4、启用所有光照状态
光源如何发出光线、光线如何与材质作用而决定顶点的颜色,这一系列事情都是光照计算引擎做的