diff options
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet.h | 35 | ||||
-rw-r--r-- | intern/cycles/kernel/closure/bsdf_microfacet_multi.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_passes.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/svm/svm_types.h | 6 |
4 files changed, 43 insertions, 22 deletions
diff --git a/intern/cycles/kernel/closure/bsdf_microfacet.h b/intern/cycles/kernel/closure/bsdf_microfacet.h index 2f73434706c..2884ea62a18 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet.h @@ -37,6 +37,7 @@ CCL_NAMESPACE_BEGIN typedef ccl_addr_space struct MicrofacetExtra { float3 color, cspec0; + float3 fresnel_color; float clearcoat; } MicrofacetExtra; @@ -276,6 +277,22 @@ ccl_device_forceinline float D_GTR1(float NdotH, float alpha) return (alpha2 - 1.0f) / (M_PI_F * logf(alpha2) * t); } +ccl_device_forceinline void bsdf_microfacet_fresnel_color(const ShaderData *sd, + MicrofacetBsdf *bsdf) +{ + kernel_assert(CLOSURE_IS_BSDF_MICROFACET_FRESNEL(bsdf->type)); + + float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); + bsdf->extra->fresnel_color = interpolate_fresnel_color( + sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0); + + if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID) { + bsdf->extra->fresnel_color *= 0.25f * bsdf->extra->clearcoat; + } + + bsdf->sample_weight *= average(bsdf->extra->fresnel_color); +} + /* GGX microfacet with Smith shadow-masking from: * * Microfacet Models for Refraction through Rough Surfaces @@ -305,15 +322,13 @@ ccl_device int bsdf_microfacet_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const Sha { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -321,15 +336,13 @@ ccl_device int bsdf_microfacet_ggx_clearcoat_setup(MicrofacetBsdf *bsdf, const S { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= 0.25f * bsdf->extra->clearcoat * F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = bsdf->alpha_x; bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + return SD_BSDF | SD_BSDF_HAS_EVAL; } @@ -364,15 +377,13 @@ ccl_device int bsdf_microfacet_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsdf, con { bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0); - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; - bsdf->alpha_x = saturate(bsdf->alpha_x); bsdf->alpha_y = saturate(bsdf->alpha_y); bsdf->type = CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID; + bsdf_microfacet_fresnel_color(sd, bsdf); + 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 9780dd87415..a5fe989bcd1 100644 --- a/intern/cycles/kernel/closure/bsdf_microfacet_multi.h +++ b/intern/cycles/kernel/closure/bsdf_microfacet_multi.h @@ -402,9 +402,7 @@ ccl_device int bsdf_microfacet_multi_ggx_aniso_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -424,9 +422,7 @@ ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, con bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return bsdf_microfacet_multi_ggx_common_setup(bsdf); } @@ -582,9 +578,7 @@ ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsd bsdf->type = CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID; - float F0 = fresnel_dielectric_cos(1.0f, bsdf->ior); - float F = average(interpolate_fresnel_color(sd->I, bsdf->N, bsdf->ior, F0, bsdf->extra->cspec0)); - bsdf->sample_weight *= F; + bsdf_microfacet_fresnel_color(sd, bsdf); return SD_BSDF | SD_BSDF_HAS_EVAL | SD_BSDF_NEEDS_LCG; } diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h index c1d74dddc2a..3e423e42573 100644 --- a/intern/cycles/kernel/kernel_passes.h +++ b/intern/cycles/kernel/kernel_passes.h @@ -145,7 +145,17 @@ ccl_device_inline void kernel_update_denoising_features(KernelGlobals *kg, normal += sc->N * sc->sample_weight; sum_weight += sc->sample_weight; if (bsdf_get_specular_roughness_squared(sc) > sqr(0.075f)) { - albedo += sc->weight; + float3 closure_albedo = sc->weight; + /* Closures that include a Fresnel term typically have weights close to 1 even though their + * actual contribution is significantly lower. + * To account for this, we scale their weight by the average fresnel factor (the same is also + * done for the sample weight in the BSDF setup, so we don't need to scale that here). */ + if (CLOSURE_IS_BSDF_MICROFACET_FRESNEL(sc->type)) { + MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc; + closure_albedo *= bsdf->extra->fresnel_color; + } + + albedo += closure_albedo; sum_nonspecular_weight += sc->sample_weight; } } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 01710f713ac..aa4dfdca2d1 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -552,6 +552,12 @@ typedef enum ClosureType { (type >= CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID && \ type <= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID) || \ (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID)) +#define CLOSURE_IS_BSDF_MICROFACET_FRESNEL(type) \ + (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_FRESNEL_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_CLEARCOAT_ID || \ + type == CLOSURE_BSDF_MICROFACET_GGX_ANISO_FRESNEL_ID) #define CLOSURE_IS_BSDF_OR_BSSRDF(type) (type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) #define CLOSURE_IS_BSSRDF(type) \ (type >= CLOSURE_BSSRDF_CUBIC_ID && type <= CLOSURE_BSSRDF_PRINCIPLED_RANDOM_WALK_ID) |