Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision b1d8ddc14bdd97574508596ce2ffbcfcca8bcce2)
+++ new-game.cpp	(revision cffca4d29396387d707220e40d5c35e06aaae72e)
@@ -43,6 +43,5 @@
    GLuint shader_program;
    unsigned int num_points;
-   GLvoid* vertex_vbo_offset;
-   GLvoid* texture_vbo_offset;
+   GLint vertex_vbo_offset;
    vector<GLfloat> points;
    vector<GLfloat> colors;
@@ -102,5 +101,5 @@
 
 void renderScene(vector<SceneObject>& objects,
-                  GLuint shader_program1, GLuint shader_program2,
+                  GLuint color_sp, GLuint texture_sp,
                   GLuint vao1, GLuint vao2,
                   GLuint shader1_mat_loc, GLuint shader2_mat_loc,
@@ -257,192 +256,4 @@
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
-   mat4 T_model, R_model;
-
-   // triangle
-   objects.push_back(SceneObject());
-   objects[0].id = 0;
-   objects[0].shader_program = 0;
-   objects[0].vertex_vbo_offset = (GLvoid*) (0 * sizeof(float) * 3);
-   objects[0].texture_vbo_offset = (GLvoid*)(0 * sizeof(float) * 2);
-   objects[0].points = {
-       0.0f,  0.5f,  0.0f,
-      -0.5f, -0.5f,  0.0f,
-       0.5f, -0.5f,  0.0f,
-       0.5f, -0.5f,  0.0f,
-      -0.5f, -0.5f,  0.0f,
-       0.0f,  0.5f,  0.0f,
-   };
-   objects[0].colors = {
-      1.0f, 0.0f, 0.0f,
-      0.0f, 0.0f, 1.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 0.0f, 1.0f,
-      1.0f, 0.0f, 0.0f,
-   };
-   objects[0].texcoords = {
-      1.0f, 1.0f,
-      0.0f, 1.0f,
-      0.0f, 0.0f,
-      1.0f, 1.0f,
-      0.0f, 0.0f,
-      1.0f, 0.0f
-   };
-   objects[0].normals = {
-       0.0f,  0.0f,  1.0f,
-       0.0f,  0.0f,  1.0f,
-       0.0f,  0.0f,  1.0f,
-       0.0f,  0.0f, -1.0f,
-       0.0f,  0.0f, -1.0f,
-       0.0f,  0.0f, -1.0f,
-   };
-   objects[0].selected_colors = {
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-   };
-   objects[0].num_points = objects[0].points.size() / 3;
-
-   T_model = translate(mat4(), vec3(0.45f, 0.0f, 0.0f));
-   R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
-   objects[0].model_mat = T_model*R_model;
-
-   // square
-   objects.push_back(SceneObject());
-   objects[1].id = 1;
-   objects[1].shader_program = 0;
-   objects[1].vertex_vbo_offset = (GLvoid*) (6 * sizeof(float) * 3);
-   objects[1].texture_vbo_offset = (GLvoid*)(6 * sizeof(float) * 2);
-   objects[1].points = {
-       0.5f,  0.5f,  0.0f,
-      -0.5f,  0.5f,  0.0f,
-      -0.5f, -0.5f,  0.0f,
-       0.5f,  0.5f,  0.0f,
-      -0.5f, -0.5f,  0.0f,
-       0.5f, -0.5f,  0.0f,
-   };
-   objects[1].colors = {
-      1.0f, 0.0f, 0.0f,
-      0.0f, 0.0f, 1.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 1.0f, 0.0f,
-      0.0f, 0.0f, 1.0f,
-      1.0f, 0.0f, 0.0f,
-   };
-   objects[1].texcoords = {
-      1.0f, 1.0f,
-      0.0f, 1.0f,
-      0.0f, 0.0f,
-      1.0f, 1.0f,
-      0.0f, 0.0f,
-      1.0f, 0.0f
-   };
-   objects[1].normals = {
-      0.0f,  0.0f,  1.0f,
-      0.0f,  0.0f,  1.0f,
-      0.0f,  0.0f,  1.0f,
-      0.0f,  0.0f,  1.0f,
-      0.0f,  0.0f,  1.0f,
-      0.0f,  0.0f,  1.0f,
-   };
-   objects[1].selected_colors = {
-      0.0f, 0.6f, 0.9f,
-      0.0f, 0.6f, 0.9f,
-      0.0f, 0.6f, 0.9f,
-      0.0f, 0.6f, 0.9f,
-      0.0f, 0.6f, 0.9f,
-      0.0f, 0.6f, 0.9f,
-   };
-   objects[1].num_points = objects[1].points.size() / 3;
-
-   T_model = translate(mat4(), vec3(-0.5f, 0.0f, -1.00f));
-   R_model = rotate(mat4(), 0.5f, vec3(0.0f, 1.0f, 0.0f));
-   objects[1].model_mat = T_model*R_model;
-
-   vector<SceneObject>::iterator obj_it;
-   GLsizeiptr offset;
-
-   GLsizeiptr points_buffer_size = 0;
-   GLsizeiptr textures_buffer_size = 0;
-
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      points_buffer_size += obj_it->points.size() * sizeof(GLfloat);
-      textures_buffer_size += obj_it->texcoords.size() * sizeof(GLfloat);
-   }
-
-   GLuint points_vbo = 0;
-   glGenBuffers(1, &points_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->points.size() * sizeof(GLfloat), &obj_it->points[0]);
-      offset += obj_it->points.size() * sizeof(GLfloat);
-   }
-
-   GLuint colors_vbo = 0;
-   glGenBuffers(1, &colors_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->colors.size() * sizeof(GLfloat), &obj_it->colors[0]);
-      offset += obj_it->colors.size() * sizeof(GLfloat);
-   }
-
-   GLuint selected_colors_vbo = 0;
-   glGenBuffers(1, &selected_colors_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->selected_colors.size() * sizeof(GLfloat), &obj_it->selected_colors[0]);
-      offset += obj_it->selected_colors.size() * sizeof(GLfloat);
-   }
-
-   GLuint texcoords_vbo = 0;
-   glGenBuffers(1, &texcoords_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
-   glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->texcoords.size() * sizeof(GLfloat), &obj_it->texcoords[0]);
-      offset += obj_it->texcoords.size() * sizeof(GLfloat);
-   }
-
-   GLuint normals_vbo = 0;
-   glGenBuffers(1, &normals_vbo);
-   glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
-   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
-
-   offset = 0;
-   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
-      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->normals.size() * sizeof(GLfloat), &obj_it->normals[0]);
-      offset += obj_it->normals.size() * sizeof(GLfloat);
-   }
-
-   GLuint vao = 0;
-   glGenVertexArrays(1, &vao);
-   glBindVertexArray(vao);
-
-   glEnableVertexAttribArray(0);
-   glEnableVertexAttribArray(1);
-   glEnableVertexAttribArray(2);
-
-   GLuint vao2 = 0;
-   glGenVertexArrays(1, &vao2);
-   glBindVertexArray(vao2);
-
-   glEnableVertexAttribArray(0);
-   glEnableVertexAttribArray(1);
-   glEnableVertexAttribArray(2);
 
    // I can create a vbo to store all points for all models,
