Index: NewOpenGLGame.vcxproj
===================================================================
--- NewOpenGLGame.vcxproj	(revision 5c02dddfb353ccc0de8203d5381d6e41fbabde09)
+++ NewOpenGLGame.vcxproj	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
@@ -163,4 +163,6 @@
     <None Include="color.frag" />
     <None Include="color.vert" />
+    <None Include="laser.frag" />
+    <None Include="laser.vert" />
     <None Include="texture.frag" />
     <None Include="texture.vert" />
Index: laser.frag
===================================================================
--- laser.frag	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
+++ laser.frag	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
@@ -0,0 +1,9 @@
+#version 410
+
+in vec3 position_eye, color;
+
+out vec4 frag_color;
+
+void main() {
+  frag_color = vec4(color, 1.0f);
+}
Index: laser.vert
===================================================================
--- laser.vert	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
+++ laser.vert	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
@@ -0,0 +1,15 @@
+#version 410
+
+uniform mat4 view, proj;
+
+layout(location = 0) in vec3 vertex_position;
+layout(location = 1) in vec3 vertex_color;
+
+out vec3 position_eye, color;
+
+void main() {
+  position_eye = vec3(view * vec4(vertex_position, 1.0));
+  color = vertex_color;
+
+  gl_Position = proj * vec4(position_eye, 1.0);
+}
Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision 5c02dddfb353ccc0de8203d5381d6e41fbabde09)
+++ new-game.cpp	(revision b155f13e5e3eb9d802f665238cf7e834b23e953d)
@@ -104,4 +104,10 @@
 void calculateObjectBoundingBox(SceneObject& obj);
 
+void addLaserToScene(vec3 start, vec3 end, vec3 color,
+                  GLfloat width,
+                  unsigned int& num_lasers,
+                  GLuint laser_points_vbo,
+                  GLuint laser_colors_vbo);
+
 void initializeBuffers(
                   GLuint* points_vbo,
@@ -141,8 +147,8 @@
                   GLuint color_sp, GLuint texture_sp,
                   GLuint vao1, GLuint vao2,
-                  GLuint points_vbo, GLuint normals_vbo,
-                  GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
+                  GLuint colors_vbo, GLuint selected_colors_vbo,
                   SceneObject* selectedObject,
                   map<GLuint, BufferInfo>& shaderBufferInfo);
+void renderLasers(GLuint sp, GLuint vao, unsigned int numLasers);
 void renderSceneGui();
 
@@ -345,7 +351,9 @@
    GLuint color_sp = loadShaderProgram("./color.vert", "./color.frag");
    GLuint texture_sp = loadShaderProgram("./texture.vert", "./texture.frag");
+   GLuint laser_sp = loadShaderProgram("./laser.vert", "./laser.frag");
 
    shaderBufferInfo[color_sp] = BufferInfo();
    shaderBufferInfo[texture_sp] = BufferInfo();
+   shaderBufferInfo[laser_sp] = BufferInfo();
 
    SceneObject obj;
@@ -795,5 +803,5 @@
    obj.selected_colors = { 0.0f };
 
-   T_model = translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.8f));
+   T_model = translate(mat4(1.0f), vec3(0.0f, -1.2f, 1.65f));
    R_model = rotate(mat4(1.0f), 20.0f * (float)ONE_DEG_IN_RAD, vec3(1.0f, 0.0f, 0.0f));
    R_model = mat4(1.0f);
@@ -828,4 +836,22 @@
       model_mat_idx_vbo);
 
+   unsigned int max_num_lasers = 20;
+   unsigned int num_lasers = 0;
+
+   GLuint laser_points_vbo = 0;
+   glGenBuffers(1, &laser_points_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, laser_points_vbo);
+   glBufferData(GL_ARRAY_BUFFER, max_num_lasers * 18 * sizeof(GLfloat) * 3, NULL, GL_DYNAMIC_DRAW);
+
+   GLuint laser_colors_vbo = 0;
+   glGenBuffers(1, &laser_colors_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, laser_colors_vbo);
+   glBufferData(GL_ARRAY_BUFFER, max_num_lasers * 18 * sizeof(GLfloat) * 3, NULL, GL_DYNAMIC_DRAW);
+
+   addLaserToScene(vec3(0.34f, -2.0f, 1.6f), vec3(0.34f, -2.0f, -3.0f), vec3(0.0f, 1.0f, 0.0f), 0.04f,
+      num_lasers, laser_points_vbo, laser_colors_vbo);
+   addLaserToScene(vec3(-0.34f, -2.0f, 1.6f), vec3(-0.34f, -2.0f, -3.0f), vec3(0.0f, 1.0f, 0.0f), 0.04f,
+      num_lasers, laser_points_vbo, laser_colors_vbo);
+
    GLuint vao = 0;
    glGenVertexArrays(1, &vao);
@@ -866,4 +892,17 @@
    glBindBuffer(GL_ARRAY_BUFFER, model_mat_idx_vbo);
    glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, 0, 0);
+
+   GLuint laser_vao = 0;
+   glGenVertexArrays(1, &laser_vao);
+   glBindVertexArray(laser_vao);
+
+   glEnableVertexAttribArray(0);
+   glEnableVertexAttribArray(1);
+
+   glBindBuffer(GL_ARRAY_BUFFER, laser_points_vbo);
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   glBindBuffer(GL_ARRAY_BUFFER, laser_colors_vbo);
+   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
    float cam_speed = 1.0f;
