Engine.SkinColorReplaceFilter = class extends PIXI.Filter
{
    constructor()
    {
        var frag = 
            `
            precision mediump float;
            
            uniform sampler2D uSampler;
            varying vec2 vTextureCoord;

            uniform float _Amount;
            uniform vec3 _Color;

            uniform float epsilon;
            uniform vec3 colorA;
            uniform vec3 colorB;
            uniform vec3 colorC;
            uniform vec3 colorD;

            void main(void)
            {
                vec4 col = texture2D(uSampler, vTextureCoord);
                
                vec4 overlayColor;
                overlayColor.rgb = _Color; //vec3(dot(col.rgb, _Color));
                overlayColor.a = col.a;

                vec4 fragColor;
                fragColor.rgb = (col.rgb * (1.0 - _Amount)) + (overlayColor.rgb * _Amount);
                //fragColor.rgb = col.rgb + (overlayColor.rgb * _Amount);
                fragColor.a = col.a;

                vec3 colorDiff = colorA - (col.rgb / max(col.a, 0.0000000001));
                float colorDistance = length(colorDiff);
                float doReplace = step(colorDistance, epsilon);

                colorDiff = colorB - (col.rgb / max(col.a, 0.0000000001));
                colorDistance = length(colorDiff);
                doReplace = doReplace + step(colorDistance, epsilon);

                colorDiff = colorC - (col.rgb / max(col.a, 0.0000000001));
                colorDistance = length(colorDiff);
                doReplace = doReplace + step(colorDistance, epsilon);

                colorDiff = colorD - (col.rgb / max(col.a, 0.0000000001));
                colorDistance = length(colorDiff);
                doReplace = min(1.0, doReplace + step(colorDistance, epsilon));

                gl_FragColor = vec4(mix(col.rgb, fragColor.rgb * col.a, doReplace), col.a);

            }
            `;
        
        super(null, frag);
        
        this.amount = 0.3;
        this.color = new Color(1, 1, 1);
    }

    init(colorA, colorB, colorC, colorD, color, amount = 0.3, epsilon = 0.25)
    {
        this.color = color;
        this.colorA = colorA;
        this.colorB = colorB;
        this.colorC = colorC;
        this.colorD = colorD;
        this.epsilon = epsilon;
        this.amount = amount;
    }

    apply(filterManager, input, output, clear, currentState)
    {
        this.uniforms._Amount = this.amount;
        this.uniforms._Color = [this.color.r, this.color.g, this.color.b];
        this.uniforms.colorA = [this.colorA.r, this.colorA.g, this.colorA.b];
        this.uniforms.colorB = [this.colorB.r, this.colorB.g, this.colorB.b];
        this.uniforms.colorC = [this.colorC.r, this.colorC.g, this.colorC.b];
        this.uniforms.colorD = [this.colorD.r, this.colorD.g, this.colorD.b];
        this.uniforms.epsilon = this.epsilon;

        super.apply(filterManager, input, output, clear, currentState);
    }
}