@@ -472,6 +283,207 @@
    // For now, I could implement this with a glDrawElements call per object and update the model uniform for each object
 
-   GLuint shader_program = loadShaderProgram("./color.vert", "./color.frag");
-   GLuint shader_program2 = loadShaderProgram("./texture.vert", "./texture.frag");
+   GLuint color_sp = loadShaderProgram("./color.vert", "./color.frag");
+   GLuint texture_sp = loadShaderProgram("./texture.vert", "./texture.frag");
+
+   mat4 T_model, R_model;
+
+   // triangle
+   objects.push_back(SceneObject());
+   objects[0].id = 0;
+   objects[0].shader_program = color_sp;
+   objects[0].vertex_vbo_offset = 0;
+   objects[0].points = {
+       0.0f,  0.5f,  0.0f,
+      -0.5f, -0.5f,  0.0f,
+       0.5f, -0.5f,  0.0f,
+       0.5f, -0.5f,  0.0f,
+      -0.5f, -0.5f,  0.0f,
+       0.0f,  0.5f,  0.0f,
+   };
+   objects[0].colors = {
+      1.0f, 0.0f, 0.0f,
+      0.0f, 0.0f, 1.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 0.0f, 1.0f,
+      1.0f, 0.0f, 0.0f,
+   };
+   objects[0].texcoords = {
+      1.0f, 1.0f,
+      0.0f, 1.0f,
+      0.0f, 0.0f,
+      1.0f, 1.0f,
+      0.0f, 0.0f,
+      1.0f, 0.0f
+   };
+   objects[0].normals = {
+       0.0f,  0.0f,  1.0f,
+       0.0f,  0.0f,  1.0f,
+       0.0f,  0.0f,  1.0f,
+       0.0f,  0.0f, -1.0f,
+       0.0f,  0.0f, -1.0f,
+       0.0f,  0.0f, -1.0f,
+   };
+   objects[0].selected_colors = {
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+   };
+   objects[0].num_points = objects[0].points.size() / 3;
+
+   T_model = translate(mat4(), vec3(0.45f, 0.0f, 0.0f));
+   R_model = rotate(mat4(), 0.0f, vec3(0.0f, 1.0f, 0.0f));
+   objects[0].model_mat = T_model*R_model;
+
+   // square
+   objects.push_back(SceneObject());
+   objects[1].id = 1;
+   objects[1].shader_program = texture_sp;
+   objects[1].vertex_vbo_offset = 6;
+   objects[1].points = {
+       0.5f,  0.5f,  0.0f,
+      -0.5f,  0.5f,  0.0f,
+      -0.5f, -0.5f,  0.0f,
+       0.5f,  0.5f,  0.0f,
+      -0.5f, -0.5f,  0.0f,
+       0.5f, -0.5f,  0.0f,
+   };
+   objects[1].colors = {
+      1.0f, 0.0f, 0.0f,
+      0.0f, 0.0f, 1.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 1.0f, 0.0f,
+      0.0f, 0.0f, 1.0f,
+      1.0f, 0.0f, 0.0f,
+   };
+   objects[1].texcoords = {
+      1.0f, 1.0f,
+      0.0f, 1.0f,
+      0.0f, 0.0f,
+      1.0f, 1.0f,
+      0.0f, 0.0f,
+      1.0f, 0.0f
+   };
+   objects[1].normals = {
+      0.0f,  0.0f,  1.0f,
+      0.0f,  0.0f,  1.0f,
+      0.0f,  0.0f,  1.0f,
+      0.0f,  0.0f,  1.0f,
+      0.0f,  0.0f,  1.0f,
+      0.0f,  0.0f,  1.0f,
+   };
+   objects[1].selected_colors = {
+      0.0f, 0.6f, 0.9f,
+      0.0f, 0.6f, 0.9f,
+      0.0f, 0.6f, 0.9f,
+      0.0f, 0.6f, 0.9f,
+      0.0f, 0.6f, 0.9f,
+      0.0f, 0.6f, 0.9f,
+   };
+   objects[1].num_points = objects[1].points.size() / 3;
+
+   T_model = translate(mat4(), vec3(-0.5f, 0.0f, -1.00f));
+   R_model = rotate(mat4(), 0.5f, vec3(0.0f, 1.0f, 0.0f));
+   objects[1].model_mat = T_model*R_model;
+
+   vector<SceneObject>::iterator obj_it;
+   GLsizeiptr offset;
+
+   GLsizeiptr points_buffer_size = 0;
+   GLsizeiptr textures_buffer_size = 0;
+
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      points_buffer_size += obj_it->points.size() * sizeof(GLfloat);
+      textures_buffer_size += obj_it->texcoords.size() * sizeof(GLfloat);
+   }
+
+   GLuint points_vbo = 0;
+   glGenBuffers(1, &points_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   offset = 0;
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->points.size() * sizeof(GLfloat), &obj_it->points[0]);
+      offset += obj_it->points.size() * sizeof(GLfloat);
+   }
+
+   GLuint colors_vbo = 0;
+   glGenBuffers(1, &colors_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   offset = 0;
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->colors.size() * sizeof(GLfloat), &obj_it->colors[0]);
+      offset += obj_it->colors.size() * sizeof(GLfloat);
+   }
+
+   GLuint selected_colors_vbo = 0;
+   glGenBuffers(1, &selected_colors_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   offset = 0;
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->selected_colors.size() * sizeof(GLfloat), &obj_it->selected_colors[0]);
+      offset += obj_it->selected_colors.size() * sizeof(GLfloat);
+   }
+
+   GLuint texcoords_vbo = 0;
+   glGenBuffers(1, &texcoords_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
+   glBufferData(GL_ARRAY_BUFFER, textures_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   offset = 0;
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->texcoords.size() * sizeof(GLfloat), &obj_it->texcoords[0]);
+      offset += obj_it->texcoords.size() * sizeof(GLfloat);
+   }
+
+   GLuint normals_vbo = 0;
+   glGenBuffers(1, &normals_vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
+   glBufferData(GL_ARRAY_BUFFER, points_buffer_size, NULL, GL_DYNAMIC_DRAW);
+
+   offset = 0;
+   for (obj_it = objects.begin(); obj_it != objects.end(); obj_it++) {
+      glBufferSubData(GL_ARRAY_BUFFER, offset, obj_it->normals.size() * sizeof(GLfloat), &obj_it->normals[0]);
+      offset += obj_it->normals.size() * sizeof(GLfloat);
+   }
+
+   GLuint vao = 0;
+   glGenVertexArrays(1, &vao);
+   glBindVertexArray(vao);
+
+   glEnableVertexAttribArray(0);
+   glEnableVertexAttribArray(1);
+   glEnableVertexAttribArray(2);
+
+   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
+   glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   GLuint vao2 = 0;
+   glGenVertexArrays(1, &vao2);
+   glBindVertexArray(vao2);
+
+   glEnableVertexAttribArray(0);
+   glEnableVertexAttribArray(1);
+   glEnableVertexAttribArray(2);
+
+   glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
+   glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+   glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
+   glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);
 
    float speed = 1.0f;
