[Bf-blender-cvs] [98cea7edcef] master: Fix T65298 Eevee: Principled BSDF doesn't use specular with metals

Clément Foucault noreply at git.blender.org
Wed Jun 5 12:20:51 CEST 2019


Commit: 98cea7edcefa58d5eb7e2350461b8efe33fe7d9e
Author: Clément Foucault
Date:   Wed Jun 5 12:17:37 2019 +0200
Branches: master
https://developer.blender.org/rB98cea7edcefa58d5eb7e2350461b8efe33fe7d9e

Fix T65298 Eevee: Principled BSDF doesn't use specular with metals

This does add some more register pressure as it passes a new vec3 down
the shading function. But for now we care more about accuracy than
efficiency.

===================================================================

M	source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M	source/blender/draw/engines/eevee/shaders/default_frag.glsl
M	source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
M	source/blender/gpu/shaders/gpu_shader_material.glsl

===================================================================

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 0f3e7ba7efb..c332f68728f 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -644,19 +644,19 @@ vec3 F_schlick(vec3 f0, float cos_theta)
 }
 
 /* Fresnel approximation for LTC area lights (not MRP) */
-vec3 F_area(vec3 f0, vec2 lut)
+vec3 F_area(vec3 f0, vec3 f90, vec2 lut)
 {
   /* Unreal specular matching : if specular color is below 2% intensity,
    * treat as shadowning */
-  return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y + lut.x * f0;
+  return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y * f90 + lut.x * f0;
 }
 
 /* Fresnel approximation for IBL */
-vec3 F_ibl(vec3 f0, vec2 lut)
+vec3 F_ibl(vec3 f0, vec3 f90, vec2 lut)
 {
   /* Unreal specular matching : if specular color is below 2% intensity,
    * treat as shadowning */
-  return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y + lut.x * f0;
+  return saturate(50.0 * dot(f0, vec3(0.3, 0.6, 0.1))) * lut.y * f90 + lut.x * f0;
 }
 
 /* GGX */
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index c568b4d94be..64a1c725a6b 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -29,8 +29,9 @@ Closure nodetree_exec(void)
   vec3 dielectric = vec3(0.034) * specular * 2.0;
   vec3 albedo = mix(basecol, vec3(0.0), metallic);
   vec3 f0 = mix(dielectric, basecol, metallic);
+  vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
   vec3 out_diff, out_spec, ssr_spec;
