J
JayR
Guest
I have overlapping sprites consisting of Head, 4 Limbs and a Torso that makes up a character. I would like to create a border around this character as a whole and not on its individual sprites as it is overlapping which looks funky.
I used surfaces with the masking technique and it works like a charm. Sadly, to create the surface I had to draw the 6 sprites in 8 directions with offset to create the surface which proves to be extremely slow on my phone.
Decided to go with shaders. I have a shader but it only draws a border on the individual sprite and not as a whole. Can anyone help me on this?
I used surfaces with the masking technique and it works like a charm. Sadly, to create the surface I had to draw the 6 sprites in 8 directions with offset to create the surface which proves to be extremely slow on my phone.
Decided to go with shaders. I have a shader but it only draws a border on the individual sprite and not as a whole. Can anyone help me on this?
Code:
//
// Simple passthrough vertex shader
//
attribute vec3 in_Position; // (x,y,z)
//attribute vec3 in_Normal; // (x,y,z) unused in this shader.
attribute vec4 in_Colour; // (r,g,b,a)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
void main() {
vec4 object_space_pos = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0);
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
v_vColour = in_Colour;
v_vTexcoord = in_TextureCoord;
}
Code:
//
// Sprite outline shader
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform float outlineRadius;
void maxAlphaAround(inout float alpha) {
for(float i = 0.0; i < 5.0; ++i) {
float xx = floor(sqrt(outlineRadius * outlineRadius - (i * outlineRadius) * (i * outlineRadius)));
alpha = max(alpha, texture2D(gm_BaseTexture, v_vTexcoord + vec2(xx, outlineRadius - xx)).a);
alpha = max(alpha, texture2D(gm_BaseTexture, v_vTexcoord + vec2(outlineRadius - xx, xx)).a);
alpha = max(alpha, texture2D(gm_BaseTexture, v_vTexcoord - vec2(xx, outlineRadius - xx)).a);
alpha = max(alpha, texture2D(gm_BaseTexture, v_vTexcoord - vec2(outlineRadius - xx, xx)).a);
}
}
void minAlphaAround(inout float alpha) {
for(float i = 0.0; i < 5.0; ++i) {
float xx = floor(sqrt(outlineRadius * outlineRadius - (i * outlineRadius) * (i * outlineRadius)));
alpha = min(alpha, texture2D(gm_BaseTexture, v_vTexcoord + vec2(xx, outlineRadius - xx)).a);
alpha = min(alpha, texture2D(gm_BaseTexture, v_vTexcoord + vec2(outlineRadius - xx, xx)).a);
alpha = min(alpha, texture2D(gm_BaseTexture, v_vTexcoord - vec2(xx, outlineRadius - xx)).a);
alpha = min(alpha, texture2D(gm_BaseTexture, v_vTexcoord - vec2(outlineRadius - xx, xx)).a);
}
}
void main() {
gl_FragColor = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);
float alpha = texture2D(gm_BaseTexture, v_vTexcoord).a;
if(alpha == 0.0) {
// potential for being a border
maxAlphaAround(alpha);
gl_FragColor = vec4(0, 0, 0, alpha);
} else if(alpha != 1.0) {
// already kind of transparent
minAlphaAround(alpha);
if(alpha == 0.0) {
// this is near an edge, but was transparent
gl_FragColor = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord) * texture2D(gm_BaseTexture, v_vTexcoord).aaaa;
gl_FragColor.a = 1.0;
}
}
}