From 31ec733bdadb302275e79db256418c4202f6976b Mon Sep 17 00:00:00 2001
From: gbrochar <gaetanbrochard@protonmail.com>
Date: Tue, 24 Nov 2020 13:10:47 +0100
Subject: [PATCH] fixed WebGL warning, add distance support

---
 src/client/changeshader.ts |  4 +--
 src/client/main.ts         | 62 +++++++++++++++++++++++---------------
 src/client/objparser.js    | 17 +++++++++--
 src/client/shaders.ts      |  3 +-
 views/index.ejs            | 11 +++++--
 5 files changed, 64 insertions(+), 33 deletions(-)

diff --git a/src/client/changeshader.ts b/src/client/changeshader.ts
index aca1e91..14ed83b 100644
--- a/src/client/changeshader.ts
+++ b/src/client/changeshader.ts
@@ -15,7 +15,7 @@ export function changeFragmentShader(gl: any,
 	fragmentShader: any,
 	fsSource: string,
 	vsSource: string) {
-	shaderProgram = unlinkShaderProgram(gl,
+	[shaderProgram, fragmentShader] = unlinkShaderProgram(gl,
 		fragmentShader,
 		shaderProgram);
 	[shaderProgram, fragmentShader] = initShaderProgram(gl,
@@ -40,5 +40,5 @@ export function changeFragmentShader(gl: any,
 				shaderProgram, 'umodelMatrix'),
 		},
 	};
-	return programInfo;
+	return [programInfo, fragmentShader];
 }
diff --git a/src/client/main.ts b/src/client/main.ts
index abc42c3..5a9e65d 100644
--- a/src/client/main.ts
+++ b/src/client/main.ts
@@ -85,7 +85,11 @@ function main() {
 			0.), 10.);
 		vec3 tmp = extremize(mod(vPosition.xyz + vec3(100.), vec3(3.)), 3.);
 		float texture = (tmp.x + tmp.y + tmp.z) / 9.;
-		gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * 0.1) + (specular * vec3(1.)), 1.0);
+		if (abs(vNormal.x) + abs(vNormal.y) + abs(vNormal.z) > 0.01) {
+			gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * vec3(0.1)) + (specular * vec3(1.)), 1.0);
+		} else {
+			gl_FragColor = vec4((texture * vec3(1.)), 1.0);
+		}
 	}`;
 
 	const fsSource2 = `
@@ -121,7 +125,11 @@ function main() {
 			0.), 10.);
 		vec3 tmp = extremize(mod(vPosition.xyz + vec3(100.), vec3(3.)), 3.);
 		vec3 texture = vec3(tmp.x / 3., tmp.y / 3., tmp.z / 3.);
