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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
uniform float sampleCount;
uniform float z;
out vec4 FragColor;
void main()
{
float x = floor(gl_FragCoord.x) / (LUT_SIZE - 1.0);
float y = floor(gl_FragCoord.y) / (LUT_SIZE - 1.0);
float ior = clamp(sqrt(x), 0.05, 0.999);
/* ior is sin of critical angle. */
float critical_cos = sqrt(1.0 - saturate(ior * ior));
y = y * 2.0 - 1.0;
/* Maximize texture usage on both sides of the critical angle. */
y *= (y > 0.0) ? (1.0 - critical_cos) : critical_cos;
/* Center LUT around critical angle to avoid strange interpolation issues when the critical
* angle is changing. */
y += critical_cos;
float NV = clamp(y, 1e-4, 0.9999);
float a = z * z;
float a2 = clamp(a * a, 1e-8, 0.9999);
vec3 V = vec3(sqrt(1.0 - NV * NV), 0.0, NV);
/* Integrating BTDF */
float btdf_accum = 0.0;
float fresnel_accum = 0.0;
for (float j = 0.0; j < sampleCount; j++) {
for (float i = 0.0; i < sampleCount; i++) {
vec3 Xi = (vec3(i, j, 0.0) + 0.5) / sampleCount;
Xi.yz = vec2(cos(Xi.y * M_2PI), sin(Xi.y * M_2PI));
/* Microfacet normal. */
vec3 H = sample_ggx(Xi, a2, V);
float VH = dot(V, H);
/* Check if there is total internal reflections. */
float fresnel = F_eta(ior, VH);
fresnel_accum += fresnel;
float eta = 1.0 / ior;
if (dot(H, V) < 0.0) {
H = -H;
eta = ior;
}
vec3 L = refract(-V, H, eta);
float NL = -L.z;
if ((NL > 0.0) && (fresnel < 0.999)) {
float LH = dot(L, H);
/* Balancing the adjustments made in G1_Smith. */
float G1_l = NL * 2.0 / G1_Smith_GGX_opti(NL, a2);
/* btdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV)
* pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */
float btdf = G1_l * abs(VH * LH) / (VH * abs(LH));
btdf_accum += btdf;
}
}
}
btdf_accum /= sampleCount * sampleCount;
fresnel_accum /= sampleCount * sampleCount;
if (z == 0.0) {
/* Perfect mirror. Increased precision because the roughness is clamped. */
fresnel_accum = F_eta(ior, NV);
}
if (x == 0.0) {
/* Special case. */
fresnel_accum = 1.0;
btdf_accum = 0.0;
}
/* There is place to put multi-scatter result (which is a little bit different still)
* and / or lobe fitting for better sampling of. */
FragColor = vec4(btdf_accum, fresnel_accum, 0.0, 1.0);
}
|