ImageVerifierCode 换一换
格式:DOCX , 页数:42 ,大小:804.25KB ,
资源ID:5866568      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/5866568.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(VC++游戏开发随记之四十.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

VC++游戏开发随记之四十.docx

1、VC+游戏开发随记之四十【Visual C+】游戏开发笔记四十 浅墨DirectX教程之八 绘制真实质感的三维世界:光照与材质专场本篇文章里,我们对Direct3D之中固定功能流水线中的3D光照编程相关的知识进行了详尽的剖析,文章末尾依旧是提供文章配套的详细注释的demo源代码的欣赏,并在文章末尾提供了源代码下载。一、引言光,乃万物之源。我们根本无法想象,这个美丽怡人的世界,如果没有光的陪伴,会是怎样的一副满目疮痍。计算机3D世界作为现实世界的高度逼真的模仿,必然也少不了光的陪伴。回到我们的Direct3D应用程序中来,在Direct3D中运用光照,能有效地增强3D场景的真实感。在3D场景中使

2、用光照其实非常地简单,我们不需要为物体的每个顶点都去指定颜色值,只要我们告诉Direct3D我们使用的是什么类型的光照,我们的物体的材质的具体参数以及物体表面相对于光源的朝向,Direct3D就会根据其内置的算法计算出每个顶点的颜色值,产生出逼真的光照效果。当然随着我们学习的深入,功力的加深,就可以不单单依赖于Direct3D中内建的光照算法,可以根据各种功能的着色器的编写,自己写出更加优化更加逼真的光照效果来。作为目前刚刚接触到Direct3D中的光照和材质这一块内容,我们还是老老实实地先把固定功能流水线中的这一套非常好学好掌握的光照与材质的体系系统地进行讲解,先把基础打牢,先把走学会,这样

3、才能为后面我们的腾飞做铺垫。说到一套完整的光照体系,有两对组成方面,第一,光照,第二,材质。这两者天生就是一对好搭档,我们可以把它们看做光照计算的两要素,想要绘制出具有光照的真实三维世界,两者缺一不可。下面就开始正式讲解,首先我们来看看四大光照类型:二、四大光照类型1.环境光(Ambient Light)一个物体即使没有直接被光源照射,但是只要有光线通过其他物体的折射、反射到达物体,它也可能被看见。这种基于整个自然界环境的整体亮度,称为环境光(Ambient Light)或者背景光。环境光没有位置或者方向上的特征,只有一个颜色亮度值,而且不会衰减,所以在所有方向和所有物体表面上投射的环境光的数

4、量是恒定不变的。想要以较低的代价和开销来近似模拟光照的话,直接开启环境光是一个不错的选择。在Direct3D中环境光的设置非常简单,也就是用一下SetRenderState,代码如下:cppview plaincopyprint?1. pd3dDevice-SetRenderState(D3DRS_AMBIENT,D3DCOLOR_XRGB(36,36,36);/设置一下环境光其中第一个参数填D3DRS_AMBIENT,代表环境光的设置,而第二个参数填一个颜色值就可以了。2.漫反射光(DiffuseLight)漫反射光在我们的生活中最为普遍,太阳的直射,日光灯的照射都可以看成漫反射的近似。这种

5、类型的光沿着特定的方向传播。当它到达某一表面时,将沿着各个方向均匀反射,所以我们无论从哪个方向观察,物体表面的亮度都是相同的,所以采用漫反射这种光照模型时,无需考虑观察者的位置,但是需要考虑漫反射光的空间位置和方向。从一个光源发出的光一般都是这种类型的。漫反射光并没有简洁的设置方法,具体下文会讲到的,请大家继续往下看。3.镜面反射光(SpecularLight)镜面反射光,顾名思义,沿着特定的方向传播,当此类光到达一个表面时,将严格地沿着另一个方向反射,从而形成只能在一个角度范围内才能观察到的高亮度照射。这种光照模型模拟了从光滑发光面如镜子、一块金属或者一块发光塑料等材料来进行光线反射的情形。

6、如果我们移动一下光源的话,就会发现镜面亮光区所发生的变化,这意味着镜面反射取决于观察者的角度。我们可以这样来归纳,漫反射与视觉无关,而镜面反射与视觉相关。需要注意的是,镜面光与其他类型的光相比,计算量要大得多,Direct3D默认情况是把镜面反射关起来的。如果我们想启用镜面反射的话,用下面的代码,即把渲染状态D3DRS_SPECULARENABLE设为true:cppview plaincopyprint?1. pd3dDevice-SetRenderState(D3DRS_SPECULARENABLE,true);4.自发光自发光就是对象自己发出的光,其实他是根据通过对象的自发光材质实现的,

7、下面我们在讲解材质时讲到的D3DMATERIAL9结构体,这个结构体的成员Emissive描述自发光的颜色和透明度。自发光影响着一个对象的颜色,比如我们可以通过设置自发光的颜色属性,把一些灰暗的材质变得明亮一些。需要提出来的是,我们可以使用材质的自发光属性来“照亮”这个对象,而不用在场景中内部添加灯光,从而缩小了计算量。自发光属性创建的材质并不发射出能被场景内其他对象反射的光,也就是说,它发出的光并不参与光运算,而为了实现反射光,需要在场景中添加额外的灯光。讲解完四大光照类型,接下来当然少不了三大光源类型。三、三大光源类型在Direct3D中的光源类型和光照类型是两个完全不同的概念,光照模型描

8、述的是光线的反射特征,而光源类型主要强调的是能够产生这些光照模型的方式以及光线的位置、方向、强度等特征。Direct3D中主要有3种类型的的光源,我们把他们合称为三大光源:点光源(Point Light)、方向光(Directional Light)和聚光灯(Spot Light)。而在Direct3D 9.0c中,讲到光源,必须讲到一个结构体,那就是D3DLIGHT9结构体,在展开讲解各中光源类型之前,先让我们看看这个结构体的具体内容,我们可以在MSDN中查到这个结构体有如下原型:cppview plaincopyprint?1. typedefstructD3DLIGHT92. D3DLI

9、GHTTYPEType;3. D3DCOLORVALUEDiffuse;4. D3DCOLORVALUESpecular;5. D3DCOLORVALUEAmbient;6. D3DVECTORPosition;7. D3DVECTORDirection;8. floatRange;9. floatFalloff;10. floatAttenuation0;11. floatAttenuation1;12. floatAttenuation2;13. floatTheta;14. floatPhi;15. D3DLIGHT9,*LPD3DLIGHT; 第一个参数,D3DLIGHTTYPE类型的

10、Type,表示光源的类型,在D3DLIGHTTYPE这个枚举体中取值,而D3DLIGHTTYPE枚举体有如下定义:cppview plaincopyprint?1. typedefenumD3DLIGHTTYPE2. D3DLIGHT_POINT=1,3. D3DLIGHT_SPOT=2,4. D3DLIGHT_DIRECTIONAL=3,5. D3DLIGHT_FORCE_DWORD=0x7fffffff6. D3DLIGHTTYPE,*LPD3DLIGHTTYPE;我们可以由英语单词很容易理解到,D3DLIGHT_POINT为点光源类型,D3DLIGHT_SPOT为聚光灯类型,D3DLIG

11、HT_DIRECTIONAL为方向光源类型,而最后一个参数依然是前面我们几次提到的没有存在感的那个,我们不用去纠结它。 第二个参数到第四个参数是一个类型的,我们结合起来讲解。这三个参数都为D3DCOLORVALUE类型的颜色值,而参数名分别为Diffuse,Specular,Ambient,分别表示我们这个光源的漫反射,镜面反射和环境光的颜色值。 第五个参数,D3DVECTOR类型的Position,表示光源的位置。 第六个参数,D3DVECTOR类型的Direction,表示光源的光照方向。 第七个参数,float类型的Range,表示光源的光照范围,只在某些光源类型中有意义。 第八个参数以

12、及第十二,第十三个参数又是一个类型的,我们依然一起来介绍。也就是同为float类型的Falloff,Theta以及Phi,这三个参数都是用在聚光灯光源类型中的,也就是说只有我们把D3DLIGHT9的第一个参数Type设为D3DLIGHT_SPOT聚光灯类型的时候,这三个参数才有意义。第九、第十、第十一这三个参数显然也是同一阵营的,我们也一起介绍,Attenuation0 Attenuation2都为衰减系数,定义了光强随着距离衰减的方式,衰减公式如下:其中,D为光源到顶点的距离,A0A2分别对应于Attenuation0 Attenuation2。讲解完成,下面我们看看具体怎么使用。在Dire

13、ct3D中使用光照的话,也就是用我们这个D3DLIGHT9结构体实例化一个具体的光源类型,然后无脑地进行喜闻乐见的填空题操作,对这个结构体的参数进行赋值,赋值完成后调用IDirect3DDevice9接口的SetLight方法设置光源,然后调用IDirect3DDevice9接口的LightEnable方法启用光照就可以了。下面我们来分别看看这两个方法。首先是SetLight,SetLight方法用于设置光源:cppview plaincopyprint?1. HRESULTSetLight(2. inDWORDIndex,3. inconstD3DLIGHT9*pLight4. ); 第一个

14、参数,DWORD类型的Index,取值于0到7之间,表示选择第1到8个光源。 第二个参数,const D3DLIGHT9类型的*pLight,显然就是指向D3DLIGHT9结构体的指针,包含设置好的灯光类型,我们在使用的时候,在这里就填我们之前实例化的D3DLIGHT9结构体的名称,并在名称之前加一个“&”取地址符号就可以了。然后是LightEnable方法,LightEnable方法用于启用光照:cppview plaincopyprint?1. HRESULTLightEnable(2. inDWORDLightIndex,3. inBOOLbEnable4. ); 第一个参数,DWORD

15、类型的Index,取值于0到7之间,表示选择第1到8个光源。 第二个参数,BOOL类型的bEnable,填true或者flase表示启用或者禁用第一个参数里面指定的光照。讲解完需要用到的一个结构体和两个方法,下面我们就来进入三大光源的讲解。1.点光源点光源(Point Light)具有颜色和位置,但没有方向,它向所有方向发射的光都一样。它是一个从中心向空间中各个方向发射相等强度光线的光源,且光的亮度会不随着距离而衰减。要定义一个点光源的话,实例化一个D3DLIGHT9结构体,将第一个参数设为D3DLIGHT_POINT然后进行其余参数的设置即可,这样实例化出的这个结构体就是一个点光源了。下面我

16、们看一个点光源设置的实例:cppview plaincopyprint?1. D3DLIGHT9light;2. :ZeroMemory(&light,sizeof(light);3. light.Type=D3DLIGHT_POINT;/点光源4. light.Ambient=D3DXCOLOR(0.8f,0.8f,0.8f,1.0f);5. light.Diffuse=D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);6. light.Specular=D3DXCOLOR(0.3f,0.3f,0.3f,1.0f);7. light.Position=D3DXVECTOR3(0.

17、0f,200.0f,0.0f);8. light.Attenuation0=1.0f;9. light.Attenuation1=0.0f;10. light.Attenuation2=0.0f;11. light.Range=300.0f;12. pd3dDevice-SetLight(0,&light);/设置光源13. pd3dDevice-LightEnable(0,true);/启用光照上面的这段代码非常好理解,首先实例化一个D3DLIGHT9结构体,然后先把这个结构体用ZeroMemory置零,接着开始做填空题填充这个D3DLIGHT9结构体,因为这里是点光源,所以Light.Ty

18、pe这个参数需要为D3DLIGHT_POINT,表示点光源。设置完之后,接着用SetLight设置光源,用LightEnable启用光照。2.方向光源方向光源是从无穷远处发出的一组平行、均匀的光线,在场景中以相同的方向传播,只具有颜色和方向,不受到衰减和范围的影响。同样地,要定义一个方向光源的话,实例化一个D3DLIGHT9结构体,将第一个参数设为D3DLIGHT_DIRECTIONAL然后进行其余参数的设置即可,这样实例化出的这个结构体就是一个方向光源了。下面我们看一个方向光源设置的实例:cppview plaincopyprint?1. D3DLIGHT9light;2. :ZeroMem

19、ory(&light,sizeof(light);3. light.Type=D3DLIGHT_DIRECTIONAL;/方向光源4. light.Ambient=D3DXCOLOR(0.5f,0.5f,0.5f,1.0f);5. light.Diffuse=D3DXCOLOR(1.0f,1.0f,1.0f,1.0f);6. light.Specular=D3DXCOLOR(0.3f,0.3f,0.3f,1.0f);7. light.Direction=D3DXVECTOR3(1.0f,0.0f,0.0f);8. pd3dDevice-SetLight(0,&light);/设置光源9. pd

20、3dDevice-LightEnable(0,true);/启用光照3.聚光灯光源这里的聚光灯光源,就是我们在演唱会时看到的那样的聚光灯,也如我们生活中的探照灯。聚光灯发出的光由一个明亮的内椎体(inner cone)和大一点的外椎体(outer cone)组成。显然内锥体中的光是最亮的,内锥体到外椎体外围的光强逐渐衰减,到了外椎体以外,已经衰减得没有光了。上面我们讲到,光线强度从内锥体到外锥体逐渐衰减,是通过聚光灯的Falloff、Theta、和Phi这三个属性共同来控制其衰减规律。下图显示了这Phi和Theta参数之间的关系和他们如何影响着一个聚光灯的内外锥体的:而Falloff用于控制光

21、强如何从内锥体的外侧向外锥体的内侧减弱的,通常我们将其设为1.0f,来让光线在两个圆锥间平滑地减弱。下图清晰地显示了Falloff参数是如何来取决内锥体和外锥体之间的光强变化的。因为聚光灯受到衰减规律和光照范围的影响,场景中的每个顶点在计算光照时,都要考虑这些因素,这使得聚光灯成为在Direct3D中首屈一指的高开销光源,因此我们要谨慎使用聚光灯。同样地,要定义一个聚光灯光源的话,实例化一个D3DLIGHT9结构体,将第一个参数设为D3DLIGHT_SPOT然后进行其余参数的设置即可,这样实例化出的这个结构体就是一个聚光灯光源了。讲完聚光灯的概念,依然是一个设置聚光灯光源的实例:cppview

22、 plaincopyprint?1. D3DLIGHT9light;2. :ZeroMemory(&light,sizeof(light);3. light.Type=D3DLIGHT_SPOT;/聚光灯光源4. light.Position=D3DXVECTOR3(100.0f,100.0f,100.0f);5. light.Direction=D3DXVECTOR3(-1.0f,-1.0f,-1.0f);6. light.Ambient=D3DXCOLOR(0.3f,0.3f,0.3f,1.0f);7. light.Diffuse=D3DXCOLOR(1.0f,1.0f,1.0f,1.0f

23、);8. light.Specular=D3DXCOLOR(0.3f,0.3f,0.3f,0.3f);9. light.Attenuation0=1.0f;10. light.Attenuation1=0.0f;11. light.Attenuation2=0.0f;12. light.Range=300.0f;13. light.Falloff=0.1f;14. light.Phi=D3DX_PI/3.0f;15. light.Theta=D3DX_PI/6.0f;16. pd3dDevice-SetLight(0,&light);/设置光源17. pd3dDevice-LightEnabl

24、e(0,true);/启用光照四、材质对于光照计算,光照和材质两者缺一不可。物体表面的材质属性决定了它能反射什么颜色的光线以及能反射多少,而在Direct3D中,关于物体表面的材质属性,由一个结构体D3DMATERIAL9来负责管理。我们可以在MSDN中查到这个结构体有如下原型:cppview plaincopyprint?1. typedefstructD3DMATERIAL92. D3DCOLORVALUEDiffuse;3. D3DCOLORVALUEAmbient;4. D3DCOLORVALUESpecular;5. D3DCOLORVALUEEmissive;6. floatPow

25、er;7. D3DMATERIAL9,*LPD3DMATERIAL9; 第一个参数,D3DCOLORVALUE类型的Diffuse,表示物体表面对漫反射光的反射率,我们可以发现这个参数类型为D3DCOLORVALUE,也就是Direct3D中的颜色类型。我们可以用像D3DXCOLOR(A ,R, G, B)这样的句式来表示某种颜色,其中A ,R, G, B分别表示0.0f到1.0f之间的红色,绿色,蓝色,透明色的分量值,比如这样写:D3DXCOLOR(0.5f, 0.5f, 0.7f, 1.0f)。 第二个参数,D3DCOLORVALUE类型的Ambient,表示物体表面对环境光的反射率,填一

26、个颜色值。 第三个参数,D3DCOLORVALUE类型的Specular,表示物体表面对镜面反射光的反射率,同样是填一个颜色值 第四个参数,D3DCOLORVALUE类型的Emissive,表示物体的自发光颜色值,同样是填一个颜色值。 第五个参数,float类型的Power,表示镜面反射指数,他的值越大,高光强度和周围亮度相差就越大。我们还需要知道,物体的顶点颜色的亮度总和有一个公式:其中等式左边的I total表示物体最终的颜色值,通过这个式子我们可以知道,物体的颜色总和=物体反射环境光+物体反射漫反射光+物体反射镜面反射光+自发光。也就是说,物体的最终颜色值由D3DMATERIAL9结构体

27、中设置的四种颜色值共同决定。在做完填空题,设置好我们的材质属性后,就需要调用一个SetMaterial方法来设置我们当前使用的材质属性,我们可以在MSDN中查到这个参数有如下原型:cppview plaincopyprint?1. HRESULTSetMaterial(2. inconstD3DMATERIAL9*pMaterial3. );这个方法唯一的一个参数就是指向D3DMATERIAL9结构体的指针,我们在使用的时候要记得在前面加上一个“&”取地址符号。讲解完相关概念,下面我们依然是看一个设置材质的实例:cppview plaincopyprint?1. /设置材质2. D3DMATE

28、RIAL9mtrl;3. :ZeroMemory(&mtrl,sizeof(mtrl);4. mtrl.Ambient=D3DXCOLOR(0.5f,0.5f,0.7f,1.0f);5. mtrl.Diffuse=D3DXCOLOR(0.6f,0.6f,0.6f,1.0f);6. mtrl.Specular=D3DXCOLOR(0.3f,0.3f,0.3f,0.3f);7. mtrl.Emissive=D3DXCOLOR(0.0f,0.0f,0.0f,1.0f);8. g_pd3dDevice-SetMaterial(&mtrl);另外需要注意,我们如果没有在程序中用代码来指定材质属性的话,Direct3D有自己的一套默认材质,默认材质反射所有

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1