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:
authorClément Foucault <foucault.clem@gmail.com>2018-08-09 16:03:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-08-09 17:46:03 +0300
commitddc2796e4d872fe3c063570ae735421f52bb56b9 (patch)
tree385f8684354dca46d8ecf0eab1e2c08445be416f /source/blender/gpu/shaders
parent2b41b208c7e5e74a0a5fe043f4bfab2a122a9ed1 (diff)
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.
Diffstat (limited to 'source/blender/gpu/shaders')
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl45
1 files changed, 36 insertions, 9 deletions
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(