Custom Blur Filter implementation

by adil_invideo

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.1.3/pixi.min.js"></script>
<div class="controller">
  <input type="range" min="0" max="20" id="radius" value="0" />
  <label for="radius">Radius</label>
</div>

<div class='wrapper'>
  <img id="img" src="https://d1efk3962q5p8g.cloudfront.net/480x480/dog_1608633207370.png" />
</div>

CSS

.controller {
  display: flex;
  flex-direction: column;
  width: 30%;
}

.wrapper {
  width: 400px;
  overflow: hidden;
}

img {
  width: 100%;
}

JavaScript

/* 
	References : https://xorshaders.weebly.com/tutorials/blur-shaders-5-part-2
*/
const directionToken = "<direction>";
const qualityToken = "<quality>";
const frag = `
varying highp vec2 vTextureCoord;
uniform sampler2D uSampler;

uniform vec2 size;	//width,height,radius
uniform float radius;

const int quality = ${qualityToken};
const int directions = ${directionToken};
const float Pi = 6.28318530718;//pi * 2
  
void main() {

  vec2 radius = radius / size.xy;
  vec4 color = texture2D(uSampler, vTextureCoord);

  for (float d = 0.0; d < Pi; d += Pi / float(directions)) {
    for (float i = 1.0 / float(quality); i <= 1.0; i += 1.0 / float(quality)) {
      color += texture2D(uSampler, vTextureCoord + vec2(cos(d), sin(d)) * radius * i);
    }
  }
  color /= float(quality) * float(directions) + 1.0;

  gl_FragColor = color;
}
`;


class NewBlurFilter extends PIXI.Filter {

  constructor(width, height, radius, quality, directions) {
    const uniforms = {
      size: [width, height],
      radius,
    };
    const fragmentShader =
      frag
      .replace(directionToken, (directions || 10).toString())
      .replace(qualityToken, (quality || 6).toString());
    super(null, fragmentShader, uniforms);
  }

  get radius() {
    return this._radius;
  }

  set radius(value) {
    this._radius = value;
    this._updateTransform();
  }

  _updateTransform() {
    this.uniforms.radius = this._radius;
  }
}

const imgSrc = "https://d1efk3962q5p8g.cloudfront.net/480x480/dog_1608633207370.png";

const width = 600;
const height = 260;
const app = new PIXI.Application({
  width,
  height,
  transparent: true
});

document.body.appendChild(app.view);

const img = new PIXI.Sprite.from(imgSrc);
img.width = 400;
img.height = height;
app.stage.addChild(img);


const blur = new NewBlurFilter(400, height, 0);
img.filters = [blur];

const imgDom = document.getElementById('img');
document.getElementById("radius").oninput = e => {
  const value = e.target.value;
  blur.radius =...