3D遊戲從入門到精通-21-22

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

 

其它渲染部份,同點光源是一樣的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章