FabricJS Puppet Wrap

by codingdude

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.min.js"></script>
<canvas width="600" height="400" id="c"></canvas>



<img style="display:none" src="https://upload.wikimedia.org/wikipedia/en/0/05/Flag_of_Brazil.svg" id="my-image" crossorigin="anonymous">

<input id="v" type="range" min="-5" max="5" step="any" value="0">

JavaScript

//https://testdrive-archive.azurewebsites.net/Graphics/Warp/Default.html

function setupFilter(options){
  fabric.Image.filters[options.filterName] = fabric.util.createClass(fabric.Image.filters.BaseFilter, Object.assign({

    type: options.filterName,

    applyTo2d: function(options) {
      alert("This filter only works on browsers that support webgl");
    },
    resolution:100,
    getPosition:function(){
      var resolution = this.resolution;
       var q = 0.001;

          var r = (1 - q * 2) / resolution;
          var c = new Float32Array(resolution * resolution * 12); //2 numbers per coord; three coords per triangle; 2 triagles per square; resolution * resolution squares

          var i = 0;

          for (var xs = 0; xs < resolution; xs++) {
              for (var ys = 0; ys < resolution; ys++) {

                  var x = r * xs + q;
                  var y = r * ys + q;

                  c[i++] = x;
                  c[i++] = y;

                  c[i++] = x + r;
                  c[i++] = y;

                  c[i++] = x;
                  c[i++] = y + r;

                  c[i++] = x + r;
                  c[i++] = y;

                  c[i++] = x;
                  c[i++] = y + r;

                  c[i++] = x + r;
                  c[i++] = y + r;

              }
          }
          return c;
    },
    renderLines:false,
    applyToWebGL: function(options) {


      options.aPosition = this.getPosition();
      var gl = options.context;
      var shader = this.retrieveShader(options);
      if (options.pass === 0 && options.originalTexture) {
        gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);
      }
      else {
        gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);
      }
      gl.useProgram(shader.program);

      this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);

      gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);
      gl.uniform1f(shader.uniformLocations.uStepH,...