-		gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * vec3(0.1)) + (specular * vec3(1.)), 1.0);
+		if (abs(vNormal.x) + abs(vNormal.y) + abs(vNormal.z) > 0.01) {
+			gl_FragColor = vec4((texture * diffuse * 0.9) + (texture * vec3(0.1)) + (specular * vec3(1.)), 1.0);
+		} else {
+			gl_FragColor = vec4((texture * vec3(1.)), 1.0);
+		}
 	}`;
 	
 	/* eslint-enable */
@@ -129,27 +137,16 @@ function main() {
 	fetch('/static/objs/teapot_normals.obj').then((response) => {
 		return response.text();
 	}).then((data: any) => {
+		let distance: any = $('#input1').val();
+		distance = parseFloat(distance);
 		const [
-			convertedPositions,
-			convertedNormals,
+			positions,
+			normals,
 			uvs,
 			indices,
 		] = convert(data);
 		console.log(uvs);
-		console.log(squareRotation);
-		const normals: any = [];
-		const positions: any = [];
-		for (let i = 0; i < convertedNormals.length; i++) {
-			if (i % 4 != 0) {
-				normals.push(convertedNormals[i]);
-			}
-		}
-		for (let i = 0; i < convertedPositions.length; i++) {
-			if (i % 4 != 0) {
-				positions.push(convertedPositions[i]);
-			}
-		}
-		const [shaderProgram, fragmentShader]: any = initShaderProgram(gl,
+		let [shaderProgram, fragmentShader]: any = initShaderProgram(gl,
 			vsSource,
 			fsSource);
 
@@ -188,19 +185,34 @@ function main() {
 				changed = true;
 			}
 			then = now;
-			drawScene(gl, programInfo, buffers, deltaTime, indices.length);
+			drawScene(gl,
+				programInfo,
+				buffers,
+				deltaTime,
+				indices.length,
+				distance);
 			requestAnimationFrame(render);
 		}
 
 		$(function() {
+			$('#input1').on('keypress', function(event: any) {
+				if (event.which === 13) {
+					event.preventDefault();
+					$('#button3').click();
+				}
+			});
 			$('#button1').on('click', function() {
-				programInfo = changeFragmentShader(gl,
+				[programInfo, fragmentShader] = changeFragmentShader(gl,
 					shaderProgram, fragmentShader, fsSource, vsSource);
 			});
 			$('#button2').on('click', function() {
-				programInfo = changeFragmentShader(gl,
+				[programInfo, fragmentShader] = changeFragmentShader(gl,
 					shaderProgram, fragmentShader, fsSource2, vsSource);
 			});
+			$('#button3').on('click', function() {
+				distance = $('#input1').val();
+				distance = parseFloat(distance);
+			});
 		});
 		requestAnimationFrame(render);
 	});
@@ -214,12 +226,14 @@ function main() {
  * @param {any} buffers the buffers to draw
  * @param {number} deltaTime the difference in time since last call
  * @param {number} length the index buffer length
+ * @param {number} distance distance of camera
  */
 function drawScene(gl: any,
 	programInfo: any,
 	buffers: any,
 	deltaTime: number,
-	length: number) {
+	length: number,
+	distance: number) {
 	gl.clearColor(0.0, 0.0, 0.0, 1.0);
 	gl.clearDepth(1.0);
 	gl.enable(gl.DEPTH_TEST);
@@ -236,7 +250,7 @@ function drawScene(gl: any,
 	const fieldOfView = 45 * Math.PI / 180;
 	const aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
 	const zNear = 0.1;
-	const zFar = 70.0;
+	const zFar = 150.0;
 	const projectionMatrix = mat4.create();
 
 	// note: glmatrix.js always has the first argument
@@ -273,7 +287,7 @@ function drawScene(gl: any,
 	mat4.translate(
 		viewMatrix,
 		viewMatrix,
-		[0.0, 0.0, -50.0]);
+		[0.0, 0.0, -distance]);
 
 	// Tell WebGL how to pull out the positions from the position
 	// buffer into the vertexPosition attribute.
diff --git a/src/client/objparser.js b/src/client/objparser.js
index 5d44259..ec669a0 100644
--- a/src/client/objparser.js
+++ b/src/client/objparser.js
@@ -14,7 +14,14 @@ export default function convert (objText) {
 		const line = lines[i];
 		if (line != '')
 		{
-			const chunks = line.split(" ").map(x => x.trim());
+			const rawchunks = line.split(" ").map(x => x.trim());
+			const chunks = [];
+
+			for (let i = 0; i < rawchunks.length; i++) {
+				if (rawchunks[i] != '') {
+					chunks.push(rawchunks[i]);
+				}
+			}
 
 			switch (chunks[0]) {
 				case "v": {
@@ -101,8 +108,12 @@ export default function convert (objText) {
 		const d = (vertices[i].startsWith("s") ? vertices[i].substr(1) : vertices[i]).split("/");
 
 		outPositions.push(...positions[d[0] - 1]);
-		outNormals.push(...normals[d[2] - 1]);
-		outUVs.push(...uvs[d[1] - 1]);
+		if (normals.length) {
+			outNormals.push(...normals[d[2] - 1]);
+		}
+		if (uvs.length) {
+			outUVs.push(...uvs[d[1] - 1]);
+		}
 	}
 	return [outPositions, outNormals, outUVs, indices];
 };
\ No newline at end of file
diff --git a/src/client/shaders.ts b/src/client/shaders.ts
index 13018e6..ae6ebf2 100644
--- a/src/client/shaders.ts
+++ b/src/client/shaders.ts
@@ -7,9 +7,8 @@
  */
 export function unlinkShaderProgram(gl: any, shader: any, shaderProgram: any) {
 	// Create the shader program
-	gl.detachShader(shaderProgram, shader);
 	gl.deleteShader(shader);
-	return shaderProgram;
+	return [shaderProgram, shader];
 }
 
 /**
diff --git a/views/index.ejs b/views/index.ejs
index d7cad2f..e48a1da 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -14,8 +14,15 @@
 		<div id="root">
 			<canvas id='glCanvas' width='640' height='640'></canvas>
 			<div id='ui'>
-				<button id='button1'>Change Shader to black and white</button>
-				<button id='button2'>Change Shader to colored</button>
+				<div class='ui-block'>
+					<button id='button1'>Change Shader to black and white</button>
+					<button id='button2'>Change Shader to colored</button>
+				</div>
+				<div class='ui-block'>
+					<input id='input1' value='50'></input>
+					<button id='button3'>Change camera distance</button>
+					<div style='display: inline'>Max distance is 150</div>
+				</div>
 			</div>
 		</div>
 		<script src="js/bundle.js"></script>