| 導購 | 订阅 | 在线投稿
分享
 
 
 

讓你領會真實火焰效果模擬再現

來源:互聯網  2008-05-19 00:45:18  評論

遊戲制作離不開各種各樣的特效,火焰效果更是這些特效當中最常用的一種。在網上有很多的這方面的例子,但似乎都不太理想。下面我主要介紹幾種有效的火焰模擬算法。

在講述火焰算法之前,我想先介紹一個經典的Blur算法,這將爲我們後面的文章提供很好的技術基礎,因爲這是模擬火焰的關鍵所在。^_^

對于不同的效果我們要采取不同的模糊(Blur)算法,在這裏我只介紹最簡單的一種。

其實Blur算法相當簡單,並不像很多人想象的那麽神秘,只要一句話就可以解釋清楚。我們所要做的不過是把屏幕上的每一個點用它周圍的四個點的平均值代替即可。即:

王朝网络

好了,下面我們進入主題,Let' s get in …… FIRE ! ! !

總的來說,模擬一個火焰效果需要以下這三個步驟:放置熱源、火焰上升、減掉衰減因子。

1.放置熱源:

放置熱源很好理解,也很好實現,我們只需要在屏幕的適當位置(想升起火焰的地方)放上一些亮點就可以了,比如:

for (int i=0; i

putpixel (i, 199, rand()%256);

2.火焰上升:

我們已經有了熱源,那麽如何使火焰升起來呢?這就要用到我們剛才講到的Blur了。由于火焰是要向上升的,所以我們不能簡單的選擇待處理pixel的上、下 、左、右四個相臨pixel,而是要選擇它本身和它下面的三個pixel。具體實現的pseudo-code如下:

for (int y=0; y

{

for (int x=0; 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

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

{

for (x=0;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,這是一個開啓保護模式的程序,如果沒有程序將無法運行。

(作者:周軍)

  遊戲制作離不開各種各樣的特效,火焰效果更是這些特效當中最常用的一種。在網上有很多的這方面的例子,但似乎都不太理想。下面我主要介紹幾種有效的火焰模擬算法。   在講述火焰算法之前,我想先介紹一個經典的Blur算法,這將爲我們後面的文章提供很好的技術基礎,因爲這是模擬火焰的關鍵所在。^_^   對于不同的效果我們要采取不同的模糊(Blur)算法,在這裏我只介紹最簡單的一種。   其實Blur算法相當簡單,並不像很多人想象的那麽神秘,只要一句話就可以解釋清楚。我們所要做的不過是把屏幕上的每一個點用它周圍的四個點的平均值代替即可。即:      [url=/bbs/detail_1440377.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129117477.gif[/img][/url]   好了,下面我們進入主題,Let' s get in …… FIRE ! ! !   總的來說,模擬一個火焰效果需要以下這三個步驟:放置熱源、火焰上升、減掉衰減因子。   1. 放置熱源:   放置熱源很好理解,也很好實現,我們只需要在屏幕的適當位置(想升起火焰的地方)放上一些亮點就可以了,比如:   for (int i=0; i   putpixel (i, 199, rand()%256);   2. 火焰上升:   我們已經有了熱源,那麽如何使火焰升起來呢?這就要用到我們剛才講到的Blur了。由于火焰是要向上升的,所以我們不能簡單的選擇待處理pixel的上、下 、左、右四個相臨pixel,而是要選擇它本身和它下面的三個pixel。具體實現的pseudo-code如下:   for (int y=0; y   {   for (int x=0; 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)      [url=/bbs/detail_1440377.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129117570.gif[/img][/url]   圖2. 沒有衰減(不可取!)      [url=/bbs/detail_1440377.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129117695.gif[/img][/url]   具體實現的pseudo-code如下:   if (--bright   bright = 0; //衰減且保證bright=0   記住:千萬不要忘了檢驗不要讓bright小于0,否則……自己試試就知道了,嘿嘿~~~~~~   也許讀者會發現我們現在的火焰有些死板,所以我們不妨試著在火焰上加入一些spark(火星),這可以使我們的火焰更加有戲劇性雖然它在一定程度上削弱了火焰的真實性。其效果圖如下:      [url=/bbs/detail_1440377.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129117820.gif[/img][/url]   圖3. 添加了火星的效果 (FireWithSpark.exe)   看過Seumas McNally(我很崇拜的大師,呵呵)的ParticleFire(粒子火焰,見ParticleFire.exe)的朋友可能會知道,他在他的火焰處理上就用這個算法以使他的火焰更富戲劇性。   到此爲止,我已經完整地介紹了模擬一個火焰效果地全部算法。但是這樣模擬出來的火焰始終過于死板、不夠逼真(當然,最爲逼真的效果莫過于通過基于Alpha通道的僞粒子系統的實現,在這裏我們不作討論)。如何才能解決這個問題呢?一個很好的辦法是把我們的熱源放置在一個運動的物體上(Hugo就曾使用feed back和warp的技術逼真地模擬了火焰的效果,中國的程序員也有用與Hugo完全相同的算法真實模擬了這個效果),而不是放在屏幕底部,這樣通過物體的運動再加上一些放縮、模糊技巧就可以使我們的火焰産生出意想不到的效果了!^_^。   具體運行效果如圖4所示:    [url=/bbs/detail_1440377.html][img]http://images.wangchao.net.cn/images/upload/images/lsdn/1211129118008.gif[/img][/url]   圖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   {   for (x=0;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,這是一個開啓保護模式的程序,如果沒有程序將無法運行。   (作者:周軍)
󰈣󰈤
王朝萬家燈火計劃
期待原創作者加盟
 
 
 
>>返回首頁<<
 
 
 
 
 熱帖排行
 
 
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有