Circular Life Bar

This shader can represent any stats, such as life or stamina (or both \(°o°)/)
You can change a lot of parameters:

-the percentage of the circle
-all the colors
-the antialiasing (I recommend not using it if you use the pixelation as it makes things weird)
-the pixelation (having the pixel factor to 0 act like there is no pixelation)
-the radius of the ring
-the width of the ring
-the radius of the background
-the starting angle of the ring
-the spacing of the segments
-the angle of the segments
-and of course, the segments count

 

I used this tutorial to help me create this shader: https://www.youtube.com/watch?v=V5h2ClMUguQ&ab_channel=DevOrenge

 

I also used a bit of code from this shader: https://godotshaders.com/shader/radial-progress-shader/

Shader code
shader_type canvas_item;

const float PI = 3.141592656;

uniform float removed_segments:hint_range(0., 1.) = 1.;
uniform vec4 ring_color : hint_color = vec4(1);
uniform vec4 bg_color : hint_color = vec4(0,0,0,1);
uniform vec4 bg_line_color : hint_color = vec4(0.5,0.5,0.5,1);
uniform vec4 empty_cell_color : hint_color = vec4(0.25,0.25,0.25,1);
uniform bool antialias = false;
uniform float pixelFactor : hint_range(0,1) = .25;
uniform float radius :hint_range(0, 1) = 0.7;
uniform float line_width :hint_range(0, 1) = 0.21;
uniform float bg_width :hint_range(0, 1) = 0.28;
uniform float start_angle:hint_range(0., 360.) = 0.;
uniform float segment_spacing:hint_range(0., 1.) = 0.05;
uniform float segment_angle:hint_range(0., 1.) = 0.;
uniform int segment_count = 3;

mat2 tex_rotate(float _angle){
	return mat2(vec2(cos(_angle), -sin(_angle)), vec2(sin(_angle), cos(_angle)));
}

void fragment(){
	vec2 uv;
	if(pixelFactor != 0.){
		vec2 pixelNumber = vec2(textureSize(TEXTURE, 0)) * pixelFactor;
		vec2 pixelated_UV = round(UV * pixelNumber) / pixelNumber;
		uv = (pixelated_UV * 2.0 - 1.0) * tex_rotate((-radians(start_angle)));
	}else{
		uv = (UV * 2.0 - 1.0) * tex_rotate((-radians(start_angle)));
	}
	
	float angle = atan(uv.x, uv.y) + PI;
	float segment_size = (2. * PI) / float(segment_count);
	float segment = abs(sin(mod(angle + PI * 2. * segment_angle + segment_size / 2., segment_size) - segment_size / 2.)) * length(uv) - segment_spacing;
	angle -= removed_segments * 2. * PI;
	float circle = length(uv) - radius;
	float ring = abs(circle) - line_width;
	float background = abs(circle) - bg_width;
	
	if(antialias){
		ring /= fwidth(circle);
		angle /= fwidth(angle);
		segment /= fwidth(segment);
		background /= fwidth(background);
	}else{
		ring = ceil(ring);
		angle = ceil(angle);
		segment = ceil(segment);
		background = ceil(background);
	}
	ring = 1. - ring;
	segment = 1. - segment;
	background = 1. - background;
	
	ring = clamp(ring,0,1);
	angle = clamp(angle,0,1);
	segment = clamp(segment,0,1);
	background = clamp(background,0,1);
	float base_ring = ring;
	
	ring -= angle;
	if(segment_count >= 2) ring -= segment;
	ring = clamp(ring,0,1);
	
	if(ring > 0.){
		COLOR = ring_color;
		COLOR.a = ring;
	}else{
		if(segment >= 1. && base_ring >= 1.){
			COLOR = bg_line_color;
		}else if(base_ring >= 1.){
			COLOR = empty_cell_color;
		}else{
			COLOR = bg_color;
		}
		COLOR.a = background;
	}
}
Live Preview
Tags
2d, bar, circle, gui, health, pixel, progress, stamina, variable
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

Comments 5

    1. I don't know if you still need help but to set up the shader you can use a texture rect with a white texture on it.
      I have a HUD class wich is a singleton with a function "UpdateLifeBar". So I can call this function inside the player. The Hud have a reference to the life bar so it can modifie the parameters inside the "UpdateLifeBar" function.
      I hope it helps you on your journey of making games :)

      0
  1. Tarnished

    hint_color has been renamed to source_color for those wanting to use it in Godot 4.x

    4