phaserjs / phaser-ce

Phaser CE is a fun, free and fast 2D game framework for making HTML5 games for desktop and mobile web browsers, supporting Canvas and WebGL rendering.
http://phaser.io
MIT License
1.34k stars 491 forks source link

Applying a Filter to a Group breaks mask #173

Open Xan0C opened 7 years ago

Xan0C commented 7 years ago

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]

samme commented 7 years ago

In v2.7.7: https://codepen.io/samme/pen/gWGgaB

samid737 commented 6 years ago

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)..

Xan0C commented 6 years ago

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);
        }
    }

};
ndee85 commented 5 years ago

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?

ndee85 commented 5 years ago

@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.