1+ #![ cfg_attr( target_arch = "spirv" , no_std) ]
2+ #![ allow( clippy:: missing_safety_doc) ]
3+
4+ use spirv_std:: { spirv, glam:: { vec2, vec4, Vec2 , Vec4 , UVec3 } , Image , num_traits:: Float } ;
5+ use spirv_std:: image:: SampledImage ;
6+
7+ #[ repr( C ) ]
8+ #[ derive( Copy , Clone ) ]
9+ pub struct Particle {
10+ pub pos : Vec2 ,
11+ pub vel : Vec2 ,
12+ pub gradient_pos : Vec4 ,
13+ }
14+
15+ #[ repr( C ) ]
16+ #[ derive( Copy , Clone ) ]
17+ pub struct Ubo {
18+ pub delta_t : f32 ,
19+ pub dest_x : f32 ,
20+ pub dest_y : f32 ,
21+ pub particle_count : i32 ,
22+ }
23+
24+ fn attraction ( pos : Vec2 , attract_pos : Vec2 ) -> Vec2 {
25+ let delta = attract_pos - pos;
26+ const DAMP : f32 = 0.5 ;
27+ let d_damped_dot = delta. dot ( delta) + DAMP ;
28+ let inv_dist = 1.0 / d_damped_dot. sqrt ( ) ;
29+ let inv_dist_cubed = inv_dist * inv_dist * inv_dist;
30+ delta * inv_dist_cubed * 0.0035
31+ }
32+
33+ fn repulsion ( pos : Vec2 , attract_pos : Vec2 ) -> Vec2 {
34+ let delta = attract_pos - pos;
35+ let target_distance = delta. dot ( delta) . sqrt ( ) ;
36+ delta * ( 1.0 / ( target_distance * target_distance * target_distance) ) * -0.000035
37+ }
38+
39+ #[ spirv( compute( threads( 256 , 1 , 1 ) ) ) ]
40+ pub fn main_cs (
41+ #[ spirv( global_invocation_id) ] global_id : UVec3 ,
42+ #[ spirv( storage_buffer, descriptor_set = 0 , binding = 0 ) ] particles : & mut [ Particle ] ,
43+ #[ spirv( uniform, descriptor_set = 0 , binding = 1 ) ] ubo : & Ubo ,
44+ ) {
45+ let index = global_id. x ;
46+ if index >= ubo. particle_count as u32 {
47+ return ;
48+ }
49+
50+ let idx = index as usize ;
51+ let mut vel = particles[ idx] . vel ;
52+ let mut pos = particles[ idx] . pos ;
53+
54+ let dest_pos = vec2 ( ubo. dest_x , ubo. dest_y ) ;
55+
56+ let delta = dest_pos - pos;
57+ let target_distance = delta. dot ( delta) . sqrt ( ) ;
58+ vel += repulsion ( pos, dest_pos) * 0.05 ;
59+
60+ pos += vel * ubo. delta_t ;
61+
62+ if pos. x < -1.0 || pos. x > 1.0 || pos. y < -1.0 || pos. y > 1.0 {
63+ vel = ( -vel * 0.1 ) + attraction ( pos, dest_pos) * 12.0 ;
64+ } else {
65+ particles[ idx] . pos = pos;
66+ }
67+
68+ particles[ idx] . vel = vel;
69+ particles[ idx] . gradient_pos . x += 0.02 * ubo. delta_t ;
70+ if particles[ idx] . gradient_pos . x > 1.0 {
71+ particles[ idx] . gradient_pos . x -= 1.0 ;
72+ }
73+ }
74+
75+ #[ spirv( vertex) ]
76+ pub fn main_vs (
77+ in_pos : Vec2 ,
78+ in_gradient_pos : Vec4 ,
79+ #[ spirv( position) ] out_position : & mut Vec4 ,
80+ #[ spirv( point_size) ] out_point_size : & mut f32 ,
81+ out_color : & mut Vec4 ,
82+ out_gradient_pos : & mut f32 ,
83+ ) {
84+ * out_point_size = 8.0 ;
85+ * out_color = vec4 ( 0.035 , 0.035 , 0.035 , 1.0 ) ;
86+ * out_gradient_pos = in_gradient_pos. x ;
87+ * out_position = vec4 ( in_pos. x , in_pos. y , 1.0 , 1.0 ) ;
88+ }
89+
90+ #[ spirv( fragment) ]
91+ pub fn main_fs (
92+ _in_color : Vec4 ,
93+ in_gradient_pos : f32 ,
94+ #[ spirv( point_coord) ] point_coord : Vec2 ,
95+ #[ spirv( descriptor_set = 0 , binding = 0 ) ] sampler_color_map : & SampledImage < Image ! ( 2 D , type =f32 , sampled) > ,
96+ #[ spirv( descriptor_set = 0 , binding = 1 ) ] sampler_gradient_ramp : & SampledImage < Image ! ( 2 D , type =f32 , sampled) > ,
97+ out_frag_color : & mut Vec4 ,
98+ ) {
99+ let color = sampler_gradient_ramp. sample ( vec2 ( in_gradient_pos, 0.0 ) ) . truncate ( ) ;
100+ let tex_color = sampler_color_map. sample ( point_coord) . truncate ( ) ;
101+ * out_frag_color = vec4 ( tex_color. x * color. x , tex_color. y * color. y , tex_color. z * color. z , 1.0 ) ;
102+ }
0 commit comments