Index: graphics_library/graphics_library.vcxproj
===================================================================
--- graphics_library/graphics_library.vcxproj	(revision 2ce51543b128ac8a1a9243f31d1d3774ee076a44)
+++ graphics_library/graphics_library.vcxproj	(revision 9cbdc9c1776765a4f73524cf019ae6a955b71877)
@@ -67,4 +67,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="common\controls.cpp" />
+    <ClCompile Include="common\shader.cpp" />
+    <ClCompile Include="common\texture.cpp" />
     <ClCompile Include="main.cpp" />
   </ItemGroup>
@@ -74,4 +77,11 @@
     <None Include="SimpleVertexShader.vertexshader" />
     <None Include="SingleColor.fragmentshader" />
+    <None Include="TextureFragmentShader.fragmentshader" />
+    <None Include="TransformVertexShader.vertexshader" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="common\controls.hpp" />
+    <ClInclude Include="common\shader.hpp" />
+    <ClInclude Include="common\texture.hpp" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
Index: graphics_library/graphics_library.vcxproj.filters
===================================================================
--- graphics_library/graphics_library.vcxproj.filters	(revision 2ce51543b128ac8a1a9243f31d1d3774ee076a44)
+++ graphics_library/graphics_library.vcxproj.filters	(revision 9cbdc9c1776765a4f73524cf019ae6a955b71877)
@@ -14,7 +14,22 @@
       <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
     </Filter>
+    <Filter Include="Header Files\common">
+      <UniqueIdentifier>{d934654a-a839-48d6-a4a6-a620fcaee36e}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="Source Files\common">
+      <UniqueIdentifier>{a04b1a63-118b-4076-b6ab-fafdf8011916}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="common\controls.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="common\shader.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="common\texture.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
@@ -33,4 +48,21 @@
       <Filter>Resource Files</Filter>
     </None>
+    <None Include="TextureFragmentShader.fragmentshader">
+      <Filter>Resource Files</Filter>
+    </None>
+    <None Include="TransformVertexShader.vertexshader">
+      <Filter>Resource Files</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="common\controls.hpp">
+      <Filter>Header Files\common</Filter>
+    </ClInclude>
+    <ClInclude Include="common\shader.hpp">
+      <Filter>Header Files\common</Filter>
+    </ClInclude>
+    <ClInclude Include="common\texture.hpp">
+      <Filter>Header Files\common</Filter>
+    </ClInclude>
   </ItemGroup>
 </Project>
Index: graphics_library/main.cpp
===================================================================
--- graphics_library/main.cpp	(revision 2ce51543b128ac8a1a9243f31d1d3774ee076a44)
+++ graphics_library/main.cpp	(revision 9cbdc9c1776765a4f73524cf019ae6a955b71877)
@@ -1,345 +1,246 @@
-#include <cstdio>
-#include <cstdlib>
-#include <string>
-#include <fstream>
-#include <vector>
-#include <algorithm>
-
+// Include standard headers
+#include <stdio.h>
+#include <stdlib.h>
+
+// Include GLEW
 #include <GL/glew.h>
+
+// Include GLFW
 #include <GL/glfw.h>
 
+// Include GLM
 #include <glm/glm.hpp>
 #include <glm/gtc/matrix_transform.hpp>
 using namespace glm;
 
