import Filter from './Filter';
import { Matrix } from '../../../math';
import TextureTransform from '../../../textures/TextureTransform';
const spriteMaskFilter = {
frag: `
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);
gl_FragColor = original;
}
`,
vert: `
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 Tiny.Filter
* @memberof Tiny
*/
export default class SpriteMaskFilter extends Filter {
/**
* @param {Tiny.Sprite} sprite - the target sprite
*/
constructor(sprite) {
const maskMatrix = new Matrix();
super(
spriteMaskFilter.vert,
spriteMaskFilter.frag
);
sprite.renderable = false;
this.maskSprite = sprite;
this.maskMatrix = maskMatrix;
}
/**
* Applies the filter
*
* @param {Tiny.FilterManager} filterManager - The renderer to retrieve the filter from
* @param {Tiny.RenderTarget} input - The input render target.
* @param {Tiny.RenderTarget} output - The target to output to.
* @param {boolean} clear - Should the output be cleared before rendering to it
*/
apply(filterManager, input, output, clear) {
const maskSprite = this.maskSprite;
const tex = this.maskSprite.texture;
if (!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 TextureTransform(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, clear);
}
}