2
// Book: OpenGL(R) ES 2.0 Programming Guide
3
// Authors: Aaftab Munshi, Dan Ginsburg, Dave Shreiner
5
// ISBN-13: 9780321502797
6
// Publisher: Addison-Wesley Professional
7
// URLs: http://safari.informit.com/9780321563835
8
// http://www.opengles-book.com
13
// This is an example that demonstrates rendering a particle system
14
// using a vertex shader and point sprites.
20
#define NUM_PARTICLES 2000
21
#define PARTICLE_SIZE 7
23
int randomTemp = 8765;
25
int curr = randomTemp;
26
randomTemp = (1140671485 * randomTemp + 12820163) % 4294967296;
27
return ((float)curr) / 4294967296;
32
// Handle to a program object
35
// Attribute locations
37
GLint startPositionLoc;
43
GLint centerPositionLoc;
49
// Particle vertex data
50
GLfloat particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
59
// Load texture from disk
61
GLuint LoadTexture ( char *fileName )
65
char *buffer = esLoadTGA ( fileName, &width, &height );
70
esLogMessage ( "Error loading (%s) image.\n", fileName );
74
glGenTextures ( 1, &texId );
75
glBindTexture ( GL_TEXTURE_2D, texId );
77
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer );
78
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
79
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
80
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
81
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
90
// Initialize the shader and program object
92
int Init ( ESContext *esContext )
94
UserData *userData = esContext->userData;
98
"uniform float u_time; \n"
99
"uniform vec3 u_centerPosition; \n"
100
"attribute float a_lifetime; \n"
101
"attribute vec3 a_startPosition; \n"
102
"attribute vec3 a_endPosition; \n"
103
"varying float v_lifetime; \n"
106
" if ( u_time <= a_lifetime ) \n"
108
" gl_Position.xyz = a_startPosition + \n"
109
" (u_time * a_endPosition); \n"
110
" gl_Position.xyz += u_centerPosition; \n"
111
" gl_Position.w = 1.0; \n"
114
" gl_Position = vec4( -1000, -1000, 0, 0 ); \n"
115
" v_lifetime = 1.0 - ( u_time / a_lifetime ); \n"
116
" v_lifetime = clamp ( v_lifetime, 0.0, 1.0 ); \n"
117
" gl_PointSize = ( v_lifetime * v_lifetime ) * 40.0; \n"
120
GLbyte fShaderStr[] =
121
"precision mediump float; \n"
122
"uniform vec4 u_color; \n"
123
"varying float v_lifetime; \n"
124
"uniform sampler2D s_texture; \n"
128
" texColor = texture2D( s_texture, gl_PointCoord ); \n"
129
" gl_FragColor = vec4( u_color ) * texColor; \n"
130
" gl_FragColor.a *= v_lifetime; \n"
133
// Load the shaders and get a linked program object
134
userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
136
// Get the attribute locations
137
userData->lifetimeLoc = glGetAttribLocation ( userData->programObject, "a_lifetime" );
138
userData->startPositionLoc = glGetAttribLocation ( userData->programObject, "a_startPosition" );
139
userData->endPositionLoc = glGetAttribLocation ( userData->programObject, "a_endPosition" );
141
// Get the uniform locations
142
userData->timeLoc = glGetUniformLocation ( userData->programObject, "u_time" );
143
userData->centerPositionLoc = glGetUniformLocation ( userData->programObject, "u_centerPosition" );
144
userData->colorLoc = glGetUniformLocation ( userData->programObject, "u_color" );
145
userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" );
147
glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
149
// Fill in particle data array
150
for ( i = 0; i < NUM_PARTICLES; i++ )
152
GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE];
154
// Lifetime of particle
155
(*particleData++) = myrandom();
157
// End position of particle
158
(*particleData++) = myrandom() * 2 - 1.0f;
159
(*particleData++) = myrandom() * 2 - 1.0f;
160
(*particleData++) = myrandom() * 2 - 1.0f;
162
// Start position of particle
163
(*particleData++) = myrandom() * 0.25 - 0.125f;
164
(*particleData++) = myrandom() * 0.25 - 0.125f;
165
(*particleData++) = myrandom() * 0.25 - 0.125f;
168
glGenBuffers(1, &userData->vertexObject);
169
glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
170
glBufferData( GL_ARRAY_BUFFER, NUM_PARTICLES * PARTICLE_SIZE * 4, userData->particleData, GL_STATIC_DRAW );
172
// Initialize time to cause reset on first update
173
userData->time = 1.0f;
175
userData->textureId = LoadTexture ( "smoke.tga" );
176
if ( userData->textureId <= 0 )
185
// Update time-based variables
187
void Update ( ESContext *esContext, float deltaTime )
190
UserData *userData = esContext->userData;
192
userData->time += deltaTime;
194
if ( userData->time >= 1.0f )
199
userData->time = 0.0f;
201
// Pick a new start location and color
202
centerPos[0] = myrandom() - 0.5f;
203
centerPos[1] = myrandom() - 0.5f;
204
centerPos[2] = myrandom() - 0.5f;
206
glUniform3fv ( userData->centerPositionLoc, 1, ¢erPos[0] );
209
color[0] = myrandom() * 0.5 + 0.5f;
210
color[1] = myrandom() * 0.5 + 0.5f;
211
color[2] = myrandom() * 0.5 + 0.5f;
214
glUniform4fv ( userData->colorLoc, 1, &color[0] );
217
// Load uniform time variable
218
glUniform1f ( userData->timeLoc, userData->time );
222
// Draw a triangle using the shader pair created in Init()
224
void Draw ( ESContext *esContext )
226
UserData *userData = esContext->userData;
229
glViewport ( 0, 0, esContext->width, esContext->height );
231
// Clear the color buffer
232
glClear ( GL_COLOR_BUFFER_BIT );
234
// Use the program object
235
glUseProgram ( userData->programObject );
237
// Load the vertex attributes
238
glBindBuffer( GL_ARRAY_BUFFER, userData->vertexObject );
239
glVertexAttribPointer ( userData->lifetimeLoc, 1, GL_FLOAT,
240
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
243
glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
244
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
247
glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
248
GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
252
glEnableVertexAttribArray ( userData->lifetimeLoc );
253
glEnableVertexAttribArray ( userData->endPositionLoc );
254
glEnableVertexAttribArray ( userData->startPositionLoc );
256
glEnable ( GL_BLEND );
257
glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
260
glActiveTexture ( GL_TEXTURE0 );
261
glBindTexture ( GL_TEXTURE_2D, userData->textureId );
262
//glEnable ( GL_TEXTURE_2D );
264
// Set the sampler texture unit to 0
265
glUniform1i ( userData->samplerLoc, 0 );
267
Update ( esContext, 133 * 0.001125 );
269
glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
271
eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
277
void ShutDown ( ESContext *esContext )
279
UserData *userData = esContext->userData;
281
// Delete texture object
282
glDeleteTextures ( 1, &userData->textureId );
284
// Delete program object
285
glDeleteProgram ( userData->programObject );
289
int main ( int argc, char *argv[] )
294
esInitContext ( &esContext );
295
esContext.userData = &userData;
297
esCreateWindow ( &esContext, "ParticleSystem", 320, 240, ES_WINDOW_RGB );
299
if ( !Init ( &esContext ) )
302
esRegisterDrawFunc ( &esContext, Draw );
303
// esRegisterUpdateFunc ( &esContext, Update );
307
//esMainLoop ( &esContext );
309
ShutDown ( &esContext );