资源描述
OpenGL进阶(六)-粒子系统
一、提要
有一款例子特效软件叫做particle illution,在影视后期和游戏制作领域都可以用到,相信很多人都接触过,今天我们用SDL+OpenGL来实现例子效果。
确保你搞定了物理模拟的代码!
代码下载
二、原理简介
所谓的例子系统,就是同时控制一大堆类似的对象,这些对象可能是形体,可能是图片,有着不同的特征(寿命,速度,位置)。有了之前的基础,我们可以很轻易地搞定今天的东西。
三、代码清单
首先是粒子的头文件,我直接写成结构体了,里面有一些基本的属性。
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particle.h
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.20
9. *****************************************************************************/
10. #ifndef PARTICLE_H
11. #define PARTICLE_H
12. #include "vector3d.h"
13. typedef struct
14. {
15. float r;
16. float g;
17. float b;
18. float alpha;
19. }Color;
20.
21. typedef struct
22. {
23. Vector3D position;
24. Vector3D velocity;
25. Vector3D acceleration;
26. Color color;
27. float age;
28. float life;
29. float size;
30. }Particle;
31.
32. #endif // PARTICLE_H
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particle.h
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.20
9. *****************************************************************************/
10. #ifndef PARTICLE_H
11. #define PARTICLE_H
12. #include "vector3d.h"
13. typedef struct
14. {
15. float r;
16. float g;
17. float b;
18. float alpha;
19. }Color;
20.
21. typedef struct
22. {
23. Vector3D position;
24. Vector3D velocity;
25. Vector3D acceleration;
26. Color color;
27. float age;
28. float life;
29. float size;
30. }Particle;
31.
32. #endif // PARTICLE_H
我们用球体来模拟例子,所以size表示的就是球体的半径。
接下来是粒子系统类(类名拼写错了*-*)
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particalsystem.h
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.20
9. *****************************************************************************/
10.
11. #ifndef PARTICALSYSTEM_H
12. #define PARTICALSYSTEM_H
13. #include <vector>
14. #include <math.h>
15. #include <time.h>
16. #include <stdlib.h>
17. #include <iostream>
18. #include <GL/gl.h>
19. #include <GL/glu.h>
20. #include "particle.h"
21. #define PI 3.1415926
22. using namespace std;
23. class ParticalSystem
24. {
25. public:
26. ParticalSystem();
27. ParticalSystem(int _count,float _gravity){ptlCount=_count;gravity=_gravity;};
28. void init();
29. void simulate(float dt);
30. void aging(float dt);
31. void applyGravity();
32. void kinematics(float dt);
33. void render();
34. virtual ~ParticalSystem();
35. protected:
36. private:
37. int ptlCount;
38. float gravity;
39. GLUquadricObj *mySphere;
40. vector<Particle> particles;
41. };
42.
43. #endif // PARTICALSYSTEM_H
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particalsystem.h
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.20
9. *****************************************************************************/
10.
11. #ifndef PARTICALSYSTEM_H
12. #define PARTICALSYSTEM_H
13. #include <vector>
14. #include <math.h>
15. #include <time.h>
16. #include <stdlib.h>
17. #include <iostream>
18. #include <GL/gl.h>
19. #include <GL/glu.h>
20. #include "particle.h"
21. #define PI 3.1415926
22. using namespace std;
23. class ParticalSystem
24. {
25. public:
26. ParticalSystem();
27. ParticalSystem(int _count,float _gravity){ptlCount=_count;gravity=_gravity;};
28. void init();
29. void simulate(float dt);
30. void aging(float dt);
31. void applyGravity();
32. void kinematics(float dt);
33. void render();
34. virtual ~ParticalSystem();
35. protected:
36. private:
37. int ptlCount;
38. float gravity;
39. GLUquadricObj *mySphere;
40. vector<Particle> particles;
41. };
42.
43. #endif // PARTICALSYSTEM_H
解释一下几个重要函数:
init:做一些例子系统的初始化工作;
aging:计算粒子的年龄;
applyGravity:向粒子施加重力;
kinematics:这个单词的意思是运动学,所以就是负责管理粒子的加速,位移;
simulate:例子模拟的总负责函数;
render:渲染粒子;
然后来看函数是怎么实现的:
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particalsystem.Cpp
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.22
9. *****************************************************************************/
10.
11. #include "particalsystem.h"
12.
13. ParticalSystem::ParticalSystem()
14. {
15. //ctor
16. }
17.
18. ParticalSystem::~ParticalSystem()
19. {
20. //dtor
21. }
22.
23. void ParticalSystem::init()
24. {
25. int i;
26. srand(unsigned(time(0)));
27. Color colors[3]={{0,0,1,1},{1,0,1,1}};
28. for(i=0;i<ptlCount;i++)
29. {
30. //theta =(rand()%361)/360.0* 2*PI;
31. Particle tmp={Vector3D(0,0,0),Vector3D(((rand()%50)-26.0f),((rand()%50)-26.0f),((rand()%50)-26.0f)),Vector3D(0,0,0),colors[rand()%2],0.0f,0.5+0.05*(rand()%10),0.3f};
32. particles.push_back(tmp);
33. }
34. mySphere=gluNewQuadric();
35. }
36. void ParticalSystem::simulate(float dt)
37. {
38. aging(dt);
39. applyGravity();
40. kinematics(dt);
41. }
42. void ParticalSystem::aging(float dt)
43. {
44. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
45. {
46. iter->age+=dt;
47. if(iter->age>iter->life)
48. {
49. iter->position=Vector3D(0,0,0);
50. iter->age=0.0;
51. iter->velocity=Vector3D(((rand()%30)-15.0f),((rand()%30)-11.0f),((rand()%30)-15.0f));
52. }
53. }
54. }
55. void ParticalSystem::applyGravity()
56. {
57. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
58. iter->acceleration=Vector3D(0,gravity,0);
59. }
60.
61. void ParticalSystem::kinematics(float dt)
62. {
63. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
64. {
65. iter->position = iter->position+iter->velocity*dt;
66. iter->velocity = iter->velocity+iter->acceleration*dt;
67. }
68. }
69. void ParticalSystem::render()
70. {
71.
72. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
73. {
74. float alpha = 1 - iter->age / iter->life;//calculate the alpha value according to the age of particle.
75. Vector3D tmp=iter->position;
76. glColor4f(iter->color.r,iter->color.g,iter->color.b,alpha);
77. glPushMatrix();
78. glTranslatef(tmp.x,tmp.y,tmp.z);
79. gluSphere(mySphere,iter->size, 32, 16);
80. glPopMatrix();
81. }
82.
83. }
[cpp] view plaincopy
1. /*****************************************************************************
2. Copyright: 2012, ustc All rights reserved.
3. contact:k283228391@
4. File name: particalsystem.Cpp
5. Description:Partical in opengl.
6. Author:Silang Quan
7. Version: 1.0
8. Date: 2012.12.22
9. *****************************************************************************/
10.
11. #include "particalsystem.h"
12.
13. ParticalSystem::ParticalSystem()
14. {
15. //ctor
16. }
17.
18. ParticalSystem::~ParticalSystem()
19. {
20. //dtor
21. }
22.
23. void ParticalSystem::init()
24. {
25. int i;
26. srand(unsigned(time(0)));
27. Color colors[3]={{0,0,1,1},{1,0,1,1}};
28. for(i=0;i<ptlCount;i++)
29. {
30. //theta =(rand()%361)/360.0* 2*PI;
31. Particle tmp={Vector3D(0,0,0),Vector3D(((rand()%50)-26.0f),((rand()%50)-26.0f),((rand()%50)-26.0f)),Vector3D(0,0,0),colors[rand()%2],0.0f,0.5+0.05*(rand()%10),0.3f};
32. particles.push_back(tmp);
33. }
34. mySphere=gluNewQuadric();
35. }
36. void ParticalSystem::simulate(float dt)
37. {
38. aging(dt);
39. applyGravity();
40. kinematics(dt);
41. }
42. void ParticalSystem::aging(float dt)
43. {
44. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
45. {
46. iter->age+=dt;
47. if(iter->age>iter->life)
48. {
49. iter->position=Vector3D(0,0,0);
50. iter->age=0.0;
51. iter->velocity=Vector3D(((rand()%30)-15.0f),((rand()%30)-11.0f),((rand()%30)-15.0f));
52. }
53. }
54. }
55. void ParticalSystem::applyGravity()
56. {
57. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
58. iter->acceleration=Vector3D(0,gravity,0);
59. }
60.
61. void ParticalSystem::kinematics(float dt)
62. {
63. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
64. {
65. iter->position = iter->position+iter->velocity*dt;
66. iter->velocity = iter->velocity+iter->acceleration*dt;
67. }
68. }
69. void ParticalSystem::render()
70. {
71.
72. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
73. {
74. float alpha = 1 - iter->age / iter->life;//calculate the alpha value according to the age of particle.
75. Vector3D tmp=iter->position;
76. glColor4f(iter->color.r,iter->color.g,iter->color.b,alpha);
77. glPushMatrix();
78. glTranslatef(tmp.x,tmp.y,tmp.z);
79. gluSphere(mySphere,iter->size, 32, 16);
80. glPopMatrix();
81. }
82.
83. }
实现还是比较简单的,下面渲染看一下^^.
首先要在initGL函数中添加两句话:
[cpp] view plaincopy
1. glEnable(GL_BLEND);
2. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
[cpp] view plaincopy
1. glEnable(GL_BLEND);
2. glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
这样透明度才会有效。
接着初始化一个例子系统,并对例子进行初始化:
[cpp] view plaincopy
1. ParticalSystem ps;
[cpp] view plaincopy
1. ParticalSystem ps;
[plain] view plaincopy
1. int main( int argc, char* argv[] )
2. {
3. // Color depth in bits of our window.
4. int flags= SDL_OPENGL|SDL_RESIZABLE;
5. //Set the SDL
6. initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);
7. //Set the OpenGL
8. initGL(SCREEN_WIDTH, SCREEN_HEIGHT );
9. ps=ParticalSystem(100,-15.0);
10. ps.init();
11. //main loop
12. while(true)
13. {
14. /* Process incoming events. */
15. handleEvents( );
16. ps.simulate(0.01);
17. /* Draw the screen. */
18. renderGL( );
19. }
20. return 0;
21. }
[plain] view plaincopy
1. int main( int argc, char* argv[] )
2. {
3. // Color depth in bits of our window.
4. int flags= SDL_OPENGL|SDL_RESIZABLE;
5. //Set the SDL
6. initSDL(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,flags);
7. //Set the OpenGL
8. initGL(SCREEN_WIDTH, SCREEN_HEIGHT );
9. ps=ParticalSystem(100,-15.0);
10. ps.init();
11. //main loop
12. while(true)
13. {
14. /* Process incoming events. */
15. handleEvents( );
16. ps.simulate(0.01);
17. /* Draw the screen. */
18. renderGL( );
19. }
20. return 0;
21. }
然后是渲染函数:
[cpp] view plaincopy
1. void renderGL()
2. {
3. // Clear the color and depth buffers.
4. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
5. // We don't want to modify the projection matrix. */
6. glMatrixMode( GL_MODELVIEW );
7. glLoadIdentity( );
8. // Move down the z-axis.
9. glTranslatef(0.0f,0.0f,-35.0f);
10. ps.render();
11. SDL_GL_SwapBuffers( );
12. }
[cpp] view plaincopy
1. void renderGL()
2. {
3. // Clear the color and depth buffers.
4. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
5. // We don't want to modify the projection matrix. */
6. glMatrixMode( GL_MODELVIEW );
7. glLoadIdentity( );
8. // Move down the z-axis.
9. glTranslatef(0.0f,0.0f,-35.0f);
10. ps.render();
11. SDL_GL_SwapBuffers( );
12. }
跑一下:
效果还是不错的~下面我们来实现一些更棒的效果!
四、动态模糊和碰撞检测
动态模糊的实现比较简单,主循环不再每次把整个画面清空,而是每帧画一个半透明的黑色长方形,就可以模拟动态模糊(motion blur)的效果。
将之前的
[cpp] view plaincopy
1. // Clear the color and depth buffers.
2. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
[cpp] view plaincopy
1. // Clear the color and depth buffers.
2. glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT );
改成
[cpp] view plaincopy
1. // Clear the depth buffers.
2. glClear(GL_DEPTH_BUFFER_BIT );
[cpp] view plaincopy
1. // Clear the depth buffers.
2. glClear(GL_DEPTH_BUFFER_BIT );
然后在例子系统的render函数中添加画矩形的代码:
[cpp] view plaincopy
1. void ParticalSystem::render()
2. {
3.
4. for(vector<Particle>::iterator iter=particles.begin();iter!=particles.end();iter++)
5. {
6. float alpha = 1 - iter->age / iter->life;
7. Vector3D tmp=iter->position;
8. glColor4f(iter->color.r,iter->color.g,iter->color.b,alpha);
9. //glColor4f(1.0f, 1.0f, 1.0f, 0.1);
10. glPushMatrix();
11. glTranslatef(tmp.x,tmp.y,tmp.z);
12. gluSphere(mySphere,iter->size, 32, 16);
13. glPopMatrix();
14. }
15.
16. //Motion blue
17. glColor4f(0.0f,0.0f,0.0f,0.1);
18. glBegin(GL_QUADS);
19. glVertex3f(-20.0f , -20.0f , 20.0f );
20. glVertex3f( 20.0f , -20.0f , 20.0f );
21. g
展开阅读全文