@@ -912,4 +951,7 @@
    GLuint texture_sp_ub_index = glGetUniformBlockIndex(texture_sp, "models");
 
+   GLuint laser_view_mat_loc = glGetUniformLocation(laser_sp, "view");
+   GLuint laser_proj_mat_loc = glGetUniformLocation(laser_sp, "proj");
+
    glUseProgram(color_sp);
    glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
@@ -925,4 +967,8 @@
    glUniformBlockBinding(texture_sp, texture_sp_ub_index, ub_binding_point);
    glBindBufferRange(GL_UNIFORM_BUFFER, ub_binding_point, ubo, 0, GL_MAX_UNIFORM_BLOCK_SIZE);
+
+   glUseProgram(laser_sp);
+   glUniformMatrix4fv(laser_view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
+   glUniformMatrix4fv(laser_proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
 
    bool cam_moved = false;
@@ -1113,4 +1159,7 @@
          glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
 
+         glUseProgram(laser_sp);
+         glUniformMatrix4fv(laser_view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
+
          cam_moved = false;
       }
@@ -1129,8 +1178,8 @@
                color_sp, texture_sp,
                vao, vao2,
-               points_vbo, normals_vbo,
-               colors_vbo, texcoords_vbo, selected_colors_vbo,
+               colors_vbo, selected_colors_vbo,
                selectedObject,
                shaderBufferInfo);
+            renderLasers(laser_sp, laser_vao, num_lasers);
             renderSceneGui();
             break;
@@ -1477,4 +1526,66 @@
 }
 
+// currently only works correctly for lasers oriented along the z axis
+void addLaserToScene(vec3 start, vec3 end, vec3 color, GLfloat width, unsigned int& num_lasers,
+                  GLuint laser_points_vbo, GLuint laser_colors_vbo) {
+   GLuint size_in_buffer = 18 * sizeof(GLfloat) * 3;
+
+   // I really need to create a direction vector and add/subtract that from start and end
+   // to get the right coords
+   // Also need to multiply the width times a vector perpendicular to it
+   vec3 dir = end - start;
+
+   vector<GLfloat> laser_points = {
+      end.x + width / 2,   end.y,   start.z - width,
+      end.x - width / 2,   end.y,   start.z - width,
+      start.x - width / 2, start.y, start.z,
+      end.x + width / 2,   end.y,   start.z - width,
+      start.x - width / 2, start.y, start.z,
+      start.x + width / 2, start.y, start.z,
+      end.x + width / 2,   end.y,   end.z + width,
+      end.x - width / 2,   end.y,   end.z + width,
+      start.x - width / 2, start.y, start.z - width,
+      end.x + width / 2,   end.y,   end.z + width,
+      start.x - width / 2, start.y, start.z - width,
+      start.x + width / 2, start.y, start.z - width,
+      end.x + width / 2,   end.y,   end.z,
+      end.x - width / 2,   end.y,   end.z,
+      start.x - width / 2, start.y, end.z + width,
+      end.x + width / 2,   end.y,   end.z,
+      start.x - width / 2, start.y, end.z + width,
+      start.x + width / 2, start.y, end.z + width,
+   };
+
+   vec3 end_color = vec3(1.0f, 0.0f, 0.0f); // temporary
+   vector<GLfloat> laser_colors = {
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      color.x, color.y, color.z,
+      color.x, color.y, color.z,
+      color.x, color.y, color.z,
+      color.x, color.y, color.z,
+      color.x, color.y, color.z,
+      color.x, color.y, color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+      end_color.x, end_color.y, end_color.z,
+   };
+
+   glBindBuffer(GL_ARRAY_BUFFER, laser_points_vbo);
+   glBufferSubData(GL_ARRAY_BUFFER, num_lasers * size_in_buffer, size_in_buffer, &laser_points[0]);
+
+   glBindBuffer(GL_ARRAY_BUFFER, laser_colors_vbo);
+   glBufferSubData(GL_ARRAY_BUFFER, num_lasers * size_in_buffer, size_in_buffer, &laser_colors[0]);
+
+   num_lasers++;
+}
+
 void initializeBuffers(
                   GLuint* points_vbo,
@@ -1679,6 +1790,5 @@
                   GLuint color_sp, GLuint texture_sp,
                   GLuint vao1, GLuint vao2,
-                  GLuint points_vbo, GLuint normals_vbo,
-                  GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
+                  GLuint colors_vbo, GLuint selected_colors_vbo,
                   SceneObject* selectedObject,
                   map<GLuint, BufferInfo>& shaderBufferInfo) {
@@ -1703,4 +1813,11 @@
 
    glDrawArrays(GL_TRIANGLES, shaderBufferInfo[texture_sp].vbo_base, shaderBufferInfo[texture_sp].vbo_offset);
+}
+
+void renderLasers(GLuint sp, GLuint vao, unsigned int numLasers) {
+   glUseProgram(sp);
+   glBindVertexArray(vao);
+
+   glDrawArrays(GL_TRIANGLES, 0, numLasers * 18);
 }
 
