Commits

Jason McKesson committed bd1775f

UBO code may work.

Comments (0)

Files changed (7)

Documents/meshFormat.rnc

+datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace msh = "http://www.arcsynthesis.com/gltut/mesh"
+
+##Structure and elements
+div
+{
+    start = mf.rootelements
+    
+    mf.rootelements =
+        mf.mesh
+        
+    mf.mesh =
+        ##The mesh format
+        element msh:mesh {mf.mesh.content}
+
+    mf.mesh.content =
+        mf.attribute+, (mf.indices+ | mf.arrays+)
+        
+    mf.attribute =
+        ##A single attribute array.
+        element msh:attribute { mf.attribute.content }
+        
+    mf.attribute.content =
+        mf.attribute.attlist, text
+
+    mf.indices =
+        ##A single element array, which is rendered with a particular rendering command.
+        element msh:indices { mf.indices.content }
+        
+    mf.indices.content =
+        mf.indices.attlist, text
+        
+    mf.arrays =
+        ##A single array rendering, which is rendered with a particular rendering command.
+        ##Cannot be combined with element arrays in a single mesh.
+        element msh:arrays { mf.arrays.content }
+        
+    mf.arrays.content =
+        mf.arrays.attlist, text
+}
+
+##Attributes
+div
+{
+    mf.attribute.attlist =
+        mf.attribute.index.attribute, mf.attribute.type.attribute, mf.attribute.size.attribute
+        
+    mf.indices.attlist =
+        mf.indices.type.attribute, mf.cmd.attribute, mf.indices.primrestart.attribute?
+        
+    mf.arrays.attlist =
+        mf.cmd.attribute, mf.arrays.start.attribute, mf.arrays.count.attribute
+        
+    mf.attribute.index.attribute =
+        ##The attribute index to be used for this attribute.
+        attribute index { xsd:nonNegativeInteger { minInclusive = "0" maxExclusive = "16"} }
+        
+    mf.attribute.size.attribute =
+        ##The size of each value in the attribute. 1-4.
+        attribute size { xsd:positiveInteger { minInclusive = "1" maxInclusive = "4"} }
+    
+    mf.attribute.type.attribute =
+        ##The type of the attribute's data. Integer, float, normalized, etc.
+        attribute type { "float" | "int" | "uint" | "short" | "ushort" | "byte" | "ubyte" |
+            "norm-int" | "norm-uint" | "norm-short" | "norm-ushort" | "norm-byte" | "norm-ubyte"}
+        
+    mf.indices.type.attribute =
+        ##The type of the index data.
+        attribute type { "uint" | "ushort" | "ubyte" }
+    
+    mf.cmd.attribute =
+        ##The command used to render this part of the mesh.
+        attribute cmd { "triangles" | "tri-strip" | "tri-fan" | "lines" | "line-strip" |
+        "line-loop" | "points" }
+        
+    mf.indices.primrestart.attribute =
+        ##Sets the primitive restart index. Don't set it if you don't want one.
+        attribute prim-restart { xsd:unsignedInt }
+        
+    mf.arrays.start.attribute =
+        ##Sets the initial index for array rendering.
+        attribute start { xsd:nonNegativeInteger }
+    
+    mf.arrays.count.attribute =
+        ##Sets the number of elements to be rendered with array rendering.
+        attribute count { xsd:positiveInteger }
+}
+

