在前面的章節中我們看到了通過OpenGL提供的幾種基本圖元來類比實現顯示世界中的各種物體。但是,實際上有些物體很難用這幾個簡單圖元能夠完全表示出來的,即便加上透明、紋理映射、混合、霧的效果等,也很難逼真的反映真實物體,達不到理想的效果。因為這些物體要麼在邏輯結構上難以表達,要麼就是動態,或者根本沒有固體的表面。如煙、雲、火焰、水等自然物體就屬於這一範疇。
為瞭解決類似的問題,在1982年William T.Reeves提出了粒子系統(Particle System)的概念,類比不規則模糊物體的產生。在粒子系統中,一個物體由一系列的粒子來表示,每一個粒子都有自己的生命週期,都要經曆出生、生長和死亡的三個階段,並且有自己的位置、速度、顏色、大小等等,充分體現了不規則物體的動態和隨機性,從而能夠很好地類比火、雲、水、森林和原野等許多自然景象。利用粒子系統,Reeves類比了電影《Star Trek Ⅱ: The Wrath of Khan》 中的一系列特技鏡頭。
此後,Reeves和Blau對粒子系統進行了發展,他們用“volume filling ”基本單元產生隨時可能改變形狀但又基本保持不變的實體,如草葉的隨風抖動,並提出了一個巧妙的繪製模型,並且用於電影《The Adventures of Andre and Wally B. 》中的三維森林和草的產生。
粒子系統產生物體的基本步驟是
1、產生新的粒子加入到當前的粒子系統中
2、賦予每一個新粒子唯一的屬性
3、將那些已經超過生存期的粒子標記為死亡
4、根據粒子的動態屬性對粒子進行移動和變換
5、顯示由有生命的粒子組成的圖象。
在大型的3D遊戲中,粒子系統是一個必不可少的部分。象發射的子彈、雷射霰彈,燃燒的火焰都是粒子系統是具體實現。
當然,一個完整的功能強大的粒子系統的設計並不是一蹴而就的。我們這裡只對粒子系統作一個基本的介紹,然後實現一個簡單的粒子系統。
首先,我們來設計一個粒子類:
class CParticle
{
private:
CParticleSystem * mParent; //本粒子所在的粒子系統,後面介紹
public:
VERTEX3D mPreviousLocation; // 粒子上一次的位置
VERTEX3D mCurrentLocation; // 粒子當前位置
VECTOR3D mVelocity; // 粒子當前速度
float mColor[4]; // 粒子顏色
float mColorCounter[4]; // 顏色計數器
float mAlpha; // 粒子當前透明度
float mAlphaCounter; // 增加減少透明度計數器
float mSize; // 粒子當前大小
float mSizeCounter; //增加減少大小計數器
float mAge; //粒子當前生命
float mDyingAge; //粒子死亡期
void SetParentSystem(CParticleSystem* parent);
void Create(CParticleSystem* parent, float TimeCounter);
bool Update(float TimeCounter);
CParticle();
~CParticle();
};
私人成員mParent用於設定本粒子所屬的粒子系統,從粒子系統中得到相關的資訊來建立新的粒子。其他的成員都有簡單說明,容易理解。
mColorCounter則表示粒子生命週期內顏色變換的計算。例如,如果定義一個粒子的產生時的顏色是黃色,死亡時的顏色是紅色,那麼在生長過程中的顏色則線性變化,變化的次數就是mColorCounter=(紅色-黃色)/mDyingAge。而粒子的大小、透明度也是採用同樣的方法處理的。為了計算粒子的生命,可以給粒子附上一個在整個粒子系統生命基礎上的一個隨機值。