Commits

Jason McKesson committed d2472b1

Tut12: Added interpolators to framework. Added lighting manager.

  • Participants
  • Parent commits 53eb28f

Comments (0)

Files changed (8)

File Tut 12 Dynamic Range/Lights.cpp

+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <stack>
+#include <math.h>
+#include "Lights.h"
+
+static float g_fLightHeight = 5.5f;
+static float g_fLightRadius = 70.0f;
+
+glm::vec4 CalcLightPosition(const Framework::Timer &timer, float alphaOffset)
+{
+	const float fLoopDuration = 5.0f;
+	const float fScale = 3.14159f * 2.0f;
+
+	float timeThroughLoop = timer.GetAlpha() + alphaOffset;
+
+	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
+
+	ret.x = cosf(timeThroughLoop * fScale) * g_fLightRadius;
+	ret.z = sinf(timeThroughLoop * fScale) * g_fLightRadius;
+
+	return ret;
+}
+
+const float g_fLightAttenuation = 1.0f / (15.0f * 15.0f);
+
+LightManager::LightManager()
+	: keyLightTimer(Framework::Timer::TT_LOOP, 5.0f)
+	, ambientInterpolator(false, 5)
+{
+	ambientInterpolator.AppendValue(glm::vec4(0.2f, 0.2f, 0.2f, 1.0f));
+	ambientInterpolator.AppendValue(glm::vec4(0.0f, 0.0f, 0.0f, 1.0f));
+	ambientInterpolator.AppendValue(glm::vec4(0.7f, 0.7f, 0.7f, 1.0f));
+	ambientInterpolator.AppendValue(glm::vec4(0.0f, 0.5f, 0.0f, 1.0f));
+	ambientInterpolator.AppendValue(glm::vec4(0.2f, 0.2f, 0.2f, 1.0f));
+}
+
+void LightManager::UpdateTime()
+{
+	keyLightTimer.Update();
+}
+
+bool LightManager::TogglePause()
+{
+	return keyLightTimer.TogglePause();
+}
+
+LightBlock LightManager::GetLightPositions( const glm::mat4 &worldToCameraMat ) const
+{
+	LightBlock lightData;
+
+	lightData.ambientIntensity = ambientInterpolator.Interpolate(keyLightTimer.GetAlpha());
+	lightData.lightAttenuation = g_fLightAttenuation;
+
+	lightData.lights[0].cameraSpaceLightPos =
+		worldToCameraMat * glm::vec4(0.0f, 1.0f, 0.0f, 0.0f);
+
+	lightData.lights[0].lightIntensity = glm::vec4(0.5f, 0.5f, 0.5f, 1.0f);
+
+	for(int light = 1; light < NUMBER_OF_LIGHTS; light++)
+	{
+		glm::vec4 worldLightPos = CalcLightPosition(keyLightTimer,
+			light * (1.0f / (NUMBER_OF_LIGHTS - 1)));
+		glm::vec4 lightPosCameraSpace = worldToCameraMat * worldLightPos;
+
+		lightData.lights[light].cameraSpaceLightPos = lightPosCameraSpace;
+		lightData.lights[light].lightIntensity = glm::vec4(0.1f, 0.1f, 0.0f, 1.0f);
+	}
+
+	return lightData;
+}
+
+int LightManager::GetNumberOfPointLights() const
+{
+	return NUMBER_OF_LIGHTS - 1;
+}
+
+glm::vec3 LightManager::GetWorldLightPosition( int iLightIx ) const
+{
+	glm::vec4 worldLightPos = CalcLightPosition(keyLightTimer,
+		iLightIx * (1.0f / (NUMBER_OF_LIGHTS - 1)));
+
+
+	return glm::vec3(worldLightPos);
+}

File Tut 12 Dynamic Range/Lights.h

+
+#ifndef LIGHTS_H
+#define LIGHTS_H
+
+#include "../framework/Timer.h"
+#include <glm/glm.hpp>
+#include "../framework/Interpolators.h"
+
+
+struct PerLight
+{
+	glm::vec4 cameraSpaceLightPos;
+	glm::vec4 lightIntensity;
+};
+
+const int NUMBER_OF_LIGHTS = 4;
+
+struct LightBlock
+{
+	glm::vec4 ambientIntensity;
+	float lightAttenuation;
+	float padding[3];
+	PerLight lights[NUMBER_OF_LIGHTS];
+};
+
+class LightManager
+{
+public:
+	LightManager();
+
+	void UpdateTime();
+
+	bool TogglePause();
+
+	LightBlock GetLightPositions(const glm::mat4 &worldToCameraMat) const;
+
+	int GetNumberOfPointLights() const;
+	glm::vec3 GetWorldLightPosition(int iLightIx) const;
+
+private:
+	Framework::Timer keyLightTimer;
+	Framework::LinearInterpolator<glm::vec4> ambientInterpolator;
+
+};
+
+#endif //LIGHTS_H

