WebGL GPU normals

by tautin

HTML

<script src="http://176.150.209.228:8080/normals-jsfiddle-gpu/utils/gl-matrix.js"></script>
<script src="http://176.150.209.228:8080/normals-jsfiddle-gpu/utils/gl-utils.js"></script>
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>WebGL Demo</title>
  </head>

  <body>

    <canvas id="glcanvas"></canvas>

    <div id="controls">

      <div>
        <label for="rotation">Rotation:</label>
        <input type="range" id="rotation" name="rotation" min="0" max="360" value="0">
      </div>

      <div>
        <label for="tilt">Tilt:</label>
        <input type="range" id="tilt" name="tilt" min="0" max="180" value="0">
      </div>

      <div>
        <label for="zoom">Zoom:</label>
        <input type="range" id="zoom" name="zoom" min="0" max="100" value="0">
      </div>

      <div>
        <label for="drawingMode">Drawing mode:</label>

        <select name="drawingMode" id="drawingMode">
          <option value="TRIANGLES">TRIANGLES</option>
          <option value="TRIANGLE_STRIP">TRIANGLE_STRIP</option>
          <option value="TRIANGLE_FAN">TRIANGLE_FAN</option>
          <option value="LINES">LINES</option>
          <option value="LINE_STRIP">LINE_STRIP</option>
          <option value="LINE_LOOP">LINE_LOOP</option>
          <option value="POINTS">POINTS</option>
        </select>
      </div>

    </div>

  </body>

</html>

CSS

html, body {
  width: 100%;
  height: 100%;
  padding: 0px;
  margin: 0px;
}

canvas {
  margin: 0px;
}

#controls {
  margin: 0px;
  padding: 10px;
}

#controls div {
  height: 30px;
  display: flex;
  align-items: center;
}

label {
  display: inline-block;
  width: 180px;
}

JavaScript

const canvasWidth = 500;
const canvasHeight = 300;

const SIZE = 2;
const RESOLUTION = 32;
const Z_SCALE = 5000 / SIZE;

const DEM = "https://api.mapbox.com/v4/mapbox.terrain-rgb/11/1030/755.pngraw?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4M29iazA2Z2gycXA4N2pmbDZmangifQ.-g_vE53SD2WrJ6tFX7QHmA";
const TEXTURE = "https://lh3.googleusercontent.com/proxy/6n4D_qzYn_UhdvsAxjfkvPefY2IvjKjeOm9CAzqbYMcYg37P0f3sC5JJu7QvhpJMD46xbbFGnx56hjoDL6fqQimCk_KLjSNb2xtYJblPtOQnzf4J6tSiIQ";

const rotationElement = document.getElementById("rotation");
const tiltElement = document.getElementById("tilt");
const zoomElement = document.getElementById("zoom");
const drawingModeElement = document.getElementById("drawingMode");

let triangles = [];
let triangleNormals = [];
let vertexNormals = [];

main();

function main() {

	const canvas = document.querySelector('#glcanvas');

	// Set the display size of the canvas:
	canvas.style.width = canvasWidth + "px";
	canvas.style.height = canvasHeight + "px";

	// Manage HiDPI monitors:
	let devicePixelRatio = window.devicePixelRatio || 1;
	canvas.width = canvasWidth * devicePixelRatio;
	canvas.height = canvasHeight * devicePixelRatio;

	// Get the WebGL context:
  const gl = canvas.getContext('webgl2');

  // If we don't have a GL context, give up now
  if (!gl) {
    alert('Unable to initialize WebGL. Your browser or machine may not support it.');
    return;
  }

  // Tile shaders
  const vsSource = `#version 300 es

		precision highp float;
		precision highp int;

		uniform mat4 u_Model;
		uniform mat4 u_View;
		uniform mat4 u_Projection;

		in vec3 a_Position;
		in vec3 a_Normal;
		in vec2 a_TextureCoordinates;

		out vec3 v_Position;
    out vec3 v_Normal;
    out vec2 v_TextureCoordinates;

		out mat4 v_Model;
		out mat4 v_View;
		out mat4 v_Projection;

		void main() {

			v_Model = u_Model;
			v_View = u_View;
			v_Projection = u_Projection;

			v_TextureCoordinates = a_TextureCoordinates;
			v_Position = vec3(u_View * u_Model *...