Skip to content

Commit ae5fa9c

Browse files
committed
Add computeparticles rust shader
1 parent ee2a02e commit ae5fa9c

6 files changed

Lines changed: 113 additions & 0 deletions

File tree

shaders/rust/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ members = [
7474
"pushdescriptors/cube",
7575
"descriptorbuffer/cube",
7676
"dynamicrendering/texture",
77+
"computeparticles/particle",
7778
]
7879

7980
[workspace.dependencies]
3.46 KB
Binary file not shown.
880 Bytes
Binary file not shown.
692 Bytes
Binary file not shown.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "computeparticles-particle"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
spirv-std = { workspace = true }
8+
9+
[lib]
10+
crate-type = ["dylib"]
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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!(2D, type=f32, sampled)>,
96+
#[spirv(descriptor_set = 0, binding = 1)] sampler_gradient_ramp: &SampledImage<Image!(2D, 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

Comments
 (0)