Jason McKesson avatar Jason McKesson committed bb87c5c

Updated tutorials 9-11 to use UBOs. Updated docs to use new code.

Comments (0)

Files changed (30)

Documents/Illumination/Tutorial 09.xml

 uniform vec3 dirToLight;
 uniform vec4 lightIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+    mat4 cameraToClipMatrix;
+};
 
 void main()
 {
                 is the direction from the surface <emphasis>towards</emphasis> the light. It is not
                 the direction <emphasis>from</emphasis> the light.</para>
             <para>We also have a light intensity uniform value, as well as two matrices for
-                positions and a separate one for normals.</para>
+                positions and a separate one for normals. Notice that the
+                    <varname>cameraToClipMatrix</varname> is in a uniform block. This allows us to
+                update all programs that use the projection matrix just by changing the buffer
+                object.</para>
             <para>The first line of <function>main</function> simply does the position transforms we
                 need to position our vertices, as we have seen before. We don't need to store the
                 camera-space position, so we can do the entire transformation in a single
 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+    mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Documents/Illumination/Tutorial 10.xml

         <para>The light is computed initially in world space, then transformed into camera space.
             The camera-space light position is given to both of the shaders. Rendering proceeds
             normally from there.</para>
-        <para>Our vertex shader has had a few changes:</para>
+        <para>Our vertex shader, <filename>PosVertexLighting_PCN.vert</filename> has had a few
+            changes:</para>
         <example>
             <title>Per-Vertex Point Light Vertex Shader</title>
             <programlisting>#version 330
 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+    mat4 cameraToClipMatrix;
+};
 
 void main()
 {
 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
+
+uniform Projection
+{
+    mat4 cameraToClipMatrix;
+};
 
 void main()
 {
 out vec3 vertexNormal;
 out vec3 modelSpacePosition;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+    mat4 cameraToClipMatrix;
+};
+
 void main()
 {
     gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));
             necessary because interpolating between two unit vectors does not mean you will get a
             unit vector after interpolation. Indeed, interpolating the 3 components guarantees that
             you will not get a unit vector.</para>
+        <!-- 
         <section>
             <title>Caught in a Lie</title>
             <para>While this may look perfect, there is still one problem. Use the <keycombo>
                 more vertices, more executions of our (admittedly simple) vertex shader, and more
                 triangles rasterized or discarded for being back-facing.</para>
         </section>
+        -->
     </section>
     <section>
         <?dbhtml filename="Tut10 Distant Points of Light.html" ?>
                 changed from the last one, but there have been some additions:</para>
             <example>
                 <title>Light Attenuation Fragment Shader Definitions</title>
-                <programlisting language="glsl">uniform mat4 clipToCameraMatrix;
-uniform ivec2 windowSize;
-uniform vec2 depthRange;
+                <programlisting language="glsl">uniform float lightAttenuation;
+uniform bool bUseRSquare;
 
-uniform float lightAttenuation;
-uniform bool bUseRSquare;</programlisting>
+uniform UnProjection
+{
+    mat4 clipToCameraMatrix;
+    ivec2 windowSize;
+};</programlisting>
             </example>
-            <para>The first three lines are the information we need to perform the
-                previously-discussed reverse-transformation, so that we can turn
-                    <varname>gl_FragCoord</varname> into a camera-space position. Notice that the
-                    <varname>windowSize</varname> uses a new type: <type>ivec2</type>. This is a
-                2-dimensional vector of integers.</para>
-            <para>Thus far, we have only modified uniforms of floating-point type. All of the vector
-                uploading functions we have used have been of the forms
-                    <function>glUniform#f</function> or <function>glUniform#fv</function>, where the
-                # is a number 1-4. The <quote>v</quote> represents a vector version, which takes a
-                pointer instead of 1-4 parameters.</para>
-            <para>Uploading to an integer uniform uses functions of the form
-                    <function>glUniform#i</function> and <function>glUniform#iv</function>. So the
-                code we use to set the window size uniform is this:</para>
-            <programlisting language="cpp">glUniform2i(g_FragWhiteDiffuseColor.windowSizeUnif, w, h);</programlisting>
-            <para>The <varname>w</varname> and <varname>h</varname> values are the width and height
-                passed to the <function>reshape</function> function. That is where this line of code
-                is, and that is where we set both the clip-to-camera matrix and the window size. The
-                    <varname>depthRange</varname> is set in the initialization code, since it never
-                changes.</para>
             <para>The <varname>lightAttenuation</varname> uniform is just a float, but
                     <varname>bUseRSquare</varname> uses a new type: boolean.</para>
             <para>GLSL has the <type>bool</type> type just like C++ does. The
             <para>The integer form of uniform uploading is used, but the floating-point form could
                 be allowed as well. The number 0 represents false, and any other number is
                 true.</para>