File Tut 12 Dynamic Range/Scene Lighting.cpp

 #include <glm/glm.hpp>
 #include <glm/gtc/type_ptr.hpp>
 
+#include "Lights.h"
+
 #define ARRAY_COUNT( array ) (sizeof( array ) / (sizeof( array[0] ) * (sizeof( array ) != sizeof(void*) || sizeof( array[0] ) <= sizeof(void*))))
 
 struct ProgramData
 			glm::value_ptr(cameraToClip));
 		glUseProgram(0);
 	}
-
 };
 
 float g_fzNear = 1.0f;
 	Framework::Timer keyLightTimer;
 };
 
-TimeKeeper g_time;
+LightManager g_lights;
 
 Framework::RadiusDef radiusDef = {50.0f, 3.0f, 80.0f, 4.0f, 1.0f};
 glm::vec3 objectCenter = glm::vec3(-50.0f, 0.0f, 50.0f);
 	float padding[3];
 };
 
-struct PerLight
-{
-	glm::vec3 cameraSpaceLightPos;
-	float padding;
-	glm::vec4 lightIntensity;
-};
-
-struct LightBlock
-{
-	glm::vec4 ambientIntensity;
-	float lightAttenuation;
-	float padding[3];
-	PerLight lights;
-};
-
 struct ProjectionBlock
 {
 	glm::mat4 cameraToClipMatrix;
 };
 
-LightBlock g_lightData;
-
 GLuint g_lightUniformBuffer;
 GLuint g_materialUniformBuffer;
 GLuint g_projectionUniformBuffer;
 	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);
 	glBindBuffer(GL_UNIFORM_BUFFER, 0);
 }
 
-static float g_fLightHeight = 1.5f;
-static float g_fLightRadius = 70.0f;
-
-static float g_fRotateTime = 0.0f;
-static float g_fPrevTime = 0.0f;
-
 bool g_bDrawCameraPos = false;
 
-glm::vec4 CalcLightPosition()
-{
-	const float fLoopDuration = 5.0f;
-	const float fScale = 3.14159f * 2.0f;
-
-	float timeThroughLoop = g_time.keyLightTimer.GetAlpha();
-
-	glm::vec4 ret(0.0f, g_fLightHeight, 0.0f, 1.0f);
-
-	ret.x = cosf(timeThroughLoop * fScale) * g_fLightRadius;
-	ret.z = sinf(timeThroughLoop * fScale) * g_fLightRadius;
-
-	return ret;
-}
-
-const float g_fLightAttenuation = 1.0f / (50.0f * 50.0f);
-
-const glm::vec4 g_darkColor(0.2f, 0.2f, 0.2f, 1.0f);
-const glm::vec4 g_lightColor(1.0f);
-
 //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_time.Update();
+	g_lights.UpdateTime();
 
 	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 	glClearDepth(1.0f);
 		Framework::MatrixStack modelMatrix;
 		modelMatrix.SetMatrix(g_mousePole.CalcMatrix());
 
-		const glm::vec4 &worldLightPos = CalcLightPosition();
-		const glm::vec4 &lightPosCameraSpace = modelMatrix.Top() * worldLightPos;
-
 		ProgramData &prog = g_Programs[LM_VERT_COLOR_DIFFUSE_SPECULAR];
 
-		LightBlock lightData;
-		lightData.ambientIntensity = glm::vec4(0.2f, 0.2f, 0.2f, 1.0f);
-		lightData.lightAttenuation = g_fLightAttenuation;
-		lightData.lights.cameraSpaceLightPos = glm::vec3(lightPosCameraSpace);
-		lightData.lights.lightIntensity = glm::vec4(0.8f, 0.8f, 0.8f, 1.0f);
+		const glm::mat4 &worldToCamMat = modelMatrix.Top();
+		LightBlock lightData = g_lights.GetLightPositions(worldToCamMat);
 
 		glBindBuffer(GL_UNIFORM_BUFFER, g_lightUniformBuffer);
 		glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(lightData), &lightData);
 			}
 
 			//Render the light
