光照系统用于增强场景的真实感,描述实体的形状和立体感,启用光照系统后,Direct3D会根据材质,光源属性等信息自动计算每个顶点的颜色值,使绘制结果更加逼真
Direct3D的光照模型中,光源的光由以下三个分量组成
Direct3D的各类光都可用D3DCOLORVALUE或D3DXCOLOR表示,使用D3DXCOLOR表示时,其中alpha值会被忽略
材质用于定义物体表面对各类光的反射比例,由结构D3DMATERIAL9表示
typedef struct D3DMATERIAL9
{
D3DCOLORVALUE Diffuse;
D3DCOLORVALUE Ambient;
D3DCOLORVALUE Specular;
D3DCOLORVALUE Emissive;
float power;
}D3DMATERIAL9, *LPD3DMATERIAL9;
//Emissive设置了物体的自发光属性,power指定了高光点的锐度
Direct3D通过顶点法线计算光纤到达表面时的入射角并进一步计算光照,由于一个顶点常常被若干平面共享,因此,常采用计算所属各面法线平均值的方法来计算顶点法线
//顶点顺时针绕序和逆时针绕序所计算出的法线方向相反
void calcNormal(D3DXVECTOR3 *p0,
D3DXVECTOR3 *p1,
D3DXVECTOR3 *p2,
D3DXVECTOR3 result)
{
D3DXVECTOR3 u = *p1 - *p0;
D3DXVECTOR3 v = *p2 - *p0;
D3DXVec3Cross(out, &u, &v);
D3DXVec3Normalize(out, out);
}
Device->SetRenderStaes(D3DRS_NORMALIZENORMALS, true);
Direct3D支持三种类型的光源
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;
//Setup light
D3DLIGHT9 light1;
::ZeroMemory(&light1, sizeof(light1));
light1.Type = D3DLIGHT_DIRECTIONAL;
light1.Ambient = WHITE * 0.3f;
light1.Diffuse = RED;
light1.Specular = WHITE * 0.7f;
light1.Direction ={ 1.0f, 0.0f, 0.0f };
pD3DDEV->SetLight(0, &light1);
pD3DDEV->LightEnable(0, true
//Set Light position
float posinit = 0.0f;
D3DXMATRIX position = (&posinit);
position._11 = 3.0f;
position._22 = 3.0f;
position._33 = 3.0f;
D3DXMATRIX rotate;
static float y = 0.0f;
D3DXMatrixRotationY(&rotate, y);
y += DeltaTime;
//Set Light
D3DLIGHT9 lt;
::ZeroMemory(<, sizeof(lt));
lt.Type = D3DLIGHT_POINT;
lt.Ambient = WHITE * 0.3f;
lt.Diffuse = RED;
lt.Specular = WHITE * 0.7f;
lt.Range = 100.0f;
lt.Attenuation0 = 1.0f;
lt.Attenuation1 = 0.0f;
lt.Attenuation2 = 0.0f;
lt.Position = D3DXVECTOR3(position._11 * sinf(y), position._22 , position._33* cosf(y));
pD3DDEV->SetLight(0, <);
pD3DDEV->LightEnable(0, true);
//Set Light
D3DLIGHT9 light;
static float posx = 0.0f;
static float posy = 0.0f;
D3DXVECTOR3 dir = D3DXVECTOR3(posx, posy, 1.0f);
light.Type = D3DLIGHT_SPOT;
light.Ambient = WHITE * 0.3f;
light.Diffuse = RED;
light.Specular = WHITE * 0.7f;
light.Attenuation0 = 1.0f;
light.Attenuation1 = 0.0f;
light.Attenuation2 = 0.0f;
light.Position = D3DXVECTOR3(0.0f, 0.0f, -3.0f);
light.Falloff = 5.0f;
light.Range = 100.0f;
light.Phi = D3DX_PI / 2.5;
light.Theta = D3DX_PI / 45;
if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
posx -= 0.5f * DeltaTime;
if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
posx += 0.5f * DeltaTime;
if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
posy += 0.5f * DeltaTime;
if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
posy -= 0.5f * DeltaTime;
light.Direction = dir;
pD3DDEV->SetLight(0, &light);
pD3DDEV->LightEnable(0, true);
Written with StackEdit.