2 mesh2d_functions as mesh_functions, 3 mesh2d_vertex_output::VertexOutput, 4 mesh2d_view_bindings::view, 7#ifdef TONEMAP_IN_SHADER 8#import bevy_core_pipeline::tonemapping 11#import bevy_render::color_operations::linear_to_srgb 14#import bevy_render::color_operations::linear_rgb_to_oklab 18 @builtin(instance_index) instance_index: u32, 19#ifdef VERTEX_POSITIONS 20 @location(0) position: vec3<f32>, 23 @location(1) normal: vec3<f32>, 26 @location(2) uv: vec2<f32>, 29 @location(3) tangent: vec4<f32>, 32 @location(4) color: vec4<f32>, 37fn vertex(vertex: Vertex) -> VertexOutput { 38 var out: VertexOutput; 44#ifdef VERTEX_POSITIONS 45 var world_from_local = mesh_functions::get_world_from_local(vertex.instance_index); 46 let position = vec4<f32>(vertex.position * vec3<f32>(material.vertex_scale, 1.0) + vec3<f32>(material.vertex_offset, 0.0), 1.0); 48 out.world_position = mesh_functions::mesh2d_position_local_to_world( 52 out.position = mesh_functions::mesh2d_position_world_to_clip(out.world_position); 56 out.world_normal = mesh_functions::mesh2d_normal_local_to_world(vertex.normal, vertex.instance_index); 60 out.world_tangent = mesh_functions::mesh2d_tangent_local_to_world( 67 out.color = vertex.color; 72struct SpriteMaterial { 76 vertex_scale: vec2<f32>, 77 vertex_offset: vec2<f32>, 78 uv_transform: mat3x3<f32>, 80 tile_stretch_value: vec2<f32>, 85 side_stretch_value: vec2<f32>, 86 center_stretch_value: vec2<f32>, 89const SPRITE_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS: u32 = 3221225472u; 90const SPRITE_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE: u32 = 0u; 91const SPRITE_MATERIAL_FLAGS_ALPHA_MODE_MASK: u32 = 1073741824u; 92const SPRITE_MATERIAL_FLAGS_ALPHA_MODE_BLEND: u32 = 2147483648u; 94const SPRITE_MATERIAL_FLAGS_FLIP_X: u32 = 1u; 95const SPRITE_MATERIAL_FLAGS_FLIP_Y: u32 = 2u; 96const SPRITE_MATERIAL_FLAGS_TILE_X: u32 = 4u; 97const SPRITE_MATERIAL_FLAGS_TILE_Y: u32 = 8u; 99@group(#{MATERIAL_BIND_GROUP}) @binding(0) var<uniform> material: SpriteMaterial; 100@group(#{MATERIAL_BIND_GROUP}) @binding(1) var texture: texture_2d<f32>; 101@group(#{MATERIAL_BIND_GROUP}) @binding(2) var texture_sampler: sampler; 106) -> @location(0) vec4<f32> { 110 if (material.flags & SPRITE_MATERIAL_FLAGS_FLIP_X) != 0u { 113 if (material.flags & SPRITE_MATERIAL_FLAGS_FLIP_Y) != 0u { 117 if (material.flags & SPRITE_MATERIAL_FLAGS_TILE_X) != 0u { 118 uv.x = (uv.x - material.tile_stretch_value.x * floor(uv.x / material.tile_stretch_value.x)) / material.tile_stretch_value.x; 120 if (material.flags & SPRITE_MATERIAL_FLAGS_TILE_Y) != 0u { 121 uv.y = (uv.y - material.tile_stretch_value.y * floor(uv.y / material.tile_stretch_value.y)) / material.tile_stretch_value.y; 125 if material.scale.x != 0.0 { 126 uv = apply_slicing(uv); 129 uv = (material.uv_transform * vec3(uv, 1.0)).xy; 131 let sprite_color = textureSample(texture, texture_sampler, uv); 132 var output_color = alpha_discard(sprite_color * material.color); 134#ifdef TONEMAP_IN_SHADER 135 output_color = tonemapping::tone_mapping(output_color, view.color_grading); 139 output_color = vec4(linear_to_srgb(output_color.rgb), output_color.a); 143 output_color = vec4(linear_rgb_to_oklab(output_color.rgb), output_color.a); 149fn apply_slicing(uv: vec2<f32>) -> vec2<f32> { 150 let min_inset_scaled = material.min_inset / material.scale; 151 let max_inset_scaled = material.max_inset / material.scale; 153 let left = uv.x < min_inset_scaled.x; 154 let right = uv.x > 1.0 - max_inset_scaled.x; 155 let top = uv.y < min_inset_scaled.y; 156 let bottom = uv.y > 1.0 - max_inset_scaled.y; 160 return uv * material.scale; 166 1.0 - (1.0 - uv.x) * material.scale.x, 167 uv.y * material.scale.y, 174 uv.x * material.scale.x, 175 1.0 - (1.0 - uv.y) * material.scale.y 181 return vec2<f32>(1.0) - (vec2<f32>(1.0) - uv) * material.scale; 187 tile_or_stretch(uv.x, min_inset_scaled.x, 1.0 - max_inset_scaled.x, material.min_inset.x, 1.0 - material.max_inset.x, material.side_stretch_value.x), 188 uv.y * material.scale.y 195 tile_or_stretch(uv.x, min_inset_scaled.x, 1.0 - max_inset_scaled.x, material.min_inset.x, 1.0 - material.max_inset.x, material.side_stretch_value.x), 196 1.0 - (1.0 - uv.y) * material.scale.y 203 uv.x * material.scale.x, 204 tile_or_stretch(uv.y, min_inset_scaled.y, 1.0 - max_inset_scaled.y, material.min_inset.y, 1.0 - material.max_inset.y, material.side_stretch_value.y) 211 1.0 - (1.0 - uv.x) * material.scale.x, 212 tile_or_stretch(uv.y, min_inset_scaled.y, 1.0 - max_inset_scaled.y, material.min_inset.y, 1.0 - material.max_inset.y, material.side_stretch_value.y) 218 tile_or_stretch(uv.x, min_inset_scaled.x, 1.0 - max_inset_scaled.x, material.min_inset.x, 1.0 - material.max_inset.x, material.center_stretch_value.x), 219 tile_or_stretch(uv.y, min_inset_scaled.y, 1.0 - max_inset_scaled.y, material.min_inset.y, 1.0 - material.max_inset.y, material.center_stretch_value.y) 224fn tile_or_stretch(p: f32, a: f32, b: f32, c: f32, d: f32, stretch_value: f32) -> f32 { 225 if stretch_value == 0.0 { 226 return stretch_interval(p, a, b, c, d); 228 return tile_interval(p, a, b, c, d, stretch_value); 232fn tile_interval(p: f32, a: f32, b: f32, c: f32, d: f32, stretch_value: f32) -> f32 { 233 let value = (p - a) / (b - a); 234 let tile_value = (value - stretch_value * floor(value / stretch_value)) / stretch_value; 235 return tile_value * (d - c) + c; 239fn stretch_interval(p: f32, a: f32, b: f32, c: f32, d: f32) -> f32 { 240 return (p - a) / (b - a) * (d - c) + c; 243fn alpha_discard(output_color: vec4<f32>) -> vec4<f32> { 244 var color = output_color; 245 let alpha_mode = material.flags & SPRITE_MATERIAL_FLAGS_ALPHA_MODE_RESERVED_BITS; 247 if alpha_mode == SPRITE_MATERIAL_FLAGS_ALPHA_MODE_OPAQUE { 253 else if alpha_mode == SPRITE_MATERIAL_FLAGS_ALPHA_MODE_MASK { 254 if color.a >= material.alpha_cutoff {