Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl30
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl55
3 files changed, 55 insertions, 33 deletions
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 1ac965d24ca..cb4d8931af0 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -24,6 +24,7 @@ float ior_from_f0(float f0)
return (-f - 1.0) / (f - 1.0);
}
+/* Simplified form of F_eta(eta, 1.0). */
float f0_from_ior(float eta)
{
float A = (eta - 1.0) / (eta + 1.0);
@@ -69,7 +70,7 @@ float F_eta(float eta, float cos_theta)
/* Fresnel color blend base on fresnel factor */
vec3 F_color_blend(float eta, float fresnel, vec3 f0_color)
{
- float f0 = F_eta(eta, 1.0);
+ float f0 = f0_from_ior(eta);
float fac = saturate((fresnel - f0) / (1.0 - f0));
return mix(f0_color, vec3(1.0), fac);
}
diff --git a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
index b504b78ee06..2ffe23a9197 100644
--- a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
@@ -11,18 +11,17 @@ void main()
float x = floor(gl_FragCoord.x) / (LUT_SIZE - 1.0);
float y = floor(gl_FragCoord.y) / (LUT_SIZE - 1.0);
- float ior = sqrt(x);
- ior = clamp(sqrt(ior), 0.0, 0.99995);
+ float ior = clamp(sqrt(x), 0.05, 0.999);
/* ior is sin of critical angle. */
float critical_cos = sqrt(1.0 - saturate(ior * ior));
- /* Manual fit to range. */
- y = y * 1.45 + 0.05;
- /* Remap for better accuracy. */
- float NV = 1.0 - y * y;
- /* Center LUT around critical angle to always have a sharp cut if roughness is 0. */
- NV += critical_cos;
- NV = clamp(NV, 0.0, 0.9999);
+ 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);
@@ -56,7 +55,7 @@ void main()
vec3 L = refract(-V, H, eta);
float NL = -L.z;
- if ((NL > 0.0) && (fresnel < 1.0)) {
+ if ((NL > 0.0) && (fresnel < 0.999)) {
float LH = dot(L, H);
/* Balancing the adjustments made in G1_Smith. */
@@ -73,6 +72,17 @@ void main()
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 multiscater 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);
diff --git a/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
index 65338cf0dac..b0cd6ac8459 100644
--- a/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/common_utiltex_lib.glsl
@@ -40,35 +40,51 @@ vec2 brdf_lut(float cos_theta, float roughness)
return textureLod(utilTex, vec3(lut_coords(cos_theta, roughness), BRDF_LUT_LAYER), 0.0).rg;
}
+/* Return texture coordinates to sample Surface LUT. */
+vec3 lut_coords_btdf(float cos_theta, float roughness, float ior)
+{
+ /* ior is sin of critical angle. */
+ float critical_cos = sqrt(1.0 - ior * ior);
+
+ vec3 coords;
+ coords.x = sqr(ior);
+ coords.y = cos_theta;
+ coords.y -= critical_cos;
+ coords.y /= (coords.y > 0.0) ? (1.0 - critical_cos) : critical_cos;
+ coords.y = coords.y * 0.5 + 0.5;
+ coords.z = roughness;
+
+ coords = saturate(coords);
+
+ /* scale and bias coordinates, for correct filtered lookup */
+ coords.xy = coords.xy * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
+
+ return coords;
+}
+
/* Returns GGX BTDF in first component and fresnel in second. */
vec2 btdf_lut(float cos_theta, float roughness, float ior)
{
+ if (ior <= 1e-5) {
+ return vec2(0.0);
+ }
+
if (ior >= 1.0) {
vec2 split_sum = brdf_lut(cos_theta, roughness);
float f0 = f0_from_ior(ior);
- float fresnel = F_brdf_single_scatter(vec3(f0), vec3(1.0), split_sum).r;
+ /* Baked IOR for GGX BRDF. */
+ const float specular = 1.0;
+ const float eta_brdf = (2.0 / (1.0 - sqrt(0.08 * specular))) - 1.0;
+ /* Avoid harsh transition comming from ior == 1. */
+ float f90 = fast_sqrt(saturate(f0 / (f0_from_ior(eta_brdf) * 0.25)));
+ float fresnel = F_brdf_single_scatter(vec3(f0), vec3(f90), split_sum).r;
/* Setting the BTDF to one is not really important since it is only used for multiscatter
* and it's already quite close to ground truth. */
float btdf = 1.0;
return vec2(btdf, fresnel);
}
- /* ior is sin of critical angle. */
- float critical_cos = sqrt(1.0 - ior * ior);
-
- vec3 coords;
- coords.x = sqr(ior);
- coords.y = sqrt(1.0 + critical_cos - cos_theta);
- coords.y = (coords.y - 0.05) / 1.45;
- coords.z = roughness;
-
- coords = saturate(coords);
-
- coords.xy = coords.xy * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE;
- /* Bias the lookup in the NV direction to be able to do the clear cut
- * at the end of the function. */
- float clear_cut = saturate(roughness * lut_btdf_layer_count * 0.5);
- coords.y -= clear_cut * 0.5 / LUT_SIZE;
+ vec3 coords = lut_coords_btdf(cos_theta, roughness, ior);
float layer = coords.z * lut_btdf_layer_count;
float layer_floored = floor(layer);
@@ -82,11 +98,6 @@ vec2 btdf_lut(float cos_theta, float roughness, float ior)
/* Manual trilinear interpolation. */
vec2 btdf = mix(btdf_low, btdf_high, layer - layer_floored);
- /* Do a manual trim if roughness is low enough to avoid seeing the bilinear interpolation. */
- if (clear_cut < 1.0 && cos_theta < critical_cos) {
- btdf = mix(vec2(0.0, 1.0), btdf, clear_cut);
- }
-
return btdf;
}