~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/glbook/Chapter_13/ParticleSystem/ParticleSystem.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// Book:      OpenGL(R) ES 2.0 Programming Guide
 
3
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
 
4
// ISBN-10:   0321502795
 
5
// ISBN-13:   9780321502797
 
6
// Publisher: Addison-Wesley Professional
 
7
// URLs:      http://safari.informit.com/9780321563835
 
8
//            http://www.opengles-book.com
 
9
//
 
10
 
 
11
// ParticleSystem.c
 
12
//
 
13
//    This is an example that demonstrates rendering a particle system
 
14
//    using a vertex shader and point sprites.
 
15
//
 
16
#include <stdlib.h>
 
17
#include <math.h>
 
18
#include "esUtil.h"
 
19
 
 
20
#define NUM_PARTICLES   2000
 
21
#define PARTICLE_SIZE   7
 
22
 
 
23
int randomTemp = 8765;
 
24
float myrandom() {
 
25
  int curr = randomTemp;
 
26
  randomTemp = (1140671485 * randomTemp + 12820163) % 4294967296;
 
27
  return ((float)curr) / 4294967296;
 
28
}
 
29
 
 
30
typedef struct
 
31
{
 
32
   // Handle to a program object
 
33
   GLuint programObject;
 
34
 
 
35
   // Attribute locations
 
36
   GLint  lifetimeLoc;
 
37
   GLint  startPositionLoc;
 
38
   GLint  endPositionLoc;
 
39
   
 
40
   // Uniform location
 
41
   GLint timeLoc;
 
42
   GLint colorLoc;
 
43
   GLint centerPositionLoc;
 
44
   GLint samplerLoc;
 
45
 
 
46
   // Texture handle
 
47
   GLuint textureId;
 
48
 
 
49
   // Particle vertex data
 
50
   GLfloat particleData[ NUM_PARTICLES * PARTICLE_SIZE ];
 
51
 
 
52
   // Current time
 
53
   float time;
 
54
 
 
55
  GLuint vertexObject;
 
56
} UserData;
 
57
 
 
58
///
 
59
// Load texture from disk
 
60
//
 
61
GLuint LoadTexture ( char *fileName )
 
62
{
 
63
   int width,
 
64
       height;
 
65
   char *buffer = esLoadTGA ( fileName, &width, &height );
 
66
   GLuint texId;
 
67
 
 
68
   if ( buffer == NULL )
 
69
   {
 
70
      esLogMessage ( "Error loading (%s) image.\n", fileName );
 
71
      return 0;
 
72
   }
 
73
 
 
74
   glGenTextures ( 1, &texId );
 
75
   glBindTexture ( GL_TEXTURE_2D, texId );
 
76
 
 
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 );
 
82
 
 
83
   free ( buffer );
 
84
 
 
85
   return texId;
 
86
}
 
87
 
 
88
 
 
89
///
 
90
// Initialize the shader and program object
 
91
//
 
92
int Init ( ESContext *esContext )
 
93
{
 
94
   UserData *userData = esContext->userData;
 
95
   int i;
 
96
   
 
97
   GLbyte vShaderStr[] =
 
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"
 
104
      "void main()                                          \n"
 
105
      "{                                                    \n"
 
106
      "  if ( u_time <= a_lifetime )                        \n"
 
107
      "  {                                                  \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"
 
112
      "  }                                                  \n"
 
113
      "  else                                               \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"
 
118
      "}";
 
119
      
 
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"
 
125
      "void main()                                          \n"
 
126
      "{                                                    \n"
 
127
      "  vec4 texColor;                                     \n"
 
128
      "  texColor = texture2D( s_texture, gl_PointCoord );  \n"
 
129
      "  gl_FragColor = vec4( u_color ) * texColor;         \n"
 
130
      "  gl_FragColor.a *= v_lifetime;                      \n"
 
131
      "}                                                    \n";
 
132
 
 
133
   // Load the shaders and get a linked program object
 
134
   userData->programObject = esLoadProgram ( vShaderStr, fShaderStr );
 
135
 
 
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" );
 
140
   
 
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" );
 
146
 
 
147
   glClearColor ( 0.0f, 0.0f, 0.0f, 1.0f );
 
148
 
 
149
   // Fill in particle data array
 
150
   for ( i = 0; i < NUM_PARTICLES; i++ )
 
151
   {
 
152
      GLfloat *particleData = &userData->particleData[i * PARTICLE_SIZE];
 
153
   
 
154
      // Lifetime of particle
 
155
      (*particleData++) = myrandom();
 
156
 
 
157
      // End position of particle
 
158
      (*particleData++) = myrandom() * 2 - 1.0f;
 
159
      (*particleData++) = myrandom() * 2 - 1.0f;
 
160
      (*particleData++) = myrandom() * 2 - 1.0f;
 
161
 
 
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;
 
166
   }
 
167
 
 
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 );
 
171
 
 
172
   // Initialize time to cause reset on first update
 
173
   userData->time = 1.0f;
 
