Using post processing for outlines

I’ve made outline effects before using materials, but I’ve noticed quite a few issues popping up when the sprite is scaled in some form. I’ve been thinking about using post processing to draw the outline by copying the sprite and filling it with one colour, and then shifting those copies in each direction.

This is fairly similar to the shader process I’ve been using, but I can’t for the life of me figure out how to do this with post processing, and I can’t seem to find any tutorials that would be helpful for this task.

Any ideas?

What does it look like now? Not sure I understand what you are after :slight_smile:

Ah, apologies, this is what it looks like:

Here’s the code:

varying mediump vec2 var_texcoord0; // position of sprite colour coordinates
uniform lowp sampler2D texture_sampler; // colour of sprite
uniform lowp vec4 tint; // stores applied sprite colour
uniform lowp vec4 border_width; // stores outline width and state (x and y)
uniform lowp vec4 outline_tint; // stores applied outline colour
uniform lowp vec4 blink_trigger; // stores blinking state
uniform lowp vec4 blink_tint; // stores applied blink colour

void main()
{
	// write a color of the current fragment to a variable (lowp = low precision)
	lowp vec4 tint_applied = vec4(tint.xyz * tint.w, tint.w); // default sprite tint
	lowp vec4 colour_of_pixel = texture2D(texture_sampler, var_texcoord0.xy); // initial pixel colour
	lowp vec4 outline_tint = vec4(outline_tint.xyz * outline_tint.w, outline_tint.w); // colour on outline
	lowp vec3 border_width = vec3(border_width.r,border_width.g,border_width.b);
	lowp vec4 blink_tint = vec4(blink_tint.xyz * blink_tint.w, blink_tint.w); // colour on blink

	if((blink_trigger.r == 1.0) && (colour_of_pixel.a != 0.0))
	{
		colour_of_pixel = vec4(blink_tint.xyz * blink_tint.a * colour_of_pixel.a, blink_tint.a * colour_of_pixel.a); // apply blink colour
	} else {
		if(colour_of_pixel.a >= 0.5) {
			colour_of_pixel = colour_of_pixel * tint_applied; // apply base colour
		} else { // Important code starts here
			if ((texture2D(texture_sampler, vec2(var_texcoord0.x + border_width.x, var_texcoord0.y)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x - border_width.x, var_texcoord0.y)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x, var_texcoord0.y + border_width.z)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x, var_texcoord0.y - border_width.z)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x + border_width.x, var_texcoord0.y + border_width.z)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x + border_width.x, var_texcoord0.y - border_width.z)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x - border_width.x, var_texcoord0.y + border_width.z)).a != 0.0
			|| texture2D(texture_sampler, vec2(var_texcoord0.x - border_width.x, var_texcoord0.y - border_width.z)).a != 0.0)) // Important code ends here
			{
				if (colour_of_pixel.a >= 0.25) {
					colour_of_pixel = colour_of_pixel * vec4(outline_tint.xyz*border_width.y, border_width.y) * tint_applied;
				} else {
					colour_of_pixel = vec4(outline_tint.xyz*border_width.y, border_width.y);
				}
			} else {
				colour_of_pixel = vec4(0.0,0.0,0.0,0.0);
			}
		}
	}
	gl_FragColor = colour_of_pixel;  // write the colour_of_pixel to the output gl_FragColor
}

Some of this code is (quite obviously) taken from the fragment program tutorial. The important code has been marked.

As far as I know(I had the same issue) it is not possible to do it by using atlas(multiple sprites on a sheet). But you can do it by using single sprite image.

2 Likes

I actually am only using a single sprite for each character/object, but my issue is more to do with changing scale, since it shrinks the outline, and it’s locked to the transparent areas of the sprite as it’s a quad, which means that at a small enough scale, the sprite outline will simply fill all of the sprite’s transparent areas.

The only solution I can think of is to create smaller versions of the sprites for each scale, but this would mean I cannot scale the collision shapes without putting them into a separate object. This would cause difficulty with spawning new objects.