FabricJS Filter Glitch
by codingdude
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
<script id="glitchShader" type="x-shader/x-vertex">
precision highp float;
uniform sampler2D uTexture;
uniform float uPhase;
uniform float uStepW,uStepH;
varying vec2 vTexCoord;
float sat( float t ) {
return clamp( t, 0.0, 1.0 );
}
vec2 sat( vec2 t ) {
return clamp( t, 0.0, 1.0 );
}
//remaps inteval [a;b] to [0;1]
float remap ( float t, float a, float b ) {
return sat( (t - a) / (b - a) );
}
//note: /\ t=[0;0.5;1], y=[0;1;0]
float linterp( float t ) {
return sat( 1.0 - abs( 2.0*t - 1.0 ) );
}
vec3 spectrum_offset( float t ) {
float t0 = 3.0 * t - 1.5;
return clamp( vec3( -t0, 1.0-abs(t0), t0), 0.0, 1.0);
/*
vec3 ret;
float lo = step(t,0.5);
float hi = 1.0-lo;
float w = linterp( remap( t, 1.0/6.0, 5.0/6.0 ) );
float neg_w = 1.0-w;
ret = vec3(lo,1.0,hi) * vec3(neg_w, w, neg_w);
return pow( ret, vec3(1.0/2.2) );
*/
}
//note: [0;1]
float rand( vec2 n ) {
return fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
}
//note: [-1;1]
float srand( vec2 n ) {
return rand(n) * 2.0 - 1.0;
}
float mytrunc( float x, float num_levels )
{
return floor(x*num_levels) / num_levels;
}
vec2 mytrunc( vec2 x, float num_levels )
{
return floor(x*num_levels) / num_levels;
}
void main() {
float aspect = uStepW / uStepH;
vec2 uv = vec2(vTexCoord.x,1.0 - vTexCoord.y); // vec2(uStepW,uStepH);
uv.y = 1.0 - uv.y;
float GLITCH = 0.4;
float gnm = sat( GLITCH );
float time = uPhase;
float rnd0 = rand( mytrunc( vec2(time, time), 6.0 ) );
float r0 = sat((1.0-gnm)*0.7 + rnd0);
float rnd1 = rand( vec2(mytrunc( uv.x, 10.0*r0 ), time) ); //horz
float r1 = 0.5 - 0.5 * gnm + rnd1;
r1 = 1.0 - max( 0.0, ((r1<1.0) ? r1 : 0.9999999) ); //note: weird ass bug on old drivers
float rnd2 = rand( vec2(mytrunc( uv.y, 40.0*r1 ), time) ); //vert
float r2 = sat( rnd2 );
float rnd3 = rand( vec2(mytrunc( uv.y, 10.0*r0 ), time) );
float r3 =...
JavaScript
fabric.textureSize = 4096;//for filters on large images
var canvas = new fabric.Canvas('c');
var imgElement = document.getElementById('my-image');
var imgInstance = new fabric.Image(imgElement, {
left: 100,
top: 50,
angle: 0,
opacity: 1,
scaleX:0.1,
scaleY:0.1
});
canvas.add(imgInstance);
fabric.Image.filters.Glitch = fabric.util.createClass(fabric.Image.filters.BaseFilter, {
type: 'Glitch',
radius:0.1,
smoothness:0.5,
mainParameter:"phase",
/**
* Fragment source for the redify program
*/
fragmentSource: window.document.getElementById("glitchShader").textContent,
applyTo2d: function(options) {
var imageData = options.imageData,
data = imageData.data, i, len = data.length;
for (i = 0; i < len; i += 4) {
data[i + 1] = 0;
data[i + 2] = 0;
}
},
getUniformLocations: function(gl, program) {
return {
uPhase: gl.getUniformLocation(program, 'uPhase')
};
},
sendUniformData: function(gl, uniformLocations) {
gl.uniform1f(uniformLocations.uPhase, this.phase);
}
});
fabric.Image.filters.Glitch.fromObject = fabric.Image.filters.BaseFilter.fromObject;
var glitch = new fabric.Image.filters.Glitch({phase:0.5});
imgInstance.filters.push(glitch);
imgInstance.applyFilters();
var slider = window.document.getElementById("phase");
slider.oninput = slider.onchange = function(){
glitch.phase = this.value;
console.log(this.value);
imgInstance.applyFilters();
canvas.requestRenderAll();
}