Source: tiny/core/renderers/webgl/filters/SpriteMaskFilter.js

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);
  }
}
Documentation generated by JSDoc 3.4.3 on Fri Jul 09 2021 19:32:25 GMT+0800 (CST)