Fix: Cycles invalid normals in various situations

Fix issues related to NaN normals in some situations by trying
to detect when these cases might occur and just reverting back
to default normals.

As a side effect of these changes, OSL now behaves correctly
when given a non-normalized normal.

Pull Request: https://projects.blender.org/blender/blender/pulls/114960
This commit is contained in:
Alaska 2024-01-02 16:24:04 +01:00 committed by Brecht Van Lommel
parent 1f3ce2a311
commit 9b3699db67
4 changed files with 34 additions and 26 deletions

View File

@ -129,7 +129,7 @@ ccl_device float3 ensure_valid_specular_reflection(float3 Ng, float3 I, float3 N
* The X axis is found by normalizing the component of N that's orthogonal to Ng.
* The Y axis isn't actually needed.
*/
const float3 X = normalize(N - dot(N, Ng) * Ng);
const float3 X = safe_normalize_fallback(N - dot(N, Ng) * Ng, N);
/* Calculate N.z and N.x in the local coordinate system.
*

View File

@ -78,7 +78,7 @@ ccl_device void osl_closure_diffuse_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
sd->flag |= bsdf_diffuse_setup(bsdf);
}
@ -100,7 +100,7 @@ ccl_device void osl_closure_oren_nayar_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
bsdf->roughness = closure->roughness;
sd->flag |= bsdf_oren_nayar_setup(bsdf);
@ -123,7 +123,7 @@ ccl_device void osl_closure_translucent_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
sd->flag |= bsdf_translucent_setup(bsdf);
}
@ -145,7 +145,7 @@ ccl_device void osl_closure_reflection_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = bsdf->alpha_y = 0.0f;
sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
@ -168,7 +168,7 @@ ccl_device void osl_closure_refraction_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->ior = closure->ior;
bsdf->alpha_x = bsdf->alpha_y = 0.0f;
@ -214,7 +214,7 @@ ccl_device void osl_closure_dielectric_bsdf_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = closure->ior;
@ -286,7 +286,7 @@ ccl_device void osl_closure_conductor_bsdf_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = 0.0f;
@ -338,7 +338,7 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->T = closure->T;
@ -422,7 +422,7 @@ ccl_device void osl_closure_microfacet_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = closure->ior;
@ -498,7 +498,7 @@ ccl_device void osl_closure_microfacet_f82_tint_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = 0.0f;
@ -542,7 +542,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_glass_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = bsdf->alpha_x;
bsdf->ior = closure->ior;
@ -573,7 +573,7 @@ ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->alpha_x = closure->alpha_x;
bsdf->alpha_y = closure->alpha_y;
bsdf->ior = 1.0f;
@ -608,7 +608,7 @@ ccl_device void osl_closure_ashikhmin_velvet_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->sigma = closure->sigma;
sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
@ -635,7 +635,7 @@ ccl_device void osl_closure_sheen_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
bsdf->roughness = closure->roughness;
const int sheen_flag = bsdf_sheen_setup(kg, sd, bsdf);
@ -666,7 +666,7 @@ ccl_device void osl_closure_diffuse_toon_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->size = closure->size;
bsdf->smooth = closure->smooth;
@ -690,7 +690,7 @@ ccl_device void osl_closure_glossy_toon_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->size = closure->size;
bsdf->smooth = closure->smooth;
@ -758,7 +758,7 @@ ccl_device void osl_closure_diffuse_ramp_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
if (!bsdf->colors) {
@ -785,7 +785,7 @@ ccl_device void osl_closure_phong_ramp_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->exponent = closure->exponent;
bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8);
@ -830,7 +830,8 @@ ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg,
/* create one closure per color channel */
bssrdf->albedo = closure->albedo;
bssrdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bssrdf->N = maybe_ensure_valid_specular_reflection(sd,
safe_normalize_fallback(closure->N, sd->N));
bssrdf->alpha = closure->roughness;
bssrdf->ior = closure->ior;
bssrdf->anisotropy = closure->anisotropy;
@ -857,7 +858,7 @@ ccl_device void osl_closure_hair_reflection_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->T = closure->T;
bsdf->roughness1 = closure->roughness1;
bsdf->roughness2 = closure->roughness2;
@ -884,7 +885,7 @@ ccl_device void osl_closure_hair_transmission_setup(
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->T = closure->T;
bsdf->roughness1 = closure->roughness1;
bsdf->roughness2 = closure->roughness2;
@ -911,7 +912,7 @@ ccl_device void osl_closure_hair_chiang_setup(KernelGlobals kg,
return;
}
bsdf->N = maybe_ensure_valid_specular_reflection(sd, closure->N);
bsdf->N = maybe_ensure_valid_specular_reflection(sd, safe_normalize_fallback(closure->N, sd->N));
bsdf->sigma = closure->sigma;
bsdf->v = closure->v;
bsdf->s = closure->s;
@ -951,7 +952,7 @@ ccl_device void osl_closure_hair_huang_setup(KernelGlobals kg,
return;
}
bsdf->N = closure->N;
bsdf->N = safe_normalize_fallback(closure->N, sd->N);
bsdf->sigma = closure->sigma;
bsdf->roughness = closure->roughness;
bsdf->tilt = closure->tilt;

View File

@ -70,8 +70,8 @@ ccl_device
return svm_node_closure_bsdf_skip(kg, offset, type);
}
float3 N = stack_valid(data_node.x) ? safe_normalize(stack_load_float3(stack, data_node.x)) :
sd->N;
float3 N = stack_valid(data_node.x) ? stack_load_float3(stack, data_node.x) : sd->N;
N = safe_normalize_fallback(N, sd->N);
float param1 = (stack_valid(param1_offset)) ? stack_load_float(stack, param1_offset) :
__uint_as_float(node.z);
@ -132,6 +132,7 @@ ccl_device
float3 coat_normal = stack_valid(coat_normal_offset) ?
stack_load_float3(stack, coat_normal_offset) :
sd->N;
coat_normal = safe_normalize_fallback(coat_normal, sd->N);
// get the base color
uint4 data_base_color = read_node(kg, &offset);

View File

@ -408,6 +408,12 @@ ccl_device_inline float3 safe_normalize(const float3 a)
return (t != 0.0f) ? a * (1.0f / t) : a;
}
ccl_device_inline float3 safe_normalize_fallback(const float3 a, const float3 fallback)
{
float t = len(a);
return (t != 0.0f) ? a * (1.0f / t) : fallback;
}
ccl_device_inline float3 safe_normalize_len(const float3 a, ccl_private float *t)
{
*t = len(a);