diff --git a/lab4/src/lab4.js b/lab4/src/lab4.js
index 87c4822e49a12a4a157f254e5bf3a36a0481c351..ac88cf40853f2962b85b47939a4b46190e136b28 100644
--- a/lab4/src/lab4.js
+++ b/lab4/src/lab4.js
@@ -23,21 +23,21 @@ const VSHADER_SOURCE =
     // TODO: Implement your vertex shader code here
     'attribute vec3 a_Position;\n' +
     'attribute vec3 a_Normal;\n' +
-    'attribute vec4 a_Color_tmp;\n' +
+    //'attribute vec4 a_Color_tmp;\n' +
 
     'uniform mat4 u_View;\n' +
     'uniform mat4 u_Projection;\n' +
     'uniform mat4 u_Model;\n' +
     'uniform mat4 u_MvpMatrixFromLight;\n' + 
 
-    'varying vec4 v_Color;\n' +
+    //'varying vec4 v_Color;\n' +
     'varying vec3 v_Vertex;\n' +
     'varying vec3 v_Normal;\n' +
     'varying vec4 v_PositionFromLight;\n' +
 
     'void main() {\n' +
   
-    '   v_Color = a_Color_tmp;\n' +
+    //'   v_Color = u_Color;\n' +
 
     '   v_Vertex = vec3(u_View * u_Model * vec4(a_Position, 1.0));\n' +
     '   v_Normal = vec3(u_View * u_Model * vec4(a_Normal, 0.0));\n' +
@@ -59,9 +59,11 @@ const FSHADER_SOURCE =
     'uniform vec3 u_Light_position;\n' +
     'uniform float u_Directionnel;\n' +
     'uniform sampler2D u_ShadowMap;\n' +
+    'uniform float u_Clicked;\n' +
+    'uniform vec4 u_Color;\n' +
 
     // TODO: Implement your fragment shader code here
-    'varying vec4 v_Color;\n' +
+    //'varying vec4 v_Color;\n' +
     'varying vec3 v_Vertex;\n' +
     'varying vec3 v_Normal;\n' +
     'varying vec4 v_PositionFromLight;\n' +
@@ -80,70 +82,75 @@ const FSHADER_SOURCE =
     '    vec3 color;\n' +
     '    float d;\n' +
     '    float attenuation;\n' +
+    '    vec4 color_tmp;\n' +
 
     '	 vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;\n' +
     ' 	 vec4 rgbaDepth = texture2D(u_ShadowMap, shadowCoord.xy);\n' +
 	' 	 float depth = rgbaDepth.r;\n' + // Retrieve the z-value from R
 	'	 float visibility = (shadowCoord.z > depth + 0.005) ? 0.6 : 1.0;\n' +
 
+    '    if(u_Clicked > 0.5) {\n' +
+    '        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
+    '    } else {\n' +
 
-    '    ambient_color = vec3(0.0, 0.0, 0.0);\n' +
-    '    light_color = vec3(1.0, 1.0, 1.0);\n' +
-    '    shininess = 10.0;\n' +
+    '        ambient_color = vec3(0.0, 0.0, 0.0);\n' +
+    '        light_color = vec3(1.0, 1.0, 1.0);\n' +
+    '        shininess = 10.0;\n' +
 
     // Calculate the ambient color as a percentage of the surface color
-    '    ambient_color = ambient_color * vec3(v_Color);\n' + 
+    '        ambient_color = ambient_color * vec3(u_Color);\n' + 
 
     // Calculate a vector from the fragment location to the light source
-    '    if(u_Directionnel > 0.5) {\n' +
-    '        to_light = normalize(u_Light_position + v_Vertex);\n' +
-    '    } else {\n' +
-    '        to_light = normalize(u_Light_position - v_Vertex);\n' +
-    '    }\n' +
+    '        if(u_Directionnel > 0.5) {\n' +
+    '            to_light = normalize(u_Light_position + v_Vertex);\n' +
+    '        } else {\n' +
+    '            to_light = normalize(u_Light_position - v_Vertex);\n' +
+    '        }\n' +
 
     // The vertex's normal vector is being interpolated across the primitive
     // which can make it un-normalized. So normalize the vertex's normal vector.
-    '    vertex_normal = normalize(v_Normal);\n' +
+    '        vertex_normal = normalize(v_Normal);\n' +
 
     // Calculate the cosine of the angle between the vertex's normal vector
     // and the vector going to the light.
-    '    cos_angle = dot(vertex_normal, to_light);\n' + 
-    '    cos_angle = clamp(cos_angle, 0.0, 1.0);\n' +
+    '        cos_angle = dot(vertex_normal, to_light);\n' + 
+    '        cos_angle = clamp(cos_angle, 0.0, 1.0);\n' +
 
     // Scale the color of this fragment
-    '    diffuse_color = vec3(v_Color) * cos_angle; \n' +
+    '        diffuse_color = vec3(u_Color) * cos_angle; \n' +
 
     // Calculate the reflection vector
-    '    reflection = 2.0 * dot(vertex_normal, to_light) * vertex_normal - to_light;\n' +
+    '        reflection = 2.0 * dot(vertex_normal, to_light) * vertex_normal - to_light;\n' +
 
     // Calculate a vector from fragment location to the camera.
     // The camera is at the origin, so negating the vertex location gives the vector
-    '    to_camera = -1.0 * v_Vertex;\n' +
+    '        to_camera = -1.0 * v_Vertex;\n' +
 
     // Calculate the cosine of the angle between the reflection vector
     // and the vector going to the camera.
-    '    reflection = normalize(reflection);\n' +
-    '    to_camera = normalize(to_camera);\n' +
-    '    cos_angle = dot(reflection, to_camera);\n' +
-    '    cos_angle = clamp(cos_angle, 0.0, 1.0);\n' +
-    '    cos_angle = pow(cos_angle, shininess);\n' +
+    '        reflection = normalize(reflection);\n' +
+    '        to_camera = normalize(to_camera);\n' +
+    '        cos_angle = dot(reflection, to_camera);\n' +
+    '        cos_angle = clamp(cos_angle, 0.0, 1.0);\n' +
+    '        cos_angle = pow(cos_angle, shininess);\n' +
 
     // The specular color is from the light source, not the object
-    '    if(cos_angle > 0.0) {\n' +
-    '        specular_color = light_color * cos_angle;\n' +
-    '        diffuse_color = diffuse_color * (1.0 - cos_angle);\n' +
-    '    } else {\n' +
-    '        specular_color = vec3(0.0, 0.0, 0.0);\n' +
-    '    }\n' +
+    '        if(cos_angle > 0.0) {\n' +
+    '            specular_color = light_color * cos_angle;\n' +
+    '            diffuse_color = diffuse_color * (1.0 - cos_angle);\n' +
+    '        } else {\n' +
+    '            specular_color = vec3(0.0, 0.0, 0.0);\n' +
+    '        }\n' +
 
     //Atténuation
-    '    to_light = u_Light_position - v_Vertex;\n' +
-    '    d = length(to_light);\n' +
-    '    attenuation = clamp(10.0 / d, 0.0, 1.0);\n' +
+    '        to_light = u_Light_position - v_Vertex;\n' +
+    '        d = length(to_light);\n' +
+    '        attenuation = clamp(10.0 / d, 0.0, 1.0);\n' +
 
-    '    color = attenuation * (ambient_color + diffuse_color + specular_color);\n' +
-    //'    color = (ambient_color + diffuse_color + specular_color);\n' +
-    ' 	 gl_FragColor = vec4(color.rgb * visibility, v_Color.a);\n' +
+    '        color = attenuation * (ambient_color + diffuse_color + specular_color);\n' +
+    //'      color = attenuation * (ambient_color + u_Color.rgb);\n' +
+    ' 	     gl_FragColor = vec4(color.rgb * visibility, u_Color.a);\n' +
+    '    }\n' +
     '}\n' +
     '\n';
 
