diff --git a/Final_Project/final_project.css b/Final_Project/final_project.css
index 0cf3d361fd844e388b5fb1a6c14829b0f9c59e04..e34e41ff6d1580503f929cb8aa34862bf42d1d52 100644
--- a/Final_Project/final_project.css
+++ b/Final_Project/final_project.css
@@ -6,7 +6,6 @@ body {
   background: #ebf9ff
 }
 
-
 .layout-td {
     padding: 20px;
     /* background: pink; */
@@ -92,10 +91,19 @@ body {
   background-color: #9cd5fc;
 }
 
-.code-box {
-  width: 300px;
+#code-box {
+  visibility: hidden;
+  width: 450px;
+  height: 600px;
   background: #daf1ff;
   border: 1px solid #4f98c2;
   margin: 5px;
   padding: 10px;
+  overflow:scroll;
+}
+
+#code-content {
+  font-size: 15px;
+  word-wrap: break-word;
+  white-space: pre-wrap;
 }
\ No newline at end of file
diff --git a/Final_Project/final_project.html b/Final_Project/final_project.html
index 8904e3b868ffc1dc123434fe1141bb24af80a5b6..0c0a78865a6976fbb3ebeef603856154ae183fe0 100644
--- a/Final_Project/final_project.html
+++ b/Final_Project/final_project.html
@@ -13,18 +13,24 @@
 </head>
 
 <body onload="main()">
-    <H2> WebGL - After-images of rotating Cube </H2>
-    <p style="width:700px">
+    <H1> WebGL - After-images of rotating Cube </H1>
+    <p style="width:800px">
 		This demo shows the after-images when the 3D cube rotates.
 		Each after-image has a location coordinate where the cube was at previous frames.
 		The older after-image, the fainter it is, and you can control the number of after-images.
 		The after-image is saved every frame. If you change the frequency of after-images, you can set to display the after-image every n frames.
 	</p>
+	<br><div>
+			<h2>About After-image</h2>
+			<p style="width:800px">
+				In OpenGL, it 'draw' every frame. So in order to display the after-images, the location coordinate of the cube at that time should be stored every frame. In this demo, the set number of after-image(saved as the cube moves) is set number * frequency and the rest is deleted for saving memory. And after drawing the cube, it 'draw' after-image more and more transparent  from the most recent saved.
+			</p>
+		</div>
 	<table>
 		<tr>
 			<tr>
 				<td class="layout-td">
-					<canvas id="helloapicanvas" style="border: none;" width="500" height="500"></canvas><br><br>
+					<canvas id="helloapicanvas" style="border: none;margin-top: 50px" width="500" height="500"></canvas><br><br>
 					<table border=2> 
 						<tr > 
 						<td id="matrix0"> 	<td id="matrix4">  	<td id="matrix8">  	<td id="matrix12"> 
@@ -38,14 +44,14 @@
 
 				</td>
 				<td class="layout-td">
+						<h3>Controls</h3>
 						<div class="tab">
 							<button class="tablinks" id="clickedBtn" onclick="openControls(event, 'Translation')">Translation</button>
 							<button class="tablinks" onclick="openControls(event, 'Rotation')">Rotation</button>
 							<button class="tablinks" onclick="openControls(event, 'After-image')">After-image</button>
 						</div>
 
-						<div id="Translation" class="tabcontent">
-							<h3>Translation</h3>
+						<div id="Translation" class="tabcontent"><br>
 							<button class="cont_btn" onclick="trXinc('+')">X + 0.1</button>
 							<button class="cont_btn" onclick="trYinc('+')">Y + 0.1</button>
 							<button class="cont_btn" onclick="trZinc('+')">Z + 0.1</button>
@@ -59,8 +65,7 @@
 							<p id="webTrZ">Control Z of the Cube</p>
 						</div>
 						  
-						<div id="Rotation" class="tabcontent">
-							<h3>Rotation</h3>
+						<div id="Rotation" class="tabcontent"><br>
 							<button class="cont_btn" onclick="animRotate('+')">Animation Rotate + 0.01</button><br>
 							<button class="cont_btn" onclick="animRotate('-')">Animation Rotate - 0.01</button>
 							<br>
@@ -74,7 +79,6 @@
 						</div>
 						
 						<div id="After-image" class="tabcontent">
-							<h3>After-image</h3>
 							<p id="val_traceNum">The Number of After-image: 5</p>
 							<div class="slidecontainer">
 								<input type="range" class="slider" min="1" max="10" value="5" class="slider" id="traceNum" onchange="changeTraceNum(this.value)">
