## OpenGL ES Particle System Tutorial: Part 2/3

Ricardo Rendon Cepeda

BOOM! Develop a bare bones particle system!

Welcome back to our 3-part OpenGL ES particle system tutorial series! Here you’ll learn how to make a cool and fun particle system from scratch, and integrate it into an iOS app.

Here’s an overview of the series:

• Part 1: In the first part, you learned all about particle systems and point sprites, and created a small app to help you learn as you go.
• Part 2: You are here! This time you’ll learn to create a generic particle-emitter paired system. That’s code word for “awesome and reusable”.
• Part 3: Finally, you’ll use your newly developed skills to integrate particle effects into a simple 2D game.

Without further ado, time to get cracking on your new particle-emitter system!

## Getting Started

To get started, you’ll need a simple project that uses OpenGL ES 2.0 and GLKit to render a blue screen that will serve as a starting point.

If you completed Part 1 of this tutorial series like a boss, see if you can complete a similar project setup named GLParticles2 that renders a blue screen `(0.53, 0.81, 0.92, 1.00)` — without downloading the starter code.

If you need some help, feel free to have a peek at the basic instructions and requisites hidden below:

Solution Inside: Challenge Hints SelectShow

If you haven’t read Part 1, want to save a bit of time, are itching to get to the explosion part of this tutorial, or just aren’t feeling like a boss today, then feel free to download the starter code for this tutorial to hurry things along.

Whichever option you chose, build and run your project! You should now have an empty blue screen as shown below:

In Part 1 you learned that particle systems work in a two-level hierarchy composed of the emitter and the particles themselves. Furthermore, you saw that particle systems are affected by global, external factors such as time.

To put this knowledge to good use, you need to find a good real-world system to model that involves lots of individual particles, moving independently, and affected by external forces. Hmm — how about an explosion? Or more specifically, a simple blast, where your particles will spread outwards from your emitter center over time.

Go to File\New\File… and create a new file with the iOS\Cocoa Touch\Objective-C class subclass template. Enter EmitterObject for the class and NSObject for the subclass. Make sure both checkboxes are unchecked, click Next, and click Create.

Open EmitterObject.h and replace the `#import` line with the following:

 `#import `

Still working in EmitterObject.h, replace the contents of EmitterObject.m with:

 ```#import "EmitterObject.h"   #define NUM_PARTICLES 180   typedef struct Particle { float pID; float pRadiusOffset; float pVelocityOffset; float pDecayOffset; float pSizeOffset; GLKVector3 pColorOffset; } Particle;   typedef struct Emitter { Particle eParticles[NUM_PARTICLES]; float eRadius; float eVelocity; float eDecay; float eSize; GLKVector3 eColor; } Emitter;   @implementation EmitterObject { // Instance variables GLKVector2 _gravity; float _life; float _time; }   @end```

You may have noticed that this is set up similar to EmitterTemplate.h in Part 1 of this tutorial. However, since you’re creating a generic particle system, the emitter code has now been abstracted into a class in order to easily create multiple emitters.

Additionally, particle and emitter properties have been prefixed with p and e respectively to ease implementation as your project grows.

One important field in `Particle` is `pID`. This serves as a unique identifier for each particle. It will store an angle in radians which you’ll use to calculate each particle’s position in the simulation.

From fireworks to demolitions, explosives have many inherent properties calculated at the emitter level. However, due to the individual nature of fragments, they are offset at the particle level. For example, an explosion may have an average blast radius of 10m, but fragments may travel anywhere between 9m or 11m from the emitter source.

In your system design, every emitter property listed below also has a comparable particle offset:

• Explosion velocity
• Explosion decay
• Fragment size
• Fragment color

These properties define a simulation that is further governed by the following global external factors:

• World gravity
• Current time

Thus you have the basis for the structures, and their respective variables, defined in EmitterObject.m.

Since each emitter object is unique, each instance should also manage its own set of rendering cycle instructions.

Add the following method declarations to EmitterObject.h, just before the `@end` line:

 ```- (id)initEmitterObject; - (void)renderWithProjection:(GLKMatrix4)projectionMatrix; - (void)updateLifeCycle:(float)timeElapsed;```

Add the following basic implementations for these methods to EmitterObject.m, just before the `@end` line:

 ```- (id)initEmitterObject { if(self = [super init]) { // Initialize variables _gravity = GLKVector2Make(0.0f, 0.0f); _life = 0.0f; _time = 0.0f; } return self; }   - (void)renderWithProjection:(GLKMatrix4)projectionMatrix {   }   - (void)updateLifeCycle:(float)timeElapsed {   }```

Due to their parameters and public declaration, you may have deduced that these methods are meant to be accessed from outside the class. If so, you’re absolutely right!

`initEmitterObject` initializes the variable of an `EmitterObject` instance. Your GLKit view controller calls `renderWithProjection:` to display the rendered scene properly within your `GLKView`. Finally, `updateLifeCycle:` is called for each refresh cycle to give your emitter a chance to update itself appropriately.

