var angleStep = (Math.PI * 2 / 10).toFixed(7);

var vert = `
attribute vec2 aVertexPosition;
attribute vec2 aTextureCoord;

uniform mat3 projectionMatrix;

varying vec2 vTextureCoord;

void main(void)
{
    gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
    vTextureCoord = aTextureCoord;
}`;

var frag = `
varying vec2 vTextureCoord;
uniform sampler2D uSampler;

uniform vec2 thickness;
uniform vec4 outlineColor;
uniform vec4 filterClamp;

const float DOUBLE_PI = 3.14159265358979323846264 * 2.;

void main(void) {
    vec4 ownColor = texture2D(uSampler, vTextureCoord);
    vec4 curColor;
    float maxAlpha = 0.;
    vec2 displaced;
    for (float angle = 0.; angle <= DOUBLE_PI; angle += ${angleStep}) {
        displaced.x = vTextureCoord.x + thickness.x * cos(angle);
        displaced.y = vTextureCoord.y + thickness.y * sin(angle);
        curColor = texture2D(uSampler, clamp(displaced, filterClamp.xy, filterClamp.zw));
        maxAlpha = max(maxAlpha, curColor.a);
    }
    float resultAlpha = max(maxAlpha, ownColor.a);
    gl_FragColor = vec4((ownColor.rgb + outlineColor.rgb * (1. - ownColor.a)) * resultAlpha, resultAlpha);
}`;

class OutlineFilter extends PIXI.Filter {
    constructor(thickness = 1, color = 0x000000) {
        const samples = 10;
        super(vert, frag);
        this.uniforms.thickness = new Float32Array([0, 0]);
        this.thickness = thickness;
        this.uniforms.outlineColor = PIXI.utils.hex2rgb(color, new Float32Array([0, 0, 0, 1]));
    }
    apply(filterManager, input, output, clear) {
        this.uniforms.thickness[0] = this.thickness / input.sourceFrame.width;
        this.uniforms.thickness[1] = this.thickness / input.sourceFrame.height;
        filterManager.applyFilter(this, input, output, clear);
    }
}

b = new Bitmap(Graphics.width, Graphics.height);
b.fillAll('silver');
back = scene.addChild(new Sprite(b));

s = scene.addChild(new Sprite(Bitmap.load('icons8-beta-96.png')));
s._filters = [new OutlineFilter(3, 0xFF0000)];