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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#ifndef BSDF_GLSLIB
#define BSDF_GLSLIB 1
#ifndef M_PI
#define M_PI 3.14159265359
#endif
vec3 qt_schlick3(in vec3 f0, in vec3 f90, in float VdotH, in float fresnelPower)
{
return f0 + (f90 - f0) * (1.0 - clamp(pow( VdotH, fresnelPower), 0.0, 1.0 ) );
}
float qt_G_GGX_2cos(in float cos_theta_m, in float alpha) {
float k = 0.5 * alpha;
return 0.5 / (cos_theta_m * (1.0 - k) + k);
}
float qt_D_GGX(in float cos_theta_m, in float alpha) {
float alpha2 = alpha * alpha;
float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m;
return alpha2 / (M_PI * d * d);
}
float qt_V_GGX(in float NdotL, in float NdotV, in float alphaRoughness)
{
return qt_G_GGX_2cos(NdotL, alphaRoughness) * qt_G_GGX_2cos(NdotV, alphaRoughness);
}
// An alternative to using a LUT is to use this function
// see: https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile
vec2 qt_brdfApproximation(in vec3 N, in vec3 viewDir, in float roughness)
{
float nDotV = clamp(dot(N, viewDir), 0.0, 1.0);
const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022);
const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04);
vec4 r = roughness * c0 + c1;
float a004 = min(r.x * r.x, exp2(-9.28 * nDotV)) * r.x + r.y;
return vec2(-1.04, 1.04) * a004 + r.zw;
}
float qt_applyIorToRoughness(in float roughness, in float ior)
{
// Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and
// an IOR of 1.5 results in the default amount of microfacet refraction.
return roughness * clamp(ior * 2.0 - 2.0, 0.0, 1.0);
}
vec3 qt_getPunctualRadianceTransmission(in vec3 normal, in vec3 view, in vec3 pointToLight, in float roughness,
in vec3 f0, in vec3 f90, in vec3 baseColor, in float ior)
{
float clampedRoughness = clamp(roughness, 0.0001, 1.0);
float alphaRoughness = clampedRoughness * clampedRoughness;
float transmissionRougness = qt_applyIorToRoughness(alphaRoughness, ior);
vec3 n = normalize(normal); // Outward direction of surface point
vec3 v = normalize(view); // Direction from surface point to view
vec3 l = normalize(pointToLight);
vec3 l_mirror = normalize(l + 2.0*n*dot(-l, n)); // Mirror light reflection vector on surface
vec3 h = normalize(l_mirror + v); // Halfway vector between transmission light vector and v
float D = qt_D_GGX(clamp(dot(n, h), 0.0, 1.0), transmissionRougness);
vec3 F = qt_schlick3(f0, f90, clamp(dot(v, h), 0.0, 1.0), 5.0);
float Vis = qt_V_GGX(clamp(dot(n, l_mirror), 0.0, 1.0), clamp(dot(n, v), 0.0, 1.0), transmissionRougness);
// Transmission BTDF
return (1.0 - F) * baseColor * D * Vis;
}
#endif
|