用DirectX實現粒子系統(三)

2021-09-08 00:23:36 字數 3751 閱讀 5943

引言

前面說了,乙個複雜的現象是由若干個基本單元構成的,所以,我們最先定義這個基本單元-粒子,乙個粒子主要有哪些屬性呢?由上面的圖可知,首先粒子是有顏色的,上面一共有白,紅,黃,綠四種顏色的粒子。其次,粒子是有大小的,只有大小不同的粒子相互組合才能構成特殊的漸進效果。再次粒子也是有紋理的,比如上面的效果中,我們一共使用了如下三種紋理

粒子也是有位置的,給粒子設定乙個初始位置,然後按照時間不斷變化粒子的位置才能形成特殊的效果。粒子也是有生命週期的,因為隨著時間的流逝,粒子會漸漸變暗,最終消亡,消亡的粒子將不再被渲染。運動的粒子還要有乙個初始速度及加速度。就這些了!下面列出了乙個粒子應該具備的所有屬性。

所以,我們可以如下定義乙個粒子類。

class

particle

;

有了粒子類,我們還需定義乙個粒子系統類,粒子系統類的任務是操作粒子類,來完成粒子的生成,更新,渲染,消亡及再生成的過程,通過生成及更新粒子的狀態來實現整個粒子系統的效果。這是乙個抽象類,包含四個純虛函式,init函式用來初始化粒子系統,比如建立vertex buffer,載入粒子對應的紋理等。update函式用來更新粒子系統的狀態,也就是更新系統中每個粒子的狀態,包括粒子的速度,位置,存活時間等,都由該函式來更新。render函式用來渲染粒子系統,這是最關鍵的乙個函式。addparticle函式用來新增新的粒子到粒子系統中,因為每個粒子都是有生命週期的,超過生命週期的粒子則為死忙狀態,為了節約資源,我們將死亡狀態的粒子重新設定為新生粒子,然後修改其屬性再加入到粒子系統中,這樣就可以通過有限的粒子實現多個**效果了。

#include "

particle.h

"class

particlesystem

;#endif

//end particlesystem_h

然後,我們定義乙個emitter類來繼承上面的抽象類,並實現其中每個純虛函式。emitter類來完成具體的粒子系統需要的工作。

先看建構函式,建構函式主要做一些初始化工作。

emitter::emitter(idirect3ddevice9* pdevice, emitterconfig* emitterconfig, particleconfig*particleconfig)

:m_particletexture(null), pvb(null)

然後是init函式,在這個函式裡,我們建立vertex buffer,並從檔案建立粒子紋理。

void

emitter::init()

接下來是update函式,注意這個函式每一幀都會呼叫一次,而且先於render函式呼叫,所以整個粒子系統在渲染之前是通過該函式對每個粒子進行初始狀態設定的。在這個函式中,我們對容器vector中的每個粒子都進行狀態更新。首先判斷粒子是否存活,如果存活則更新狀態,否則通過呼叫resetparticle函式重置粒子狀態為存活,並再次將其加入粒子系統,這樣可以避免生成新的粒子,在效能上可以獲得優勢。更新粒子的狀態包括更新位置,更新粒子時間及顏色,如果粒子的存活時間超過其生命週期則將其置為死亡狀態。第二個for語句用來生成新的粒子,因為剛開始,整個粒子系統中並沒有粒子存在,所以容器vector為空,這意味著第乙個for語句在粒子系統剛剛執行時是不會執行的。需要通過第二個for語句向系統中增加新的粒子。直到填滿整個容器。隨後的迴圈渲染才會呼叫第乙個for語句。

void emitter::update(float

timedelta)

}else

resetparticle((particle*)(&(*citor))) ;

}//emit new particle

for (int i = 0 ; i < m_numparticlestoadd && buffer.size() < vbsize; ++i)

}