Open up MainViewController.m and add the following code to the top of the file, after the `#import` statement:

 ```#import "EmitterObject.h"   @interface MainViewController ()   // Properties @property (strong) EmitterObject* emitter;   @end```

This gives `MainViewController` access to an `EmitterObject`.

Add the following line to MainViewController.m at the end of `viewDidLoad`:

 ```// Set up Emitter self.emitter = [[EmitterObject alloc] initEmitterObject];```

This creates a new `EmitterObject` instance and stores it in your new `emitter` property.

Add the following code to MainViewController.m at the end of `glkView:drawInRect:`:

 ```// Create Projection Matrix float aspectRatio = view.frame.size.width / view.frame.size.height; GLKMatrix4 projectionMatrix = GLKMatrix4MakeScale(1.0f, aspectRatio, 1.0f);   // Render Emitter [self.emitter renderWithProjection:projectionMatrix];```

This code defines the position of the scene that is visible in the `GLKView`. Recall from Part 1 of this tutorial series that OpenGL ES 2.0 screen coordinates range from -1 to +1 on the x and y axes. Therefore, this matrix converts between the device’s coordinate system and the `GLKView`‘s coordinate system (width and height in points).

You then pass this projection matrix to your `emitter` object’s `renderWithProjection:` for every `GLKView` draw cycle.

Finally, add the following method to MainViewController.m just before the `@end` line at the bottom of the file:

 ```- (void)update { // Update Emitter [self.emitter updateLifeCycle:self.timeSinceLastUpdate]; }```

In the code above, `update` is called automatically by GLKit at the appropriate refresh rate. Inside `update` you call `emitter`‘s `updateLifeCycle:` to give your emitter a chance to update itself. You’ll flesh out `updateLifeCycle:` a bit later.

Now you can handle all of your OpenGL ES 2.0 calls within your `EmitterObject` class. Pretty slick!

Now that your self-contained `emitter` is sketched out, you’re ready to create some shaders for your system.

Go to File\New\File…, choose the iOS\Other\Empty template, then click Next. Name the new file Emitter.vsh, uncheck the box next to your GLParticles2 target, and click Create.

Repeat the process above for another new file, but this time name it Emitter.fsh. These files will be used to write your vertex and fragment shaders.

Copy the following code into Emitter.vsh:

 ```// Vertex Shader   static const char* EmitterVS = STRINGIFY (   // Attributes attribute float a_pID; attribute float a_pRadiusOffset; attribute float a_pVelocityOffset; attribute float a_pDecayOffset; attribute float a_pSizeOffset; attribute vec3 a_pColorOffset;   // Uniforms uniform mat4 u_ProjectionMatrix; uniform vec2 u_Gravity; uniform float u_Time; uniform float u_eRadius; uniform float u_eVelocity; uniform float u_eDecay; uniform float u_eSize;   // Varying varying vec3 v_pColorOffset;   void main(void) { }   );```

The above code should look familiar from Part 1 of this tutorial. Because there are so many variables in this shader, all attributes are prefaced with `a_`, all uniforms are prefaced with `u_`, and all varyings are prefaced with `v_` in order to help tell them apart.

Add the following code to Emitter.vsh, inside `main`:

 ```// 1 // Convert polar angle to cartesian coordinates and calculate radius float x = cos(a_pID); float y = sin(a_pID); float r = u_eRadius * a_pRadiusOffset;   // 2 // Lifetime float growth = r / (u_eVelocity + a_pVelocityOffset); float decay = u_eDecay + a_pDecayOffset;   // 3 // If blast is growing if(u_Time < growth) { float time = u_Time / growth; x = x * r * time; y = y * r * time; }   // 4 // Else if blast is decaying else { float time = (u_Time - growth) / decay; x = (x * r) + (u_Gravity.x * time); y = (y * r) + (u_Gravity.y * time); }   // 5 // Required OpenGLES 2.0 outputs gl_Position = u_ProjectionMatrix * vec4(x, y, 0.0, 1.0); gl_PointSize = max(0.0, (u_eSize + a_pSizeOffset));   // Fragment Shader outputs v_pColorOffset = a_pColorOffset;```

There’s plenty of new code here with a lot of equations, so take a moment to review the code comment by comment:

1. Each particle has a unique ID in radians which you must convert to cartesian coordinates. By calculating the radius, you have enough information to animate a particle’s trajectory all the way to its final position.
2. The lifetime of a particle is defined in terms of:
• Growth: The time taken for a particle to reach its final position when traveling at a certain speed, which is found by way of `total radius / total velocity`.
• Decay: The total decay time of the emitter and particle.
3. If the blast is growing, the particle is traveling from its source towards its final position. In this case, time becomes relative to the particle’s growth lifespan.
4. If the blast is decaying, the particle is traveling in the direction of gravity from its final position. In this case, time becomes relative to the particle’s decay lifespan.
5. Both required outputs (the point location and size) and optional outputs (the particle color offset) are passed along the graphics pipeline.

