光照与材质
一、光照模型:
1、环境光:环境光没有位置和方向,它是光线经过多次散射后所形成的光。所有的光线都均匀地从各个方向照射到物体上,并且照亮场景中的所有物体。环境光只有一个颜色值,而且不会衰减,所以在所有方向和所有物体表面上投射的环境光的数量是恒定不变的。
环境光是完全独立于场景中的任何发光物体的光照模型,所以环境光模型也被称作全局光照模型。在Direct3D应用程序中,可以调用IDirect3DDevice接口的SetRenderState方法设置场景中的环境光。例如: // 设置灰色的环境光
g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(222, 222, 222) );
2、漫反射光:漫反射光在生活中最为普遍,太阳的直射、日光灯的照射都可以看成漫反射的近似。漫反射不同于环境光,漫反射光的空间位置和方向对物体的照明有很大影响。但与观察者位置无关,因此在漫反射光照模型中一个物体的表面在所有方向上的反射都是一样的,如图4.1所示。
3、镜面反射光:镜面反射发生在光滑物体(如金属物品、玻璃制品等)的表面,当光线照射到这类物体表面时产生的高光反射,并且当观察者移动自己所处的位置,反射的亮度也不一样,观察方向与反射光线越靠拢,发射光的强大就越大,如图4.2所示。
由于镜面反射的计算量比较大,Direct3D在默认状态下不对物体进行镜面反射计算,可以调
用SetRenderState方法启用镜面反射。例如:
g_pd3dDevice->SetRenderState ( D3DRS_SPECULARENABLE , TRUE );
二、光源类型:
Direct3D提供了三种光源类型:点光源(Point Light)、方向光(Directional Light)和聚光灯(Spot Light)。在Direct3D中,光源类型及其属性由D3DLIGHT9结构表示。该结构体的定义如下:
typedef struct D3DLIGHT9 {
D3DLIGHTTYPE Type; // 光源类型 D3DCOLORVALUE Diffuse; // 漫反射光强度 D3DCOLORVALUE Specular; // 环境光强度 D3DCOLORVALUE Ambient; // 镜面反射光强度 D3DVECTOR Position; // 光源位置 D3DVECTOR Direction; // 光照方向 float Range; // 光照范围 float Attenuation0; // 衰减系数1 float Attenuation1; // 衰减系数2
float Attenuation2; // 衰减系数3 float Falloff; // 聚光灯的辐射系数 float Theta; // 聚光灯的内锥体大小 float Phi; // 聚光灯的外锥体大小 } D3DLIGHT9, *LPD3DLIGHT;
1、点光源是从一个中心点向空间中各个方向发射相等强度光线的光源。点光源具有颜色和位置,但没有确定的方向。点光源向各个方向发出光相,并且光的亮度会随着距离而衰减,如图4.3所示。
为了能够使用点光源,在应用程序中需要提供光源的位置、颜色和衰减系数等参数。例如,下面的代码将创建一个范围为1000.0f,颜色为白色且位于原点的点光源。 D3DLIGHT9 light;
::ZeroMemory( &light, sizeof(light) );
light.Type = D3DLIGHT_POINT; // 点光源 light.Ambient = D3DCOLOR_XRGB(255, 255, 255); // 环境光, 白色 light.Ambient.r= light.Ambient.g= light.Ambient.b=
light.Diffuse = D3DCOLOR_XRGB(255, 255, 255); // 漫反射光, 白色 light.Specular = D3DCOLOR_XRGB(255, 255, 255); // 镜面反射光, 白色 light.Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f); // 点光源位置, 原点 light.Range = 1000.0f; // 光照范围, 1000 light.Attenuation0 = 1.0f; // 衰减系数 实例:
2、方向光是从无穷远处发出的一组平行、均匀的光线,在场景中以相同的方向传播。方向光发出的光只有颜色和方向,并且不会受到衰减和范围的影响,如图4.4所示。
在初始化方向光时,当指定D3DLIGHT9结构类型的变量时,需要指定Type成员为D3DLIGHT_DIRECTION,并制定方向光的光照方向。例如: D3DLIGHT9 light;
::ZeroMemory( &light, sizeof(light) );
light.Type = D3DLIGHT_DIRECTIONAL; // 方向光 light.Ambient = D3DCOLOR_XRGB(255, 255, 255); light.Diffuse = D3DCOLOR_XRGB(255, 255, 255); light.Specular = D3DCOLOR_XRGB(255, 255, 255);
light.Direction = D3DXVECTOR3(1.0f, 0.0f, 1.0f); // 光照方向
3、聚光灯发出圆锥形的光,并且由内锥体和外锥体两部分组成。其中内锥中的光最亮,而外锥以外则没有光,从内锥体到外锥体间光强逐渐衰减,如图4.5所示。
D3DLIGHT9结构体包含了Falloff、Theta和Phi三个成员描述聚光灯。其中,Falloff字段用于控制光强如何从内锥的外侧向外锥的内侧减弱,通常将该字段设为1.0f,以使光在两个圆锥间平滑地减弱。Theta和Phi字段用于控制聚光灯的内、外锥体的大小,分别以弧度表示内、外锥体的角度。
在创建一个聚光灯时,除了指定Falloff、Theta和Phi成员的值外,还需要指定聚光灯的光照范围、方向和衰减系数。例如: D3DLIGHT9 light;
::ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_SPOT; // 聚光灯 //light.Ambient = 0.0f;
light.Diffuse = D3DCOLOR_XRGB(255, 255, 255); light.Specular = D3DCOLOR_XRGB(255, 255, 255);
light.Position = D3DXVECTOR3(-10.0f, 5.0f, -10.0f); // 位置 light.Direction = D3DXVECTOR3(1.0f, 0.0f, 1.0f); // 光照方向 light.Range = 1000.0f; // 光照范围 light.Falloff = 1.0f; // 辐射系数 light.Attenuation0 = 1.0f; // 衰减系数 light.Theta = 0.4f; // 内锥体大小 light.Phi = 0.9f; // 外锥体大小
三、 D3D材质
Direct3D提供D3DMATERIAL9结构用于描述物体的材质,其中包含了反射环境光、漫反射光和镜面反射光的颜色属性。该结构体的定义如下: typedef struct D3DMATERIAL9 {
D3DCOLORVALUE Diffuse; D3DCOLORVALUE Ambient; D3DCOLORVALUE Specular; D3DCOLORVALUE Emissive; float Power;
} D3DMATERIAL9, *LPD3DMATERIAL9; 当初始化D3DMATERIQAL9结构后,可以调用IDirect3DDevice9接口的SetMaterial方法设置材质。例如:
D3DMATERIAL9 mtrl;
ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
mtrl.Diffuse.r = mtrl.Ambient.r = mtrl.Specular.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = mtrl.Specular.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = mtrl.Specular.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = mtrl.Specular.a = 1.0f; g_pd3dDevice->SetMaterial( &mtrl );
完整实例:
绘制四个三角形围成的椎状体:
_D3DVECTOR {x=0.00000000 y=0.70710671 z=-0.70710671 } _D3DVECTOR
+
#include
LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //顶点缓冲区对象 LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; // 索引缓冲区对象