您的位置:首页 > 其它

17. 增加对硬件光照的支持

2011-08-21 22:55 260 查看
该游戏项目一开始先创建名为light.h、material.h的两个文件。

light.h头文件用于创建灯源结构,该结构用于创建Direct3D中的灯源对象。以某种方式实现该结构,这样也可将其用于OpenGL或其他渲染系统。光源结构模仿了Direct3D中的D3DLIGHT结构,所以它们是完全兼容的。

light.h

#ifndef _UGP_LIGHT_H_
#define _UGP_LIGHT_H_

struct stLight
{
stLight()
{
type = 0;
posX = 0, posY = 0, posZ = 0;
dirX = 0, dirY = 0, dirZ = 0;
ambientR = ambientG = ambientB = ambientA = 1;
diffuseR = diffuseG = diffuseB = diffuseA = 1;
specularR = specularG = specularB = specularA = 0;
range = 0;
falloff = 0;
attenuation0 = 0;
attenuation1 = 0;
attenuation2 = 0;
theta = 0;
phi = 0;
}

int type;
float posX, posY, posZ;
float dirX, dirY, dirZ;
float ambientR, ambientG, ambientB, ambientA;
float diffuseR, diffuseG, diffuseB, diffuseA;
float specularR, specularG, specularB, specularA;
float range;
float falloff;
float attenuation0;
float attenuation1;
float attenuation2;
float theta;
float phi;
};

#endif


  material.h

// ========================================================================
//§ material.h 文件
//§
//§ 【描述】:定义材质结构:stMaterial
//§
// ========================================================================

#ifndef _UGP_MATERIAL_H_
#define _UGP_MATERIAL_H_

struct stMaterial
{
stMaterial()
{
emissiveR = emissiveG = emissiveB = emissiveA = 0;
ambientR = ambientG = ambientB = ambientA = 1;
diffuseR = diffuseG = diffuseB = diffuseA = 1;
specularR = specularG = specularB = specularA = 0;
power = 0;
}

float emissiveR, emissiveG, emissiveB, emissiveA;
float ambientR, ambientG, ambientB, ambientA;
float diffuseR, diffuseG, diffuseB, diffuseA;
float specularR, specularG, specularB, specularA;
float power;
};

#endif


  

Direct3D渲染系统需要一种创建光源和材质的方法。这可以通过为渲染系统添加三个新函数来实现。第一个函数是SetMaterial(),它的参数包括材质(stMaterial)对象,并将其施加到渲染设备上。第二个新函数是SetLight(),它的参数包括灯源对象、灯源索引(因为Direct3D和OpenGL由多达8个的硬件光源,所以索引值可以是0~7),并且调用必须的Direct3D函数用于在硬件中创建和注册光源。最后一个新函数是DisalbeLight(),它以想要关闭灯源的索引为参数。给出了新增加的CD3DRenderer和CRenderInterface类。

class CRenderInterface
{
// ...The beginning of the class functions...

// 设置材质
virtual void SetMaterial(stMaterial *mat) = 0;

// 设置并启用光源
virtual void SetLight(stLight *light, int index) = 0;

// 关闭光源
virtual void DisableLight(int index) = 0;

// ...The rest of the class's functions...
};

class CD3DRenderer : public CRenderInterface
{
// ...The beginning of the class functions...

// 设置材质
void SetMaterial(stMaterial *mat);

// 设置并启用光源
void SetLight(stLight *light, int index);

// 关闭光源
void DisableLight(int index);

// ...The rest of the class's functions...
};


  D3DRenderer.cpp源文件实现了三个和Direct3D打交道的函数。SetMaterial()函数使用材质结构中的信息创建Direct3D材质对象,并调用Direct3D设备函数SetMaterial()将该对象直接发送给Direct3D。这同样使用于SetLight()函数。SetLight()函数的参数包括光源结构,该函数使用该参数设置D3DLIGHT9对象,并将其直接发送给Direct3D。DisableLight()函数的参数包括光源索引,它将关闭注册在该索引上的所有光源。给出了这些函数的源代码。

// 设置材质
void CD3DRenderer::SetMaterial(stMaterial *mat)
{
if(!mat || !m_Device) return;

D3DMATERIAL9 m = { mat->diffuseR, mat->diffuseG,
mat->diffuseB, mat->diffuseA,
mat->ambientR, mat->ambientG,
mat->ambientB, mat->ambientA,
mat->specularR, mat->specularG,
mat->specularB, mat->specularA,
mat->emissiveR, mat->emissiveG,
mat->emissiveB, mat->emissiveA,
mat->power
};

m_Device->SetMaterial(&m);
}

// 设置并启用光源
void CD3DRenderer::SetLight(stLight *light, int index)
{
if(!light || !m_Device || index < 0) return;

D3DLIGHT9 l;

l.Ambient.a = light->ambientA;
l.Ambient.r = light->ambientR;
l.Ambient.g = light->ambientG;
l.Ambient.b = light->ambientB;
l.Attenuation0 = light->attenuation0;
l.Attenuation1 = light->attenuation1;
l.Attenuation2 = light->attenuation2;
l.Diffuse.a = light->diffuseA;
l.Diffuse.r = light->diffuseR;
l.Diffuse.g = light->diffuseG;
l.Diffuse.b = light->diffuseB;
l.Direction.x = light->dirX;
l.Direction.y = light->dirY;
l.Direction.z = light->dirZ;
l.Falloff = light->falloff;
l.Phi = light->phi;
l.Position.x = light->posX;
l.Position.y = light->posY;
l.Position.z = light->posZ;
l.Range = light->range;
l.Specular.a = light->specularA;
l.Specular.r = light->specularR;
l.Specular.g = light->specularG;
l.Specular.b = light->specularB;
l.Theta = light->theta;

if(light->type == LIGHT_POINT) l.Type = D3DLIGHT_POINT;
else if (light->type == LIGHT_SPOT) l.Type = D3DLIGHT_SPOT;
else l.Type = D3DLIGHT_DIRECTIONAL;

m_Device->SetLight(index, &l);
m_Device->LightEnable(index, TRUE);
}

// 关闭光源
void CD3DRenderer::DisableLight(int index)
{
if(!m_Device) return;

m_Device->LightEnable(index, FALSE);
}


  

还需要在“defines.h”头文件里加入这几行代码:

// Light type defines.
// 光源类型
#define LIGHT_POINT 1      // 点光源
#define LIGHT_DIRECTIONAL 2  // 方向光
#define LIGHT_SPOT 3      // 聚光灯


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: