- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
import { Filter } from '../Filter';
import type { Point } from '@pixi/math';
import { Matrix } from '@pixi/math';
import type { CLEAR_MODES } from '@pixi/constants';
import vertex from './spriteMaskFilter.vert';
import fragment from './spriteMaskFilter.frag';
import { TextureMatrix } from '../../textures/TextureMatrix';
import type { FilterSystem } from '../FilterSystem';
import type { IMaskTarget } from '../../mask/MaskData';
import type { Texture } from '../../textures/Texture';
import type { RenderTexture } from '../../renderTexture/RenderTexture';
import type { Dict } from '@pixi/utils';
export interface ISpriteMaskTarget extends IMaskTarget
{
_texture: Texture;
worldAlpha: number;
anchor: Point;
}
export interface ISpriteMaskFilter extends Filter
{
maskSprite: IMaskTarget;
}
/**
* This handles a Sprite acting as a mask, as opposed to a Graphic.
*
* WebGL only.
* @memberof PIXI
*/
export class SpriteMaskFilter extends Filter
{
/** @private */
_maskSprite: IMaskTarget;
/** Mask matrix */
maskMatrix: Matrix;
/**
* @param {PIXI.Sprite} sprite - The target sprite.
*/
constructor(sprite: IMaskTarget);
/**
* @param vertexSrc - The source of the vertex shader.
* @param fragmentSrc - The source of the fragment shader.
* @param uniforms - Custom uniforms to use to augment the built-in ones.
*/
constructor(vertexSrc?: string, fragmentSrc?: string, uniforms?: Dict<any>);
/** @ignore */
constructor(vertexSrc?: string | IMaskTarget, fragmentSrc?: string, uniforms?: Dict<any>)
{
let sprite = null;
if (typeof vertexSrc !== 'string' && fragmentSrc === undefined && uniforms === undefined)
{
sprite = vertexSrc as IMaskTarget;
vertexSrc = undefined;
fragmentSrc = undefined;
uniforms = undefined;
}
super(vertexSrc as string || vertex, fragmentSrc || fragment, uniforms);
this.maskSprite = sprite;
this.maskMatrix = new Matrix();
}
/**
* Sprite mask
* @type {PIXI.DisplayObject}
*/
get maskSprite(): IMaskTarget
{
return this._maskSprite;
}
set maskSprite(value: IMaskTarget)
{
this._maskSprite = value;
if (this._maskSprite)
{
this._maskSprite.renderable = false;
}
}
/**
* Applies the filter
* @param filterManager - The renderer to retrieve the filter from
* @param input - The input render target.
* @param output - The target to output to.
* @param clearMode - Should the output be cleared before rendering to it.
*/
apply(filterManager: FilterSystem, input: RenderTexture, output: RenderTexture, clearMode: CLEAR_MODES): void
{
const maskSprite = this._maskSprite as ISpriteMaskTarget;
const tex = maskSprite._texture;
if (!tex.valid)
{
return;
}
if (!tex.uvMatrix)
{
// margin = 0.0, let it bleed a bit, shader code becomes easier
// assuming that atlas textures were made with 1-pixel padding
tex.uvMatrix = new TextureMatrix(tex, 0.0);
}
tex.uvMatrix.update();
this.uniforms.npmAlpha = tex.baseTexture.alphaMode ? 0.0 : 1.0;
this.uniforms.mask = tex;
// get _normalized sprite texture coords_ and convert them to _normalized atlas texture coords_ with `prepend`
this.uniforms.otherMatrix = filterManager.calculateSpriteMatrix(this.maskMatrix, maskSprite)
.prepend(tex.uvMatrix.mapCoord);
this.uniforms.alpha = maskSprite.worldAlpha;
this.uniforms.maskClamp = tex.uvMatrix.uClampFrame;
filterManager.applyFilter(this, input, output, clearMode);
}
}