Tut 07 World in Motion/World Scene.cpp

 
 static const TreeData g_forest[] =
 {
-	{10.0f, 10.0f, 2.0f, 3.0f},
+	{-45.0f, -40.0f, 2.0f, 3.0f},
+	{-42.0f, -35.0f, 2.0f, 3.0f},
+	{-39.0f, -29.0f, 2.0f, 4.0f},
+	{-44.0f, -26.0f, 3.0f, 3.0f},
+	{-40.0f, -22.0f, 2.0f, 4.0f},
+	{-36.0f, -15.0f, 3.0f, 3.0f},
+	{-41.0f, -11.0f, 2.0f, 3.0f},
+	{-37.0f, -6.0f, 3.0f, 3.0f},
+	{-45.0f, 0.0f, 2.0f, 3.0f},
+	{-39.0f, 4.0f, 3.0f, 4.0f},
+	{-36.0f, 8.0f, 2.0f, 3.0f},
+	{-44.0f, 13.0f, 3.0f, 3.0f},
+	{-42.0f, 17.0f, 2.0f, 3.0f},
+	{-38.0f, 23.0f, 3.0f, 4.0f},
+	{-41.0f, 27.0f, 2.0f, 3.0f},
+	{-39.0f, 32.0f, 3.0f, 3.0f},
+	{-44.0f, 37.0f, 3.0f, 4.0f},
+	{-36.0f, 42.0f, 2.0f, 3.0f},
+
+	{-32.0f, -45.0f, 2.0f, 3.0f},
+	{-30.0f, -42.0f, 2.0f, 4.0f},
+	{-34.0f, -38.0f, 3.0f, 5.0f},
+	{-33.0f, -35.0f, 3.0f, 4.0f},
+	{-29.0f, -28.0f, 2.0f, 3.0f},
+	{-26.0f, -25.0f, 3.0f, 5.0f},
+	{-35.0f, -21.0f, 3.0f, 4.0f},
+	{-31.0f, -17.0f, 3.0f, 3.0f},
+	{-28.0f, -12.0f, 2.0f, 4.0f},
+	{-29.0f, -7.0f, 3.0f, 3.0f},
+	{-26.0f, -1.0f, 2.0f, 4.0f},
+	{-32.0f, 6.0f, 2.0f, 3.0f},
+	{-30.0f, 10.0f, 3.0f, 5.0f},
+	{-33.0f, 14.0f, 2.0f, 4.0f},
+	{-35.0f, 19.0f, 3.0f, 4.0f},
+	{-28.0f, 22.0f, 2.0f, 3.0f},
+	{-33.0f, 26.0f, 3.0f, 3.0f},
+	{-29.0f, 31.0f, 3.0f, 4.0f},
+	{-32.0f, 38.0f, 2.0f, 3.0f},
+	{-27.0f, 41.0f, 3.0f, 4.0f},
+	{-31.0f, 45.0f, 2.0f, 4.0f},
+	{-28.0f, 48.0f, 3.0f, 5.0f},
+
+	{-25.0f, -48.0f, 2.0f, 3.0f},
+	{-20.0f, -42.0f, 3.0f, 4.0f},
+	{-22.0f, -39.0f, 2.0f, 3.0f},
+	{-19.0f, -34.0f, 2.0f, 3.0f},
+	{-23.0f, -30.0f, 3.0f, 4.0f},
+	{-24.0f, -24.0f, 2.0f, 3.0f},
+	{-16.0f, -21.0f, 2.0f, 3.0f},
+	{-17.0f, -17.0f, 3.0f, 3.0f},
+	{-25.0f, -13.0f, 2.0f, 4.0f},
+	{-23.0f, -8.0f, 2.0f, 3.0f},
+	{-17.0f, -2.0f, 3.0f, 3.0f},
+	{-16.0f, 1.0f, 2.0f, 3.0f},
+	{-19.0f, 4.0f, 3.0f, 3.0f},
+	{-22.0f, 8.0f, 2.0f, 4.0f},
+	{-21.0f, 14.0f, 2.0f, 3.0f},
+	{-16.0f, 19.0f, 2.0f, 3.0f},
+	{-23.0f, 24.0f, 3.0f, 3.0f},
+	{-18.0f, 28.0f, 2.0f, 4.0f},
+	{-24.0f, 31.0f, 2.0f, 3.0f},
+	{-20.0f, 36.0f, 2.0f, 3.0f},
+	{-22.0f, 41.0f, 3.0f, 3.0f},
+	{-21.0f, 45.0f, 2.0f, 3.0f},
+
+	{-12.0f, -40.0f, 2.0f, 4.0f},
+	{-11.0f, -35.0f, 3.0f, 3.0f},
+	{-10.0f, -29.0f, 1.0f, 3.0f},
+	{-9.0f, -26.0f, 2.0f, 2.0f},
+	{-6.0f, -22.0f, 2.0f, 3.0f},
+	{-15.0f, -15.0f, 1.0f, 3.0f},
+	{-8.0f, -11.0f, 2.0f, 3.0f},
+	{-14.0f, -6.0f, 2.0f, 4.0f},
+	{-12.0f, 0.0f, 2.0f, 3.0f},
+	{-7.0f, 4.0f, 2.0f, 2.0f},
+	{-13.0f, 8.0f, 2.0f, 2.0f},
+	{-9.0f, 13.0f, 1.0f, 3.0f},
+	{-13.0f, 17.0f, 3.0f, 4.0f},
+	{-6.0f, 23.0f, 2.0f, 3.0f},
+	{-12.0f, 27.0f, 1.0f, 2.0f},
+	{-8.0f, 32.0f, 2.0f, 3.0f},
+	{-10.0f, 37.0f, 3.0f, 3.0f},
+	{-11.0f, 42.0f, 2.0f, 2.0f},
+
+
+	{15.0f, 5.0f, 2.0f, 3.0f},
+	{15.0f, 10.0f, 2.0f, 3.0f},
+	{15.0f, 15.0f, 2.0f, 3.0f},
+	{15.0f, 20.0f, 2.0f, 3.0f},
+	{15.0f, 25.0f, 2.0f, 3.0f},
+	{15.0f, 30.0f, 2.0f, 3.0f},
+	{15.0f, 35.0f, 2.0f, 3.0f},
+	{15.0f, 40.0f, 2.0f, 3.0f},
+	{15.0f, 45.0f, 2.0f, 3.0f},
+
+	{25.0f, 5.0f, 2.0f, 3.0f},
+	{25.0f, 10.0f, 2.0f, 3.0f},
+	{25.0f, 15.0f, 2.0f, 3.0f},
+	{25.0f, 20.0f, 2.0f, 3.0f},
+	{25.0f, 25.0f, 2.0f, 3.0f},
+	{25.0f, 30.0f, 2.0f, 3.0f},
+	{25.0f, 35.0f, 2.0f, 3.0f},
+	{25.0f, 40.0f, 2.0f, 3.0f},
+	{25.0f, 45.0f, 2.0f, 3.0f},
 };
 
 void DrawForest(Framework::MatrixStack &modelMatrix)
 	}
 }
 