+            <para>The <classname>UnProjection</classname> uniform block contains data that only
+                changes when the window changes. This uniform block is updated along with the vertex
+                shader's <classname>Projection</classname> block. This data is used to perform the
+                previously-discussed reverse-transformation operation, so that we can turn
+                    <varname>gl_FragCoord</varname> into a camera-space position.</para>
+            <para>Notice that the <varname>windowSize</varname> uses a new type: <type>ivec2</type>.
+                This is a 2-dimensional vector of integers.</para>
         </section>
         <section>
             <title>Functions in GLSL</title>
                 <title>Window to Camera Space Function</title>
                 <programlisting language="glsl">vec3 CalcCameraSpacePosition()
 {
-    vec3 ndcPos;
+    vec4 ndcPos;
     ndcPos.xy = ((gl_FragCoord.xy / windowSize.xy) * 2.0) - 1.0;
-    ndcPos.z = (2.0 * gl_FragCoord.z - depthRange.x - depthRange.y) / (depthRange.y - depthRange.x);
+    ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
+        (gl_DepthRange.far - gl_DepthRange.near);
+    ndcPos.w = 1.0;
     
-    vec4 clipPos;
-    clipPos.w = 1.0f / gl_FragCoord.w;
-    clipPos.xyz = ndcPos.xyz * clipPos.w;
+    vec4 clipPos = ndcPos / gl_FragCoord.w;
     
     return vec3(clipToCameraMatrix * clipPos);
 }</programlisting>
                 original function. This is because our viewport always sets the lower-left position
                 of the viewport to (0, 0). This is what you get when you plug zeros into that
                 equation.</para>
-            <para>From there, the clip-space position is computed as previously shown. Then the
-                result is multiplied through the clip-to-camera matrix, and that vector is returned
-                to the caller.</para>
+            <para>The <varname>gl_DepthRange</varname> variable is a special uniform defined by GLSL
+                for fragment shaders. As the name suggests, it properly mirrors the values passed to
+                    <function>glDepthRange</function>; this way, we do not have to put it in our
+                uniform block.</para>
+            <para>After the transformation to NDC space, we compute the clip-space position as
+                previously shown. Then the result is multiplied through the clip-to-camera matrix,
+                and that vector is returned to the caller.</para>
             <para>This is a simple function that uses only uniforms to compute a value. It takes no
-                inputs and outputs. The second function is not quite as simple.</para>
+                arguments. The second function is not quite as simple.</para>
             <example>
                 <title>Light Intensity Application Function</title>
                 <programlisting language="glsl">vec4 ApplyLightIntensity(in vec3 cameraSpacePosition, out vec3 lightDirection)
             </itemizedlist>
         </section>
         <section>
-            <title>GLSL Functions of Note</title>
+            <title>GLSL Features of Note</title>
+            <glosslist>
+                <glossentry>
+                    <glossterm>gl_DepthRange</glossterm>
+                    <glossdef>
+                        <para>A built-in OpenGL uniform defined for fragment shaders only. This
+                            uniform stores the parameters passed to
+                                <function>glDepthRange.</function> When those parameters change, all
+                            programs are automatically updated.</para>
+                    </glossdef>
+                </glossentry>
+            </glosslist>
             <funcsynopsis>
                 <funcprototype>
                     <funcdef>vec <function>inversesqrt</function></funcdef>

Tut 09 Lights on/Ambient Lighting.cpp

 	GLuint lightIntensityUnif;
 	GLuint ambientIntensityUnif;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 	GLuint normalModelToCameraMatrixUnif;
 };
 ProgramData g_WhiteAmbDiffuseColor;
 ProgramData g_VertexAmbDiffuseColor;
 
+const int g_projectionBlockIndex = 2;
+
 ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
 	data.dirToLightUnif = glGetUniformLocation(data.theProgram, "dirToLight");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 }
 
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(0.0f, 1.0f);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 glm::vec4 g_lightDirection(0.866f, 0.5f, 0.0f, 0.0f);
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(g_WhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_WhiteAmbDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteAmbDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexAmbDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexAmbDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();

Tut 09 Lights on/Basic Lighting.cpp

 	GLuint dirToLightUnif;
 	GLuint lightIntensityUnif;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 	GLuint normalModelToCameraMatrixUnif;
 };
 ProgramData g_WhiteDiffuseColor;
 ProgramData g_VertexDiffuseColor;
 
