Commits

Jason McKesson committed 75d616c

Tut12: HDR tutorial works.

  • Participants
  • Parent commits 85a5f81

Comments (0)

Files changed (9)

Tut 12 Dynamic Range/HDR Lighting.cpp

+#include <algorithm>
+#include <string>
+#include <vector>
+#include <stack>
+#include <math.h>
+#include <glloader/gl_3_3_comp.h>
+#include <GL/freeglut.h>
+#include "../framework/framework.h"
+#include "../framework/Mesh.h"
+#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>
+
+#include "Lights.h"
+#include "Scene.h"
+
+#define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
+
+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;
+float g_fzFar = 1000.0f;
+
+struct Shaders
+{
+	const char *fileVertexShader;
+	const char *fileFragmentShader;
+};
+
+ProgramData g_Programs[LP_MAX_LIGHTING_PROGRAM_TYPES];
+Shaders g_ShaderFiles[LP_MAX_LIGHTING_PROGRAM_TYPES] =
+{
+	{"PCN.vert", "DiffuseSpecularHDR.frag"},
+	{"PCN.vert", "DiffuseOnlyHDR.frag"},
+
+	{"PN.vert", "DiffuseSpecularMtlHDR.frag"},
+	{"PN.vert", "DiffuseOnlyMtlHDR.frag"},
+};
+
+UnlitProgData g_Unlit;
+
+const int g_materialBlockIndex = 0;
+const int g_lightBlockIndex = 1;
+const int g_projectionBlockIndex = 2;
+
+UnlitProgData LoadUnlitProgram(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));
+
+	UnlitProgData data;
+	data.theProgram = Framework::CreateProgram(shaderList);
+	data.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+	data.objectColorUnif = glGetUniformLocation(data.theProgram, "objectColor");
+
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	return data;
+}
+
+ProgramData LoadLitProgram(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.modelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "modelToCameraMatrix");
+
+	data.normalModelToCameraMatrixUnif = glGetUniformLocation(data.theProgram, "normalModelToCameraMatrix");
+
+	GLuint materialBlock = glGetUniformBlockIndex(data.theProgram, "Material");
+	GLuint lightBlock = glGetUniformBlockIndex(data.theProgram, "Light");
+	GLuint projectionBlock = glGetUniformBlockIndex(data.theProgram, "Projection");
+
+	glUniformBlockBinding(data.theProgram, materialBlock, g_materialBlockIndex);
+	glUniformBlockBinding(data.theProgram, lightBlock, g_lightBlockIndex);
+	glUniformBlockBinding(data.theProgram, projectionBlock, g_projectionBlockIndex);
+
+	return data;
+}
+
+void InitializePrograms()
+{
+	for(int iProg = 0; iProg < LP_MAX_LIGHTING_PROGRAM_TYPES; iProg++)
+	{
+		g_Programs[iProg] = LoadLitProgram(
+			g_ShaderFiles[iProg].fileVertexShader, g_ShaderFiles[iProg].fileFragmentShader);
+	}
+
+	g_Unlit = LoadUnlitProgram("PosTransform.vert", "UniformColor.frag");
+}
+
+const ProgramData &GetProgram(LightingProgramTypes eType)
+{
+	return g_Programs[eType];
+}
+
+
+LightManager g_lights;
+
+Framework::RadiusDef radiusDef = {50.0f, 3.0f, 80.0f, 4.0f, 1.0f};
+glm::vec3 objectCenter = glm::vec3(-59.5f, 4.0f, 65.0f);
+
+Framework::MousePole g_mousePole(objectCenter, radiusDef);
+
+namespace
+{
+	void MouseMotion(int x, int y)
+	{
+		g_mousePole.GLUTMouseMove(glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+
+	void MouseButton(int button, int state, int x, int y)
+	{
+		g_mousePole.GLUTMouseButton(button, state, glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+
+	void MouseWheel(int wheel, int direction, int x, int y)
+	{
+		g_mousePole.GLUTMouseWheel(direction, glm::ivec2(x, y));
+		glutPostRedisplay();
+	}
+}
+
+struct ProjectionBlock
+{
+	glm::mat4 cameraToClipMatrix;
+};
+
+GLuint g_lightUniformBuffer;
+GLuint g_materialUniformBuffer;
+GLuint g_projectionUniformBuffer;
+
+const glm::vec4 g_skyDaylightColor = glm::vec4(0.65f, 0.65f, 1.0f, 1.0f);
+
+void SetupDaytimeLighting()
+{
+	SunlightValue values[] =
+	{
+		{ 0.0f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+		{ 4.5f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+		{ 6.5f/24.0f, glm::vec4(0.15f, 0.05f, 0.05f, 1.0f), glm::vec4(0.3f, 0.1f, 0.10f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f)},
+		{ 8.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)},
+		{18.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)},
+		{19.5f/24.0f, glm::vec4(0.15f, 0.05f, 0.05f, 1.0f), glm::vec4(0.3f, 0.1f, 0.1f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f)},
+		{20.5f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+	};
+
+	g_lights.SetSunlightValues(values, 7);
+
+	g_lights.SetPointLightIntensity(0, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f));
+	g_lights.SetPointLightIntensity(1, glm::vec4(0.0f, 0.0f, 0.3f, 1.0f));
+	g_lights.SetPointLightIntensity(2, glm::vec4(0.3f, 0.0f, 0.0f, 1.0f));
+}
+
+void SetupNighttimeLighting()
+{
+	SunlightValue values[] =
+	{
+		{ 0.0f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+		{ 4.5f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+		{ 6.5f/24.0f, glm::vec4(0.15f, 0.05f, 0.05f, 1.0f), glm::vec4(0.3f, 0.1f, 0.10f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f)},
+		{ 8.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)},
+		{18.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)},
+		{19.5f/24.0f, glm::vec4(0.15f, 0.05f, 0.05f, 1.0f), glm::vec4(0.3f, 0.1f, 0.1f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f)},
+		{20.5f/24.0f, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f), glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), g_skyDaylightColor},
+	};
+
+	g_lights.SetSunlightValues(values, 7);
+
+	g_lights.SetPointLightIntensity(0, glm::vec4(0.6f, 0.6f, 0.6f, 1.0f));
+	g_lights.SetPointLightIntensity(1, glm::vec4(0.0f, 0.0f, 0.7f, 1.0f));
+	g_lights.SetPointLightIntensity(2, glm::vec4(0.7f, 0.0f, 0.0f, 1.0f));
+}
+
+void SetupHDRLighting()
+{
+	SunlightValueHDR values[] =
+	{
+		{ 0.0f/24.0f, glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), glm::vec4(1.8f, 1.8f, 1.8f, 1.0f), g_skyDaylightColor, 3.0f},
+		{ 4.5f/24.0f, glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), glm::vec4(1.8f, 1.8f, 1.8f, 1.0f), g_skyDaylightColor, 3.0f},
+		{ 6.5f/24.0f, glm::vec4(0.225f, 0.075f, 0.075f, 1.0f), glm::vec4(0.45f, 0.15f, 0.15f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f), 1.5f},
+		{ 8.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 1.0f},
+		{18.0f/24.0f, glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), 1.0f},
+		{19.5f/24.0f, glm::vec4(0.225f, 0.075f, 0.075f, 1.0f), glm::vec4(0.45f, 0.15f, 0.15f, 1.0f), glm::vec4(0.5f, 0.1f, 0.1f, 1.0f), 1.5f},
+		{20.5f/24.0f, glm::vec4(0.6f, 0.6f, 0.6f, 1.0f), glm::vec4(1.8f, 1.8f, 1.8f, 1.0f), g_skyDaylightColor, 3.0f},
+	};
+
+	g_lights.SetSunlightValues(values, 7);
+
+	g_lights.SetPointLightIntensity(0, glm::vec4(0.6f, 0.6f, 0.6f, 1.0f));
+	g_lights.SetPointLightIntensity(1, glm::vec4(0.0f, 0.0f, 0.7f, 1.0f));
+	g_lights.SetPointLightIntensity(2, glm::vec4(0.7f, 0.0f, 0.0f, 1.0f));
+}
+
+Scene *g_pScene = NULL;
+
+//Called after the window and OpenGL are initialized. Called exactly once, before the main loop.
+void init()
+{
+	InitializePrograms();
+
+	try
+	{
+		g_pScene = new Scene();
+	}
+	catch(std::exception &except)
+	{
+		printf(except.what());
+		throw;
+	}
+
+	SetupDaytimeLighting();
+
+	g_lights.CreateTimer("tetra", Framework::Timer::TT_LOOP, 2.5f);
+
+	glutMouseFunc(MouseButton);
+ 	glutMotionFunc(MouseMotion);
+	glutMouseWheelFunc(MouseWheel);
+
+	glEnable(GL_CULL_FACE);
+	glCullFace(GL_BACK);
+	glFrontFace(GL_CW);
+
+	const float depthZNear = 0.0f;
+	const float depthZFar = 1.0f;
+
+	glEnable(GL_DEPTH_TEST);
+	glDepthMask(GL_TRUE);
+	glDepthFunc(GL_LEQUAL);
+	glDepthRange(depthZNear, depthZFar);
+	glEnable(GL_DEPTH_CLAMP);
+
+	//Setup our Uniform Buffers
+	glGenBuffers(1, &g_lightUniformBuffer);
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferData(GL_UNIFORM_BUFFER, sizeof(LightBlock), NULL, GL_DYNAMIC_DRAW);
+
+	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_lightBlockIndex, g_lightUniformBuffer,
+		0, sizeof(LightBlock));
+
+	glBindBufferRange(GL_UNIFORM_BUFFER, g_projectionBlockIndex, g_projectionUniformBuffer,
+		0, sizeof(ProjectionBlock));
+
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+bool g_bDrawCameraPos = false;
+bool g_bDrawLights = true;
+
+//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()
+{
+	g_lights.UpdateTime();
+
+	glm::vec4 bkg = g_lights.GetBackgroundColor();
+
+	glClearColor(bkg[0], bkg[1], bkg[2], bkg[3]);
+	glClearDepth(1.0f);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+	Framework::MatrixStack modelMatrix;
+	modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
+
+	const glm::mat4 &worldToCamMat = modelMatrix.Top();
+	LightBlockHDR lightData = g_lights.GetLightInformationHDR(worldToCamMat);
+
+	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
+	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightData), &lightData);
+	glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+	if(g_pScene)
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+
+		g_pScene->Draw(modelMatrix, g_materialBlockIndex, g_lights.GetTimerValue("tetra"));
+	}
+
+	{
+		Framework::MatrixStackPusher push(modelMatrix);
+		//Render the sun
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+
+			glm::vec3 sunlightDir(g_lights.GetSunlightDirection());
+			modelMatrix.Translate(sunlightDir * 500.0f);
+			modelMatrix.Scale(30.0f, 30.0f, 30.0f);
+
+			glUseProgram(g_Unlit.theProgram);
+			glUniformMatrix4fv(g_Unlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+
+			glm::vec4 lightColor = g_lights.GetSunlightIntensity();
+			glUniform4fv(g_Unlit.objectColorUnif, 1, glm::value_ptr(lightColor));
+			g_pScene->GetSphereMesh()->Render("flat");
+		}
+
+		//Render the lights
+		if(g_bDrawLights)
+		{
+			for(int light = 0; light < g_lights.GetNumberOfPointLights(); light++)
+			{
+				Framework::MatrixStackPusher push(modelMatrix);
+
+				modelMatrix.Translate(g_lights.GetWorldLightPosition(light));
+
+				glUseProgram(g_Unlit.theProgram);
+				glUniformMatrix4fv(g_Unlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+					glm::value_ptr(modelMatrix.Top()));
+
+				glm::vec4 lightColor = g_lights.GetPointLightIntensity(light);
+				glUniform4fv(g_Unlit.objectColorUnif, 1, glm::value_ptr(lightColor));
+				g_pScene->GetCubeMesh()->Render("flat");
+			}
+		}
+
+		if(g_bDrawCameraPos)
+		{
+			Framework::MatrixStackPusher push(modelMatrix);
+
+			modelMatrix.SetIdentity();
+			modelMatrix.Translate(glm::vec3(0.0f, 0.0f, -g_mousePole.GetLookAtDistance()));
+
+			glDisable(GL_DEPTH_TEST);
+			glDepthMask(GL_FALSE);
+			glUseProgram(g_Unlit.theProgram);
+			glUniformMatrix4fv(g_Unlit.modelToCameraMatrixUnif, 1, GL_FALSE,
+				glm::value_ptr(modelMatrix.Top()));
+			glUniform4f(g_Unlit.objectColorUnif, 0.25f, 0.25f, 0.25f, 1.0f);
+			g_pScene->GetCubeMesh()->Render("flat");
+			glDepthMask(GL_TRUE);
+			glEnable(GL_DEPTH_TEST);
+			glUniform4f(g_Unlit.objectColorUnif, 1.0f, 1.0f, 1.0f, 1.0f);
+			g_pScene->GetCubeMesh()->Render("flat");
+		}
+	}
+
+	glutPostRedisplay();
+	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);
+
+	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();
+}
+
+
+TimerTypes g_eTimerMode = TIMER_ALL;
+
+//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)
+{
+	bool bChangedShininess = false;
+	bool bChangedLightModel = false;
+	switch (key)
+	{
+	case 27:
+		delete g_pScene;
+		g_pScene = NULL;
+		glutLeaveMainLoop();
+		break;
+		
+	case 'p': g_lights.TogglePause(g_eTimerMode); break;
+	case '-': g_lights.RewindTime(g_eTimerMode, 1.0f); break;
+	case '=': g_lights.FastForwardTime(g_eTimerMode, 1.0f); break;
+	case 't': g_bDrawCameraPos = !g_bDrawCameraPos; break;
+	case '1': g_eTimerMode = TIMER_ALL; printf("All\n"); break;
+	case '2': g_eTimerMode = TIMER_SUN; printf("Sun\n"); break;
+	case '3': g_eTimerMode = TIMER_LIGHTS; printf("Lights\n"); break;
+
+	case 'l': SetupDaytimeLighting(); break;
+	case 'L': SetupNighttimeLighting(); break;
+	case 'k': SetupHDRLighting(); break;
+
+	case 32:
+		{
+			float sunAlpha = g_lights.GetSunTime();
+			float sunTimeHours = sunAlpha * 24.0f + 12.0f;
+			sunTimeHours = sunTimeHours > 24.0f ? sunTimeHours - 24.0f : sunTimeHours;
+			int sunHours = int(sunTimeHours);
+			float sunTimeMinutes = (sunTimeHours - sunHours) * 60.0f;
+			int sunMinutes = int(sunTimeMinutes);
+			printf("%02i:%02i\n", sunHours, sunMinutes);
+		}
+		break;
+	}
+
+	g_mousePole.GLUTKeyOffset(key, 5.0f, 1.0f);
+}
+
+

