1#import bevy_render::view::View 2#import bevy_ui::ui_node::{ 3 draw_uinode_background, 7#import bevy_render::color_operations::{ 8 convert_to_linear_rgba, 22#import bevy_render::maths::PI 24const TAU: f32 = 2. * PI; 26const RIGHT_VERTEX = 2u; 27const BOTTOM_VERTEX = 4u; 29const RADIAL: u32 = 16u; 30const FILL_START: u32 = 32u; 31const FILL_END: u32 = 64u; 32const CONIC: u32 = 128u; 33const BORDER_LEFT: u32 = 256u; 34const BORDER_TOP: u32 = 512u; 35const BORDER_RIGHT: u32 = 1024u; 36const BORDER_BOTTOM: u32 = 2048u; 37const BORDER_ANY: u32 = BORDER_LEFT + BORDER_TOP + BORDER_RIGHT + BORDER_BOTTOM; 39fn enabled(flags: u32, mask: u32) -> bool { 40 return (flags & mask) != 0u; 43@group(0) @binding(0) var<uniform> view: View; 45struct GradientVertexOutput { 46 @location(0) uv: vec2<f32>, 47 @location(1) @interpolate(flat) size: vec2<f32>, 48 @location(2) @interpolate(flat) flags: u32, 49 @location(3) @interpolate(flat) radius: vec4<f32>, 50 @location(4) @interpolate(flat) border: vec4<f32>, 53 @location(5) point: vec2<f32>, 54 @location(6) @interpolate(flat) g_start: vec2<f32>, 55 @location(7) @interpolate(flat) dir: vec2<f32>, 56 @location(8) @interpolate(flat) start_color: vec4<f32>, 57 @location(9) @interpolate(flat) start_len: f32, 58 @location(10) @interpolate(flat) end_len: f32, 59 @location(11) @interpolate(flat) end_color: vec4<f32>, 60 @location(12) @interpolate(flat) hint: f32, 61 @builtin(position) position: vec4<f32>, 66 @location(0) vertex_position: vec3<f32>, 67 @location(1) vertex_uv: vec2<f32>, 68 @location(2) flags: u32, 71 @location(3) radius: vec4<f32>, 74 @location(4) border: vec4<f32>, 75 @location(5) size: vec2<f32>, 76 @location(6) point: vec2<f32>, 77 @location(7) @interpolate(flat) g_start: vec2<f32>, 78 @location(8) @interpolate(flat) dir: vec2<f32>, 79 @location(9) @interpolate(flat) start_color: vec4<f32>, 80 @location(10) @interpolate(flat) start_len: f32, 81 @location(11) @interpolate(flat) end_len: f32, 82 @location(12) @interpolate(flat) end_color: vec4<f32>, 83 @location(13) @interpolate(flat) hint: f32 84) -> GradientVertexOutput { 85 var out: GradientVertexOutput; 86 out.position = view.clip_from_world * vec4(vertex_position, 1.0); 94 out.start_color = start_color; 95 out.start_len = start_len; 96 out.end_len = end_len; 97 out.end_color = end_color; 98 out.g_start = g_start; 105fn fragment(in: GradientVertexOutput) -> @location(0) vec4<f32> { 107 if enabled(in.flags, RADIAL) { 108 g_distance = radial_distance(in.point, in.g_start, in.dir.x); 109 } else if enabled(in.flags, CONIC) { 110 g_distance = conic_distance(in.dir.x, in.point, in.g_start); 112 g_distance = linear_distance(in.point, in.g_start, in.dir); 115 let gradient_color = interpolate_gradient( 125 if enabled(in.flags, BORDER_ANY) { 126 return draw_uinode_border(gradient_color, in.point, in.size, in.radius, in.border, in.flags); 128 return draw_uinode_background(gradient_color, in.point, in.size, in.radius, in.border, in.flags); 132fn rem_euclid(a: f32, b: f32) -> f32 { 133 return ((a % b) + b) % b; 144 return dot(point - g_start, g_dir); 152 let d = point - center; 153 return length(vec2(d.x, d.y * ratio)); 161 let d = point - center; 162 let angle = atan2(-d.x, d.y) + PI; 163 return (((angle - start) % TAU) + TAU) % TAU; 168 start_color: vec3<f32>, 169 end_color: vec3<f32>, 173 return mix_oklch(start_color, end_color, t); 174#else ifdef IN_OKLCH_LONG 175 return mix_oklch_long(start_color, end_color, t); 177 return mix_hsv(start_color, end_color, t); 178#else ifdef IN_HSV_LONG 179 return mix_hsv_long(start_color, end_color, t); 181 return mix_hsl(start_color, end_color, t); 182#else ifdef IN_HSL_LONG 183 return mix_hsl_long(start_color, end_color, t); 186 return mix(start_color, end_color, t); 191fn convert_to_linear_rgba( 195 let rgb = oklch_to_linear_rgb(color.xyz); 196#else ifdef IN_OKLCH_LONG 197 let rgb = oklch_to_linear_rgb(color.xyz); 199 let rgb = hsv_to_linear_rgb(color.xyz); 200#else ifdef IN_HSV_LONG 201 let rgb = hsv_to_linear_rgb(color.xyz); 203 let rgb = hsl_to_linear_rgb(color.xyz); 204#else ifdef IN_HSL_LONG 205 let rgb = hsl_to_linear_rgb(color.xyz); 207 let rgb = oklab_to_linear_rgb(color.xyz); 209 let rgb = srgb_to_linear(color.xyz); 214 return vec4(rgb, color.a); 217fn interpolate_gradient( 219 start_color: vec4<f32>, 221 end_color: vec4<f32>, 226 if start_distance == end_distance { 227 if distance <= start_distance && enabled(flags, FILL_START) { 228 return convert_to_linear_rgba(start_color); 230 if start_distance <= distance && enabled(flags, FILL_END) { 231 return convert_to_linear_rgba(end_color); 236 var t = (distance - start_distance) / (end_distance - start_distance); 239 if enabled(flags, FILL_START) { 240 return convert_to_linear_rgba(start_color); 246 if enabled(flags, FILL_END) { 247 return convert_to_linear_rgba(end_color); 255 t = 0.5 * (1 + (t - hint) / (1.0 - hint)); 258 return convert_to_linear_rgba(vec4(mix_colors(start_color.xyz, end_color.xyz, t), mix(start_color.a, end_color.a, t)));