slider_lerp.glsl (3801B)
1 /* See LICENSE for copyright details */ 2 #version 330 3 4 /* TODO: this shader should be instanced!! */ 5 6 in vec2 fragTexCoord; 7 in vec4 fragColor; 8 9 out vec4 out_colour; 10 11 #define CPM_PICKER 0 12 #define CPM_SLIDERS 1 13 14 #define CM_RGB 0 15 #define CM_HSV 1 16 17 uniform int u_mode; 18 uniform int u_colour_mode; 19 uniform float u_radius; 20 uniform float u_border_thick; 21 uniform vec4 u_colours[3]; 22 uniform vec4 u_regions[4]; 23 24 /* input: h [0,360] | s,v [0, 1] * 25 * output: rgb [0,1] */ 26 vec3 hsv2rgb(vec3 hsv) 27 { 28 vec3 k = mod(vec3(5, 3, 1) + hsv.x / 60, 6); 29 k = max(min(min(k, 4 - k), 1), 0); 30 return hsv.z - hsv.z * hsv.y * k; 31 } 32 33 bool in_rounded_region(vec2 pos, vec4 min_max, float radius) 34 { 35 vec2 min_xy = min_max.xy; 36 vec2 max_xy = min_max.zw; 37 vec2 ulp = vec2(min_xy.x + radius, max_xy.y - radius); 38 vec2 urp = vec2(max_xy.x - radius, max_xy.y - radius); 39 vec2 blp = vec2(min_xy.x + radius, min_xy.y + radius); 40 vec2 brp = vec2(max_xy.x - radius, min_xy.y + radius); 41 42 bool ulr = length(ulp - pos) < radius; 43 bool urr = length(urp - pos) < radius; 44 bool blr = length(blp - pos) < radius; 45 bool brr = length(brp - pos) < radius; 46 bool rect = (pos.x > min_xy.x) && (pos.x < max_xy.x) && 47 (pos.y < max_xy.y - radius) && (pos.y > min_xy.y + radius); 48 bool upr = (pos.x > ulp.x) && (pos.x < urp.x) && (pos.y < max_xy.y) && (pos.y > min_xy.y); 49 50 return rect || ulr || urr || blr || brr || upr; 51 } 52 53 vec4 picker_mode(vec2 pos) 54 { 55 vec4 result = vec4(0); 56 vec4 shift = vec4(vec2(u_border_thick), -vec2(u_border_thick)); 57 58 if (in_rounded_region(pos, u_regions[0], u_radius + u_border_thick)) { 59 result.w = 1; 60 if (in_rounded_region(pos, u_regions[0] + shift, u_radius)) { 61 float scale = u_regions[0].w - u_regions[0].y; 62 result = mix(vec4(1, u_colours[0].yzw), vec4(0, u_colours[0].yzw), 63 (pos.y - u_regions[0].y) / scale); 64 } 65 } else if (in_rounded_region(pos, u_regions[1], u_radius + u_border_thick)) { 66 result.w = 1; 67 if (in_rounded_region(pos, u_regions[1] + shift, u_radius)) { 68 float scale = u_regions[1].w - u_regions[1].y; 69 result = mix(u_colours[2], u_colours[1], 70 (pos.y - u_regions[1].y) / scale); 71 } 72 } else if (in_rounded_region(pos, u_regions[2], u_radius + u_border_thick)) { 73 result.w = 1; 74 if (in_rounded_region(pos, u_regions[2] + shift, u_radius)) { 75 vec2 scale = u_regions[2].zw - u_regions[2].xy; 76 vec2 t = (pos - u_regions[2].xy) / scale; 77 result = vec4(u_colours[0].x, t.x, t.y, 1); 78 } 79 } 80 81 result.x *= 360; 82 return vec4(hsv2rgb(result.xyz), result.w); 83 } 84 85 bool slider_fill(vec2 pos, int idx, out vec4 colour) 86 { 87 bool result = false; 88 vec4 shift = vec4(vec2(u_border_thick), -vec2(u_border_thick)); 89 colour = vec4(0); 90 if (in_rounded_region(pos, u_regions[idx], u_radius + u_border_thick)) { 91 colour.w = 1; 92 if (in_rounded_region(pos, u_regions[idx] + shift, u_radius)) { 93 float scale = u_regions[idx].z - u_regions[idx].x; 94 vec4 c1 = u_colours[0]; 95 vec4 c2 = u_colours[0]; 96 c1[idx] = 0; 97 c2[idx] = 1; 98 colour = mix(c1, c2, (pos.x - u_regions[idx].x) / scale); 99 } 100 result = true; 101 } 102 return result; 103 } 104 105 vec4 slider_mode(vec2 pos) 106 { 107 vec4 result = vec4(0); 108 vec4 fill_out; 109 110 if (slider_fill(pos, 0, fill_out)) result = fill_out; 111 else if (slider_fill(pos, 1, fill_out)) result = fill_out; 112 else if (slider_fill(pos, 2, fill_out)) result = fill_out; 113 else if (slider_fill(pos, 3, fill_out)) result = fill_out; 114 115 switch (u_colour_mode) { 116 case CM_RGB: break; 117 case CM_HSV: result.x *= 360; result = vec4(hsv2rgb(result.xyz), result.w); break; 118 } 119 120 return result; 121 } 122 123 void main() 124 { 125 vec2 pos = gl_FragCoord.xy; 126 out_colour = vec4(0); 127 switch (u_mode) { 128 case CPM_PICKER: out_colour = picker_mode(pos); break; 129 case CPM_SLIDERS: out_colour = slider_mode(pos); break; 130 } 131 }