+const int g_projectionBlockIndex = 2;
+
 ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
 	data.dirToLightUnif = glGetUniformLocation(data.theProgram, "dirToLight");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(0.0f, 1.0f);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 glm::vec4 g_lightDirection(0.866f, 0.5f, 0.0f, 0.0f);
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(g_WhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();

Tut 09 Lights on/Scale and Lighting.cpp

 	GLuint dirToLightUnif;
 	GLuint lightIntensityUnif;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 	GLuint normalModelToCameraMatrixUnif;
 };
 ProgramData g_WhiteDiffuseColor;
 ProgramData g_VertexDiffuseColor;
 
+const int g_projectionBlockIndex = 2;
+
 ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
 	data.dirToLightUnif = glGetUniformLocation(data.theProgram, "dirToLight");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 }
 
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(0.0f, 1.0f);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 glm::vec4 g_lightDirection(0.866f, 0.5f, 0.0f, 0.0f);
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(g_WhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();

Tut 09 Lights on/data/DirAmbVertexLighting_PCN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 09 Lights on/data/DirAmbVertexLighting_PN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 09 Lights on/data/DirVertexLighting_PCN.vert

 uniform vec3 dirToLight;
 uniform vec4 lightIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 09 Lights on/data/DirVertexLighting_PN.vert

 uniform vec3 dirToLight;
 uniform vec4 lightIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+layout(std140) uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 10 Plane Lights/Fragment Attenuation.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 {
 	GLuint theProgram;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 
 	GLuint lightIntensityUnif;
 
 	GLuint normalModelToCameraMatrixUnif;
 	GLuint cameraSpaceLightPosUnif;
-	GLuint clipToCameraMatrixUnif;
 	GLuint windowSizeUnif;
-	GLuint depthRangeUnif;
 	GLuint lightAttenuationUnif;
 	GLuint bUseRSquareUnif;
 };
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 };
 
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+const int g_unprojectionBlockIndex = 1;
+
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
 	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
 	data.cameraSpaceLightPosUnif = glGetUniformLocation(data.theProgram, "cameraSpaceLightPos");
-	data.clipToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "clipToCameraMatrix");
 	data.windowSizeUnif = glGetUniformLocation(data.theProgram, "windowSize");
-	data.depthRangeUnif = glGetUniformLocation(data.theProgram, "depthRange");
 	data.lightAttenuationUnif = glGetUniformLocation(data.theProgram, "lightAttenuation");
 	data.bUseRSquareUnif = glGetUniformLocation(data.theProgram, "bUseRSquare");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+	GLuint unprojectionBlock = glGetUniformBlockIndex(data.theProgram, "UnProjection");
