Rainbow Border

A rotating rainbow border I made for my Shop UI in my first ever game, TRASH HERO.

You can set the size of the border via:
ShaderMaterial.set_shader_parameter("node_size", size)

Shader code
shader_type canvas_item;

/// Width of the shimmering rainbow border in pixels.
uniform float border_px : hint_range(2.0, 24.0) = 2.0;
/// Animation speed — higher values spin the hue faster.
uniform float speed : hint_range(0.1, 4.0) = 0.9;
/// Brightness multiplier applied to the rainbow colour (creates a glow effect).
uniform float glow_intensity : hint_range(1.0, 3.5) = 2.0;
/// Actual pixel dimensions of the node this material is applied to.
/// Set from GDScript via ShaderMaterial.set_shader_parameter("node_size", size).
uniform vec2 node_size = vec2(64.0, 64.0);

/// Converts an HSV colour to RGB.
vec3 hsv_to_rgb(vec3 c) {
	vec4 k = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
	vec3 p = abs(fract(c.xxx + k.xyz) * 6.0 - k.www);
	return c.z * mix(k.xxx, clamp(p - k.xxx, 0.0, 1.0), c.y);
}

void fragment() {
	// Convert UV to pixel coordinates relative to this node.
	vec2 pixel = UV * node_size;

	// Distance from the nearest edge in pixels.
	float dist_left   = pixel.x;
	float dist_right  = node_size.x - pixel.x;
	float dist_top    = pixel.y;
	float dist_bottom = node_size.y - pixel.y;
	float edge_dist   = min(min(dist_left, dist_right), min(dist_top, dist_bottom));

	if (edge_dist > border_px) {
		// Centre of the banner is fully transparent — only the border band is drawn.
		COLOR = vec4(0.0);
	} else {
		// Animated hue: TIME drives the global spin; position offsets phase so
		// the colour travels around the border rather than flashing uniformly.
		// Guard the divisor against zero so we never produce NaN during the one
		// frame when node_size may not yet have been set from GDScript.
		float denom  = max(node_size.x + node_size.y, 1.0);
		float phase   = (pixel.x + pixel.y) / denom;
		float hue     = fract(TIME * speed * 0.25 + phase);
		vec3  rainbow = hsv_to_rgb(vec3(hue, 1.0, 1.0));

		// Alpha fades from full at the very edge to zero at the inner boundary,
		// giving a soft inner glow rather than a harsh cut.
		float alpha = 1.0 - smoothstep(0.0, border_px, edge_dist);
		alpha = pow(alpha, 0.5);

		COLOR = vec4(rainbow * glow_intensity, alpha * 0.92);
	}
}
Live Preview
Tags
border, rainbow, Shiny
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

0 Comments
Oldest
Newest Most Voted