Add the following code to `Emitter.fsh`:

 ```// Fragment Shader   static const char* EmitterFS = STRINGIFY (   // Varying varying highp vec3 v_pColorOffset;   // Uniforms uniform highp float u_Time; uniform highp vec3 u_eColor;   void main(void) { // Color highp vec4 color = vec4(1.0); color.rgb = u_eColor + v_pColorOffset; color.rgb = clamp(color.rgb, vec3(0.0), vec3(1.0));   // Required OpenGL ES 2.0 outputs gl_FragColor = color; }   );```

The fragment shader simply calculates the final color of each particle, based on the overall emitter color and particle offset. The result then uses the clamp function to stay within the bounds of `0.0` for black and `1.0` for white.

If your code is completely black and you aren’t getting automatic GLSL syntax highlighting, then you need to tell Xcode what type of file you are working with.

Part 1 showed you how to turn on syntax highlighting for GLSL files, but there’s another quick way to accomplish the same thing. Look to the top bar of Xcode, go to Editor\Syntax Coloring, and select GLSL from the list as shown in the screenshot below:

## Building an Objective-C Bridge

Your shaders are ready to run on the GPU, but just as in Part 1, you must create a “bridge” to feed them the necessary data from the CPU. Time to switch back to Objective-C!

First, you’ll need to download the resources for this tutorial. Unzip GLParticles2-resources.zip, which creates a folder named Resources. Right-click on the GLParticles folder in XCode’s Project Navigator and select Add Files to “GLParticles2″…, as shown below:

Select the Resources folder you unzipped and click Add. Make sure Copy items into destination’s group folder is checked, Create groups for any added folders is selected, and GLParticles2 is checked in the “Add to targets” section, as shown below:

ShaderProcessor.h and ShaderProcessor.mm are relatively simple shader processors that will be used by your emitter. They are included in the resources file, and were explained back in Part 1 of this tutorial. For that reason they won’t be covered in detail in this part of the tutorial.

Go to File\New\File… and create a new file with the iOS\Cocoa Touch\Objective-C class subclass template. Enter EmitterShader for the Class and NSObject for the subclass. Make sure the checkbox for the GLParticles2 target is checked, click Next, and click Create.

Replace the contents of EmitterShader.h with the following:

 ```#import   @interface EmitterShader : NSObject   // Program Handle @property (readwrite) GLuint program;   // Attribute Handles @property (readwrite) GLint a_pID; @property (readwrite) GLint a_pRadiusOffset; @property (readwrite) GLint a_pVelocityOffset; @property (readwrite) GLint a_pDecayOffset; @property (readwrite) GLint a_pSizeOffset; @property (readwrite) GLint a_pColorOffset;   // Uniform Handles @property (readwrite) GLuint u_ProjectionMatrix; @property (readwrite) GLint u_Gravity; @property (readwrite) GLint u_Time; @property (readwrite) GLint u_eRadius; @property (readwrite) GLint u_eVelocity; @property (readwrite) GLint u_eDecay; @property (readwrite) GLint u_eSize; @property (readwrite) GLint u_eColor;   // Methods - (void)loadShader;   @end```

Now, replace the contents of EmitterShader.m with the following:

 ```#import "EmitterShader.h" #import "ShaderProcessor.h"   // Shaders #define STRINGIFY(A) #A #include "Emitter.vsh" #include "Emitter.fsh"   @implementation EmitterShader   - (void)loadShader { // Program ShaderProcessor* shaderProcessor = [[ShaderProcessor alloc] init]; self.program = [shaderProcessor BuildProgram:EmitterVS with:EmitterFS];   // Attributes self.a_pID = glGetAttribLocation(self.program, "a_pID"); self.a_pRadiusOffset = glGetAttribLocation(self.program, "a_pRadiusOffset"); self.a_pVelocityOffset = glGetAttribLocation(self.program, "a_pVelocityOffset"); self.a_pDecayOffset = glGetAttribLocation(self.program, "a_pDecayOffset"); self.a_pSizeOffset = glGetAttribLocation(self.program, "a_pSizeOffset"); self.a_pColorOffset = glGetAttribLocation(self.program, "a_pColorOffset");   // Uniforms self.u_ProjectionMatrix = glGetUniformLocation(self.program, "u_ProjectionMatrix"); self.u_Gravity = glGetUniformLocation(self.program, "u_Gravity"); self.u_Time = glGetUniformLocation(self.program, "u_Time"); self.u_eRadius = glGetUniformLocation(self.program, "u_eRadius"); self.u_eVelocity = glGetUniformLocation(self.program, "u_eVelocity"); self.u_eDecay = glGetUniformLocation(self.program, "u_eDecay"); self.u_eSize = glGetUniformLocation(self.program, "u_eSize"); self.u_eColor = glGetUniformLocation(self.program, "u_eColor"); }   @end```