@@ -93,26 +97,19 @@
 
 				</td>
 				<td class="layout-td">
-					<h3>major code</h3>
-					<button class="cont_btn2" onclick="changeTraceColor('color')">Original</button>
-					<button class="cont_btn2" onclick="changeTraceColor('white')">White</button>
-					<button class="cont_btn2" onclick="changeTraceColor('gray')">Gray</button>
-					<div class="code-box">
-						<p id="code-content">
-							This is space for major code.
-						</p>
-					</div>
-					<div class="code-box">
-						<h4>About After-image</h4>
-						<p>
-							In OpenGL, it 'draw' every frame. So in order to display the after-images, the location coordinate of the cube at that time should be stored every frame. In this demo, the set number of after-image(saved as the cube moves) is set number * frequency and the rest is deleted for saving memory. And after drawing the cube, it 'draw' after-image more and more transparent  from the most recent saved.
-						</p>
+					<h3>JavaScript code</h3>
+					<button class="cont_btn2" onclick="showCode('rendering')">Rendering</button>
+					<button class="cont_btn2" onclick="showCode('control')">Controls</button>
+					<button class="cont_btn2" onclick="showCode('shader')">Shader</button>
+					<div id="code-box">
+						<pre id="code-content">
+						</pre>
 					</div>
 				</td>
 			</tr>
 		</tr>
 	</table>
-	
+
     <p> (CC-NC-BY) 2019 JungYeun Won </p>
 </body>
 