-using namespace std;
-
-/*
-
-Rendering Pipeline
-
-All models are defined
-All vertices in each model are in model space
-
-Apply the model transformation to each model (based on model position, rotation, and scaling)
-This results in all vertices being in world space
-
-Apply the view transformation (based on camera position and rotation)
-Vertices are in camera coordinates
-
-Apply the projection matrix (camera lens angle, clipping planes) to turn coordinates into screen coordinates
-
-*/
-
-GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path);
-
-int main() {
-   // Initialise GLFW
-   if( !glfwInit() )
-   {
-      fprintf( stderr, "Failed to initialize GLFW\n" );
-      return -1;
-   }
-
-   glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4);
-   glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
-   glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
-   glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
-
-   // Open a window and create its OpenGL context
-   if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
-   {
-      fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
-      glfwTerminate();
-      return -1;
-   }
-
-   // Initialize GLEW
-   glewExperimental = true; // Needed for core profile
-   if (glewInit() != GLEW_OK) {
-      fprintf(stderr, "Failed to initialize GLEW\n");
-      return -1;
-   }
-
-   glfwSetWindowTitle( "Tutorial 02" );
-
-   // Ensure we can capture the escape key being pressed below
-   glfwEnable( GLFW_STICKY_KEYS );
-
-   // Dark blue background
-   glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
-
-   // Enable depth test
-   glEnable(GL_DEPTH_TEST);
-   // Accept fragment if it closer to the camera than the former one
-   glDepthFunc(GL_LESS);
-
-   GLuint VertexArrayID;
-   glGenVertexArrays(1, &VertexArrayID);
-   glBindVertexArray(VertexArrayID);
-
-   // Create and compile our GLSL program from the shaders
-   GLuint programID = LoadShaders( "SimpleTransform.vertexshader", "SingleColor.fragmentshader" );
-
-   // Get a handle for our "MVP" uniform
-   GLuint MatrixID = glGetUniformLocation(programID, "MVP");
-
-   // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
-   glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
-   // Or, for an ortho camera :
-   //glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates
+#include "common/shader.hpp"
+#include "common/texture.hpp"
+#include "common/controls.hpp"
+
+int main( void )
+{
+        // Initialise GLFW
+        if( !glfwInit() )
+        {
+                fprintf( stderr, "Failed to initialize GLFW\n" );
+                return -1;
+        }
+
+        glfwOpenWindowHint(GLFW_FSAA_SAMPLES, 4);
+        glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
+        glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3);
+        glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+
+        // Open a window and create its OpenGL context
+        if( !glfwOpenWindow( 1024, 768, 0,0,0,0, 32,0, GLFW_WINDOW ) )
+        {
+                fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" );
+                glfwTerminate();
+                return -1;
+        }
+
+        // Initialize GLEW
+        glewExperimental = true; // Needed for core profile
+        if (glewInit() != GLEW_OK) {
+                fprintf(stderr, "Failed to initialize GLEW\n");
+                return -1;
+        }
+
+        glfwSetWindowTitle( "Tutorial 06" );
+
+        // Ensure we can capture the escape key being pressed below
+        glfwEnable( GLFW_STICKY_KEYS );
+        glfwSetMousePos(1024/2, 768/2);
+
+        // Dark blue background
+        glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
+
+        // Enable depth test
+        glEnable(GL_DEPTH_TEST);
+        // Accept fragment if it closer to the camera than the former one
+        glDepthFunc(GL_LESS); 
+
+        // Cull triangles which normal is not towards the camera
+        glEnable(GL_CULL_FACE);
+
+        GLuint VertexArrayID;
+        glGenVertexArrays(1, &VertexArrayID);
+        glBindVertexArray(VertexArrayID);
+
+        // Create and compile our GLSL program from the shaders
+        GLuint programID = LoadShaders( "TransformVertexShader.vertexshader", "TextureFragmentShader.fragmentshader" );
+
+        // Get a handle for our "MVP" uniform
+        GLuint MatrixID = glGetUniformLocation(programID, "MVP");
+
+        // Load the texture
+        GLuint Texture = loadDDS("uvtemplate.DDS");
         
