openGL粒子系統實現

來源:互聯網
上載者:User

先看一些,我是在Mac os 10.5.8系統上,在xcode中編寫的,openGL程式是使用GLUT建立的.

星星效果,從中間向z軸,也就是垂直螢幕向外射出,感覺就是在穿梭.

雪花效果,在空中漂浮.

火焰效果,不是很像..不好意思

   今天上網查了點資料,自己寫了個粒子系統,修改相關參數即可實作類別似瀑布,火焰,飛雪等效果,其實粒子系統並不複雜,主要的處理過程為3個,

1.初始化粒子的狀態.

2.對粒子進行渲染,更新它的狀態.

3.如果粒子的狀態表示它的周期結束,則調用1再此初始化它的狀態即可.

其中,粒子的狀態包括一下:

1.標示符是否啟用,也就是說是否接受渲染以及更新操作(主要用於動態修改參與渲染的粒子數目).

2.生命值,這裡設為區間在[0.0 - 1.0],方便在啟用了混合模式下將之設為Alpha值來顯示透明度.

3.衰減速率,一個較小的值,用於每次更新後對生命值進行衰減,當生命值小於0時即表示粒子周期結束.

4.RBG顏色,分別用3個GLfloat類型的變數來表示.

5.xyz位置座標.

6.當前速度xs,ys,zs.

7.3個方向速度的加速度xg,yg,zg,可以理解為3個方向的重力分量.

粒子的屬性基本就是這樣了,那麼粒子系統的過程便是先建立一個粒子集合,例如1000個粒子集合particle[1000],然後對齊進行初始化,設定初始位置,速度,加速度等,然後放入openGL渲染函數,用一個適當的方式將它繪製出來,我選擇的是GL_POINT,繪製一個點,開啟點平滑模式後就是以圓的方式表現.然後繪製完就對它的狀態進行更新,對於粒子的顏色,我這裡是選擇利用life*10轉為GLint的值作為一個2維數組的pos來得到,所以粒子不同階段的顏色不同,這裡發出源碼

這是Particle.h,定義了粒子系統的一些函數以及結構體.

/*<br /> * Particle.h<br /> * GL_PARTICLE_SYSTEM<br /> *<br /> * Created by Jackie Deng on 10-1-22.<br /> * Copyright 2010 dsd. All rights reserved.<br /> *<br /> */<br />#import <OpenGL/OpenGL.h></p><p>#ifndef _PARTICLE_SYSTEM_<br />#define _PARTICLE_SYSTEM_<br />#define MAX_PARTICLE_NUM 1000<br />////////////////////////////////////////////////////<br />//預設風格集合<br />#define PSTYLE_STAR 0<br />#define PSTYLE_FIRE 1<br />#define PSTYLE_SNOW 2<br />////////////////////////////////////////////////////<br />typedef struct particle {</p><p>GLboolean active;//是否活躍<br />GLfloat life;//生命</p><p>GLfloat fade; //衰減速度</p><p>//顏色<br />GLfloat r;//紅色<br />GLfloat g;//綠色<br />GLfloat b;//藍色</p><p>//位置<br />GLfloat x;<br />GLfloat y;<br />GLfloat z;</p><p>//速度<br />GLfloat xs;<br />GLfloat ys;<br />GLfloat zs;</p><p>//加速度<br />GLfloat xg;<br />GLfloat yg;<br />GLfloat zg;</p><p>}Particle;<br />extern void particleInitCallBack(GLvoid (*p)(Particle * q) ); /*初始化回調 */<br />extern void particleDisplayCallBack(GLvoid (*p)(Particle *q)); /* 渲染回調*/<br />extern void particleUpdateCallBack(GLvoid (*p)(Particle *q)); /* 更新 */<br />extern void particleSysStartUp(); /* 初始化粒子系統 */<br />extern void particleInitAll(); /*初始化所有粒子*/<br />extern void particleMainLoop(); /*主迴圈 */<br />extern void particleSetNumber(GLuint num); /*設定粒子總數*/<br />extern void particleSetColorArray(GLint array[][3],GLuint count); /*設定顏色*/<br />extern void particleSetDefaultStyle(GLuint mode); /*切換到預設風格*/<br />#endif<br /> 這是Particle.c.