These two files comprise the requisite shader handles which tell your Objective-C variables where to find their GLSL counterparts. These shader handles are very similar to the `EmitterShader` you wrote in Part 1, but with quite a few more variables.

Note: You need to be aware of the number of variables you use in your shaders. It turns out that different graphics hardware has different limitations on the number of variables that can be used. In iOS, your shader will fail to compile at runtime if these limits are exceeded. Refer to the Best Practices for Shaders section of Apple’s documentation for more information.

Open up EmitterObject.m and add the following line just below the existing `#import` statement:

 `#import "EmitterShader.h"`

Still working in EmitterObject.m, add the following properties just above the `@implementation` statement:

 ```@interface EmitterObject ()   @property (assign) Emitter emitter; @property (strong) EmitterShader* shader;   @end```

Stay with EmitterObject.m and add the following method that loads your shader, just above the `@end` statement:

 ```- (void)loadShader { self.shader = [[EmitterShader alloc] init]; [self.shader loadShader]; glUseProgram(self.shader.program); }```

At this point, you’re ready to load up your particle system. Add the following methods to EmitterObject.m, after `loadShader`:

 ```// 1 - (float)randomFloatBetween:(float)min and:(float)max { float range = max - min; return (((float) (arc4random() % ((unsigned)RAND_MAX + 1)) / RAND_MAX) * range) + min; }   - (void)loadParticleSystem { // 2 Emitter newEmitter = {0.0f};   // 3 // Offset bounds float oRadius = 0.10f; // 0.0 = circle; 1.0 = ring float oVelocity = 0.50f; // Speed float oDecay = 0.25f; // Time float oSize = 8.00f; // Pixels float oColor = 0.25f; // 0.5 = 50% shade offset   // 4 // Load Particles for(int i=0; i

Okay — that’s a ton of code. Take a minute to walk through the code, comment by comment:

1. This function is taken straight from Part 1 and is used to produce a random float value between two bounds.
2. The member variables of your `Emitter` structure can’t be assigned values through your emitter property. Therefore, you must create a new emitter variable for this initialization stage, which is then assigned in full to your emitter property.
3. Here, you define the bounds used to calculate each particle’s offset according to the particle system structures.
4. All particles are initialized with a unique ID and random offsets.
5. Here, you define your emitter properties, creating a custom explosion based on a generic template.
6. Next, you set the global factors that affect the simulation of your scene.
7. Your new emitter is assigned to your emitter property and a Vertex Buffer Object (VBO) is created for storing its particles.

To finish off your emitter, scroll all the way back up EmitterObject.m and add the following code to `initEmitterObject` inside the `if` statement immediately after your variable initialization statements:

 ```// Load Shader [self loadShader];   // Load Particle System [self loadParticleSystem];```

All of the emitter and particle frameworks are in place. All that’s left to do is add the code that will take care of rendering your system on-screen.

Open EmitterObject.m and add the following code to `renderWithProjection:`:

 ```// Uniforms glUniformMatrix4fv(self.shader.u_ProjectionMatrix, 1, 0, projectionMatrix.m); glUniform2f(self.shader.u_Gravity, _gravity.x, _gravity.y); glUniform1f(self.shader.u_Time, _time); glUniform1f(self.shader.u_eRadius, self.emitter.eRadius); glUniform1f(self.shader.u_eVelocity, self.emitter.eVelocity); glUniform1f(self.shader.u_eDecay, self.emitter.eDecay); glUniform1f(self.shader.u_eSize, self.emitter.eSize); glUniform3f(self.shader.u_eColor, self.emitter.eColor.r, self.emitter.eColor.g, self.emitter.eColor.b);   // Attributes glEnableVertexAttribArray(self.shader.a_pID); glEnableVertexAttribArray(self.shader.a_pRadiusOffset); glEnableVertexAttribArray(self.shader.a_pVelocityOffset); glEnableVertexAttribArray(self.shader.a_pDecayOffset); glEnableVertexAttribArray(self.shader.a_pSizeOffset); glEnableVertexAttribArray(self.shader.a_pColorOffset);   glVertexAttribPointer(self.shader.a_pID, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pID))); glVertexAttribPointer(self.shader.a_pRadiusOffset, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pRadiusOffset))); glVertexAttribPointer(self.shader.a_pVelocityOffset, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pVelocityOffset))); glVertexAttribPointer(self.shader.a_pDecayOffset, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pDecayOffset))); glVertexAttribPointer(self.shader.a_pSizeOffset, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pSizeOffset))); glVertexAttribPointer(self.shader.a_pColorOffset, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (void*)(offsetof(Particle, pColorOffset)));   // Draw particles glDrawArrays(GL_POINTS, 0, NUM_PARTICLES); glDisableVertexAttribArray(self.shader.a_pID); glDisableVertexAttribArray(self.shader.a_pRadiusOffset); glDisableVertexAttribArray(self.shader.a_pVelocityOffset); glDisableVertexAttribArray(self.shader.a_pDecayOffset); glDisableVertexAttribArray(self.shader.a_pSizeOffset); glDisableVertexAttribArray(self.shader.a_pColorOffset);```