Tut 12 Dynamic Range/Lights.cpp

 	posValues.push_back(glm::vec3(-60.0f, 20.0f, 90.0f));
 	posValues.push_back(glm::vec3(-40.0f, 25.0f, 90.0f));
 
-
 	m_lightPos[2].SetValues(posValues);
-	m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 5.0f));
+	m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f));
 }
 
+typedef std::pair<float, float> MaxIntensityData;
+typedef std::vector<MaxIntensityData> MaxIntensityVector;
 typedef std::pair<glm::vec4, float> LightVectorData;
-typedef std::vector<LightVectorData> LightVectors;
+typedef std::vector<LightVectorData> LightVector;
 
 glm::vec4 GetValue(const LightVectorData &data) {return data.first;}
 float GetTime(const LightVectorData &data) {return data.second;}
-
-void LightManager::SetSunlightValues( const std::vector<SunlightValue> &values )
-{
-	LightVectors ambient;
-	LightVectors light;
-	LightVectors background;
-
-	for(size_t valIx = 0; valIx < values.size(); ++valIx)
-	{
-		ambient.push_back(LightVectorData(values[valIx].ambient, values[valIx].normTime));
-		light.push_back(LightVectorData(values[valIx].sunlightIntensity, values[valIx].normTime));
-		background.push_back(LightVectorData(values[valIx].backgroundColor, values[valIx].normTime));
-	}
-
-	m_ambientInterpolator.SetValues(ambient);
-	m_sunlightInterpolator.SetValues(light);
-	m_backgroundInterpolator.SetValues(background);
-}
+float GetValue(const MaxIntensityData &data) {return data.first;}
+float GetTime(const MaxIntensityData &data) {return data.second;}
 
 void LightManager::SetSunlightValues( SunlightValue *pValues, int iSize )
 {
-	LightVectors ambient;
-	LightVectors light;
-	LightVectors background;
+	LightVector ambient;
+	LightVector light;
+	LightVector background;
 
 	for(int valIx = 0; valIx < iSize; ++valIx)
 	{
 	m_ambientInterpolator.SetValues(ambient);
 	m_sunlightInterpolator.SetValues(light);
 	m_backgroundInterpolator.SetValues(background);
+
+	MaxIntensityVector maxIntensity;
+	maxIntensity.push_back(MaxIntensityData(1.0f, 0.0f));
+	m_maxIntensityInterpolator.SetValues(maxIntensity, false);
+}
+
+void LightManager::SetSunlightValues( SunlightValueHDR *pValues, int iSize )
+{
+	LightVector ambient;
+	LightVector light;
+	LightVector background;
+	MaxIntensityVector maxIntensity;
+
+	for(int valIx = 0; valIx < iSize; ++valIx)
+	{
+		ambient.push_back(LightVectorData(pValues[valIx].ambient, pValues[valIx].normTime));
+		light.push_back(LightVectorData(pValues[valIx].sunlightIntensity, pValues[valIx].normTime));
+		background.push_back(LightVectorData(pValues[valIx].backgroundColor, pValues[valIx].normTime));
+		maxIntensity.push_back(MaxIntensityData(pValues[valIx].maxIntensity, pValues[valIx].normTime));
+	}
+
+	m_ambientInterpolator.SetValues(ambient);
+	m_sunlightInterpolator.SetValues(light);
+	m_backgroundInterpolator.SetValues(background);
+	m_maxIntensityInterpolator.SetValues(maxIntensity);
 }
 
 struct UpdateTimer
 	}
 }
 
