=== modified file 'data/shaders/bump-normals.frag'
--- data/shaders/bump-normals.frag	2011-07-19 10:09:30 +0000
+++ data/shaders/bump-normals.frag	2011-07-27 15:02:27 +0000
@@ -2,8 +2,6 @@
 precision mediump float;
 #endif
 
-uniform vec4 LightSourcePosition;
-uniform vec3 LightSourceHalfVector;
 uniform sampler2D NormalMap;
 uniform mat4 NormalMatrix;
 

=== modified file 'data/shaders/bump-poly.frag'
--- data/shaders/bump-poly.frag	2011-07-19 10:09:30 +0000
+++ data/shaders/bump-poly.frag	2011-07-27 15:02:27 +0000
@@ -2,9 +2,6 @@
 precision mediump float;
 #endif
 
-uniform vec4 LightSourcePosition;
-uniform vec3 LightSourceHalfVector;
-
 varying vec3 Normal;
 
 void main(void)

=== modified file 'data/shaders/light-advanced.frag'
--- data/shaders/light-advanced.frag	2011-07-13 15:03:43 +0000
+++ data/shaders/light-advanced.frag	2011-07-27 15:02:27 +0000
@@ -2,9 +2,6 @@
 precision mediump float;
 #endif
 
-uniform vec4 LightSourcePosition;
-uniform vec3 LightSourceHalfVector;
-
 varying vec3 Normal;
 
 void main(void)

=== modified file 'data/shaders/light-basic.vert'
--- data/shaders/light-basic.vert	2010-11-19 13:11:20 +0000
+++ data/shaders/light-basic.vert	2011-07-27 15:02:27 +0000
@@ -4,8 +4,6 @@
 
 uniform mat4 ModelViewProjectionMatrix;
 uniform mat4 NormalMatrix;
-uniform vec4 LightSourcePosition;
-uniform vec4 MaterialColor;
 
 varying vec4 Color;
 varying vec2 TextureCoord;
@@ -21,7 +19,7 @@
     // Multiply the diffuse value by the vertex color (which is fixed in this case)
     // to get the actual color that we will use to draw this vertex with
     float diffuse = max(dot(N, L), 0.0);
-    Color = diffuse * MaterialColor;
+    Color = diffuse * MaterialDiffuse;
 
     // Set the texture coordinates as a varying
     TextureCoord = texcoord;

=== modified file 'data/shaders/light-phong.frag'
--- data/shaders/light-phong.frag	2011-07-12 17:53:10 +0000
+++ data/shaders/light-phong.frag	2011-07-27 15:02:27 +0000
@@ -2,8 +2,6 @@
 precision mediump float;
 #endif
 
-uniform vec4 LightSourcePosition;
-
 varying vec3 vertex_normal;
 varying vec4 vertex_position;
 

=== modified file 'src/scene-build.cpp'
--- src/scene-build.cpp	2011-07-05 13:45:41 +0000
+++ src/scene-build.cpp	2011-07-27 15:02:27 +0000
@@ -25,6 +25,7 @@
 #include "log.h"
 #include "mat.h"
 #include "stack.h"
+#include "shader-source.h"
 #include <cmath>
 
 SceneBuild::SceneBuild(Canvas &pCanvas) :
@@ -44,6 +45,8 @@
 {
     static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
     static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.frag");
+    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
+    static const LibMatrix::vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 1.0f);
     Model model;
 
     if(!model.load_3ds(GLMARK_DATA_PATH"/models/horse.3ds"))
@@ -58,8 +61,14 @@
 
     model.convert_to_mesh(mMesh, attribs);
 
-    if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
-                                        frg_shader_filename))
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource frg_source(frg_shader_filename);
+
+    vtx_source.add_global_const("LightSourcePosition", lightPosition);
+    vtx_source.add_global_const("MaterialDiffuse", materialDiffuse);
+
+    if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
+                                          frg_source.str()))
     {
         return 0;
     }