@@ -508,24 +520,21 @@
    proj_mat = make_mat4(proj_arr);
 
-   GLuint model_test_loc = glGetUniformLocation(shader_program, "model");
-   GLuint view_test_loc = glGetUniformLocation(shader_program, "view");
-   GLuint proj_test_loc = glGetUniformLocation(shader_program, "proj");
-
-   GLuint model_mat_loc = glGetUniformLocation(shader_program2, "model");
-   GLuint view_mat_loc = glGetUniformLocation(shader_program2, "view");
-   GLuint proj_mat_loc = glGetUniformLocation(shader_program2, "proj");
-
-   glUseProgram(shader_program);
+   GLuint model_test_loc = glGetUniformLocation(color_sp, "model");
+   GLuint view_test_loc = glGetUniformLocation(color_sp, "view");
+   GLuint proj_test_loc = glGetUniformLocation(color_sp, "proj");
+
+   GLuint model_mat_loc = glGetUniformLocation(texture_sp, "model");
+   GLuint view_mat_loc = glGetUniformLocation(texture_sp, "view");
+   GLuint proj_mat_loc = glGetUniformLocation(texture_sp, "proj");
+
+   glUseProgram(color_sp);
    glUniformMatrix4fv(model_test_loc, 1, GL_FALSE, value_ptr(objects[0].model_mat));
    glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
    glUniformMatrix4fv(proj_test_loc, 1, GL_FALSE, value_ptr(proj_mat));
 