-LightBlock LightManager::GetLightPositions( const glm::mat4 &worldToCameraMat ) const
+LightBlock LightManager::GetLightInformation( const glm::mat4 &worldToCameraMat ) const
 {
 	LightBlock lightData;
 
 	return lightData;
 }
 
+
+LightBlockHDR LightManager::GetLightInformationHDR( const glm::mat4 &worldToCameraMat ) const
+{
+	LightBlockHDR lightData;
+
+	lightData.ambientIntensity = m_ambientInterpolator.Interpolate(m_sunTimer.GetAlpha());
+	lightData.lightAttenuation = g_fLightAttenuation;
+	lightData.maxIntensity = m_maxIntensityInterpolator.Interpolate(m_sunTimer.GetAlpha());
+
+	lightData.lights[0].cameraSpaceLightPos =
+		worldToCameraMat * GetSunlightDirection();
+	lightData.lights[0].lightIntensity = m_sunlightInterpolator.Interpolate(m_sunTimer.GetAlpha());
+
+	for(int light = 0; light < NUMBER_OF_POINT_LIGHTS; light++)
+	{
+		glm::vec4 worldLightPos =
+			glm::vec4(m_lightPos[light].Interpolate(m_lightTimers[light].GetAlpha()), 1.0f);
+		glm::vec4 lightPosCameraSpace = worldToCameraMat * worldLightPos;
+
+		lightData.lights[light + 1].cameraSpaceLightPos = lightPosCameraSpace;
+		lightData.lights[light + 1].lightIntensity = m_lightIntensity[light];
+	}
+
+	return lightData;
+}
+
 glm::vec4 LightManager::GetSunlightDirection() const
 {
 	float angle = 2.0f * 3.14159f * m_sunTimer.GetAlpha();
 	return m_backgroundInterpolator.Interpolate(m_sunTimer.GetAlpha());
 }
 