+static bool g_bDrawLookatPoint = false;
 static glm::vec3 g_camTarget(0.0f, 0.4f, 0.0f);
 
 //In spherical coordinates.
 	glClearDepth(1.0f);
 	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
+	const glm::vec3 &camPos = ResolveCamPosition();
+
 	Framework::MatrixStack camMatrix;
-	camMatrix.SetMatrix(CalcLookAtMatrix(ResolveCamPosition(), g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
+	camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
 
 	glUseProgram(UniformColor.theProgram);
 	glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
 	glUniformMatrix4fv(UniformColorTint.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
 	glUseProgram(0);
 
-	if(g_pConeMesh)
+	Framework::MatrixStack modelMatrix;
+
+	//Render the ground plane.
 	{
-		Framework::MatrixStack modelMatrix;
+		Framework::MatrixStackPusher push(modelMatrix);
 
-		//Render the ground.
-		{
-			Framework::MatrixStackPusher push(modelMatrix);
+		modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));
 
-			modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));
+		glUseProgram(UniformColor.theProgram);
+		glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
+		glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
+		g_pPlaneMesh->Render();
+		glUseProgram(0);
+	}
 
-			glUseProgram(UniformColor.theProgram);
-			glUniformMatrix4fv(UniformColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(camMatrix.Top()));
-			glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
-			glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
-			g_pPlaneMesh->Render();
-			glUseProgram(0);
-		}
+	//Draw the trees
+	DrawForest(modelMatrix);
 
-		DrawForest(modelMatrix);
+	//Draw the building.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+		modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));
 
-		{
-			Framework::MatrixStackPusher push(modelMatrix);
-			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));
+		DrawParthenon(modelMatrix);
+	}
 
-			DrawParthenon(modelMatrix);
-		}
+	if(g_bDrawLookatPoint)
+	{
+		glDisable(GL_DEPTH_TEST);
+		glm::mat4 idenity(1.0f);
+
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		glm::vec3 cameraAimVec = g_camTarget - camPos;
+		modelMatrix.Translate(0.0f, 0.0, -glm::length(cameraAimVec));
+		modelMatrix.Scale(1.0f, 1.0f, 1.0f);
+	
+		glUseProgram(ObjectColor.theProgram);
+		glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(idenity));
+		g_pCubeColorMesh->Render();
+		glUseProgram(0);
+		glEnable(GL_DEPTH_TEST);
 	}
 
 	glutSwapBuffers();
 	case 'U': g_sphereCamRelPos.z += 0.5f; break;
 		
 	case 32:
+		g_bDrawLookatPoint = !g_bDrawLookatPoint;
 		printf("Target: %f, %f, %f\n", g_camTarget.x, g_camTarget.y, g_camTarget.z);
 		printf("Position: %f, %f, %f\n", g_sphereCamRelPos.x, g_sphereCamRelPos.y, g_sphereCamRelPos.z);
 		break;

Tut 07 World in Motion/World With UBO.cpp

