Radial Progress Shader
A shader used to display a ratio of two images in a circular pattern, similar to the ProgressBar node, but much easier to work with when working outside of UI. Based off of Demindiro’s Health Circle shader. The texture that the shader is applied to is used as the fill texture, and the empty texture can be set in the shader.
sampler2D
Fill Texture Overlay: An image that is displayed over the texture the shader is applied to. Gradients are typically put here over white images.
sampler2D
BG Texture: The texture that is displayed in the portion of the radial progress that is not filled.
float
Fill Ratio: A number between 0 and 1 representing the amount of the radial progress that is filled.
float
Start Angle: An angle (in degrees) that the radial progress starts at.
float
Max Angle: The maximum angle (in degrees) that the radial progress can fill to.
bool
Invert Fill: When true, the shader will use the base texture as the background, and bg_texture
as the fill.
bool
Reflect X: When true, the radial overlay will be flipped along the X axis.
bool
Reflect Y: When true, the radial overlay will be flipped along the Y axis.
vec2
Offset: The UV offset of the radial overlay. Each value goes from -1.0 to 1.0, which will put it at each edge of the image.
Shader code
shader_type canvas_item;
const float PI = 3.141592656;
uniform sampler2D fill_texture_overlay;
uniform sampler2D bg_texture;
uniform float fill_ratio:hint_range(0., 1.) = 1.;
uniform float start_angle:hint_range(0., 360.) = 0.;
uniform float max_angle:hint_range(0., 360.) = 360.;
uniform bool invert_fill = false;
uniform bool reflect_x = false;
uniform bool reflect_y = false;
uniform vec2 offset = vec2(0., 0.);
mat2 tex_rotate(float _angle){
return mat2(vec2(cos(_angle), -sin(_angle)), vec2(sin(_angle), cos(_angle)));
}
void fragment() {
float fill_angle = radians(fill_ratio * max_angle);
vec2 uv = ((UV * 2. - 1.) + offset) * tex_rotate(-radians(start_angle));
if (reflect_x) {
uv *= mat2(vec2(-1., 0.), vec2(0., 1.));
}
if (reflect_y) {
uv *= mat2(vec2(1., 0.), vec2(0., -1.));
}
if ((!invert_fill && atan(uv.x, uv.y) + PI < fill_angle) || (invert_fill && atan(uv.x, uv.y) + PI > fill_angle)) {
COLOR = texture(TEXTURE, UV) * texture(fill_texture_overlay, UV);
} else {
COLOR = texture(bg_texture, UV);
}
}
I was trying to figure out how to pull this shader out of the textureProgress node. This is exactly what I was looking for, thanks!
I found a little error in there where invert X doesn’t invert anything. You need a -1.0 in the if statement.
Such an amazing shader, very good job!