+float LightManager::GetMaxIntensity() const
+{
+	return m_maxIntensityInterpolator.Interpolate(m_sunTimer.GetAlpha());
+}
+
 float LightManager::GetSunTime() const
 {
 	return m_sunTimer.GetAlpha();

Tut 12 Dynamic Range/Lights.h

 	PerLight lights[NUMBER_OF_LIGHTS];
 };
 
+struct LightBlockHDR
+{
+	glm::vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	float padding[2];
+	PerLight lights[NUMBER_OF_LIGHTS];
+};
+
 struct SunlightValue
 {
 	float normTime;
 	glm::vec4 backgroundColor;
 };
 
+struct SunlightValueHDR
+{
+	float normTime;
+	glm::vec4 ambient;
+	glm::vec4 sunlightIntensity;
+	glm::vec4 backgroundColor;
+	float maxIntensity;
+};
+
 enum TimerTypes
 {
 	TIMER_SUN,
 public:
 	LightManager();
 
-	void SetSunlightValues(const std::vector<SunlightValue> &values);
 	void SetSunlightValues(SunlightValue *pValues, int iSize);
+	void SetSunlightValues(SunlightValueHDR *pValues, int iSize);
 
 	void UpdateTime();
 	void TogglePause(TimerTypes eTimer);
 	void RewindTime(TimerTypes eTimer, float secRewind);
 	void FastForwardTime(TimerTypes eTimer, float secRewind);
 
-	LightBlock GetLightPositions(const glm::mat4 &worldToCameraMat) const;
+	LightBlock GetLightInformation(const glm::mat4 &worldToCameraMat) const;
+	LightBlockHDR GetLightInformationHDR(const glm::mat4 &worldToCameraMat) const;
+
 	glm::vec4 GetBackgroundColor() const;
+	float GetMaxIntensity() const;
 
 	glm::vec4 GetSunlightDirection() const;
 	glm::vec4 GetSunlightIntensity() const;
 	Framework::TimedLinearInterpolator<glm::vec4> m_ambientInterpolator;
 	Framework::TimedLinearInterpolator<glm::vec4> m_backgroundInterpolator;
 	Framework::TimedLinearInterpolator<glm::vec4> m_sunlightInterpolator;
+	Framework::TimedLinearInterpolator<float> m_maxIntensityInterpolator;
 
 	std::vector<LightInterpolator> m_lightPos;
 	std::vector<glm::vec4> m_lightIntensity;

Tut 12 Dynamic Range/Scene Lighting.cpp

 	modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
 
 	const glm::mat4 &worldToCamMat = modelMatrix.Top();
-	LightBlock lightData = g_lights.GetLightPositions(worldToCamMat);
+	LightBlock lightData = g_lights.GetLightInformation(worldToCamMat);
 
 	glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
 	glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightData), &lightData);
 	case 'L': SetupNighttimeLighting(); break;
 
 	case 32:
-		printf("%f\n", g_lights.GetSunTime());
+		{
+			float sunAlpha = g_lights.GetSunTime();
+			float sunTimeHours = sunAlpha * 24.0f + 12.0f;
+			sunTimeHours = sunTimeHours > 24.0f ? sunTimeHours - 24.0f : sunTimeHours;
+			int sunHours = int(sunTimeHours);
+			float sunTimeMinutes = (sunTimeHours - sunHours) * 60.0f;
+			int sunMinutes = int(sunTimeMinutes);
+			printf("%02i:%02i\n", sunHours, sunMinutes);
+		}
 		break;
 	}
 

Tut 12 Dynamic Range/data/DiffuseOnlyHDR.frag

+#version 330
+
+in vec4 diffuseColor;
+in vec3 vertexNormal;
+in vec3 cameraSpacePosition;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 4;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+vec4 ComputeLighting(in PerLight lightData)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(vertexNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec4 lighting = diffuseColor * lightIntensity * cosAngIncidence;
+	
+	return lighting;
+}
+
+void main()
+{
+	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light]);
+	}
+	
+	outputColor = accumLighting / Lgt.maxIntensity;
+}

Tut 12 Dynamic Range/data/DiffuseOnlyMtlHDR.frag

+#version 330
+
+in vec3 vertexNormal;
+in vec3 cameraSpacePosition;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 4;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+vec4 ComputeLighting(in PerLight lightData)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(vertexNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec4 lighting = Mtl.diffuseColor * lightIntensity * cosAngIncidence;
+	
+	return lighting;
+}
+
+void main()
+{
+	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light]);
+	}
+	
+	outputColor = accumLighting / Lgt.maxIntensity;
+}