In the code above, you are simply sending all your uniform and attribute data to your shader program and drawing all your particles.

Still working with EmitterObject.m, add the following code to `updateLifeCycle`:

 ```_time += timeElapsed;   if(_time > _life) _time = 0.0f;```

This small bit of code will continuously repeat your explosion from birth to death.

Build and run your app — your explosion should look just as if you blew up Stone Man’s stage in Mega Man 5, as shown in the image below:

There’s something incredibly satisfying to blowing things up! :] Note how each particle is completely unique, differing in position, speed, size, and color.

So far you’ve built a pretty good foundation for a generic particle system. However, as the particles decay, nothing really exciting happens — they simply fall to the ground under the force of gravity. A real explosion changes over time, such as fire turning into smoke, or embers shrinking away.

You’re going to implement a similar effect in your particle system.

Open up EmitterObject.m and modify the `Emitter` structure by replacing the following variables:

 ```float eSize; GLKVector3 eColor;```

with:

 ```float eSizeStart; float eSizeEnd; GLKVector3 eColorStart; GLKVector3 eColorEnd;```

Instead of having a fixed size and color, you now have a start and end target color and size.

Whoops — Xcode is noting some compile errors. To get rid of these compile errors, remove the following lines from `renderWithProjection:` in EmitterObject.m:

 ```glUniform1f(self.shader.u_eSize, self.emitter.eSize); glUniform3f(self.shader.u_eColor, self.emitter.eColor.r, self.emitter.eColor.g, self.emitter.eColor.b);```

Still working in EmitterObject.m, replace the following lines in `loadParticleSystem`:

 ```newEmitter.eSize = 32.00f; // Fragment size newEmitter.eColor = GLKVector3Make(1.00f, 0.50f, 0.00f); // Fragment color```

with the following:

 ```newEmitter.eSizeStart = 32.00f; // Fragment start size newEmitter.eSizeEnd = 8.00f; // Fragment end size newEmitter.eColorStart = GLKVector3Make(1.00f, 0.50f, 0.00f); // Fragment start color newEmitter.eColorEnd = GLKVector3Make(0.25f, 0.00f, 0.00f); // Fragment end color```

This will make your explosion will fade from bright orange to dark red as your particles decrease in size from 32 pixels to 8. Now you just need to communicate this to your shaders.

Open up Emitter.vsh and replace the following uniform:

 `uniform float u_eSize;`

with:

 ```uniform float u_eSizeStart; uniform float u_eSizeEnd;```

Next, add the following varying variables to Emitter.vsh just below `v_pColorOffset`:

 ```varying float v_Growth; varying float v_Decay;```

These varying variables will be used in the fragment shader.

There’s a few changes to make to `main` in Emitter.vsh, but rather than try to explain where to make your changes, just replace the entire `main` method with the following:

 ```void main(void) { // Convert polar angle to cartesian coordinates and calculate radius float x = cos(a_pID); float y = sin(a_pID); float r = u_eRadius * a_pRadiusOffset;   // Lifetime float growth = r / (u_eVelocity + a_pVelocityOffset); float decay = u_eDecay + a_pDecayOffset;   // Size float s = 1.0;   // If blast is growing if(u_Time < growth) { float time = u_Time / growth; x = x * r * time; y = y * r * time;   // 1 s = u_eSizeStart; }   // Else if blast is decaying else { float time = (u_Time - growth) / decay; x = (x * r) + (u_Gravity.x * time); y = (y * r) + (u_Gravity.y * time);   // 2 s = mix(u_eSizeStart, u_eSizeEnd, time); }   // Required OpenGL ES 2.0 outputs gl_Position = u_ProjectionMatrix * vec4(x, y, 0.0, 1.0);   // 3 gl_PointSize = max(0.0, (s + a_pSizeOffset));   // Fragment Shader outputs v_pColorOffset = a_pColorOffset; v_Growth = growth; v_Decay = decay; }```

The changes are subtle, but they’re explained below:

1. If the blast is growing, maintain the particle starting size.
2. If the blast is decaying, gradually decrease the size of the particle from the starting size to the ending size according to the relative decay time. You use the `mix` function to interpolate between the two.
3. Finally, output the resulting size after adding or subtracting the offset.

The fragment shader follows a very similar implementation.

Open Emitter.fsh and add the following lines just below `v_pColorOffset`:

 ```varying highp float v_Growth; varying highp float v_Decay;```

Then, replace the following uniform:

 `uniform highp vec3 u_eColor;`

with:

 ```uniform highp vec3 u_eColorStart; uniform highp vec3 u_eColorEnd;```