+	glUniformBlockBinding(data.theProgram, unprojectionBlock, g_unprojectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+GLuint g_unprojectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
+struct UnProjectionBlock
+{
+	glm::mat4 clipToCameraMatrix;
+	glm::ivec2 windowSize;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthRange(depthZNear, depthZFar);
 	glEnable(GL_DEPTH_CLAMP);
 
-	glUseProgram(g_FragWhiteDiffuseColor.theProgram);
-	glUniform2f(g_FragWhiteDiffuseColor.depthRangeUnif,depthZNear, depthZFar);
-	glUseProgram(g_FragVertexDiffuseColor.theProgram);
-	glUniform2f(g_FragVertexDiffuseColor.depthRangeUnif,depthZNear, depthZFar);
-	glUseProgram(0);
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glGenBuffers(1, &g_unprojectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_unprojectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(UnProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_unprojectionBlockIndex, g_unprojectionUniformBuffer,
+		0, sizeof(UnProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
 
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 {
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
-	const glm::mat4 &invMat = glm::inverse(persMatrix.Top());
 
-	glUseProgram(g_FragWhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_FragWhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUniform2i(g_FragWhiteDiffuseColor.windowSizeUnif, w, h);
-	glUniformMatrix4fv(g_FragWhiteDiffuseColor.clipToCameraMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(invMat));
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
 
-	glUseProgram(g_FragVertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_FragVertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUniform2i(g_FragVertexDiffuseColor.windowSizeUnif, w, h);
-	glUniformMatrix4fv(g_FragVertexDiffuseColor.clipToCameraMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(invMat));
+	UnProjectionBlock unprojData;
+	unprojData.clipToCameraMatrix = glm::inverse(persMatrix.Top());
+	unprojData.windowSize = glm::ivec2(w, h);
 
-	glUseProgram(g_Unlit.theProgram);
-	glUniformMatrix4fv(g_Unlit.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_unprojectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(UnProjectionBlock), &unprojData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 
 	case 'y': g_bDrawLight = !g_bDrawLight; break;
 	case 't': g_bScaleCyl = !g_bScaleCyl; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 
 	case 'h':
 		g_bUseRSquare = !g_bUseRSquare;
 
 	if(bChangedAtten)
 		printf("Atten: %f\n", g_fLightAttenuation); 
-
-	glutPostRedisplay();
 }
 
 

Tut 10 Plane Lights/Fragment Point Lighting.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 	GLuint lightIntensityUnif;
 	GLuint ambientIntensityUnif;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 };
 
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 };
 
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.modelSpaceLightPosUnif = glGetUniformLocation(data.theProgram, "modelSpaceLightPos");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(0.0f, 1.0f);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
+
 static bool g_bUseFragmentLighting = true;
 static bool g_bDrawColoredCyl = false;
 static bool g_bDrawLight = false;
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(g_WhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_FragWhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_FragWhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_FragVertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_FragVertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_Unlit.theProgram);
-	glUniformMatrix4fv(g_Unlit.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 	case 'y': g_bDrawLight = !g_bDrawLight; break;
 	case 't': g_bScaleCyl = !g_bScaleCyl; break;
 	case 'h': g_bUseFragmentLighting = !g_bUseFragmentLighting; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 	}
 
 	if(g_fLightRadius < 0.2f)

Tut 10 Plane Lights/Vertex Point Lighting.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 	GLuint lightIntensityUnif;
 	GLuint ambientIntensityUnif;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 	GLuint normalModelToCameraMatrixUnif;
 };
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 };
 
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
 	data.lightPosUnif = glGetUniformLocation(data.theProgram, "lightPos");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(0.0f, 1.0f);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
 
-	glUseProgram(g_WhiteDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_WhiteDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_VertexDiffuseColor.theProgram);
-	glUniformMatrix4fv(g_VertexDiffuseColor.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(g_Unlit.theProgram);
-	glUniformMatrix4fv(g_Unlit.cameraToClipMatrixUnif, 1, GL_FALSE,
-		glm::value_ptr(persMatrix.Top()));
-	glUseProgram(0);
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 	case 'J': g_fLightRadius -= 0.05f; break;
 
 	case 'y': g_bDrawLight = !g_bDrawLight; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 	}
 
 	if(g_fLightRadius < 0.2f)

Tut 10 Plane Lights/data/FragLightAtten.frag

 
 uniform vec3 cameraSpaceLightPos;
 
-uniform mat4 clipToCameraMatrix;
-uniform ivec2 windowSize;
-uniform vec2 depthRange;
-
 uniform float lightAttenuation;
 uniform bool bUseRSquare;
 
+uniform UnProjection
+{
+	mat4 clipToCameraMatrix;
+	ivec2 windowSize;
+};
+
 vec3 CalcCameraSpacePosition()
 {
 	vec4 ndcPos;
 	ndcPos.xy = ((gl_FragCoord.xy / windowSize.xy) * 2.0) - 1.0;
-	ndcPos.z = (2.0 * gl_FragCoord.z - depthRange.x - depthRange.y) / (depthRange.y - depthRange.x);
+	ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) /
+		(gl_DepthRange.far - gl_DepthRange.near);
 	ndcPos.w = 1.0;
 	
 	vec4 clipPos = ndcPos / gl_FragCoord.w;

Tut 10 Plane Lights/data/FragLightAtten_PCN.vert

 out vec4 diffuseColor;
 out vec3 vertexNormal;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 10 Plane Lights/data/FragLightAtten_PN.vert

 out vec4 diffuseColor;
 out vec3 vertexNormal;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 10 Plane Lights/data/FragmentLighting_PCN.vert

 out vec3 vertexNormal;
 out vec3 modelSpacePosition;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
 void main()
 {
 	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));

Tut 10 Plane Lights/data/FragmentLighting_PN.vert

 out vec3 vertexNormal;
 out vec3 modelSpacePosition;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
 void main()
 {
 	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));

Tut 10 Plane Lights/data/ModelPosVertexLighting_PCN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
 void main()
 {
 	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));

Tut 10 Plane Lights/data/ModelPosVertexLighting_PN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
 void main()
 {
 	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));