@@ -88,10 +97,6 @@
 {
     Scene::setup();
 
-    static const LibMatrix::vec4 lightAmbient(0.0f, 0.0f, 0.0f, 1.0f);
-    static const LibMatrix::vec4 lightDiffuse(0.8f, 0.8f, 0.8f, 1.0f);
-    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
-    static const LibMatrix::vec4 materialColor(1.0f, 1.0f, 1.0f, 1.0f);
 
     mUseVbo = (mOptions["use-vbo"].value == "true");
     bool interleave = (mOptions["interleave"].value == "true");
@@ -103,12 +108,6 @@
 
     mProgram.start();
 
-    // Load lighting and material uniforms
-    mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
-    mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
-    mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
-    mProgram.loadUniformVector(materialColor, "MaterialColor");
-
     mCurrentFrame = 0;
     mRotation = 0.0;
     mRunning = true;

=== modified file 'src/scene-bump.cpp'
--- src/scene-bump.cpp	2011-07-19 11:57:20 +0000
+++ src/scene-bump.cpp	2011-07-27 15:02:27 +0000
@@ -23,6 +23,7 @@
 #include "log.h"
 #include "mat.h"
 #include "stack.h"
+#include "shader-source.h"
 #include <cmath>
 
 SceneBump::SceneBump(Canvas &pCanvas) :
@@ -56,8 +57,15 @@
     static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-poly.frag");
     static const std::string low_poly_filename(GLMARK_DATA_PATH"/models/asteroid-low.3ds");
     static const std::string high_poly_filename(GLMARK_DATA_PATH"/models/asteroid-high.3ds");
+    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
     Model model;
 
+    /* Calculate the half vector */
+    LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z());
+    halfVector.normalize();
+    halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
+    halfVector.normalize();
+
     std::string poly_filename = type == "high-poly" ?
                                 high_poly_filename : low_poly_filename;
 
@@ -73,8 +81,16 @@
 
     model.convert_to_mesh(mMesh, attribs);
 
-    if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
-                                        frg_shader_filename))
+    /* Load shaders */
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource frg_source(frg_shader_filename);
+
+    /* Add constants to shaders */
+    frg_source.add_global_const("LightSourcePosition", lightPosition);
+    frg_source.add_global_const("LightSourceHalfVector", halfVector);
+
+    if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
+                                          frg_source.str()))
     {
         return;
     }
@@ -90,11 +106,18 @@
 {
     static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals.vert");
     static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/bump-normals.frag");
+    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
     Model model;
 
     if(!model.load_3ds(GLMARK_DATA_PATH"/models/asteroid-low.3ds"))
         return;
 
+    /* Calculate the half vector */
+    LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z());
+    halfVector.normalize();
+    halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
+    halfVector.normalize();
+
     /* 
      * We don't care about the vertex normals. We are using a per-fragment
      * normal map (in object space coordinates).
@@ -105,8 +128,16 @@
 
     model.convert_to_mesh(mMesh, attribs);
 
-    if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
-                                        frg_shader_filename))
+    /* Load shaders */
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource frg_source(frg_shader_filename);
+
+    /* Add constants to shaders */
+    frg_source.add_global_const("LightSourcePosition", lightPosition);
+    frg_source.add_global_const("LightSourceHalfVector", halfVector);
+
+    if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
+                                          frg_source.str()))
     {
         return;
     }
@@ -131,22 +162,11 @@
     else if (bump_render == "off" || bump_render == "high-poly")
         setup_model_plain(bump_render);
 
-    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
 
     mMesh.build_vbo();
 
     mProgram.start();
 
-    // Load lighting and material uniforms
-    mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
-
-    // Calculate and load the half vector
-    LibMatrix::vec3 halfVector(lightPosition.x(), lightPosition.y(), lightPosition.z());
-    halfVector.normalize();
-    halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
-    halfVector.normalize();
-    mProgram.loadUniformVector(halfVector, "LightSourceHalfVector");
-
     // Load texture sampler value
     mProgram.loadUniformScalar(0, "NormalMap");
 