/*<br /> * Particle.c<br /> * GL_PARTICLE_SYSTEM<br /> *<br /> * Created by Jackie Deng on 10-1-22.<br /> * Copyright 2010 dsd. All rights reserved.<br /> *<br /> */<br />//////////////////////////////////////////////////////<br />//使用說明:<br />//基於openGL的c語言粒子系統<br />//開始調用particleSysStartUp()函數初始化<br />//通過調用particleSetDefaultStyle(mode)使用內建的風格<br />//通過調用particleInitCallBack() 綁定自訂初始化回調<br />//通過調用particleDisplayCallBack() 綁定自訂渲染函數<br />//通過調用particleUpdataCallBack() 綁定自訂更新函數<br />//回呼函數原型為 GLvoid callBackFunction(Particle *q);<br />//將particleMainLoop()放在openGL的更新函數中<br />//完成<br />//////////////////////////////////////////////////////<br />#include "Particle.h"<br />#include <stdio.h><br />#include <stdlib.h><br />#include <math.h></p><p>GLuint g_particleMaxNumber = MAX_PARTICLE_NUM; //螢幕上最大粒子數<br />Particle g_particles[MAX_PARTICLE_NUM]; //粒子集合<br />GLuint g_colorCount; //顏色總數<br />GLint (*g_colorArray)[3]; //顏色數組指標<br />GLfloat slowDown = 0.5f;//衰減因子</p><p>////////////////////////////////////////////////////////<br />/* 回呼函數指標 分別是初始粒子開始狀態 渲染粒子 更新例子狀態的回呼函數指標 */<br />GLvoid (*pInitFunction)(Particle *q);<br />GLvoid (*pDisplayFunction)(Particle *q);<br />GLvoid (*pUpdataFunction)(Particle *q);<br />////////////////////////////////////////////////////////<br />/* 列印*/<br />void trace(char * str)<br />{<br />printf("Trace:[%s]/n",str);<br />}<br />////////////////////////////////////////////////////////<br />/* 預設顏色集合 */<br />GLint defaultColor[][10][3] =<br />{<br />/* for star */<br />255,0,255,<br />230,0,255,<br />205,0,255,<br />180,0,255,<br />155,0,255,<br />120,0,255,<br />95,0,255,<br />70,0,255,<br />45,0,255,<br />20,0,255,<br />/* for fire */<br />255,20,0,<br />255,45,0,<br />255,70,0,<br />255,95,0,<br />255,120,0,<br />255,155,0,<br />255,180,0,<br />255,205,0,<br />255,230,0,<br />255,255,0,<br />/* for Rainbow */<br />20,20,20,<br />45,45,45,<br />70,70,70,<br />95,95,95,<br />120,120,120,<br />155,155,155,<br />180,180,180,<br />205,205,205,<br />230,230,230,<br />255,255,255,<br />};<br />////////////////////////////////////////////////////////<br />/* 預設風格供測試調用 */<br />//星星 發射<br />void StarInitFunction(Particle *q)<br />{<br />q->active = GL_TRUE;<br />q->life = 1.0f;<br />q->fade = rand()%1000 * 0.0002f;<br />q->r = g_colorArray[g_colorCount-1][0]/255.0f;<br />q->g = g_colorArray[g_colorCount-1][1]/255.0f;<br />q->b = g_colorArray[g_colorCount-1][2]/255.0f;<br />q->x = 0;<br />q->y = 0;<br />q->z = 0;<br />q->xs = 5 - rand()%10;<br />q->ys = 5 - rand()%10;<br />q->zs = 1.01f;<br />q->xg = 0;<br />q->yg = -0.05f;<br />q->zg = 0.5;<br />}<br />/* 火焰 */<br />void FireInitFunction(Particle *q)<br />{<br />q->active = GL_TRUE;<br />q->life = rand()%100 * 0.01f; //1.0f;<br />q->fade = 0.006f;<br />q->r = g_colorArray[g_colorCount-1][0]/255.0f;<br />q->g = g_colorArray[g_colorCount-1][1]/255.0f;<br />q->b = g_colorArray[g_colorCount-1][2]/255.0f;<br />q->x = 20 - rand()%400*0.1;<br />q->y = 0;<br />q->z = 0;<br />q->xs = q->x /25;<br />q->ys = 1.9;<br />q->zs = 0;<br />q->xg = 0;<br />q->yg = 0;<br />q->zg = 0;</p><p>q->xg = (fabs(q->xs)/75) * (q->xs > 0? -1:1);<br />}<br />/* 雪球 */<br />void RainBowInitFunction(Particle *q)<br />{<br />q->active = GL_TRUE;<br />q->life = 1.0f;<br />q->fade = (1 + rand()%40)*0.001f;<br />q->r = g_colorArray[g_colorCount-1][0]/255.0f;<br />q->g = g_colorArray[g_colorCount-1][1]/255.0f;<br />q->b = g_colorArray[g_colorCount-1][2]/255.0f;<br />q->x = -300 + rand()%200;<br />q->y = 300 + rand()%50;<br />q->z = 0;<br />q->xs = 0;<br />q->ys = -(2 + rand()%5);<br />q->zs = (rand()%5)*0.01f;</p><p>q->xg = (rand()%10)*0.01f;<br />q->yg = -0.01f;<br />q->zg = (rand()%10)*0.01f;</p><p>}<br />/* 彩虹球更新 */<br />void RainBowUpdateFunction(Particle *particle)<br />{<br />if(particle->life < 0.0f)<br />{<br />pInitFunction(particle);<br />}<br />else<br />{//更新位置<br />particle->x += particle->xs*slowDown;<br />particle->y += particle->ys*slowDown;<br />particle->z += particle->zs*slowDown;</p><p>//更新速度<br />particle->xs += particle->xg;<br />particle->ys += particle->yg;<br />particle->zs += particle->zg;</p><p>//更新生命<br />particle->life -= particle->fade;</p><p>//更新顏色<br />GLuint colorPos = (GLuint)(particle->life * (g_colorCount -1));<br />particle->r = g_colorArray[colorPos][0]/255.0f;<br />particle->g = g_colorArray[colorPos][1]/255.0f;<br />particle->b = g_colorArray[colorPos][2]/255.0f;</p><p>}<br />}<br />////////////////////////////////////////////////////////<br />//預設的顯示函數 小球<br />void particleDefaultDisplayCallBack(Particle *q)<br />{<br />glColor4f(q->r, q->g, q->b,q->life);<br />//glPointSize(10 * q->life);</p><p>glBegin(GL_POINTS);<br />glVertex3f(q->x, q->y, q->z);</p><p>glEnd();<br />}<br />////////////////////////////////////////////////////////<br />/* 設定回呼函數*/<br />void particleInitCallBack(GLvoid (*p)(Particle * q) )<br />{<br />trace("設定初始化回調");<br />pInitFunction = p;</p><p>//初始化所有點<br />particleInitAll();<br />}<br />void particleDisplayCallBack(GLvoid (*p)(Particle *q))<br />{<br />trace("設定渲染回調");<br />pDisplayFunction = p;<br />}<br />void particleUpdateCallBack(GLvoid (*p)(Particle *q))<br />{<br />trace("設定更新回調");<br />pUpdataFunction = p;<br />}<br />////////////////////////////////////////////////////////<br />/* 設定粒子數量,如果超出合法範圍則設為最大值的一半 */<br />void particleSetNumber(GLuint num)<br />{<br />if(num <= 0 || num >= MAX_PARTICLE_NUM)<br />{<br />trace("數量錯誤,設為最大限制的一半");<br />num = MAX_PARTICLE_NUM/2;<br />}<br />else<br />g_particleMaxNumber = num;<br />}<br />/* 更新粒子狀態,如果生命週期結束,則再次初始化它 */<br />void particleDefalutUpdates(Particle * particle)<br />{</p><p>if(particle->life < 0.0f)<br />{<br />pInitFunction(particle);<br />}<br />else<br />{//更新位置<br />particle->x += particle->xs*slowDown;<br />particle->y += particle->ys*slowDown;<br />particle->z += particle->zs*slowDown;</p><p>//更新速度<br />particle->xs += particle->xg;<br />particle->ys += particle->yg;<br />particle->zs += particle->zg;</p><p>//更新生命<br />particle->life -= particle->fade;</p><p>//更新顏色<br />GLuint colorPos = (GLuint)(particle->life * (g_colorCount -1));<br />particle->r = g_colorArray[colorPos][0]/255.0f;<br />particle->g = g_colorArray[colorPos][1]/255.0f;<br />particle->b = g_colorArray[colorPos][2]/255.0f;<br />}<br />}</p><p>/* 第一次初始化所有粒子 */<br />void particleInitAll()<br />{<br />int i;<br />for(i = 0; i < g_particleMaxNumber; i++)<br />{<br />pInitFunction(&g_particles[i]);<br />printf("[%d - %f]/n",i,g_particles[i].fade);<br />}<br />}</p><p>/* 粒子主迴圈 調用顯示 並且更新狀態 */<br />void particleMainLoop()<br />{<br />int i;<br />for(i = 0; i < g_particleMaxNumber; i++)<br />{<br />pDisplayFunction(&g_particles[i]);</p><p>pUpdataFunction(&g_particles[i]);<br />}<br />}<br />/* 設定顏色數組 */<br />void particleSetColorArray(GLint array[][3],GLuint count)<br />{</p><p>g_colorArray = array;<br />g_colorCount = count;<br />}<br />/* 設定已有風格 */<br />void particleSetDefaultStyle(GLuint mode)<br />{<br />pDisplayFunction = particleDefaultDisplayCallBack;<br />pUpdataFunction = particleDefalutUpdates;</p><p>switch (mode)<br />{<br />case PSTYLE_STAR:<br />pInitFunction = StarInitFunction;<br />break;<br />case PSTYLE_FIRE:<br />pInitFunction = FireInitFunction;<br />break;<br />case PSTYLE_SNOW:<br />pInitFunction = RainBowInitFunction;<br />pUpdataFunction = RainBowUpdateFunction;<br />break;<br />default:<br />break;<br />}</p><p>particleSetColorArray(defaultColor[mode],10);<br />}<br />/* 初始化粒子系統 */<br />void particleSysStartUp()<br />{<br />//賦值預設顯示函數<br />particleSetDefaultStyle(PSTYLE_STAR);</p><p>//初始化所有點<br />particleInitAll();<br />} 

  為什麼我要用c語言寫,因為我在家使用的是vs IDE,在公司使用的是xCode,一個用c++,一個用objective-c,但是2者都包括c,所以用c來寫可以方便的為2者服務,這樣多好.在這裡面我寫了3個效果.可以調用particleSetDefaultStyle來調用,當示範好了,只要設定自己的回呼函數,就可以使用自己的方式來初始化,渲染以及更新粒子系統了,這個版本暫時只能支援1組粒子效果的顯示,接下來將把粒子集合與之分離,變成獨立的資料結構,然後位粒子系統添加一個粒子列隊,這樣就可以支援多組粒子效果同時在螢幕上顯示了.就這樣把.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.