-   // Camera matrix
-   glm::mat4 View = glm::lookAt(
-      glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
-      glm::vec3(0,0,0), // and looks at the origin
-      glm::vec3(0,1,0)  // Head is up (set to 0,-1,0 to look upside-down)
-   );
-
-   // Model matrix : an identity matrix (model will be at the origin)
-   glm::mat4 Model = glm::mat4(1.0f);
-   // Our ModelViewProjection : multiplication of our 3 matrices
-   glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way around
-
-   // Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
-   // A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
-   static const GLfloat g_vertex_buffer_data[] = {
-      -1.0f,-1.0f,-1.0f, // triangle 1 : begin
-      -1.0f,-1.0f, 1.0f,
-      -1.0f, 1.0f, 1.0f, // triangle 1 : end
-      1.0f, 1.0f,-1.0f, // triangle 2 : begin
-      -1.0f,-1.0f,-1.0f,
-      -1.0f, 1.0f,-1.0f, // triangle 2 : end
-      1.0f,-1.0f, 1.0f,
-      -1.0f,-1.0f,-1.0f,
-      1.0f,-1.0f,-1.0f,
-      1.0f, 1.0f,-1.0f,
-      1.0f,-1.0f,-1.0f,
-      -1.0f,-1.0f,-1.0f,
-      -1.0f,-1.0f,-1.0f,
-      -1.0f, 1.0f, 1.0f,
-      -1.0f, 1.0f,-1.0f,
-      1.0f,-1.0f, 1.0f,
-      -1.0f,-1.0f, 1.0f,
-      -1.0f,-1.0f,-1.0f,
-      -1.0f, 1.0f, 1.0f,
-      -1.0f,-1.0f, 1.0f,
-      1.0f,-1.0f, 1.0f,
-      1.0f, 1.0f, 1.0f,
-      1.0f,-1.0f,-1.0f,
-      1.0f, 1.0f,-1.0f,
-      1.0f,-1.0f,-1.0f,
-      1.0f, 1.0f, 1.0f,
-      1.0f,-1.0f, 1.0f,
-      1.0f, 1.0f, 1.0f,
-      1.0f, 1.0f,-1.0f,
-      -1.0f, 1.0f,-1.0f,
-      1.0f, 1.0f, 1.0f,
-      -1.0f, 1.0f,-1.0f,
-      -1.0f, 1.0f, 1.0f,
-      1.0f, 1.0f, 1.0f,
-      -1.0f, 1.0f, 1.0f,
-      1.0f,-1.0f, 1.0f
-   };
-
-   GLuint vertexbuffer;
-   glGenBuffers(1, &vertexbuffer);
-   glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
-   glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
-
-   // One color for each vertex. They were generated randomly.
-   static const GLfloat g_color_buffer_data[] = {
-      0.583f,  0.771f,  0.014f,
-      0.609f,  0.115f,  0.436f,
-      0.327f,  0.483f,  0.844f,
-      0.822f,  0.569f,  0.201f,
-      0.435f,  0.602f,  0.223f,
-      0.310f,  0.747f,  0.185f,
-      0.597f,  0.770f,  0.761f,
-      0.559f,  0.436f,  0.730f,
-      0.359f,  0.583f,  0.152f,
-      0.483f,  0.596f,  0.789f,
-      0.559f,  0.861f,  0.639f,
-      0.195f,  0.548f,  0.859f,
-      0.014f,  0.184f,  0.576f,
-      0.771f,  0.328f,  0.970f,
-      0.406f,  0.615f,  0.116f,
-      0.676f,  0.977f,  0.133f,
-      0.971f,  0.572f,  0.833f,
-      0.140f,  0.616f,  0.489f,
-      0.997f,  0.513f,  0.064f,
-      0.945f,  0.719f,  0.592f,
-      0.543f,  0.021f,  0.978f,
-      0.279f,  0.317f,  0.505f,
-      0.167f,  0.620f,  0.077f,
-      0.347f,  0.857f,  0.137f,
-      0.055f,  0.953f,  0.042f,
-      0.714f,  0.505f,  0.345f,
-      0.783f,  0.290f,  0.734f,
-      0.722f,  0.645f,  0.174f,
-      0.302f,  0.455f,  0.848f,
-      0.225f,  0.587f,  0.040f,
-      0.517f,  0.713f,  0.338f,
-      0.053f,  0.959f,  0.120f,
-      0.393f,  0.621f,  0.362f,
-      0.673f,  0.211f,  0.457f,
-      0.820f,  0.883f,  0.371f,
-      0.982f,  0.099f,  0.879f
-   };
-
-   GLuint colorbuffer;
-   glGenBuffers(1, &colorbuffer);
-   glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
-   glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
-
-   do{
-
-      // Clear the screen
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-      // Use our shader
-      glUseProgram(programID);
-
-      // Send our transformation to the currently bound shader, 
-      // in the "MVP" uniform
-      glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
-
-      // 1rst attribute buffer : vertices
-      glEnableVertexAttribArray(0);
-      glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
-      glVertexAttribPointer(
-         0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
-         3,                  // size
-         GL_FLOAT,           // type
-         GL_FALSE,           // normalized?
-         0,                  // stride
-         (void*)0            // array buffer offset
-      );
-
-      // 2nd attribute buffer : colors
-      glEnableVertexAttribArray(1);
-      glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
-      glVertexAttribPointer(
-         1,                   // attribute. No particular reason for 1, but must match the layout in the shader.
-         3,                   // size
-         GL_FLOAT,            // type
-         GL_FALSE,            // normalized?
-         0,                   // stride
-         (void*)0             // array buffer offset
-      );
-
-      // Draw the triangle !
-      glDrawArrays(GL_TRIANGLES, 0, 12*3);
-
-      glDisableVertexAttribArray(0);
-
-      // Swap buffers
-      glfwSwapBuffers();
-
-   } // Check if the ESC key was pressed or the window was closed
-   while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
-      glfwGetWindowParam( GLFW_OPENED ) );
-
-   // Cleanup VBO
-   glDeleteBuffers(1, &vertexbuffer);
-   glDeleteProgram(programID);
-   glDeleteVertexArrays(1, &VertexArrayID);
-
-   // Close OpenGL window and terminate GLFW
-   glfwTerminate();
-
-   return 0;
+        // Get a handle for our "myTextureSampler" uniform
+        GLuint TextureID  = glGetUniformLocation(programID, "myTextureSampler");
+
+        // Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle.
+        // A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
+        static const GLfloat g_vertex_buffer_data[] = { 
+                -1.0f,-1.0f,-1.0f,
+                -1.0f,-1.0f, 1.0f,
+                -1.0f, 1.0f, 1.0f,
+                 1.0f, 1.0f,-1.0f,
+                -1.0f,-1.0f,-1.0f,
+                -1.0f, 1.0f,-1.0f,
+                 1.0f,-1.0f, 1.0f,
+                -1.0f,-1.0f,-1.0f,
+                 1.0f,-1.0f,-1.0f,
+                 1.0f, 1.0f,-1.0f,
+                 1.0f,-1.0f,-1.0f,
+                -1.0f,-1.0f,-1.0f,
+                -1.0f,-1.0f,-1.0f,
+                -1.0f, 1.0f, 1.0f,
+                -1.0f, 1.0f,-1.0f,
+                 1.0f,-1.0f, 1.0f,
+                -1.0f,-1.0f, 1.0f,
+                -1.0f,-1.0f,-1.0f,
+                -1.0f, 1.0f, 1.0f,
+                -1.0f,-1.0f, 1.0f,
+                 1.0f,-1.0f, 1.0f,
+                 1.0f, 1.0f, 1.0f,
+                 1.0f,-1.0f,-1.0f,
+                 1.0f, 1.0f,-1.0f,
+                 1.0f,-1.0f,-1.0f,
+                 1.0f, 1.0f, 1.0f,
+                 1.0f,-1.0f, 1.0f,
+                 1.0f, 1.0f, 1.0f,
+                 1.0f, 1.0f,-1.0f,
+                -1.0f, 1.0f,-1.0f,
+                 1.0f, 1.0f, 1.0f,
+                -1.0f, 1.0f,-1.0f,
+                -1.0f, 1.0f, 1.0f,
+                 1.0f, 1.0f, 1.0f,
+                -1.0f, 1.0f, 1.0f,
+                 1.0f,-1.0f, 1.0f
+        };
+
+        // Two UV coordinatesfor each vertex. They were created withe Blender.
+        static const GLfloat g_uv_buffer_data[] = { 
+                0.000059f, 0.000004f, 
+                0.000103f, 0.336048f, 
+                0.335973f, 0.335903f, 
+                1.000023f, 0.000013f, 
+                0.667979f, 0.335851f, 
+                0.999958f, 0.336064f, 
+                0.667979f, 0.335851f, 
+                0.336024f, 0.671877f, 
+                0.667969f, 0.671889f, 
+                1.000023f, 0.000013f, 
+                0.668104f, 0.000013f, 
+                0.667979f, 0.335851f, 
+                0.000059f, 0.000004f, 
+                0.335973f, 0.335903f, 
+                0.336098f, 0.000071f, 
+                0.667979f, 0.335851f, 
+                0.335973f, 0.335903f, 
+                0.336024f, 0.671877f, 
+                1.000004f, 0.671847f, 
+                0.999958f, 0.336064f, 
+                0.667979f, 0.335851f, 
+                0.668104f, 0.000013f, 
+                0.335973f, 0.335903f, 
+                0.667979f, 0.335851f, 
+                0.335973f, 0.335903f, 
+                0.668104f, 0.000013f, 
+                0.336098f, 0.000071f, 
+                0.000103f, 0.336048f, 
+                0.000004f, 0.671870f, 
+                0.336024f, 0.671877f, 
+                0.000103f, 0.336048f, 
+                0.336024f, 0.671877f, 
+                0.335973f, 0.335903f, 
+                0.667969f, 0.671889f, 
+                1.000004f, 0.671847f, 
+                0.667979f, 0.335851f
+        };
+
+        GLuint vertexbuffer;
+        glGenBuffers(1, &vertexbuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
+
+        GLuint uvbuffer;
+        glGenBuffers(1, &uvbuffer);
+        glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
+        glBufferData(GL_ARRAY_BUFFER, sizeof(g_uv_buffer_data), g_uv_buffer_data, GL_STATIC_DRAW);
+
+        do{
+
+                // Clear the screen
+                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+                // Use our shader
+                glUseProgram(programID);
+
+                // Compute the MVP matrix from keyboard and mouse input
+                computeMatricesFromInputs();
+                glm::mat4 ProjectionMatrix = getProjectionMatrix();
+                glm::mat4 ViewMatrix = getViewMatrix();
+                glm::mat4 ModelMatrix = glm::mat4(1.0);
+                glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
+
+                // Send our transformation to the currently bound shader, 
+                // in the "MVP" uniform
+                glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
+
+                // Bind our texture in Texture Unit 0
+                glActiveTexture(GL_TEXTURE0);
+                glBindTexture(GL_TEXTURE_2D, Texture);
+                // Set our "myTextureSampler" sampler to user Texture Unit 0
+                glUniform1i(TextureID, 0);
+
+                // 1rst attribute buffer : vertices
+                glEnableVertexAttribArray(0);
+                glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
+                glVertexAttribPointer(
+                        0,                  // attribute. No particular reason for 0, but must match the layout in the shader.
+                        3,                  // size
+                        GL_FLOAT,           // type
+                        GL_FALSE,           // normalized?
+                        0,                  // stride
+                        (void*)0            // array buffer offset
+                );
+
+                // 2nd attribute buffer : UVs
+                glEnableVertexAttribArray(1);
+                glBindBuffer(GL_ARRAY_BUFFER, uvbuffer);
+                glVertexAttribPointer(
+                        1,                                // attribute. No particular reason for 1, but must match the layout in the shader.
+                        2,                                // size : U+V => 2
+                        GL_FLOAT,                         // type
+                        GL_FALSE,                         // normalized?
+                        0,                                // stride
+                        (void*)0                          // array buffer offset
+                );
+
+                // Draw the triangle !
+                glDrawArrays(GL_TRIANGLES, 0, 12*3); // 12*3 indices starting at 0 -> 12 triangles
+
+                glDisableVertexAttribArray(0);
+                glDisableVertexAttribArray(1);
+
+                // Swap buffers
+                glfwSwapBuffers();
+
+        } // Check if the ESC key was pressed or the window was closed
+        while( glfwGetKey( GLFW_KEY_ESC ) != GLFW_PRESS &&
+                   glfwGetWindowParam( GLFW_OPENED ) );
+
+        // Cleanup VBO and shader
+        glDeleteBuffers(1, &vertexbuffer);
+        glDeleteBuffers(1, &uvbuffer);
+        glDeleteProgram(programID);
+        glDeleteTextures(1, &TextureID);
+        glDeleteVertexArrays(1, &VertexArrayID);
+
+        // Close OpenGL window and terminate GLFW
+        glfwTerminate();
+
+        return 0;
 }