+			for(int light = 0; light < g_lights.GetNumberOfPointLights(); light++)
 			{
 				Framework::MatrixStackPusher push(modelMatrix);
 
-				modelMatrix.Translate(glm::vec3(worldLightPos));
-				modelMatrix.Scale(1.f, 1.f, 1.f);
+				modelMatrix.Translate(g_lights.GetWorldLightPosition(light));
 
 				glUseProgram(g_Unlit.theProgram);
 				glUniformMatrix4fv(g_Unlit.modelToCameraMatrixUnif, 1, GL_FALSE,
 		glutLeaveMainLoop();
 		break;
 		
-	case 'i': g_fLightHeight += 2.f; break;
-	case 'k': g_fLightHeight -= 2.f; break;
-	case 'l': g_fLightRadius += 2.f; break;
-	case 'j': g_fLightRadius -= 2.f; break;
-	case 'I': g_fLightHeight += 0.5f; break;
-	case 'K': g_fLightHeight -= 0.5f; break;
-	case 'L': g_fLightRadius += 0.5f; break;
-	case 'J': g_fLightRadius -= 0.5f; break;
-
-	case 'b': g_time.keyLightTimer.TogglePause(); break;
+	case 'b': g_lights.TogglePause(); break;
 	case 't': g_bDrawCameraPos = !g_bDrawCameraPos; break;
 
 	case 'w': g_mousePole.OffsetTargetPos(Framework::MousePole::DIR_FORWARD, 5.0f); break;
 	case 'q': g_mousePole.OffsetTargetPos(Framework::MousePole::DIR_DOWN, 5.0f); break;
 	}
 
-	if(g_fLightRadius < 0.2f)
-		g_fLightRadius = 0.2f;
-
 	glutPostRedisplay();
 }
 

File Tut 12 Dynamic Range/data/DiffuseOnly.frag

 
 struct PerLight
 {
-	vec3 cameraSpaceLightPos;
+	vec4 cameraSpaceLightPos;
 	vec4 lightIntensity;
 };
 
+const int numberOfLights = 4;
+
 uniform Light
 {
 	vec4 ambientIntensity;
 	float lightAttenuation;
-	PerLight lights;
+	PerLight lights[numberOfLights];
 } Lgt;
 
 
 	float lightDistanceSqr = dot(lightDifference, lightDifference);
 	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
 	
-	return (1 / ( 1.0 + Lgt.lightAttenuation * sqrt(lightDistanceSqr)));
+	return (1 / ( 1.0 + Lgt.lightAttenuation * Lgt.lightAttenuation
+		* sqrt(lightDistanceSqr)));
 }
 
-void main()
+vec4 ComputeLighting(in PerLight lightData)
 {
-	vec3 lightDir = vec3(0.0);
-	float atten = CalcAttenuation(cameraSpacePosition,
-		Lgt.lights.cameraSpaceLightPos, lightDir);
-	vec4 attenIntensity = atten * Lgt.lights.lightIntensity;
+	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 = clamp(cosAngIncidence, 0, 1);
 	
-	outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +
-		(diffuseColor * Lgt.ambientIntensity);
+	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;
+}

File Tut 12 Dynamic Range/data/DiffuseSpecular.frag

 
 struct PerLight
 {
-	vec3 cameraSpaceLightPos;
+	vec4 cameraSpaceLightPos;
 	vec4 lightIntensity;
 };
 
+const int numberOfLights = 4;
+
 uniform Light
 {
 	vec4 ambientIntensity;
 	float lightAttenuation;
-	PerLight lights;
+	PerLight lights[numberOfLights];
 } Lgt;
 
 
 	float lightDistanceSqr = dot(lightDifference, lightDifference);
 	lightDirection = lightDifference * inversesqrt(lightDistanceSqr);
 	
-	return (1 / ( 1.0 + Lgt.lightAttenuation * sqrt(lightDistanceSqr)));
+	return (1 / ( 1.0 + Lgt.lightAttenuation * Lgt.lightAttenuation
+		* sqrt(lightDistanceSqr)));
 }
 
-void main()
+vec4 ComputeLighting(in PerLight lightData)
 {
 	vec3 lightDir;
-	float atten = CalcAttenuation(cameraSpacePosition,
-		Lgt.lights.cameraSpaceLightPos, lightDir);
-	vec4 attenIntensity = atten * Lgt.lights.lightIntensity;
+	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);
 	float gaussianTerm = exp(exponent);
 
 	gaussianTerm = cosAngIncidence != 0.0 ? gaussianTerm : 0.0;
