Ring / Wave shader

A spatial shader that draws rings on a 3D plane. (With a few changes it can be also applied to canvas items)

There are various parameters in the shader material that can be customized.

Quick setup: Create a MeshInstance3D with a PlaneMesh and assign the material as material override.

Shader code
shader_type spatial;
render_mode unshaded;

/*
RING SHADER
*/


uniform vec3 ring_color: source_color = vec3(1.0);
uniform float ring_frequency = 50.0;
/** Portion of the visible rings. Negative values give wider rings, positive values give narrower rings*/
uniform float ring_portion: hint_range(-0.9, 0.9, 0.1) = 0.0;
/** Negative values move the rings outwards, positive value move the rings inwards */
uniform float move_speed = -10.0;
uniform bool smooth_edge = false;

void fragment() {
	float dist = distance(UV, vec2(0.5,0.5));
	float rings = sin(dist * ring_frequency + (TIME * move_speed));
	rings = step(ring_portion, rings);
	float blend_alpha = smoothstep(0.5, 0.4, dist);
	if (dist > 0.5 || rings < 1.0){
		ALPHA = 0.0;
	}
	else if (rings > 0.0){
		ALBEDO = ring_color;
		ALPHA = smooth_edge ? blend_alpha : 1.0;
	}
}
Tags
animation, circle, moving, ring, wave
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

Ring of Power

Focus circle / ring

Radar Blip Ring

Subscribe
Notify of
guest

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Asmoday4949
Asmoday4949
23 days ago

Hello,

Thanks for sharing.

I did a small change to your code to avoid branch divergence (if/else). I replaced these lines:

	if (dist > 0.5 || rings < 1.0){
		ALPHA = 0.0;
	}
	else if (rings > 0.0){
		ALBEDO = ring_color;
		ALPHA = smooth_edge ? blend_alpha : 1.0;
	}

by these:

    bool is_rings = (rings > 0.0) && bool(1 - int(dist > 0.5 || rings < 1.0));

    ALPHA = float(is_rings) * mix(1.0, blend_alpha, float(smooth_edge));
    ALBEDO = float(is_rings) * ring_color;