1#import bevy_render::view::View 2#import bevy_hanabi::vfx_common::{ 3 IndirectBuffer, SimParams, Spawner, 4 seed, tau, pcg_hash, to_float01, frand, frand2, frand3, frand4, 5 rand_uniform_f, rand_uniform_vec2, rand_uniform_vec3, rand_uniform_vec4, 6 rand_normal_f, rand_normal_vec2, rand_normal_vec3, rand_normal_vec4, proj 13struct ParticleBuffer { 14 particles: array<Particle>, 18 @builtin(position) position: vec4<f32>, 19 @location(0) color: vec4<f32>, 21 @location(1) uv: vec2<f32>, 24 @location(2) normal: vec3<f32>, 28@group(0) @binding(0) var<uniform> view: View; 29@group(0) @binding(1) var<uniform> sim_params : SimParams; 31@group(1) @binding(0) var<storage, read> particle_buffer : ParticleBuffer; 32@group(1) @binding(1) var<storage, read> indirect_buffer : IndirectBuffer; 33@group(1) @binding(2) var<storage, read> spawner : Spawner; 37fn get_camera_position_effect_space() -> vec3<f32> { 38 let view_pos = view.world_from_view[3].xyz; 39#ifdef LOCAL_SPACE_SIMULATION 40 let inverse_transform = transpose( 42 spawner.inverse_transform[0].xyz, 43 spawner.inverse_transform[1].xyz, 44 spawner.inverse_transform[2].xyz, 47 return inverse_transform * view_pos; 53fn get_camera_rotation_effect_space() -> mat3x3<f32> { 54 let view_rot = mat3x3(view.world_from_view[0].xyz, view.world_from_view[1].xyz, view.world_from_view[2].xyz); 55#ifdef LOCAL_SPACE_SIMULATION 56 let inverse_transform = transpose( 58 spawner.inverse_transform[0].xyz, 59 spawner.inverse_transform[1].xyz, 60 spawner.inverse_transform[2].xyz, 63 return inverse_transform * view_rot; 70fn unpack_compressed_transform(compressed_transform: mat3x4<f32>) -> mat4x4<f32> { 73 compressed_transform[0], 74 compressed_transform[1], 75 compressed_transform[2], 76 vec4<f32>(0.0, 0.0, 0.0, 1.0) 82fn unpack_compressed_transform_3x3_transpose(compressed_transform: mat3x4<f32>) -> mat3x3<f32> { 84 compressed_transform[0].xyz, 85 compressed_transform[1].xyz, 86 compressed_transform[2].xyz, 94fn transform_position_simulation_to_world(sim_position: vec3<f32>) -> vec4<f32> { 95#ifdef LOCAL_SPACE_SIMULATION 96 let transform = unpack_compressed_transform(spawner.transform); 97 return transform * vec4<f32>(sim_position, 1.0); 99 return vec4<f32>(sim_position, 1.0); 103fn transform_normal_simulation_to_world(sim_normal: vec3<f32>) -> vec3<f32> { 104#ifdef LOCAL_SPACE_SIMULATION 108 let transform = unpack_compressed_transform_3x3_transpose(spawner.inverse_transform); 109 return transform * sim_normal; 121fn transform_position_simulation_to_clip(sim_position: vec3<f32>) -> vec4<f32> { 122 return view.clip_from_world * transform_position_simulation_to_world(sim_position); 125fn inverse_transpose_mat3(m: mat3x3<f32>) -> mat3x3<f32> { 126 let tmp0 = cross(m[1], m[2]); 127 let tmp1 = cross(m[2], m[0]); 128 let tmp2 = cross(m[0], m[1]); 129 let inv_det = 1.0 / dot(m[2], tmp2); 130 return mat3x3<f32>(tmp0 * inv_det, tmp1 * inv_det, tmp2 * inv_det); 137 @builtin(instance_index) instance_index: u32, 138 @location(0) vertex_position: vec3<f32>, 140 @location(1) vertex_uv: vec2<f32>, 143 @location(2) vertex_normal: vec3<f32>, 149 let pong = spawner.render_pong; 150 let particle_index = indirect_buffer.indices[3u * instance_index + pong]; 151 var particle = particle_buffer.particles[particle_index]; 153 var out: VertexOutput; 157 if (instance_index == 0) { 158 out.position = vec4(0.0); 163 let prev_index = indirect_buffer.indices[3u * (instance_index - 1u) + pong]; 164 let prev_particle = particle_buffer.particles[prev_index]; 168 if (prev_particle.ribbon_id != particle.ribbon_id) { 169 out.position = vec4(0.0); 178 let row_count = {{FLIPBOOK_ROW_COUNT}}; 179 let ij = vec2<f32>(f32(particle.sprite_index % row_count), f32(particle.sprite_index / row_count)); 180 uv = (ij + uv) * {{FLIPBOOK_SCALE}}; 190 var delta = particle.position - prev_particle.position; 192 axis_x = normalize(delta); 193 axis_y = normalize(cross(axis_x, axis_z)); 194 axis_z = cross(axis_x, axis_y); 196 position = mix(particle.position, prev_particle.position, 0.5); 197 size = vec3(length(delta), size.y, 1.0); 202 let vpos = vertex_position * size; 203 let sim_position = position + axis_x * vpos.x + axis_y * vpos.y + axis_z * vpos.z; 204 out.position = transform_position_simulation_to_clip(sim_position); 209 let normal = inverse_transpose_mat3(mat3x3(axis_x, axis_y, axis_z)) * vertex_normal; 210 out.normal = transform_normal_simulation_to_world(normal); 211#endif // NEEDS_NORMAL 217fn fragment(in: VertexOutput) -> @location(0) vec4<f32> { 220 var alpha_cutoff: f32 = {{ALPHA_CUTOFF}}; 222 var color = in.color; 227 var normal = in.normal; 230{{FRAGMENT_MODIFIERS}} 233 if color.a >= alpha_cutoff {