Tut 10 Plane Lights/data/PosTransform.vert

 
 layout(location = 0) in vec3 position;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
 
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
+
 void main()
 {
 	gl_Position = cameraToClipMatrix * (modelToCameraMatrix * vec4(position, 1.0));

Tut 10 Plane Lights/data/PosVertexLighting_PCN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 10 Plane Lights/data/PosVertexLighting_PN.vert

 uniform vec4 lightIntensity;
 uniform vec4 ambientIntensity;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 11 Shinies/Blinn vs Phong Lighting.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 {
 	GLuint theProgram;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 
 	GLuint lightIntensityUnif;
 	GLuint lightAttenuationUnif;
 	GLuint shininessFactorUnif;
 	GLuint baseDiffuseColorUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
 };
 
 struct UnlitProgData
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
-
 };
 
 float g_fzNear = 1.0f;
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
 	data.shininessFactorUnif = glGetUniformLocation(data.theProgram, "shininessFactor");
 	data.baseDiffuseColorUnif = glGetUniformLocation(data.theProgram, "baseDiffuseColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
 
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 	glDepthRange(depthZNear, depthZFar);
 	glEnable(GL_DEPTH_CLAMP);
 
-	glUseProgram(0);
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 {
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
-	const glm::mat4 &invMat = glm::inverse(persMatrix.Top());
 
-	for(int iProg = 0; iProg < LM_MAX_LIGHTING_MODEL; iProg++)
-	{
-		g_Programs[iProg].whiteProg.SetWindowData(persMatrix.Top());
-		g_Programs[iProg].colorProg.SetWindowData(persMatrix.Top());
-	}
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
 
-	g_Unlit.SetWindowData(persMatrix.Top());
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 
 	case 'y': g_bDrawLightSource = !g_bDrawLightSource; break;
 	case 't': g_bScaleCyl = !g_bScaleCyl; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 	case 'g': g_bDrawDark = !g_bDrawDark; break;
 	case 'h':
 		g_eLightModel += 2;

Tut 11 Shinies/Gaussian Specular Lighting.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 {
 	GLuint theProgram;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 
 	GLuint lightIntensityUnif;
 	GLuint lightAttenuationUnif;
 	GLuint shininessFactorUnif;
 	GLuint baseDiffuseColorUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
 };
 
 struct UnlitProgData
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
-
 };
 
 float g_fzNear = 1.0f;
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
 	data.shininessFactorUnif = glGetUniformLocation(data.theProgram, "shininessFactor");
 	data.baseDiffuseColorUnif = glGetUniformLocation(data.theProgram, "baseDiffuseColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(depthZNear, depthZFar);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 {
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
-	const glm::mat4 &invMat = glm::inverse(persMatrix.Top());
 
-	for(int iProg = 0; iProg < LM_MAX_LIGHTING_MODEL; iProg++)
-	{
-		g_Programs[iProg].whiteProg.SetWindowData(persMatrix.Top());
-		g_Programs[iProg].colorProg.SetWindowData(persMatrix.Top());
-	}
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
 
-	g_Unlit.SetWindowData(persMatrix.Top());
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 
 	case 'y': g_bDrawLightSource = !g_bDrawLightSource; break;
 	case 't': g_bScaleCyl = !g_bScaleCyl; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 	case 'g': g_bDrawDark = !g_bDrawDark; break;
 	case 'h':
 		g_eLightModel += 2;

Tut 11 Shinies/Phong Lighting.cpp

 #include "../framework/MatrixStack.h"
 #include "../framework/MousePole.h"
 #include "../framework/ObjectPole.h"
+#include "../framework/Timer.h"
 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
 {
 	GLuint theProgram;
 
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
 
 	GLuint lightIntensityUnif;
 	GLuint lightAttenuationUnif;
 	GLuint shininessFactorUnif;
 	GLuint baseDiffuseColorUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
 };
 
 struct UnlitProgData
 	GLuint theProgram;
 
 	GLuint objectColorUnif;
-	GLuint cameraToClipMatrixUnif;
 	GLuint modelToCameraMatrixUnif;
-
-	void SetWindowData(const glm::mat4 cameraToClip)
-	{
-		glUseProgram(theProgram);
-		glUniformMatrix4fv(cameraToClipMatrixUnif, 1, GL_FALSE,
-			glm::value_ptr(cameraToClip));
-		glUseProgram(0);
-	}
 };
 
 float g_fzNear = 1.0f;
 
 UnlitProgData g_Unlit;
 
+const int g_projectionBlockIndex = 2;
+
 UnlitProgData LoadUnlitProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
 {
 	std::vector<GLuint> shaderList;
 	UnlitProgData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	ProgramData data;
 	data.theProgram = Framework::CreateProgram(shaderList);
 	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
-	data.cameraToClipMatrixUnif = glGetUniformLocation(data.theProgram, "cameraToClipMatrix");
 	data.lightIntensityUnif = glGetUniformLocation(data.theProgram, "lightIntensity");
 	data.ambientIntensityUnif = glGetUniformLocation(data.theProgram, "ambientIntensity");
 
 	data.shininessFactorUnif = glGetUniformLocation(data.theProgram, "shininessFactor");
 	data.baseDiffuseColorUnif = glGetUniformLocation(data.theProgram, "baseDiffuseColor");
 
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
 	return data;
 }
 
 	}
 }
 
