Glow shader from PIXI to Cocos2D-JS help

Hello, i try use glow shader for pixi, but it`s not working.


My project: https://github.com/Edisoni/GlowShader-Cocos2d

My files:
FSH:

varying vec2 vTextureCoord;

uniform float distance;
uniform float outerStrength;
uniform float innerStrength;
uniform vec4 glowColor;
uniform vec4 filterArea;
vec2 px = vec2(1.0 / filterArea.x, 1.0 / filterArea.y);

void main(void) {
const float PI = 3.14159265358979323846264;
vec4 ownColor = texture2D(CC_Texture0, vTextureCoord);
vec4 curColor;
float totalAlpha = 0.0;
float maxTotalAlpha = 0.0;
float cosAngle;
float sinAngle;
for (float angle = 0.0; angle <= PI * 2.0; angle += 0.4) {
cosAngle = cos(angle);
sinAngle = sin(angle);
for (float curDistance = 1.0; curDistance <= 5.0; curDistance++) {
curColor = texture2D(CC_Texture0, vec2(vTextureCoord.x + cosAngle * curDistance * px.x, vTextureCoord.y + sinAngle * curDistance * px.y));
totalAlpha += (distance - curDistance) * curColor.a;
maxTotalAlpha += (distance - curDistance);
}
}
maxTotalAlpha = max(maxTotalAlpha, 0.0001);
ownColor.a = max(ownColor.a, 0.0001);
ownColor.rgb = ownColor.rgb / ownColor.a;
float outerGlowAlpha = (totalAlpha / maxTotalAlpha) * outerStrength * (1. - ownColor.a);
float innerGlowAlpha = ((maxTotalAlpha - totalAlpha) / maxTotalAlpha) * innerStrength * ownColor.a;
float resultAlpha = (ownColor.a + outerGlowAlpha);
gl_FragColor = vec4(mix(mix(ownColor.rgb, glowColor.rgb, innerGlowAlpha / ownColor.a), glowColor.rgb, outerGlowAlpha / resultAlpha) * resultAlpha, resultAlpha);
}

VSH:

attribute vec4 a_position;
attribute vec2 a_texCoord;

varying vec2 vTextureCoord;

void main()
{
gl_Position = (CC_PMatrix) * a_position;
vTextureCoord = a_texCoord;
}

JS Code:

var getGlowEffect = function () {
var effect = new cc.GLProgram(res.glow_vsh, res.glow_fsh);
effect.addAttribute(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION);
effect.addAttribute(cc.ATTRIBUTE_NAME_COLOR, cc.VERTEX_ATTRIB_COLOR);
effect.addAttribute(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORDS);
effect.link();

        var distanceUniform = effect.getUniformLocationForName("distance");
        var outerStrength = effect.getUniformLocationForName("outerStrength");
        var innerStrength = effect.getUniformLocationForName("innerStrength");
        var glowColor = effect.getUniformLocationForName("glowColor");
        var filterArea = effect.getUniformLocationForName("filterArea");
        effect.updateUniforms();
        effect.setUniformLocationWith1f(distanceUniform, (30).toFixed(7));
        effect.setUniformLocationWith1f(outerStrength, (2).toFixed(7));
        effect.setUniformLocationWith1f(innerStrength, (10).toFixed(7));
        effect.setUniformLocationWith4f(glowColor, [1.0,0.0,0.0,1.0]);
        effect.setUniformLocationWith4f(filterArea, [1.0,1.0,0.0,0.0]);
        return effect;
    };
    this.sprite = new cc.Sprite(res.HelloWorld_png);
    this.sprite.shaderProgram = getGlowEffect();
    this.sprite.attr({
        x: size.width / 2,
        y: size.height / 2
    });
    this.addChild(this.sprite, 0);

I don’t know what’s the correct final glow effect in PIXI.

But I found a few errors in your code:

  • First, if you want to pass array data to the uniforms, you should change your code
 effect.setUniformLocationWith4f(glowColor, [1.0,0.0,0.0,1.0]);
 effect.setUniformLocationWith4f(filterArea, [1.0,1.0,0.0,0.0]);

to

            effect.setUniformLocationWith4fv(glowColor, [1.0,0.0,0.0,1.0]);
            effect.setUniformLocationWith4fv(filterArea, [1.0,1.0,0.0,0.0]);

Pay attention to the suffix 4f → 4fv

  • Secondly, Sprite use RenderCmd for rendering, so you should pass the shader program to the render command.
        this.sprite._renderCmd._shaderProgram = getGlowEffect();

Here is the test result from my side:

Hope it helps.

The modified vertex shader:

attribute vec4 a_position;
attribute vec2 a_texCoord;
attribute vec4 a_color;

varying lowp vec4 v_fragmentColor;
varying mediump vec2 vTextureCoord;

void main()
{
    gl_Position = CC_PMatrix * a_position;
    vTextureCoord = a_texCoord;
    v_fragmentColor = a_color;
}

The modified fragment shader:

precision lowp float;
varying vec4 v_fragmentColor;
varying vec2 vTextureCoord;

uniform float distance;
uniform float outerStrength;
uniform float innerStrength;
uniform vec4 glowColor;
uniform vec4 filterArea;
vec2 px = vec2(1.0 / filterArea.x, 1.0 / filterArea.y);

void main(void) {
    const float PI = 3.14159265358979323846264;
    vec4 ownColor = v_fragmentColor * texture2D(CC_Texture0, vTextureCoord);
    vec4 curColor;
    float totalAlpha = 0.0;
    float maxTotalAlpha = 0.0;
    float cosAngle;
    float sinAngle;
    for (float angle = 0.0; angle <= PI * 2.0; angle += 0.4) {
       cosAngle = cos(angle);
       sinAngle = sin(angle);
       for (float curDistance = 1.0; curDistance <= 5.0; curDistance++) {
           curColor = texture2D(CC_Texture0, vec2(vTextureCoord.x + cosAngle * curDistance * px.x, vTextureCoord.y + sinAngle * curDistance * px.y));
           totalAlpha += (distance - curDistance) * curColor.a;
           maxTotalAlpha += (distance - curDistance);
       }
    }
    maxTotalAlpha = max(maxTotalAlpha, 0.0001);

    ownColor.a = max(ownColor.a, 0.0001);
    ownColor.rgb = ownColor.rgb / ownColor.a;
    float outerGlowAlpha = (totalAlpha / maxTotalAlpha)  * outerStrength * (1. - ownColor.a);
    float innerGlowAlpha = ((maxTotalAlpha - totalAlpha) / maxTotalAlpha) * innerStrength * ownColor.a;
    float resultAlpha = (ownColor.a + outerGlowAlpha);
    gl_FragColor = vec4(mix(mix(ownColor.rgb, glowColor.rgb, innerGlowAlpha / ownColor.a), glowColor.rgb, outerGlowAlpha / resultAlpha) * resultAlpha, resultAlpha);
}

Hello, in pixi effect

And code:
var sprite = PIXI.Sprite.fromImage(res.helloworld_png);
sprite.x = 300;
sprite.y = 300;
sprite.filters = [new GlowFilter(15, 2, 5, 0xFF0000, 0.5)];
game.stage.addChild(sprite);

In cocos i try your code:


and commit it
https://github.com/Edisoni/GlowShader-Cocos2d/commit/fcec04967a5a6dd9a57c0e0891e7d15bb732185c

You might need to tweak the shader code, I don’t have time to look at the details now.