Skip to content

Commit 87b4e69

Browse files
committed
Add inlineuniformblocks rust shader
1 parent 7c74957 commit 87b4e69

File tree

6 files changed

+154
-0
lines changed

6 files changed

+154
-0
lines changed

shaders/rust/Cargo.lock

Lines changed: 7 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ members = [
4444
"indirectdraw/ground",
4545
"indirectdraw/indirectdraw",
4646
"indirectdraw/skysphere",
47+
"inlineuniformblocks/pbr",
4748
"instancing/instancing",
4849
"instancing/planet",
4950
"instancing/starfield",
4.73 KB
Binary file not shown.
6.17 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 = "inlineuniformblocks-pbr"
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: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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, Vec3, Vec4}, num_traits::Float};
5+
use core::f32::consts::PI;
6+
7+
#[repr(C)]
8+
#[derive(Copy, Clone)]
9+
pub struct Ubo {
10+
pub projection: Mat4,
11+
pub model: Mat4,
12+
pub view: Mat4,
13+
pub cam_pos: Vec3,
14+
}
15+
16+
#[repr(C)]
17+
#[derive(Copy, Clone)]
18+
pub struct PushConsts {
19+
pub obj_pos: Vec3,
20+
}
21+
22+
#[repr(C)]
23+
#[derive(Copy, Clone)]
24+
pub struct UniformInline {
25+
pub roughness: f32,
26+
pub metallic: f32,
27+
pub r: f32,
28+
pub g: f32,
29+
pub b: f32,
30+
pub ambient: f32,
31+
}
32+
33+
#[spirv(vertex)]
34+
pub fn main_vs(
35+
in_pos: Vec3,
36+
in_normal: Vec3,
37+
#[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &Ubo,
38+
#[spirv(push_constant)] push_consts: &PushConsts,
39+
#[spirv(position)] out_position: &mut Vec4,
40+
out_world_pos: &mut Vec3,
41+
out_normal: &mut Vec3,
42+
) {
43+
let loc_pos = (ubo.model * vec4(in_pos.x, in_pos.y, in_pos.z, 1.0)).truncate();
44+
*out_world_pos = loc_pos + push_consts.obj_pos;
45+
let model_mat3 = mat3(
46+
ubo.model.x_axis.truncate(),
47+
ubo.model.y_axis.truncate(),
48+
ubo.model.z_axis.truncate(),
49+
);
50+
*out_normal = model_mat3 * in_normal;
51+
*out_position = ubo.projection * ubo.view * vec4(out_world_pos.x, out_world_pos.y, out_world_pos.z, 1.0);
52+
}
53+
54+
// Normal Distribution function --------------------------------------
55+
fn d_ggx(dot_nh: f32, roughness: f32) -> f32 {
56+
let alpha = roughness * roughness;
57+
let alpha2 = alpha * alpha;
58+
let denom = dot_nh * dot_nh * (alpha2 - 1.0) + 1.0;
59+
alpha2 / (PI * denom * denom)
60+
}
61+
62+
// Geometric Shadowing function --------------------------------------
63+
fn g_schlicksmith_ggx(dot_nl: f32, dot_nv: f32, roughness: f32) -> f32 {
64+
let r = roughness + 1.0;
65+
let k = (r * r) / 8.0;
66+
let gl = dot_nl / (dot_nl * (1.0 - k) + k);
67+
let gv = dot_nv / (dot_nv * (1.0 - k) + k);
68+
gl * gv
69+
}
70+
71+
// Fresnel function ----------------------------------------------------
72+
fn f_schlick(cos_theta: f32, metallic: f32, material_color: Vec3) -> Vec3 {
73+
let f0 = vec3(0.04, 0.04, 0.04).lerp(material_color, metallic);
74+
f0 + (vec3(1.0, 1.0, 1.0) - f0) * (1.0 - cos_theta).powf(5.0)
75+
}
76+
77+
// Specular BRDF composition --------------------------------------------
78+
fn brdf(l: Vec3, v: Vec3, n: Vec3, metallic: f32, roughness: f32, material_color: Vec3) -> Vec3 {
79+
// Precalculate vectors and dot products
80+
let h = (v + l).normalize();
81+
let dot_nv = n.dot(v).clamp(0.0, 1.0);
82+
let dot_nl = n.dot(l).clamp(0.0, 1.0);
83+
let _dot_lh = l.dot(h).clamp(0.0, 1.0);
84+
let dot_nh = n.dot(h).clamp(0.0, 1.0);
85+
86+
// Light color fixed
87+
let light_color = vec3(1.0, 1.0, 1.0);
88+
89+
let mut color = vec3(0.0, 0.0, 0.0);
90+
91+
if dot_nl > 0.0 {
92+
let rroughness = roughness.max(0.05);
93+
// D = Normal distribution (Distribution of the microfacets)
94+
let d = d_ggx(dot_nh, rroughness);
95+
// G = Geometric shadowing term (Microfacets shadowing)
96+
let g = g_schlicksmith_ggx(dot_nl, dot_nv, rroughness);
97+
// F = Fresnel factor (Reflectance depending on angle of incidence)
98+
let f = f_schlick(dot_nv, metallic, material_color);
99+
100+
let spec = d * f * g / (4.0 * dot_nl * dot_nv);
101+
102+
color += spec * dot_nl * light_color;
103+
}
104+
105+
color
106+
}
107+
108+
#[spirv(fragment)]
109+
pub fn main_fs(
110+
in_world_pos: Vec3,
111+
in_normal: Vec3,
112+
#[spirv(uniform, descriptor_set = 0, binding = 0)] ubo: &Ubo,
113+
#[spirv(uniform, descriptor_set = 1, binding = 0)] material: &UniformInline,
114+
out_color: &mut Vec4,
115+
) {
116+
let n = in_normal.normalize();
117+
let v = (ubo.cam_pos - in_world_pos).normalize();
118+
119+
let roughness = material.roughness;
120+
let material_color = vec3(material.r, material.g, material.b);
121+
122+
// Specular contribution
123+
let light_pos = vec3(0.0, 0.0, 10.0);
124+
let mut lo = vec3(0.0, 0.0, 0.0);
125+
let l = (light_pos - in_world_pos).normalize();
126+
lo += brdf(l, v, n, material.metallic, roughness, material_color);
127+
128+
// Combine with ambient
129+
let mut color = material_color * material.ambient;
130+
color += lo;
131+
132+
// Gamma correct
133+
color = color.powf(0.4545);
134+
135+
*out_color = vec4(color.x, color.y, color.z, 1.0);
136+
}

0 commit comments

Comments
 (0)