1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
struct FragmentInput {
@location(0) uv: vec2<f32>,
@location(1) normal: vec3<f32>,
@location(2) world_pos: vec3<f32>,
}
struct FragmentOutput {
@location(0) color: vec4<f32>,
}
struct Material {
albedo: vec3<f32>,
metallic: f32,
roughness: f32,
}
@group(0) @binding(0) var<uniform> material: Material;
@group(0) @binding(1) var<uniform> light_dir: vec3<f32>;
@group(0) @binding(2) var<uniform> camera_pos: vec3<f32>;
@group(0) @binding(3) var albedo_tex_tex: texture_2d<f32>;
@group(0) @binding(4) var albedo_tex_samp: sampler;
fn fresnel_schlick(cos_theta: f32, f0: vec3<f32>) -> vec3<f32> {
return (f0 + ((vec3<f32>(1.0, 1.0, 1.0) - f0) * pow((1.0 - cos_theta), 5.0)));
}
fn compute_lighting(normal: vec3<f32>, view_dir: vec3<f32>, albedo: vec3<f32>) -> vec3<f32> {
let n = normalize(normal);
let l = normalize(light_dir);
let h = normalize((l + view_dir));
let ndotl = max(dot(n, l), 0.0);
let ndoth = max(dot(n, h), 0.0);
let f0 = mix(vec3<f32>(0.04, 0.04, 0.04), albedo, material.metallic);
let f = fresnel_schlick(max(dot(h, view_dir), 0.0), f0);
let specular = (f * pow(ndoth, ((1.0 - material.roughness) * 256.0)));
let diffuse = ((albedo * ndotl) * (vec3<f32>(1.0, 1.0, 1.0) - f));
return (diffuse + specular);
}
@fragment
fn fs_main(input: FragmentInput) -> FragmentOutput {
var __luma_output: FragmentOutput;
let tex_color = textureSample(albedo_tex_tex, albedo_tex_samp, input.uv);
let albedo = (tex_color.rgb * material.albedo);
let view_dir = normalize((camera_pos - input.world_pos));
let color = compute_lighting(input.normal, view_dir, albedo);
__luma_output.color = vec4<f32>(color, tex_color.a);
return __luma_output;
}