diff --git a/Final_Project/final_project.js b/Final_Project/final_project.js
index 6a11f9fa33ec78182a605b363fb987fd75f739a5..bc7a00557a2072d7cb0b115ba2bd74065a3fa324 100644
--- a/Final_Project/final_project.js
+++ b/Final_Project/final_project.js
@@ -16,7 +16,6 @@ function testGLError(functionLastCalled) {
 }
 
 function initialiseGL(canvas) {
-    document.getElementById("clickedBtn").click();
 
     try {
  // Try to grab the standard context. If it fails, fallback to experimental
@@ -241,7 +240,7 @@ transX = 0.0; transY = 0.0; transZ = 0.0;
 frames = 1;
 var rotAxis = [1,0,1];
 
-function animRotate(sign)
+function animRotate(sign)   //  increase or decrease rotation speed
 {
     if (sign=='+')
         animRotValue += 0.01;
@@ -251,12 +250,12 @@ function animRotate(sign)
     document.getElementById("animRot").innerHTML = "Rotation speed: "+ animRotValue.toFixed(4);
 }
 
-function animPause(){
+function animPause(){   // pause the rotating cube
     animRotValue = 0.0;
     document.getElementById("animRot").innerHTML = "Rotation speed: "+ animRotValue.toFixed(4);
 }
 
-function changeRotAxis(axis){
+function changeRotAxis(axis){   // change rotating direction
     switch(axis){
         case 'X':
             if (rotAxis[0]==1)
@@ -328,13 +327,14 @@ function trZinc(sign) // translate Z increase or decrease
 	    document.getElementById("webTrZ").innerHTML = "Translation Z : " + transZ.toFixed(4);
 }
 
+// About Trace(After-image)
 var trace = [];
 var traceNum = 5;
 var traceFreq = 5;
 var traceTotalNum = traceNum * traceFreq;
 var trace_alpha = 0.5/traceNum;
-var slider_traceNum = document.getElementById("traceNum");
 var traceColor = "color";
+var slider_traceNum = document.getElementById("traceNum");
 
 function addTrace(mat){
     if(trace.length>=traceTotalNum){
@@ -361,14 +361,12 @@ function changeTraceColor(type){
 
 function renderScene() {
 
-    // console.log("Frame "+frames+"\n");
     frames += 1 ;
 
     var locPmatrix = gl.getUniformLocation(gl.programObject, "Pmatrix");
     var locVmatrix = gl.getUniformLocation(gl.programObject, "Vmatrix");
     var locMmatrix = gl.getUniformLocation(gl.programObject, "Mmatrix");
 
-    // uniform으로 GPU한테 던져줌
     gl.uniformMatrix4fv(locPmatrix, false, proj_matrix);
     gl.uniformMatrix4fv(locVmatrix, false, view_matrix);
     // gl.uniformMatrix4fv(locMmatrix, false, mov_matrix);
@@ -376,17 +374,18 @@ function renderScene() {
     if (!testGLError("gl.uniformMatrix4fv")) {
         return false;
     }
+
     // gl.enable(gl.DEPTH_TEST);
     // gl.depthFunc(gl.LEQUAL); 
-	gl.enable(gl.CULL_FACE); // 이거(Culling) 켜면 뒷면 안그림
+	gl.enable(gl.CULL_FACE);
 	gl.enable(gl.BLEND);
     gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
     gl.blendEquation(gl.FUNC_ADD);
-    gl.clearColor(0.6, 0.8, 1.0, 1.0);  // 배경색 설정
+    gl.clearColor(0.6, 0.8, 1.0, 1.0);  // set background color
     gl.clearDepth(1.0); 
     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    
 
-    gl.enableVertexAttribArray(0); // 좌표
+    gl.enableVertexAttribArray(0); // coordinates
     gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 36, 0);
     gl.enableVertexAttribArray(1); // color
     gl.vertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 36, 12);
@@ -397,7 +396,6 @@ function renderScene() {
         return false;
     }
 
-    // Earth
     glMatrix.mat4.identity(mov_matrix);
     glMatrix.mat4.rotate(mov_matrix,mov_matrix,rotValue, rotAxis);
     glMatrix.mat4.translate(mov_matrix, mov_matrix, [transX,transY,transZ]);
@@ -407,7 +405,7 @@ function renderScene() {
     var mov_matrix_child = mov_matrix.slice();
     addTrace(mov_matrix_child);
 
-    // original cube
+    // draw original cube
     gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
     gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData(1.0, "color")), gl.STATIC_DRAW);
     gl.uniformMatrix4fv(locMmatrix, false, trace[trace.length -1].slice());
@@ -424,7 +422,6 @@ function renderScene() {
             gl.drawArrays(gl.TRIANGLES, 0, 36);
     }
     
-    // 회전 수치 표
     document.getElementById("matrix0").innerHTML = mov_matrix[0].toFixed(4);
 	document.getElementById("matrix1").innerHTML = mov_matrix[1].toFixed(4);
 	document.getElementById("matrix2").innerHTML = mov_matrix[2].toFixed(4);
@@ -450,6 +447,7 @@ function renderScene() {
 
 function main() {
     var canvas = document.getElementById("helloapicanvas");
+    document.getElementById("clickedBtn").click();
     console.log("Start");
 
     if (!initialiseGL(canvas)) {
@@ -482,11 +480,199 @@ function main() {
     })();
 }
 
-function showCode(){
+// Show Javascript code on HTML
+function showCode(type){
+    document.getElementById("code-box").style.visibility = "visible";
     var codeContent = document.getElementById("code-content");
 
+    if(type=='rendering'){
+        codeContent.innerHTML = 
+`// This is code of 'renderScene' function.
+// This code run every frame and draw the original cube and after-image of it.
+
+// gl.enable(gl.DEPTH_TEST);
+// gl.depthFunc(gl.LEQUAL); 
+gl.enable(gl.CULL_FACE);
+gl.enable(gl.BLEND);
+gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
+gl.blendEquation(gl.FUNC_ADD);
+gl.clearColor(0.6, 0.8, 1.0, 1.0);  // set background color
+gl.clearDepth(1.0); 
+gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);    
+
+gl.enableVertexAttribArray(0); // coordinates
+gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 36, 0);
+gl.enableVertexAttribArray(1); // color
+gl.vertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 36, 12);
+
+if (!testGLError("gl.vertexAttribPointer")) {
+    return false;
+}
+
+glMatrix.mat4.identity(mov_matrix);
+glMatrix.mat4.rotate(mov_matrix,mov_matrix,rotValue, rotAxis);
+glMatrix.mat4.translate(mov_matrix, mov_matrix, [transX,transY,transZ]);
+rotValue += animRotValue; 
+gl.uniformMatrix4fv(locMmatrix, false, mov_matrix);
+
+var mov_matrix_child = mov_matrix.slice();
+addTrace(mov_matrix_child);
+
+// draw original cube
+gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
+gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData(1.0, "color")), gl.STATIC_DRAW);
+gl.uniformMatrix4fv(locMmatrix, false, trace[trace.length -1].slice());
+gl.drawArrays(gl.TRIANGLES, 0, 36);
+
+// draw trace of cube
+color_a = 0.5;
+for (var i = trace.length -1; i>=0;i-=traceFreq){
+    color_a -= trace_alpha;
+    gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData(color_a, traceColor)), gl.STATIC_DRAW);
+    gl.uniformMatrix4fv(locMmatrix, false, trace[i].slice());
+    if (color_a > 0.0)
+        gl.drawArrays(gl.TRIANGLES, 0, 36);
+}`;
+    }
+    else if(type=="control"){
+        codeContent.innerHTML = 
+`// This is code of functions that control basic parameters
+
+// translate X increase or decrease
+function trXinc(sign) 
+{
+    if(sign=='+')
+        transX += 0.01;
+    else
+        transX -= 0.01;
+}
+
+// translate Y increase or decrease
+function trYinc(sign) 
+{
+	if(sign=='+')
+        transY += 0.01;
+    else
+        transY -= 0.01;
+}
+
+// translate Z increase or decrease
+function trZinc(sign) 
+{
+	if(sign=='+')
+        transZ += 0.01;
+    else
+        transZ -= 0.01;
+}
+
+//  increase or decrease rotation speed
+function animRotate(sign)
+{
+    if (sign=='+')
+        animRotValue += 0.01;
+    else
+        animRotValue -= 0.01;
+}
+
+// pause the rotating cube
+function animPause(){
+    animRotValue = 0.0;
+}
+
+// change rotating direction
+// 'rotAxis' is an array that its length is 3.
+// ex) rotAxis = [0,0,1]
+function changeRotAxis(axis){
+    switch(axis){
+        case 'X':
+            if (rotAxis[0]==1)
+                rotAxis[0]=0;
+            else
+                rotAxis[0]=1;
+            break;
+        case 'Y':
+            if (rotAxis[1]==1)
+                rotAxis[1]=0;
+            else
+                rotAxis[1]=1;
+            break;
+        case 'Z':
+            if (rotAxis[2]==1)
+                rotAxis[2]=0;
+            else
+                rotAxis[2]=1;
+            break;
+    }
+    // clear trace array when change rotating direction
+    trace = []; 
+}`;
+    }
+    else {
+        codeContent.innerHTML =
+`// This is code of 'initialiseShaders' fuction.
+
+var fragmentShaderSource = '
+    varying mediump vec4 color; 
+    void main(void) 
+    { 
+        gl_FragColor = 1.0 * color;
+    }';
+
+gl.fragShader = gl.createShader(gl.FRAGMENT_SHADER);
+gl.shaderSource(gl.fragShader, fragmentShaderSource);
+gl.compileShader(gl.fragShader);
+if (!gl.getShaderParameter(gl.fragShader, gl.COMPILE_STATUS)) {
+    alert("Failed to compile the fragment shader.\n" + gl.getShaderInfoLog(gl.fragShader));
+    return false;
+}
+
+var vertexShaderSource = '
+    attribute highp vec3 myVertex; 
+    attribute highp vec4 myColor; 
+    uniform mediump mat4 Pmatrix; 
+    uniform mediump mat4 Vmatrix; 
+    uniform mediump mat4 Mmatrix; 
+    varying mediump vec4 color; 
+    void main(void)  
+    { 
+        gl_Position = Pmatrix*Vmatrix*Mmatrix*vec4(myVertex, 1.0); 
+        color = myColor;
+    }';
+
+gl.vertexShader = gl.createShader(gl.VERTEX_SHADER);
+gl.shaderSource(gl.vertexShader, vertexShaderSource);
+gl.compileShader(gl.vertexShader);
+if (!gl.getShaderParameter(gl.vertexShader, gl.COMPILE_STATUS)) {
+    alert("Failed to compile the vertex shader.\n" + gl.getShaderInfoLog(gl.vertexShader));
+    return false;
+}
+
+gl.programObject = gl.createProgram();
+
+// Attach the fragment and vertex shaders to it
+gl.attachShader(gl.programObject, gl.fragShader);
+gl.attachShader(gl.programObject, gl.vertexShader);
+
+// Bind the custom vertex attribute
+gl.bindAttribLocation(gl.programObject, 0, "myVertex");
+gl.bindAttribLocation(gl.programObject, 1, "myColor");
+
+// Link the program
+gl.linkProgram(gl.programObject);
+
+if (!gl.getProgramParameter(gl.programObject, gl.LINK_STATUS)) {
+    alert("Failed to link the program.\n" + gl.getProgramInfoLog(gl.programObject));
+    return false;
+}
+
+gl.useProgram(gl.programObject);`
+    }
+    
+
 }
 
+// Show Control Tabs
 function openControls(evt, contName) {
     // Declare all variables
     var i, tabcontent, tablinks;