Fix #108211: Cycles: Correctly split Glass BSDF contributions
So far, each closure in Cycles was either diffuse OR glossy OR transmissive, and its color and contributions were assigned to the corresponding direct/indirect/color passes. However, since Glass is a single closure now, that is no longer enough, since glass has both a glossy and a transmissive component. Therefore, this commit adds support for splitting contributions from the Glass closure between the two types. For 4.0, we might want to also use this for Principled Hair since it also technically has both types, but that would be a change from the existing result so it's not part of 3.6 yet.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user