Index: OpenGLGame.vcxproj
===================================================================
--- OpenGLGame.vcxproj	(revision 7d2b0b939e693b4a2e2af92be31aacc7500f7ada)
+++ OpenGLGame.vcxproj	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
@@ -23,4 +23,5 @@
     <ClCompile Include="FileStackWalker.cpp" />
     <ClCompile Include="game-gui-glfw.cpp" />
+    <ClCompile Include="graphics-pipeline_opengl.cpp" />
     <ClCompile Include="IMGUI\imgui.cpp" />
     <ClCompile Include="IMGUI\imgui_demo.cpp" />
@@ -39,4 +40,6 @@
     <ClInclude Include="game-gui-glfw.hpp" />
     <ClInclude Include="game-gui.hpp" />
+    <ClInclude Include="graphics-pipeline.hpp" />
+    <ClInclude Include="graphics-pipeline_opengl.hpp" />
     <ClInclude Include="IMGUI\imgui.h" />
     <ClInclude Include="IMGUI\imgui_internal.h" />
@@ -48,4 +51,14 @@
     <ClInclude Include="opengl-game.hpp" />
     <ClInclude Include="StackWalker.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="gl-shaders\asteroid.frag" />
+    <None Include="gl-shaders\asteroid.vert" />
+    <None Include="gl-shaders\explosion.frag" />
+    <None Include="gl-shaders\explosion.vert" />
+    <None Include="gl-shaders\laser.frag" />
+    <None Include="gl-shaders\laser.vert" />
+    <None Include="gl-shaders\ship.frag" />
+    <None Include="gl-shaders\ship.vert" />
   </ItemGroup>
   <PropertyGroup Label="Globals">
Index: graphics-pipeline_opengl.cpp
===================================================================
--- graphics-pipeline_opengl.cpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
+++ graphics-pipeline_opengl.cpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
@@ -0,0 +1,60 @@
+#include "graphics-pipeline_opengl.hpp"
+
+#include <iostream>
+#include <fstream>
+
+using namespace std;
+
+GraphicsPipeline_OpenGL::GraphicsPipeline_OpenGL() {
+}
+
+GraphicsPipeline_OpenGL::~GraphicsPipeline_OpenGL() {
+}
+
+void GraphicsPipeline_OpenGL::createPipeline(string vertShaderFile, string fragShaderFile) {
+   shaderProgram = loadShaderProgram(vertShaderFile, fragShaderFile);
+
+   glGenVertexArrays(1, &vao);
+   numPoints = 0;
+}
+
+GLuint GraphicsPipeline_OpenGL::loadShaderProgram(string vertShaderFile, string fragShaderFile) {
+   GLuint vs = loadShader(GL_VERTEX_SHADER, vertShaderFile);
+   GLuint fs = loadShader(GL_FRAGMENT_SHADER, fragShaderFile);
+
+   GLuint shader_program = glCreateProgram();
+   glAttachShader(shader_program, vs);
+   glAttachShader(shader_program, fs);
+
+   glLinkProgram(shader_program);
+
+   return shader_program;
+}
+
+GLuint GraphicsPipeline_OpenGL::loadShader(GLenum type, string file) {
+   cout << "Loading shader from file " << file << endl;
+
+   ifstream shaderFile(file);
+   GLuint shaderId = 0;
+
+   if (shaderFile.is_open()) {
+      string line, shaderString;
+
+      while (getline(shaderFile, line)) {
+         shaderString += line + "\n";
+      }
+      shaderFile.close();
+      const char* shaderCString = shaderString.c_str();
+
+      shaderId = glCreateShader(type);
+      glShaderSource(shaderId, 1, &shaderCString, NULL);
+      glCompileShader(shaderId);
+
+      cout << "Loaded successfully" << endl;
+   }
+   else {
+      cout << "Failed to load the file" << endl;
+   }
+
+   return shaderId;
+}
Index: graphics-pipeline_opengl.hpp
===================================================================
--- graphics-pipeline_opengl.hpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
+++ graphics-pipeline_opengl.hpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
@@ -0,0 +1,24 @@
+#ifndef _GRAPHICS_PIPELINE_OPENGL_H
+#define _GRAPHICS_PIPELINE_OPENGL_H
+
+#include <GL/glew.h>
+
+#include "graphics-pipeline.hpp"
+
+class GraphicsPipeline_OpenGL : public GraphicsPipeline {
+   public:
+      GraphicsPipeline_OpenGL();
+      ~GraphicsPipeline_OpenGL();
+
+      void createPipeline(string vertShaderFile, string fragShaderFile);
+
+   private:
+      GLuint shaderProgram;
+      GLuint vao;
+      unsigned int numPoints;
+
+      GLuint loadShaderProgram(string vertShaderFile, string fragShaderFile);
+      GLuint loadShader(GLenum type, string file);
+};
+
+#endif // _GRAPHICS_PIPELINE_OPENGL_H
Index: opengl-game.cpp
===================================================================
--- opengl-game.cpp	(revision 7d2b0b939e693b4a2e2af92be31aacc7500f7ada)
+++ opengl-game.cpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
@@ -103,4 +103,18 @@
    // Otherwise, it seems they get overridden by ImGui
    ((GameGui_GLFW*)gui)->bindEventHandlers();
+
+   graphicsPipelines.push_back(GraphicsPipeline_OpenGL());
+   graphicsPipelines.back().createPipeline("gl-shaders/ship.vert", "gl-shaders/ship.frag");
+
+   graphicsPipelines.push_back(GraphicsPipeline_OpenGL());
+   graphicsPipelines.back().createPipeline("gl-shaders/asteroid.vert", "gl-shaders/asteroid.frag");
+
+   graphicsPipelines.push_back(GraphicsPipeline_OpenGL());
+   graphicsPipelines.back().createPipeline("gl-shaders/laser.vert", "gl-shaders/laser.frag");
+
+   graphicsPipelines.push_back(GraphicsPipeline_OpenGL());
+   graphicsPipelines.back().createPipeline("gl-shaders/explosion.vert", "gl-shaders/explosion.frag");
+
+   cout << "Created " << graphicsPipelines.size() << " graphics pipelines" << endl;
 }
 
Index: opengl-game.hpp
===================================================================
--- opengl-game.hpp	(revision 7d2b0b939e693b4a2e2af92be31aacc7500f7ada)
+++ opengl-game.hpp	(revision 3de31cf9a2f6b3cc1cc099d6546879b28ff849e3)
@@ -6,4 +6,5 @@
 
 #include "game-gui-glfw.hpp"
+#include "graphics-pipeline_opengl.hpp"
 
 class OpenGLGame {
@@ -16,4 +17,7 @@
    private:
       GameGui* gui;
+
+      vector<GraphicsPipeline_OpenGL> graphicsPipelines;
+
       GLFWwindow* window;
 
