[Bf-blender-cvs] [ddc2796e4d8] blender2.8: Eevee: Principled BSDF: Add support for the sheen parameter

Clément Foucault noreply at git.blender.org
Thu Aug 9 16:46:06 CEST 2018


Commit: ddc2796e4d872fe3c063570ae735421f52bb56b9
Author: Clément Foucault
Date:   Thu Aug 9 15:03:15 2018 +0200
Branches: blender2.8
https://developer.blender.org/rBddc2796e4d872fe3c063570ae735421f52bb56b9

Eevee: Principled BSDF: Add support for the sheen parameter

This is a rough (but fast) approximation that still match cycles reference
in common case.

In practice, it's just adding more of the diffuse light computed for the
diffuse contribution.

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

M	source/blender/gpu/shaders/gpu_shader_material.glsl

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

diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index c9564a21d15..56fa6291c65 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1065,17 +1065,29 @@ float floorfrac(float x, out int i)
 
 /* bsdfs */
 
+vec3 tint_from_color(vec3 color)
+{
+	float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
+	return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
+}
+
 void convert_metallic_to_specular_tinted(
-        vec3 basecol, float metallic, float specular_fac, float specular_tint,
+        vec3 basecol, vec3 basecol_tint, float metallic, float specular_fac, float specular_tint,
         out vec3 diffuse, out vec3 f0)
 {
-	float lum = dot(basecol, vec3(0.3, 0.6, 0.1)); /* luminance approx. */
-	vec3 tint = lum > 0 ? basecol / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */
-	vec3 tmp_col = mix(vec3(1.0), tint, specular_tint);
+	vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint);
 	f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic);
 	diffuse = basecol * (1.0 - metallic);
 }
 
+vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint)
+{
+	float f = 1.0 - NV;
+	/* Empirical approximation (manual curve fitting). Can be refined. */
+	float sheen = f*f*f*0.077 + f*0.01 + 0.00026;
+	return sheen * mix(vec3(1.0), basecol_tint, sheen_tint);
+}
+
 #ifndef VOLUMETRICS
 void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result)
 {
@@ -1137,16 +1149,21 @@ void node_bsdf_principled(
 	transmission = saturate(transmission);
 	float dielectric = 1.0 - metallic;
 	transmission *= dielectric;
+	sheen *= dielectric;
 	subsurface_color *= dielectric;
 
 	vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec;
-	convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
+	vec3 ctint = tint_from_color(base_color.rgb);
+	convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
+
+	float NV = dot(N, cameraVec);
+	vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
 
 	/* Far from being accurate, but 2 glossy evaluation is too expensive.
 	 * Most noticeable difference is at grazing angles since the bsdf lut
 	 * f0 color interpolation is done on top of this interpolation. */
 	vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint);
-	float fresnel = F_eta(ior, dot(N, cameraVec));
+	float fresnel = F_eta(ior, NV);
 	vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel;
 	f0 = mix(f0, spec_col, transmission);
 
@@ -1164,6 +1181,7 @@ void node_bsdf_principled(
 	vec3 vN = normalize(mat3(ViewMatrix) * N);
 	result = CLOSURE_DEFAULT;
 	result.radiance = out_spec + out_refr;
+	result.radiance += out_diff * out_sheen; /* Coarse approx. */
 #ifndef USE_SSS
 	result.radiance += (out_diff + out_trans) * mixed_ss_base_color *  (1.0 - transmission);
 #endif
@@ -1192,13 +1210,17 @@ void node_bsdf_principled_dielectric(
 	float dielectric = 1.0 - metallic;
 
 	vec3 diffuse, f0, out_diff, out_spec, ssr_spec;
-	convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
+	vec3 ctint = tint_from_color(base_color.rgb);
+	convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
+
+	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);
 
 	vec3 vN = normalize(mat3(ViewMatrix) * N);
 	result = CLOSURE_DEFAULT;
-	result.radiance = out_spec + out_diff * diffuse;
+	result.radiance = out_spec + out_diff * (diffuse + out_sheen);
 	result.ssr_data = vec4(ssr_spec, roughness);
 	result.ssr_normal = normal_encode(vN, viewCameraVec);
 	result.ssr_id = int(ssr_id);
@@ -1250,12 +1272,16 @@ void node_bsdf_principled_subsurface(
 	metallic = saturate(metallic);
 
 	vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec;
-	convert_metallic_to_specular_tinted(base_color.rgb, metallic, specular, specular_tint, diffuse, f0);
+	vec3 ctint = tint_from_color(base_color.rgb);
+	convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0);
 
 	subsurface_color = subsurface_color * (1.0 - metallic);
 	vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface);
 	float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface;
 
+	float NV = dot(N, cameraVec);
+	vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint);
+
 	eevee_closure_skin(N, mixed_ss_base_color, f0, int(ssr_id), roughness, 1.0, sss_scalef,
 	                   out_diff, out_trans, out_spec, ssr_spec);
 
@@ -1276,6 +1302,7 @@ void node_bsdf_principled_subsurface(
 #else
 	result.radiance += (out_diff + out_trans) * mixed_ss_base_color;
 #endif
+	result.radiance += out_diff * out_sheen;
 }
 
 void node_bsdf_principled_glass(



More information about the Bf-blender-cvs mailing list