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 =...