FabricJS Filter Polar Coordinates

by codingdude

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
<canvas width="600" height="400" id="c"></canvas>
<img style="display:none" src="https://i.imgur.com/IzBRPq3.jpg" id="my-image" crossorigin="anonymous">

<label for="radius">Radius <input type="range" id="radius" min="0" max="1" step="any"></label><br/>
<label for="rotation">Rotation <input type="range" id="rotation" min="0" max="1" step="any"></label>
<br/>
<label for="flip">Rotation <input type="checkbox" id="flip" ></label>

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,

    applyTo2d: function(options) {
      alert("This filter only works on browsers that support webgl");
    },
    getUniformLocations: function(gl, program) {
        return options.uniforms(gl,program);
      },
    createTexture: function(backend, image) {
        return backend.getCachedTexture(image.cacheKey, image._element);
      },    
    sendUniformData: function(gl, uniformLocations) {
        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: "PolarCoordinates",
    mainParameter: "uRotation",
    uniforms:function(gl,program){
      return {uRadius:gl.getUniformLocation(program, 'uRadius'), uRotation:gl.getUniformLocation(program, 'uRotation'), uFlip:gl.getUniformLocation(program, 'uFlip')  };
    },
    sendUniformData:function(gl,uniformLocations){
      gl.uniform1f(uniformLocations.uRadius, this.uRadius);
      gl.uniform1f(uniformLocations.uRotation, this.uRotation);
      gl.uniform1f(uniformLocations.uFlip, this.uFlip);
    },
    fragmentSource: `
    precision highp float;
    uniform sampler2D uTexture;
    varying vec2 vTexCoord;
    #define PI 3.14159265358979323844
    
    uniform float uRadius,uRotation,uFlip;

    void main() {
        vec2 pos = vTexCoord;
       ...