1#import bevy_render::view::View;2#import bevy_render::globals::Globals;4@group(0) @binding(0)5var<uniform> view: View;6@group(0) @binding(1)7var<uniform> globals: Globals;9@group(1) @binding(0) var sprite_texture: texture_2d<f32>;10@group(1) @binding(1) var sprite_sampler: sampler;12struct UiVertexOutput {13 @location(0) uv: vec2<f32>,14 @location(1) color: vec4<f32>,16 // Defines the dividing line that are used to split the texture atlas rect into corner, side and center slices17 // The distances are normalized and from the top left corner of the texture atlas rect18 // x = distance of the left vertical dividing line19 // y = distance of the top horizontal dividing line20 // z = distance of the right vertical dividing line21 // w = distance of the bottom horizontal dividing line22 @location(2) @interpolate(flat) texture_slices: vec4<f32>,24 // Defines the dividing line that are used to split the render target into corner, side and center slices25 // The distances are normalized and from the top left corner of the render target26 // x = distance of left vertical dividing line27 // y = distance of top horizontal dividing line28 // z = distance of right vertical dividing line29 // w = distance of bottom horizontal dividing line30 @location(3) @interpolate(flat) target_slices: vec4<f32>,32 // The number of times the side or center texture slices should be repeated when mapping them to the border slices33 // x = number of times to repeat along the horizontal axis for the side textures34 // y = number of times to repeat along the vertical axis for the side textures35 // z = number of times to repeat along the horizontal axis for the center texture36 // w = number of times to repeat along the vertical axis for the center texture37 @location(4) @interpolate(flat) repeat: vec4<f32>,39 // normalized texture atlas rect coordinates40 // x, y = top, left corner of the atlas rect41 // z, w = bottom, right corner of the atlas rect42 @location(5) @interpolate(flat) atlas_rect: vec4<f32>,43 @builtin(position) position: vec4<f32>,44}46@vertex47fn vertex(48 @location(0) vertex_position: vec3<f32>,49 @location(1) vertex_uv: vec2<f32>,50 @location(2) vertex_color: vec4<f32>,51 @location(3) texture_slices: vec4<f32>,52 @location(4) target_slices: vec4<f32>,53 @location(5) repeat: vec4<f32>,54 @location(6) atlas_rect: vec4<f32>,55) -> UiVertexOutput {56 var out: UiVertexOutput;57 out.uv = vertex_uv;58 out.color = vertex_color;59 out.position = view.clip_from_world * vec4<f32>(vertex_position, 1.0);60 out.texture_slices = texture_slices;61 out.target_slices = target_slices;62 out.repeat = repeat;63 out.atlas_rect = atlas_rect;64 return out;65}67/// maps a point along the axis of the render target to slice coordinates68fn map_axis_with_repeat(69 // normalized distance along the axis70 p: f32,71 // target min dividing point72 il: f32,73 // target max dividing point74 ih: f32,75 // slice min dividing point76 tl: f32,77 // slice max dividing point78 th: f32,79 // number of times to repeat the slice for sides and the center80 r: f32,81) -> f32 {82 if p < il {83 // inside one of the two left (horizontal axis) or top (vertical axis) corners84 return (p / il) * tl;85 } else if ih < p {86 // inside one of the two (horizontal axis) or top (vertical axis) corners87 return th + ((p - ih) / (1 - ih)) * (1 - th);88 } else {89 // not inside a corner, repeat the texture90 return tl + fract((r * (p - il)) / (ih - il)) * (th - tl);91 }92}94fn map_uvs_to_slice(95 uv: vec2<f32>,96 target_slices: vec4<f32>,97 texture_slices: vec4<f32>,98 repeat: vec4<f32>,99) -> vec2<f32> {100 var r: vec2<f32>;101 if target_slices.x <= uv.x && uv.x <= target_slices.z && target_slices.y <= uv.y && uv.y <= target_slices.w {102 // use the center repeat values if the uv coords are inside the center slice of the target103 r = repeat.zw;104 } else {105 // use the side repeat values if the uv coords are outside the center slice106 r = repeat.xy;107 }109 // map horizontal axis110 let x = map_axis_with_repeat(uv.x, target_slices.x, target_slices.z, texture_slices.x, texture_slices.z, r.x);112 // map vertical axis113 let y = map_axis_with_repeat(uv.y, target_slices.y, target_slices.w, texture_slices.y, texture_slices.w, r.y);115 return vec2(x, y);116}118@fragment119fn fragment(in: UiVertexOutput) -> @location(0) vec4<f32> {120 // map the target uvs to slice coords121 let uv = map_uvs_to_slice(in.uv, in.target_slices, in.texture_slices, in.repeat);123 // map the slice coords to texture coords124 let atlas_uv = in.atlas_rect.xy + uv * (in.atlas_rect.zw - in.atlas_rect.xy);126 return in.color * textureSample(sprite_texture, sprite_sampler, atlas_uv);127}