174
 
 
175
   userData->textureId = LoadTexture ( "smoke.tga" );
 
176
   if ( userData->textureId <= 0 )
 
177
   {
 
178
      return FALSE;
 
179
   }
 
180
   
 
181
   return TRUE;
 
182
}
 
183
 
 
184
///
 
185
//  Update time-based variables
 
186
//
 
187
void Update ( ESContext *esContext, float deltaTime )
 
188
{
 
189
//  deltaTime = 0.1;
 
190
   UserData *userData = esContext->userData;
 
191
  
 
192
   userData->time += deltaTime;
 
193
 
 
194
   if ( userData->time >= 1.0f )
 
195
   {
 
196
      float centerPos[3];
 
197
      float color[4];
 
198
 
 
199
      userData->time = 0.0f;
 
200
 
 
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;
 
205
      
 
206
      glUniform3fv ( userData->centerPositionLoc, 1, &centerPos[0] );
 
207
 
 
208
      // Random color
 
209
      color[0] = myrandom() * 0.5 + 0.5f;
 
210
      color[1] = myrandom() * 0.5 + 0.5f;
 
211
      color[2] = myrandom() * 0.5 + 0.5f;
 
212
      color[3] = 1.0;
 
213
 
 
214
      glUniform4fv ( userData->colorLoc, 1, &color[0] );
 
215
   }
 
216
 
 
217
   // Load uniform time variable
 
218
   glUniform1f ( userData->timeLoc, userData->time );
 
219
}
 
220
 
 
221
///
 
222
// Draw a triangle using the shader pair created in Init()
 
223
//
 
224
void Draw ( ESContext *esContext )
 
225
{
 
226
   UserData *userData = esContext->userData;
 
227
      
 
228
   // Set the viewport
 
229
   glViewport ( 0, 0, esContext->width, esContext->height );
 
230
   
 
231
   // Clear the color buffer
 
232
   glClear ( GL_COLOR_BUFFER_BIT );
 
233
 
 
234
   // Use the program object
 
235
   glUseProgram ( userData->programObject );
 
236
 
 
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), 
 
241
                           0 );
 
242
   
 
243
   glVertexAttribPointer ( userData->endPositionLoc, 3, GL_FLOAT,
 
244
                           GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
 
245
                           4 );
 
246
 
 
247
   glVertexAttribPointer ( userData->startPositionLoc, 3, GL_FLOAT,
 
248
                           GL_FALSE, PARTICLE_SIZE * sizeof(GLfloat),
 
249
                           4 * 4 );
 
250
 
 
251
   
 
252
   glEnableVertexAttribArray ( userData->lifetimeLoc );
 
253
   glEnableVertexAttribArray ( userData->endPositionLoc );
 
254
   glEnableVertexAttribArray ( userData->startPositionLoc );
 
255
   // Blend particles
 
256
   glEnable ( GL_BLEND );
 
257
   glBlendFunc ( GL_SRC_ALPHA, GL_ONE );
 
258
 
 
259
   // Bind the texture
 
260
   glActiveTexture ( GL_TEXTURE0 );
 
261
   glBindTexture ( GL_TEXTURE_2D, userData->textureId );
 
262
   //glEnable ( GL_TEXTURE_2D );
 
263
 
 
264
   // Set the sampler texture unit to 0
 
265
   glUniform1i ( userData->samplerLoc, 0 );
 
266
 
 
267
   Update ( esContext, 133 * 0.001125 );
 
268
 
 
269
   glDrawArrays( GL_POINTS, 0, NUM_PARTICLES );
 
270
   
 
271
   eglSwapBuffers ( esContext->eglDisplay, esContext->eglSurface );
 
272
}
 
273
 
 
274
///
 
275
// Cleanup
 
276
//
 
277
void ShutDown ( ESContext *esContext )
 
278
{
 
279
   UserData *userData = esContext->userData;
 
280
 
 
281
   // Delete texture object
 
282
   glDeleteTextures ( 1, &userData->textureId );
 
283
 
 
284
   // Delete program object
 
285
   glDeleteProgram ( userData->programObject );
 
286
}
 
287
 
 
288
 
 
289
int main ( int argc, char *argv[] )
 
290
{
 
291
   ESContext esContext;
 
292
   UserData  userData;
 
293
 
 
294
   esInitContext ( &esContext );
 
295
   esContext.userData = &userData;
 
296
 
 
297
   esCreateWindow ( &esContext, "ParticleSystem", 320, 240, ES_WINDOW_RGB );
 
298
   
 
299
   if ( !Init ( &esContext ) )
 
300
      return 0;
 
301
 
 
302
   esRegisterDrawFunc ( &esContext, Draw );
 
303
//   esRegisterUpdateFunc ( &esContext, Update );
 
304
   
 
305
   Draw (&esContext);
 
306
  Draw (&esContext);
 
307
  //esMainLoop ( &esContext );
 
308
 
 
309
   ShutDown ( &esContext );
 
310
}