1#import bevy_render::view::View 2#import bevy_ui::ui_node::{ 3 draw_uinode_background, 7const PI: f32 = 3.14159265358979323846; 8const TAU: f32 = 2. * PI; 9const HUE_GUARD: f32 = 0.0001; 12const RIGHT_VERTEX = 2u; 13const BOTTOM_VERTEX = 4u; 15const RADIAL: u32 = 16u; 16const FILL_START: u32 = 32u; 17const FILL_END: u32 = 64u; 18const CONIC: u32 = 128u; 19const BORDER_LEFT: u32 = 256u; 20const BORDER_TOP: u32 = 512u; 21const BORDER_RIGHT: u32 = 1024u; 22const BORDER_BOTTOM: u32 = 2048u; 23const BORDER_ANY: u32 = BORDER_LEFT + BORDER_TOP + BORDER_RIGHT + BORDER_BOTTOM; 25fn enabled(flags: u32, mask: u32) -> bool { 26 return (flags & mask) != 0u; 29@group(0) @binding(0) var<uniform> view: View; 31struct GradientVertexOutput { 32 @location(0) uv: vec2<f32>, 33 @location(1) @interpolate(flat) size: vec2<f32>, 34 @location(2) @interpolate(flat) flags: u32, 35 @location(3) @interpolate(flat) radius: vec4<f32>, 36 @location(4) @interpolate(flat) border: vec4<f32>, 39 @location(5) point: vec2<f32>, 40 @location(6) @interpolate(flat) g_start: vec2<f32>, 41 @location(7) @interpolate(flat) dir: vec2<f32>, 42 @location(8) @interpolate(flat) start_color: vec4<f32>, 43 @location(9) @interpolate(flat) start_len: f32, 44 @location(10) @interpolate(flat) end_len: f32, 45 @location(11) @interpolate(flat) end_color: vec4<f32>, 46 @location(12) @interpolate(flat) hint: f32, 47 @builtin(position) position: vec4<f32>, 52 @location(0) vertex_position: vec3<f32>, 53 @location(1) vertex_uv: vec2<f32>, 54 @location(2) flags: u32, 57 @location(3) radius: vec4<f32>, 60 @location(4) border: vec4<f32>, 61 @location(5) size: vec2<f32>, 62 @location(6) point: vec2<f32>, 63 @location(7) @interpolate(flat) g_start: vec2<f32>, 64 @location(8) @interpolate(flat) dir: vec2<f32>, 65 @location(9) @interpolate(flat) start_color: vec4<f32>, 66 @location(10) @interpolate(flat) start_len: f32, 67 @location(11) @interpolate(flat) end_len: f32, 68 @location(12) @interpolate(flat) end_color: vec4<f32>, 69 @location(13) @interpolate(flat) hint: f32 70) -> GradientVertexOutput { 71 var out: GradientVertexOutput; 72 out.position = view.clip_from_world * vec4(vertex_position, 1.0); 80 out.start_color = start_color; 81 out.start_len = start_len; 82 out.end_len = end_len; 83 out.end_color = end_color; 84 out.g_start = g_start; 91fn fragment(in: GradientVertexOutput) -> @location(0) vec4<f32> { 93 if enabled(in.flags, RADIAL) { 94 g_distance = radial_distance(in.point, in.g_start, in.dir.x); 95 } else if enabled(in.flags, CONIC) { 96 g_distance = conic_distance(in.dir.x, in.point, in.g_start); 98 g_distance = linear_distance(in.point, in.g_start, in.dir); 101 let gradient_color = interpolate_gradient( 111 if enabled(in.flags, BORDER_ANY) { 112 return draw_uinode_border(gradient_color, in.point, in.size, in.radius, in.border, in.flags); 114 return draw_uinode_background(gradient_color, in.point, in.size, in.radius, in.border); 119fn gamma(value: f32) -> f32 { 123 if value <= 0.04045 { 124 return value / 12.92; 126 return pow((value + 0.055) / 1.055, 2.4); 131fn inverse_gamma(value: f32) -> f32 { 136 if value <= 0.0031308 { 137 return value * 12.92; 139 return 1.055 * pow(value, 1.0 / 2.4) - 0.055; 143fn srgb_to_linear_rgb(color: vec3<f32>) -> vec3<f32> { 151fn linear_rgb_to_srgb(color: vec3<f32>) -> vec3<f32> { 153 inverse_gamma(color.x), 154 inverse_gamma(color.y), 155 inverse_gamma(color.z) 159fn oklab_to_linear_rgb(c: vec3<f32>) -> vec3<f32> { 160 let l_ = c.x + 0.39633778 * c.y + 0.21580376 * c.z; 161 let m_ = c.x - 0.105561346 * c.y - 0.06385417 * c.z; 162 let s_ = c.x - 0.08948418 * c.y - 1.2914855 * c.z; 163 let l = l_ * l_ * l_; 164 let m = m_ * m_ * m_; 165 let s = s_ * s_ * s_; 167 4.0767417 * l - 3.3077116 * m + 0.23096994 * s, 168 -1.268438 * l + 2.6097574 * m - 0.34131938 * s, 169 -0.0041960863 * l - 0.7034186 * m + 1.7076147 * s, 173fn hsl_to_linear_rgb(hsl: vec3<f32>) -> vec3<f32> { 177 let c = (1.0 - abs(2.0 * l - 1.0)) * s; 179 let x = c * (1.0 - abs(hp % 2.0 - 1.0)); 183 if 0.0 <= hp && hp < 1.0 { 184 r = c; g = x; b = 0.0; 185 } else if 1.0 <= hp && hp < 2.0 { 186 r = x; g = c; b = 0.0; 187 } else if 2.0 <= hp && hp < 3.0 { 188 r = 0.0; g = c; b = x; 189 } else if 3.0 <= hp && hp < 4.0 { 190 r = 0.0; g = x; b = c; 191 } else if 4.0 <= hp && hp < 5.0 { 192 r = x; g = 0.0; b = c; 193 } else if 5.0 <= hp && hp < 6.0 { 194 r = c; g = 0.0; b = x; 197 return srgb_to_linear_rgb(vec3(r + m, g + m, b + m)); 200fn hsv_to_linear_rgb(hsva: vec3<f32>) -> vec3<f32> { 201 let h = hsva.x * 6.0; 205 let x = c * (1.0 - abs(h % 2.0 - 1.0)); 210 if 0.0 <= h && h < 1.0 { 211 r = c; g = x; b = 0.0; 212 } else if 1.0 <= h && h < 2.0 { 213 r = x; g = c; b = 0.0; 214 } else if 2.0 <= h && h < 3.0 { 215 r = 0.0; g = c; b = x; 216 } else if 3.0 <= h && h < 4.0 { 217 r = 0.0; g = x; b = c; 218 } else if 4.0 <= h && h < 5.0 { 219 r = x; g = 0.0; b = c; 220 } else if 5.0 <= h && h < 6.0 { 221 r = c; g = 0.0; b = x; 223 return srgb_to_linear_rgb(vec3(r + m, g + m, b + m)); 226fn oklch_to_linear_rgb(c: vec3<f32>) -> vec3<f32> { 228 return oklab_to_linear_rgb(vec3(c.x, c.y * cos(hue), c.y * sin(hue))); 231fn rem_euclid(a: f32, b: f32) -> f32 { 232 return ((a % b) + b) % b; 244 return dot(point - g_start, g_dir); 252 let d = point - center; 253 return length(vec2(d.x, d.y * ratio)); 261 let d = point - center; 262 let angle = atan2(-d.x, d.y) + PI; 263 return (((angle - start) % TAU) + TAU) % TAU; 266fn mix_oklch(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 274 } else if b.y < HUE_GUARD { 278 let hue_diff = g - h; 279 if abs(hue_diff) > 0.5 { 281 h += (hue_diff - 1.) * t; 283 h += (hue_diff + 1.) * t; 295fn mix_oklch_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 300 } else if b.y < HUE_GUARD { 304 let hue_diff = g - h; 305 if abs(hue_diff) < 0.5 { 307 h += (hue_diff - 1.) * t; 309 h += (hue_diff + 1.) * t; 321fn mix_hsl(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 329 } else if b.y < HUE_GUARD { 334 fract(h + (fract(g - h + 0.5) - 0.5) * t), 340fn mix_hsl_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 345 } else if b.y < HUE_GUARD { 349 let d = fract(g - h + 0.5) - 0.5; 351 fract(h + (d + select(1., -1., 0. < d)) * t), 357fn mix_hsv(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 365 } else if b.y < HUE_GUARD { 369 let hue_diff = g - h; 370 if abs(hue_diff) > 0.5 { 372 h += (hue_diff - 1.0) * t; 374 h += (hue_diff + 1.0) * t; 386fn mix_hsv_long(a: vec3<f32>, b: vec3<f32>, t: f32) -> vec3<f32> { 391 } else if b.y < HUE_GUARD { 395 let hue_diff = g - h; 396 if abs(hue_diff) < 0.5 { 398 h += (hue_diff - 1.0) * t; 400 h += (hue_diff + 1.0) * t; 412fn interpolate_gradient( 414 start_color: vec4<f32>, 416 end_color: vec4<f32>, 421 if start_distance == end_distance { 422 if distance <= start_distance && enabled(flags, FILL_START) { 423 return convert_to_linear_rgba(start_color); 425 if start_distance <= distance && enabled(flags, FILL_END) { 426 return convert_to_linear_rgba(end_color); 431 var t = (distance - start_distance) / (end_distance - start_distance); 434 if enabled(flags, FILL_START) { 435 return convert_to_linear_rgba(start_color); 441 if enabled(flags, FILL_END) { 442 return convert_to_linear_rgba(end_color); 450 t = 0.5 * (1 + (t - hint) / (1.0 - hint)); 453 return convert_to_linear_rgba(vec4(mix_colors(start_color.xyz, end_color.xyz, t), mix(start_color.a, end_color.a, t))); 458 start_color: vec3<f32>, 459 end_color: vec3<f32>, 463 return mix_oklch(start_color, end_color, t); 464#else ifdef IN_OKLCH_LONG 465 return mix_oklch_long(start_color, end_color, t); 467 return mix_hsv(start_color, end_color, t); 468#else ifdef IN_HSV_LONG 469 return mix_hsv_long(start_color, end_color, t); 471 return mix_hsl(start_color, end_color, t); 472#else ifdef IN_HSL_LONG 473 return mix_hsl_long(start_color, end_color, t); 476 return mix(start_color, end_color, t); 481fn convert_to_linear_rgba( 485 let rgb = oklch_to_linear_rgb(color.xyz); 486#else ifdef IN_OKLCH_LONG 487 let rgb = oklch_to_linear_rgb(color.xyz); 489 let rgb = hsv_to_linear_rgb(color.xyz); 490#else ifdef IN_HSV_LONG 491 let rgb = hsv_to_linear_rgb(color.xyz); 493 let rgb = hsl_to_linear_rgb(color.xyz); 494#else ifdef IN_HSL_LONG 495 let rgb = hsl_to_linear_rgb(color.xyz); 497 let rgb = oklab_to_linear_rgb(color.xyz); 499 let rgb = pow(color.xyz, vec3(2.2)); 504 return vec4(rgb, color.a);