现在的位置: 首页 > 综合 > 正文

游戏开发基础(五)

2013年10月01日 ⁄ 综合 ⁄ 共 3603字 ⁄ 字号 评论关闭

 

第五章
光照时,无需自行指定顶点的颜色值;Direct3D会将顶点送入光照计算引擎,依据光源类型,材质以及物体表面相对于光源的朝向,计算出每个顶点的颜色值。基于某种关照模型计算出个顶点的颜色,会使绘制结果更加逼真
环境光:这种类型的光经其他表面反射到达物体表面,并照亮整个场景
满射光:这种类型光沿着特定的方向传播,当它到达某一表面时,将沿着各个方向均匀反射,采用该模型时,无需考虑观察者的位置,这样,漫射光方程中,仅需考虑光传播的方向以及表面的朝向,从一个点光源发出的光一般都是这种类型的。
镜面光这种类型的光沿着特定方向传播,当此类光到达一个表面时,将严格地沿着另一个方向反射,从而形成只能在一定角度范围内才能观察到的高亮照射,因为在这种模型中,光线均沿同一个方向反射,所以在镜面光照方程中,不仅需要考虑光线的入射方向和图元的表面朝向,而且还需要考虑观察点的位置。镜面光可用于模拟物体上的高光点
如果想启用镜面光,必须将绘制状态D3DRS_SPECULARENABLE设为true
Device->SetRenderState(D3DRS_SPECULARENABLE,true)
每种类型的光都可用结构D3DCOLORVALUE或D3DXCOLOR来表示,这些类型描述了光线的颜色
描述光线的颜色时,D3DXCOLOR类中的Alpha值都将被忽略
例:D3DXCOLOR redAmbient(1.0f,0.0f,0.0f,1.0f);

物体的颜色是由该物体所反射的光的颜色决定的,Direct3D通过定义物体的材质来模拟同样的现象,材质允许定义的物体表面对各种颜色光的反射比例
材质用的结构D3DMATERIAL9
typedef struct D3DMATERIAL9{
 D3DCOLORVALUE Diffuse;//材质对漫射光的反射率
 D3DCOLORVALUE Ambient; //材质对环境光的反射率
 D3DCOLORVALUE Specular; //材质对镜面光的反射率
 D3DCOLORVALUE Emissive; //该分量用于增强物体的亮度,使之看起来好像可以自己发光
 float Power;//指定镜面高光点的锐度,该值越大,高光点的锐度越大
}D3DMATERIAL9,*LPD3DMATERIAL9;

例:一个红色球体,让该球的材质的属性定义为只反射红色光,而吸收所有其他颜色的光。
D3DMATERIAL9 red;
::ZeroMemory(&red,sizeof(red));
red.Diffuse  = D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
red.Ambient  = D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
red.Specular = D3DXCOLOR(1.0f,0.0f,0.0f,1.0f);
red.Emissive = D3DXCOLOR(0.0f,0.0f,0.0f,1.0f);
red.Power = 5.0f;
这里,我们将绿色和蓝色分量设为0,表明该材质对这些颜色的光的反射率为0%,将红色分量设为1.表明该材质对红色光的反射率为100%,注意,我们可以控制材质在各种类型光(环境光,漫射光和镜面光)照射下哪种颜色的光将被反射。

顶点结构中不含有材质属性,但我们必须对当前材质进行设定
IDirect3DDevice9::SetMaterial(CONST D3DMATERIAL9* pMaterial)

要绘制不同材质的物体:
D3DMATERIAL9 buleMaterial,redMaterial;
Deivce->SetMaterial(&buleMaterial)
drawSphere()
Deivce->SetMaterial(&redMaterial)
drawSphere()

面法线是描述多边形朝向的向量
顶点法线描述的是构成多边形的各个顶点的法线
Direct3D需要知道顶点的法线方向,以确定光线到达表面时的入射角,而且,由于光照计算是对每个顶点进行的,所以Direct3D需要知道表面在每个顶点处的局部朝向(法线方向),顶点法线与表面法线不一定相同

描述一个顶点法线
struct Vertex{
 float x,y,z;
 float _nx,_ny,_nz;
 static const DWORD FVF ;
};

