Hey guys,
I am looking into outlining sprites using a shader - I am not an expert on shaders at all.
I looked around a bit (googlefu) but did not find any already existing solution.
This is what I got so far:
solid color:
alpha color:
slightly more complex shape:
Here is the shader code:
class OutlinePipeline extends Phaser.Renderer.WebGL.Pipelines.TextureTintPipeline {
constructor(game: Phaser.Game) {
let config = {game: game,
renderer: game.renderer,
fragShader: `
precision mediump float;
uniform sampler2D uMainSampler;
varying vec2 outTexCoord;
void main(void) {
vec4 color = texture2D(uMainSampler, outTexCoord);
vec4 colorU = texture2D(uMainSampler, vec2(outTexCoord.x, outTexCoord.y - 0.001));
vec4 colorD = texture2D(uMainSampler, vec2(outTexCoord.x, outTexCoord.y + 0.001));
vec4 colorL = texture2D(uMainSampler, vec2(outTexCoord.x + 0.001, outTexCoord.y));
vec4 colorR = texture2D(uMainSampler, vec2(outTexCoord.x - 0.001, outTexCoord.y));
gl_FragColor = color;
if (color.a == 0.0 && (colorU.a != 0.0 || colorD.a != 0.0 || colorL.a != 0.0 || colorR.a != 0.0) ) {
gl_FragColor = vec4(1.0, 0.0, 0.0, .2);
}
}`};
super(config);
}
}
To get this to run:
in create:
(<Phaser.Renderer.WebGL.WebGLRenderer>this.game.renderer).addPipeline('outline', new OutlinePipeline(this.game));
And to activate / deactivate it on a sprite:
this.sprite.setPipeline("outline");
this.sprite.resetPipeline();
And here are the problems I am looking for input on
-
“0.001” is a magic value that works for texture lookup on 1024 x 1024 textures.
Found it just by trying - there should be a way to get the texture size and calculate this value. -
The color & alpha are hard coded into the shader - I guess I should have a look on how the tint pipline get’s the values into the shader
-
When looking up the pixels, at the border we look up pixels of other sprites - for that reason there needs to be padding (at least 1 pixel) on the sprite sheet, I don’t know if this could be restricted to only lookup within the sprite itself.
-
For this to work a 1 pixel transparent border around the picture as part of the sprite is needed. (though I think this is ok and kind of expected)
-
With some tinkering I guess with this method a glow is possible (lookup further out, different alphas)
Feedback or tips on any of the points is very welcome.