Newer
Older
pixi.js / src / pixi / renderers / webgl / utils / WebGLMaskManager.js
@mathew groves mathew groves on 15 May 2014 6 KB Added Complex Graphics
/**
 * @author Mat Groves http://matgroves.com/ @Doormat23
 */
 
//BA0285
//Intercontinental Hotel, 888 Howard Street
//San Francisco

/**
* @class WebGLMaskManager
* @constructor
* @param gl {WebGLContext} the current WebGL drawing context
* @private
*/
PIXI.WebGLMaskManager = function(gl)
{
    this.maskStack = [];
    this.maskPosition = 0;

    this.setContext(gl);

    this.reverse = false;
    this.count = 0;
};  

/**
* Sets the drawing context to the one given in parameter
* @method setContext 
* @param gl {WebGLContext} the current WebGL drawing context
*/
PIXI.WebGLMaskManager.prototype.setContext = function(gl)
{
    this.gl = gl;
};

/**
* Applies the Mask and adds it to the current filter stack
* @method pushMask
* @param maskData {Array}
* @param renderSession {RenderSession}
*/
PIXI.WebGLMaskManager.prototype.pushMask = function(maskData, renderSession)
{
    this.count = 0;
    this.pushMaskReal(maskData, renderSession);

    return;
    this.maskStack.push(maskData);

    
    this.popMaskReal(maskData, renderSession);

    maskData.worldTransform.tx += 30;
    
    this.pushMaskReal(maskData, renderSession);
    //this.popMaskReal(maskData, renderSession);

    maskData.worldTransform.tx -= 30;

    maskData.worldTransform.tx += -50;
    
    //this.pushMaskReal(maskData, renderSession);
    //this.popMaskReal(maskData, renderSession);

    maskData.worldTransform.tx -= -50;


    return;
    var gl = this.gl;


    if(this.maskStack.length === 0)
    {
        gl.enable(gl.STENCIL_TEST);
        gl.stencilFunc(gl.ALWAYS,1,1);
    }
    
    //  maskData.visible = false;

    this.maskStack.push(maskData);
    gl.clear(gl.STENCIL_BUFFER_BIT);

    gl.colorMask(false, false, false, false);
    
    // draw that mask! 
    
    gl.stencilFunc(gl.ALWAYS,1,0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
    PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);


    gl.stencilFunc(gl.EQUAL,0xFF, 0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
    PIXI.WebGLGraphics.renderGraphicsQuadMask(maskData, renderSession);

    // second mask
    
    maskData.worldTransform.tx += 10;

    gl.stencilFunc(gl.ALWAYS,1,0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT); 

    PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);
    

    gl.stencilFunc(gl.EQUAL, 1, 0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);
    PIXI.WebGLGraphics.renderGraphicsQuadMask(maskData, renderSession);

    maskData.worldTransform.tx -= 10;

    // 3rd..
    
    maskData.worldTransform.tx -= 50;

    gl.stencilFunc(gl.ALWAYS,1,0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
    PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);


    gl.stencilFunc(gl.EQUAL,0xFF-2, 0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);
    PIXI.WebGLGraphics.renderGraphicsQuadMask(maskData, renderSession);

    maskData.worldTransform.tx += 50;

/*
    //  PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);


    // first mask is a freebee!
    if(this.maskStack.length === 1)
    {

    }
    else
    {
        //gl.colorMask(false, false, false, false);
        //gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);   
    }

    */
   
    gl.colorMask(true, true, true, true);
    gl.stencilFunc(gl.EQUAL,0xFF-3, 0xFF);///this.maskStack.length);
   // gl.stencilFunc(gl.EQUAL,2, 0xFF)
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
};

PIXI.WebGLMaskManager.prototype.pushMaskReal = function(maskData, renderSession)
{
    var gl = this.gl;
    this.maskStack.push(maskData);
  //  console.log(this.maskStack.length, this.count++)
    var level = this.count++;
    var reverse = !(level % 2);
  
    if(level === 0)
    {
        gl.enable(gl.STENCIL_TEST);
        gl.stencilFunc(gl.ALWAYS,1,1);
        gl.clear(gl.STENCIL_BUFFER_BIT);
    }
    

    gl.colorMask(false, false, false, false); 
    
    gl.stencilFunc(gl.ALWAYS,0,0xFF);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
    PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);
   
    if(reverse)
    {
        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);      
    }

    PIXI.WebGLGraphics.renderGraphicsQuadMask(maskData, renderSession);

    if(reverse)
    {
        gl.stencilFunc(gl.EQUAL,0xFF-(level+1), 0xFF)
    }
    else
    {
        gl.stencilFunc(gl.EQUAL,level+1, 0xFF)
    }

    gl.colorMask(true, true, true, true);
    gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
}



/**
* Removes the last filter from the filter stack and doesn't return it
* @method popMask
*
* @param renderSession {RenderSession} an object containing all the useful parameters
*/
PIXI.WebGLMaskManager.prototype.popMask = function(renderSession)
{
    this.popMaskReal(renderSession);
    return;
   // return;
    var gl = this.gl;

    var maskData = this.maskStack.pop();

    if(maskData)
    {
        gl.colorMask(false, false, false, false);

        //gl.stencilFunc(gl.ALWAYS,1,1);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);

        PIXI.WebGLGraphics.renderGraphics(maskData, renderSession);

        gl.colorMask(true, true, true, true);
        gl.stencilFunc(gl.LESS,0,this.maskStack.length);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);
    }
   
    if(this.maskStack.length === 0)gl.disable(gl.STENCIL_TEST);
};

PIXI.WebGLMaskManager.prototype.popMaskReal = function(renderSession)
{
    var gl = this.gl;
    var maskData = this.maskStack.pop();

    var level = this.count;
    var reverse = !(this.count % 2);
  

    /*if(level === 0)
    {
        gl.enable(gl.STENCIL_TEST);
        gl.stencilFunc(gl.ALWAYS,1,1);
        gl.clear(gl.STENCIL_BUFFER_BIT);
    }*/

    if(maskData)
    {

        gl.colorMask(false, false, false, false); 
        
         if(!reverse)
        {
            gl.stencilFunc(gl.EQUAL, 0xFF - level, 0xFF);
            gl.stencilOp(gl.KEEP,gl.KEEP,gl.INCR);      
        }
        else
        {
            gl.stencilFunc(gl.EQUAL,level, 0xFF);
            gl.stencilOp(gl.KEEP,gl.KEEP,gl.DECR);      
        }

        PIXI.WebGLGraphics.renderGraphicsQuadMask(maskData, renderSession);

        gl.stencilFunc(gl.ALWAYS,0,0xFF);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.INVERT);
        PIXI.WebGLGraphics.renderGraphicsMask(maskData, renderSession);
       
    }
    
    if(level === 0)
    {
        //console.log(">>")
        gl.disable(gl.STENCIL_TEST);
    }
    else
    {  

        if(reverse)
        {
            gl.stencilFunc(gl.EQUAL,0xFF-(level-1), 0xFF)
        }
        else
        {
            gl.stencilFunc(gl.EQUAL,level-1, 0xFF)
        }

        gl.colorMask(true, true, true, true);
        gl.stencilOp(gl.KEEP,gl.KEEP,gl.KEEP);

    }   

    this.count--;
}

/**
* Destroys the mask stack
* @method destroy
*/
PIXI.WebGLMaskManager.prototype.destroy = function()
{
    this.maskStack = null;
    this.gl = null;
};