@@ -246,13 +253,13 @@ const vertices = new Float32Array([
 
 // This is the model
 const verticesSurface = new Float32Array([
-	100, 	-4/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
-	100, 	-4/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
-	-100, 	-4/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
+	100, 	-6/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
+	100, 	-6/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
+	-100, 	-6/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
 
-	100, 	-4/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
-	-100, 	-4/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
-	-100, 	-4/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,    
+	100, 	-6/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
+	-100, 	-6/7, 		100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,
+	-100, 	-6/7, 		-100, 		1.0, 1.0, 1.0, 1.0,        0.0,                1.0,          0.0,    
 ]);
 
 var OFFSCREEN_WIDTH = 2048, OFFSCREEN_HEIGHT = 2048;
@@ -295,15 +302,16 @@ function drawShadowSurface(gl, program, surface, viewMatrix, projectionMatrix, m
 }
 
 
-function drawFrustum(gl, program, frustum, viewMatrix, projectionMatrix, modelMatrix, light, shadow) {
+function drawFrustum(gl, program, frustum, viewMatrix, projectionMatrix, modelMatrix, light, shadow, clicked, color) {
 	gl.useProgram(program);
     gl.uniform1i(program.u_ShadowMap, 0);
     
 	initAttributeVariable(gl, program.a_Position, frustum.buffer, 3, 10*4, 0);
 	initAttributeVariable(gl, program.a_Color, frustum.buffer, 4, 10*4, 3*4);
     initAttributeVariable(gl, program.a_Normal, frustum.buffer, 3, 10*4, 7*4);
-
     
+    // Color
+    gl.uniform4fv(program.u_Color, color);
 
     // Light
     gl.uniform3fv(program.u_Light_position, light.position.elements);
@@ -314,7 +322,8 @@ function drawFrustum(gl, program, frustum, viewMatrix, projectionMatrix, modelMa
     gl.uniformMatrix4fv(program.u_Projection, false, projectionMatrix.elements);
     gl.uniformMatrix4fv(program.u_Model, false, modelMatrix.elements);
     gl.uniformMatrix4fv(program.u_MvpMatrixFromLight, false, shadow.mvpMatrixFromLight_f.elements);
-   
+    
+    gl.uniform1f(program.u_Clicked, clicked);
 
 	// Draw the rectangle
 	gl.drawArrays(gl.TRIANGLES, 0, frustum.numberIndices);
@@ -322,13 +331,16 @@ function drawFrustum(gl, program, frustum, viewMatrix, projectionMatrix, modelMa
 }
 
 
-function drawSurface(gl, program, surface, viewMatrix, projectionMatrix, modelMatrix, light, shadow) {
+function drawSurface(gl, program, surface, viewMatrix, projectionMatrix, modelMatrix, light, shadow, color) {
 	gl.useProgram(program);
     gl.uniform1i(program.u_ShadowMap, 0);
 
 	initAttributeVariable(gl, program.a_Position, surface.buffer, 3,  10*4, 0);
 	initAttributeVariable(gl, program.a_Color, surface.buffer, 4, 10*4, 3*4);
     initAttributeVariable(gl, program.a_Normal, surface.buffer, 3, 10*4, 7*4);
+    
+    // Color
+    gl.uniform4fv(program.u_Color, color);
 
 	// Pass the rotation matrix to the vertex shader
 	gl.uniformMatrix4fv(program.u_View, false, viewMatrix.elements);
@@ -340,6 +352,8 @@ function drawSurface(gl, program, surface, viewMatrix, projectionMatrix, modelMa
     gl.uniform3fv(program.u_Light_position, light.position.elements);
     gl.uniform1f(program.u_Directionnel, light.directionnel);
 
+    gl.uniform1f(program.u_Clicked, 0);
+
 	// Draw the rectangle
 	gl.drawArrays(gl.TRIANGLES, 0, surface.numberIndices);
 
@@ -451,6 +465,44 @@ function initFramebufferObject(gl) {
   	return framebuffer;
 }
 
+function drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow) {
+    gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);               // Change the drawing destination to FBO
+
+    gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT); // Set view port for FBO
+
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO
+
+    // Draw the triangle and the plane (for generating a shadow map)
+    drawShadowFrustum(gl, shadowProgram, frustum.vertex, frustum.viewMatrix, projectionMatrix, frustum.modelMatrix, shadow);
+    drawShadowSurface(gl, shadowProgram, surface.vertex, surface.viewMatrix, projectionMatrix, surface.modelMatrix, shadow);
+
+
+    gl.bindFramebuffer(gl.FRAMEBUFFER, null);               // Change the drawing destination to color buffer
+
+    gl.viewport(0, 0, canvas.width, canvas.height);
+
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    // Clear color and depth buffer
+
+    drawFrustum(gl, program, frustum.vertex, frustum.viewMatrix, projectionMatrix, frustum.modelMatrix, light, shadow, 0, frustum.color);
+    drawSurface(gl, program, surface.vertex, surface.viewMatrix, projectionMatrix, surface.modelMatrix, light, shadow, surface.color);
+}
+
+// must call drawScene after its usage
+function check(x, y, gl, fbo, program, frustum, projectionMatrix, light, shadow) { 
+    let picked = false;
+
+    drawFrustum(gl, program, frustum.vertex, frustum.viewMatrix, projectionMatrix, frustum.modelMatrix, light, shadow, 1, [1.0, 0.0, 0.0, 1.0]);
+
+    // Read pixel at the clicked position
+    let pixels = new Uint8Array(4); // Array for storing the pixel value y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
+
+    if (pixels[0] == 255 && pixels[1] == 0 && pixels[2] == 0 && pixels[3] == 255) // The mouse in on frustume
+        picked = true;
+
+    return picked;
+}
+
 function main() {
     // Retrieve <canvas> element
     const canvas = document.getElementById('my-canvas');
@@ -487,11 +539,11 @@ function main() {
     }
 
     //Colors
-    program.a_Color = gl.getAttribLocation(program, 'a_Color_tmp');
-    if (program.a_Color < 0) {
-        console.log('Failed to get the storage location of a_Color_tmp');
-        return -1;
-    }
+    // program.a_Color = gl.getAttribLocation(program, 'a_Color_tmp');
+    // if (program.a_Color < 0) {
+    //     console.log('Failed to get the storage location of a_Color_tmp');
+    //     return -1;
+    // }
 
     // Get storage location of u_View
   	program.u_View = gl.getUniformLocation(program, 'u_View');
@@ -543,6 +595,18 @@ function main() {
     	return;
   	}
 
+    program.u_Clicked = gl.getUniformLocation(program, 'u_Clicked');
+    if (program.u_Clicked < 0) {
+        console.log('Failed to get the storage location of attribute or uniform variable from u_ShadowMap'); 
+        return;
+    }
+
+    program.u_Color = gl.getUniformLocation(program, 'u_Color');
+    if (program.u_Color < 0) {
+        console.log('Failed to get the storage location of attribute or uniform variable from u_ShadowMap'); 
+        return;
+    }
+
     // Initialize framebuffer object (FBO)  
 	var fbo = initFramebufferObject(gl);
 	if (!fbo) {
@@ -557,37 +621,37 @@ function main() {
     gl.clearColor(0, 0, 0, 1);
     gl.enable(gl.DEPTH_TEST);
 
+    let frustum = new Object();
+    let surface = new Object();
 
     // Write the positions of vertices to a vertex shader
-    var frustum = initVertexBuffers(gl, program, vertices);
+    frustum.vertex = initVertexBuffers(gl, program, vertices);
 
     // Write the positions of vertices to a vertex shader
-    var surface = initVertexBuffers(gl, program, verticesSurface);
-
-
-
-    // Clear <canvas>
-    //gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+    surface.vertex = initVertexBuffers(gl, program, verticesSurface);
 
   	// Model matrix
- 	let viewMatrix_Frustum = new Matrix4();
-  	// Model matrix
-  	let viewMatrix_Surface = new Matrix4();
+ 	frustum.viewMatrix = new Matrix4();
+  	surface.viewMatrix = new Matrix4();
+
     let projectionMatrix = new Matrix4();
     
-    let modelMatrix_Frustum = new Matrix4();
-    let modelMatrix_Surface = new Matrix4();
+    frustum.modelMatrix = new Matrix4();
+    surface.modelMatrix = new Matrix4();
 
     // Light
     let light = new Object();
+    light.init = [0.0, 1.0, -2.0];
     light.position = new Vector3([0.0, 1.0, -2.0]);
     light.directionnel = 0.0;
 
   	// Set the rotation matrix
     projectionMatrix.setPerspective(40, 1, 0.1, 10);
     // 1, 0, -3
- 	viewMatrix_Frustum.setLookAt(1, 2, -3, 0, 0, 0, 0, 1, 0);
- 	viewMatrix_Surface.setLookAt(1, 2, -3, 0, 0, 0, 0, 1, 0);
+    let initCamera = [1, 2, -3];
+
+ 	frustum.viewMatrix.setLookAt(initCamera[0], initCamera[1], initCamera[2], 0, 0, 0, 0, 1, 0);
+ 	surface.viewMatrix.setLookAt(initCamera[0], initCamera[1], initCamera[2], 0, 0, 0, 0, 1, 0);
 
     let shadow = new Object();
     shadow.viewProjMatrixFromLight = new Matrix4();
@@ -598,47 +662,47 @@ function main() {
     shadow.mvpMatrixFromLight_f = new Matrix4();
     shadow.mvpMatrixFromLight_s = new Matrix4();
 
-	gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);               // Change the drawing destination to FBO
-
-    gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT); // Set view port for FBO
-
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO
-
-    // Draw the triangle and the plane (for generating a shadow map)
-    drawShadowFrustum(gl, shadowProgram, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, shadow);
-
-    drawShadowSurface(gl, shadowProgram, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, shadow);
-
+    frustum.color = [1.0, 0.0, 0.0, 1.0];
+    surface.color = [1.0, 1.0, 1.0, 1.0];
 
-    gl.bindFramebuffer(gl.FRAMEBUFFER, null);               // Change the drawing destination to color buffer
-
-    gl.viewport(0, 0, canvas.width, canvas.height);
-
-    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    // Clear color and depth buffer
-
-    drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light, shadow);
-
-  	drawSurface(gl, program, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light, shadow);
+    let clicked = 0;
 
+    drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
 
   	var onCanvas = false;
+    
     let newX;
     let newY;
     let newZ;
     let position_x = document.getElementById("position-x");
     let position_y = document.getElementById("position-y");
-    position_x.value = 0.0;
-    position_y.value = 0.0;
-
-	canvas.addEventListener("mousedown", function(e) {
-		onCanvas = true;
+    position_x.value = light.init[0];
+    position_y.value = light.init[1];
+
+	canvas.addEventListener("mousedown", function(event) {
+        let x = event.clientX, y = event.clientY;
+        let rect = event.target.getBoundingClientRect();
+        if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom) {
+            // If pressed position is inside <canvas>, check if it is above object
+            let x_in_canvas = x - rect.left, y_in_canvas = rect.bottom - y;
+            let picked = check(x_in_canvas, y_in_canvas, gl, fbo, program, frustum, projectionMatrix, light, shadow)
+            drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
+            if(picked) {
+                //change color
+                frustum.color = frustum.color[0] == 1.0 ? [0.0, 0.0, 1.0, 1.0] : [1.0, 0.0, 0.0, 1.0];
+                drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
+            } else {
+                onCanvas = true; // si c'est pas un click sur le frustum on effectue une rotation de la camera normal
+            }
+        }
 	});
 
 	canvas.addEventListener("mouseup", function(e) {
 		onCanvas = false;
 	});
 
-	canvas.addEventListener("mousemove", function(e) {
+	canvas.addEventListener("mousemove", function(event) {
+
 		if(onCanvas) {
 			bounds = canvas.getBoundingClientRect();
 	       	let x = (event.clientX - bounds.left - canvas.clientLeft)/canvas.width;
@@ -651,32 +715,10 @@ function main() {
     	    gl.enable(gl.DEPTH_TEST);
 
     	    // Set the rotation matrix
- 			viewMatrix_Frustum.setLookAt(newX, newY, newZ, 0, 0, 0, 0, 1, 0);
- 			viewMatrix_Surface.setLookAt(newX, newY, newZ, 0, 0, 0, 0, 1, 0);
-
-    		// Clear <canvas>
-    		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-
-    		
-
-    		gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);               // Change the drawing destination to FBO
-    		gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT); // Set view port for FBO
-    		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO
-
-    		// Draw the triangle and the plane (for generating a shadow map)
-    		drawShadowFrustum(gl, shadowProgram, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, shadow);
-    		drawShadowSurface(gl, shadowProgram, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, shadow);
-
-    		gl.bindFramebuffer(gl.FRAMEBUFFER, null);               // Change the drawing destination to color buffer
-    		gl.viewport(0, 0, canvas.width, canvas.height);
-
-            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO
-
-
-            drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light, shadow);
-
-  			drawSurface(gl, program, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light, shadow);
+ 			frustum.viewMatrix.setLookAt(newX, newY, newZ, 0, 0, 0, 0, 1, 0);
+ 			surface.viewMatrix.setLookAt(newX, newY, newZ, 0, 0, 0, 0, 1, 0);
 
+            drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
 		}
 	});
 
@@ -684,43 +726,43 @@ function main() {
         switch(e.key) {
             case "ArrowUp":
                 let up = light.position.elements[1] + 0.1;
-                if(up <= 1) {
+                if(up <= 1 + light.init[1]) {
                     position_y.value = up.toFixed(2);
                     light.position.elements[1] = up;
+                    shadow.viewProjMatrixFromLight.setPerspective(70, OFFSCREEN_WIDTH/OFFSCREEN_HEIGHT, 1.0, 100.0);
+                    shadow.viewProjMatrixFromLight.lookAt(light.position.elements[0], light.position.elements[1], light.position.elements[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
                 }
-                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-                drawSurface(gl, programSurface, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light);
-                drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light);
+                drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
                 break;
             case "ArrowDown":
                 let down = light.position.elements[1] - 0.1;
-                if(down >= -1) {
+                if(down >= - 1 + light.init[1]) {
                     position_y.value = down.toFixed(2);
                     light.position.elements[1] = down;
+                    shadow.viewProjMatrixFromLight.setPerspective(70, OFFSCREEN_WIDTH/OFFSCREEN_HEIGHT, 1.0, 100.0);
+                    shadow.viewProjMatrixFromLight.lookAt(light.position.elements[0], light.position.elements[1], light.position.elements[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
                 }
-                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-                drawSurface(gl, programSurface, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light);
-                drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light);
+                drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
                 break;
             case "ArrowRight":
                 let right = light.position.elements[0] + 0.1;
-                if(right <= 1) {
+                if(right <= 1 + light.init[0]) {
                     position_x.value = right.toFixed(2);
                     light.position.elements[0] = right;
+                    shadow.viewProjMatrixFromLight.setPerspective(70, OFFSCREEN_WIDTH/OFFSCREEN_HEIGHT, 1.0, 100.0);
+                    shadow.viewProjMatrixFromLight.lookAt(light.position.elements[0], light.position.elements[1], light.position.elements[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
                 }
-                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-                drawSurface(gl, programSurface, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light);
-                drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light);
+                drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
                 break;
             case "ArrowLeft":
                 let left = light.position.elements[0] - 0.1;
-                if(left >= -1) {
+                if(left >= -1 + light.init[0]) {
                     position_x.value = left.toFixed(2);
                     light.position.elements[0] = left;
+                    shadow.viewProjMatrixFromLight.setPerspective(70, OFFSCREEN_WIDTH/OFFSCREEN_HEIGHT, 1.0, 100.0);
+                    shadow.viewProjMatrixFromLight.lookAt(light.position.elements[0], light.position.elements[1], light.position.elements[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
                 }
-                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
-                drawSurface(gl, programSurface, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light);
-                drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light);
+                drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
                 break;
             default:
         }
@@ -730,30 +772,8 @@ function main() {
     for(let i = 0; i < directionnels_radio.length; i++) {
         directionnels_radio[i].addEventListener("click", function() {
             light.directionnel =  this.value;
-            gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);               // Change the drawing destination to FBO
-
-            gl.viewport(0, 0, OFFSCREEN_HEIGHT, OFFSCREEN_HEIGHT); // Set view port for FBO
-
-            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);   // Clear FBO
-
-            // Draw the triangle and the plane (for generating a shadow map)
-            drawShadowFrustum(gl, shadowProgram, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, shadow);
-
-            drawShadowSurface(gl, shadowProgram, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, shadow);
-
-
-            gl.bindFramebuffer(gl.FRAMEBUFFER, null);               // Change the drawing destination to color buffer
-
-            gl.viewport(0, 0, canvas.width, canvas.height);
-
-            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    // Clear color and depth buffer
-
-
-
-            drawSurface(gl, program, surface, viewMatrix_Surface, projectionMatrix, modelMatrix_Surface, light, shadow);
-
-            drawFrustum(gl, program, frustum, viewMatrix_Frustum, projectionMatrix, modelMatrix_Frustum, light, shadow);
 
+            drawScene(gl, canvas, fbo, program, shadowProgram, frustum, surface, projectionMatrix, light, shadow)
         });
     }
 }