Ring of Power

It’s a simple ring that can be used as an indicator (of an activated power, for instance). It uses a noise texture and additive blend for best result.

I recommend to use a tween or an animation player to add some dynamics.

Parameters are:

  • radius : Must be in ]0, 1]. Be careful to not overshoot when add the thickness. Radius plus thickness should be less than 1.
  • thickness : Must be in ]0, 1]. Thickness of the ring.
  • color : Obviously, the tint of the ring.
  • brightness : Color intensity multiplier.
  • angular_speed : Rotation speed of the ring (in rad/s).
  • radial_speed : Speed of the texture slide (in or out).
  • alpha : Alpha channel override.
  • noise : An seamless noise texture is preferred. But any seamless function can work (did i mention that it must be seamless ?).

Note : When using Godot 4.x, replace hint_color at line 8 with source_color. (Thx jboadas)

 
Shader code
shader_type canvas_item;
render_mode blend_add;

uniform float radius : hint_range(0.0, 1.0, 0.01) = .7;

uniform float thickness : hint_range(0.0, 1.0, 0.01) = .2;

uniform vec4 color : hint_color = vec4(0.9, 0.4, 0.1, 1.0);

uniform float brightness : hint_range(0.0, 15.0, 0.01) = 5.0;

uniform float angular_speed : hint_range(-5.0, 5.0, 0.01) = 2.5;

uniform float radial_speed : hint_range(-5.0, 5.0, 0.01) = 1.4;

uniform float alpha : hint_range(0.0, 1.0, 0.01) = .5;

uniform sampler2D noise;

void fragment() {
	vec2 v = vec2(.5) - UV;
	float d = length(v) * 2.;
	float angle = atan(v.y, v.x) + (TIME * angular_speed);
	float thick_ratio = 1. - (abs(d - max(0., radius)) / max(.0001, thickness));
	vec2 polar = fract(vec2(angle / 6.28, d + (TIME * radial_speed)));
	vec4 col = thick_ratio * brightness * color;
	vec3 tex = texture(noise, polar).rgb;
	col.a = (alpha * (tex.r + tex.g + tex.b) * clamp(thick_ratio, 0., 1.)) / 3.;
	COLOR = col;
}
Tags
colorful, motion, noise, ring
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.

More from CasualGarageCoder

2D Fountain

(Almost) Invisible Character

Shield with impact waves

Subscribe
Notify of
guest

11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Mike
Mike
8 months ago

Cool! Thank you very much!

jboadas
8 months ago

Cannot make it work, it says:

res://shaders/power_ring.gdshader:8 - Expected valid type hint after ':'.
 Shader compilation failed.
E  8-> uniform vec4 color : hint_color = vec4(0.9, 0.4, 0.1, 1.0);
jboadas
8 months ago
Reply to  jboadas

In Godot 4 hint_color has been renamed to source_color

jboadas
8 months ago
Reply to  jboadas

After replace hint_color with source_color it works, beautiful shader, Very Thanks

RoseBloom
RoseBloom
7 months ago

Thank you very much!

orbital_comma
orbital_comma
7 months ago

This stops working after one rotation unless I fract polar, like

vec2 polar = fract(vec2(angle / 6.28, d + (TIME * radial_speed));

My noise texture would need to repeat infinitely for texture(noise, polar) to be able to pull noise with arbitrarily large polar.x and polar.y values.

I’m sure I’m missing a setting that does this… I have ‘seamless’ checked. Any idea what I’m missing?

lvar999
lvar999
10 days ago

่ฟ™ไธชๆ•ˆๆžœ็œŸไธ้”™