WebGl warp

by Hooman Askari

HTML

<h1 id="DemoTitle">
    Photo warping with WebGL
  </h1>
  <h2>click and drag</h2>
  
  <div id="DemoContent">
    <div style='width:600px; height:600px'>
        <div style='position: relative'>          
        <!-- WebGL canvas -->
        <canvas style='position: absolute' id='webglcanvas' width='600' height='600'></canvas>
  
        <!-- notation cavas --> 
          <canvas style='position: absolute' id='2dcanvas' width='600' height='600'></canvas>
        </div>
    </div>
    <div style="text-align:center">
      
      <button id="openphoto1" onclick="OpenPhoto1()">Open a photo</button>      
      <span id="openphoto2" style="display:none">Pick a photo: <input type="file" id="files" /></span> <br />
      <button onclick="undo()">Undo</button>         
      <button onclick="reset()">Start over</button>        
      <button onclick="save()">Save</button>      
    </div>
  </div>
  
  <div id="ErrorMessage" style="display:none">
    <div class="heading">Sorry!</div>
      This demonstation requires a browser with WebGL support.
    </div>
    <div id="log"></div>
  
   <div id="Details">
      <div class="heading">WebGL 101</div>        
      To render the warped photo above, a mesh of 400 triangle coordinates, a photo, a vertex & 
      fragment shader program and uniform points are uploaded to the GPU using WebGL.<br />                                      
      <br />        
   <!-- The show uniform points checkbox -->
      <label><input type="checkbox" name="showUniforms" id="showUniforms" onchange="renderer.changeMode();renderer.render()" />Show uniform points</label> 
      <div>
        <label><input type="radio" name="rendertype" id="renderLines" onclick="renderer.render()" />Show triangle mesh</label>
        <label><input type="radio" name="rendertype" id="renderTriangles" onclick="renderer.render()" checked />Show rendered photo</label>
      </div>
        <br />
      When you click and drag on the photo, new uniform points are set...

CSS

/* Prevent text selection from being displayed when the user drags out of the canvas */
*::selection {
  background:transparent;
}

#DemoContent {
  margin-top:10px;
}

#DemoContent {
  width:600px;
  margin-left:auto;
  margin-right:auto;
  margin-top:10px;
}

#Details {
  margin-top:10px;
  margin-bottom:10px;
  padding:20px;
   border-radius:4px;
}

body {
 -ms-user-select: none; /* turn off user selection */
 font-size: 12pt;
}

canvas {
  -ms-touch-action: none; /* turn off panning and zooming */
}

.heading
{
  font-size: 20pt;
  font-weight: normal;
}

#ErrorMessage {
  position:absolute;
  top:100px;
  left:20%;
  right:20%;
  background-color:lightcoral;
  padding:20px;
  border-radius:4px;
}

JavaScript

'use strict';

window.onload = main;    // Startup

// Point object - converts incoming values to a -1 to 1 range).
function Point(x, y) {
    if (x<-1) x = -1;
    if (y<-1) y = -1;
    if (x>1) x = 1;
    if (y>1) y = 1;
    
    this.x = x;
    this.y = y;
}

// A new mouse manipulation.
function Move(point) { 
    this.point1 = new Point(point.x, point.y);
    this.point2 = new Point(point.x, point.y);
    
    this.move = function (point) {
        this.point2.x = point.x;
        this.point2.y = point.y;
    }
    
}

var renderer = new function () {

    var gl;                 // Handle to the context.
    var lineprogram;        // Handle to GLSL program that draws lines.
    var pictureprogram;     // Handle to GLSL program that draws a picture.

    this.texCoordLocation;   // Location of the texture for the picture fragment shader.
    this.texCoordLocation2;  // Location of the texture for the line fragment shader.

    this.texCoordBuffer;   // The buffer for the texture for the picture fragment shader.
    this.texCoordBuffer2;   // The buffer for the texture for the line fragment shader.
    
    var moves = [];  
    var MAXMOVES = 10;
    var currentMove = 0;

    var resolution = 300;  // Resolution of the mesh.


    // First init called by main().
    // Initialize the gl context variable.

    this.init = function () {
      // Get a context from our canvas object with id = "webglcanvas".
      var canvas = document.getElementById("webglcanvas"); 
        try {
          // Get the context into a local gl and and a public gl.
          // Use preserveDrawingBuffer:true to keep the drawing buffer after presentation
          var gl = this.gl = canvas.getContext("webgl", { preserveDrawingBuffer: true });
        }
          catch (e) {
          // Fail quietly 
        }

        // If we can't get a WebGL context (no WebGL support), then display an error message.
        if (!this.gl) {
         ...