版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第 19 20 课源码第 19 课 粒子系统:你是否希望创建喷射的效果。,喷泉,流星之类的效果。这一课将告诉你如何创建一个简单的例子系统,并用它来创建一种欢迎来到第十九课.你已经学习了很多知识,并且现在想自己来实践.我将在这讲解一个新命令. 三角形带(我的理解就是画很多三角形来组要的形状),它非常容易使用,当画很多三角形的时候能加快你程序的运行速度.在本课中,我将会教你该如何做一个半复杂的微粒程序.一旦您了解微粒程序的原理后,在创建例如:火,烟,喷泉等效果将是很轻松的事情.我必须警告你!直到今天我从未写一个真正的粒子程序.写一个出名的复杂的粒子程序.我尝试过,但在我了解我不能控制所有点变疯狂之
2、后我放弃了!你也许不相信我要告诉你的,但这个课程从头到尾都是的想法.开始我没有一点想法,并且没有任何技术数据放在面前.我开始考虑粒子,突然脑袋装满想法(脑袋开启了?):给予每个粒子生命,任意变化颜色,速度,重力影响等等.来适应环境的变化,把每个粒子看成单一的从这个点运动到另一个点的颗粒.很快我完成了这个项目.我看看时钟然后有个想法突然出现.四个小时过去了!我偶尔记得已经停止喝咖啡,眨眼,但是 4 个小时.?尽管这个程序我觉得很棒,并象的运行,但它不可能是最好的粒子引擎,这个我不关心,只要他运行好就可以.并且我能把它运行在象的那么严密项目中.如果你是那种想了解透彻的人,那么你要花费很多时间在网络
3、上查找资料并弄明白它.在程序中有很多小的代码会看起来很模糊:)本课(使它更容易了解).所用的部分代码来自于Lesson1.但有很多新的代码,因此我将重写一些发生代码变化的部分下面用到的代码来自于Lesson6,我将会增加5 行新的代码在程序的前面.第一行stdio.h允许读文件中的数据.它和以前用在纹理当中是一样的.第二行定义了一些要在屏幕上显示的粒子的数目.告诉程序 MAX_PARTICLES 在这里的数值为 1000.第三条行将不断分离的彩色的粒子栓牢在一起,并设置为默认情况.sp 和 rp 用来确定空格键和返回键是否有按住.#define MAX_PARTICLES 1000/ 定义最大
4、的粒子数bool boolboolrainbow=true;/ 是否为彩虹模式空格键是否被按下回车键是否被按下sp;rp;/下面四行是复杂的变量.变量 slowdown 控制粒子移动的快慢.数值愈高,移动越慢.数值越底,移动越快.如果数值降低,粒子将快速的移动!粒子的速度影响它们在荧屏中移动的距离.记住速度慢的粒子不会射很远的.变量xspeed和 yspeed 控制尾部的方向.xspeed 将会增加粒子在x 轴上速度.如果 xspeed 是正值粒子将会向右边移动多.如果 xspeed 负价值,粒子将会向左边移动多.那个值越高,就向那个方向移动比较多.yspeed 工作相同的方法,但是在y 轴上
5、.因为有其它的影响粒子的运动,所以我多.xspeed 和 yspeed 有助于在想要的方向上移动粒子.最的图象,而且当接近你时很后是变量 zoom,酷用该变量移入或移出的屏幕.在粒子引擎里,有时可看见float float floatfloatslowdown=2.0f; xspeed; yspeed;zoom=-40.0f;/粒子/X 方向的速度/ Y 方向的速度/ 沿Z 轴缩放定义了一个复杂的循环变量叫做Loop.用这变量预先定义粒子并在屏幕中画粒子.col 用来给予粒子不同的颜色.delay 用来控制在彩虹模式中圆的颜色变化.最后,设定一个空间(粒子纹理).我用纹理而不用点的重要原因是,
6、点的速度慢,而且挺麻烦的.其次纹理很酷:)你用一个正方形的粒子,一张你脸的小片等等.很好控制!,一张星星的图GLu GLuGLuloop; col;delay;/ 循环变量/ 当前的颜色/ 彩虹效果延迟好!现在是有趣的东西.下描述单一粒子结构,这是给予粒子的属性.用型变量 active 开始,如果为 true,的粒子为活跃的.如果为 false 则粒子为死的,此时就删除它.在程序中我没有使用活跃的,因为它很好的实现.变量 life 和fade 来控制粒子显示多久以及显示时候的亮度.随着 life 数值的降低fade 的数值也相应降低.这将导致一些粒子比其他粒子燃烧的时间长.typedef st
7、ructbool active;/ 创建粒子数据结构/ 是否激活/ 粒子生命floife;float fade;/ 衰度变量 r,g 和b 用来表示粒子的红色强度,绿色强度和蓝色强度.当r 的值变成 1.0f 时粒子将会很红,当三个变量全为 1.0f 时则粒子将变成白色.floatfloat floatr;g;b;/红色值绿色值蓝色值变量x.y 和z 控制粒子在屏幕上显示的位置.x 表示粒子在x 轴上的位置.y 表示y 轴上的位置.z 表示粒子z 轴上的位置float floatfloatx;y;z;/X YZ位置位置位置下面三个变量很重要.这三个变量控制粒子在每个轴上移动的快慢和方向.如果
8、xi 是负价粒子将会向左移动,正值将会向右移动.如果 yi 是负值粒子将会向下移动,正值将向上.最后,如果 zi 负值粒子将会向荧屏移向观察者.移动,正植将float floatfloatxi;yi;zi;/X YZ方向方向方向最后,另外 3 个变量!每一个变量可被看成加速度.如果 xg 正值时,粒子将会被拉倒右边,负值将拉向左边.所以如果粒子向左移动(负的)而上.zg 拉进或拉出屏幕.给它一个正的加速度,粒子速度将变慢.最后将向反方向移动(高中物理).yg 拉下或拉float floatfloatxg;yg;zg;/X YZ方向重力加速度方向重力加速度方向重力加速度结构的名字为particl
9、es.particles;/ 粒子数据结构下面粒子,创建一个数组叫 particle.数组空间为每个粒子提供相应的信息MAX_PARTICLES 个元素.也就是说创建 1000(MAX_PARTICLES)个particles particleMAX_PARTICLES;/ 保存 1000 个粒子的数组在颜色数组上减少一些代码来12 中不同的颜色.对每一个颜色从 0 到 11亮红,亮绿,和亮蓝.下面的颜色表里包含 12 个渐变颜色从红色到紫罗兰色sic GLfloat colors123=/ 彩虹颜色1.0f,0.5f,0.5f,1.0f,0.75f,0.5f,1.0f,1.0f,0.5f,0
10、.75f,1.0f,0.5f,0.5f,1.0f,0.5f,0.5f,1.0f,0.75f,0.5f,1.0f,1.0f,0.5f,0.75f,1.0f,0.5f,0.5f,1.0f,0.75f,0.5f,1.0f,1.0f,0.5f,1.0f,1.0f,0.5f,0.75f;这段代码调用前面的代码载入位图,与前面的代码相同,只是位图的名称不同。载入一符名为Partic位图mp 的if (TextureImage0=LoadBMP(Data/Particmp) / 载入粒子纹理窗口改变大小的代码和前面一样,不需要改变使用光滑的阴影,清除背景为黑色,关闭深度测试,绑定并的改变就是禁用深度测试和初
11、始化粒子纹理.启用位图后选择粒子纹理。唯一glDisable(GL_DEPTH_TEST);/深度测试下面代码初始化每个粒子.从活跃的粒子开始.如果粒子不活跃,它在荧屏上将不出现,无论它有多少life.当使粒子活跃之後,给它 life.我怀疑给粒子生命和颜色渐变的是否是最好的方法,但当它运行一次后,效果很好!life 满值是 1.0f.这也给粒子完整的光亮.for (loop=0;loopMAX_PARTICLES;loop+)/初始化所有的粒子particleloop.active=true;particleloop.life=1.0f;/ 使所有的粒子为激活状态/ 所有的粒子生命值为最大通
12、过给定的值来设定粒子退色快慢.每次粒子被拉的时候 life 随着 fade 而减小.结束的数值将是 099 中的任意一个,然后平分 1000 份来得到一个很小的浮点数.最后把结果加上 0.003f 来使 fade 速度值不为 0particleloop.fade=float(rand()%100)/1000.0f+0.003f;/ 随机生成衰率既然粒子是活跃的,而且又给它生命,下面将给它颜色数值.一开始,就想每个粒子有不同的颜色.我怎么做才能使每个粒子与前面颜色箱里的颜色一一对应那?数学很简单,用 loop 变量乘以箱子中颜色的数目与粒子最大值(MAX_PARTICLES)的余数.这样防止最后
13、的颜色数值大于最大的颜色数值(12).举例:900*(12/900)=12.1000*(12/1000)=12,等等particleloop.r=colorsloop*(12/MAX_PARTICLES)0; particleloop.g=colorsloop*(12/MAX_PARTICLES)1;particleloop.b=colorsloop*(12/MAX_PARTICLES)2;/粒子的红色颜色粒子的绿色颜色粒子的蓝色颜色现在设定每个粒子移动的方向和速度.通过将结果乘于 10.0f 来创造开始时的效果.会以任意一个正或负值结束.这个数值将以任意速度,任意方向移动粒子.particl
14、eloop.xi=float(rand()%50)-26.0f)*10.0f;particleloop.yi=float(rand()%50)-25.0f)*10.0f; particleloop.zi=float(rand()%50)-25.0f)*10.0f;/随机生成X 轴方向速度随机生成Y 轴方向速度随机生成Z 轴方向速度最后,设定加速度的数值.不像一般的加速度仅仅把事物拉下,的加速度能拉出,拉下,拉左,拉右,拉前和xg 设为 0.0f.在 x 方向没有拉力.设 yg拉后粒子.开始需要强大的向下加速度.为了达到这样的效果为-0.8f 来产生一个向下的拉力.如果值为正则拉向上.不希望粒子
15、拉近或远离,所以将 zg 设为 0.0fparticleloop.xg=0.0f;particleloop.yg=-0.8f; particleloop.zg=0.0f;/ 设置 X 轴方向加速度为 0/设置Y 轴方向加速度为-0.8设置Z 轴方向加速度为 0现在为有趣的部分.下面的部分是从哪里拉粒子,检查加速度等等.你要明白它是怎么实现的,因此仔细的看:)重置Mview 巨阵.在画粒子位置的时候用 glVertex3f()命令来代替 tranlations,这样在view 巨阵画粒子的时候不会改变mDrawGLScene(GLvoid)/ 绘制粒子glClear(GL_COLOR_BUFFE
16、R_BITglLoadIdentity();| GL_DEPTH_BUFFER_BIT);/ 重置模型变换矩阵/ 以黑色背景清楚开始创建一个循环loop.这个环将会更新每一个粒子.for (loop=0;loopMAX_PARTICLES;loop+)/ 循环所有的粒子首先做的事物是检查粒子是否活跃.如果不活跃,则不被更新.在这个程序中,它们始终活跃.但是在你自己的程序中,你可能想要使某粒子不活跃if (particleloop.active)/ 如果粒子为激活的下面三个变量是确定 x,y 和z 位置的暂时变量.注意:在 z 的位置上加上 zoom 以便的场景在以前的基础上再移入zoom 个位
17、置.particleloop.x 告诉要画的x 的位置.particleloop.y 告诉要画的y 的位置.particleloop.z 告诉要画的z 的位置float floatfloatx=particleloop.x; y=particleloop.y;z=particleloop.z+zoom;/ 返回X 轴的位置/ 返回Y 轴的位置/ 返回 Z 轴的位置既然知道粒子位置,就能给粒子上色.particleloop.r 保存粒子的亮红,particleloop.g 保存粒子的亮绿,particleloop.b 保存粒子的亮蓝.注意我用 alpha 为粒子生命.当粒子要燃尽时,它会越来越透
18、明直到它最后.这就是为什么粒子的生命不应该超过 1.0f.如果你想粒子燃烧时间长,可降低 fade 减小的速度/ 设置粒子颜色glColor4f(particleloop.r,particleloop.g,particleloop.b,particleloop.life);有粒子的位置,并设置颜色了.所以现在来画的粒子.用一个三角形带来代替一个四边形这样使程序运行快一点.很多 3D card 画三角形带比画四边形要快的多.有些 3D card 将四边形分成两个三角形,而有些不.所以按照自己的想法来,所以来画一个生动的三角形带glBegin(GL_TRIANGLE_STRIP);/ 绘制三角形带
19、从红宝书引述:三角形带就是画一连续的三角形(三个边的多角形)使用vertiV0,V1,V2,然后 V2,V1,V3(注意顺序),然后 V2,V3,V4 等等.画三角形的顺序一样才能保证三角形带为相同的表面.要求方向是很重要的,例如:剔除,最少用三点来画当第一个三角形使用 verti0,1 和 2 被画.如果你看你将会理解用顶点 0,1 和 2 构造第一个三角形(顶端右边,顶端左边,底部的右边).第二个三角形用点 verti2,1 和 3 构造.再一次,如果你注意,点verti2,1 和3 构造第二个三角形(底部右边,顶端左边,底部左边).注意:两个三角形画点顺序相同.我看到很多的要求第二个三角
20、形反方向画.这是不对的.Opengl 从新整理顶点来保证所有的三角形为同一方向!注意:你在屏幕上看见的三角形个数是你叙述的顶点的个数减 2.在程序中在有 4 个顶点,所以看见二个三角形glTexCoord2d(1,1); glTexCoord2d(0,1); glTexCoord2d(1,0);glTexCoord2d(0,0);glVertex3f(x+0.5f,y+0.5f,z); glVertex3f(x-0.5f,y+0.5f,z); glVertex3f(x+0.5f,y-0.5f,z);glVertex3f(x-0.5f,y-0.5f,z);最后告诉Opengl画完三角形带glEn
21、d();现在能移动粒子.下面公式可能看起来很奇怪,其实很简单.首先取得当前粒子的x 位置.然后把 x 运动速度加上粒子被1000 倍后的值.所以如果粒子在x 轴(0)上屏幕中心的位置,运动值(xi)为 x 轴方向+10(移动为右),而 slowdown 等于 1,移向右边以 10/(1*1000)或 0.01f 速度.如果增加 slowdown 值到 2只移动 0.005f.希望能帮助你了解 slowdown 如何工作.那也是为什么用 10.0f 乘开始值来叫象素移动快速,创造一个爆发效果.y 和z 轴用相同的公式来计算附近移动粒子particleloop.x+=particleloop.xi
22、/(slowdown*1000); particleloop.y+=particleloop.yi/(slowdown*1000);particleloop.z+=particleloop.zi/(slowdown*1000);/更新X 坐标的位置更新Y 坐标的位置更新Z 坐标的位置在计算出下一步粒子移到那里,开始考虑重力和阻力.在下面的第一行,将阻力(xg)和移动速度(xi)相们的移动速度是 10 和阻力是 1.每时每刻粒子都在抵抗阻力.第二次画粒子时,阻力开始作用,移动速度将会从 10 掉到 9.第三次画粒子时,阻力再一次作用,移动速度降低到 8.如果粒子燃烧为超过 10 次重画,它将会最
23、后结束,并向相反方向移动.因为移动速度会变成负值.阻力同样使用于y 和z 移动速度particleloop.xi+=particleloop.xg; particleloop.yi+=particleloop.yg;particleloop.zi+=particleloop.zg;/更新X 轴方向速度大小更新Y 轴方向速度大小更新Z 轴方向速度大小下行将粒子的生命减少.如果不这么做,粒子无法烧尽.用粒子当前的 life 减去当前的 fade 值.每粒子都有不同的 fade 值,因此他们全部将会以不同的速度烧尽particleloop.life-=particleloop.fade;/ 减少粒子
24、的生命值现在检查当生命为零的话粒子是否活着if (particleloop.life0.0f)/ 如果粒子生命值小于 0如果粒子是小时(烧尽),会使它复原.给它全值生命和新的衰弱速度.particleloop.life=1.0f;/ 产生一个新的粒子particleloop.fade=float(rand()%100)/1000.0f+0.003f; / 随机生成衰率也重新设定粒子在屏幕中心放置.重新设定粒子的x,y 和z 位置为零particleloop.x=0.0f;particleloop.y=0.0f;/ 新粒子出现在屏幕的particleloop.z=0.0f;在粒子从新设置之后,将
25、给它新的移动速度/方向.注意:我增加最大和最小值,粒子移动速度为从 50 到 60 的任意值,但是这次没将移动速度乘 10.这次不想要一个爆发的效果,而要比较慢地移动粒子.也注意我把xspeed和x 轴移动速度相加,y 轴移动速度和 yspeed 相加.这个控制粒子的移动方向.particleloop.xi=xspeed+float(rand()%60)-32.0f); / 随机生成粒子速度particleloop.yi=yspeed+float(rand()%60)-30.0f); particleloop.zi=float(rand()%60)-30.0f);最后分配粒子一种新的颜色.变量
26、 col 保存一个数字从 1 到 11(12 种颜色),用这个变量去找红,绿,度在颜色箱里面.下面第一行表示红色的强度,数值保存在 colorscol0.所以如果 col 是 0,红色的亮度就是 1.0f.绿色的和蓝色的值用相同的方法.如果你不了解为什么红色亮度为 1.0f 那 col 就为 0.我将一点点的解释.看着程序的最前面.找到那行:sic GLfloat colors123.注意:12 行3 列.三个数字的第一行是红色强度.第二行是绿色强度而且第三行是蓝色强度.0,1和2下面描述的 1st,2nd 和 3rd 就是我刚提及的.如果 col 等于 0,要看第一个组.11 是最後一个组(
27、第 12 种颜色).particleloop.r=colorscol0;particleloop.g=colorscol1; particleloop.b=colorscol2;/ 设置粒子颜色下行描述加速度的数值是多少.通过小键盘 8 号键,增加 yg(y 地心引力)值.这引起向上的力.如果这个程序在循环外面,那么须生成另一个循环做相同的工作,因此最好放在这里/ 如果小键盘 8 被按住,增加Y 轴方向的加速度if (keysVK_NUMPAD8 & (particleloop.yg-1.5f) particleloop.yg-=0.01f;现在更改向右的拉力.如果按下 6 号键时增加向右的拉
28、力./ 如果小键盘 6 被按住,增加X 轴方向的加速度if (keysVK_NUMPAD6 & (particleloop.xg-1.5f) particleloop.xg-=0.01f;我仅仅为乐趣增加了一些代码.兄弟产生很棒的效果:)通过按住 tab 键所有粒子都回到屏幕中心.所有的粒子在从新开始运动,再产生一个大的爆发.在粒子变弱之后,你最初的效果会再一次出现if (keysVK_TAB)particleloop.x=0.0f; particleloop.y=0.0f; particleloop.z=0.0f;/ 按 Tab 键,使粒子回到原点particleloop.xi=float(
29、rand()%50)-26.0f)*10.0f; / 随机生成速度particleloop.yi=float(rand()%50)-25.0f)*10.0f; particleloop.zi=float(rand()%50)-25.0f)*10.0f;return TRUE;/ 绘制完毕成功返回代码KillGLWindow(),CreateGLWindow()和 WndProc()中没有改变,所以码直接跳到Wain().我将重写代我喜欢简单的代码.在一行上不想包含很多东西,所以使代码象一个清洁工:)下面的代码检查+是否被按下.如果它和slowdown 一起实现则 slowdown 减少 0.01f.粒子就可以较快速地移动.if (keysVK_ADD & (slowdown1.0f) slowdown-=0.01f;/ 按+号,加速粒子下面的代码检查-是否被按下.如果它和slowdown 一起实现则 slowdown 增加 0.01f.粒子就可以较慢速地移动.我实质的极限是 4.0f,我不想它太慢的运动,你可以随你的要求改变最大最小值if (keysVK_SUBTRACT & (slowdown25) / 空格键,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026数学核心素养量感同步课件
- 数据安全策略与实施指南
- 财务员工KPI绩效考评表示例
- 养老服务机构员工绩效考评表
- IT系统管理员服务器巡检与维护方案
- 年度业绩对账通知函6篇范本
- 交通运输车辆调度人员绩效考核表
- 体育设施安装与维护管理方案手册
- 食品行业质量安全监控员绩效衡量表
- 教育培训成果KPI考核表
- 灰岩地区长大隧道机械化快速施工技术
- 《勾股定理》整章综合测试(一)338345
- (完整)注册安全工程师考试题库(含答案)
- GB/T 17880.6-1999铆螺母技术条件
- YY 0899-2020医用微波设备附件的通用要求
- JJF 1915-2021倾角仪校准规范
- GB/T 325-2000包装容器钢桶
- 执行-如何完成任务的学问课件
- 临床实践中的循证医学(课件新修)
- 特种作业人员安全操作规程
- 抢救病人现场记录单
评论
0/150
提交评论