3D游戏从入门到精通-21-22

来源:互联网 发布:免费产品推广软件 编辑:程序博客网 时间:2024/05/14 22:27
2.10.1灯光与材质
在现实的世界里,没有光线,是什么东西也看不见的。在D3D的世界里,也是一样的。但是在D3D里有一种光线,是非常奇怪的,这种光线是没有方向,没有位置,整个世界全可以照亮的光线,它就是环境光,它其实有点像我们现实生活里的无影灯。在D3D里光线分为三种类型,分别是点光源、聚光灯和方向光。
 
材质就是说明物体是吸收什么样颜色的光线和反射什么样颜色的光线。在现实世界里,看到各种各样的物体,各色各样的。同是太阳光照射下,看到花朵有红色的,有白色的,有黄色的,还有粉红色的。这种不同的颜色的表现,我们就说是它们的材质不同,也就是它们吸收光线和反射的光线不同。
 
在D3D里有下面几种光线类型:
typedef enum D3DLIGHTTYPE
{
    D3DLIGHT_POINT = 1,
    D3DLIGHT_SPOT = 2,
    D3DLIGHT_DIRECTIONAL = 3,
    D3DLIGHT_FORCE_DWORD = 0x7fffffff,
} D3DLIGHTTYPE, *LPD3DLIGHTTYPE;
 
点光源
点光源是有位置和有颜色,但没有单一方向,而是向四面八方向发出光线的光源。它有点像电灯泡一样,向各个方向都发出光线。如下图所示:
点光源的显示,主要与点光源的位置和物体的顶点法线有关。通过点光源的位置与顶点的法线的夹角来计算表面的光照亮度,顶点的法线跟点光源夹角越小,就越亮。下面就是一个点光源的例子显示的图:
在这个图里,地板是有很多顶点连接的三角形组成,每个顶点的法线方向是垂直于地板。因此地板的亮度就是一个中间亮,慢慢向四周减弱的过程。下面就仔细地看看怎么实现点光源的显示。
在D3D里要表达光源,就得使用数据结构来表示,这是任何程序都缺少不了的。下面就是D3D里用来表示光源的数据结构:
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;
在这个结构里,
Type是光源的类型,就是点光源、方向光和聚光灯。
Diffuse是光源发出漫射光的颜色。
Specular是光源发出镜面反射光的颜色。
Ambient是光源发出环境光的颜色。
Position是光源的位置。方向光是没有位置的。
Direction是光源的方向。点光源是没有方向的。这里使用向量来表达光线的方向,向量可以不用规格化,但不能是零长度的向量。
Range是光线的范围,就是说在这个距离内的物体都能照亮,但方向光是没有范围的。并且这个距离的长度最大不能超过FLT_MAX的平方根。
Falloff是表示聚光灯的内心圈最亮点到外圈的衰减量。这个只能使用在聚光灯上。
Attenuation0、Attenuation1和Attenuation2是用下面的公式来表达的:
        Atten = 1/( Attenuation0+ Attenuation1* d + Attenuation2* d2)
这三个系数表示光强度与距离的关系,Attenuation0是恒定衰减量,Attenuation1是定义线性衰减量,Attenuation2是定义二次衰减量。很多时候,都是让Attenuation0等于0,Attenuation1等于1,Attenuation2等于0,这样光强度就与距离d成反比了。
Theta是聚光灯内光圈的角度。
Phi是聚光灯外光圈的角度。
如下图所示:
 
聚光灯
像汽车的远光灯发出的灯光,就是聚光灯。它有位置、方向和颜色。下面的就是聚光的例子显示的效果图:
 

聚光灯比点光源多了方向,还多了内光圈和外光圈了的角度。因此,初始化灯光的结构时,就需要设置它们才能让聚光灯有效里显示出来。程序初始化如下:

//

//初始化灯光。

//蔡军生 2006/09/03

//

void CCAISpotLight::InitLight(void)

{

  //

  ZeroMemory( &m_meshMaterialFloor, sizeof(D3DMATERIAL9) );

  m_meshMaterialFloor.Diffuse.r = 1.0f;

  m_meshMaterialFloor.Diffuse.g = 1.0f;

  m_meshMaterialFloor.Diffuse.b = 1.0f;

  m_meshMaterialFloor.Diffuse.a = 1.0f;

 

  m_meshMaterialFloor.Ambient.r = 1.0f;

  m_meshMaterialFloor.Ambient.g = 1.0f;

  m_meshMaterialFloor.Ambient.b = 1.0f;

  m_meshMaterialFloor.Ambient.a = 1.0f;

  m_pd3dDevice->SetMaterial( &m_meshMaterialFloor );

 

  //聚光灯

  ZeroMemory( &m_ligthSpot, sizeof(D3DLIGHT9) );

  m_ligthSpot.Diffuse.r    = 1.0f;

  m_ligthSpot.Diffuse.g    = 1.0f;

  m_ligthSpot.Diffuse.b    = 1.0f;

  m_ligthSpot.Diffuse.a    = 1.0f;

  m_ligthSpot.Type         = D3DLIGHT_SPOT;

  m_ligthSpot.Position     = D3DXVECTOR3( 0.0f, 2.0f, 0.0f );

  //

  m_ligthSpot.Direction     = D3DXVECTOR3( 0, -1.0, 0 );

 

  m_ligthSpot.Attenuation0 = 0.0f;

  m_ligthSpot.Attenuation1 = 0.1f;

  m_ligthSpot.Attenuation2 = 0.0f;

  m_ligthSpot.Range        = 30.0f;

 

  //

  m_ligthSpot.Theta        = D3DX_PI/10;

  m_ligthSpot.Phi          = D3DX_PI/4;

  m_ligthSpot.Falloff      = 3.0;

 

  m_pd3dDevice->SetLight( 0, &m_ligthSpot );

 

  //

  ZeroMemory( &m_meshMaterialSpot, sizeof(D3DMATERIAL9) );

  m_meshMaterialSpot.Emissive.r = 1.0f;

  m_meshMaterialSpot.Emissive.g = 1.0f;

  m_meshMaterialSpot.Emissive.b = 1.0f;

  m_meshMaterialSpot.Emissive.a = 1.0f;

 

}

 

上面首先设置地板的材料颜色,接着就初始化聚光灯的结构m_ligthSpot,这里选择灯光类型为D3DLIGHT_SPOT,颜色是白色。还设置了方向和位置,还有内圈的角度为D3DX_PI/10,而外圈的角度为D3DX_PI/4,从内光圈到外光圈衰减为3.0

 

其它渲染部份,同点光源是一样的。

原创粉丝点击