diff --git a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache
index dac6088bf451fbefa7a16ef579c7e6581539db88..97fdfa576eb3e3b4dbf0d86c5c766e77baae4511 100644
--- a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache
+++ b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/CXX.includecache
@@ -65,9 +65,9 @@ glm/gtc/quaternion.hpp
 -
 glm/gtx/quaternion.hpp
 -
-gl/gl.h
+GL/gl.h
 -
-gl/glu.h
+GL/glu.h
 -
 
 /home/thomas/Documents/Minimisation/apps/specular_estimation/src/objloader.cpp
diff --git a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o
index 8fdb5fd66b50683eaab1cb5b09a01b2498042308..7f98717753ddbe98d79c5a9148ab4d3f1790ee42 100644
Binary files a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o and b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o differ
diff --git a/apps/specular_estimation/src/Charuco.h b/apps/specular_estimation/src/Charuco.h
index 75d48e75bc2e9f3035c9510d698a7aeb76a29161..68aa00cec05da1ad20970ba5be6884f3a2c2c2f1 100644
--- a/apps/specular_estimation/src/Charuco.h
+++ b/apps/specular_estimation/src/Charuco.h
@@ -25,29 +25,37 @@ void charucoCalibration(int width, int height, cv::Ptr<cv::aruco::CharucoBoard>
 
 	std::vector< cv::Mat > charucoImages;
 	const std::string charucoPath = "/home/thomas/Documents/2017-12-04/charuco/";
-	loadCharucoImages(charucoImages, charucoPath, "charuco");
-
-	// Load a premade dictionary of ArUco markers
-	int dictionaryId = 0;
-	cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
-
-	// Create a ChArUco board
-	int xSquares = 11;
-	int ySquares = 9;
-	float squareSideLength = 0.04f;
-	float markerSideLength = 0.02f;
-	charucoBoard = cv::aruco::CharucoBoard::create(xSquares, ySquares, squareSideLength, markerSideLength, dictionary);
-
-	//charucoBoardImage = drawCharuco(charucoBoard, height, ((height * xSquares) / ySquares), false, false);
-
-	// Rotate ChArUco board
-	//cv::Mat tempImage = drawCharuco(charucoBoard, ((width * ySquares) / xSquares), width, false, false);
-	//cv::rotate(tempImage, charucoBoardImage, cv::ROTATE_90_COUNTERCLOCKWISE);
-
-	// Calibrate the camera using the ChArUco board images to obtain the camera matrix and distortion coefficients
-	calibrateCamera(xSquares, ySquares, squareSideLength, markerSideLength, dictionaryId, charucoImages, cameraMatrix, distortionCoefficients);
-	//calibrateCamera(xSquares, ySquares, squareSideLength, markerSideLength, dictionaryId, textureImages, cameraMatrix, distortionCoefficients);
-
+	
+	cameraMatrix           = cv::imread(charucoPath + "cameraMatrix.png",           CV_LOAD_IMAGE_COLOR);
+	distortionCoefficients = cv::imread(charucoPath + "distortionCoefficients.png", CV_LOAD_IMAGE_COLOR);
+	if (!cameraMatrix.data && !distortionCoefficients.data) {
+	
+		loadCharucoImages(charucoImages, charucoPath, "charuco");
+
+		// Load a premade dictionary of ArUco markers
+		int dictionaryId = 0;
+		cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::PREDEFINED_DICTIONARY_NAME(dictionaryId));
+
+		// Create a ChArUco board
+		int xSquares = 11;
+		int ySquares = 9;
+		float squareSideLength = 0.04f;
+		float markerSideLength = 0.02f;
+		charucoBoard = cv::aruco::CharucoBoard::create(xSquares, ySquares, squareSideLength, markerSideLength, dictionary);
+		
+		//charucoBoardImage = drawCharuco(charucoBoard, height, ((height * xSquares) / ySquares), false, false);
+
+		// Rotate ChArUco board
+		//cv::Mat tempImage = drawCharuco(charucoBoard, ((width * ySquares) / xSquares), width, false, false);
+		//cv::rotate(tempImage, charucoBoardImage, cv::ROTATE_90_COUNTERCLOCKWISE);
+
+		// Calibrate the camera using the ChArUco board images to obtain the camera matrix and distortion coefficients
+		calibrateCamera(xSquares, ySquares, squareSideLength, markerSideLength, dictionaryId, charucoImages, cameraMatrix, distortionCoefficients);
+		//calibrateCamera(xSquares, ySquares, squareSideLength, markerSideLength, dictionaryId, textureImages, cameraMatrix, distortionCoefficients);
+
+		cv::imwrite(charucoPath + "cameraMatrix.png", cameraMatrix);
+		cv::imwrite(charucoPath + "distortionCoefficients.png", distortionCoefficients);
+	}
 }
 
 void charucoAlignment(std::vector< cv::Mat > & charucoImages, std::vector< cv::Mat > textureImages, int numberOfLights, int width, int height, cv::Mat& rotationMatrix, cv::Mat& rotationVector, cv::Mat& perspectiveTransform, cv::Mat lightDirections, cv::Mat& lightDirectionsPerspective, std::vector< cv::Vec3d > & rvecs, std::vector< cv::Vec3d > & tvecs, cv::Ptr<cv::aruco::CharucoBoard> charucoBoard, cv::Mat charucoBoardImage, cv::Mat cameraMatrix, cv::Mat distortionCoefficients) {
diff --git a/apps/specular_estimation/src/OpenGL.h b/apps/specular_estimation/src/OpenGL.h
index 48bd920ab4e8253cb1d0d1a4e2c3a9836de3026f..2f6ac878f0393c4986a37b55a699e302eb489131 100644
--- a/apps/specular_estimation/src/OpenGL.h
+++ b/apps/specular_estimation/src/OpenGL.h
@@ -22,23 +22,23 @@
 #include <glm/gtc/quaternion.hpp>
 #include <glm/gtx/quaternion.hpp>
 
-/*#include <windows.h>	// Header File For Windows
-#include <gl\gl.h>		// Header File For The OpenGL32 Library
-#include <gl\glu.h>		// Header File For The GLu32 Library*/
+//#include <windows.h>	// Header File For Windows
+#include <GL/gl.h>		// Header File For The OpenGL32 Library
+#include <GL/glu.h>		// Header File For The GLu32 Library
 
-void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, float mouseSpeed, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, bool& shadowControl);
-void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, int& lightNumber, int numberOfLights);
+void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, float mouseSpeed, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, bool& shadowControl, float& SpecularIntensity, float& SpecularPower, bool& calculateResidual);
+void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, int& lightNumber, int numberOfLights, float& SpecularIntensity, float& SpecularPower, bool& calculateResidual);
 void createMesh(cv::Mat Z, cv::Mat normals, std::vector<glm::vec3> & out_vertices, std::vector<glm::vec2> & out_uvs, std::vector<glm::vec3> & out_normals, std::vector<unsigned int> & out_indices);
 GLuint loadMat(cv::Mat cv_texture);
-void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, std::vector< cv::Mat > textureImages, cv::Mat lightDirections, int width, int height, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, int& windowWidth, int& windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID);
-void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, GLuint programID, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint depthProgramID, GLuint quad_programID, GLuint FramebufferName, GLuint quad_vertexbuffer, GLuint VertexArrayID, int numberOfLights);
+void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, std::vector< cv::Mat > textureImages, cv::Mat lightDirections, int& windowWidth, int& windowHeight, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID, float& SpecularIntensity, float& SpecularPower);
+void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, GLuint programID, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint depthProgramID, GLuint quad_programID, GLuint FramebufferName, GLuint quad_vertexbuffer, GLuint VertexArrayID, int numberOfLights, float& SpecularIntensity, float& SpecularPower);
 void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::vec3 lightInvDir, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, glm::mat4 MVP, glm::mat4 ModelMatrix, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP);
 void renderShadows(GLuint FramebufferName, int shadowResolution, GLuint depthProgramID, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, GLuint depthMatrixID, GLuint vertexbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, glm::mat4 depthModelMatrix, glm::mat4 depthMVP);
 void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer);
 void computeResidual(int imageNumber, int windowHeight, int windowWidth, std::vector < cv::Mat > textureImages, cv::Mat& residual, double& sum);
 void computeResiduals(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, int& lightNumber, int numberOfLights);
 
