text: ﻿"use strict";
  
  function main() {
      // Get A WebGL context
      /** @type {HTMLCanvasElement} */
      var canvas = document.getElementById("canvas");
      var gl = canvas.getContext("webgl");
      if (!gl) {
          return;
      }
  
      // look up the divcontainer
      var divContainerElement = document.getElementById("divcontainer");
  
      // make the div
      var div = document.createElement("div");
  
      // assign it a CSS class
      div.className = "floating-div";
  
      // make a text node for its content
      var textNode = document.createTextNode("");
      div.appendChild(textNode);
  
      // add it to the divcontainer
      divContainerElement.appendChild(div);
  
      // setup GLSL program
      var program = webglUtils.createProgramFromScripts(gl, ["3d-vertex-shader", "3d-fragment-shader"]);
  
      // look up where the vertex data needs to go.
      var positionLocation = gl.getAttribLocation(program, "a_position");
      var colorLocation = gl.getAttribLocation(program, "a_color");
  
      // lookup uniforms
      var matrixLocation = gl.getUniformLocation(program, "u_matrix");
  
      // Create a buffer to put positions in
      var positionBuffer = gl.createBuffer();
      // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
      gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
      // Put geometry data into buffer
      setGeometry(gl);
  
      // Create a buffer to put colors in
      var colorBuffer = gl.createBuffer();
      // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = colorBuffer)
      gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
      // Put geometry data into buffer
      setColors(gl);
  
      function radToDeg(r) {
          return r * 180 / Math.PI;
      }
  
      function degToRad(d) {
          return d * Math.PI / 180;
      }
  
      var translation = [0, 30, -360];
      var rotation = [degToRad(190), degToRad(0), degToRad(0)];
      var fieldOfViewRadians = degToRad(60);
      var rotationSpeed = 1.2;
  
      var x = 0;
      var y = 0;
      var dx = 4;
      var dy = 4;
  
      var then = 0;
  
      requestAnimationFrame(drawScene);
  
      // Draw the scene.
      function drawScene(clock) {
          // Convert to seconds
          clock *= 0.001;
          // Subtract the previous time from the current time
          var deltaTime = clock - then;
          // Remember the current time for the next frame.
          then = clock;
  
          webglUtils.resizeCanvasToDisplaySize(gl.canvas);
  
          // Tell WebGL how to convert from clip space to pixels
          gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
  
          x += dx;
          y += dy;
          if (x < 0 || x > gl.canvas.width) {
              dx = -dx;
          }
          if (y < 0 || y > gl.canvas.height) {
              dy = -dy;
          }
  
          div.style.left = Math.floor(x) + "px";
          div.style.top = Math.floor(y) + "px";
          textNode.nodeValue = clock.toFixed(2);
  
          // Every frame increase the rotation a little.
          rotation[1] += rotationSpeed * deltaTime;
  
          // Clear the canvas AND the depth buffer.
          gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  
          // Turn on culling. By default backfacing triangles
          // will be culled.
          gl.enable(gl.CULL_FACE);
  
          // Enable the depth buffer
          gl.enable(gl.DEPTH_TEST);
  
          // Tell it to use our program (pair of shaders)
          gl.useProgram(program);
  
          // Turn on the position attribute
          gl.enableVertexAttribArray(positionLocation);
  
          // Bind the position buffer.
          gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
  
          // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
          var size = 3;          // 3 components per iteration
          var type = gl.FLOAT;   // the data is 32bit floats
          var normalize = false; // don't normalize the data
          var stride = 0;        // 0 = move forward size * sizeof(type) each iteration to get the next position
          var offset = 0;        // start at the beginning of the buffer
          gl.vertexAttribPointer(
              positionLocation, size, type, normalize, stride, offset);
  
          // Turn on the color attribute
          gl.enableVertexAttribArray(colorLocation);
  
          // Bind the color buffer.
          gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
  
          // Tell the attribute how to get data out of colorBuffer (ARRAY_BUFFER)
          var size = 3;                 // 3 components per iteration
          var type = gl.UNSIGNED_BYTE;  // the data is 8bit unsigned values
          var normalize = true;         // normalize the data (convert from 0-255 to 0-1)
          var stride = 0;               // 0 = move forward size * sizeof(type) each iteration to get the next position
          var offset = 0;               // start at the beginning of the buffer
          gl.vertexAttribPointer(
              colorLocation, size, type, normalize, stride, offset);
  
          // Compute the matrices
          var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
          var projectionMatrix =
              m4.perspective(fieldOfViewRadians, aspect, 1, 2000);
  
          var spread = 170;
          for (var yy = -1; yy <= 1; ++yy) {
              for (var xx = -2; xx <= 2; ++xx) {
                  var matrix =
                      m4.translate(projectionMatrix, translation[0] + xx * spread, translation[1] + yy * spread, translation[2]);
                  matrix = m4.xRotate(matrix, rotation[0]);
                  matrix = m4.yRotate(matrix, rotation[1] + yy * xx * 0.2);
                  matrix = m4.zRotate(matrix, rotation[2]);
  
                  // Set the matrix.
                  gl.uniformMatrix4fv(matrixLocation, false, matrix);
  
                  // Draw the geometry.
                  gl.drawArrays(gl.TRIANGLES, 0, 16 * 6);
              }
          }
  
          requestAnimationFrame(drawScene);
      }
  }
  
  // Fill the buffer with the values that define a letter 'F'.
  function setGeometry(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Float32Array([
              // left column front
              0, 0, 0,
              0, 150, 0,
              30, 0, 0,
              0, 150, 0,
              30, 150, 0,
              30, 0, 0,
  
              // top rung front
              30, 0, 0,
              30, 30, 0,
              100, 0, 0,
              30, 30, 0,
              100, 30, 0,
              100, 0, 0,
  
              // middle rung front
              30, 60, 0,
              30, 90, 0,
              67, 60, 0,
              30, 90, 0,
              67, 90, 0,
              67, 60, 0,
  
              // left column back
                0, 0, 30,
               30, 0, 30,
                0, 150, 30,
                0, 150, 30,
               30, 0, 30,
               30, 150, 30,
  
              // top rung back
               30, 0, 30,
              100, 0, 30,
               30, 30, 30,
               30, 30, 30,
              100, 0, 30,
              100, 30, 30,
  
              // middle rung back
               30, 60, 30,
               67, 60, 30,
               30, 90, 30,
               30, 90, 30,
               67, 60, 30,
               67, 90, 30,
  
              // top
                0, 0, 0,
              100, 0, 0,
              100, 0, 30,
                0, 0, 0,
              100, 0, 30,
                0, 0, 30,
  
              // top rung right
              100, 0, 0,
              100, 30, 0,
              100, 30, 30,
              100, 0, 0,
              100, 30, 30,
              100, 0, 30,
  
              // under top rung
              30, 30, 0,
              30, 30, 30,
              100, 30, 30,
              30, 30, 0,
              100, 30, 30,
              100, 30, 0,
  
              // between top rung and middle
              30, 30, 0,
              30, 60, 30,
              30, 30, 30,
              30, 30, 0,
              30, 60, 0,
              30, 60, 30,
  
              // top of middle rung
              30, 60, 0,
              67, 60, 30,
              30, 60, 30,
              30, 60, 0,
              67, 60, 0,
              67, 60, 30,
  
              // right of middle rung
              67, 60, 0,
              67, 90, 30,
              67, 60, 30,
              67, 60, 0,
              67, 90, 0,
              67, 90, 30,
  
              // bottom of middle rung.
              30, 90, 0,
              30, 90, 30,
              67, 90, 30,
              30, 90, 0,
              67, 90, 30,
              67, 90, 0,
  
              // right of bottom
              30, 90, 0,
              30, 150, 30,
              30, 90, 30,
              30, 90, 0,
              30, 150, 0,
              30, 150, 30,
  
              // bottom
              0, 150, 0,
              0, 150, 30,
              30, 150, 30,
              0, 150, 0,
              30, 150, 30,
              30, 150, 0,
  
              // left side
              0, 0, 0,
              0, 0, 30,
              0, 150, 30,
              0, 0, 0,
              0, 150, 30,
              0, 150, 0]),
          gl.STATIC_DRAW);
  }
  
  // Fill the buffer with colors for the 'F'.
  function setColors(gl) {
      gl.bufferData(
          gl.ARRAY_BUFFER,
          new Uint8Array([
              // left column front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
  
              // top rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
  
              // middle rung front
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
            200, 70, 120,
  
              // left column back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
  
              // top rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
  
              // middle rung back
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
            80, 70, 200,
  
              // top
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
            70, 200, 210,
  
              // top rung right
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
            200, 200, 70,
  
              // under top rung
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
            210, 100, 70,
  
              // between top rung and middle
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
            210, 160, 70,
  
              // top of middle rung
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
            70, 180, 210,
  
              // right of middle rung
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
            100, 70, 210,
  
              // bottom of middle rung.
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
            76, 210, 100,
  
              // right of bottom
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
            140, 210, 80,
  
              // bottom
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
            90, 130, 110,
  
              // left side
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220,
            160, 160, 220]),
          gl.STATIC_DRAW);
  }
  
  main();
  