-   glUseProgram(shader_program2);
+   glUseProgram(texture_sp);
    glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, value_ptr(objects[1].model_mat));
    glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
    glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, value_ptr(proj_mat));
-
-   objects[0].shader_program = shader_program;
-   objects[1].shader_program = shader_program2;
 
    bool cam_moved = false;
@@ -593,12 +602,4 @@
       }
 
-      if (selectedObject == &objects[1] &&
-         objects[1].shader_program == shader_program2) {
-         objects[1].shader_program = shader_program;
-      } else if (selectedObject != &objects[1] &&
-         objects[1].shader_program == shader_program) {
-         objects[1].shader_program = shader_program2;
-      }
-
       /*
       model[12] = last_position + speed*elapsed_seconds;
@@ -615,5 +616,5 @@
          case STATE_GAME:
             renderScene(objects,
-               shader_program, shader_program2,
+               color_sp, texture_sp,
                vao, vao2,
                model_test_loc, model_mat_loc,
@@ -665,8 +666,8 @@
          view_mat = R*T;
 
-         glUseProgram(shader_program);
+         glUseProgram(color_sp);
          glUniformMatrix4fv(view_test_loc, 1, GL_FALSE, value_ptr(view_mat));
 
-         glUseProgram(shader_program2);
+         glUseProgram(texture_sp);
          glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
 
@@ -817,6 +818,28 @@
 }
 
+// The easiest thing here seems to be to set all the colors we want in a CPU array once per frame,
+// them copy it over to the GPU and make one draw call
+// This method also easily allows us to use any colors we want for each shape.
+// Try to compare the frame times for the current method and the new one
+//
+// Alternatively, I have one large color buffer that has selected and unselected colors
+// Then, when I know which object is selected, I can use glVertexAttribPointer to decide
+// whether to use the selected or unselected color for it
+
+// I'll have to think of the best way to do something similar when using
+// one draw call. Probably, in that case, I'll use one draw call for all unselectable objects
+// and use the approach mentioned above for all selectable objects.
+// I can have one colors vbo for unselectable objects and another for selected+unselected colors
+// of selectable objects
+
+// For both colored and textured objects, using a single draw call will only work for objects
+// that don't change state (i.e. don't change colors or switch from colored to textured).
+
+// This means I'll probably have one call for static colored objects, one call for static textured objects,
+// a loop of calls for dynamic currently colored objects, and a loop of calls for dynamic currently textured objects.
+// This will increase if I add new shaders since I'll need either one new call or one new loop of calls per shader
+
 void renderScene(vector<SceneObject>& objects,
-                  GLuint shader_program1, GLuint shader_program2,
+                  GLuint color_sp, GLuint texture_sp,
                   GLuint vao1, GLuint vao2,
                   GLuint shader1_mat_loc, GLuint shader2_mat_loc,
@@ -824,19 +847,15 @@
                   GLuint colors_vbo, GLuint texcoords_vbo, GLuint selected_colors_vbo,
                   SceneObject* selectedObject) {
-   if (selectedObject == &objects[1]) {
-      objects[1].shader_program = shader_program1;
-   } else if (selectedObject != &objects[1]) {
-      objects[1].shader_program = shader_program2;
-   }
-
-   vector<int> program1_objects, program2_objects;
-
-   // group scene objects by shader
+
+   vector<int> colored_objs, selected_objs, textured_objs, static_colored_objs, static_textured_objs;
+
+   // group scene objects by shader and vbo
    for (unsigned int i = 0; i < objects.size(); i++) {
-      if (objects[i].shader_program == shader_program1) {
-         program1_objects.push_back(i);
-      }
-      else if (objects[i].shader_program == shader_program2) {
-         program2_objects.push_back(i);
+      if (selectedObject == &objects[i]) {
+         selected_objs.push_back(i);
+      } else if (objects[i].shader_program == color_sp) {
+         colored_objs.push_back(i);
+      } else if (objects[i].shader_program == texture_sp) {
+         textured_objs.push_back(i);
       }
    }
@@ -844,42 +863,32 @@
    vector<int>::iterator it;
 
-   glUseProgram(shader_program1);
+   glUseProgram(color_sp);
    glBindVertexArray(vao1);
 
-   for (it = program1_objects.begin(); it != program1_objects.end(); it++) {
+   glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
+   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   for (it = colored_objs.begin(); it != colored_objs.end(); it++) {
       glUniformMatrix4fv(shader1_mat_loc, 1, GL_FALSE, value_ptr(objects[*it].model_mat));
 
-      glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
-      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, objects[*it].vertex_vbo_offset);
-
-      if (selectedObject == &objects[*it]) {
-         glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
-      } else {
-         glBindBuffer(GL_ARRAY_BUFFER, colors_vbo);
-      }
-      glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, objects[*it].vertex_vbo_offset);
-
-      glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
-      glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, objects[*it].vertex_vbo_offset);
-
-      glDrawArrays(GL_TRIANGLES, 0, objects[*it].num_points);
-   }
-
-   glUseProgram(shader_program2);
+      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
+   }
+
+   glBindBuffer(GL_ARRAY_BUFFER, selected_colors_vbo);
+   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
+
+   for (it = selected_objs.begin(); it != selected_objs.end(); it++) {
+      glUniformMatrix4fv(shader1_mat_loc, 1, GL_FALSE, value_ptr(objects[*it].model_mat));
+
+      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
+   }
+
+   glUseProgram(texture_sp);
    glBindVertexArray(vao2);
 
-   for (it = program2_objects.begin(); it != program2_objects.end(); it++) {
+   for (it = textured_objs.begin(); it != textured_objs.end(); it++) {
       glUniformMatrix4fv(shader2_mat_loc, 1, GL_FALSE, value_ptr(objects[*it].model_mat));
 
-      glBindBuffer(GL_ARRAY_BUFFER, points_vbo);
-      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, objects[*it].vertex_vbo_offset);
-
-      glBindBuffer(GL_ARRAY_BUFFER, texcoords_vbo);
-      glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, objects[*it].texture_vbo_offset);
-
-      glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
-      glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, objects[*it].vertex_vbo_offset);
-
-      glDrawArrays(GL_TRIANGLES, 0, objects[*it].num_points);
+      glDrawArrays(GL_TRIANGLES, objects[*it].vertex_vbo_offset, objects[*it].num_points);
    }
 }