+	
+	vec4 lighting = diffuseColor * lightIntensity * cosAngIncidence;
+	lighting += Mtl.specularColor * lightIntensity * gaussianTerm;
+	
+	return lighting;
+}
 
-	outputColor = (diffuseColor * attenIntensity * cosAngIncidence) +
-		(Mtl.specularColor * attenIntensity * gaussianTerm) +
-		(diffuseColor * Lgt.ambientIntensity);
+void main()
+{
+	vec4 accumLighting = diffuseColor * Lgt.ambientIntensity;
+	for(int light = 0; light < numberOfLights; light++)
+	{
+		accumLighting += ComputeLighting(Lgt.lights[light]);
+	}
+	
+	outputColor = accumLighting;
 }

File Tut 12 Dynamic Range/tutorials.lua

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

File framework/Interpolators.h

+
+#ifndef INTERPOLATORS_H
+#define INTERPOLATORS_H
+
+#include <math.h>
+#include <vector>
+
+namespace Framework
+{
+	template<typename ValueType>
+	class LinearInterpolator
+	{
+	public:
+		explicit LinearInterpolator(bool isLoop)
+			: m_isLoop(isLoop)
+			, m_numSegments(0)
+		{}
+
+		LinearInterpolator(bool isLoop, int iNumReserve)
+			: m_isLoop(isLoop)
+			, m_numSegments(0)
+		{
+			m_values.reserve(iNumReserve);
+		}
+
+		void AppendValue(const ValueType &data)
+		{
+			m_values.push_back(data);
+			m_numSegments = m_isLoop ? m_values.size() : (m_values.size() - 1);
+			if(m_values.size() < 2)
+				m_numSegments = 0;
+		}
+
+		ValueType Interpolate(float fAlpha) const
+		{
+			if(m_numSegments == 0)
+				return m_values[0];
+
+			fAlpha *= m_numSegments;
+
+			float intPart = 0.0f;
+			float sectionAlpha = modf(fAlpha, &intPart);
+
+			int iStartIx = (int)intPart;
+
+			int iNextIx = iStartIx + 1;
+			if(m_isLoop && (iNextIx == m_numSegments))
+			{
+				iNextIx = 0;
+			}
+
+			if((size_t)iNextIx > m_numSegments)
+				return m_values.back();
+
+
+			float invSecAlpha = 1.0f - sectionAlpha;
+
+			return m_values[iStartIx] * invSecAlpha + m_values[iNextIx] * sectionAlpha;
+		}
+
+	private:
+		std::vector<ValueType> m_values;
+		size_t m_numSegments;
+		bool m_isLoop;
+	};
+
+	template<typename ValueType, typename SplineBasis>
+	class CubicInterpolator
+	{
+	public:
+		CubicInterpolator(const SplineBasis &basis, bool isLoop)
+			: m_numSegments(0)
+			, m_basis(basis)
+			, m_isLoop(isLoop)
+		{}
+
+		CubicInterpolator(const SplineBasis &basis, bool isLoop, int iNumReserve)
+			: m_numSegments(0)
+			, m_basis(basis)-
+			, m_isLoop(isLoop)
+		{
+			m_values.reserve(iNumReserve);
+		}
+
+		void AppendValue(const ValueType &data)
+		{
+			m_values.push_back(data);
+
+			size_t numValues = m_values.size();
+			if(numValues < 4)
+				m_numSegments = 0;
+			else
+				m_numSegments = SplineBasis::CountSegments(numValues, m_isLoop);
+		}
+
+		ValueType Interpolate(float fAlpha) const
+		{
+			if(m_numSegments == 0)
+				return m_values[0];
+
+			fAlpha *= m_numSegments;
+
+			float intPart = 0.0f;
+			float sectionAlpha = modf(fAlpha, &intPart);
+
+			int iStartIx = (int)intPart;
+
+			m_basis.Interpolate(m_values, iStartIx, sectionAlpha);
+		}
+
+	private:
+		std::vector<ValueType> m_values;
+		size_t m_numSegments;
+		SplineBasis m_basis;
+		bool m_isLoop;
+	};
+}
+
+
+
+#endif //INTERPOLATORS_H

File framework/Timer.h

 		//Resets the timer, as though the user just created the object with the original parameters.
 		void Reset();
 
-		//Pauses/unpauses. Returns true if the timer is paused.
+		//Pauses/unpauses. Returns true if the timer is paused after the toggling.
 		bool TogglePause();
 
 		//Updates the time for the timer. Returns true if the timer has reached the end.