您现在的位置: 中国IT实验室 >> 游戏开发 >> 开发文档 >> 文章正文
让你领会真实火焰效果模拟再现
来源:chinaitlab整理收集 作者: 时间:2005-3-3


  游戏制作离不开各种各样的特效,火焰效果更是这些特效当中最常用的一种。在网上有很多的这方面的例子,但似乎都不太理想。下面我主要介绍几种有效的火焰模拟算法。
  在讲述火焰算法之前,我想先介绍一个经典的Blur算法,这将为我们后面的文章提供很好的技术基础,因为这是模拟火焰的关键所在。^_^ 对于不同的效果我们要采取不同的模糊(Blur)算法,在这里我只介绍最简单的一种。
  其实Blur算法相当简单,并不像很多人想象的那么神秘,只要一句话就可以解释清楚。我们所要做的不过是把屏幕上的每一个点用它周围的四个点的平均值代替即可。即:
  
 

  好了,下面我们进入主题,Let' s get in …… FIRE ! ! !
  总的来说,模拟一个火焰效果需要以下这三个步骤:放置热源、火焰上升、减掉衰减因子。
  1. 放置热源:
  放置热源很好理解,也很好实现,我们只需要在屏幕的适当位置(想升起火焰的地方)放上一些亮点就可以了,比如:
  for (int i=0; i<320; i++)
  putpixel (i, 199, rand()%256);
  2. 火焰上升:
  我们已经有了热源,那么如何使火焰升起来呢?这就要用到我们刚才讲到的Blur了。由于火焰是要向上升的,所以我们不能简单的选择待处理pixel的上、下 、左、右四个相临pixel,而是要选择它本身和它下面的三个pixel。具体实现的pseudo-code如下:
  for (int y=0; y<200; y++)
  {
  for (int x=0; x<320; x++)
  {
  pixel(x,y)=(pixel(x,y)+
  pixel(x-1,y+1)+
  pixel(x,y+1)+
  pixel(x+1,y+1))/4;
  
  //……
  
  putpixel (x,y,bright);
  }
  }
  3. 减衰减因子:
  看到上面的 "//……" 了么?对了,那儿就是我们要添加如下这段代码的地方。为什么要减掉一个衰减因子呢?让我们通过两副图的对比来说明它的重要性吧:
  图1. 减掉了衰减因子 (Fire.exe)
  
 

  图2. 没有衰减(不可取!)
  
 

  具体实现的pseudo-code如下:
  if (--bright < 0)
  bright = 0; //衰减且保证bright>=0
  记住:千万不要忘了检验不要让bright小于0,否则……自己试试就知道了,嘿嘿~~~~~~
  也许读者会发现我们现在的火焰有些死板,所以我们不妨试着在火焰上加入一些spark(火星),这可以使我们的火焰更加有戏剧性虽然它在一定程度上削弱了火焰的真实性。其效果图如下:
  
 

  
图3. 添加了火星的效果 (FireWithSpark.exe)

  看过Seumas McNally(我很崇拜的大师,呵呵)的ParticleFire(粒子火焰,见ParticleFire.exe)的朋友可能会知道,他在他的火焰处理上就用这个算法以使他的火焰更富戏剧性。
  到此为止,我已经完整地介绍了模拟一个火焰效果地全部算法。但是这样模拟出来的火焰始终过于死板、不够逼真(当然,最为逼真的效果莫过于通过基于Alpha通道的伪粒子系统的实现,在这里我们不作讨论)。如何才能解决这个问题呢?一个很好的办法是把我们的热源放置在一个运动的物体上(Hugo就曾使用feed back和warp的技术逼真地模拟了火焰的效果,中国的程序员也有用与Hugo完全相同的算法真实模拟了这个效果),而不是放在屏幕底部,这样通过物体的运动再加上一些放缩、模糊技巧就可以使我们的火焰产生出意想不到的效果了!^_^。
  具体运行效果如图4所示:
  

  图4. 通过Rotate产生的火焰效果 (CoolFire.exe)
  下面我就对这个算法的具体步骤进行简要地分析,并在适当的地方给出相应的代码、伪码。
  这个算法主要也分成四个步骤:放置热源、移动物体、放缩、模糊。
  1. 放置热源:
  这个步骤和上面步骤完全一样,不过就是画出一个物体。
  2. 移动物体:
  在我的程序中我用了一系列的矩阵变换以完成物体的运动,当然也可以像Hugo一样,用feed back的技巧(只不过就是在一个平面上而不是3维空间中旋转物体)。具体实现见CoolFire.cpp,关于矩阵运算的具体实现见我的《走进3D的世界--C++中用运算符重载实现矩阵运算》一文,有关矩阵的运算请参考计算几何的有关书籍,在这里不作过多讨论。
  Obj=rotX(thetaX)*rotY(thetaY)*rotZ(thetaZ);
  3. 放缩:
  在程序中我的放缩采用了这样一个算法:先任取一定点(x,y),然后依次把屏幕上的每一个点与这个点比较,用它们之间的距离乘上一个放缩因子在加到(x,y)上,这个值便是放缩的索引值,以下便是实现的代码(未优化):
  long Offset=0;
  
  for (y=0;y<200;y++)
  {
  for (x=0;x<320;x++)
  {
  IndexX=sx+(x-sx)*ScaleX;
  IndexY=sy+(y-sy)*ScaleY;
  lpVideoBuffer[Offset++]=lpSrcBuffer[IndexY*320+IndexX];
  }
  }
  为了便于理解,我没有对代码进行优化,读者在编写程序时必须对以上代码进行有效地优化,具体方法是:先在一次循环中算出IndexX和IndexY的值并保存在数组中,待进行放缩操作时直接用它们作索引放缩,而不是像上面的代码一样边计算边操作放缩。
  4. 模糊:现在全国人民都知道Blur了吧,那我就不再罗嗦了。
  好了,我想,对于火焰的算法我已经很清晰地展示在您地面前了,有效地运用这些算法一定会为您地游戏开发带来很大地便利。
  文章中的所有实例(除了ParticleFire以外)均在Watcom C++中调试成功,读者在运行的时候必须保证您的运行目录里有dos4gw.exe,这是一个开启保护模式的程序,如果没有程序将无法运行。
  (作者:周军)
收藏本文 责编:admin 


相关文章
基于D3D Effect的引擎模式探讨
介绍简易制作飞行模拟游戏的方法
WU反走样(Anti-aliased)直线初探
基于Alpha通道的伪粒子系统的应用
借助DirectDraw实现对水波的计算机模拟
推荐文章


 精彩友情推荐
·神州数码交换机
·神州数码交换机价格
·神州数码网络交换机
·netgear交换机
·网件交换机
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  针对于移动新出台的政策,需要尽快地把我们公司的游戏对应到不同的手机平台,这是针对市场策略的有利调整............
Quake-III代码里神奇的浮点开方函数
基于Dialogue的MFC程序调用DirectX
关于Kjava手机平台移植可行性报告
网络游戏的数据传输处理和防火墙穿
浅谈网游的数据传输处理和防火墙穿
向量几何在游戏编程中的使用(六)
向量几何在游戏编程中的使用(五)
向量几何在游戏编程中的使用(四)
向量几何在游戏编程中的使用(三)
向量几何在游戏编程中的使用(二)
  培训中心