Tut 12 Dynamic Range/data/DiffuseSpecularHDR.frag

+#version 330
+
+in vec4 diffuseColor;
+in vec3 vertexNormal;
+in vec3 cameraSpacePosition;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 4;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+vec4 ComputeLighting(in PerLight lightData)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(vertexNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+	vec3 halfAngle = normalize(lightDir + viewDirection);
+	float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));
+	float exponent = angleNormalHalf / Mtl.specularShininess;
+	exponent = -(exponent * exponent);
+	float gaussianTerm = exp(exponent);
+
+	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
+
+void main()
+{
+	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light]);
+	}
+	
+	outputColor = accumLighting / Lgt.maxIntensity;
+}

Tut 12 Dynamic Range/data/DiffuseSpecularMtlHDR.frag

+#version 330
+
+in vec3 vertexNormal;
+in vec3 cameraSpacePosition;
+
+out vec4 outputColor;
+
+layout(std140) uniform;
+
+uniform Material
+{
+	vec4 diffuseColor;
+	vec4 specularColor;
+	float specularShininess;
+} Mtl;
+
+struct PerLight
+{
+	vec4 cameraSpaceLightPos;
+	vec4 lightIntensity;
+};
+
+const int numberOfLights = 4;
+
+uniform Light
+{
+	vec4 ambientIntensity;
+	float lightAttenuation;
+	float maxIntensity;
+	PerLight lights[numberOfLights];
+} Lgt;
+
+
+float CalcAttenuation(in vec3 cameraSpacePosition,
+	in vec3 cameraSpaceLightPos,
+	out vec3 lightDirection)
+{
+	vec3 lightDifference =  cameraSpaceLightPos - cameraSpacePosition;
+	float lightDistanceSqr = dot(lightDifference, lightDifference);
+	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
+	
+	return (1 / ( 1.0 + Lgt.lightAttenuation * lightDistanceSqr));
+}
+
+vec4 ComputeLighting(in PerLight lightData)
+{
+	vec3 lightDir;
+	vec4 lightIntensity;
+	if(lightData.cameraSpaceLightPos.w == 0.0)
+	{
+		lightDir = vec3(lightData.cameraSpaceLightPos);
+		lightIntensity = lightData.lightIntensity;
+	}
+	else
+	{
+		float atten = CalcAttenuation(cameraSpacePosition,
+			lightData.cameraSpaceLightPos.xyz, lightDir);
+		lightIntensity = atten * lightData.lightIntensity;
+	}
+	
+	vec3 surfaceNormal = normalize(vertexNormal);
+	float cosAngIncidence = dot(surfaceNormal, lightDir);
+	cosAngIncidence = cosAngIncidence < 0.0001 ? 0.0 : cosAngIncidence;
+	
+	vec3 viewDirection = normalize(-cameraSpacePosition);
+	
+	vec3 halfAngle = normalize(lightDir + viewDirection);
+	float angleNormalHalf = acos(dot(halfAngle, surfaceNormal));
+	float exponent = angleNormalHalf / Mtl.specularShininess;
+	exponent = -(exponent * exponent);
+	float gaussianTerm = exp(exponent);
+
+	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = Mtl.diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
+
+void main()
+{
+	vec4 accumLighting = Mtl.diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light]);
+	}
+	
+	outputColor = accumLighting / Lgt.maxIntensity;
+}

Tut 12 Dynamic Range/tutorials.lua

 	"data/DiffuseSpecularMtl.frag", "data/DiffuseOnlyMtl.frag"
 )
 
+SetupProject("Tut 12 HDR Lighting", "HDR Lighting.cpp",
+	"Lights.h", "Lights.cpp", "Scene.h", "Scene.cpp",
+	"data/PNC.vert", "data/PN.vert",
+	"data/DiffuseSpecular.frag", "data/DiffuseOnly.frag",
+	"data/DiffuseSpecularMtl.frag", "data/DiffuseOnlyMtl.frag"
+)
+