diff --git a/intern/cycles/kernel/closure/bsdf_toon.h b/intern/cycles/kernel/closure/bsdf_toon.h index efa49310cf1..823a33508e0 100644 --- a/intern/cycles/kernel/closure/bsdf_toon.h +++ b/intern/cycles/kernel/closure/bsdf_toon.h @@ -18,15 +18,20 @@ typedef struct ToonBsdf { static_assert(sizeof(ShaderClosure) >= sizeof(ToonBsdf), "ToonBsdf is too large!"); +ccl_device_inline int bsdf_toon_setup_common(ccl_private ToonBsdf *bsdf) +{ + bsdf->size = clamp(bsdf->size, 1e-5f, 1.0f) * M_PI_2_F; + bsdf->smooth = saturatef(bsdf->smooth) * M_PI_2_F; + + return SD_BSDF | SD_BSDF_HAS_EVAL; +} + /* DIFFUSE TOON */ ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf) { bsdf->type = CLOSURE_BSDF_DIFFUSE_TOON_ID; - bsdf->size = saturatef(bsdf->size); - bsdf->smooth = saturatef(bsdf->smooth); - - return SD_BSDF | SD_BSDF_HAS_EVAL; + return bsdf_toon_setup_common(bsdf); } ccl_device float bsdf_toon_get_intensity(float max_angle, float smooth, float angle) @@ -57,19 +62,17 @@ ccl_device Spectrum bsdf_diffuse_toon_eval(ccl_private const ShaderClosure *sc, ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; + float max_angle = bsdf->size; + float smooth = bsdf->smooth; float cosNO = dot(bsdf->N, wo); if (cosNO >= 0.0f) { - float max_angle = bsdf->size * M_PI_2_F; - float smooth = bsdf->smooth * M_PI_2_F; float angle = safe_acosf(fmaxf(cosNO, 0.0f)); + float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); - float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); - - if (eval > 0.0f) { - float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); - - *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); + if (angle < sample_angle) { + float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); + *pdf = M_1_2PI_F / one_minus_cos(sample_angle); return make_spectrum(*pdf * eval); } } @@ -87,29 +90,22 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; - float max_angle = bsdf->size * M_PI_2_F; - float smooth = bsdf->smooth * M_PI_2_F; + float max_angle = bsdf->size; + float smooth = bsdf->smooth; float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); - float angle = sample_angle * rand.x; - if (sample_angle > 0.0f) { - float unused; - *wo = sample_uniform_cone(bsdf->N, one_minus_cos(sample_angle), rand, &unused, pdf); + float cosNO; + *wo = sample_uniform_cone(bsdf->N, one_minus_cos(sample_angle), rand, &cosNO, pdf); - if (dot(Ng, *wo) > 0.0f) { - *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); - } - else { - *eval = zero_spectrum(); - *pdf = 0.0f; - } - } - else { - *eval = zero_spectrum(); - *pdf = 0.0f; + if (dot(Ng, *wo) > 0.0f) { + float angle = acosf(cosNO); + *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); + return LABEL_REFLECT | LABEL_DIFFUSE; } - return LABEL_REFLECT | LABEL_DIFFUSE; + *pdf = 0.0f; + *eval = zero_spectrum(); + return LABEL_NONE; } /* GLOSSY TOON */ @@ -117,10 +113,7 @@ ccl_device int bsdf_diffuse_toon_sample(ccl_private const ShaderClosure *sc, ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf) { bsdf->type = CLOSURE_BSDF_GLOSSY_TOON_ID; - bsdf->size = saturatef(bsdf->size); - bsdf->smooth = saturatef(bsdf->smooth); - - return SD_BSDF | SD_BSDF_HAS_EVAL; + return bsdf_toon_setup_common(bsdf); } ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc, @@ -129,8 +122,8 @@ ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc, ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; - float max_angle = bsdf->size * M_PI_2_F; - float smooth = bsdf->smooth * M_PI_2_F; + float max_angle = bsdf->size; + float smooth = bsdf->smooth; float cosNI = dot(bsdf->N, wi); float cosNO = dot(bsdf->N, wo); @@ -140,12 +133,13 @@ ccl_device Spectrum bsdf_glossy_toon_eval(ccl_private const ShaderClosure *sc, float cosRO = dot(R, wo); float angle = safe_acosf(fmaxf(cosRO, 0.0f)); - - float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); - *pdf = 0.5f * M_1_PI_F / (1.0f - cosf(sample_angle)); - return make_spectrum(*pdf * eval); + if (angle < sample_angle) { + float eval = bsdf_toon_get_intensity(max_angle, smooth, angle); + *pdf = M_1_2PI_F / one_minus_cos(sample_angle); + return make_spectrum(*pdf * eval); + } } *pdf = 0.0f; return zero_spectrum(); @@ -160,8 +154,8 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, ccl_private float *pdf) { ccl_private const ToonBsdf *bsdf = (ccl_private const ToonBsdf *)sc; - float max_angle = bsdf->size * M_PI_2_F; - float smooth = bsdf->smooth * M_PI_2_F; + float max_angle = bsdf->size; + float smooth = bsdf->smooth; float cosNI = dot(bsdf->N, wi); if (cosNI > 0) { @@ -169,30 +163,21 @@ ccl_device int bsdf_glossy_toon_sample(ccl_private const ShaderClosure *sc, float3 R = (2 * cosNI) * bsdf->N - wi; float sample_angle = bsdf_toon_get_sample_angle(max_angle, smooth); - float angle = sample_angle * rand.x; - float unused; - *wo = sample_uniform_cone(R, one_minus_cos(sample_angle), rand, &unused, pdf); + float cosRO; + *wo = sample_uniform_cone(R, one_minus_cos(sample_angle), rand, &cosRO, pdf); - if (dot(Ng, *wo) > 0.0f) { - float cosNO = dot(bsdf->N, *wo); - - /* make sure the direction we chose is still in the right hemisphere */ - if (cosNO > 0) { - *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); - } - else { - *pdf = 0.0f; - *eval = zero_spectrum(); - } - } - else { - *pdf = 0.0f; - *eval = zero_spectrum(); + /* make sure the direction we chose is still in the right hemisphere */ + if (dot(Ng, *wo) > 0.0f && dot(bsdf->N, *wo) > 0.0f) { + float angle = acosf(cosRO); + *eval = make_spectrum(*pdf * bsdf_toon_get_intensity(max_angle, smooth, angle)); + return LABEL_GLOSSY | LABEL_REFLECT; } } - return LABEL_GLOSSY | LABEL_REFLECT; + *pdf = 0.0f; + *eval = zero_spectrum(); + return LABEL_NONE; } CCL_NAMESPACE_END