-void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, std::vector< cv::Mat > textureImages, cv::Mat lightDirections, int width, int height, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, int& windowWidth, int& windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID) {
+void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture, std::vector< cv::Mat > textureImages, cv::Mat lightDirections, int& windowWidth, int& windowHeight, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, GLuint& programID, GLuint& MatrixID, GLuint& ModelMatrixID, GLuint& ViewMatrixID, GLuint& DepthBiasID, GLuint& lightInvDirID, GLuint& Texture, GLuint& TextureID, GLuint& depthTexture, GLuint& ShadowMapID, GLuint& vertexbuffer, GLuint& uvbuffer, GLuint& normalbuffer, GLuint& elementbuffer, std::vector<unsigned int> & indices, GLuint& depthProgramID, GLuint& quad_programID, GLuint& FramebufferName, GLuint& quad_vertexbuffer, GLuint& VertexArrayID, float& SpecularIntensity, float& SpecularPower) {
 	// Initialise the GLFW library first
 	if (!glfwInit()) {
 		std::cerr << "Failed to initialise GLFW.\n";
@@ -54,10 +54,6 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture,
 	glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Only needed for macOS
 	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Disable old OpenGL
 
-	// Set the window width and height to be 1600 and 900
-	windowWidth = width;
-	windowHeight = height;
-
 	// Set the shadow resolution to 4096x4096
 	int shadowResolution = 4096;
 
@@ -158,7 +154,7 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture,
 	// Render to Texture - specific code begins here
 	// ---------------------------------------------
 
-	// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
+	// The framebuffer, which regroups 0, 1 or more textures, and 0 or 1 depth buffers
 	FramebufferName = 0;
 	glGenFramebuffers(1, &FramebufferName);
 	glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);
@@ -211,6 +207,9 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture,
 	// Get a handle for the "myTextureSampler" uniform
 	TextureID = glGetUniformLocation(programID, "myTextureSampler");
 	//SpecularID = glGetUniformLocation(programID, "mySpecularSampler");
+	
+	//SpecularIntensity = glGetUniformLocation(programID, "specularIntensity");
+	//SpecularPower = glGetUniformLocation(programID, "specularPower");
 
 	// Get a handle for the "MVP" uniform
 	MatrixID = glGetUniformLocation(programID, "MVP");
@@ -239,7 +238,7 @@ void initialiseOpenGL(cv::Mat cv_depth, cv::Mat cv_normals, cv::Mat cv_texture,
 	float mouseSpeed = 0.005f;
 }
 
-void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, GLuint programID, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint depthProgramID, GLuint quad_programID, GLuint FramebufferName, GLuint quad_vertexbuffer, GLuint VertexArrayID, int numberOfLights) {
+void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, GLuint programID, GLuint MatrixID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint depthProgramID, GLuint quad_programID, GLuint FramebufferName, GLuint quad_vertexbuffer, GLuint VertexArrayID, int numberOfLights, float& SpecularIntensity, float& SpecularPower) {
 	
 	int lightNumber = 0;
 
@@ -259,9 +258,9 @@ void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int wind
 		// Compute the MVP matrix from keyboard and mouse input
 		glm::mat4 ModelMatrix = glm::mat4(1.0);
 		glm::mat4 MVP, ViewMatrix, depthBiasMVP, ProjectionMatrix;
-		bool perspectiveProjection, shadowControl;
-		//computeMatricesFromInputs(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, mouseSpeed, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection, shadowControl);
-		computeMatricesFromLights(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection = false, lightDirections, textureImages, lightNumber, numberOfLights);
+		bool perspectiveProjection, shadowControl, calculateResidual;
+		//computeMatricesFromInputs(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, mouseSpeed, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection, shadowControl, SpecularIntensity, SpecularPower, calculateResidual);
+		computeMatricesFromLights(windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, ProjectionMatrix, ViewMatrix, lightInvDir, depthProjectionMatrix, depthViewMatrix, perspectiveProjection = false, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensity, SpecularPower, calculateResidual);
 		MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
 
 		glm::mat4 biasMatrix(
@@ -275,11 +274,14 @@ void openGL(glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int wind
 
 		// Render the polygons
 		renderPolygons(windowWidth, windowHeight, programID, lightInvDir, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP);
-
-		// Compute the residual image and sum of differences
-		cv::Mat residual;
-		double sum;
-		computeResidual(lightNumber, windowHeight, windowWidth, textureImages, residual, sum);
+		
+		
+		if (calculateResidual) {
+			// Compute the residual image and sum of differences
+			cv::Mat residual;
+			double sum;
+			computeResidual(lightNumber, windowHeight, windowWidth, textureImages, residual, sum);
+		}
 
 		// Optionally render the shadowmap (for debug only)
 		//void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer);
@@ -400,9 +402,7 @@ void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::ve
 
 	// Use the shader
 	glUseProgram(programID);
-
 	
-
 	// Send the transformation to the currently bound shader, in the "MVP" uniform
 	glUniformMatrix4fv(MatrixID,      1, GL_FALSE, &MVP[0][0]);
 	glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
@@ -564,7 +564,9 @@ void computeResiduals(int windowWidth, int windowHeight, glm::vec3& position, fl
 	}
 }
 
-void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, int& lightNumber, int numberOfLights) {
+void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, cv::Mat lightDirections, std::vector< cv::Mat > textureImages, int& lightNumber, int numberOfLights, float& SpecularIntensity, float& SpecularPower, bool& calculateResidual) {
+	
+	calculateResidual = false;
 	
 	// Direction: Convert Spherical coordinates to Cartesian coordinates
 	glm::vec3 direction(
@@ -592,6 +594,7 @@ void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& pos
 				lightNumber = numberOfLights - 1;
 			}
 			lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 1), -lightDirections.at<float>(lightNumber, 0), lightDirections.at<float>(lightNumber, 2));
