『粒子系統』由多個『粒子』,每個『粒子』都有其獨立『屬性』如『尺寸』『顏色』『速度』,每個『粒子』都可獨立運作.當大量『粒子』同時運作便可產生其特的3D效果.『飄雪』『流星』『爆炸』『飛機引擎火焰』.
『飄雪』演示程式在天空落雪,時用『廣告牌』技術另廣告牌總是對這鏡頭.下載『飄雪』
粒子系統大約分為
1.初此化粒子系統
2.生成粒子
3.更新粒子系統
4.渲染粒子系統
基本『粒子』屬性 | 簡介 |
位置 | 3D空間中的座標 |
速度 | 基本上粒子都會移動,你需要方向向量再乘以時間而求得速度 |
尺寸 | 粒子的尺寸可能變化 |
重量 | 外力對粒子影響 |
顏色 | 為粒子設定渲染顏色 |
形態 | 常見『點』『直線』『紋理四邊形』 |
宿主 | 粒子擁有者 |
生命週期 | 粒子存活時間 |
定義粒子結構
typedef struct PARTICLE_TYP {
VECTOR3D pos;// 位置
VECTOR3D velocity;// 速度與方向
VECTOR3D acceleration;// 加速度
float energy;// 生命週期(秒)
float size;// 尺寸
float weight;// 重量
float color[4];// 顏色
}PARTICLE,*PARTICLE_PTR;
『粒子系統』屬性 | 簡介 |
粒子隊列 | 要管理的所有粒子 |
數量 | 粒子量 |
位置 | 活動範圍中心位置 |
範圍 | 粒子活動範圍 |
屬性 | 常見『點』『直線』『紋理四邊形』 |
紋理 | 把紋理存儲在『粒子系統』 |
Particle(粒子系統)
typedef struct PARTICLE_SYSTEM_TYP{
int attr;// 屬性
PARTICLE_PTR array;// 數組
int count;// 實制個數
VECTOR3D origin;// 原點
VECTOR3D velocity;// 速度與方向
VECTOR3D velocity_variation;// 速度變量
float energy;// 生命週期(秒)
//有效範圍
float height;// 高
float width; // 寬
float depth; // 深
float size;// 尺寸
TEXTURE_PTR texture;// 紋理
}PARTICLE_SYSTEM, *PARTICLE_SYSTEM_PTR;
1.初此化粒子系統
bool Init_Particle(PARTICLE_SYSTEM_PTR system, int count,
VECTOR3D_PTR origin, VECTOR3D_PTR velocity, VECTOR3D_PTR variation,
float height, float width, float depth,float size,float energy,
TEXTURE_PTR texture)// 紋理
{
if (system == NULL)
return false;
memset(system,0,sizeof(PARTICLE_SYSTEM));// 清空
system->count = count; // 粒子數量
system->array = (PARTICLE_PTR)malloc(sizeof(PARTICLE)*count);// 分配空間
system->texture = texture;// 紋理
system->size = size;// 尺寸
system->height = height;// 高
system->width = width;// 寬
system->depth = depth;// 深
Copy_VECTOR3D(&system->origin, origin);// 原點
Copy_VECTOR3D(&system->velocity, velocity);// 速度與方向
Copy_VECTOR3D(&system->velocity_variation, variation);// 速度變量
PARTICLE_PTR particle;// 粒子
for (int i = 0; i < count; ++i)
{
particle = &system->array[i];// 粒子
Buid_Particle(system, particle);
}
return true;
}
2.生成粒子
void Buid_Particle(PARTICLE_SYSTEM_PTR system, PARTICLE_PTR particle)
{
particle->energy = system->energy;// 生命週期(秒)
particle->size = system->size;// 尺寸
// 粒子位置
particle->pos.x = system->origin.x + FRAND_RANGE1() * (system->width /2.0f);// x
particle->pos.y = system->origin.y + FRAND_RANGE1() * (system->height/2.0f);// y
particle->pos.z = system->origin.z + FRAND_RANGE1() * (system->depth /2.0f);// z
// 粒子速度
particle->velocity.x = system->velocity.x ;
particle->velocity.y = system->velocity.y ;
particle->velocity.z = system->velocity.z ;
}
3.更新粒子系統
void Update_Particle(PARTICLE_SYSTEM_PTR system,float time)
{
PARTICLE_PTR particle;// 粒子
for (int i = 0; i < system->count; ++i)
{
particle = &system->array[i];// 粒子
VECTOR3D vector;
Scale_VECTOR3D(&vector, &particle->velocity, time);
Add_VECTOR3D(&particle->pos, &particle->pos, &vector);// 移動粒子
// 判斷有無超出返圍
particle->energy = particle->energy – time;// 計算生命週期
if (particle->energy < 0 && particle->pos.y < 0)// 生命週期
Buid_Particle(system, particle);
}
}
4.繪畫貝粒子系統(紋理)
bool Draw_Texture_Particle(PARTICLE_SYSTEM_PTR system,
CAMERA3D_PTR camera, BILLBOARD_PTR billboard)
{
glPushMatrix();// 壓入矩陣
glPushAttrib(GL_ALL_ATTRIB_BITS);
glDisable(GL_LIGHTING);// 禁用光照
glDisable(GL_LIGHT0);// 禁用0號燈光
glEnable(GL_DEPTH_TEST);// 啟用深度測試
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_ALPHA_TEST);// 啟用透面測試
glAlphaFunc(GL_GREATER, 0);// 透面色
PARTICLE_PTR particle;// 粒子
for (int i = 0; i < system->count; ++i)
{
particle = &system->array[i];// 粒子
//檢查3D球體是否為於視錐體內
if (Compute_Sphere_In_Frustum(&camera->frustum, &particle->pos, particle->size) == true)
{ // 繪畫Billboard廣告牌
Draw_Billboard(billboard, &particle->pos, particle->size);
}
}
glPopAttrib();// 彈出屬性
glPopMatrix();// 彈出矩陣
return true;
}