+#include <string>
+#include <vector>
+#include <stack>
+#include <math.h>
+#include <glloader/gl_3_2_comp.h>
+#include <GL/freeglut.h>
+#include "../framework/framework.h"
+#include <glm/glm.hpp>
+#include <glm/gtc/type_ptr.hpp>
+
+#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
+
+struct ProgramData
+{
+	GLuint theProgram;
+	GLuint globalUniformBlockIndex;
+	GLuint modelToWorldMatrixUnif;
+	GLuint baseColorUnif;
+	GLuint thing;
+};
+
+float g_fzNear = 1.0f;
+float g_fzFar = 1000.0f;
+
+ProgramData UniformColor;
+ProgramData ObjectColor;
+ProgramData UniformColorTint;
+
+GLuint g_GlobalMatricesUBO;
+
+static const int g_iGlobalMatricesBindingIndex = 0;
+
+ProgramData LoadProgram(const std::string &strVertexShader, const std::string &strFragmentShader)
+{
+	std::vector<GLuint> shaderList;
+
+	shaderList.push_back(Framework::LoadShader(GL_VERTEX_SHADER, strVertexShader));
+	shaderList.push_back(Framework::LoadShader(GL_FRAGMENT_SHADER, strFragmentShader));
+
+	ProgramData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToWorldMatrixUnif = glGetUniformLocation(data.theProgram, "modelToWorldMatrix");
+	data.globalUniformBlockIndex = glGetUniformBlockIndex(data.theProgram, "GlobalMatrices");
+	data.baseColorUnif = glGetUniformLocation(data.theProgram, "baseColor");
+
+	glUniformBlockBinding(data.theProgram, data.globalUniformBlockIndex, g_iGlobalMatricesBindingIndex);
+
+	return data;
+}
+
+void InitializeProgram()
+{
+	UniformColor = LoadProgram("PosOnlyWorldTransformUBO.vert", "ColorUniform.frag");
+	ObjectColor = LoadProgram("PosColorWorldTransformUBO.vert", "ColorPassthrough.frag");
+	UniformColorTint = LoadProgram("PosColorWorldTransformUBO.vert", "ColorMultUniform.frag");
+
+	glGenBuffers(1, &g_GlobalMatricesUBO);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * 2, NULL, GL_STREAM_DRAW);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_iGlobalMatricesBindingIndex, g_GlobalMatricesUBO,
+		0, sizeof(glm::mat4) * 2);
+}
+
+glm::mat4 CalcLookAtMatrix(const glm::vec3 &cameraPt, const glm::vec3 &lookPt, const glm::vec3 &upPt)
+{
+	glm::vec3 lookDir = glm::normalize(lookPt - cameraPt);
+	glm::vec3 upDir = glm::normalize(upPt);
+
+	glm::vec3 rightDir = glm::normalize(glm::cross(lookDir, upDir));
+	glm::vec3 perpUpDir = glm::cross(rightDir, lookDir);
+
+	glm::mat4 rotMat(1.0f);
+	rotMat[0] = glm::vec4(rightDir, 0.0f);
+	rotMat[1] = glm::vec4(perpUpDir, 0.0f);
+	rotMat[2] = glm::vec4(-lookDir, 0.0f);
+
+	rotMat = glm::transpose(rotMat);
+
+	glm::mat4 transMat(1.0f);
+	transMat[3] = glm::vec4(-cameraPt, 1.0f);
+
+	return rotMat * transMat;
+}
+
+Framework::Mesh *g_pConeMesh = NULL;
+Framework::Mesh *g_pCylinderMesh = NULL;
+Framework::Mesh *g_pCubeTintMesh = NULL;
+Framework::Mesh *g_pCubeColorMesh = NULL;
+Framework::Mesh *g_pPlaneMesh = NULL;
+
+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
+void init()
+{
+	InitializeProgram();
+
+	try
+	{
+		g_pConeMesh = new Framework::Mesh("UnitConeTint.xml");
+		g_pCylinderMesh = new Framework::Mesh("UnitCylinderTint.xml");
+		g_pCubeTintMesh = new Framework::Mesh("UnitCubeTint.xml");
+		g_pCubeColorMesh = new Framework::Mesh("UnitCubeColor.xml");
+		g_pPlaneMesh = new Framework::Mesh("UnitPlane.xml");
+	}
+	catch(std::exception &except)
+	{
+		printf(except.what());
+	}
+
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+	glFrontFace(GL_CW);
+
+	glEnable(GL_DEPTH_TEST);
+	glDepthMask(GL_TRUE);
+	glDepthFunc(GL_LEQUAL);
+	glDepthRange(0.0f, 1.0f);
+}
+
+static float g_fYAngle = 0.0f;
+static float g_fXAngle = 0.0f;
+
+//Trees are 3x3 in X/Z, and fTrunkHeight+fConeHeight in the Y.
+void DrawTree(Framework::MatrixStack &modelMatrix, float fTrunkHeight = 2.0f, float fConeHeight = 3.0f)
+{
+	//Draw trunk.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(1.0f, fTrunkHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.694f, 0.4f, 0.106f, 1.0f);
+		g_pCylinderMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the treetop
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, fTrunkHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(3.0f, fConeHeight, 3.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.0f, 1.0f, 0.0f, 1.0f);
+		g_pConeMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+const float g_fColumnBaseHeight = 0.25f;
+
+//Columns are 1x1 in the X/Z, and fHieght units in the Y.
+void DrawColumn(Framework::MatrixStack &modelMatrix, float fHeight = 5.0f)
+{
+	//Draw the bottom of the column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the top of the column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, fHeight - g_fColumnBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(1.0f, g_fColumnBaseHeight, 1.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw the main column.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, g_fColumnBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(0.8f, fHeight - (g_fColumnBaseHeight * 2.0f), 0.8f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCylinderMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+const float g_fParthenonWidth = 14.0f;
+const float g_fParthenonLength = 20.0f;
+const float g_fParthenonColumnHeight = 5.0f;
+const float g_fParthenonBaseHeight = 1.0f;
+const float g_fParthenonTopHeight = 2.0f;
+
+void DrawParthenon(Framework::MatrixStack &modelMatrix)
+{
+	//Draw base.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonBaseHeight, g_fParthenonLength));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw top.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, g_fParthenonColumnHeight + g_fParthenonBaseHeight, 0.0f));
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth, g_fParthenonTopHeight, g_fParthenonLength));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(UniformColorTint.theProgram);
+		glUniformMatrix4fv(UniformColorTint.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		glUniform4f(UniformColorTint.baseColorUnif, 0.9f, 0.9f, 0.9f, 0.9f);
+		g_pCubeTintMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw columns.
+	const float fFrontZVal = (g_fParthenonLength / 2.0f) - 1.0f;
+	const float fRightXVal = (g_fParthenonWidth / 2.0f) - 1.0f;
+
+	for(int iColumnNum = 0; iColumnNum < int(g_fParthenonWidth / 2.0f); iColumnNum++)
+	{
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f,
+				g_fParthenonBaseHeight, fFrontZVal));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3((2.0f * iColumnNum) - (g_fParthenonWidth / 2.0f) + 1.0f,
+				g_fParthenonBaseHeight, -fFrontZVal));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+	}
+
+	//Don't draw the first or last columns, since they've been drawn already.
+	for(int iColumnNum = 1; iColumnNum < int((g_fParthenonLength - 2.0f) / 2.0f); iColumnNum++)
+	{
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(fRightXVal,
+				g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(-fRightXVal,
+				g_fParthenonBaseHeight, (2.0f * iColumnNum) - (g_fParthenonLength / 2.0f) + 1.0f));
+
+			DrawColumn(modelMatrix, g_fParthenonColumnHeight);
+		}
+	}
+
+	//Draw interior.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(0.0f, 1.0f, 0.0f));
+		modelMatrix.Scale(glm::vec3(g_fParthenonWidth - 6.0f, g_fParthenonColumnHeight,
+			g_fParthenonLength - 6.0f));
+		modelMatrix.Translate(glm::vec3(0.0f, 0.5f, 0.0f));
+
+		glUseProgram(ObjectColor.theProgram);
+		glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		g_pCubeColorMesh->Render();
+		glUseProgram(0);
+	}
+
+	//Draw headpiece.
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		modelMatrix.Translate(glm::vec3(
+			0.0f,
+			g_fParthenonColumnHeight + g_fParthenonBaseHeight + (g_fParthenonTopHeight / 2.0f),
+			g_fParthenonLength / 2.0f));
+		modelMatrix.RotateX(-135.0f);
+		modelMatrix.RotateY(45.0f);
+
+		glUseProgram(ObjectColor.theProgram);
+		glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+		g_pCubeColorMesh->Render();
+		glUseProgram(0);
+	}
+}
+
+struct TreeData
+{
+	float fXPos;
+	float fZPos;
+	float fTrunkHeight;
+	float fConeHeight;
+};
+
+static const TreeData g_forest[] =
+{
+	{-45.0f, -40.0f, 2.0f, 3.0f},
+	{-42.0f, -35.0f, 2.0f, 3.0f},
+	{-39.0f, -29.0f, 2.0f, 4.0f},
+	{-44.0f, -26.0f, 3.0f, 3.0f},
+	{-40.0f, -22.0f, 2.0f, 4.0f},
+	{-36.0f, -15.0f, 3.0f, 3.0f},
+	{-41.0f, -11.0f, 2.0f, 3.0f},
+	{-37.0f, -6.0f, 3.0f, 3.0f},
+	{-45.0f, 0.0f, 2.0f, 3.0f},
+	{-39.0f, 4.0f, 3.0f, 4.0f},
+	{-36.0f, 8.0f, 2.0f, 3.0f},
+	{-44.0f, 13.0f, 3.0f, 3.0f},
+	{-42.0f, 17.0f, 2.0f, 3.0f},
+	{-38.0f, 23.0f, 3.0f, 4.0f},
+	{-41.0f, 27.0f, 2.0f, 3.0f},
+	{-39.0f, 32.0f, 3.0f, 3.0f},
+	{-44.0f, 37.0f, 3.0f, 4.0f},
+	{-36.0f, 42.0f, 2.0f, 3.0f},
+
+	{-32.0f, -45.0f, 2.0f, 3.0f},
+	{-30.0f, -42.0f, 2.0f, 4.0f},
+	{-34.0f, -38.0f, 3.0f, 5.0f},
+	{-33.0f, -35.0f, 3.0f, 4.0f},
+	{-29.0f, -28.0f, 2.0f, 3.0f},
+	{-26.0f, -25.0f, 3.0f, 5.0f},
+	{-35.0f, -21.0f, 3.0f, 4.0f},
+	{-31.0f, -17.0f, 3.0f, 3.0f},
+	{-28.0f, -12.0f, 2.0f, 4.0f},
+	{-29.0f, -7.0f, 3.0f, 3.0f},
+	{-26.0f, -1.0f, 2.0f, 4.0f},
+	{-32.0f, 6.0f, 2.0f, 3.0f},
+	{-30.0f, 10.0f, 3.0f, 5.0f},
+	{-33.0f, 14.0f, 2.0f, 4.0f},
+	{-35.0f, 19.0f, 3.0f, 4.0f},
+	{-28.0f, 22.0f, 2.0f, 3.0f},
+	{-33.0f, 26.0f, 3.0f, 3.0f},
+	{-29.0f, 31.0f, 3.0f, 4.0f},
+	{-32.0f, 38.0f, 2.0f, 3.0f},
+	{-27.0f, 41.0f, 3.0f, 4.0f},
+	{-31.0f, 45.0f, 2.0f, 4.0f},
+	{-28.0f, 48.0f, 3.0f, 5.0f},
+
+	{-25.0f, -48.0f, 2.0f, 3.0f},
+	{-20.0f, -42.0f, 3.0f, 4.0f},
+	{-22.0f, -39.0f, 2.0f, 3.0f},
+	{-19.0f, -34.0f, 2.0f, 3.0f},
+	{-23.0f, -30.0f, 3.0f, 4.0f},
+	{-24.0f, -24.0f, 2.0f, 3.0f},
+	{-16.0f, -21.0f, 2.0f, 3.0f},
+	{-17.0f, -17.0f, 3.0f, 3.0f},
+	{-25.0f, -13.0f, 2.0f, 4.0f},
+	{-23.0f, -8.0f, 2.0f, 3.0f},
+	{-17.0f, -2.0f, 3.0f, 3.0f},
+	{-16.0f, 1.0f, 2.0f, 3.0f},
+	{-19.0f, 4.0f, 3.0f, 3.0f},
+	{-22.0f, 8.0f, 2.0f, 4.0f},
+	{-21.0f, 14.0f, 2.0f, 3.0f},
+	{-16.0f, 19.0f, 2.0f, 3.0f},
+	{-23.0f, 24.0f, 3.0f, 3.0f},
+	{-18.0f, 28.0f, 2.0f, 4.0f},
+	{-24.0f, 31.0f, 2.0f, 3.0f},
+	{-20.0f, 36.0f, 2.0f, 3.0f},
+	{-22.0f, 41.0f, 3.0f, 3.0f},
+	{-21.0f, 45.0f, 2.0f, 3.0f},
+
+	{-12.0f, -40.0f, 2.0f, 4.0f},
+	{-11.0f, -35.0f, 3.0f, 3.0f},
+	{-10.0f, -29.0f, 1.0f, 3.0f},
+	{-9.0f, -26.0f, 2.0f, 2.0f},
+	{-6.0f, -22.0f, 2.0f, 3.0f},
+	{-15.0f, -15.0f, 1.0f, 3.0f},
+	{-8.0f, -11.0f, 2.0f, 3.0f},
+	{-14.0f, -6.0f, 2.0f, 4.0f},
+	{-12.0f, 0.0f, 2.0f, 3.0f},
+	{-7.0f, 4.0f, 2.0f, 2.0f},
+	{-13.0f, 8.0f, 2.0f, 2.0f},
+	{-9.0f, 13.0f, 1.0f, 3.0f},
+	{-13.0f, 17.0f, 3.0f, 4.0f},
+	{-6.0f, 23.0f, 2.0f, 3.0f},
+	{-12.0f, 27.0f, 1.0f, 2.0f},
+	{-8.0f, 32.0f, 2.0f, 3.0f},
+	{-10.0f, 37.0f, 3.0f, 3.0f},
+	{-11.0f, 42.0f, 2.0f, 2.0f},
+
+
+	{15.0f, 5.0f, 2.0f, 3.0f},
+	{15.0f, 10.0f, 2.0f, 3.0f},
+	{15.0f, 15.0f, 2.0f, 3.0f},
+	{15.0f, 20.0f, 2.0f, 3.0f},
+	{15.0f, 25.0f, 2.0f, 3.0f},
+	{15.0f, 30.0f, 2.0f, 3.0f},
+	{15.0f, 35.0f, 2.0f, 3.0f},
+	{15.0f, 40.0f, 2.0f, 3.0f},
+	{15.0f, 45.0f, 2.0f, 3.0f},
+
+	{25.0f, 5.0f, 2.0f, 3.0f},
+	{25.0f, 10.0f, 2.0f, 3.0f},
+	{25.0f, 15.0f, 2.0f, 3.0f},
+	{25.0f, 20.0f, 2.0f, 3.0f},
+	{25.0f, 25.0f, 2.0f, 3.0f},
+	{25.0f, 30.0f, 2.0f, 3.0f},
+	{25.0f, 35.0f, 2.0f, 3.0f},
+	{25.0f, 40.0f, 2.0f, 3.0f},
+	{25.0f, 45.0f, 2.0f, 3.0f},
+};
+
+void DrawForest(Framework::MatrixStack &modelMatrix)
+{
+	for(int iTree = 0; iTree < ARRAY_COUNT(g_forest); iTree++)
+	{
+		const TreeData &currTree = g_forest[iTree];
+
+		Framework::MatrixStackPusher push(modelMatrix);
+		modelMatrix.Translate(glm::vec3(currTree.fXPos, 0.0f, currTree.fZPos));
+		DrawTree(modelMatrix, currTree.fTrunkHeight, currTree.fConeHeight);
+	}
+}
+
+static bool g_bDrawLookatPoint = false;
+static glm::vec3 g_camTarget(0.0f, 0.4f, 0.0f);
+
+//In spherical coordinates.
+static glm::vec3 g_sphereCamRelPos(67.5f, -46.0f, 150.0f);
+
+glm::vec3 ResolveCamPosition()
+{
+	Framework::MatrixStack tempMat;
+
+	float rho = Framework::DegToRad(g_sphereCamRelPos.x);
+	float theta = Framework::DegToRad(g_sphereCamRelPos.y + 90.0f);
+
+	float fSinTheta = sinf(theta);
+	float fCosTheta = cosf(theta);
+	float fCosRho = cosf(rho);
+	float fSinRho = sinf(rho);
+
+	glm::vec3 dirToCamera(fSinTheta * fCosRho, fCosTheta, fSinTheta * fSinRho);
+	return (dirToCamera * g_sphereCamRelPos.z) + g_camTarget;
+}
+
+//Called to update the display.
+//You should call glutSwapBuffers after all of your rendering to display what you rendered.
+//If you need continuous updates of the screen, call glutPostRedisplay() at the end of the function.
+void display()
+{
+	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	if(g_pConeMesh && g_pCylinderMesh && g_pCubeTintMesh && g_pCubeColorMesh && g_pPlaneMesh)
+	{
+		const glm::vec3 &camPos = ResolveCamPosition();
+
+		Framework::MatrixStack camMatrix;
+		camMatrix.SetMatrix(CalcLookAtMatrix(camPos, g_camTarget, glm::vec3(0.0f, 1.0f, 0.0f)));
+
+		glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
+		glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4), glm::value_ptr(camMatrix.Top()));
+		glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+		Framework::MatrixStack modelMatrix;
+
+		//Render the ground plane.
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+
+			modelMatrix.Scale(glm::vec3(100.0f, 1.0f, 100.0f));
+
+			glUseProgram(UniformColor.theProgram);
+			glUniformMatrix4fv(UniformColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+			glUniform4f(UniformColor.baseColorUnif, 0.302f, 0.416f, 0.0589f, 1.0f);
+			g_pPlaneMesh->Render();
+			glUseProgram(0);
+		}
+
+		//Draw the trees
+		DrawForest(modelMatrix);
+
+		//Draw the building.
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+			modelMatrix.Translate(glm::vec3(20.0f, 0.0f, -10.0f));
+
+//			DrawParthenon(modelMatrix);
+		}
+
+		if(g_bDrawLookatPoint)
+		{
+			/*
+			glDisable(GL_DEPTH_TEST);
+			glm::mat4 idenity(1.0f);
+
+			Framework::MatrixStackPusher push(modelMatrix);
+
+			glm::vec3 cameraAimVec = g_camTarget - camPos;
+			modelMatrix.Translate(0.0f, 0.0, -glm::length(cameraAimVec));
+			modelMatrix.Scale(1.0f, 1.0f, 1.0f);
+
+			glUseProgram(ObjectColor.theProgram);
+			glUniformMatrix4fv(ObjectColor.modelToWorldMatrixUnif, 1, GL_FALSE, glm::value_ptr(modelMatrix.Top()));
+			glUniformMatrix4fv(ObjectColor.worldToCameraMatrixUnif, 1, GL_FALSE, glm::value_ptr(idenity));
+			g_pCubeColorMesh->Render();
+			glUseProgram(0);
+			glEnable(GL_DEPTH_TEST);
+			*/
+		}
+	}
+
+	glutSwapBuffers();
+}
+
+//Called whenever the window is resized. The new window size is given, in pixels.
+//This is an opportunity to call glViewport or glScissor to keep up with the change in size.
+void reshape (int w, int h)
+{
+	Framework::MatrixStack persMatrix;
+	persMatrix.Perspective(45.0f, (h / (float)w), g_fzNear, g_fzFar);
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_GlobalMatricesUBO);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4), glm::value_ptr(persMatrix.Top()));
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+/*
+	glUseProgram(UniformColor.theProgram);
+	glUniformMatrix4fv(UniformColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
+	glUseProgram(ObjectColor.theProgram);
+	glUniformMatrix4fv(ObjectColor.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
+	glUseProgram(UniformColorTint.theProgram);
+	glUniformMatrix4fv(UniformColorTint.cameraToClipMatrixUnif, 1, GL_FALSE, glm::value_ptr(persMatrix.Top()));
+	glUseProgram(0);
+*/
+
+	glViewport(0, 0, (GLsizei) w, (GLsizei) h);
+	glutPostRedisplay();
+}
+
+//Called whenever a key on the keyboard was pressed.
+//The key is given by the ''key'' parameter, which is in ASCII.
+//It's often a good idea to have the escape key (ASCII value 27) call glutLeaveMainLoop() to 
+//exit the program.
+void keyboard(unsigned char key, int x, int y)
+{
+	switch (key)
+	{
+	case 27:
+		delete g_pConeMesh;
+		g_pConeMesh = NULL;
+		delete g_pCylinderMesh;
+		g_pCylinderMesh = NULL;
+		delete g_pCubeTintMesh;
+		g_pCubeTintMesh = NULL;
+		delete g_pCubeColorMesh;
+		g_pCubeColorMesh = NULL;
+		delete g_pPlaneMesh;
+		g_pPlaneMesh = NULL;
+		glutLeaveMainLoop();
+		break;
+	case 'w': g_camTarget.z -= 4.0f; break;
+	case 's': g_camTarget.z += 4.0f; break;
+	case 'd': g_camTarget.x += 4.0f; break;
+	case 'a': g_camTarget.x -= 4.0f; break;
+	case 'e': g_camTarget.y -= 4.0f; break;
+	case 'q': g_camTarget.y += 4.0f; break;
+	case 'W': g_camTarget.z -= 0.4f; break;
+	case 'S': g_camTarget.z += 0.4f; break;
+	case 'D': g_camTarget.x += 0.4f; break;
+	case 'A': g_camTarget.x -= 0.4f; break;
+	case 'E': g_camTarget.y -= 0.4f; break;
+	case 'Q': g_camTarget.y += 0.4f; break;
+	case 'i': g_sphereCamRelPos.y -= 11.25f; break;
+	case 'k': g_sphereCamRelPos.y += 11.25f; break;
+	case 'j': g_sphereCamRelPos.x -= 11.25f; break;
+	case 'l': g_sphereCamRelPos.x += 11.25f; break;
+	case 'o': g_sphereCamRelPos.z -= 5.0f; break;
+	case 'u': g_sphereCamRelPos.z += 5.0f; break;
+	case 'I': g_sphereCamRelPos.y -= 1.125f; break;
+	case 'K': g_sphereCamRelPos.y += 1.125f; break;
+	case 'J': g_sphereCamRelPos.x -= 1.125f; break;
+	case 'L': g_sphereCamRelPos.x += 1.125f; break;
+	case 'O': g_sphereCamRelPos.z -= 0.5f; break;
+	case 'U': g_sphereCamRelPos.z += 0.5f; break;
+		
+	case 32:
+		g_bDrawLookatPoint = !g_bDrawLookatPoint;
+		printf("Target: %f, %f, %f\n", g_camTarget.x, g_camTarget.y, g_camTarget.z);
+		printf("Position: %f, %f, %f\n", g_sphereCamRelPos.x, g_sphereCamRelPos.y, g_sphereCamRelPos.z);
+		break;
+	}
+
+	g_sphereCamRelPos.y = glm::clamp(g_sphereCamRelPos.y, -78.75f, -1.0f);
+	g_camTarget.y = g_camTarget.y > 0.0f ? g_camTarget.y : 0.0f;
+	g_sphereCamRelPos.z = g_sphereCamRelPos.z > 5.0f ? g_sphereCamRelPos.z : 5.0f;
+
+	glutPostRedisplay();
+}
+
+

