float square(float a) { return a*a; } float normal_distribution_ggx(vec3 normal, vec3 halfway, float roughness) { float a2 = square(square(roughness)); float dotnh = max(dot(normal, halfway), 0.0); float dotnh2 = square(dotnh); return a2 / (PI * square(dotnh2 * (a2 - 1.0) + 1.0)); } float k_direct(float roughness) { return square(roughness + 1) / 8; } float k_ibl(float roughness) { return square(roughness) / 2; } float geometry_schlick_ggx(float dotnv, float k) { return dotnv / (dotnv * (1.0 - k) + k); } float geometry_smith(vec3 normal, vec3 vdir, vec3 point_to_light, float k) { float dotnv = max(dot(normal, vdir), 0.0); float dotnl = max(dot(normal, point_to_light), 0.0); return geometry_schlick_ggx(dotnv, k) * geometry_schlick_ggx(dotnl, k); } float fresnel_schlick(float cos_theta, float F0) { return F0 + (1.0 - F0) * pow(1.0 - cos_theta, 5.0); }