diff --git a/src/core/renderers/webgl/managers/StencilManager.js b/src/core/renderers/webgl/managers/StencilManager.js index 2590356..91edfa5 100644 --- a/src/core/renderers/webgl/managers/StencilManager.js +++ b/src/core/renderers/webgl/managers/StencilManager.js @@ -38,7 +38,7 @@ } /** - * Applies the Mask and adds it to the current filter stack. @alvin + * Applies the Mask and adds it to the current stencil stack. @alvin * * @param {PIXI.Graphics} graphics - The mask */ @@ -49,60 +49,75 @@ this.renderer._activeRenderTarget.attachStencilBuffer(); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const prevMaskCount = this.stencilMaskStack.length; - if (sms.length === 0) + if (prevMaskCount === 0) { gl.enable(gl.STENCIL_TEST); - gl.clear(gl.STENCIL_BUFFER_BIT); - gl.stencilFunc(gl.ALWAYS, 1, 1); } - sms.push(graphics); + this.stencilMaskStack.push(graphics); + // Increment the refference stencil value where the new mask overlaps with the old ones. gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); + gl.stencilFunc(gl.EQUAL, prevMaskCount, this._getBitwiseMask()); gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } /** - * TODO @alvin + * Removes the last mask from the stencil stack. @alvin */ popStencil() { this.renderer.setObjectRenderer(this.renderer.plugins.graphics); const gl = this.renderer.gl; - const sms = this.stencilMaskStack; + const graphics = this.stencilMaskStack.pop(); - const graphics = sms.pop(); - - if (sms.length === 0) + if (this.stencilMaskStack.length === 0) { // the stack is empty! gl.disable(gl.STENCIL_TEST); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(0); } else { + // Decrement the refference stencil value where the popped mask overlaps with the other ones gl.colorMask(false, false, false, false); - gl.stencilFunc(gl.EQUAL, 0, sms.length); gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR); - this.renderer.plugins.graphics.render(graphics); - gl.colorMask(true, true, true, true); - gl.stencilFunc(gl.NOTEQUAL, 0, sms.length); - gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + this._useCurrent(); } } /** + * Setup renderer to use the current stencil data. + */ + _useCurrent() + { + const gl = this.renderer.gl; + + gl.colorMask(true, true, true, true); + gl.stencilFunc(gl.EQUAL, this.stencilMaskStack.length, this._getBitwiseMask()); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + } + + /** + * Fill 1s equal to the number of acitve stencil masks. + * + * @return {number} The bitwise mask. + */ + _getBitwiseMask() + { + return (1 << this.stencilMaskStack.length) - 1; + } + + /** * Destroys the mask stack. * */