再下來就是resetparticle函式,這個函式用來重置乙個死亡粒子的狀態,使其再次進入粒子系統,這樣要比重新生成乙個粒子節省時間。首先將粒子狀態置為存活,然後將其已存活時間設定為0,然後是設定粒子的生命週期,這裡可以從配置檔案讀取值,也可以通過函式隨機生成乙個值,這樣的話每個粒子的生命週期都是隨機的,會產生不同的效果。否則的話,所有粒子同時生成,同時消亡,則略顯生硬。接下來設定粒子的位置和顏色,最後設定粒子的速度,這裡的速度和物理學中的速度一樣,是個向量,我們選取範圍為[-1,-1,-1]到[1,1,1]內的向量,這樣產生的所有速度將構成乙個半徑為1的球體。和烟花的效果比較類似。

void emitter::resetparticle(particle*particle)

else

particle->m_position =m_position ;

particle->m_color =m_particlecolor ;

d3dxvector3 min = d3dxvector3(-1.0f, -1.0f, -1.0f

); d3dxvector3 max = d3dxvector3( 1.0f, 1.0f, 1.0f

); utilities::getrandomvector(&particle->m_velocity, &min, &max);

//normalize to make spherical

d3dxvec3normalize(&particle->m_velocity, &particle->m_velocity);

}

接下來是addparticle函式,該函式首先生成並重置乙個粒子,然後將該粒子新增到粒子系統中。

void

emitter::addparticle()

最後,也是最重要的,render函式,用來完成最終的粒子系統渲染工作。在這個函式裡,我們首先設定一系列的renderstate,這些renderstate都是用來設定粒子的渲染狀態,這裡就不一一詳述了,接下來設定紋理,也不必多說。最後是真正繪製粒子的**,在繪製的時候,我們採用分批處理的辦法,每次繪製一部分粒子,這裡我們設定了乙個vbbatchsize值,這就是每次繪製的粒子個數,我們會在vertex buffer中一次性鎖住這麼多粒子,然後繪製,繪製完畢移動到下一批,繼續繪製,直到剩下的粒子數小於vbbatchsize,最後再把所有剩下的粒子一次性繪製完畢即可。

void

emitter::render()}}

pvb->unlock() ;

//render the left particles

if(numparticleinbatch)

//restore state

device->setrenderstate( d3drs_alphablendenable, false );

}

好啦,這就是整個粒子系統的繪製過程了,在這裡我們採用了配置檔案的方式,為的是能將每個粒子系統的引數寫到檔案了,這樣每個檔案實際上就對應乙個特效,我們可以通過新增配置檔案的方式來實現不同的特效,核心**部分則不用修改。

用DirectX實現粒子系統(三)

引言 前面說了,乙個複雜的現象是由若干個基本單元構成的,所以,我們最先定義這個基本單元 粒子,乙個粒子主要有哪些屬性呢?由上面的圖可知,首先粒子是有顏色的,上面一共有白,紅,黃,綠四種顏色的粒子。其次,粒子是有大小的,只有大小不同的粒子相互組合才能構成特殊的漸進效果。再次粒子也是有紋理的,比如上面的...

粒子系統的簡單實現

粒子系統說起來高深摸測,其實就是許多許多許多許多許多許多的點圖象,然後對其進行執行速度,方向,衰減的處理。不可少的,先定義一些全域性變數。const intmaxpoint 1000 粒子的個數 float slowdown 2.0f float xspeed 粒子的速度,這裡沒有給出。可以自己加 ...

CCParticleSystem粒子系統

第一次接觸粒子系統,以前遊戲裡面的一些小特效,像製作動畫一樣,是採用一幀一幀的切出來的,由於這種特效,變化無常,切出來的幀,都非常的大,也很耗記憶體,一下就記憶體溢位了.呵呵 主要是以前都沒有接觸過.現在接觸了,以後遊戲就可以用到了.開心 建立乙個ccparticlesystem粒子系統 ccpar...