Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision e1eec78b46bbc21e2acea988dcc0fdefc06f34d4)
+++ new-game.cpp	(revision db06984dd8b4a063db3a92fd593585c1fa2d7f26)
@@ -157,4 +157,6 @@
                   GLuint* model_mat_idx_vbo);
 
+GLuint initializeParticleEffectBuffers();
+
 void populateBuffers(vector<SceneObject*>& objects,
                   map<GLuint, BufferInfo>& shaderBufferInfo,
@@ -193,8 +195,10 @@
 
 void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
-                  GLuint color_sp, GLuint asteroid_sp, GLuint texture_sp, GLuint laser_sp,
-                  GLuint color_vao, GLuint asteroid_vao, GLuint texture_vao, GLuint laser_vao,
+                  GLuint color_sp, GLuint asteroid_sp, GLuint texture_sp, GLuint laser_sp, GLuint explosion_sp,
+                  GLuint color_vao, GLuint asteroid_vao, GLuint texture_vao, GLuint laser_vao, GLuint explosion_vao,
                   GLuint colors_vbo, GLuint selected_colors_vbo,
                   SceneObject* selectedObject);
+void renderExplosion(GLuint explosion_sp, GLuint explosion_vao, GLuint tex);
+
 void renderSceneGui();
 
@@ -206,4 +210,5 @@
 const int KEY_STATE_UNCHANGED = -1;
 const bool FULLSCREEN = false;
+const int EXPLOSION_PARTICLE_COUNT = 300;
 unsigned int MAX_UNIFORMS = 0; // Requires OpenGL constants only available at runtime, so it can't be const
 
@@ -438,4 +443,5 @@
    GLuint texture_sp = loadShaderProgram("./texture.vert", "./texture.frag");
    GLuint laser_sp = loadShaderProgram("./laser.vert", "./laser.frag");
+   GLuint explosion_sp = loadShaderProgram("./explosion.vert", "./explosion.frag");
 
    shaderBufferInfo[color_sp] = BufferInfo();
@@ -558,4 +564,6 @@
    glVertexAttribIPointer(2, 1, GL_UNSIGNED_INT, 0, 0);
 
+   GLuint explosion_vao = initializeParticleEffectBuffers();
+
    float cam_speed = 1.0f;
    float cam_yaw_speed = 60.0f*ONE_DEG_IN_RAD;
@@ -600,5 +608,4 @@
    GLuint asteroid_proj_mat_loc = glGetUniformLocation(asteroid_sp, "proj");
    GLuint asteroid_sp_models_ub_index = glGetUniformBlockIndex(asteroid_sp, "models");
-   //GLuint asteroid_sp_hp_ub_index = glGetUniformBlockIndex(asteroid_sp, "hp_uniform");
 
    GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
@@ -610,4 +617,6 @@
    GLuint laser_color_loc = glGetUniformLocation(laser_sp, "laser_color");
    GLuint laser_sp_models_ub_index = glGetUniformBlockIndex(laser_sp, "models");
+
+   GLuint elapsed_system_time_loc = glGetUniformLocation(explosion_sp, "elapsed_system_time");
 
 
@@ -905,4 +914,7 @@
       }
 
+      glUseProgram(explosion_sp);
+      glUniform1f(elapsed_system_time_loc, (GLfloat)current_seconds);
+
       // Render scene
 
@@ -916,6 +928,6 @@
          case STATE_GAME:
             renderScene(shaderBufferInfo,
-               color_sp, asteroid_sp, texture_sp, laser_sp,
-               color_vao, asteroid_vao, texture_vao, laser_vao,
+               color_sp, asteroid_sp, texture_sp, laser_sp, explosion_sp,
+               color_vao, asteroid_vao, texture_vao, laser_vao, explosion_vao,
                colors_vbo, selected_colors_vbo,
                selectedObject);
@@ -1886,4 +1898,46 @@
 }
 
+GLuint initializeParticleEffectBuffers() {
+   float vv[EXPLOSION_PARTICLE_COUNT * 3]; // initial velocities vec3
+   float vt[EXPLOSION_PARTICLE_COUNT]; // initial times
+   float t_accum = 0.0f; // start time
+
+   for (int i = 0; i < EXPLOSION_PARTICLE_COUNT; i++) {
+      vt[i] = t_accum;
+      t_accum += 0.01f;
+
+      float randx = ((float)rand() / (float)RAND_MAX) * 1.0f - 0.5f;
+      float randz = ((float)rand() / (float)RAND_MAX) * 1.0f - 0.5f;
+      vv[i*3] = randx;
+      vv[i*3 + 1] = 1.0f;
+      vv[i*3 + 2] = randz;
+   }
+
+   GLuint velocity_vbo;
+   glGenBuffers(1, &velocity_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, velocity_vbo);
+   glBufferData(GL_ARRAY_BUFFER, sizeof(vv), vv, GL_STATIC_DRAW);
+
+   GLuint time_vbo;
+   glGenBuffers(1, &time_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, time_vbo);
+   glBufferData(GL_ARRAY_BUFFER, sizeof(vt), vt, GL_STATIC_DRAW);
+
+   GLuint vao;
+   glGenVertexArrays(1, &vao);
+   glBindVertexArray(vao);
+
+   glBindBuffer(GL_ARRAY_BUFFER, velocity_vbo);
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
+
+   glBindBuffer(GL_ARRAY_BUFFER, time_vbo);
+   glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 0, NULL);
+
+   glEnableVertexAttribArray(0);
+   glEnableVertexAttribArray(1);
+
+   return vao;
+}
+
 void populateBuffers(vector<SceneObject*>& objects,
                   map<GLuint, BufferInfo>& shaderBufferInfo,
@@ -2219,6 +2273,6 @@
 
 void renderScene(map<GLuint, BufferInfo>& shaderBufferInfo,
-                  GLuint color_sp, GLuint asteroid_sp, GLuint texture_sp, GLuint laser_sp,
-                  GLuint color_vao, GLuint asteroid_vao, GLuint texture_vao, GLuint laser_vao,
+                  GLuint color_sp, GLuint asteroid_sp, GLuint texture_sp, GLuint laser_sp, GLuint explosion_sp,
+                  GLuint color_vao, GLuint asteroid_vao, GLuint texture_vao, GLuint laser_vao, GLuint explosion_vao,
                   GLuint colors_vbo, GLuint selected_colors_vbo,
                   SceneObject* selectedObject) {
@@ -2259,4 +2313,22 @@
    glDrawArrays(GL_TRIANGLES, shaderBufferInfo[laser_sp].vbo_base, shaderBufferInfo[laser_sp].vbo_offset);
 
+   glDisable(GL_BLEND);
+
+   renderExplosion(explosion_sp, explosion_vao, 0);
+}
+
+void renderExplosion(GLuint explosion_sp, GLuint explosion_vao, GLuint tex) {
+   glEnable(GL_BLEND);
+   glEnable(GL_PROGRAM_POINT_SIZE);
+
+   //glActiveTexture(GL_TEXTURE1);
+   //glBindTexture(GL_TEXTURE_2D, tex);
+   glUseProgram(explosion_sp);
+
+   glBindVertexArray(explosion_vao);
+
+   glDrawArrays(GL_POINTS, 0, EXPLOSION_PARTICLE_COUNT);
+
+   glDisable(GL_PROGRAM_POINT_SIZE);
    glDisable(GL_BLEND);
 }
