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
50
51
52
53
54
55
-- PBR fragment shader — tests helper function calls, multiple builtins,
-- struct construction, and complex expressions.
struct FragmentInput
uv: vec2
normal: vec3
world_pos: vec3
end
struct FragmentOutput
color: vec4
end
struct Material
albedo: vec3
metallic: float
roughness: float
end
uniform material: Material
uniform light_dir: vec3
uniform camera_pos: vec3
uniform albedo_tex: sampler2D
function fresnel_schlick(cos_theta: float, f0: vec3) -> vec3
return f0 + (vec3(1.0, 1.0, 1.0) - f0) * pow(1.0 - cos_theta, 5.0)
end
function compute_lighting(normal: vec3, view_dir: vec3, albedo: vec3) -> vec3
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(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(1.0, 1.0, 1.0) - f)
return diffuse + specular
end
@entry(fragment)
function fs_main(input: FragmentInput) -> FragmentOutput
let tex_color = sample(albedo_tex, 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)
return FragmentOutput {
color = vec4(color, tex_color.a),
}
end