Skip to content

Commit bb3d516

Browse files
committed
Add particlesystem rust shaders
1 parent c49d4e4 commit bb3d516

File tree

10 files changed

+225
-0
lines changed

10 files changed

+225
-0
lines changed

shaders/rust/Cargo.lock

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

shaders/rust/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ members = [
6565
"offscreen/phong",
6666
"offscreen/quad",
6767
"parallaxmapping/parallax",
68+
"particlesystem/particle",
69+
"particlesystem/normalmap",
6870
"pbrbasic/pbr",
6971
"pbribl/filtercube",
7072
"pbribl/genbrdflut",
3.22 KB
Binary file not shown.
8.04 KB
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 = "particlesystem-normalmap"
3+
version = "0.1.0"
4+
edition.workspace = true
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::{mat3, vec3, vec4, Mat4, Vec2, Vec3, Vec4}, num_traits::Float};
5+
6+
#[repr(C)]
7+
#[derive(Copy, Clone)]
8+
pub struct Ubo {
9+
pub projection: Mat4,
10+
pub model: Mat4,
11+
pub normal: Mat4,
12+
pub light_pos: Vec4,
13+
}
14+
15+
#[spirv(vertex)]
16+
pub fn main_vs(
17+
in_pos: Vec3,
18+
in_uv: Vec2,
19+
in_normal: Vec3,
20+
in_tangent: Vec4,
21+
#[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &Ubo,
22+
#[spirv(position)] out_position: &mut Vec4,
23+
out_uv: &mut Vec2,
24+
out_light_vec: &mut Vec3,
25+
out_light_vec_b: &mut Vec3,
26+
out_light_dir: &mut Vec3,
27+
out_view_vec: &mut Vec3,
28+
) {
29+
let vertex_position = (ubo.model * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0)).truncate();
30+
*out_light_dir = (ubo.light_pos.truncate() - vertex_position).normalize();
31+
32+
let bi_tangent = in_normal.cross(in_tangent.truncate());
33+
34+
// Setup (t)angent-(b)inormal-(n)ormal matrix for converting
35+
// object coordinates into tangent space
36+
let normal_mat3 = mat3(
37+
ubo.normal.x_axis.truncate(),
38+
ubo.normal.y_axis.truncate(),
39+
ubo.normal.z_axis.truncate(),
40+
);
41+
let tbn_matrix = mat3(
42+
normal_mat3 * in_tangent.truncate(),
43+
normal_mat3 * bi_tangent,
44+
normal_mat3 * in_normal
45+
);
46+
47+
*out_light_vec = tbn_matrix.transpose() * (ubo.light_pos.truncate() - vertex_position);
48+
49+
let light_dist = ubo.light_pos.truncate() - in_pos;
50+
*out_light_vec_b = vec3(
51+
in_tangent.truncate().dot(light_dist),
52+
bi_tangent.dot(light_dist),
53+
in_normal.dot(light_dist)
54+
);
55+
56+
*out_view_vec = vec3(
57+
in_tangent.truncate().dot(in_pos),
58+
bi_tangent.dot(in_pos),
59+
in_normal.dot(in_pos)
60+
);
61+
62+
*out_uv = in_uv;
63+
64+
*out_position = ubo.projection * ubo.model * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0);
65+
}
66+
67+
const LIGHT_RADIUS: f32 = 45.0;
68+
69+
#[spirv(fragment)]
70+
pub fn main_fs(
71+
in_uv: Vec2,
72+
in_light_vec: Vec3,
73+
in_light_vec_b: Vec3,
74+
_in_light_dir: Vec3,
75+
in_view_vec: Vec3,
76+
#[spirv(descriptor_set = 0, binding = 1)] s_color_map: &spirv_std::image::SampledImage<spirv_std::Image!(2D, type=f32, sampled)>,
77+
#[spirv(descriptor_set = 0, binding = 2)] s_normal_height_map: &spirv_std::image::SampledImage<spirv_std::Image!(2D, type=f32, sampled)>,
78+
out_frag_color: &mut Vec4,
79+
) {
80+
let specular_color = vec3(0.85, 0.5, 0.0);
81+
82+
let inv_radius = 1.0 / LIGHT_RADIUS;
83+
let ambient = 0.25;
84+
85+
let rgb = s_color_map.sample(in_uv).truncate();
86+
let normal = ((s_normal_height_map.sample(in_uv).truncate() - 0.5) * 2.0).normalize();
87+
88+
let dist_sqr = in_light_vec_b.dot(in_light_vec_b);
89+
let l_vec = in_light_vec_b * (1.0 / dist_sqr.sqrt());
90+
91+
let atten = (1.0 - inv_radius * dist_sqr.sqrt()).clamp(0.0, 1.0).max(ambient);
92+
let diffuse = l_vec.dot(normal).clamp(0.0, 1.0);
93+
94+
let light = (-in_light_vec).normalize();
95+
let view = in_view_vec.normalize();
96+
let reflect_dir = (-light).reflect(normal);
97+
98+
let specular = view.dot(reflect_dir).max(0.0).powf(4.0);
99+
100+
let final_color = (rgb * atten + (diffuse * rgb + 0.5 * specular * specular_color)) * atten;
101+
*out_frag_color = vec4(final_color.x, final_color.y, final_color.z, 1.0);
102+
}
1.92 KB
Binary file not shown.
5.46 KB
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 = "particlesystem-particle"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
6+
[dependencies]
7+
spirv-std = { workspace = true }
8+
9+
[lib]
10+
crate-type = ["dylib"]
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#![cfg_attr(target_arch = "spirv", no_std)]
2+
#![allow(clippy::missing_safety_doc)]
3+
4+
use spirv_std::{spirv, glam::{vec4, Mat4, Vec2, Vec4}, num_traits::Float};
5+
6+
#[repr(C)]
7+
#[derive(Copy, Clone)]
8+
pub struct Ubo {
9+
pub projection: Mat4,
10+
pub modelview: Mat4,
11+
pub viewport_dim: Vec2,
12+
pub point_size: f32,
13+
}
14+
15+
#[spirv(vertex)]
16+
pub fn main_vs(
17+
in_pos: Vec4,
18+
in_color: Vec4,
19+
in_alpha: f32,
20+
in_size: f32,
21+
in_rotation: f32,
22+
in_type: i32,
23+
#[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &Ubo,
24+
#[spirv(position)] out_position: &mut Vec4,
25+
#[spirv(point_size)] out_point_size: &mut f32,
26+
out_color: &mut Vec4,
27+
out_alpha: &mut f32,
28+
#[spirv(flat)] out_type: &mut i32,
29+
out_rotation: &mut f32,
30+
) {
31+
*out_color = in_color;
32+
*out_alpha = in_alpha;
33+
*out_type = in_type;
34+
*out_rotation = in_rotation;
35+
36+
*out_position = ubo.projection * ubo.modelview * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0);
37+
38+
// Base size of the point sprites
39+
let sprite_size = 8.0 * in_size;
40+
41+
// Scale particle size depending on camera projection
42+
let eye_pos = ubo.modelview * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0);
43+
let projected_corner = ubo.projection * vec4(0.5 * sprite_size, 0.5 * sprite_size, eye_pos.z, eye_pos.w);
44+
*out_point_size = ubo.viewport_dim.x * projected_corner.x / projected_corner.w;
45+
}
46+
47+
#[spirv(fragment)]
48+
pub fn main_fs(
49+
#[spirv(point_coord)] point_coord: Vec2,
50+
in_color: Vec4,
51+
in_alpha: f32,
52+
#[spirv(flat)] in_type: i32,
53+
in_rotation: f32,
54+
#[spirv(descriptor_set = 0, binding = 1)] sampler_smoke: &spirv_std::image::SampledImage<spirv_std::Image!(2D, type=f32, sampled)>,
55+
#[spirv(descriptor_set = 0, binding = 2)] sampler_fire: &spirv_std::image::SampledImage<spirv_std::Image!(2D, type=f32, sampled)>,
56+
out_frag_color: &mut Vec4,
57+
) {
58+
let alpha = if in_alpha <= 1.0 { in_alpha } else { 2.0 - in_alpha };
59+
60+
// Rotate texture coordinates
61+
let rot_center = 0.5;
62+
let rot_cos = in_rotation.cos();
63+
let rot_sin = in_rotation.sin();
64+
let rot_uv = Vec2::new(
65+
rot_cos * (point_coord.x - rot_center) + rot_sin * (point_coord.y - rot_center) + rot_center,
66+
rot_cos * (point_coord.y - rot_center) - rot_sin * (point_coord.x - rot_center) + rot_center
67+
);
68+
69+
let color = if in_type == 0 {
70+
// Flame
71+
let c = sampler_fire.sample(rot_uv);
72+
out_frag_color.w = 0.0;
73+
c
74+
} else {
75+
// Smoke
76+
let c = sampler_smoke.sample(rot_uv);
77+
out_frag_color.w = c.w * alpha;
78+
c
79+
};
80+
81+
*out_frag_color = vec4(
82+
color.x * in_color.x * alpha,
83+
color.y * in_color.y * alpha,
84+
color.z * in_color.z * alpha,
85+
out_frag_color.w
86+
);
87+
}

0 commit comments

Comments
 (0)