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.
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.
q1: #extension GL_OES_standard_derivatives : enable
then
replace your magic 0.001 with dFdx(outTexCoord) dFdy(outTexCoord)
BTW: gl_FragColor = color.a * colurU.a * colorD.a * ..... colorR.a == 0. ? color : vec4(1., 0., 0., .2);
ternery condition is faster then IF.
q2:
suggest that use 3.17.0, there is native Shader gameobject to use, so no need to deal with the renderer.
q3:
texturepacker provides such functionality for you, why not use it? shader is still a resource we need to save… if you mean your texture is an atlas, then
outTexCoord *= frameSize / resolution
outTexCoord += framePosition / resolution
q4:
of course, OpenGL even renders gaps if you donot pad some transparent pixels between image blocks.
// in preload method
this.load.glsl("myGlsl", "external_glsl_file.glsl");
// then in create method
const obj = this.add.shader("myGlsl");
obj.setSampler2D(...); // or shortcut methods: setChannel0 / setChannel1 ... setChannel3
obj.setUniform(...);
// and then just treat this obj as an image to use, even add it into a container...
interesting … shader objects native, i blink and it gets 20 more options. Not up to me to tell people how to do what as for one im just a rank amateur hobbyist. Ever since ive seen the shadertoy website coming up on pouet.net glsl has been winking but far from there. In this case, phaser being pretty hungry already i think id just add an extra frame to the spritesheet which (i think) would in the end take up less resources than a ‘subroutine’ (pardon my archaic) calculating one.
ofcourse i do agree : doing it with a shader is lot more pretty (code-wise) but the client/player/user in the end will notice nothing but maybe the amount of cpu used on the device it runs on … mighty interesting though …
This is what I ended up using, be aware that this was for phaser 3.16.2 and used some magic numbers as you can see. I think shader pipelines have changed since then.
It seems like the hardcoded color values could be replaced with uniforms, similar to how tint pipelines pass colors into shaders. That way, the outline color and alpha could be controlled at runtime without modifying the shader each time.