Mar 10
25
Next: 33. OpenGL Animating Textures
Today we are going to be working with particle engines. The one here
is pretty basic but extremely easy to use and expand on. I have even
added texture masking for weirdly shaped particles. But unfortunately
I am yet to change the color of these on-the-fly without disrupting the
masking so for the moment, you cannot change the color to a number such as
0.1, 0.2, 0.3… it must be a whole number. Eg: 1 or 0.
Anyway, lets get on with the tutorial.
————————————————————————
Section 1: Variables
First off, we need to declare our header files. For this project we need
#include <GL/gl.h>
#include <GL/glut.h>
#include <windows.h>
#include <stdio.h>
#include <math.h>
This first variable I am going to use to hold the number of particles
we will display on the screen at any one time.
const ParticleCount = 500
Of course we also need something to hold our textures.
GLfloat texture[10];
Now here, I am creating a Type called PARTICLES which will hold all
our information for our particles.
typedef struct
{
The X position
double Xpos;
The Y position
double Ypos;
The Z position
double Zpos;
The movement on the X axis while being displayed
double Xmov;
The movement on the Z axis while being displayed
double Zmov;
The amount of Red within the object
double Red;
The amount of Green within the object
double Green;
The amount of Blue within the object
double Blue;
The angle of rotation
double Direction;
How fast it accelerates upwards
double Acceleration;
How fast it decelerates downwards
double Deceleration;
How much we wish to scale it
double Scalez;
}PARTICLES;
And now we will create a variable that will hold each of the PARTICLES
information for each actual Particle
PARTICLES Particle[ParticleCount];
————————————————————————
Section 2: Creation
To create the particles I am going to call the function glCreateParticles
during the initialization section of the code with:
glCreateParticles
Now for the creation function:
void glCreateParticles (void) {
This will be a temporary variable to cycle through our particles
int i;
We are going to loop through our particles until we reach the end
for (i = 1; i < ParticleCount; i++)
{
Set the inital X position to 0
Particle[i].Xpos = 0;
Set the inital Y position to -5
Particle[i].Ypos = -5;
Set the inital Z position to -5
Particle[i].Zpos = -5;
Set the amount of movement on the X axis to a random number, we dont want
all our particles doing the same thing
Particle[i].Xmov = (((((((2 – 1 + 1) * rand()%11) + 1) – 1 + 1) * rand()%11) + 1) * 0.005) – (((((((2 – 1 + 1) * rand()%11) + 1) – 1 + 1) * rand()%11) + 1) * 0.005);
Set the amount of movement on the Z axis to a random number, as above, we dont
want all our particles doing the same thing
Particle[i].Zmov = (((((((2 – 1 + 1) * rand()%11) + 1) – 1 + 1) * rand()%11) + 1) * 0.005) – (((((((2 – 1 + 1) * rand()%11) + 1) – 1 + 1) * rand()%11) + 1) * 0.005);
Set the amount of Red to 1
Particle[i].Red = 1;
Set the amount of Green to 1
Particle[i].Green = 1;
Set the amount of Blue to 1
Particle[i].Blue = 1;
Scale the particle to 1 quarter of its original size
Particle[i].Scalez = 0.25;
Set the initial rotation angle to 0
Particle[i].Direction = 0;
Set the amount of acceleration to a random number so they climb to different
heights
Particle[i].Acceleration = ((((((8 – 5 + 2) * rand()%11) + 5) – 1 + 1) * rand()%11) + 1) * 0.02;
Decrease their acceleration by 0.0025. They will slow down at a constant
rate but you will not see a difference
Particle[i].Deceleration = 0.0025;
}
}
—————————————————————————-
Section 3: Updating the Particles
The particles would not be effective, if they stayed at their inital state, so
we want them to change and acctually move. I am doing this by calling:
glUpdateParticles in my Display function.
void glUpdateParticles (void) {
Once again, another temporary variable to handle the cycle through the particles
int i;
Loop through all of the particles
for (i = 1; i < ParticleCount; i++)
{
Set the color of the current particle
glColor3f (Particle[i].Red, Particle[i].Green, Particle[i].Blue);
Move the particle on the Y axes, adding on the amount of acceleration
and then subtracting the rate of deceleration
Particle[i].Ypos = Particle[i].Ypos + Particle[i].Acceleration – Particle[i].Deceleration;
Increase the deceleration rate so the particle falls gaining speed
Particle[i].Deceleration = Particle[i].Deceleration + 0.0025;
Move the particle on the X axis
Particle[i].Xpos = Particle[i].Xpos + Particle[i].Xmov;
Move the particle on the Z axis
Particle[i].Zpos = Particle[i].Zpos + Particle[i].Zmov;
Rotate the particle
Particle[i].Direction = Particle[i].Direction + ((((((int)(0.5 – 0.1 + 0.1) * rand()%11) + 1) – 1 + 1) * rand()%11) + 1);
Now here I am saying that if the particle goes beneath its initial height
which I set earlier to -5, then it will restart the particle changing some
of the variables.
if (Particle[i].Ypos < -5)
{
Set the X position
Particle[i].Xpos = 0;
Set the Y position
Particle[i].Ypos = -5;
Set the Z position
Particle[i].Zpos = -5;
Set the amount of Red
Particle[i].Red = 1;
Set the amount of Green
Particle[i].Green = 1;
Set the amount of Blue
Particle[i].Blue = 1;
Set the angle of rotation
Particle[i].Direction = 0;
Adjust the Acceleration rate to another random number
Particle[i].Acceleration = ((((((8 – 5 + 2) * rand()%11) + 5) – 1 + 1) * rand()%11) + 1) * 0.02;
Reset the Deceleration rate
Particle[i].Deceleration = 0.0025;
}
}
}
—————————————————————————-
Section 4: Drawing the Particles
To draw the particles, I am calling the following function: glDrawParticle
from within the Display function, after the updating function.
void glDrawParticles (void) {
Yet another temporary variable for our cycles
int i;
Looping through our particles again
for (i = 1; i < ParticleCount; i++)
{
Distinguish the start of our current particle, we do not wish for them
all to be affected by the ones prior
glPushMatrix();
Translate the particle on the X, Y and Z axis accordingly
glTranslatef (Particle[i].Xpos, Particle[i].Ypos, Particle[i].Zpos);
Rotate the particle
glRotatef (Particle[i].Direction – 90, 0, 0, 1);
Scale the particle
glScalef (Particle[i].Scalez, Particle[i].Scalez, Particle[i].Scalez);
Disable Depth Testing so our masking appears as one
glDisable (GL_DEPTH_TEST);
Enable blending
glEnable (GL_BLEND);
Set the blending function to Take our Destination Colour and combine it with
Zero which is Black
glBlendFunc (GL_DST_COLOR, GL_ZERO);
Bind our mask
glBindTexture (GL_TEXTURE_2D, texture[0]);
Draw our shape
glBegin (GL_QUADS);
glTexCoord2d (0, 0);
glVertex3f (-1, -1, 0);
glTexCoord2d (1, 0);
glVertex3f (1, -1, 0);
glTexCoord2d (1, 1);
glVertex3f (1, 1, 0);
glTexCoord2d (0, 1);
glVertex3f (-1, 1, 0);
glEnd();
Then set out blending function to combine White with White
glBlendFunc (GL_ONE, GL_ONE);
Bind our texture
glBindTexture (GL_TEXTURE_2D, texture[1]);
Draw the shape
glBegin (GL_QUADS);
glTexCoord2d (0, 0);
glVertex3f (-1, -1, 0);
glTexCoord2d (1, 0);
glVertex3f (1, -1, 0);
glTexCoord2d (1, 1);
glVertex3f (1, 1, 0);
glTexCoord2d (0, 1);
glVertex3f (-1, 1, 0);
glEnd();
Re-enable Depth Testing
glEnable(GL_DEPTH_TEST);
End the changes to the current object
glPopMatrix();
}
}
}
————————————————————————-
And there we have it, a simple particle engine that pumps out 500 particles
at a steady framerate of 80 frames per second.
If you have any questions, feel free to email me at swiftless@gmail.com
|
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209. 210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223. 224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237. 238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. |
#include <GL/gl.h> #include <GL/glut.h> #include <windows.h> #include <stdio.h> #include <math.h> GLfloat texture[10]; const ParticleCount = 500; typedef struct PARTICLES Particle[ParticleCount]; GLuint LoadTextureRAW( const char * filename, int width, void square (void) { void glCreateParticles (void) { void glUpdateParticles (void) { glColor3f (Particle[i].Red, Particle[i].Green, Particle[i].Ypos = Particle[i].Ypos + Particle[i] Particle[i].Xpos = Particle[i].Xpos + Particle[i].Xmov; Particle[i].Direction = Particle[i].Direction + ((((((int if (Particle[i].Ypos < -5) } void glDrawParticles (void) { glTranslatef (Particle[i].Xpos, Particle[i].Ypos, Particle[i].Zpos); glBegin (GL_QUADS); glPopMatrix(); } void display (void) { void init (void) { glCreateParticles(); texture[0] = LoadTextureRAW( “particle_mask.raw”,256,256 void reshape (int w, int h) { int main (int argc, char **argv) { //function to load the RAW file GLuint LoadTextureRAW( const char * filename, int width, file = fopen( filename, “rb” ); data = (unsigned char *)malloc( width * height * 3 ); fread( data, width * height * 3, 1, file ); glGenTextures(1, &texture ); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height, free( data ); return texture; void FreeTexture( GLuint texture ) |
Download Texture Mask(.RAW file)
Download Texture Mask(.BMP file)
Related posts:
- 35. OpenGL Tiling Engine
- 22. OpenGL Camera
- 23. OpenGL Camera Part 2
- 20. OpenGL MipMap Generation
- 33. OpenGL Animating Textures
Next: 33. OpenGL Animating Textures