diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index 11bf7e96d87..5cb20d68805 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -367,7 +367,12 @@ ccl_device_inline void bsdf_roughness_eta(const KernelGlobals kg, case CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID: { ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; *roughness = make_float2(bsdf->alpha_x, bsdf->alpha_y); - *eta = CLOSURE_IS_REFRACTIVE(bsdf->type) ? 1.0f / bsdf->ior : bsdf->ior; + if (CLOSURE_IS_REFRACTION(bsdf->type) || CLOSURE_IS_GLASS(bsdf->type)) { + *eta = 1.0f / bsdf->ior; + } + else { + *eta = bsdf->ior; + } break; } case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID: @@ -672,7 +677,9 @@ ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float } ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd, - ccl_private const ShaderClosure *sc) + ccl_private const ShaderClosure *sc, + const bool reflection, + const bool transmission) { Spectrum albedo = sc->weight; /* Some closures include additional components such as Fresnel terms that cause their albedo to @@ -686,12 +693,16 @@ ccl_device_inline Spectrum bsdf_albedo(ccl_private const ShaderData *sd, * extra overhead though. */ #if defined(__SVM__) || defined(__OSL__) if (CLOSURE_IS_BSDF_MICROFACET(sc->type)) { - albedo *= bsdf_microfacet_estimate_fresnel(sd, (ccl_private const MicrofacetBsdf *)sc); + albedo *= bsdf_microfacet_estimate_fresnel( + sd, (ccl_private const MicrofacetBsdf *)sc, reflection, transmission); } else if (sc->type == CLOSURE_BSDF_PRINCIPLED_SHEEN_ID) { + kernel_assert(reflection); albedo *= ((ccl_private const PrincipledSheenBsdf *)sc)->avg_value; } else if (sc->type == CLOSURE_BSDF_HAIR_PRINCIPLED_ID) { + /* TODO(lukas): Principled Hair could also be split into a glossy and a transmission component, + * similar to Glass BSDFs. */ albedo *= bsdf_principled_hair_albedo(sd, sc); } #endif diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 7d3dd79030a..5dea6b0c64a 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -221,12 +221,20 @@ ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetB const bool refraction) { if (bsdf->fresnel_type == MicrofacetFresnel::PRINCIPLED_V1) { + /* For Principled v1 Glass, cspec0 only provides the specular tint, the main Fresnel term + * is implicit in the phase function of the multi-scattering code. + * Therefore, for Glass, include it here on top of the Principled-specific tints. */ + float F = 1.0f; + if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) { + F = fresnel_dielectric_cos(dot(wi, H), bsdf->ior); + } + ccl_private FresnelPrincipledV1 *fresnel = (ccl_private FresnelPrincipledV1 *)bsdf->fresnel; if (refraction) { - return fresnel->color; + return (1.0f - F) * fresnel->color; } else { - return interpolate_fresnel_color(wi, H, bsdf->ior, fresnel->cspec0); + return F * interpolate_fresnel_color(wi, H, bsdf->ior, fresnel->cspec0); } } else if (bsdf->fresnel_type == MicrofacetFresnel::DIELECTRIC) { @@ -270,8 +278,15 @@ ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetB else if (bsdf->fresnel_type == MicrofacetFresnel::CONSTANT) { /* CONSTANT is only used my MultiGGX, which doesn't call this function. * Therefore, this case only happens when determining the albedo of a MultiGGX closure. - * In that case, return 1.0 since the constant color is already baked into the weight. */ - return one_spectrum(); + * In that case, the constant color is already baked into the weight. + * So, just return the main dielectric Fresnel term for Glass and 1.0 for Glossy. */ + if (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) { + const float F = fresnel_dielectric_cos(dot(wi, H), bsdf->ior); + return make_spectrum(refraction ? (1.0f - F) : F); + } + else { + return refraction ? zero_spectrum() : one_spectrum(); + } } else { return one_spectrum(); @@ -285,17 +300,20 @@ ccl_device_forceinline Spectrum microfacet_fresnel(ccl_private const MicrofacetB * This is used to adjust the sample weight, as well as for the Diff/Gloss/Trans Color pass * and the Denoising Albedo pass. */ ccl_device Spectrum bsdf_microfacet_estimate_fresnel(ccl_private const ShaderData *sd, - ccl_private const MicrofacetBsdf *bsdf) + ccl_private const MicrofacetBsdf *bsdf, + const bool reflection, + const bool transmission) { - const bool is_glass = CLOSURE_IS_GLASS(bsdf->type); - const bool is_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type); + const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type); + const bool m_glass = CLOSURE_IS_GLASS(bsdf->type); + const bool m_reflection = !(m_refraction || m_glass); Spectrum albedo = zero_spectrum(); - if (!is_refractive || is_glass) { + if (reflection && (m_reflection || m_glass)) { /* BSDF has a reflective lobe. */ albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, false); } - if (is_refractive) { + if (transmission && (m_refraction || m_glass)) { /* BSDF has a refractive lobe (unless there's TIR). */ albedo += microfacet_fresnel(bsdf, sd->wi, bsdf->N, true); } @@ -402,8 +420,12 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, } ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; - const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type); + /* Refraction: Only consider BTDF + * Glass: Consider both BRDF and BTDF, mix based on Fresnel + * Reflection: Only consider BRDF */ + const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type); const bool m_glass = CLOSURE_IS_GLASS(bsdf->type); + const bool m_reflection = !(m_refraction || m_glass); const float3 N = bsdf->N; const float cos_NI = dot(N, wi); @@ -413,7 +435,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, const float alpha_x = bsdf->alpha_x; const float alpha_y = bsdf->alpha_y; - const bool is_refraction = (cos_NO < 0.0f); + const bool is_transmission = (cos_NO < 0.0f); /* Check whether the pair of directions is valid for evaluation: * - Incoming direction has to be in the upper hemisphere (Cycles convention) @@ -422,15 +444,15 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, * - Purely reflective closures can't have refraction. * - Purely refractive closures can't have reflection. */ - if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_refraction) || - (is_refraction && !m_refractive) || (!is_refraction && m_refractive && !m_glass)) + if ((cos_NI <= 0) || (alpha_x * alpha_y <= 5e-7f) || ((cos_NgO < 0.0f) != is_transmission) || + (is_transmission && m_reflection) || (!is_transmission && m_refraction)) { *pdf = 0.0f; return zero_spectrum(); } /* Compute half vector. */ - float3 H = is_refraction ? -(bsdf->ior * wo + wi) : (wi + wo); + float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo); const float inv_len_H = 1.0f / len(H); H *= inv_len_H; @@ -438,7 +460,7 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, float D, lambdaI, lambdaO; /* TODO: add support for anisotropic transmission. */ - if (alpha_x == alpha_y || is_refraction) { /* Isotropic. */ + if (alpha_x == alpha_y || is_transmission) { /* Isotropic. */ float alpha2 = alpha_x * alpha_y; if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { @@ -470,19 +492,19 @@ ccl_device Spectrum bsdf_microfacet_eval(ccl_private const ShaderClosure *sc, } float common = D / cos_NI * - (is_refraction ? sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) : - 0.25f); + (is_transmission ? sqr(bsdf->ior * inv_len_H) * fabsf(dot(H, wi) * dot(H, wo)) : + 0.25f); float lobe_pdf = 1.0f; if (m_glass) { float fresnel = fresnel_dielectric_cos(dot(H, wi), bsdf->ior); float reflect_pdf = (fresnel == 1.0f) ? 1.0f : clamp(fresnel, 0.125f, 0.875f); - lobe_pdf = is_refraction ? (1.0f - reflect_pdf) : reflect_pdf; + lobe_pdf = is_transmission ? (1.0f - reflect_pdf) : reflect_pdf; } *pdf = common * lobe_pdf / (1.0f + lambdaI); - const Spectrum F = microfacet_fresnel(bsdf, wi, H, is_refraction); + const Spectrum F = microfacet_fresnel(bsdf, wi, H, is_transmission); return F * common / (1.0f + lambdaO + lambdaI); } @@ -503,7 +525,9 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc, ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc; const float m_eta = bsdf->ior; - const bool m_refractive = CLOSURE_IS_REFRACTIVE(bsdf->type); + const bool m_refraction = CLOSURE_IS_REFRACTION(bsdf->type); + const bool m_glass = CLOSURE_IS_GLASS(bsdf->type); + const bool m_reflection = !(m_refraction || m_glass); const float alpha_x = bsdf->alpha_x; const float alpha_y = bsdf->alpha_y; bool m_singular = (m_type == MicrofacetType::SHARP) || (alpha_x * alpha_y <= 5e-7f); @@ -513,7 +537,7 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc, if (cos_NI <= 0) { *eval = zero_spectrum(); *pdf = 0.0f; - return (m_refractive ? LABEL_TRANSMIT : LABEL_REFLECT) | + return (m_reflection ? LABEL_REFLECT : LABEL_TRANSMIT) | (m_singular ? LABEL_SINGULAR : LABEL_GLOSSY); } @@ -552,13 +576,13 @@ ccl_device int bsdf_microfacet_sample(ccl_private const ShaderClosure *sc, bool valid; bool do_refract; float lobe_pdf; - if (m_refractive) { + if (m_refraction || m_glass) { bool inside; float fresnel = fresnel_dielectric(m_eta, H, wi, wo, &inside); valid = !inside; /* For glass closures, we decide between reflection and refraction here. */ - if (CLOSURE_IS_GLASS(bsdf->type)) { + if (m_glass) { if (fresnel == 1.0f) { /* TIR, reflection is the only option. */ do_refract = false; @@ -675,7 +699,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_principledv1( bsdf->fresnel_type = MicrofacetFresnel::PRINCIPLED_V1; bsdf->fresnel = fresnel; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); } ccl_device void bsdf_microfacet_setup_fresnel_conductor(ccl_private MicrofacetBsdf *bsdf, @@ -684,7 +708,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_conductor(ccl_private MicrofacetBs { bsdf->fresnel_type = MicrofacetFresnel::CONDUCTOR; bsdf->fresnel = fresnel; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); } ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint( @@ -694,7 +718,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint( { bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC_TINT; bsdf->fresnel = fresnel; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); } ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick( @@ -704,7 +728,7 @@ ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick( { bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK; bsdf->fresnel = fresnel; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); } /* GGX microfacet with Smith shadow-masking from: @@ -739,7 +763,7 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(ccl_private MicrofacetBsdf *b bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); return SD_BSDF | SD_BSDF_HAS_EVAL; } diff --git a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h index 6da5acbfbf3..91eb45932fb 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -407,7 +407,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsd bsdf->fresnel_type = MicrofacetFresnel::PRINCIPLED_V1; bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -618,7 +618,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private Microfa bsdf->fresnel_type = MicrofacetFresnel::PRINCIPLED_V1; bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID; - bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf)); + bsdf->sample_weight *= average(bsdf_microfacet_estimate_fresnel(sd, bsdf, true, true)); return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } diff --git a/intern/cycles/kernel/film/denoising_passes.h b/intern/cycles/kernel/film/denoising_passes.h index b81e65c2ab2..06a815a89a2 100644 --- a/intern/cycles/kernel/film/denoising_passes.h +++ b/intern/cycles/kernel/film/denoising_passes.h @@ -67,7 +67,7 @@ ccl_device_forceinline void film_write_denoising_features_surface(KernelGlobals } } - Spectrum closure_albedo = bsdf_albedo(sd, sc); + Spectrum closure_albedo = bsdf_albedo(sd, sc, true, true); if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) { diffuse_albedo += closure_albedo; sum_nonspecular_weight += sc->sample_weight; diff --git a/intern/cycles/kernel/film/light_passes.h b/intern/cycles/kernel/film/light_passes.h index 98b46997806..a7864cdbcca 100644 --- a/intern/cycles/kernel/film/light_passes.h +++ b/intern/cycles/kernel/film/light_passes.h @@ -20,36 +20,61 @@ CCL_NAMESPACE_BEGIN * them separately. */ ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, - const ClosureType closure_type, + const ShaderClosure *sc, + const float3 wo, Spectrum value) { eval->diffuse = zero_spectrum(); eval->glossy = zero_spectrum(); - if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) { + if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { eval->diffuse = value; } - else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) { + else if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) { eval->glossy = value; } + else if (CLOSURE_IS_GLASS(sc->type)) { + /* Glass can count as glossy or transmission, depending on which side we end up on. */ + if (dot(sc->N, wo) > 0.0f) { + eval->glossy = value; + } + } eval->sum = value; } +ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, Spectrum value) +{ + eval->diffuse = zero_spectrum(); + eval->glossy = zero_spectrum(); + eval->sum = value; +} + ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval, - const ClosureType closure_type, + const ShaderClosure *sc, + const float3 wo, Spectrum value) { - if (CLOSURE_IS_BSDF_DIFFUSE(closure_type)) { + if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) { eval->diffuse += value; } - else if (CLOSURE_IS_BSDF_GLOSSY(closure_type)) { + else if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) { eval->glossy += value; } + else if (CLOSURE_IS_GLASS(sc->type)) { + if (dot(sc->N, wo) > 0.0f) { + eval->glossy += value; + } + } eval->sum += value; } +ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval, Spectrum value) +{ + eval->sum += value; +} + ccl_device_inline bool bsdf_eval_is_zero(ccl_private BsdfEval *eval) { return is_zero(eval->sum); diff --git a/intern/cycles/kernel/integrator/mnee.h b/intern/cycles/kernel/integrator/mnee.h index 5f73e5bbcb6..18277f91204 100644 --- a/intern/cycles/kernel/integrator/mnee.h +++ b/intern/cycles/kernel/integrator/mnee.h @@ -981,7 +981,7 @@ ccl_device_forceinline int kernel_path_mnee_sample(KernelGlobals kg, bool found_refractive_microfacet_bsdf = false; for (int ci = 0; ci < sd_mnee->num_closure; ci++) { ccl_private ShaderClosure *bsdf = &sd_mnee->closure[ci]; - if (CLOSURE_IS_REFRACTIVE(bsdf->type)) { + if (CLOSURE_IS_REFRACTION(bsdf->type) || CLOSURE_IS_GLASS(bsdf->type)) { /* Note that Glass closures are treated as refractive further below. */ found_refractive_microfacet_bsdf = true; diff --git a/intern/cycles/kernel/integrator/surface_shader.h b/intern/cycles/kernel/integrator/surface_shader.h index a0fa9255628..89e21d7808a 100644 --- a/intern/cycles/kernel/integrator/surface_shader.h +++ b/intern/cycles/kernel/integrator/surface_shader.h @@ -90,11 +90,12 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg, { /* Filter out closures. */ if (kernel_data.integrator.filter_closures) { - if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) { + const int filter_closures = kernel_data.integrator.filter_closures; + if (filter_closures & FILTER_CLOSURE_EMISSION) { sd->closure_emission_background = zero_spectrum(); } - if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) { + if (filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) { sd->flag &= ~SD_BSDF_HAS_EVAL; } @@ -102,19 +103,20 @@ ccl_device_inline void surface_shader_prepare_closures(KernelGlobals kg, for (int i = 0; i < sd->num_closure; i++) { ccl_private ShaderClosure *sc = &sd->closure[i]; - if ((CLOSURE_IS_BSDF_DIFFUSE(sc->type) && - (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIFFUSE)) || - (CLOSURE_IS_BSDF_GLOSSY(sc->type) && - (kernel_data.integrator.filter_closures & FILTER_CLOSURE_GLOSSY)) || - (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) && - (kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSMISSION))) + const bool filter_diffuse = (filter_closures & FILTER_CLOSURE_DIFFUSE); + const bool filter_glossy = (filter_closures & FILTER_CLOSURE_GLOSSY); + const bool filter_transmission = (filter_closures & FILTER_CLOSURE_TRANSMISSION); + const bool filter_glass = filter_glossy && filter_transmission; + if ((CLOSURE_IS_BSDF_DIFFUSE(sc->type) && filter_diffuse) || + (CLOSURE_IS_BSDF_GLOSSY(sc->type) && filter_glossy) || + (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) && filter_transmission) || + (CLOSURE_IS_GLASS(sc->type) && filter_glass)) { sc->type = CLOSURE_NONE_ID; sc->sample_weight = 0.0f; } else if ((CLOSURE_IS_BSDF_TRANSPARENT(sc->type) && - (kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSPARENT))) - { + (filter_closures & FILTER_CLOSURE_TRANSPARENT))) { sc->type = CLOSURE_HOLDOUT_ID; sc->sample_weight = 0.0f; sd->flag |= SD_HOLDOUT; @@ -218,6 +220,13 @@ ccl_device_forceinline bool _surface_shader_exclude(ClosureType type, uint light return true; } } + /* Glass closures are both glossy and transmissive, so only exclude them if both are filtered. */ + const uint exclude_glass = SHADER_EXCLUDE_TRANSMIT | SHADER_EXCLUDE_GLOSSY; + if ((light_shader_flags & exclude_glass) == exclude_glass) { + if (CLOSURE_IS_GLASS(type)) { + return true; + } + } return false; } @@ -245,7 +254,7 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg, Spectrum eval = bsdf_eval(kg, sd, sc, wo, &bsdf_pdf); if (bsdf_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval * sc->weight); + bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight); sum_pdf += bsdf_pdf * sc->sample_weight; } } @@ -268,7 +277,7 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg, * factors drop out when using balance heuristic weighting. */ float sum_pdf = 0.0f; float sum_sample_weight = 0.0f; - bsdf_eval_init(result_eval, CLOSURE_NONE_ID, zero_spectrum()); + bsdf_eval_init(result_eval, zero_spectrum()); for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; @@ -278,7 +287,7 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg, Spectrum eval = bsdf_eval(kg, sd, sc, wo, &bsdf_pdf); kernel_assert(bsdf_pdf >= 0.0f); if (bsdf_pdf != 0.0f) { - bsdf_eval_accum(result_eval, sc->type, eval * sc->weight); + bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight); sum_pdf += bsdf_pdf * sc->sample_weight; kernel_assert(bsdf_pdf * sc->sample_weight >= 0.0f); pdfs[i] = bsdf_pdf * sc->sample_weight; @@ -319,7 +328,7 @@ ccl_device_inline ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags) { - bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, zero_spectrum()); + bsdf_eval_init(bsdf_eval, zero_spectrum()); float pdf = _surface_shader_bsdf_eval_mis( kg, sd, wo, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags); @@ -441,7 +450,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg, /* Initialize to zero. */ int label = LABEL_NONE; Spectrum eval = zero_spectrum(); - bsdf_eval_init(bsdf_eval, CLOSURE_NONE_ID, eval); + bsdf_eval_init(bsdf_eval, eval); *unguided_bsdf_pdf = 0.0f; float guide_pdf = 0.0f; @@ -505,7 +514,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg, # endif if (*unguided_bsdf_pdf != 0.0f) { - bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight); + bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight); kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f); @@ -554,7 +563,7 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg, label = bsdf_sample(kg, sd, sc, path_flag, rand_bsdf, &eval, wo, pdf, sampled_roughness, eta); if (*pdf != 0.0f) { - bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight); + bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight); if (sd->num_closure > 1) { float sweight = sc->sample_weight; @@ -562,7 +571,7 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg, } } else { - bsdf_eval_init(bsdf_eval, sc->type, zero_spectrum()); + bsdf_eval_init(bsdf_eval, zero_spectrum()); } return label; @@ -634,7 +643,7 @@ ccl_device Spectrum surface_shader_diffuse(KernelGlobals kg, ccl_private const S ccl_private const ShaderClosure *sc = &sd->closure[i]; if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type)) - eval += bsdf_albedo(sd, sc); + eval += bsdf_albedo(sd, sc, true, true); } return eval; @@ -647,8 +656,8 @@ ccl_device Spectrum surface_shader_glossy(KernelGlobals kg, ccl_private const Sh for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; - if (CLOSURE_IS_BSDF_GLOSSY(sc->type)) - eval += bsdf_albedo(sd, sc); + if (CLOSURE_IS_BSDF_GLOSSY(sc->type) || CLOSURE_IS_GLASS(sc->type)) + eval += bsdf_albedo(sd, sc, true, false); } return eval; @@ -661,8 +670,8 @@ ccl_device Spectrum surface_shader_transmission(KernelGlobals kg, ccl_private co for (int i = 0; i < sd->num_closure; i++) { ccl_private const ShaderClosure *sc = &sd->closure[i]; - if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) - eval += bsdf_albedo(sd, sc); + if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) || CLOSURE_IS_GLASS(sc->type)) + eval += bsdf_albedo(sd, sc, false, true); } return eval; diff --git a/intern/cycles/kernel/integrator/volume_shader.h b/intern/cycles/kernel/integrator/volume_shader.h index 45804859d7c..f1aaac24a88 100644 --- a/intern/cycles/kernel/integrator/volume_shader.h +++ b/intern/cycles/kernel/integrator/volume_shader.h @@ -217,7 +217,7 @@ ccl_device_inline float _volume_shader_phase_eval_mis(ccl_private const ShaderDa Spectrum eval = volume_phase_eval(sd, svc, wo, &phase_pdf); if (phase_pdf != 0.0f) { - bsdf_eval_accum(result_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); + bsdf_eval_accum(result_eval, eval); sum_pdf += phase_pdf * svc->sample_weight; } @@ -237,7 +237,7 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg, Spectrum eval = volume_phase_eval(sd, svc, wo, &phase_pdf); if (phase_pdf != 0.0f) { - bsdf_eval_accum(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); + bsdf_eval_accum(phase_eval, eval); } return phase_pdf; @@ -250,7 +250,7 @@ ccl_device float volume_shader_phase_eval(KernelGlobals kg, const float3 wo, ccl_private BsdfEval *phase_eval) { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum()); + bsdf_eval_init(phase_eval, zero_spectrum()); float pdf = _volume_shader_phase_eval_mis(sd, phases, wo, -1, phase_eval, 0.0f, 0.0f); @@ -300,7 +300,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg, float guide_pdf = 0.0f; *sampled_roughness = 1.0f - fabsf(svc->g); - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum()); + bsdf_eval_init(phase_eval, zero_spectrum()); if (sample_guiding) { /* Sample guiding distribution. */ @@ -321,7 +321,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg, sd, svc, rand_phase.x, rand_phase.y, &eval, wo, unguided_phase_pdf); if (*unguided_phase_pdf != 0.0f) { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); + bsdf_eval_init(phase_eval, eval); *phase_pdf = *unguided_phase_pdf; if (use_volume_guiding) { @@ -333,7 +333,7 @@ ccl_device int volume_shader_phase_guided_sample(KernelGlobals kg, kernel_assert(reduce_min(bsdf_eval_sum(phase_eval)) >= 0.0f); } else { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, zero_spectrum()); + bsdf_eval_init(phase_eval, zero_spectrum()); } kernel_assert(reduce_min(bsdf_eval_sum(phase_eval)) >= 0.0f); @@ -360,7 +360,7 @@ ccl_device int volume_shader_phase_sample(KernelGlobals kg, int label = volume_phase_sample(sd, svc, rand_phase.x, rand_phase.y, &eval, wo, pdf); if (*pdf != 0.0f) { - bsdf_eval_init(phase_eval, CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID, eval); + bsdf_eval_init(phase_eval, eval); } return label; diff --git a/intern/cycles/kernel/svm/types.h b/intern/cycles/kernel/svm/types.h index b106cfed891..c6df2c2c9d9 100644 --- a/intern/cycles/kernel/svm/types.h +++ b/intern/cycles/kernel/svm/types.h @@ -434,12 +434,14 @@ typedef enum ClosureType { CLOSURE_BSDF_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID, CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID, + CLOSURE_BSDF_HAIR_PRINCIPLED_ID, + CLOSURE_BSDF_HAIR_TRANSMISSION_ID, + + /* Glass */ CLOSURE_BSDF_SHARP_GLASS_ID, CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID, CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID, CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID, - CLOSURE_BSDF_HAIR_PRINCIPLED_ID, - CLOSURE_BSDF_HAIR_TRANSMISSION_ID, /* Special cases */ CLOSURE_BSDF_TRANSPARENT_ID, @@ -473,15 +475,15 @@ typedef enum ClosureType { (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_HAIR_TRANSMISSION_ID) #define CLOSURE_IS_BSDF_SINGULAR(type) \ (type == CLOSURE_BSDF_REFLECTION_ID || type == CLOSURE_BSDF_REFRACTION_ID || \ - type == CLOSURE_BSDF_TRANSPARENT_ID) + type == CLOSURE_BSDF_TRANSPARENT_ID || type == CLOSURE_BSDF_SHARP_GLASS_ID) #define CLOSURE_IS_BSDF_TRANSPARENT(type) (type == CLOSURE_BSDF_TRANSPARENT_ID) #define CLOSURE_IS_BSDF_MULTISCATTER(type) \ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID || \ type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) #define CLOSURE_IS_BSDF_MICROFACET(type) \ - ((type >= CLOSURE_BSDF_MICROFACET_GGX_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \ - (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \ - type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)) + ((type >= CLOSURE_BSDF_REFLECTION_ID && type <= CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) || \ + (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) || \ + (type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID)) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) #define CLOSURE_IS_BSSRDF(type) \ (type >= CLOSURE_BSSRDF_BURLEY_ID && type <= CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID) @@ -491,8 +493,8 @@ typedef enum ClosureType { #define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID) #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID) #define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) -#define CLOSURE_IS_REFRACTIVE(type) \ - (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) +#define CLOSURE_IS_REFRACTION(type) \ + (type >= CLOSURE_BSDF_REFRACTION_ID && type <= CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) #define CLOSURE_IS_GLASS(type) \ (type >= CLOSURE_BSDF_SHARP_GLASS_ID && type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) #define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)