1// Copyright (c) 2015 Sergio Gonzalez. All rights reserved. 2// License: https://github.com/serge-rgb/milton#license 3 4 5// The triangle, in [-1,1]. 6uniform vec2 u_pointa; 7uniform vec2 u_pointb; 8uniform vec2 u_pointc; 9 10uniform vec3 u_color; 11uniform float u_angle; 12 13uniform vec2 u_triangle_point; 14 15uniform vec4 u_colors[5]; // Colors for picker buttons. 16 17uniform vec2 u_screen_size; 18 19in vec2 v_norm; 20 21 22#define PI 3.14159 23 24float 25radians_to_degrees(float r) 26{ 27 return (180.0 * r) / PI; 28} 29 30// http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl 31vec3 32hsv2rgb(vec3 c) 33{ 34 vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); 35 vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); 36 return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); 37} 38 39vec3 40hsv_to_rgb(vec3 hsv) 41{ 42 vec3 rgb; 43 44 float h = hsv.x; 45 float s = hsv.y; 46 float v = hsv.z; 47 float hh = h / 60.0; 48 int hi = int(floor(hh)); 49 float cr = v * s; 50 float rem = mod(hh, 2.0); 51 float x = cr * (1.0 - abs(rem - 1.0)); 52 float m = v - cr; 53 54 if( hi == 0 || hi == 6 ) { 55 rgb.r = cr; 56 rgb.g = x; 57 rgb.b = 0; 58 } 59 if( hi == 1 ) { 60 rgb.r = x; 61 rgb.g = cr; 62 rgb.b = 0; 63 } 64 if( hi == 2 ) { 65 rgb.r = 0; 66 rgb.g = cr; 67 rgb.b = x; 68 } 69 if( hi == 3 ) { 70 rgb.r = 0; 71 rgb.g = x; 72 rgb.b = cr; 73 } 74 if( hi == 4 ) { 75 rgb.r = x; 76 rgb.g = 0; 77 rgb.b = cr; 78 } 79 if( hi == 5 ) { 80 rgb.r = cr; 81 rgb.g = 0; 82 rgb.b = x; 83 } 84 rgb.r += m; 85 rgb.g += m; 86 rgb.b += m; 87 88 return rgb; 89} 90 91// Could be called a signed area. `orientation(a, b, c) / 2` is the area of the 92// triangle. 93// If positive, c is to the left of ab. Negative: right of ab. 0 if 94// colinear. 95float 96orientation(vec2 a, vec2 b, vec2 c) 97{ 98 return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y); 99} 100 101bool 102is_inside_triangle(vec2 p) 103{ 104 bool is_inside = 105 (orientation(u_pointa, u_pointb, p) <= 0) && 106 (orientation(u_pointb, u_pointc, p) <= 0) && 107 (orientation(u_pointc, u_pointa, p) <= 0); 108 return is_inside; 109} 110 111void 112main() 113{ 114 // NOTE: 115 // These constants gotten from gui.cc in gui_init. From bounds_radius_px, wheel_half_width, and so on. 116 float u_ui_scale = 1.75; 117 float half_width = 12.0 / 100.0; 118 float radius = (1.0 - (12.0 + 5) / 100.0); 119 120 /* vec2 screen_point = vec2(gl_FragCoord.x, u_screen_size.y-gl_FragCoord.y); */ 121 /* vec2 coord = screen_point / u_screen_size; */ 122 /* coord.y = 1-coord.y; */ 123 vec4 color = vec4(0.5, 0.5, 0.55, 0.6); 124 125 float dist = distance(vec2(0), v_norm); 126 // Wheel and triangle 127 // Show chosen color in preview circle 128 vec2 preview_center = vec2(0.75,-0.75); 129 const float preview_radius = 0.23; 130 131 float dist_to_preview = distance(preview_center, v_norm); 132 if ( dist_to_preview < preview_radius ) { 133 color = vec4(0,0,0,1); 134 const float epsilon = 0.02; 135 if ( dist_to_preview < preview_radius - epsilon ) { 136 color = vec4(u_color, 1); 137 } 138 } 139 // else if ( dist < radius + half_width ) { 140 // color = vec4(0,0,0,1); 141 // } 142#if 1 143 else if ( dist < radius+half_width ) { 144 // Wheel 145 if ( dist > radius-half_width ) { 146 vec2 n = v_norm; 147 vec2 v = vec2(1, 0); 148 float angle = acos(dot(n, v)/ (length(n) * length(v))); 149 if ( v_norm.y > 0 ) { 150 angle = (2*PI) - angle; 151 } 152 vec3 hsv = vec3(radians_to_degrees(angle),1.0,1.0); 153 //vec3 hsv = vec3(angle,1.0,1.0); 154 vec3 rgb = hsv_to_rgb(hsv); 155 color = vec4(rgb,1); 156 } 157 // Triangle 158 else if ( is_inside_triangle(v_norm) ) { 159 float area = orientation(u_pointa, u_pointb, u_pointc); 160 float v = 1 - (orientation(v_norm, u_pointc, u_pointa) / area); 161 float s = orientation(u_pointb, v_norm, u_pointa) * v / area; 162 vec3 pure_color = hsv_to_rgb(vec3(u_angle,1.0,1.0)); 163 color = vec4((1.0-(1.0-pure_color)*s)*v,1.0); 164 } 165 } 166#endif 167 // Render buttons 168 else if ( v_norm.y >= 1 ) { 169 // Get the color for the rects 170 int rect_i = int(((v_norm.x+1)/4) * 10); 171 vec4 rect_color = u_colors[rect_i]; 172 color = rect_color; 173 174 // Black outlines 175 float h = ((v_norm.x+1)/4)*10; 176 float epsilon = 0.01; 177 float epsilon2 = 0.015; 178 if ( v_norm.y > 1.4-epsilon 179 || v_norm.y < 1+epsilon 180 || (h < epsilon2 && h > - epsilon2) 181 || (h < 1 + epsilon2 && h > 1 - epsilon2) 182 || (h < 2 + epsilon2 && h > 2 - epsilon2) 183 || (h < 3 + epsilon2 && h > 3 - epsilon2) 184 || (h < 4 + epsilon2 && h > 4 - epsilon2) 185 || (h < 5 + epsilon2 && h > 5 - epsilon2) 186 || (h < 6 + epsilon2 && h > 6 - epsilon2) ) { 187 color = vec4(0,0,0,1); 188 } 189 } 190 191 float dist_to_choice = distance(v_norm, u_triangle_point); 192 const float point_radius = 0.05; 193 const float girth = 0.01; 194 if ( dist_to_choice < point_radius+girth && dist_to_choice > point_radius-girth ) { 195 color.rgb = vec3(1- color.r, 1 - color.g, 1 - color.b); 196 } 197 198 out_color = color; 199} 200