This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
Thomas Dinges 6b8bb26c45 EEVEE: Port existing EEVEE shaders and generated materials to use GPUShaderCreateInfo.
Required by Metal backend for efficient shader compilation. EEVEE material
resource binding permutations now controlled via CreateInfo and selected
based on material options. Other existing CreateInfo's also modified to
ensure explicitness for depth-writing mode. Other missing bindings also
addressed to ensure full compliance with the Metal backend.

Authored by Apple: Michael Parkin-White

Ref T96261

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D16243
2022-12-08 21:12:19 +01:00

85 lines
2.4 KiB
GLSL

#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
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_factor * z_factor;
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_factor == 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);
}