Finally, replace all of `main` with:

 ```void main(void) { // Color highp vec4 color = vec4(1.0);   // If blast is growing if(u_Time < v_Growth) { // 1 color.rgb = u_eColorStart; }   // Else if blast is decaying else { highp float time = (u_Time - v_Growth) / v_Decay;   // 2 color.rgb = mix(u_eColorStart, u_eColorEnd, time); }   // 3 color.rgb += v_pColorOffset; color.rgb = clamp(color.rgb, vec3(0.0), vec3(1.0));   // Required OpenGL ES 2.0 outputs gl_FragColor = color; }```

The color implementation is almost identical to the size implementation:

1. If the blast is growing, maintain the particle starting color.
2. If the blast is decaying, gradually change the color of the particle from the starting color to the ending color, according to the relative decay time. Again, you’re using the `mix` function to interpolate between the two.
3. Finally, output the resulting color after adding or subtracting the offset, using the `clamp` function to stay within the bounds of `0.0` (black) and `1.0` (white).

With your shaders in place it’s time to complete the obligatory `EmitterShader` bridge. See if you can complete this step all on your own! If you’re stuck, you can check out the solution below:

Solution Inside: CPU-GPU Bridge SelectShow

If you think you know what the next step is, and are still in the mood for a challenge, then go ahead and try it yourself! Otherwise, you can find the solution in the spoiler section below:

Solution Inside: Sending Data to OpenGL ES 2.0 SelectShow

Build and run your app — your particles should now decay in color and size, as shown below:

It’s a really nice visual effect, especially considering how little code you wrote to achieve this result.

Your explosion is looking good, but you’re not going to settle for “good” — you want it to look “great”. A simple texture is all you need to turn your chunky squares into tiny little sparks. Point sprites FTW!

Open Emitter.fsh and add the following uniform:

 `uniform sampler2D u_Texture;`

Still working in Emitter.fsh, add the following line to the beginning of `main`:

 `highp vec4 texture = texture2D(u_Texture, gl_PointCoord);`

Again in Emitter.fsh, change the `gl_FragColor` output line as shown below:

 `gl_FragColor = texture * color;`

As before, you need an Objective-C bridge to finish this task off. Open EmitterShader.h and add the following property:

 `@property (readwrite) GLint u_Texture;`

Finalize the implementation by opening EmitterShader.m and adding the following line to the bottom of `loadShader`:

 `self.u_Texture = glGetUniformLocation(self.program, "u_Texture");`

Now, open EmitterObject.m and add the following method just above the `@end` statement at the bottom of the file:

 ```- (void)loadTexture:(NSString *)fileName { NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], GLKTextureLoaderOriginBottomLeft, nil];   NSError* error; NSString* path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil]; GLKTextureInfo* texture = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error]; if(texture == nil) { NSLog(@"Error loading file: %@", [error localizedDescription]); }   glBindTexture(GL_TEXTURE_2D, texture.name); }```

This is the same method that you used in Part 1, which leverages Apple’s new `GLKTextureLoader` to load your texture data. But before you can call this new method, you need to do just a tiny bit of refactoring.

Open EmitterObject.h and replace the following line:

 `- (id)initEmitterObject;`

with:

 `- (id)initWithTexture:(NSString *)fileName;`

Likewise, inside EmitterObject.m, replace the following line:

 `- (id)initEmitterObject`

with:

 `- (id)initWithTexture:(NSString*)fileName`

This small change lets you pass a texture filename into the initializer.

 ```// Load Texture [self loadTexture:fileName];```

This simply calls the newly created `loadTexture` method from within `initWithTexture:`. At this stage you haven’t actually sent a texture file to this method – you’ll do that in the very next step.

Open up MainViewController.m and replace the following line in `viewDidLoad`:

 `self.emitter = [[EmitterObject alloc] initEmitterObject];`

with:

 `self.emitter = [[EmitterObject alloc] initWithTexture:@"texture_64.png"];`

Now that your EmitterObject has a new initializer, you call it here with the name of the texture to use.

Open up EmitterObject.m and add the following line to the end of the uniform block in `renderWithProjection:`:

 `glUniform1i(self.shader.u_Texture, 0);`

Finally, you need to enable blending and set the appropriate function in your rendering loop.

Open up MainViewController.m and add the following lines to `glkView:drawInRect`, just after `glClearColor` and `glClear`:

 ```// Set the blending function (normal w/ premultiplied alpha) glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);```

This sets the same blend modes as in part 1, so the textures render properly with transparency.

Build and run your app — you should see the nicely textured explosion as illustrated below:

Your particle-emitter system just keeps looking better and better. But what if you could create an explosion wherever you wanted on the screen? Read on to find out how!

Recall that you constructed your emitter class to facilitate multiple emitters. This next stage will create a new explosion wherever you tap the screen.

First, you’ll need to enable a position field for your emitter objects. Open EmitterObject.m and add the following line to your `Emitter` structure:

 `GLKVector2 ePosition;`

Now open Emitter.vsh and add the following uniform to the rest of the uniforms:

 `uniform vec2 u_ePosition;`

