谈到光照,涉及到的内容就包括光照模型和光源类型。
一、首先说一下光照模型。
由于现在的计算机的计算能力有限,无法真正实时实现现实中复杂的光照效果,所以在模拟现实光照时,我们不得不简化光照计算,经过对现实光照进行分类,最终抽象出4个光照模型,分别是:环境光、漫反射、镜面反射、自发光。
1、环境光
环境光就是场景中物体表面产生的反射光的统一光照,环境光没有位置和方向,并且值为常量。
在D3D中设置环境光的方式如下:
1 2 3 |
pDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(100, 100, 100)); |
2、漫反射
漫反射是自然界中最普遍的光照现象,它由光照方向以及顶点法向量计算得到,每个顶点的漫反射光颜色都要单独计算,所以漫反射计算比较耗时,但是这种牺牲时值得的,这能体现物体的三维深度。
3、镜面反射
顾名思义,就是发生在镜面上的光反射现象,这里的镜面就是光滑的物体表面,镜面反射的计算量比漫反射计算量还要大得多,所以在D3D中镜面反射是默认关闭的,设置它的开关状态的方法如下:
1 2 3 |
pDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE); |
4、自发光
自发光就是物体自己发出的光,这是通过对物体材质Emissive属性设置来实现的,自发光不会影响到其他物体。
二、光源
光源类型包括:方向光、点光源、聚光灯。
这些光源类型被定义在枚举类型D3DLIGHTTYPE中,定义如下:
1 2 3 4 5 6 7 8 9 |
Typedef enum _D3DLIGHTTYPE { D3DLIGHT_POINT=1,//点光源 D3DLIGHT_SPOT=2,//聚光灯 D3DLIGHT_DIRECTIONAL=3,//方向光 D3DLIGHT_FORCE_DWORD=0x7fffffff } D3DLIGHTTYPE; |
1、点光源
点光源具有颜色与位置属性,没有方向。光照强度会随着距光源中心的距离变大衰减。在具体应用中,可以利用点光源来模拟电灯或精灵。在D3D中设置点光源的方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_POINT; light.Position = D3DXVECTOR3(1, 1, 1); light.Range = 10.0f; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; light.Attenuation0 = 1.0f;//恒定变化 pDevice->SetLight(0, &light); |
2、聚光灯
聚光灯具有颜色、方向和位置。聚光灯由内锥与外锥组成,光照强度由内锥到外锥逐渐衰减。在应用中可以模拟探照灯。由于聚光灯计算量比较大,所以尽量少使用。D3D中设置光源方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_SPOT; light.Position = D3DXVECTOR3(0, 0, 0); light.Direction = D3DXVECTOR3(1, 1, 1); light.Range = 100.0f; light.Diffuse.r = light.Ambient.r = 0.5f; light.Diffuse.g = light.Ambient.g = 0.5f; light.Diffuse.b = light.Ambient.b = 0.5f; light.Phi = D3DX_PI / 4.0; light.Theta = D3DX_PI / 8.0f; light.Falloff = 1.0f; pDevice->SetLight(1, &light); |
3、方向光
方向光具有颜色、方向属性,没有位置。方向光不存在范围,所以,计算量在所以光源中最小。在应用中可以模拟太阳光。在D3D中设置光源的方式如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
D3DLIGHT9 light; ZeroMemory(&light, sizeof(light)); light.Type = D3DLIGHT_DIRECTIONAL; light.Diffuse.r = 1.0f; light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; D3DXVECTOR3 dir; Dir = D3DXVECTOR3(-1, -1, -1); D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &dir); pDevice->SetLight(2, &light); |
这些就是光照的内容,下面来说一下材质。
在光照的计算中,光照和材质是必需的,缺一不可。那什么是材质呢?
材质就是物体的质地,在D3D中的就是物体对光的吸收与反射特性。
在D3D中结构体D3DMATERIAL9表示材质信息,其定义如下:
1 2 3 4 5 6 7 8 9 10 |
Typedef struct D3DMATERIAL9 { D3DCOLORVALUE Diffuse; D3DCOLORVALUE Ambient; D3DCOLORVALUE Specular; D3DCOLORVALUE Emissive; Float Power; } D3DMATERIAL9, *LPD3DMATERIAL9; |
其中的成员变量Diffuse、Ambient、Specular分别表示物体表面的漫反射光、环境光、镜面反射光的反射系数,Emissive表示物体的自身发光度,Power表示镜面反射指数。
如果用Id、Ia、Is、Ie分别表示漫反射光、环境光、镜面反射光和自发光的亮度,那么物体顶点最终的颜色亮度为:
It = Id + Ia + Is + Ie;
1 2 3 |
HRESULT SetMaterial(CONST D3DMATERIAL *pMatrial); |
函数用来设置当前材质。
下面举例来说明物体材质的设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
D3DMATERIAL9 mtl; ZeroMemory(&mtl, sizeof(mtl)); //漫反射光 mtl.Diffuse.r = 0.5f; mtl.Diffuse.g = 0.5f; mtl.Diffuse.b = 0.5f; mtl.Diffuse.a = 1.0f; //环境光 mtl.Ambient.r = 0.2f; mtl.Ambient.g = 0.4f; mtl.Ambient.b = 0.8f; mtl.Ambient.a = 1.0f; //镜面反射光 mtl.Specular.r = 1.0f; mtl.Specular.g = 1.0f; mtl.Specular.b = 1.0f; mtl.Specular.a = 1.0f; mtl.Power = 25.0f; //自发光 mtl.Emissive.r = 0.3f; mtl.Emissive.g = 1.0f; mtl.Emissive.b = 0.6f; mtl.Emissive.a = 1.0f; gDevice->SetMaterial(&mtl); gDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE); |
好,这一讲就到这里,回头看一下,离上次更新已经快一个世纪了(汗颜,不过确实最近忙得要死),不过同样还是希望大家,编程愉快。ZXGoto与大家一起学习进步。
下面的例子是在上一篇中的太阳系项目基础上改的,运行效果如图:
源码下载地址:https://skydrive.live.com/redir?resid=7BABF310621296C8!422&authkey=!ABzYQT7jeobhRZw
- 本文固定链接: https://www.xuanyusong.com/archives/1721
- 转载请注明: ZXGoto 于 雨松MOMO程序研究院 发表
晓哥多注意下身体,小伙子,你要考虑下一代!哈哈…
支持角角!!
路过,希望博客也回访