Shader: Clamp invalid inputs of various BSDF nodes

Clamp some of the inputs of the Glossy BSDF, Glass BSDF, Sheen BSDF,
and Subsurface Scattering nodes to improve consistency between render
engines and to avoid unexpected results.

* Clamp roughness to 0..1
* Clamp subsurface radius to 0..inf
* Clamp colors to 0..inf

Pull Request: https://projects.blender.org/blender/blender/pulls/120390
This commit is contained in:
Alaska
2024-04-26 17:39:39 +02:00
committed by Brecht Van Lommel
parent e3894f0a07
commit afa66fc628
7 changed files with 34 additions and 26 deletions

View File

@@ -12,12 +12,14 @@ shader node_glass_bsdf(color Color = 0.8,
normal Normal = N,
output closure color BSDF = 0)
{
float r2 = Roughness * Roughness;
color base_color = max(Color, color(0.0));
float r2 = clamp(Roughness, 0.0, 1.0);
r2 = r2 * r2;
float eta = max(IOR, 1e-5);
eta = backfacing() ? 1.0 / eta : eta;
color F0 = F0_from_ior(eta);
color F90 = color(1.0);
BSDF = generalized_schlick_bsdf(
Normal, vector(0.0), Color, Color, r2, r2, F0, F90, -eta, distribution);
Normal, vector(0.0), base_color, base_color, r2, r2, F0, F90, -eta, distribution);
}

View File

@@ -15,7 +15,9 @@ shader node_glossy_bsdf(color Color = 0.8,
output closure color BSDF = 0)
{
/* compute roughness */
float roughness = Roughness * Roughness;
color base_color = max(Color, color(0.0));
float roughness = clamp(Roughness, 0.0, 1.0);
roughness = roughness * roughness;
float roughness_u, roughness_v;
float aniso = clamp(Anisotropy, -0.99, 0.99);
@@ -41,7 +43,8 @@ shader node_glossy_bsdf(color Color = 0.8,
}
if (distribution == "Multiscatter GGX")
BSDF = Color * microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, Color);
BSDF = base_color *
microfacet_multi_ggx_aniso(Normal, T, roughness_u, roughness_v, base_color);
else
BSDF = Color * microfacet(distribution, Normal, T, roughness_u, roughness_v, 0.0, 0);
BSDF = base_color * microfacet(distribution, Normal, T, roughness_u, roughness_v, 0.0, 0);
}

View File

@@ -11,10 +11,11 @@ shader node_sheen_bsdf(color Color = 0.8,
normal Normal = N,
output closure color BSDF = 0)
{
color base_color = max(Color, color(0.0));
float roughness = clamp(Roughness, 0.0, 1.0);
if (distribution == "ashikhmin")
BSDF = Color * ashikhmin_velvet(Normal, roughness);
BSDF = base_color * ashikhmin_velvet(Normal, roughness);
else if (distribution == "microfiber")
BSDF = Color * sheen(Normal, roughness);
BSDF = base_color * sheen(Normal, roughness);
}

View File

@@ -13,14 +13,15 @@ shader node_subsurface_scattering(color Color = 0.8,
normal Normal = N,
output closure color BSSRDF = 0)
{
BSSRDF = Color * bssrdf(method,
Normal,
Scale * Radius,
Color,
"ior",
IOR,
"anisotropy",
Anisotropy,
"roughness",
1.0);
color base_color = max(Color, color(0.0));
BSSRDF = base_color * bssrdf(method,
Normal,
Scale * Radius,
base_color,
"ior",
IOR,
"anisotropy",
Anisotropy,
"roughness",
1.0);
}

View File

@@ -470,7 +470,7 @@ ccl_device
break;
}
float roughness = sqr(param1);
float roughness = sqr(saturatef(param1));
bsdf->N = maybe_ensure_valid_specular_reflection(sd, N);
bsdf->ior = 1.0f;
@@ -513,7 +513,8 @@ ccl_device
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
if (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID) {
kernel_assert(stack_valid(data_node.z));
const Spectrum color = rgb_to_spectrum(stack_load_float3(stack, data_node.z));
const Spectrum color = max(rgb_to_spectrum(stack_load_float3(stack, data_node.z)),
zero_spectrum());
bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, color);
}
}
@@ -580,12 +581,12 @@ ccl_device
float ior = fmaxf(param2, 1e-5f);
bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
bsdf->alpha_x = bsdf->alpha_y = sqr(param1);
bsdf->alpha_x = bsdf->alpha_y = sqr(saturatef(param1));
fresnel->f0 = make_float3(F0_from_ior(ior));
fresnel->f90 = one_spectrum();
fresnel->exponent = -ior;
const float3 color = stack_load_float3(stack, data_node.y);
const float3 color = max(stack_load_float3(stack, data_node.y), zero_float3());
fresnel->reflection_tint = reflective_caustics ? rgb_to_spectrum(color) : zero_spectrum();
fresnel->transmission_tint = refractive_caustics ? rgb_to_spectrum(color) :
zero_spectrum();
@@ -622,7 +623,7 @@ ccl_device
if (bsdf) {
bsdf->N = N;
bsdf->roughness = param1;
bsdf->roughness = saturatef(param1);
sd->flag |= bsdf_sheen_setup(kg, sd, bsdf);
}
@@ -866,7 +867,8 @@ ccl_device
ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
if (bssrdf) {
bssrdf->radius = rgb_to_spectrum(stack_load_float3(stack, data_node.y) * param1);
bssrdf->radius = max(rgb_to_spectrum(stack_load_float3(stack, data_node.y) * param1),
zero_spectrum());
bssrdf->albedo = closure_weight;
bssrdf->N = maybe_ensure_valid_specular_reflection(sd, N);
bssrdf->ior = param2;

View File

@@ -15,6 +15,7 @@ void node_bsdf_glossy(vec4 color,
color = max(color, vec4(0.0));
roughness = saturate(roughness);
N = safe_normalize(N);
/* anisotropy = clamp(anisotropy, -0.99, 0.99) */
vec3 V = coordinate_incoming(g_data.P);
float NV = dot(N, V);

View File

@@ -13,8 +13,6 @@ void node_subsurface_scattering(vec4 color,
out Closure result)
{
color = max(color, vec4(0.0));
scale = max(scale, 0.0);
radius = max(radius, vec3(0));
ior = max(ior, 1e-5);
N = safe_normalize(N);
@@ -22,7 +20,7 @@ void node_subsurface_scattering(vec4 color,
sss_data.weight = weight;
sss_data.color = color.rgb;
sss_data.N = N;
sss_data.sss_radius = radius * scale;
sss_data.sss_radius = max(radius * scale, vec3(0.0));
#ifdef GPU_SHADER_EEVEE_LEGACY_DEFINES
if (do_sss == 0.0) {