Still working in Emitter.vsh, replace the following line that sets `gl_Position` in `main`:

 `gl_Position = u_ProjectionMatrix * vec4(x, y, 0.0, 1.0);`

with these two lines:

 ```vec2 position = vec2(x,y) + u_ePosition; gl_Position = u_ProjectionMatrix * vec4(position, 0.0, 1.0);```

These lines translate the points you already calculated to emit from the position you will provide in `u_ePosition`.

 `@property (readwrite) GLint u_ePosition;`

Now, add the following line to EmitterShader.m, at the very end of `loadShader`:

 `self.u_ePosition = glGetUniformLocation(self.program, "u_ePosition");`

This finds the location of the `u_ePosition` uniform in the shader and stores its id/name in a property.

Now you need to do a little refactoring to prepare for the new position input. Open up EmitterObject.h and replace the following line:

 `- (id)initWithTexture:(NSString *)fileName;`

with:

 `- (id)initWithTexture:(NSString *)fileName at:(GLKVector2)position;`

Likewise, inside EmitterObject.m, replace the following line:

 `- (id)initWithTexture:(NSString*)fileName`

with:

 `- (id)initWithTexture:(NSString *)fileName at:(GLKVector2)position`

Also in EmitterObject.m, replace the method signature:

 `- (void)loadParticleSystem`

with:

 `- (void)loadParticleSystem:(GLKVector2)position`

Now `loadParticleSystem:` takes a `position` as an argument.

Still working in EmitterObject.m, add the following code to `loadParticleSystem:`, just below the line that starts with `newEmitter.eColorEnd = ...`:

 `newEmitter.ePosition = position; // Source position`

This simply sets the position of the emitter to the position that is passed in.

Now you need to send this data to your shader. Again in EmitterObject.m add the following line to `renderWithProjection:` immediately after the other calls to `glUniform...`:

 `glUniform2f(self.shader.u_ePosition, self.emitter.ePosition.x, self.emitter.ePosition.y);`

Don’t go anywhere — you’re still working in EmitterObject.m. Return to `initWithTexture:at` and replace the following line:

 `[self loadParticleSystem];`

with:

 `[self loadParticleSystem:position];`

Replace the following line in EmitterObject.h:

 `- (void)updateLifeCycle:(float)timeElapsed;`

with:

 `- (BOOL)updateLifeCycle:(float)timeElapsed;`

This halts the rendering of an explosion once it has ceased.

Now return to EmitterObject.m and replace `updateLifeCycle:` with the following:

 ```- (BOOL)updateLifeCycle:(float)timeElapsed { _time += timeElapsed;   if(_time < _life) return YES; else return NO; }```

This new version of `updateLifeCycle:` doesn’t reset `_time` to `0` when the emitter reaches the end of its life. Instead, it returns `NO`, which will cause the emitter to stop. You’ve effectively turned the looping animation into a one-shot explosion.

There’s still two unanswered questions, though — where does the `position` come from, and where will you check the boolean condition above? The answer to both is: your GLKit View Controller.

Once again, time for some refactoring.

Open MainViewController.m and replace the following single emitter property:

 `@property (strong) EmitterObject* emitter;`

with the following property that stores an array of emitters:

 `@property (strong) NSMutableArray* emitters;`

Also in MainViewController.m, change the lines that set the emitter in `viewDidLoad` from this:

 ```// Set up Emitter self.emitter = [[EmitterObject alloc] initWithTexture:@"texture_64.png"];```

to this:

 ```// Set up Emitters self.emitters = [NSMutableArray array];```

In this new version, you aren’t creating any actual `EmitterObject`s yet — you’re just creating an `NSMutableArray` in which to store them later. You’re using a mutable array because you’ll be adding an `EmitterObject` for each tap and removing the object later on when the emitter is done.

Now that you have an array of `EmitterObject`s instead of just one, you need to change your rendering loop.

In MainViewController.m, replace the following line in `glkView:drawInRect:`:

 ```// Render Emitter [self.emitter renderWithProjection:projectionMatrix];```

with:

 ```// Render Emitters if([self.emitters count] != 0) { for(EmitterObject* emitter in self.emitters) { [emitter renderWithProjection:projectionMatrix]; } }```

This loops through all the `EmitterObject`s that currently exist and calls each emitter’s `renderWithProjection:` to draw them on screen.

Now replace your implementation of `update` in MainViewController.m with the following code:

 ```- (void)update { // Update Emitters if([self.emitters count] != 0) { NSMutableArray* deadEmitters = [NSMutableArray array];   for(EmitterObject* emitter in self.emitters) { BOOL alive = [emitter updateLifeCycle:self.timeSinceLastUpdate];   if(!alive) [deadEmitters addObject:emitter]; }   for(EmitterObject* emitter in deadEmitters) [self.emitters removeObject:emitter]; } }```

