FabricJS Displacement Filter

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>

Value:
<input id="maximum" type="range" min="0" max="1" step="any" value="0.5">

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

<img  style="display:none" src="http://www.textures4photoshop.com/tex/thumbs/seamless-texture-crumpled-paper-free-thumb36.jpg" id="disp-map"  crossorigin="anonymous">

JavaScript

/*FabricJS Plugin Template*/

fabric.textureSize = 4096;//for filters on large images
/*
  options:
    filterName - name of the filter
    mainParameter - main parameter name
    fragmentSource - code for the fragment shader
    uniforms
    sendUniformData(gl,uniformLocations)
*/
function setupFilter(options){
  fabric.Image.filters[options.filterName] = fabric.util.createClass(fabric.Image.filters.BaseFilter, Object.assign({

    type: options.filterName,
		displacementMap:null,//fabric Image
    applyTo2d: function(options) {
      alert("This filter only works on browsers that support webgl");
    },
    applyToWebGL: function(options) {
      // load texture to blend.
      var gl = options.context,
          texture = this.createTexture(options.filterBackend, this.displacementMap);
      this.bindAdditionalTexture(gl, texture, gl.TEXTURE1);
      this.callSuper('applyToWebGL', options);
      this.unbindAdditionalTexture(gl, gl.TEXTURE1);
    },
    createTexture: function(backend, image) {
      return backend.getCachedTexture(image.cacheKey, image._element);
    },
    getUniformLocations: function(gl, program) {
        return options.uniforms(gl,program);
      },
    createTexture: function(backend, image) {
        return backend.getCachedTexture(image.cacheKey, image._element);
      },    
    sendUniformData: function(gl, uniformLocations) {
    		var matrix = this.calculateMatrix();
      	gl.uniform1i(uniformLocations.uImage, 1); // texture unit 1.
      	gl.uniformMatrix3fv(uniformLocations.uTransformMatrix, false, matrix);
        options.sendUniformData(gl, uniformLocations);
    },
    isNeutralState:function(){
    	return false;//this.callSuper('isNeutralState');
    }
  },options));

  fabric.Image.filters[options.filterName].fromObject = fabric.Image.filters.BaseFilter.fromObject;
}

////////////Template end////////////////////


//init filter from template
var options={
    filterName: "Displacement",
    mainParameter: "maximum",
   ...