Fixed Geometry Mask nesting issue.

This commit is contained in:
Richard Davey 2019-04-15 16:46:19 +01:00
parent 974ceb5654
commit 1fc9b15ff1
2 changed files with 102 additions and 23 deletions

View file

@ -89,13 +89,31 @@ var GeometryMask = new Class({
// Force flushing before drawing to stencil buffer
renderer.flush();
// Enable and setup GL state to write to stencil buffer
gl.enable(gl.STENCIL_TEST);
gl.clear(gl.STENCIL_BUFFER_BIT);
if (renderer.maskStack.length === 0)
{
gl.enable(gl.STENCIL_TEST);
gl.clear(gl.STENCIL_BUFFER_BIT);
renderer.maskCount = 0;
renderer.maskReverse = true;
}
renderer.maskStack.push({ mask: this, camera: camera });
var level = renderer.maskCount;
gl.colorMask(false, false, false, false);
gl.stencilFunc(gl.NOTEQUAL, 1, 1);
gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
if (!renderer.maskReverse)
{
gl.stencilFunc(gl.EQUAL, 0xFF - level, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
}
else
{
gl.stencilFunc(gl.EQUAL, level, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
}
// Write stencil buffer
geometryMask.renderWebGL(renderer, geometryMask, 0, camera);
@ -105,16 +123,29 @@ var GeometryMask = new Class({
// Use stencil buffer to affect next rendering object
gl.colorMask(true, true, true, true);
if (this.invertAlpha)
if (!renderer.maskReverse)
{
gl.stencilFunc(gl.NOTEQUAL, 1, 1);
if (this.invertAlpha)
{
gl.stencilFunc(gl.NOTEQUAL, 0xFF - (level + 1), 0xFF);
}
else
{
gl.stencilFunc(gl.EQUAL, 0xFF - (level + 1), 0xFF);
}
}
else if (this.invertAlpha)
{
gl.stencilFunc(gl.NOTEQUAL, level + 1, 0xFF);
}
else
{
gl.stencilFunc(gl.EQUAL, 1, 1);
gl.stencilFunc(gl.EQUAL, level + 1, 0xFF);
}
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
renderer.maskCount++;
},
/**
@ -125,14 +156,67 @@ var GeometryMask = new Class({
*
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to draw flush.
*/
postRenderWebGL: function (renderer)
postRenderWebGL: function (renderer, camera)
{
var gl = renderer.gl;
// Force flush before disabling stencil test
renderer.flush();
gl.disable(gl.STENCIL_TEST);
renderer.maskStack.pop();
renderer.maskCount--;
if (renderer.maskStack.length === 0)
{
gl.disable(gl.STENCIL_TEST);
}
else
{
var level = renderer.maskCount;
gl.colorMask(false, false, false, false);
if (!renderer.maskReverse)
{
gl.stencilFunc(gl.EQUAL, 0xFF - (level + 1), 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
}
else
{
gl.stencilFunc(gl.EQUAL, level + 1, 0xFF);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
}
var geometryMask = this.geometryMask;
geometryMask.renderWebGL(renderer, geometryMask, 0, camera);
renderer.flush();
if (!renderer.maskReverse)
{
if (this.invertAlpha)
{
gl.stencilFunc(gl.NOTEQUAL, 0xFF - (level), 0xFF);
}
else
{
gl.stencilFunc(gl.EQUAL, 0xFF - (level), 0xFF);
}
}
else if (this.invertAlpha)
{
gl.stencilFunc(gl.NOTEQUAL, level, 0xFF);
}
else
{
gl.stencilFunc(gl.EQUAL, level, 0xFF);
}
gl.colorMask(true, true, true, true);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
}
},
/**

View file

@ -479,6 +479,12 @@ var WebGLRenderer = new Class({
*/
this.currentMask = null;
this.maskCount = 0;
this.maskReverse = true;
this.maskStack = [];
this.init(this.config);
},
@ -1966,16 +1972,11 @@ var WebGLRenderer = new Class({
var mask = camera.mask;
mask.preRenderWebGL(this, camera, camera._maskCamera);
// Cameras cannot have child cameras, so each one can clear the mask stack
this.currentMask = mask;
},
clearCameraMask: function (camera)
{
this.currentMask = null;
camera.mask.postRenderWebGL(this);
camera.mask.postRenderWebGL(this, camera._maskCamera);
},
setChildMask: function (renderer, child, interpolationPercentage, camera)
@ -1986,13 +1987,7 @@ var WebGLRenderer = new Class({
child.renderWebGL(renderer, child, interpolationPercentage, camera);
mask.postRenderWebGL(renderer);
// Restore camera mask
if (this.currentMask)
{
this.setCameraMask(camera);
}
mask.postRenderWebGL(renderer, camera);
},
/**