=== modified file 'src/scene-conditionals.cpp'
--- src/scene-conditionals.cpp	2011-07-07 13:59:05 +0000
+++ src/scene-conditionals.cpp	2011-07-27 15:03:54 +0000
@@ -24,6 +24,7 @@
 #include "stack.h"
 #include "vec.h"
 #include "log.h"
+#include "shader-source.h"
 
 #include <cmath>
 #include <sstream>
@@ -52,69 +53,40 @@
 {
 }
 
-static std::string &
-replace_string(std::string &str, const std::string &remove, const std::string &insert)
-{
-    std::string::size_type pos = 0;
-
-    while ((pos = str.find(remove, pos)) != std::string::npos) {
-        str.replace(pos, remove.size(), insert);
-        pos++;
-    }
-
-    return str;
-}
-
 static std::string
 get_vertex_shader_source(int steps, bool conditionals)
 {
-    std::string vtx_string, step_conditional_string, step_simple_string;
-
-    if (!gotSource(vtx_file, vtx_string) ||
-        !gotSource(step_conditional_file, step_conditional_string) ||
-        !gotSource(step_simple_file, step_simple_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
+    ShaderSource source(vtx_file);
+    ShaderSource source_main;
 
     for (int i = 0; i < steps; i++) {
         if (conditionals)
-            ss_main << step_conditional_string;
+            source_main.append_file(step_conditional_file);
         else
-            ss_main  << step_simple_string;
+            source_main.append_file(step_simple_file);
     }
 
-    replace_string(vtx_string, "$MAIN$", ss_main.str());
+    source.replace("$MAIN$", source_main.str());
 
-    return vtx_string;
+    return source.str();
 }
 
 static std::string
 get_fragment_shader_source(int steps, bool conditionals)
 {
-    std::string frg_string, step_conditional_string, step_simple_string;
-
-    if (!gotSource(frg_file, frg_string) ||
-        !gotSource(step_conditional_file, step_conditional_string) ||
-        !gotSource(step_simple_file, step_simple_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
+    ShaderSource source(frg_file);
+    ShaderSource source_main;
 
     for (int i = 0; i < steps; i++) {
         if (conditionals)
-            ss_main << step_conditional_string;
+            source_main.append_file(step_conditional_file);
         else
-            ss_main  << step_simple_string;
+            source_main.append_file(step_simple_file);
     }
 
-    replace_string(frg_string, "$MAIN$", ss_main.str());
+    source.replace("$MAIN$", source_main.str());
 
-    return frg_string;
+    return source.str();
 }
 
 void SceneConditionals::setup()

=== modified file 'src/scene-function.cpp'
--- src/scene-function.cpp	2011-07-07 13:35:24 +0000
+++ src/scene-function.cpp	2011-07-27 15:03:54 +0000
@@ -24,6 +24,7 @@
 #include "stack.h"
 #include "vec.h"
 #include "log.h"
+#include "shader-source.h"
 
 #include <sstream>
 
@@ -56,85 +57,62 @@
 {
 }
 
-static std::string &
-replace_string(std::string &str, const std::string &remove, const std::string &insert)
-{
-    std::string::size_type pos = 0;
-
-    while ((pos = str.find(remove, pos)) != std::string::npos) {
-        str.replace(pos, remove.size(), insert);
-        pos++;
-    }
-
-    return str;
-}
-
 static std::string
 get_vertex_shader_source(int steps, bool function, std::string &complexity)
 {
-    std::string vtx_string, step_low_string, step_medium_string, call_string;
-
-    if (!gotSource(vtx_file, vtx_string) ||
-        !gotSource(step_low_file, step_low_string) ||
-        !gotSource(step_medium_file, step_medium_string) ||
-        !gotSource(call_file, call_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
-    std::string process_string;
+    ShaderSource source(vtx_file);
+    ShaderSource source_main;
+    std::string step_file;
 
     if (complexity == "low")
-        process_string = step_low_string;
+        step_file = step_low_file;
     else if (complexity == "medium")
-        process_string = step_medium_string;
+        step_file = step_medium_file;
 
     for (int i = 0; i < steps; i++) {
         if (function)
-            ss_main << call_string;
+            source_main.append_file(call_file);
         else
-            ss_main << process_string;
+            source_main.append_file(step_file);
     }
 
-    replace_string(vtx_string, "$PROCESS$", function ? process_string : "");
-    replace_string(vtx_string, "$MAIN$", ss_main.str());
-
-    return vtx_string;
+    if (function)
+        source.replace_with_file("$PROCESS$", step_file);
+    else
+        source.replace("$PROCESS$", "");
+
+    source.replace("$MAIN$", source_main.str());
+
+    return source.str();
 }
 
 static std::string
 get_fragment_shader_source(int steps, bool function, std::string &complexity)
 {
-    std::string frg_string, step_low_string, step_medium_string, call_string;
-
-    if (!gotSource(frg_file, frg_string) ||
-        !gotSource(step_low_file, step_low_string) ||
-        !gotSource(step_medium_file, step_medium_string) ||
-        !gotSource(call_file, call_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
-    std::string process_string;
+    ShaderSource source(frg_file);
+    ShaderSource source_main;
+    std::string step_file;
 
     if (complexity == "low")
-        process_string = step_low_string;
+        step_file = step_low_file;
     else if (complexity == "medium")
-        process_string = step_medium_string;
+        step_file = step_medium_file;
 
     for (int i = 0; i < steps; i++) {
         if (function)
-            ss_main << call_string;
+            source_main.append_file(call_file);
         else
-            ss_main << process_string;
+            source_main.append_file(step_file);
     }
 
-    replace_string(frg_string, "$PROCESS$", function ? process_string : "");
-    replace_string(frg_string, "$MAIN$", ss_main.str());
-
-    return frg_string;
+    if (function)
+        source.replace_with_file("$PROCESS$", step_file);
+    else
+        source.replace("$PROCESS$", "");
+
+    source.replace("$MAIN$", source_main.str());
+
+    return source.str();
 }
 
 void SceneFunction::setup()

=== modified file 'src/scene-loop.cpp'
--- src/scene-loop.cpp	2011-07-08 13:00:36 +0000
+++ src/scene-loop.cpp	2011-07-27 15:03:54 +0000
@@ -24,6 +24,7 @@
 #include "stack.h"
 #include "vec.h"
 #include "log.h"
+#include "shader-source.h"
 
 #include <sstream>
 
@@ -55,87 +56,58 @@
 {
 }
 
-static std::string &
-replace_string(std::string &str, const std::string &remove, const std::string &insert)
-{
-    std::string::size_type pos = 0;
-
-    while ((pos = str.find(remove, pos)) != std::string::npos) {
-        str.replace(pos, remove.size(), insert);
-        pos++;
-    }
-
-    return str;
-}
-
 static std::string
 get_fragment_shader_source(int steps, bool loop, bool uniform)
 {
-    std::string frg_string, step_simple_string, step_loop_string;
-
-    if (!gotSource(frg_file, frg_string) ||
-        !gotSource(step_simple_file, step_simple_string) ||
-        !gotSource(step_loop_file, step_loop_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
+    ShaderSource source(frg_file);
+    ShaderSource source_main;
 
     if (loop) {
+        source_main.append_file(step_loop_file);
         if (uniform) {
-            replace_string(step_loop_string, "$NLOOPS$", "FragmentLoops");
+            source_main.replace("$NLOOPS$", "FragmentLoops");
         }
         else {
             std::stringstream ss_steps;
             ss_steps << steps;
-            replace_string(step_loop_string, "$NLOOPS$", ss_steps.str());
+            source_main.replace("$NLOOPS$", ss_steps.str());
         }
-        ss_main << step_loop_string;
     }
     else {
         for (int i = 0; i < steps; i++)
-            ss_main << step_simple_string;
+            source_main.append_file(step_simple_file);
     }
 
-    replace_string(frg_string, "$MAIN$", ss_main.str());
+    source.replace("$MAIN$", source_main.str());
 
-    return frg_string;
+    return source.str();
 }
 
 static std::string
 get_vertex_shader_source(int steps, bool loop, bool uniform)
 {
-    std::string vtx_string, step_simple_string, step_loop_string;
-
-    if (!gotSource(vtx_file, vtx_string) ||
-        !gotSource(step_simple_file, step_simple_string) ||
-        !gotSource(step_loop_file, step_loop_string))
-    {
-        return "";
-    }
-
-    std::stringstream ss_main;
+    ShaderSource source(vtx_file);
+    ShaderSource source_main;
 
     if (loop) {
+        source_main.append_file(step_loop_file);
         if (uniform) {
-            replace_string(step_loop_string, "$NLOOPS$", "VertexLoops");
+            source_main.replace("$NLOOPS$", "VertexLoops");
         }
         else {
             std::stringstream ss_steps;
             ss_steps << steps;
-            replace_string(step_loop_string, "$NLOOPS$", ss_steps.str());
+            source_main.replace("$NLOOPS$", ss_steps.str());
         }
-        ss_main << step_loop_string;
     }
     else {
         for (int i = 0; i < steps; i++)
-            ss_main << step_simple_string;
+            source_main.append_file(step_simple_file);
     }
 
-    replace_string(vtx_string, "$MAIN$", ss_main.str());
+    source.replace("$MAIN$", source_main.str());
 
-    return vtx_string;
+    return source.str();
 }
 
 

=== modified file 'src/scene-shading.cpp'
--- src/scene-shading.cpp	2011-07-19 12:00:29 +0000
+++ src/scene-shading.cpp	2011-07-27 15:02:27 +0000
@@ -26,6 +26,7 @@
 #include "stack.h"
 #include "vec.h"
 #include "log.h"
+#include "shader-source.h"
 
 #include <cmath>
 
@@ -77,6 +78,12 @@
     static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
     static const LibMatrix::vec4 materialDiffuse(0.0f, 0.0f, 1.0f, 1.0f);
 
+    // Calculate half vector for blinn-phong shading model
+    LibMatrix::vec3 halfVector(lightPosition[0], lightPosition[1], lightPosition[2]);
+    halfVector.normalize();
+    halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
+    halfVector.normalize();
+
     std::string vtx_shader_filename;
     std::string frg_shader_filename;
     const std::string &shading = mOptions["shading"].value;
@@ -94,8 +101,19 @@
         frg_shader_filename = GLMARK_DATA_PATH"/shaders/light-phong.frag";
     }
 
-    if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
-                                        frg_shader_filename))
+    // Load shaders
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource frg_source(frg_shader_filename);
+
+    // Add constants to shaders
+    vtx_source.add_global_const("LightSourcePosition", lightPosition);
+    vtx_source.add_global_const("MaterialDiffuse", materialDiffuse);
+
+    frg_source.add_global_const("LightSourcePosition", lightPosition);
+    frg_source.add_global_const("LightSourceHalfVector", halfVector);
+
+    if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
+                                          frg_source.str()))
     {
         return;
     }
@@ -107,15 +125,6 @@
     attrib_locations.push_back(mProgram.getAttribIndex("normal"));
     mMesh.set_attrib_locations(attrib_locations);
 
-    // Load lighting and material uniforms
-    mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
-    mProgram.loadUniformVector(materialDiffuse, "MaterialColor");
-    LibMatrix::vec3 halfVector(lightPosition[0], lightPosition[1], lightPosition[2]);
-    halfVector.normalize();
-    halfVector += LibMatrix::vec3(0.0, 0.0, 1.0);
-    halfVector.normalize();
-    mProgram.loadUniformVector(halfVector, "LightSourceHalfVector");
-
     mCurrentFrame = 0;
     mRotation = 0.0f;
     mRunning = true;

=== modified file 'src/scene-texture.cpp'
--- src/scene-texture.cpp	2011-07-05 13:45:41 +0000
+++ src/scene-texture.cpp	2011-07-27 15:02:27 +0000
@@ -26,8 +26,9 @@
 #include "stack.h"
 #include "vec.h"
 #include "log.h"
-
 #include "program.h"
+#include "shader-source.h"
+
 #include <cmath>
 
 SceneTexture::SceneTexture(Canvas &pCanvas) :
@@ -45,6 +46,9 @@
 {
     static const std::string vtx_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic.vert");
     static const std::string frg_shader_filename(GLMARK_DATA_PATH"/shaders/light-basic-tex.frag");
+    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
+    static const LibMatrix::vec4 materialDiffuse(1.0f, 1.0f, 1.0f, 1.0f);
+
     Model model;
 
     if(!model.load_3ds(GLMARK_DATA_PATH"/models/cube.3ds"))
@@ -54,8 +58,16 @@
     model.convert_to_mesh(mCubeMesh);
     mCubeMesh.build_vbo();
 
-    if (!Scene::load_shaders_from_files(mProgram, vtx_shader_filename,
-                                        frg_shader_filename))
+    // Load shaders
+    ShaderSource vtx_source(vtx_shader_filename);
+    ShaderSource frg_source(frg_shader_filename);
+
+    // Add constants to shaders
+    vtx_source.add_global_const("LightSourcePosition", lightPosition);
+    vtx_source.add_global_const("MaterialDiffuse", materialDiffuse);
+
+    if (!Scene::load_shaders_from_strings(mProgram, vtx_source.str(),
+                                          frg_source.str()))
     {
         return 0;
     }
@@ -85,11 +97,6 @@
 {
     Scene::setup();
 
-    static const LibMatrix::vec4 lightAmbient(0.0f, 0.0f, 0.0f, 1.0f);
-    static const LibMatrix::vec4 lightDiffuse(0.8f, 0.8f, 0.8f, 1.0f);
-    static const LibMatrix::vec4 lightPosition(20.0f, 20.0f, 10.0f, 1.0f);
-    static const LibMatrix::vec4 materialColor(1.0f, 1.0f, 1.0f, 1.0f);
-
     // Create texture according to selected filtering
     GLint min_filter = GL_NONE;
     GLint mag_filter = GL_NONE;
@@ -113,12 +120,6 @@
 
     mProgram.start();
 
-    // Load lighting and material uniforms
-    mProgram.loadUniformVector(lightAmbient, "LightSourceAmbient");
-    mProgram.loadUniformVector(lightPosition, "LightSourcePosition");
-    mProgram.loadUniformVector(lightDiffuse, "LightSourceDiffuse");
-    mProgram.loadUniformVector(materialColor, "MaterialColor");
-
     mCurrentFrame = 0;
     mRotation = LibMatrix::vec3();
     mRunning = true;

=== added file 'src/shader-source.cpp'
--- src/shader-source.cpp	1970-01-01 00:00:00 +0000
+++ src/shader-source.cpp	2011-07-27 14:43:40 +0000
@@ -0,0 +1,190 @@
+/*
+ * Copyright © 2010-2011 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis (glmark2)
+ */
+
+#include <fstream>
+
+#include "shader-source.h"
+#include "log.h"
+#include "vec.h"
+
+/** 
+ * Loads the contents of a file into a string.
+ * 
+ * @param filename the name of the file
+ * @param str the string to put the contents of the file into
+ */
+bool
+ShaderSource::load_file(const std::string& filename, std::string& str)
+{
+    using std::ifstream;
+    ifstream inputFile(filename.c_str());
+    if (!inputFile)
+    {
+        Log::error("Failed to open \"%s\"\n", filename.c_str());
+        return false;
+    }
+
+    std::string curLine;
+    while (getline(inputFile, curLine))
+    {
+        str += curLine;
+        str += '\n';
+    }
+
+    return true;
+}
+
+
+/** 
+ * Appends a string to the shader source.
+ * 
+ * @param str the string to append
+ */
+void
+ShaderSource::append(const std::string &str)
+{
+    source_ << str;
+}
+
+/** 
+ * Appends the contents of a file to the shader source.
+ * 
+ * @param filename the name of the file to append
+ */
+void
+ShaderSource::append_file(const std::string &filename)
+{
+    std::string source;
+    if (load_file(filename, source))
+        source_ << source;
+}
+
+/** 
+ * Replaces a string in the source with another string.
+ * 
+ * @param remove the string to replace
+ * @param insert the string to replace with
+ */
+void
+ShaderSource::replace(const std::string &remove, const std::string &insert)
+{
+    std::string::size_type pos = 0;
+    std::string str(source_.str());
+
+    while ((pos = str.find(remove, pos)) != std::string::npos) {
+        str.replace(pos, remove.size(), insert);
+        pos++;
+    }
+
+    source_.clear();
+    source_.str(str);
+}
+
+/** 
+ * Replaces a string in the source with the contents of a file.
+ * 
+ * @param remove the string to replace
+ * @param filename the name of the file to read from
+ */
+void
+ShaderSource::replace_with_file(const std::string &remove, const std::string &filename)
+{
+    std::string source;
+    if (load_file(filename, source))
+        replace(remove, source);
+}
+
+/** 
+ * Adds a string (usually containing a constant definition) at
+ * global (per shader) scope.
+ *
+ * The string is placed after any default precision qualifiers.
+ * 
+ * @param str the string to add
+ */
+void
+ShaderSource::add_global(const std::string &str)
+{
+    std::string::size_type pos = 0;
+    std::string source(source_.str());
+
+    /* Find the last precision qualifier */
+    pos = source.rfind("precision");
+
+    if (pos != std::string::npos) {
+        /* 
+         * Find the next #endif line of a preprocessor block that contains
+         * the precision qualifier.
+         */
+        std::string::size_type pos_if = source.find("#if", pos);
+        std::string::size_type pos_endif = source.find("#endif", pos);
+
+        if (pos_endif != std::string::npos && pos_endif < pos_if)
+            pos = pos_endif;
+
+        /* Go to the next line */
+        pos = source.find("\n", pos);
+        if (pos != std::string::npos)
+            pos++;
+    }
+    else
+        pos = 0;
+
+    source.insert(pos, str);
+
+    source_.clear();
+    source_.str(source);
+}
+
+/** 
+ * Adds a global (per shader) vec3 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ */
+void
+ShaderSource::add_global_const(const std::string &name, const LibMatrix::vec3 &v)
+{
+    std::stringstream ss;
+
+    ss << "const vec3 " << name << " = vec3(" << std::fixed;
+    ss << v.x() << ", " << v.y() << ", " << v.z() << ");" << std::endl;
+
+    add_global(ss.str());
+}
+
+/** 
+ * Adds a global (per shader) vec4 constant definition.
+ *
+ * @param name the name of the constant
+ * @param v the value of the constant
+ */
+void
+ShaderSource::add_global_const(const std::string &name, const LibMatrix::vec4 &v)
+{
+    std::stringstream ss;
+
+    ss << "const vec4 " << name << " = vec4(" << std::fixed;
+    ss << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w() << ");" << std::endl;
+
+    add_global(ss.str());
+}

=== added file 'src/shader-source.h'
--- src/shader-source.h	1970-01-01 00:00:00 +0000
+++ src/shader-source.h	2011-07-27 14:43:40 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright © 2010-2011 Linaro Limited
+ *
+ * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
+ *
+ * glmark2 is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 3 of the License, or (at your option) any later
+ * version.
+ *
+ * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * glmark2.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *  Alexandros Frantzis (glmark2)
+ */
+
+#include <string>
+#include <sstream>
+#include "vec.h"
+
+/** 
+ * Helper class for loading and manipulating shader sources.
+ */
+class ShaderSource
+{
+public:
+    ShaderSource() {}
+    ShaderSource(const std::string &filename) { append_file(filename); }
+
+    void append(const std::string &str);
+    void append_file(const std::string &filename);
+
+    void replace(const std::string &remove, const std::string &insert);
+    void replace_with_file(const std::string &remove, const std::string &filename);
+
+    void add_global(const std::string &str);
+    void add_global_const(const std::string &name, const LibMatrix::vec3 &v);
+    void add_global_const(const std::string &name, const LibMatrix::vec4 &v);
+
+    std::string str() { return source_.str(); }
+
+private:
+    bool load_file(const std::string& filename, std::string& str);
+
+    std::stringstream source_;
+};

