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);
}
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

2D Canvas Group Tint

electric ball canvas item

Various Canvas Outlines

Subscribe
Notify of
guest

6 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Throckmorpheus
15 days 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
2 months ago

cool

Jessesmari
Jessesmari
1 month 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 month 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.