Edisoni
February 11, 2017, 10:00am
#1
Hello, i try use glow shader for pixi, but it`s not working.
varying vec2 vTextureCoord;
varying vec4 vColor;
uniform sampler2D uSampler;
uniform float distance;
uniform float outerStrength;
uniform float innerStrength;
uniform vec4 glowColor;
uniform vec4 filterArea;
uniform vec4 filterClamp;
vec2 px = vec2(1.0 / filterArea.x, 1.0 / filterArea.y);
void main(void) {
const float PI = 3.14159265358979323846264;
vec4 ownColor = texture2D(uSampler, vTextureCoord);
vec4 curColor;
float totalAlpha = 0.0;
float maxTotalAlpha = 0.0;
float cosAngle;
This file has been truncated. show original
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);
owen
February 13, 2017, 4:04am
#2
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.
owen
February 13, 2017, 5:37am
#3
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);
}
Edisoni
February 13, 2017, 10:04am
#4
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
owen
February 13, 2017, 10:12am
#5
You might need to tweak the shader code, I don’t have time to look at the details now.