-  eevee_closure_default(N, albedo, f0, 1, roughness, 1.0, out_diff, out_spec, ssr_spec);
+  eevee_closure_default(N, albedo, f0, f90, 1, roughness, 1.0, out_diff, out_spec, ssr_spec);
 
   Closure result = Closure(out_spec + out_diff * albedo,
                            1.0,
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index fe3225b1086..e96667c0488 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -119,6 +119,7 @@ void CLOSURE_NAME(vec3 N
 #ifdef CLOSURE_GLOSSY
                   ,
                   vec3 f0,
+                  vec3 f90,
                   int ssr_id
 #endif
 #if defined(CLOSURE_GLOSSY) || defined(CLOSURE_REFRACTION)
@@ -264,12 +265,12 @@ void CLOSURE_NAME(vec3 N
 
 #ifdef CLOSURE_GLOSSY
   vec2 brdf_lut_lights = texture(utilTex, vec3(lut_uv, 1.0)).ba;
-  out_spec *= F_area(f0, brdf_lut_lights.xy);
+  out_spec *= F_area(f0, f90, brdf_lut_lights.xy);
 #endif
 
 #ifdef CLOSURE_CLEARCOAT
   vec2 brdf_lut_lights_clear = texture(utilTex, vec3(lut_uv_clear, 1.0)).ba;
-  out_spec_clear *= F_area(vec3(0.04), brdf_lut_lights_clear.xy);
+  out_spec_clear *= F_area(vec3(0.04), vec3(1.0), brdf_lut_lights_clear.xy);
   out_spec += out_spec_clear * C_intensity;
 #endif
 
@@ -454,7 +455,7 @@ void CLOSURE_NAME(vec3 N
 
   /* This factor is outputted to be used by SSR in order
    * to match the intensity of the regular reflections. */
-  ssr_spec = F_ibl(f0, brdf_lut);
+  ssr_spec = F_ibl(f0, f90, brdf_lut);
   float spec_occlu = specular_occlusion(NV, final_ao, roughness);
 
   /* The SSR pass recompute the occlusion to not apply it to the SSR */
@@ -475,7 +476,8 @@ void CLOSURE_NAME(vec3 N
   NV = dot(C_N, V);
   vec2 C_uv = lut_coords(NV, C_roughness);
   vec2 C_brdf_lut = texture(utilTex, vec3(C_uv, 1.0)).rg;
-  vec3 C_fresnel = F_ibl(vec3(0.04), C_brdf_lut) * specular_occlusion(NV, final_ao, C_roughness);
+  vec3 C_fresnel = F_ibl(vec3(0.04), vec3(1.0), C_brdf_lut) *
+                   specular_occlusion(NV, final_ao, C_roughness);
 
   out_spec += C_spec_accum.rgb * C_fresnel * C_intensity;
 #endif
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 3b1ad41ad95..0840c704f3f 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1241,7 +1241,7 @@ void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Clo
 {
   N = normalize(N);
   vec3 out_spec, ssr_spec;
-  eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+  eevee_closure_glossy(N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
   vec3 vN = mat3(ViewMatrix) * N;
   result = CLOSURE_DEFAULT;
   result.radiance = out_spec * color.rgb;
@@ -1269,7 +1269,7 @@ void node_bsdf_glass(
   vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb :
                                               color.rgb; /* Simulate 2 transmission event */
   eevee_closure_glass(
-      N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+      N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
   out_refr *= refr_color;
   out_spec *= color.rgb;
   float fresnel = F_eta(ior, dot(N, cameraVec));
@@ -1339,12 +1339,15 @@ void node_bsdf_principled(vec4 base_color,
   vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
   f0 = mix(f0, spec_col, transmission);
 
+  vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic);
+
   vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
 
   float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface;
   eevee_closure_principled(N,
                            mixed_ss_base_color,
                            f0,
+                           f90,
                            int(ssr_id),
                            roughness,
                            CN,
@@ -1428,7 +1431,8 @@ void node_bsdf_principled_dielectric(vec4 base_color,
   float NV = dot(N, cameraVec);
   vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
 
-  eevee_closure_default(N, diffuse, f0, int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
+  eevee_closure_default(
+      N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec);
 
   vec3 vN = mat3(ViewMatrix) * N;
   result = CLOSURE_DEFAULT;
@@ -1471,7 +1475,9 @@ void node_bsdf_principled_metallic(vec4 base_color,
   N = normalize(N);
   vec3 out_spec, ssr_spec;
 
-  eevee_closure_glossy(N, base_color.rgb, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
+  vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
+  eevee_closure_glossy(N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, out_spec, ssr_spec);
 
   vec3 vN = mat3(ViewMatrix) * N;
   result = CLOSURE_DEFAULT;
@@ -1514,8 +1520,11 @@ void node_bsdf_principled_clearcoat(vec4 base_color,
   vec3 out_spec, ssr_spec;
   N = normalize(N);
 
+  vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
   eevee_closure_clearcoat(N,
                           base_color.rgb,
+                          f90,
                           int(ssr_id),
                           roughness,
                           CN,
@@ -1578,9 +1587,12 @@ void node_bsdf_principled_subsurface(vec4 base_color,
   float NV = dot(N, cameraVec);
   vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
 
+  vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic);
+
   eevee_closure_skin(N,
                      mixed_ss_base_color,
                      f0,
+                     f90,
                      int(ssr_id),
                      roughness,
                      1.0,
@@ -1647,7 +1659,7 @@ void node_bsdf_principled_glass(vec4 base_color,
   f0 = mix(vec3(1.0), base_color.rgb, specular_tint);
 
   eevee_closure_glass(
-      N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
+      N, vec3(1.0), vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec);
 
   vec3 refr_color = base_color.rgb;
   refr_color *= (refractionDepth > 0.0) ? refr_color :
@@ -3527,6 +3539,7 @@ void node_eevee_specular(vec4 diffuse,
   eevee_closure_default_clearcoat(normal,
                                   diffuse.rgb,
                                   specular.rgb,
+                                  vec3(1.0),
                                   int(ssr_id),
                                   roughness,
                                   clearcoat_normal,



More information about the Bf-blender-cvs mailing list