-
-GLuint LoadShaders(const char * vertex_file_path,const char * fragment_file_path) {
- 
-   // Create the shaders
-   GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
-   GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
-
-   // Read the Vertex Shader code from the file
-   string VertexShaderCode;
-   ifstream VertexShaderStream(vertex_file_path, ios::in);
-   if(VertexShaderStream.is_open()){
-      string Line = "";
-      while(getline(VertexShaderStream, Line))
-            VertexShaderCode += "\n" + Line;
-      VertexShaderStream.close();
-   }else {
-      printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path);
-      getchar();
-      return 0;
-   }
-
-   // Read the Fragment Shader code from the file
-   string FragmentShaderCode;
-   ifstream FragmentShaderStream(fragment_file_path, ios::in);
-   if(FragmentShaderStream.is_open()) {
-      string Line = "";
-      while(getline(FragmentShaderStream, Line))
-         FragmentShaderCode += "\n" + Line;
-      FragmentShaderStream.close();
-   }
-
-
-
-   GLint Result = GL_FALSE;
-   int InfoLogLength;
-
-
-
-   // Compile Vertex Shader
-   printf("Compiling shader : %s\n", vertex_file_path);
-   char const * VertexSourcePointer = VertexShaderCode.c_str();
-   glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
-   glCompileShader(VertexShaderID);
-
-   // Check Vertex Shader
-   glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
-   glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-   if ( InfoLogLength > 0 ){
-      vector<char> VertexShaderErrorMessage(InfoLogLength+1);
-      glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
-      printf("%s\n", &VertexShaderErrorMessage[0]);
-   }
-
-
-
-   // Compile Fragment Shader
-   printf("Compiling shader : %s\n", fragment_file_path);
-   char const * FragmentSourcePointer = FragmentShaderCode.c_str();
-   glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
-   glCompileShader(FragmentShaderID);
-
-   // Check Fragment Shader
-   glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
-   glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-   if ( InfoLogLength > 0 ){
-      vector<char> FragmentShaderErrorMessage(InfoLogLength+1);
-      glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
-      printf("%s\n", &FragmentShaderErrorMessage[0]);
-   }
-
-
-
-   // Link the program
-   printf("Linking program\n");
-   GLuint ProgramID = glCreateProgram();
-   glAttachShader(ProgramID, VertexShaderID);
-   glAttachShader(ProgramID, FragmentShaderID);
-   glLinkProgram(ProgramID);
-
-   // Check the program
-   glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
-   glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-   if ( InfoLogLength > 0 ){
-      vector<char> ProgramErrorMessage(InfoLogLength+1);
-      glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
-      printf("%s\n", &ProgramErrorMessage[0]);
-   }
-
-   glDeleteShader(VertexShaderID);
-   glDeleteShader(FragmentShaderID);
-
-   return ProgramID;
-}
