diff options
Diffstat (limited to 'source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl')
-rw-r--r-- | source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl | 97 |
1 files changed, 62 insertions, 35 deletions
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl index 7af409dd410..3c85dc6456c 100644 --- a/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl +++ b/source/blender/gpu/shaders/material/gpu_shader_material_principled.glsl @@ -18,15 +18,22 @@ void convert_metallic_to_specular_tinted(vec3 basecol, diffuse = basecol * (1.0 - metallic); } -vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) +/* Output sheen is to be multiplied by sheen_color. */ +void principled_sheen(float NV, + vec3 basecol_tint, + float sheen, + float sheen_tint, + out float out_sheen, + out vec3 sheen_color) { float f = 1.0 - NV; /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, * therefore we need to clamp value. */ f = clamp(f, 0.0, 1.0); /* 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); + out_sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; + + sheen_color = sheen * mix(vec3(1.0), basecol_tint, sheen_tint); } void node_bsdf_principled(vec4 base_color, @@ -61,18 +68,23 @@ void node_bsdf_principled(vec4 base_color, ior = max(ior, 1e-5); metallic = saturate(metallic); transmission = saturate(transmission); + float m_transmission = 1.0 - transmission; + float dielectric = 1.0 - metallic; transmission *= dielectric; sheen *= dielectric; subsurface_color *= dielectric; - vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, out_refr, ssr_spec, sheen_color; + float out_sheen; 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); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); + + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); /* Far from being accurate, but 2 glossy evaluation is too expensive. * Most noticeable difference is at grazing angles since the bsdf lut @@ -81,8 +93,12 @@ void node_bsdf_principled(vec4 base_color, float fresnel = F_eta(ior, NV); vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; f0 = mix(f0, spec_col, transmission); + f90 = mix(f90, spec_col, transmission); - vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + /* Really poor approximation but needed to workaround issues with renderpasses. */ + spec_col = mix(vec3(1.0), spec_col, transmission); + /* Match cycles. */ + spec_col += float(clearcoat > 1e-5); vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); @@ -108,19 +124,22 @@ void node_bsdf_principled(vec4 base_color, vec3 refr_color = base_color.rgb; refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */ - out_refr *= refr_color * (1.0 - fresnel) * transmission; + refr_color *= saturate(1.0 - fresnel) * transmission; + + sheen_color *= m_transmission; + mixed_ss_base_color *= m_transmission; result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_refr; - result.radiance += out_diff * out_sheen; /* Coarse approx. */ - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color); + result.radiance += render_pass_glossy_mask(spec_col, out_spec); + /* Coarse approx. */ + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - mixed_ss_base_color *= alpha * (1.0 - transmission); + mixed_ss_base_color *= alpha; closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result); - result.transmittance = vec3(1.0 - alpha); } @@ -156,22 +175,26 @@ void node_bsdf_principled_dielectric(vec4 base_color, metallic = saturate(metallic); float dielectric = 1.0 - metallic; - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color; + float out_sheen; vec3 ctint = tint_from_color(base_color.rgb); convert_metallic_to_specular_tinted( base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + vec3 f90 = mix(vec3(1.0), f0, (1.0 - specular) * metallic); + float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); eevee_closure_default( - N, diffuse, f0, vec3(1.0), int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec); + N, diffuse, f0, f90, int(ssr_id), roughness, 1.0, true, out_diff, out_spec, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_diff * (diffuse + out_sheen); - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_diffuse_mask(diffuse, out_diff * diffuse); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); @@ -214,10 +237,9 @@ void node_bsdf_principled_metallic(vec4 base_color, N, base_color.rgb, f90, int(ssr_id), roughness, 1.0, true, out_spec, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; - closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); @@ -268,10 +290,12 @@ void node_bsdf_principled_clearcoat(vec4 base_color, true, out_spec, ssr_spec); + /* Match cycles. */ + float spec_col = 1.0 + float(clearcoat > 1e-5); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(spec_col), out_spec); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); @@ -310,7 +334,8 @@ void node_bsdf_principled_subsurface(vec4 base_color, metallic = saturate(metallic); N = normalize(N); - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 diffuse, f0, out_diff, out_spec, ssr_spec, sheen_color; + float out_sheen; vec3 ctint = tint_from_color(base_color.rgb); convert_metallic_to_specular_tinted( base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); @@ -320,7 +345,7 @@ void node_bsdf_principled_subsurface(vec4 base_color, float sss_scalef = avg(sss_scale) * subsurface; float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + principled_sheen(NV, ctint, sheen, sheen_tint, out_sheen, sheen_color); vec3 f90 = mix(vec3(1.0), base_color.rgb, (1.0 - specular) * metallic); @@ -338,14 +363,14 @@ void node_bsdf_principled_subsurface(vec4 base_color, ssr_spec); result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.radiance += out_diff * out_sheen; - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(vec3(1.0), out_spec); + result.radiance += render_pass_diffuse_mask(sheen_color, out_diff * out_sheen * sheen_color); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); - mixed_ss_base_color *= alpha * (1.0 - transmission); + mixed_ss_base_color *= alpha; closure_load_sss_data(sss_scalef, out_diff, mixed_ss_base_color, int(sss_id), result); result.transmittance = vec3(1.0 - alpha); @@ -400,16 +425,18 @@ void node_bsdf_principled_glass(vec4 base_color, vec3 refr_color = base_color.rgb; refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission events */ - out_refr *= refr_color; float fresnel = F_eta(ior, dot(N, cameraVec)); vec3 spec_col = F_color_blend(ior, fresnel, f0); - out_spec *= spec_col; - ssr_spec *= spec_col * fresnel; + spec_col *= fresnel; + refr_color *= (1.0 - fresnel); + + ssr_spec *= spec_col; result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - result.radiance += emission.rgb; + result.radiance = render_pass_glossy_mask(refr_color, out_refr * refr_color); + result.radiance += render_pass_glossy_mask(spec_col, out_spec * spec_col); + result.radiance += render_pass_emission_mask(emission.rgb); result.radiance *= alpha; closure_load_ssr_data(ssr_spec * alpha, roughness, N, viewCameraVec, int(ssr_id), result); result.transmittance = vec3(1.0 - alpha); |