+GLuint g_projectionUniformBuffer = 0;
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
 //Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
 void init()
 {
 	glDepthFunc(GL_LEQUAL);
 	glDepthRange(depthZNear, depthZFar);
 	glEnable(GL_DEPTH_CLAMP);
+
+	glGenBuffers(1, &g_projectionUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(ProjectionBlock), NULL, GL_DYNAMIC_DRAW);
+
+	//Bind the static buffers.
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
 static float g_fLightHeight = 1.5f;
 static float g_fLightRadius = 1.0f;
-static bool g_bRotateLight = true;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
+using Framework::Timer;
+Timer g_LightTimer(Timer::TT_LOOP, 5.0f);
 
 glm::vec4 CalcLightPosition()
 {
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f / fLoopDuration;
-
-	float fCurrTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
-	float fDeltaTime = fCurrTime - g_fPrevTime;
-	g_fPrevTime = fCurrTime;
-
-	if(g_bRotateLight)
-		g_fRotateTime += fDeltaTime;
-
-	float fCurrTimeThroughLoop = fmodf(g_fRotateTime, fLoopDuration);
+	float fCurrTimeThroughLoop = g_LightTimer.GetAlpha();
 
 	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
 
-	ret.x = cosf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(fCurrTimeThroughLoop * fScale) * g_fLightRadius;
+	ret.x = cosf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
+	ret.z = sinf(fCurrTimeThroughLoop * (3.14159f * 2.0f)) * g_fLightRadius;
 
 	return ret;
 }
 
 void display()
 {
+	g_LightTimer.Update();
+
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 {
 	Framework::MatrixStack persMatrix;
 	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
-	const glm::mat4 &invMat = glm::inverse(persMatrix.Top());
 
-	g_WhiteNoPhong.SetWindowData(persMatrix.Top());
-	g_ColorNoPhong.SetWindowData(persMatrix.Top());
-	g_WhitePhong.SetWindowData(persMatrix.Top());
-	g_ColorPhong.SetWindowData(persMatrix.Top());
-	g_WhitePhongOnly.SetWindowData(persMatrix.Top());
-	g_ColorPhongOnly.SetWindowData(persMatrix.Top());
+	ProjectionBlock projData;
+	projData.cameraToClipMatrix = persMatrix.Top();
 
-	g_Unlit.SetWindowData(persMatrix.Top());
+	glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
 	glutPostRedisplay();
 
 	case 'y': g_bDrawLightSource = !g_bDrawLightSource; break;
 	case 't': g_bScaleCyl = !g_bScaleCyl; break;
-	case 'b': g_bRotateLight = !g_bRotateLight; break;
+	case 'b': g_LightTimer.TogglePause(); break;
 	case 'g': g_bDrawDark = !g_bDrawDark; break;
 	case 'h':
 		g_eLightModel += 1;

Tut 11 Shinies/data/PCN.vert

 out vec3 vertexNormal;
 out vec3 cameraSpacePosition;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {

Tut 11 Shinies/data/PN.vert

 out vec3 vertexNormal;
 out vec3 cameraSpacePosition;
 
-uniform mat4 cameraToClipMatrix;
 uniform mat4 modelToCameraMatrix;
+uniform mat3 normalModelToCameraMatrix;
+
 uniform vec4 baseDiffuseColor;
 
-uniform mat3 normalModelToCameraMatrix;
+uniform Projection
+{
+	mat4 cameraToClipMatrix;
+};
 
 void main()
 {