[Bf-blender-cvs] [92030f83362] soc-2018-hair-shader: Ringfence possible NaNs with degenerate hair geometry
L. E. Segovia
noreply at git.blender.org
Wed May 23 23:01:19 CEST 2018
Commit: 92030f83362fe567f78e519e0acca0700287a933
Author: L. E. Segovia
Date: Wed May 23 20:59:40 2018 +0000
Branches: soc-2018-hair-shader
https://developer.blender.org/rB92030f83362fe567f78e519e0acca0700287a933
Ringfence possible NaNs with degenerate hair geometry
There are two ways: radiance (F) and intersect position (sd->P)
F comes from invalid core distance, sd->P from invalid intersect position
(which is usually caused from a NaN in ray->t, outside our shader)
===================================================================
M intern/cycles/kernel/closure/bsdf_hair_principled.h
M intern/cycles/kernel/geom/geom_curve.h
M intern/cycles/util/util_math_float3.h
===================================================================
diff --git a/intern/cycles/kernel/closure/bsdf_hair_principled.h b/intern/cycles/kernel/closure/bsdf_hair_principled.h
index 9b02fb28a7d..36d2325a397 100644
--- a/intern/cycles/kernel/closure/bsdf_hair_principled.h
+++ b/intern/cycles/kernel/closure/bsdf_hair_principled.h
@@ -160,6 +160,7 @@ ccl_device int bsdf_principled_hair_setup(KernelGlobals *kg, ShaderData *sd, Pri
float3 dPdCD, curve_P;
float h = curve_core_distance(kg, sd, &curve_P, &dPdCD);
+ assert(isfinite_safe(h));
dPdCD = normalize(dPdCD);
bsdf->geom = make_float4(dPdCD.x, dPdCD.y, dPdCD.z, h);
@@ -205,6 +206,8 @@ ccl_device float3 bsdf_principled_hair_eval(const ShaderData *sd, const ShaderCl
//*pdf = 0.0f;
//return make_float3(0.0f, 0.0f, 0.0f);
+ assert(isfinite3_safe(sd->P) && isfinite_safe(sd->ray_length));
+
const PrincipledHairBSDF *bsdf = (const PrincipledHairBSDF*) sc;
float3 dPdCD = float4_to_float3(bsdf->geom);
@@ -251,14 +254,18 @@ ccl_device float3 bsdf_principled_hair_eval(const ShaderData *sd, const ShaderCl
float4 F;
F = Ap[0] * azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[1] * azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[2] * azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[3] * longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v) * M_1_2PI_F;
+ assert(isfinite3_safe(F));
//printf("%f %f %f %f\n", (double)F.x, (double)F.y, (double)F.z, (double)F.w);
@@ -353,14 +360,18 @@ ccl_device int bsdf_principled_hair_sample(ShaderData *sd, const ShaderClosure *
float4 F;
F = Ap[0] * azimuthal_scattering(phi, 0, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[0], angles[1], sin_theta_o, cos_theta_o, bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[1] * azimuthal_scattering(phi, 1, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[2], angles[3], sin_theta_o, cos_theta_o, 0.25f*bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[2] * azimuthal_scattering(phi, 2, bsdf->s, gamma_o, gamma_t)
* longitudinal_scattering(angles[4], angles[5], sin_theta_o, cos_theta_o, 4.0f*bsdf->v);
+ assert(isfinite3_safe(F));
F += Ap[3] * longitudinal_scattering(sin_theta_i, cos_theta_i, sin_theta_o, cos_theta_o, 4.0f*bsdf->v) * M_1_2PI_F;
+ assert(isfinite3_safe(F));
*eval = float4_to_float3(F);
*pdf = F.w;
diff --git a/intern/cycles/kernel/geom/geom_curve.h b/intern/cycles/kernel/geom/geom_curve.h
index d0bad749945..887f1927a94 100644
--- a/intern/cycles/kernel/geom/geom_curve.h
+++ b/intern/cycles/kernel/geom/geom_curve.h
@@ -27,27 +27,27 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline float3 curvetangent(float t, float3 p0, float3 p1, float3 p2, float3 p3)
{
- float fc = 0.71f;
- float data[4];
- float t2 = t * t;
- data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
- data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
- data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
- data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+ float fc = 0.71f;
+ float data[4];
+ float t2 = t * t;
+ data[0] = -3.0f * fc * t2 + 4.0f * fc * t - fc;
+ data[1] = 3.0f * (2.0f - fc) * t2 + 2.0f * (fc - 3.0f) * t;
+ data[2] = 3.0f * (fc - 2.0f) * t2 + 2.0f * (3.0f - 2.0f * fc) * t + fc;
+ data[3] = 3.0f * fc * t2 - 2.0f * fc * t;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
}
ccl_device_inline float3 curvepoint(float t, float3 p0, float3 p1, float3 p2, float3 p3)
{
- float data[4];
- float fc = 0.71f;
- float t2 = t * t;
- float t3 = t2 * t;
- data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
- data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
- data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
- data[3] = fc * t3 - fc * t2;
- return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
+ float data[4];
+ float fc = 0.71f;
+ float t2 = t * t;
+ float t3 = t2 * t;
+ data[0] = -fc * t3 + 2.0f * fc * t2 - fc * t;
+ data[1] = (2.0f - fc) * t3 + (fc - 3.0f) * t2 + 1.0f;
+ data[2] = (fc - 2.0f) * t3 + (3.0f - 2.0f * fc) * t2 + fc * t;
+ data[3] = fc * t3 - fc * t2;
+ return data[0] * p0 + data[1] * p1 + data[2] * p2 + data[3] * p3;
}
/* Reading attributes on various curve elements */
@@ -128,55 +128,57 @@ ccl_device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd
ccl_device float curve_core_distance(KernelGlobals *kg, ShaderData *sd, float3 *curve_P, float3 *dPdCD)
{
- if((sd->type & PRIMITIVE_ALL_CURVE) == 0) {
- return 0.0f;
- }
-
- int flag = kernel_data.curve.curveflags;
- float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
- int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
- int k1 = k0 + 1;
-
- float curve_r;
- if(flag & CURVE_KN_INTERPOLATE) {
- int ka = max(k0 - 1, __float_as_int(curvedata.x));
- int kb = min(k1 + 1, __float_as_int(curvedata.x) + __float_as_int(curvedata.y) - 1);
-
- float4 P_curve[4];
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
- P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
- }
- else {
- motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
- }
-
- *curve_P = curvepoint(sd->u,
- float4_to_float3(P_curve[0]),
- float4_to_float3(P_curve[1]),
- float4_to_float3(P_curve[2]),
- float4_to_float3(P_curve[3]));
- curve_r = mix(P_curve[1].w, P_curve[2].w, sd->u);
- }
- else {
- float4 P_curve[2];
- if(sd->type & PRIMITIVE_CURVE) {
- P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
- P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
- }
- else {
- motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
- }
- *curve_P = mix(float4_to_float3(P_curve[0]), float4_to_float3(P_curve[1]), sd->u);
- curve_r = mix(P_curve[0].w, P_curve[1].w, sd->u);
- }
-
- *dPdCD = normalize(cross(sd->dPdu, sd->I));
- float h = dot(*dPdCD, sd->P - *curve_P)/curve_r;
- assert(fabsf(h) <= 2.f);
- return h;
+ if((sd->type & PRIMITIVE_ALL_CURVE) == 0) {
+ return 0.0f;
+ }
+
+ assert(isfinite3_safe(sd->P));
+
+ int flag = kernel_data.curve.curveflags;
+ float4 curvedata = kernel_tex_fetch(__curves, sd->prim);
+ int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
+ int k1 = k0 + 1;
+
+ float curve_r;
+ if(flag & CURVE_KN_INTERPOLATE) {
+ int ka = max(k0 - 1, __float_as_int(curvedata.x));
+ int kb = min(k1 + 1, __float_as_int(curvedata.x) + __float_as_int(curvedata.y) - 1);
+
+ float4 P_curve[4];
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
+ P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
+ }
+ else {
+ motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
+ }
+
+ *curve_P = curvepoint(sd->u,
+ float4_to_float3(P_curve[0]),
+ float4_to_float3(P_curve[1]),
+ float4_to_float3(P_curve[2]),
+ float4_to_float3(P_curve[3]));
+ curve_r = mix(P_curve[1].w, P_curve[2].w, sd->u);
+ }
+ else {
+ float4 P_curve[2];
+ if(sd->type & PRIMITIVE_CURVE) {
+ P_curve[0] = kernel_tex_fetch(__curve_keys, k0);
+ P_curve[1] = kernel_tex_fetch(__curve_keys, k1);
+ }
+ else {
+ motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
+ }
+ *curve_P = mix(float4_to_float3(P_curve[0]), float4_to_float3(P_curve[1]), sd->u);
+ curve_r = mix(P_curve[0].w, P_curve[1].w, sd->u);
+ }
+
+ *dPdCD = normalize(cross(sd->dPdu, sd->I));
+ float h = dot(*dPdCD, sd->P - *curve_P)/curve_r;
+ assert(fabsf(h) <= 2.f);
+ return h;
}
/* Curve thickness */
diff --git a/intern/cycles/util/util_math_float3.h b/intern/cycles/util/util_math_float3.h
index 620d0d516fe..aa961b96db5 100644
--- a/intern/cycles/util/util_math_float3.h
+++ b/intern/cycles/util/util_math_float3.h
@@ -379,12 +379,12 @@ ccl_device_inline bool isequal_float3(const float3 a, const float3 b)
ccl_device_inline float3 exp3(float3 v)
{
- return make_float3(expf(v.x), expf(v.y), expf(v.z));
+ return make_float3(expf(v.x), expf(v.y), expf(v.z));
}
ccl_device_inline float3 log3(float3 v)
{
- return make_float3(logf(v.x), logf(v.y), logf(v.z));
+ return make_float3(logf(v.x), logf(v.y), logf(v.z));
}
ccl_device_inline bool isfinite3_safe(float3 v)
@@ -392,6 +392,11 @@ ccl_device_inline bool isfinite3_safe(float3 v)
return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
}
+ccl_device_inline bool isfinite3_safe(float4 v)
+{
+ return isfinite_safe(v.x) && isfinite_safe(v.y) && isfinite_safe(v.z);
+}
+
ccl_device_inline float3 ensure_finite3(float3 v)
{
if(!isfinite_safe(v.x)) v.x = 0.0f;
More information about the Bf-blender-cvs
mailing list