Dial

Configurable dial.

9-7-2023: I have updated the shader to version 2. It has been changed slightly to work with Godot 4 by default but there are comments explaining how to use it with earlier versions of Godot.

15-1-2023: I have optimised the code by removing explicit if statements. I used some of the code snippets provided by nonunknown here: https://godotshaders.com/shader/optimize-your-shaders/

Shader code
//	Dial shader v2 by Brian Smith (steampunkdemon.itch.io)
//	MIT Licence

shader_type canvas_item;

// Replace the below references to source_color with hint_color if you are using a version of Godot before 4.
uniform vec4 indictor_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec4 border_color : source_color = vec4(0.5, 0.5, 0.5, 1.0);
uniform vec4 centre_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec4 sector1_color : source_color = vec4(0.0, 1.0, 0.0, 1.0);
uniform vec4 sector2_color : source_color = vec4(1.0, 1.0, 0.0, 1.0);
uniform vec4 sector3_color : source_color = vec4(1.0, 0.0, 0.0, 1.0);
uniform vec4 scale_mark_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);

uniform bool show_edges = false;
uniform float indicator_angle : hint_range(0.0, 1.0) = 0.0;
uniform float indicator_length : hint_range(0.1, 1.0) = 0.65;
uniform float indicator_width : hint_range(0.001, 0.01) = 0.005;
uniform float border_width : hint_range(0.0, 0.5) = 0.1;
uniform float centre_width : hint_range(0.0, 0.5) = 0.1;
uniform float sector1 : hint_range(0.0, 1.0) = 0.5;
uniform float sector2 : hint_range(0.0, 1.0) = 0.75;
uniform float sector3 : hint_range(0.0, 1.0) = 0.905;
uniform float sector_end : hint_range(0.0, 1.0) = 1.0;
uniform float scale_marks : hint_range(0.0, 20.0, 1.0) = 16.0;
uniform float major_scale_marks : hint_range(0.0, 20.0, 1.0) = 4.0;
uniform float scale_mark_width : hint_range(0.01, 0.1) = 0.02;
uniform float scale_outer : hint_range(0.0, 1.0) = 0.85;
uniform float scale_minor_inner : hint_range(0.0, 1.0) = 0.75;
uniform float scale_major_inner : hint_range(0.0, 1.0) = 0.65;

float greater_than(float x, float y) {
  return max(sign(x - y), 0.0);
}

void fragment() {
	vec2 uv = UV * 2.0 - 1.0;
	float a = (atan(uv.y, uv.x) + 3.141592656) / 6.283185312;
	float l = length(uv);

//	Uncomment the following line if you are applying the shader to a TextureRect and using a version of Godot before 4.
//	COLOR = texture(TEXTURE,UV);

//	If you do not want to render all the colored sectors remove the appropriate lines from the following block of code.
	COLOR.rgb = mix(COLOR.rgb, sector3_color.rgb, sector3_color.a * (greater_than(a, sector3) * greater_than(sector_end, a)));
	COLOR.rgb = mix(COLOR.rgb, sector2_color.rgb, sector2_color.a * (greater_than(a, sector2) * greater_than(sector3, a)));
	COLOR.rgb = mix(COLOR.rgb, sector1_color.rgb, sector1_color.a * (greater_than(a, sector1) * greater_than(sector2, a)));

//	If you do not want to render the scale marks remove the following code block.
//	If you do not want to render the major scale marks remove the second following line.
	COLOR.rgb = mix(COLOR.rgb, scale_mark_color.rgb, scale_mark_color.a * greater_than(abs(mod(a, 1.0 / scale_marks) * scale_marks * 2.0 - 1.0), 1.0 - (scale_mark_width / 6.283185312 / l) * scale_marks) * (greater_than(scale_outer, l) * greater_than(l, scale_minor_inner)));
	COLOR.rgb = mix(COLOR.rgb, scale_mark_color.rgb, scale_mark_color.a * greater_than(abs(mod(a, 1.0 / major_scale_marks) * major_scale_marks * 2.0 - 1.0), 1.0 - (scale_mark_width / 6.283185312 / l) * major_scale_marks) * (greater_than(scale_minor_inner, l) * greater_than(l, scale_major_inner)));

	COLOR.rgb = mix(COLOR.rgb, indictor_color.rgb, indictor_color.a * greater_than(indicator_length, l) * greater_than(indicator_width / l, abs(indicator_angle - (a + 1.0 * greater_than(-0.5, a - indicator_angle) - 1.0 * greater_than(a - indicator_angle, 0.5)))));

//	If you do not want to render the centre remove the following line.
	COLOR.rgb = mix(COLOR.rgb, centre_color.rgb, centre_color.a * greater_than(centre_width, l));

//	If you do not want to render the border remove the following line.
	COLOR.rgb = mix(COLOR.rgb, border_color.rgb, border_color.a * greater_than(l, 1.0 - border_width));

//	If you do not want the edges to be transparent remove the following line of code.
//	If you always want the edges to be transparent replace the following line of code with:
//	COLOR.a *= greater_than(1.0, l);
	COLOR.a *= max(sign(1.0 - l), float(show_edges));
}
Tags
dial
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from Steampunkdemon

Analogue clock face

Radar with trace blip

Simple Rainbow

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments