Skip to content

Commit e93d523

Browse files
committed
Add deferredmultisampling rust shaders
1 parent 381910c commit e93d523

File tree

16 files changed

+469
-0
lines changed

16 files changed

+469
-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
@@ -27,6 +27,8 @@ members = [
2727
"debugutils/toon",
2828
"deferred/deferred",
2929
"deferred/mrt",
30+
"deferredmultisampling/deferred",
31+
"deferredmultisampling/mrt",
3032
"descriptorbuffer/cube",
3133
"descriptorindexing",
3234
"descriptorsets/cube",
Binary file not shown.
Binary file not shown.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[package]
2+
name = "deferredmultisampling-deferred"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
6+
[lib]
7+
crate-type = ["dylib"]
8+
9+
[dependencies]
10+
spirv-std = { workspace = true }
11+
12+
[package.metadata.rust-gpu.build]
13+
capabilities = ["ImageQuery"]
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#![no_std]
2+
3+
use spirv_std::glam::{ivec2, vec2, vec4, IVec2, UVec2, Vec2, Vec3, Vec4, Vec4Swizzles};
4+
use spirv_std::image::{ImageWithMethods, sample_with};
5+
use spirv_std::{num_traits::Float, spirv, Image};
6+
7+
#[repr(C, align(16))]
8+
#[derive(Copy, Clone)]
9+
pub struct Light {
10+
pub position: Vec4, // 16 bytes, aligned to 16
11+
pub color_radius: Vec4, // 16 bytes - store color.xyz in xyz, radius in w
12+
}
13+
14+
#[repr(C, align(16))]
15+
#[derive(Copy, Clone)]
16+
pub struct UBO {
17+
pub lights: [Light; 6], // 6 * 32 = 192 bytes
18+
pub view_pos: Vec4, // 16 bytes, total = 208 bytes
19+
pub _padding1: Vec4, // 16 bytes padding to align next member to 224
20+
pub debug_display_target: Vec4, // Use Vec4 with debug_display_target in x component
21+
}
22+
23+
#[spirv(vertex)]
24+
pub fn main_vs(
25+
#[spirv(vertex_index)] vert_index: i32,
26+
#[spirv(position)] out_position: &mut Vec4,
27+
out_uv: &mut Vec2,
28+
) {
29+
let uv = vec2(((vert_index << 1) & 2) as f32, (vert_index & 2) as f32);
30+
*out_uv = uv;
31+
*out_position = vec4(uv.x * 2.0 - 1.0, uv.y * 2.0 - 1.0, 0.0, 1.0);
32+
}
33+
34+
const NUM_LIGHTS: usize = 6;
35+
36+
fn resolve(tex: &Image!(2D, format=rgba8, sampled, multisampled), uv: IVec2, num_samples: u32) -> Vec4 {
37+
let mut result = Vec4::ZERO;
38+
for i in 0..num_samples {
39+
let val: Vec4 = tex.fetch_with(uv, sample_with::sample_index(i as i32));
40+
result += val;
41+
}
42+
// Average resolved samples
43+
result / (num_samples as f32)
44+
}
45+
46+
fn calculate_lighting(pos: Vec3, normal: Vec3, albedo: Vec4, ubo: &UBO) -> Vec3 {
47+
let mut result = Vec3::ZERO;
48+
49+
for i in 0..NUM_LIGHTS {
50+
// Vector to light
51+
let l = ubo.lights[i].position.xyz() - pos;
52+
// Distance from light to fragment position
53+
let dist = l.length();
54+
55+
// Viewer to fragment
56+
let v = (ubo.view_pos.xyz() - pos).normalize();
57+
58+
// Light to fragment
59+
let l = l.normalize();
60+
61+
// Attenuation
62+
let atten = ubo.lights[i].color_radius.w / (dist.powf(2.0) + 1.0);
63+
64+
// Diffuse part
65+
let n = normal.normalize();
66+
let n_dot_l = n.dot(l).max(0.0);
67+
let diff = ubo.lights[i].color_radius.xyz() * albedo.xyz() * n_dot_l * atten;
68+
69+
// Specular part
70+
let r = (-l).reflect(n);
71+
let n_dot_r = r.dot(v).max(0.0);
72+
let spec = ubo.lights[i].color_radius.xyz() * albedo.w * n_dot_r.powf(8.0) * atten;
73+
74+
result += diff + spec;
75+
}
76+
result
77+
}
78+
79+
#[spirv(fragment)]
80+
pub fn main_fs(
81+
in_uv: Vec2,
82+
#[spirv(descriptor_set = 0, binding = 1)] sampler_position: &Image!(2D, format=rgba16f, sampled, multisampled),
83+
#[spirv(descriptor_set = 0, binding = 2)] sampler_normal: &Image!(2D, format=rgba16f, sampled, multisampled),
84+
#[spirv(descriptor_set = 0, binding = 3)] sampler_albedo: &Image!(2D, format=rgba8, sampled, multisampled),
85+
#[spirv(uniform, descriptor_set = 0, binding = 4)] ubo: &UBO,
86+
#[spirv(spec_constant(id = 0, default = 8))] num_samples: u32,
87+
out_frag_color: &mut Vec4,
88+
) {
89+
let att_dim: UVec2 = sampler_position.query_size();
90+
let uv = ivec2((in_uv.x * att_dim.x as f32) as i32, (in_uv.y * att_dim.y as f32) as i32);
91+
92+
// Debug display
93+
if ubo.debug_display_target.x as i32 > 0 {
94+
let val: Vec4 = match ubo.debug_display_target.x as i32 {
95+
1 => sampler_position.fetch_with(uv, sample_with::sample_index(0)),
96+
2 => sampler_normal.fetch_with(uv, sample_with::sample_index(0)),
97+
3 => sampler_albedo.fetch_with(uv, sample_with::sample_index(0)),
98+
4 => {
99+
let alb: Vec4 = sampler_albedo.fetch_with(uv, sample_with::sample_index(0));
100+
vec4(alb.w, alb.w, alb.w, 1.0)
101+
},
102+
_ => Vec4::ZERO,
103+
};
104+
*out_frag_color = vec4(val.x, val.y, val.z, 1.0);
105+
return;
106+
}
107+
108+
const AMBIENT: f32 = 0.15;
109+
110+
// Ambient part
111+
let alb = resolve(sampler_albedo, uv, num_samples);
112+
let mut frag_color = Vec3::ZERO;
113+
114+
// Calculate lighting for every MSAA sample
115+
for i in 0..num_samples {
116+
let pos: Vec4 = sampler_position.fetch_with(uv, sample_with::sample_index(i as i32));
117+
let normal: Vec4 = sampler_normal.fetch_with(uv, sample_with::sample_index(i as i32));
118+
let albedo: Vec4 = sampler_albedo.fetch_with(uv, sample_with::sample_index(i as i32));
119+
frag_color += calculate_lighting(pos.xyz(), normal.xyz(), albedo, ubo);
120+
}
121+
122+
frag_color = (alb.xyz() * AMBIENT) + frag_color / (num_samples as f32);
123+
124+
*out_frag_color = vec4(frag_color.x, frag_color.y, frag_color.z, 1.0);
125+
}
Binary file not shown.
10.8 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 = "deferredmultisampling-mrt"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
6+
[lib]
7+
crate-type = ["dylib"]
8+
9+
[dependencies]
10+
spirv-std = { workspace = true }
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#![no_std]
2+
3+
use spirv_std::glam::{vec4, Mat3, Mat4, Vec2, Vec3, Vec4, Vec4Swizzles};
4+
use spirv_std::spirv;
5+
use spirv_std::Image;
6+
use spirv_std::image::SampledImage;
7+
8+
#[repr(C)]
9+
#[derive(Copy, Clone)]
10+
pub struct UBO {
11+
pub projection: Mat4,
12+
pub model: Mat4,
13+
pub view: Mat4,
14+
pub instance_pos: [Vec4; 3],
15+
}
16+
17+
#[spirv(vertex)]
18+
pub fn main_vs(
19+
in_pos: Vec4,
20+
in_uv: Vec2,
21+
in_color: Vec3,
22+
in_normal: Vec3,
23+
in_tangent: Vec3,
24+
#[spirv(instance_index)] instance_index: i32,
25+
#[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &UBO,
26+
#[spirv(position)] out_position: &mut Vec4,
27+
out_normal: &mut Vec3,
28+
out_uv: &mut Vec2,
29+
out_color: &mut Vec3,
30+
out_world_pos: &mut Vec3,
31+
out_tangent: &mut Vec3,
32+
) {
33+
let tmp_pos = vec4(in_pos.x, in_pos.y, in_pos.z, 1.0) + ubo.instance_pos[instance_index as usize];
34+
35+
*out_position = ubo.projection * ubo.view * ubo.model * tmp_pos;
36+
37+
*out_uv = in_uv;
38+
39+
// Vertex position in world space
40+
*out_world_pos = (ubo.model * tmp_pos).xyz();
41+
42+
// Normal in world space
43+
let m_normal = Mat3::from_mat4(ubo.model).inverse().transpose();
44+
*out_normal = (m_normal * in_normal.normalize()).normalize();
45+
*out_tangent = (m_normal * in_tangent.normalize()).normalize();
46+
47+
// Currently just vertex color
48+
*out_color = in_color;
49+
}
50+
51+
#[spirv(fragment)]
52+
pub fn main_fs(
53+
in_normal: Vec3,
54+
in_uv: Vec2,
55+
_in_color: Vec3,
56+
in_world_pos: Vec3,
57+
in_tangent: Vec3,
58+
#[spirv(descriptor_set = 0, binding = 1)] sampler_color: &SampledImage<Image!(2D, type=f32, sampled)>,
59+
#[spirv(descriptor_set = 0, binding = 2)] sampler_normal_map: &SampledImage<Image!(2D, type=f32, sampled)>,
60+
out_position: &mut Vec4,
61+
out_normal: &mut Vec4,
62+
out_albedo: &mut Vec4,
63+
) {
64+
*out_position = vec4(in_world_pos.x, in_world_pos.y, in_world_pos.z, 1.0);
65+
66+
// Calculate normal in tangent space
67+
let n = in_normal.normalize();
68+
let t = in_tangent.normalize();
69+
let b = n.cross(t);
70+
let tbn = Mat3::from_cols(t, b, n);
71+
let sampled_normal = sampler_normal_map.sample(in_uv).xyz() * 2.0 - Vec3::splat(1.0);
72+
let tnorm = tbn * sampled_normal.normalize();
73+
*out_normal = vec4(tnorm.x, tnorm.y, tnorm.z, 1.0);
74+
75+
*out_albedo = sampler_color.sample(in_uv);
76+
}

0 commit comments

Comments
 (0)