const DWORD Vertex::FVF = D3DFVF_XYZ |D3DFVF_NORMAL;

例:用于计算一个由3个顶点构成的三角形所在面的法向量,顶点指定为顺时针绕序
void ComputeNormal(D3DXVECTOR3* p0,D3DXVECTOR3* p1,D3DXVECTOR3* p2,D3DXVECTOR3* out)
{
 D3DXVECTOR3 u = *p1 - *p0;
 D3DXVECTOR3 v = *p2 - *p0;

 D3DXVec3Cross(out,&u,&v);
 D3DXVec3Normalize(out,out);
}

当用三角形单元逼近表示曲面时,将面片法向量作为构成该面片的顶点法向量不可能产生很平滑的效果
一种更好的求取顶点法向量的方法是计算法向量均值。求出共享顶点v的所有三角形的面法向量。则vn可由面法向量取均值得到,假定有3个三角形单元共享顶点v,其面法向量分别是n0,n1和n2,则vn的计算方法为:v = (n0+n1+n2)/3,在变换过程中,顶点法线有可能不再是规范化的,所以,最好的方法是,在变换完成之后,通过使能D3DRS_NORMALIZENORMALS绘制状态使所有的法向量重新规范化。
Device->SetRenderState(D3DRS_NORMALIZENORMALS,true);

Direct3D支持3种类型的光源
*点光源,该光源在世界坐标系中有固定的位置,并向所有的方向发射光线
*方向光,该光源没有位置信息,所发射的光线相互平行地沿某一特定方向传播
*聚光灯,该光源有位置信息,其发射的光线呈锥形沿着特定方向传播,该锥形有两个角度,内部锥形,外部锥形

光源用结构D3DLIGHT9来表示
typedef struct  D3DLIGHT9{
 D3DLIGHTTYPE Type;//光源类型,D3DLIGHT_POINT,D3DLIGHT_SPOT,D3DLIGHT_DIRECTIONAL
 D3DCOLORVALUE Diffuse;//漫射光的颜色
 D3DCOLORVALUE Specular;//镜面光的颜色
 D3DCOLORVALUE Ambient;//环境光的颜色
 D3DVECTOR     Position;//光源在世界坐标系中位置的向量,对于方向光,该参数无意义
 D3DVECTOR     Direction;//一个描述光在世界坐标系中传播方向的向量,对于点光源,该参数无意义
 float        Range;// 光线"消亡"前,所能达到的最大光程,该值的最大取值为FLT_MAX开方,对于方向光,无意义
 float         Falloff;//该值仅用于聚光灯,该参数定义了光强从内锥形到外锥形的衰减方式一般取1.0f
 float        Attenuation0;//Attenuation0,Attenuation1,Attenuation2衰减变量定义了光强随距离衰减方式,仅对点光源和聚光灯有效,分别表示光常量,线性,2次距离衰减系数衰减公式为,a = 1/(A0+A1*D+A2*D*D),D为光源到顶点的距离,A0,A1,A2分别对应于Attenuation0,Attenuation1,Attenuation2
 float        Attenuation1;
 float        Attenuation2; 
 float         Theta;//仅用于聚光灯,指定了内部锥形的圆锥角,单位弧度
 float         Phi;//仅用于聚光灯,指定了外部锥形的圆锥角,单位弧度
}D3DLIGHT9,*LPD3DLIGHT9;

例:创建一个传播方向平行于x轴的方向光光源。
 D3DXVECTOR3 dir(1.0f,0.0f,0.0f);
 D3DXCOLOR c = d3d::WHITE;
 D3DLIGHT9 dirLight = d3d::InitDirectionalLight(&dir,&c);
创建后,需要在Direct3D所维护的一个光源内部列表中对所要使用的光源进行注册
 Device->SetLight(0,&light);
一旦光源注册成功,我们就可对其开关状态进行控制
 Device ->LightEnable(0,true);

为一个场景添加光照步骤:
*启用光照
*为每个物体创建一种材质,并在绘制相应物体前应用该材质
*创建一种或多种光源,设置并开启
*启用所有其余的光照状态,如镜面高光

抱歉!评论已关闭.