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