aboutsummaryrefslogtreecommitdiff
path: root/game/src/Game/Theme/PieChart/PieChart.gdshader
blob: 1707b3d0b8740538b34f997e7f7d269eb9fdfd7f (plain) (blame)
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);
   }
}