+			calculateResidual = true;
 		}
 	}
 	else if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) {
@@ -603,6 +606,20 @@ void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& pos
 				lightNumber = 0;
 			}
 			lightInvDir = glm::vec3(lightDirections.at<float>(lightNumber, 1), -lightDirections.at<float>(lightNumber, 0), lightDirections.at<float>(lightNumber, 2));
+			calculateResidual = true;
+		}
+	}
+	
+	if (glfwGetKey(window, GLFW_KEY_9) == GLFW_PRESS) {
+		if (glfwGetKey(window, GLFW_KEY_9) == GLFW_RELEASE) {
+			SpecularIntensity += 0.1f;
+			calculateResidual = true;
+		}
+	}
+	else if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS) {
+		if (glfwGetKey(window, GLFW_KEY_0) == GLFW_RELEASE) {
+			SpecularIntensity -= 0.1f;
+			calculateResidual = true;
 		}
 	}
 
@@ -610,9 +627,11 @@ void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& pos
 
 	if (glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
 		perspectiveProjection = true;
+		calculateResidual = true;
 	}
 	else if (glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
 		perspectiveProjection = false;
+		calculateResidual = true;
 	}
 
 	if (perspectiveProjection) // Projection matrix: 60° Field of View, 16:9 aspect ratio, display range: 0.1 units <-> 100 units
@@ -641,7 +660,9 @@ void computeMatricesFromLights(int windowWidth, int windowHeight, glm::vec3& pos
 	}*/
 }
 
-void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, float mouseSpeed, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, bool& shadowControl) {
+void computeMatricesFromInputs(int windowWidth, int windowHeight, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, float mouseSpeed, glm::mat4& ProjectionMatrix, glm::mat4& ViewMatrix, glm::vec3& lightInvDir, glm::mat4& depthProjectionMatrix, glm::mat4& depthViewMatrix, bool& perspectiveProjection, bool& shadowControl, float& SpecularIntensity, float& SpecularPower, bool& calculateResidual) {
+
+	calculateResidual = false;
 
 	// Set the base movement speed
 	float speed = 1.0f; // 1 unit per second
diff --git a/apps/specular_estimation/src/ShadowMapping.fragmentshader b/apps/specular_estimation/src/ShadowMapping.fragmentshader
index 4d01b5446abafe034fa8f681601fb5b64504faee..1e953174e43641ad461a65dc70fb4bccf42cd1c8 100644
--- a/apps/specular_estimation/src/ShadowMapping.fragmentshader
+++ b/apps/specular_estimation/src/ShadowMapping.fragmentshader
@@ -17,6 +17,8 @@ uniform sampler2D mySpecularSampler;
 uniform mat4 MV;
 uniform sampler2DShadow shadowMap;
 //uniform vec3 LightPosition_worldspace;
+//uniform float specularIntensity;
+//uniform float specularPower;
 
 vec2 poissonDisk[16] = vec2[]( 
    vec2( -0.94201624,  -0.39906216 ), 
@@ -55,11 +57,13 @@ void main(){
 	
 	// Material properties
 	float ambientPower  = 0.0f;
-	float specularPower = 0.0f;
+	//specularPower = 5.0f;
+	//specularIntensity = 0.5f;
 	vec3 MaterialDiffuseColor  = texture( myTextureSampler, UV ).rgb;
 	vec3 MaterialAmbientColor  = vec3(ambientPower,  ambientPower,  ambientPower) * MaterialDiffuseColor;
-	//vec3 MaterialSpecularColor = vec3(specularPower, specularPower, specularPower);
-	vec3 MaterialSpecularColor = texture( myTextureSampler, UV ).rgb;
+	
+	vec3 MaterialSpecularColor = vec3(0.5f, 0.5f, 0.5f);
+	//vec3 MaterialSpecularColor = texture( myTextureSampler, UV ).rgb;
 
 	// Distance to the light
 	//float distance = length( LightPosition_worldspace - Position_worldspace );
@@ -129,5 +133,5 @@ void main(){
 		// Diffuse: "colour" of the object
 		visibility * MaterialDiffuseColor  * LightColor * LightPower * cosTheta +
 		// Specular: reflective highlight, like a mirror
-		visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha, 5);
+		visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha, 5.0f);
 }
diff --git a/apps/specular_estimation/src/specular_estimation.cc b/apps/specular_estimation/src/specular_estimation.cc
index be1f60ca97999a89c0e77cdbb1aa13ebbb81b6f5..40187eb77abca2e517f0936feaaa1c4b06cc8c3f 100644
--- a/apps/specular_estimation/src/specular_estimation.cc
+++ b/apps/specular_estimation/src/specular_estimation.cc
@@ -124,20 +124,19 @@ int main(int argc, char** argv) {
 
 	
 
-	int windowWidth, windowHeight;
 	glm::vec3 position, lightInvDir;
 	glm::mat4 depthProjectionMatrix, depthViewMatrix;
-	float horizontalAngle, verticalAngle, FoV;
+	float horizontalAngle, verticalAngle, FoV, SpecularIntensity = 0.5f, SpecularPower = 5.0f;
 	GLuint programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID;
 	std::vector<unsigned int> indices;
 
-	initialiseOpenGL(heightMap, normalMap, texture, textureImages, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID);
-	//initialiseOpenGL(heightMap, normalMap, texture, textureImages, lightDirectionsPerspective, width, height, depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID);
-	//initialiseOpenGL(heightMap, normalMap, texture, charucoImages, lightDirectionsPerspective, width, height, depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID);
+	initialiseOpenGL(heightMap, normalMap, texture, textureImages, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensity, SpecularPower);
+	//initialiseOpenGL(heightMap, normalMap, texture, textureImages, lightDirectionsPerspective, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensity, SpecularPower);
+	//initialiseOpenGL(heightMap, normalMap, texture, charucoImages, lightDirectionsPerspective, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensity, SpecularPower);
 
-	openGL(depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights);
-	//openGL(depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirectionsPerspective, textureImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights);
-	//openGL(depthProjectionMatrix, depthViewMatrix, windowWidth, windowHeight, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirectionsPerspective, charucoImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights);
+	openGL(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights, SpecularIntensity, SpecularPower);
+	//openGL(depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirectionsPerspective, textureImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights, SpecularIntensity, SpecularPower);
+	//openGL(depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirectionsPerspective, charucoImages, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, numberOfLights, SpecularIntensity, SpecularPower);
 	
   return 0;
 }
diff --git a/bin/specular_estimation b/bin/specular_estimation
index 655deac80b3188a31c444e3a1e56a6db0efa6f1b..628c22db8175c5b704177a257def667372ce9469 100755
Binary files a/bin/specular_estimation and b/bin/specular_estimation differ