OpenGL之粒子系統

OpenGL之粒子系統

『粒子系統』由多個『粒子』,每個『粒子』都有其獨立『屬性』如『尺寸』『顏色』『速度』,每個『粒子』都可獨立運作.當大量『粒子』同時運作便可產生其特的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;

}

 

評論