Canvas Group Outline

Adds an outer stroke to a Canvas Group. It works well with pixel art and assets with anti-aliased edges and accounts for the modulate colour.

This shader creates an outline by applying dilation to the Canvas Group’s alpha channel (using a square kernel) and blending colours.

I adapted this shader from other solutions that couldn’t suit my needs. This is also my first shader, any feedback is appreciated!

Shader code
shader_type canvas_item;

uniform vec3 line_colour: source_color = vec3(1.0);
uniform int line_thickness: hint_range(0, 10) = 1;
uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;

void fragment() {
	vec2 size = SCREEN_PIXEL_SIZE * float(line_thickness);
	float line_alpha = 0.0;
	for (float i = -size.x; i <= size.x; i += SCREEN_PIXEL_SIZE.x) {
		for (float j = -size.y; j <= size.y; j += SCREEN_PIXEL_SIZE.y) {
			line_alpha += texture(screen_texture, SCREEN_UV + vec2(i, j)).a;
		}
	}
	vec4 colour = texture(screen_texture, SCREEN_UV);
	vec4 outline = vec4(line_colour, min(line_alpha, 1.0));
	COLOR *= mix(outline, colour, colour.a);
}
Live Preview
Tags
2d, border, CanvasGroup, godot4, outline, stroke
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

Related shaders

guest

8 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Throckmorpheus
1 year ago

If anyone’s having trouble with lights or CanvasModulate being double-applied to things with this shader on, adding ‘render_mode unshaded’ at the top should fix it. Though do note that this means the lights are applied to the canvas group but not the outline, which is right for my use case but may not be right for yours.

reid
1 year ago

cool

Jessesmari
Jessesmari
1 year ago

Hello there! Thank you very much for this Shader. Sadly, I can’t use it because it won’t work with z-Indexed Nodes, meaning Sprite2Ds for example, which have a z-Index other than “0”. My game demands the use of z-Indexes. Could you provide any solution to this? 🙂

Guido
Guido
1 year ago

I see a bug where if the node is zoomed out or in in the editor or in game, the outlines gets bigger or smaller (respectively). Not sure if it’s your code or something about my setup.

circumference
circumference
1 year ago

so cool

manuces
manuces
7 months ago

i would kiss you if i could