import Filter from "../Filter";
import { Matrix } from "../../math";
import Sprite from "../../display/Sprite";
import TextureMatrix from "../../texture/TextureMatrix";
import FilterManager from "../../renderers/managers/FilterManager";

const spriteMaskFilterFrag =
    "precision mediump float;" +//片元着色器用到浮点数必须设置精度
    "varying vec2 vMaskCoord;" +
    "varying vec2 vTextureCoord;" +

    "uniform sampler2D uSampler;" +
    "uniform sampler2D mask;" +
    "uniform float alpha;" +
    "uniform vec4 maskClamp;" +

    "void main(void){" +
    "float clip = step(3.5," +
    "step(maskClamp.x, vMaskCoord.x) +" +
    "step(maskClamp.y, vMaskCoord.y) +" +
    "step(vMaskCoord.x, maskClamp.z) +" +
    "step(vMaskCoord.y, maskClamp.w));" +

    "vec4 original = texture2D(uSampler, vTextureCoord);" +
    "vec4 masky = texture2D(mask, vMaskCoord);" +

    // "original *= (masky.r * masky.a * alpha * clip);" +
    "original *= (masky.a * alpha * clip);" +//不管r分量，不晓得为啥干进来

    "gl_FragColor = original;" +
    "}";
const spriteMaskFilterVert =
    "attribute vec2 aVertexPosition;" +
    "attribute vec2 aTextureCoord;" +

    "uniform mat3 projectionMatrix;" +
    "uniform mat3 otherMatrix;" +

    "varying vec2 vMaskCoord;" +
    "varying vec2 vTextureCoord;" +

    "void main(void){" +
    "gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);" +

    "vTextureCoord = aTextureCoord;" +
    "vMaskCoord = ( otherMatrix * vec3( aTextureCoord, 1.0)  ).xy;" +
    "}";

/**
 * The SpriteMaskFilter class
 *
 * @class
 * @extends Filter
 */
export default class SpriteMaskFilter extends Filter {
    maskSprite: Sprite
    maskMatrix: Matrix
    /**
     * @param {Sprite} sprite - the target sprite
     */
    constructor(sprite: Sprite) {
        const maskMatrix = new Matrix();

        super(
            spriteMaskFilterVert,
            spriteMaskFilterFrag
        );

        sprite.renderable = false;

        this.maskSprite = sprite;
        this.maskMatrix = maskMatrix;
    }

    /**
     * Applies the filter
     *
     * @param {FilterManager} filterManager - The renderer to retrieve the filter from
     * @param {RenderTarget} input - The input render target.
     * @param {RenderTarget} output - The target to output to.
     */
    apply(filterManager:FilterManager, input, output) {
        const maskSprite = this.maskSprite;
        const tex = this.maskSprite.texture;
        //如果纹理没有，或者不可用
        if (!tex || !tex.valid) return;

        if (!tex.transform) {
            // margin = 0.0, let it bleed a bit, shader code becomes easier
            // assuming that atlas textures were made with 1-pixel padding
            tex.transform = new TextureMatrix(tex, 0.0);
        }
        tex.transform.update();

        this.uniforms.mask = tex;
        this.uniforms.otherMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, maskSprite)
            .prepend(tex.transform.mapCoord);
        this.uniforms.alpha = maskSprite._worldAlpha;
        this.uniforms.maskClamp = tex.transform.uClampFrame;

        filterManager.applyFilter(this, input, output);
    }
}
