1#import bevy_render::view::View; 2#import bevy_render::globals::Globals; 4const PI: f32 = 3.14159265358979323846; 5const SAMPLES: i32 = #SHADOW_SAMPLES; 7@group(0) @binding(0) var<uniform> view: View; 9struct BoxShadowVertexOutput { 10 @builtin(position) position: vec4<f32>, 11 @location(0) point: vec2<f32>, 12 @location(1) color: vec4<f32>, 13 @location(2) @interpolate(flat) size: vec2<f32>, 14 @location(3) @interpolate(flat) radius: vec4<f32>, 15 @location(4) @interpolate(flat) blur: f32, 18fn gaussian(x: f32, sigma: f32) -> f32 { 19 return exp(-(x * x) / (2. * sigma * sigma)) / (sqrt(2. * PI) * sigma); 23fn erf(p: vec2<f32>) -> vec2<f32> { 27 var result = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a; 28 result = result * result; 29 return s - s / (result * result); 33fn selectCorner(p: vec2<f32>, c: vec4<f32>) -> f32 { 34 return mix(mix(c.x, c.y, step(0., p.x)), mix(c.w, c.z, step(0., p.x)), step(0., p.y)); 37fn horizontalRoundedBoxShadow(x: f32, y: f32, blur: f32, corner: f32, half_size: vec2<f32>) -> f32 { 38 let d = min(half_size.y - corner - abs(y), 0.); 39 let c = half_size.x - corner + sqrt(max(0., corner * corner - d * d)); 40 let integral = 0.5 + 0.5 * erf((x + vec2(-c, c)) * (sqrt(0.5) / blur)); 41 return integral.y - integral.x; 51 let center = (lower + upper) * 0.5; 52 let half_size = (upper - lower) * 0.5; 53 let p = point - center; 54 let low = p.y - half_size.y; 55 let high = p.y + half_size.y; 56 let start = clamp(-3. * blur, low, high); 57 let end = clamp(3. * blur, low, high); 58 let step = (end - start) / f32(SAMPLES); 59 var y = start + step * 0.5; 61 for (var i = 0; i < SAMPLES; i++) { 62 let corner = selectCorner(p, corners); 63 value += horizontalRoundedBoxShadow(p.x, p.y - y, blur, corner, half_size) * gaussian(y, blur) * step; 71 @location(0) vertex_position: vec3<f32>, 72 @location(1) uv: vec2<f32>, 73 @location(2) vertex_color: vec4<f32>, 74 @location(3) size: vec2<f32>, 75 @location(4) radius: vec4<f32>, 76 @location(5) blur: f32, 77 @location(6) bounds: vec2<f32>, 78) -> BoxShadowVertexOutput { 79 var out: BoxShadowVertexOutput; 80 out.position = view.clip_from_world * vec4(vertex_position, 1.0); 81 out.point = (uv.xy - 0.5) * bounds; 82 out.color = vertex_color; 91 in: BoxShadowVertexOutput, 92) -> @location(0) vec4<f32> { 93 let g = in.color.a * roundedBoxShadow(-0.5 * in.size, 0.5 * in.size, in.point, max(in.blur, 0.01), in.radius); 94 return vec4(in.color.rgb, g);