mutoo
5/19/2014 - 8:44 AM

blurred-modal-background-in-cocos2d-js

blurred-modal-background-in-cocos2d-js

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;
varying lowp vec4 v_fragmentColor;
varying mediump vec2 v_texCoord;
void main()
{
    gl_Position = (CC_PMatrix * CC_MVMatrix) * a_position;
    v_fragmentColor = a_color;
    v_texCoord = a_texCoord;
}
precision lowp float;
varying vec4 v_fragmentColor;
varying vec2 v_texCoord;

uniform sampler2D CC_Texture0;
uniform float resolution;
uniform float radius;
uniform vec2 dir;

void main() {
    //this will be our RGBA sum
    vec4 sum = vec4(0.0);
    
    //our original texcoord for this fragment
    vec2 tc = v_texCoord;
    
    //the amount to blur, i.e. how far off center to sample from 
    //1.0 -> blur by one pixel
    //2.0 -> blur by two pixels, etc.
    float blur = radius/resolution; 
    
    //the direction of our blur
    //(1.0, 0.0) -> x-axis blur
    //(0.0, 1.0) -> y-axis blur
    float hstep = dir.x;
    float vstep = dir.y;

    //apply blurring, using a 15-tap filter with predefined gaussian weights
    sum += texture2D(CC_Texture0, vec2(tc.x - 7.0*blur*hstep, tc.y - 7.0*blur*vstep)) * 0.0044299121055113265;
    sum += texture2D(CC_Texture0, vec2(tc.x - 6.0*blur*hstep, tc.y - 6.0*blur*vstep)) * 0.00895781211794;
    sum += texture2D(CC_Texture0, vec2(tc.x - 5.0*blur*hstep, tc.y - 5.0*blur*vstep)) * 0.0215963866053;
    sum += texture2D(CC_Texture0, vec2(tc.x - 4.0*blur*hstep, tc.y - 4.0*blur*vstep)) * 0.0443683338718;
    sum += texture2D(CC_Texture0, vec2(tc.x - 3.0*blur*hstep, tc.y - 3.0*blur*vstep)) * 0.0776744219933;
    sum += texture2D(CC_Texture0, vec2(tc.x - 2.0*blur*hstep, tc.y - 2.0*blur*vstep)) * 0.115876621105;
    sum += texture2D(CC_Texture0, vec2(tc.x - 1.0*blur*hstep, tc.y - 1.0*blur*vstep)) * 0.147308056121;
    sum += texture2D(CC_Texture0, vec2(tc.x, tc.y)) * 0.159576912161;
    sum += texture2D(CC_Texture0, vec2(tc.x + 1.0*blur*hstep, tc.y + 1.0*blur*vstep)) * 0.147308056121;
    sum += texture2D(CC_Texture0, vec2(tc.x + 2.0*blur*hstep, tc.y + 2.0*blur*vstep)) * 0.115876621105;
    sum += texture2D(CC_Texture0, vec2(tc.x + 3.0*blur*hstep, tc.y + 3.0*blur*vstep)) * 0.0776744219933;
    sum += texture2D(CC_Texture0, vec2(tc.x + 4.0*blur*hstep, tc.y + 4.0*blur*vstep)) * 0.0443683338718;
    sum += texture2D(CC_Texture0, vec2(tc.x + 5.0*blur*hstep, tc.y + 5.0*blur*vstep)) * 0.0215963866053;
    sum += texture2D(CC_Texture0, vec2(tc.x + 6.0*blur*hstep, tc.y + 6.0*blur*vstep)) * 0.00895781211794;
    sum += texture2D(CC_Texture0, vec2(tc.x + 7.0*blur*hstep, tc.y + 7.0*blur*vstep)) * 0.0044299121055113265;
    
    //discard alpha for our simple demo, multiply by vertex color and return
    gl_FragColor = v_fragmentColor * vec4(sum.rgb, 1.0);
}
var LayerBlur = cc.Layer.extend({
    ctor: function (blurRadius, maskColor) {
        this._super();

        // create shader program
        var program = cc.GLProgram.create(res.blur_vsh, res.blur_fsh);
        program.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
        program.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
        program.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
        program.link();
        program.updateUniforms();

        // define custom uniforms
        var resolutionUni = program.getUniformLocationForName("resolution");
        var radiusUni = program.getUniformLocationForName("radius");
        var dirUni = program.getUniformLocationForName("dir");

        // draw current scene into render_texture
        var bgTex = cc.RenderTexture.create(cc.visibleRect.width, cc.visibleRect.height);
        bgTex.begin();
        cc.director.getRunningScene().visit();
        bgTex.end();

        // step 1: do horizontal blur on bgTex

        // setup uniform
        program.use();
        program.setUniformLocationF32(resolutionUni, cc.visibleRect.width);
        program.setUniformLocationWith2f(dirUni, 1, 0);
        program.setUniformLocationF32(radiusUni, blurRadius);

        var horizontalBlur = cc.Sprite.create(bgTex.getSprite().getTexture());
        horizontalBlur.attr({anchorX: 0, anchorY: 0});
        horizontalBlur.shaderProgram = program;

        var horizontalBlurTex = cc.RenderTexture.create(cc.visibleRect.width, cc.visibleRect.height);
        horizontalBlurTex.begin();
        horizontalBlur.visit();
        horizontalBlurTex.end();

        // step 2: do vertical blur on horizontalBlurTex
        program.use();
        program.setUniformLocationF32(resolutionUni, cc.visibleRect.height);
        program.setUniformLocationWith2f(dirUni, 0, 1);

        var verticalBlur = cc.Sprite.create(horizontalBlurTex.getSprite().getTexture());
        verticalBlur.attr({anchorX: 0, anchorY: 1, scaleY: -1});
        verticalBlur.shaderProgram = program;

        bgTex.begin();
        verticalBlur.visit();
        bgTex.end();

        // blurred
        var result = cc.Sprite.create(bgTex.getSprite().getTexture());
        result.attr({anchorX: 0, anchorY: 0});
        this.addChild(result);

        // add mask color if needed
        if (maskColor) {
            this.addChild(
                cc.LayerColor.create(maskColor, cc.visibleRect.width, cc.visibleRect.height)
            );
        }
    }
});

LayerBlur.defaultBlurRadius = 0.75;
LayerBlur.create = function (blurRadius, maskColor) {
    return new LayerBlur(blurRadius, maskColor);
};