This new version of `update` checks each existing explosion to see if it’s alive or dead. If the explosion has reached the end of its life cycle, as indicated by returning `NO` from `updateLifeCycle:`, it is removed from the emitter array.

You are now managing multiple emitter objects, but you need a way to create them when you tap on the screen!

Add the following method to MainViewController.m, just above the `@end` statement at the bottom of the file:

 ```- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1 // Get touch point and screen information CGPoint touchPoint = [touches.anyObject locationInView:self.view]; CGPoint glPoint = CGPointMake(touchPoint.x/self.view.frame.size.width, touchPoint.y/self.view.frame.size.height);   // 2 // Convert touch point to GL position float aspectRatio = self.view.frame.size.width / self.view.frame.size.height; float x = (glPoint.x * 2.0f) - 1.0f; float y = ((glPoint.y * 2.0f) - 1.0f) * (-1.0f/aspectRatio);   // 3 // Create a new emitter object EmitterObject* emitter = [[EmitterObject alloc] initWithTexture:@"texture_64.png" at:GLKVector2Make(x, y)]; [self.emitters addObject:emitter]; }```

This logic in the above code is as follows:

1. An explosion will occur on every tap, so you need some information about this event — specifically, the touch point and screen aspect ratio.
2. In this tutorial, your OpenGL ES 2.0 coordinates range from -1 to +1, so you need to convert the UI touch point to an OpenGL ES 2.0 position.
3. With this information, you can now create a new emitter object and add it to your emitter array.

Build and run your app, and tap on the screen to release your destructive powers! You should see multiple explosions on the screen, as shown below:

After you’ve tired yourself out blowing up everything in sight, give yourself a big pat on the back — you’ve nearly completed your very own generic and interactive particle system!

Note: If you run your app in the simulator, you may see an unnerving pause in the rendering each time you click the simulator’s screen. Running on an actual device will give you the smooth performance you’d expect in your app.

## Correcting the Rendering Cycle

Wait – “nearly completed”? Although it feels like you’re all done, there’s one small bug in your app. Did you spot it?

It’s a subtle bug, but try the following exercise to see if you can detect what’s going on:

• Build and run your app again.
• Tap on multiple points on the screen.
• Look closely at the resulting explosions. Notice anything strange?

Every time you tap the screen and cause a new explosion, the particles of the previous explosions switch position. In fact, all of the attributes of the old explosions will change to the attributes of the latest explosion. The difference in elapsed lifetimes is what makes this bug hard to notice, because the size of the explosions change over time, but it’s definitely a noticeable effect.

In Part 1 of this tutorial series, you took some OpenGL ES 2.0 shortcuts because you were only rendering a single object. Now that you have multiple emitters, you need to pay closer attention to the rendering cycle.

Open EmitterObject.m and locate your particle VBO. As you can see, the buffer only gets bound during the emitter initialization. This means that whenever a new emitter object is created, all particles will be rendered from the last VBO to be created.

Inside EmitterObject.m, add a new instance variable to your implementation just below the declaration for `_time`:

 `GLuint _particleBuffer;`

Stay with EmitterObject.m, locate the spot where you initialize your other instance variables in `initWithTexture:at`, and add the following line:

 `_particleBuffer = 0;`

Still in EmitterObject.m, replace the following lines in `loadParticleSystem`:

 ```GLuint particleBuffer = 0; glGenBuffers(1, &particleBuffer); glBindBuffer(GL_ARRAY_BUFFER, particleBuffer);```

with:

 ```glGenBuffers(1, &_particleBuffer); glBindBuffer(GL_ARRAY_BUFFER, _particleBuffer);```

Finally, switch buffers on every render by adding the following line to the beginning of `renderWithProjection` in EmitterObject.m:

 ```// Switch Buffers glBindBuffer(GL_ARRAY_BUFFER, _particleBuffer);```

Build and run your app and tap away! Notice that your new explosions don’t affect the previous ones any more, as shown below:

You’ve done a great job completing this part of the tutorial. You’ve definitely blown this one out of the water — pun most definitely intended! :]

## Where To Go From Here?

You can find the completed project with all of the code and resources from this tutorial on GitHub. Keep an eye on the repository for any updates!

You should now have a good knowledge of the inner workings of generic particle systems, albeit in their most basic form. You should also be able to expand this particular implementation to include more properties and behaviors at both particle and emitter levels.

You have built complex shaders and can pass data to them with ease. You can also abstract rendering cycles and manage multiple graphics objects. All in all, you’ve come really far in the first two parts of this tutorial!

Feel free to play around with the project here to create some of your own cool effects. For example, try changing the look of the particle system or changing the path the particles take.

In Part 3 of this series, you will use your newly developed skills to integrate some particle effects into a simple 2D game.

If you have any questions, comments or suggestions, please feel free to join the conversation below!

... 20 total!

... 15 total!

... 29 total!

... 15 total!

... 10 total!

... 11 total!

... 11 total!

... 11 total!

... 15 total!