Tut 07 World in Motion/data/PosColorWorldTransformUBO.vert

+#version 330
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec4 color;
+
+smooth out vec4 interpColor;
+
+layout(std140) uniform GlobalMatrices
+{
+	mat4 cameraToClipMatrix;
+	mat4 worldToCameraMatrix;
+};
+
+uniform mat4 modelToWorldMatrix;
+
+void main()
+{
+	vec4 temp = modelToWorldMatrix * position;
+	temp = worldToCameraMatrix * temp;
+	gl_Position = cameraToClipMatrix * temp;
+	interpColor = color;
+}

Tut 07 World in Motion/data/PosOnlyWorldTransformUBO.vert

+#version 330
+
+layout(location = 0) in vec4 position;
+
+layout(std140) uniform GlobalMatrices
+{
+	mat4 cameraToClipMatrix;
+	mat4 worldToCameraMatrix;
+};
+
+uniform mat4 modelToWorldMatrix;
+
+void main()
+{
+	vec4 temp = modelToWorldMatrix * position;
+	temp = worldToCameraMatrix * temp;
+	gl_Position = cameraToClipMatrix * temp;
+}

Tut 07 World in Motion/tutorials.lua

 	"data/ColorPassthrough.frag",
 	"data/ColorMultUniform.frag",
 	"data/ColorUniform.frag")
+
+SetupProject("Tut 07 World With UBO", "World With UBO.cpp",
+	"data/PosOnlyWorldTransformUBO.vert",
+	"data/PosColorWorldTransformUBO.vert",
+	"data/ColorPassthrough.frag",
+	"data/ColorMultUniform.frag",
+	"data/ColorUniform.frag")
+

framework/framework.h

 		void RotateZ(float fAngDeg);
 
 		void Scale(const glm::vec3 &scaleVec);
+		void Scale(float fScaleX, float fScaleY, float fScaleZ) {Scale(glm::vec3(fScaleX, fScaleY, fScaleZ));}
 		void Translate(const glm::vec3 &offsetVec);
+		void Translate(float fTransX, float fTransY, float fTransZ) {Translate(glm::vec3(fTransX, fTransY, fTransZ));}
 
 		void ApplyMatrix(const glm::mat4 &theMatrix);
 		void SetMatrix(const glm::mat4 &theMatrix);