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
#include <metal_stdlib>
using namespace metal;
struct Material {
float3 albedo;
float metallic;
float roughness;
};
struct FragmentInput {
float2 uv [[user(locn0)]];
float3 normal [[user(locn1)]];
float3 world_pos [[user(locn2)]];
};
struct FragmentOutput {
float4 color [[user(locn0)]];
};
float3 fresnel_schlick(float cos_theta, float3 f0) {
return (f0 + ((float3(1.0, 1.0, 1.0) - f0) * pow((1.0 - cos_theta), 5.0)));
}
float3 compute_lighting(float3 normal, float3 view_dir, float3 albedo) {
float3 n = normalize(normal);
float3 l = normalize(light_dir);
float3 h = normalize((l + view_dir));
float ndotl = max(dot(n, l), 0.0);
float ndoth = max(dot(n, h), 0.0);
float3 f0 = mix(float3(0.04, 0.04, 0.04), albedo, material.metallic);
float3 f = fresnel_schlick(max(dot(h, view_dir), 0.0), f0);
float3 specular = (f * pow(ndoth, ((1.0 - material.roughness) * 256.0)));
float3 diffuse = ((albedo * ndotl) * (float3(1.0, 1.0, 1.0) - f));
return (diffuse + specular);
}
fragment FragmentOutput fs_main(FragmentInput input [[stage_in]],
constant Material& material [[buffer(0)]],
constant float3& camera_pos [[buffer(1)]],
texture2d<float> albedo_tex_tex [[texture(0)]],
sampler albedo_tex_samp [[sampler(0)]]) {
FragmentOutput __luma_output;
float4 tex_color = albedo_tex_tex.sample(albedo_tex_samp, input.uv);
float3 albedo = (tex_color.rgb * material.albedo);
float3 view_dir = normalize((camera_pos - input.world_pos));
float3 color = compute_lighting(input.normal, view_dir, albedo);
__luma_output.color = float4(color, tex_color.a);
return __luma_output;
}