forked from phaserjs/phaser
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBitmapMask.js
More file actions
286 lines (256 loc) · 10.7 KB
/
Copy pathBitmapMask.js
File metadata and controls
286 lines (256 loc) · 10.7 KB
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2019 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
var Class = require('../../utils/Class');
/**
* @classdesc
* A Bitmap Mask combines the alpha (opacity) of a masked pixel with the alpha of another pixel.
* Unlike the Geometry Mask, which is a clipping path, a Bitmap Mask behaves like an alpha mask,
* not a clipping path. It is only available when using the WebGL Renderer.
*
* A Bitmap Mask can use any Game Object to determine the alpha of each pixel of the masked Game Object(s).
* For any given point of a masked Game Object's texture, the pixel's alpha will be multiplied by the alpha
* of the pixel at the same position in the Bitmap Mask's Game Object. The color of the pixel from the
* Bitmap Mask doesn't matter.
*
* For example, if a pure blue pixel with an alpha of 0.95 is masked with a pure red pixel with an
* alpha of 0.5, the resulting pixel will be pure blue with an alpha of 0.475. Naturally, this means
* that a pixel in the mask with an alpha of 0 will hide the corresponding pixel in all masked Game Objects
* A pixel with an alpha of 1 in the masked Game Object will receive the same alpha as the
* corresponding pixel in the mask.
*
* The Bitmap Mask's location matches the location of its Game Object, not the location of the
* masked objects. Moving or transforming the underlying Game Object will change the mask
* (and affect the visibility of any masked objects), whereas moving or transforming a masked object
* will not affect the mask.
*
* The Bitmap Mask will not render its Game Object by itself. If the Game Object is not in a
* Scene's display list, it will only be used for the mask and its full texture will not be directly
* visible. Adding the underlying Game Object to a Scene will not cause any problems - it will
* render as a normal Game Object and will also serve as a mask.
*
* @class BitmapMask
* @memberof Phaser.Display.Masks
* @constructor
* @since 3.0.0
*
* @param {Phaser.Scene} scene - The Scene which this Bitmap Mask will be used in.
* @param {Phaser.GameObjects.GameObject} renderable - A renderable Game Object that uses a texture, such as a Sprite.
*/
var BitmapMask = new Class({
initialize:
function BitmapMask (scene, renderable)
{
var renderer = scene.sys.game.renderer;
/**
* A reference to either the Canvas or WebGL Renderer that this Mask is using.
*
* @name Phaser.Display.Masks.BitmapMask#renderer
* @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)}
* @since 3.11.0
*/
this.renderer = renderer;
/**
* A renderable Game Object that uses a texture, such as a Sprite.
*
* @name Phaser.Display.Masks.BitmapMask#bitmapMask
* @type {Phaser.GameObjects.GameObject}
* @since 3.0.0
*/
this.bitmapMask = renderable;
/**
* The texture used for the mask's framebuffer.
*
* @name Phaser.Display.Masks.BitmapMask#maskTexture
* @type {WebGLTexture}
* @default null
* @since 3.0.0
*/
this.maskTexture = null;
/**
* The texture used for the main framebuffer.
*
* @name Phaser.Display.Masks.BitmapMask#mainTexture
* @type {WebGLTexture}
* @default null
* @since 3.0.0
*/
this.mainTexture = null;
/**
* Whether the Bitmap Mask is dirty and needs to be updated.
*
* @name Phaser.Display.Masks.BitmapMask#dirty
* @type {boolean}
* @default true
* @since 3.0.0
*/
this.dirty = true;
/**
* The framebuffer to which a masked Game Object is rendered.
*
* @name Phaser.Display.Masks.BitmapMask#mainFramebuffer
* @type {WebGLFramebuffer}
* @since 3.0.0
*/
this.mainFramebuffer = null;
/**
* The framebuffer to which the Bitmap Mask's masking Game Object is rendered.
*
* @name Phaser.Display.Masks.BitmapMask#maskFramebuffer
* @type {WebGLFramebuffer}
* @since 3.0.0
*/
this.maskFramebuffer = null;
/**
* The previous framebuffer set in the renderer before this one was enabled.
*
* @name Phaser.Display.Masks.BitmapMask#prevFramebuffer
* @type {WebGLFramebuffer}
* @since 3.17.0
*/
this.prevFramebuffer = null;
/**
* Whether to invert the masks alpha.
*
* If `true`, the alpha of the masking pixel will be inverted before it's multiplied with the masked pixel. Essentially, this means that a masked area will be visible only if the corresponding area in the mask is invisible.
*
* @name Phaser.Display.Masks.BitmapMask#invertAlpha
* @type {boolean}
* @since 3.1.2
*/
this.invertAlpha = false;
/**
* Is this mask a stencil mask?
*
* @name Phaser.Display.Masks.BitmapMask#isStencil
* @type {boolean}
* @readonly
* @since 3.17.0
*/
this.isStencil = false;
if (renderer && renderer.gl)
{
var width = renderer.width;
var height = renderer.height;
var pot = ((width & (width - 1)) === 0 && (height & (height - 1)) === 0);
var gl = renderer.gl;
var wrap = pot ? gl.REPEAT : gl.CLAMP_TO_EDGE;
var filter = gl.LINEAR;
this.mainTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
this.maskTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
this.mainFramebuffer = renderer.createFramebuffer(width, height, this.mainTexture, true);
this.maskFramebuffer = renderer.createFramebuffer(width, height, this.maskTexture, true);
renderer.onContextRestored(function (renderer)
{
var width = renderer.width;
var height = renderer.height;
var pot = ((width & (width - 1)) === 0 && (height & (height - 1)) === 0);
var gl = renderer.gl;
var wrap = pot ? gl.REPEAT : gl.CLAMP_TO_EDGE;
var filter = gl.LINEAR;
this.mainTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
this.maskTexture = renderer.createTexture2D(0, filter, filter, wrap, wrap, gl.RGBA, null, width, height);
this.mainFramebuffer = renderer.createFramebuffer(width, height, this.mainTexture, true);
this.maskFramebuffer = renderer.createFramebuffer(width, height, this.maskTexture, true);
}, this);
}
},
/**
* Sets a new masking Game Object for the Bitmap Mask.
*
* @method Phaser.Display.Masks.BitmapMask#setBitmap
* @since 3.0.0
*
* @param {Phaser.GameObjects.GameObject} renderable - A renderable Game Object that uses a texture, such as a Sprite.
*/
setBitmap: function (renderable)
{
this.bitmapMask = renderable;
},
/**
* Prepares the WebGL Renderer to render a Game Object with this mask applied.
*
* This renders the masking Game Object to the mask framebuffer and switches to the main framebuffer so that the masked Game Object will be rendered to it instead of being rendered directly to the frame.
*
* @method Phaser.Display.Masks.BitmapMask#preRenderWebGL
* @since 3.0.0
*
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The WebGL Renderer to prepare.
* @param {Phaser.GameObjects.GameObject} maskedObject - The masked Game Object which will be drawn.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to.
*/
preRenderWebGL: function (renderer, maskedObject, camera)
{
renderer.pipelines.BitmapMaskPipeline.beginMask(this, maskedObject, camera);
},
/**
* Finalizes rendering of a masked Game Object.
*
* This resets the previously bound framebuffer and switches the WebGL Renderer to the Bitmap Mask Pipeline, which uses a special fragment shader to apply the masking effect.
*
* @method Phaser.Display.Masks.BitmapMask#postRenderWebGL
* @since 3.0.0
*
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The WebGL Renderer to clean up.
*/
postRenderWebGL: function (renderer, camera)
{
renderer.pipelines.BitmapMaskPipeline.endMask(this, camera);
},
/**
* This is a NOOP method. Bitmap Masks are not supported by the Canvas Renderer.
*
* @method Phaser.Display.Masks.BitmapMask#preRenderCanvas
* @since 3.0.0
*
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Canvas Renderer which would be rendered to.
* @param {Phaser.GameObjects.GameObject} mask - The masked Game Object which would be rendered.
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to.
*/
preRenderCanvas: function ()
{
// NOOP
},
/**
* This is a NOOP method. Bitmap Masks are not supported by the Canvas Renderer.
*
* @method Phaser.Display.Masks.BitmapMask#postRenderCanvas
* @since 3.0.0
*
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Canvas Renderer which would be rendered to.
*/
postRenderCanvas: function ()
{
// NOOP
},
/**
* Destroys this BitmapMask and nulls any references it holds.
*
* Note that if a Game Object is currently using this mask it will _not_ automatically detect you have destroyed it,
* so be sure to call `clearMask` on any Game Object using it, before destroying it.
*
* @method Phaser.Display.Masks.BitmapMask#destroy
* @since 3.7.0
*/
destroy: function ()
{
this.bitmapMask = null;
var renderer = this.renderer;
if (renderer && renderer.gl)
{
renderer.deleteTexture(this.mainTexture);
renderer.deleteTexture(this.maskTexture);
renderer.deleteFramebuffer(this.mainFramebuffer);
renderer.deleteFramebuffer(this.maskFramebuffer);
}
this.mainTexture = null;
this.maskTexture = null;
this.mainFramebuffer = null;
this.maskFramebuffer = null;
this.prevFramebuffer = null;
this.renderer = null;
}
});
module.exports = BitmapMask;