1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
shader_type canvas_item;
// The center in UV coordinates, which will always
//be 0.5, the actual radius will be controlled by the control node
//const vec2 center = vec2(0.5,0.5);
uniform float radius = 0.4;
//shadow
uniform vec2 shadow_displacement = vec2(0.75,0.75);
uniform float shadow_tightness = 10;
uniform float shadow_radius = 0.7;
uniform float shadow_thickness = 1.0;
// Control of the slices
uniform float stopAngles[5];
uniform vec3 colours[5];
// Trim
uniform vec3 trim_colour;
uniform float trim_size = 0.05;
// The center is spotlighted by the gradient,
//control its size and falloff with these
uniform float gradient_falloff = 3.6;
uniform float gradient_base = 3.1;
// control whether this is a donut instead of a pie chart
uniform bool donut = false;
uniform bool donut_inner_trim = false;
uniform float donut_inner_radius = 0.15;
// get the polar coordinates of a pixel relative to the center
vec2 getPolar(vec2 UVin, vec2 center){
vec2 relcoord = (UVin-center);
float dist = length(relcoord);
float theta = PI/2.0 + atan((relcoord.y)/(relcoord.x));
if(UVin.x < 0.5){
theta += PI;
}
return vec2(dist,theta);
}
// from thebookofshaders, returns a gradient falloff
float parabola( float base, float x, float k ){
return pow( base*x*(1.0-x), k );
}
float parabola_shadow(float base, float x){
return base*x*x;
}
void fragment() {
vec2 coords = getPolar(UV,vec2(0.5,0.5));
float dist = coords.x;
float theta = coords.y;
vec2 shadow_polar = getPolar(UV,vec2(0.0+shadow_displacement.x,0.0+shadow_displacement.y));
float shadow_peak = radius+(radius-donut_inner_radius)/2.0;
float shadow_gradient = shadow_thickness+parabola_shadow(shadow_tightness*-10.0,shadow_polar.x+shadow_peak-shadow_radius);
// inner hole of the donut => make it transparent
if(donut && dist <= donut_inner_radius){
COLOR = vec4(0.1,0.1,0.1,shadow_gradient);
}
// inner trim
else if(donut && donut_inner_trim && dist <= donut_inner_radius + trim_size){
COLOR = vec4(trim_colour,1.0);
}
// interior
else if(dist <= radius-trim_size){
for(int i=0;i<stopAngles.length();i++){
if(theta <= stopAngles[i]){
float gradient = parabola(gradient_base,dist,gradient_falloff);
COLOR = vec4(colours[i]*(1.0-gradient),1.0);
break;
}
}
}
// outer trim
else if(dist <= radius){
COLOR = vec4(trim_colour,1.0);
}
//outside the circle
else{
COLOR = vec4(0.1,0.1,0.1,shadow_gradient);
}
}
|