phaser-ce
phaser-ce copied to clipboard
Applying a Filter to a Group breaks mask
- A bug in the API:
- Phaser version(s): 2.7.6 probably >= 2.7
- Live example: https://codepen.io/Nan0C/pen/RVabZZ
- Reproduce: a. Create a Group with one or more sprites b. Apply a Filter and mask to the group
- What should happen: Filter and mask should be applied to the group. The gray boxes should only be visible above the green line
- What happens instead: Applying a filter breaks the mask applied to the group. The boxes are visible under the green line
This issue has probably something to do with the issues #39 #153 #154
I assume its a problem with the WebGLSpriteBatch or the FilterManager, since the bug happens after the PIXI.DisplayObjectContainer.prototype._renderWebGL method. Commenting out the parts where a Filter is applied makes the mask work again(obviously because its not used)[DisplayObjectContainer.js#L500]
In v2.7.7: https://codepen.io/samme/pen/gWGgaB
In 2.8.3, it seems to work when applying the same mask and filter to each child (using group.setAll):
https://codepen.io/Samid737/pen/qXOxRE
This does not work in 2.7.7 however and im not sure if it is desirable (performance)..
changing the order to first apply the mask and then the filter fixes it for this case. However in the game we have with lots of nested groups, it does not. And its probably a bad idea to just change the order. I also tried to figure out how the FilterManager and MaskManager work but only understood half of it.
https://codepen.io/Nan0C/pen/vJNjxq
PIXI.DisplayObjectContainer.prototype._renderWebGL = function (renderSession) {
if (!this.visible || this.alpha <= 0)
{
return;
}
if (this._cacheAsBitmap)
{
this._renderCachedSprite(renderSession);
return;
}
var i;
if (this._mask || this._filters)
{
// push filter first as we need to ensure the stencil buffer is correct for any masking
//Totally ignore the previous comment and do the opposite.
//shouldnt the stencil buffer be applied before masking?
//so rendering the filterpass already applies the mask?
if (this._mask) {
renderSession.spriteBatch.stop();
renderSession.maskManager.pushMask(this.mask, renderSession);
renderSession.spriteBatch.start();
}
if(this._filters) {
renderSession.spriteBatch.flush();
renderSession.filterManager.pushFilter(this._filterBlock);
}
// simple render children!
for (i = 0; i < this.children.length; i++)
{
this.children[i]._renderWebGL(renderSession);
}
renderSession.spriteBatch.stop();
if (this._filters) renderSession.filterManager.popFilter();
if (this._mask) renderSession.maskManager.popMask(this._mask, renderSession);
renderSession.spriteBatch.start();
}
else
{
// simple render children!
for (i = 0; i < this.children.length; i++)
{
this.children[i]._renderWebGL(renderSession);
}
}
};
I want to bring this issue up again. We are trying to port our framework we build ontop of phaser 2.6.2. Trying to use the latest phaser ce 2.11.1 version. We have the exact same problem. Mask do work fine in general. But as soon as we apply a filter to a group, the mask dissappears and reveals the whole group. Could it be related to #334
I tried the suggestions mentioned above, but none did help. Any suggestions, maybe there is a workaround? Or could this be a bug?
@samme @samid737 @photonstorm I did try out the solution of @Xan0C and change the order of applying the filter and mask (for testing purpose in the phaser.js). For both. DisplayObjectContainer and the Sprite object. It seems to work.
The comment explicitely says, that filter needs to be applied first in order for the stencil buffer being calculated correctly. But it seems this isn't the case. Flipping the order did help here. Refering to the examples mentioned above, the mask is applied first to, and afterwards the filter.
Would this be a viable solution to fix masks working together with filters? Any thoughts from more experienced phaser user? If any other solution would make more sense, I would be happy for some hints from your side.