Cycles: Improve smooth thin glass shadow

By allocating transparent BSDF for non-camera rays when roughness is
sufficiently low

Pull Request: https://projects.blender.org/blender/blender/pulls/159798
This commit is contained in:
Weizhen Huang 2026-06-09 17:33:26 +02:00 • committed by Weizhen Huang
parent a2ed5854c0
commit d4ee9b9e79
5 changed files with 45 additions and 10 deletions

View file

@ -1268,8 +1268,20 @@ ccl_device_inline void bsdf_thin_glass_transmission_setup(KernelGlobals kg,
const Spectrum weight,
const float3 N,
const float roughness,
const float ior)
const float ior,
const PathRayVisibility ray_visibility,
const uint32_t path_flag)
{
const float transmission_roughness = bsdf_thin_glass_transmission_roughness(roughness, ior);
if (!(ray_visibility & PATH_RAY_VISIBILITY_CAMERA) &&
roughness_is_almost_specular(transmission_roughness, transmission_roughness))
{
/* Smooth thin glass does not bend the ray and is effectively transparent, allocate transparent
* closures for non-camera rays to improve sampling and keep render passes intact. */
bsdf_transparent_setup(sd, weight, path_flag);
return;
}
/* Model double refraction events as one reflection event with the incident ray mirrored along
* the surface. */
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(
@ -1277,7 +1289,7 @@ ccl_device_inline void bsdf_thin_glass_transmission_setup(KernelGlobals kg,
if (bsdf) {
bsdf->N = -N;
bsdf->T = zero_float3();
bsdf->alpha_x = bsdf->alpha_y = bsdf_thin_glass_transmission_roughness(roughness, ior);
bsdf->alpha_x = bsdf->alpha_y = transmission_roughness;
bsdf->ior = 1.0f;
bsdf->fresnel_type = MicrofacetFresnel::NONE;
bsdf->energy_scale = 1.0f;
@ -1343,7 +1355,9 @@ ccl_device void bsdf_thin_glass_setup(KernelGlobals kg,
const float ior,
const FresnelThinFilm thinfilm,
ccl_private Spectrum *r_reflectance,
ccl_private Spectrum *r_transmittance)
ccl_private Spectrum *r_transmittance,
const PathRayVisibility ray_visibility,
const uint32_t path_flag)
{
const float cos_theta_i = dot(N, sd->wi);
bsdf_thin_glass_fresnel(kg,
@ -1362,7 +1376,8 @@ ccl_device void bsdf_thin_glass_setup(KernelGlobals kg,
kg, sd, reflection_tint, *r_reflectance * weight, N, roughness);
}
if (!is_zero(*r_transmittance)) {
bsdf_thin_glass_transmission_setup(kg, sd, *r_transmittance * weight, N, roughness, ior);
bsdf_thin_glass_transmission_setup(
kg, sd, *r_transmittance * weight, N, roughness, ior, ray_visibility, path_flag);
}
}

View file

@ -517,7 +517,7 @@ ccl_device void osl_closure_generalized_schlick_bsdf_setup(
ccl_device void osl_closure_thin_glass_setup(KernelGlobals kg,
ccl_private ShaderData *sd,
const PathRayVisibility path_visibility,
const uint32_t /*path_flag*/,
const uint32_t path_flag,
const float3 weight,
const ccl_private ThinGlassClosure *closure,
float3 *layer_albedo)
@ -563,7 +563,9 @@ ccl_device void osl_closure_thin_glass_setup(KernelGlobals kg,
closure->ior,
thinfilm,
&reflectance,
&transmittance);
&transmittance,
path_visibility,
path_flag);
if (layer_albedo != nullptr) {
*layer_albedo = transmittance * !!has_transmission + reflectance * !!has_reflection;

View file

@ -379,7 +379,9 @@ ccl_device
ior,
thinfilm,
&reflectance,
&transmittance);
&transmittance,
ray_visibility,
path_flag);
}
else {
ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc(

View file

@ -30,6 +30,7 @@
#include "util/string.h"
#include "util/transform.h"
#include "kernel/closure/bsdf_microfacet.h"
#include "kernel/svm/color_util.h"
#include "kernel/svm/mapping_util.h"
#include "kernel/svm/math_util.h"
@ -2739,7 +2740,22 @@ void PrincipledBsdfNode::simplify_settings(Scene * /* scene */)
bool PrincipledBsdfNode::has_surface_transparent()
{
return (input("Alpha")->link != nullptr || alpha < (1.0f - CLOSURE_WEIGHT_CUTOFF));
if (input("Alpha")->link != nullptr || alpha < (1.0f - CLOSURE_WEIGHT_CUTOFF)) {
return true;
}
/* Smooth thin glass are treated as transparent for non-camera rays. */
if ((input("Thin Wall")->link || thin_wall) && has_nonzero_weight("Transmission Weight")) {
if (input("Roughness")->link || input("IOR")->link) {
return true;
}
const float transmission_roughness = bsdf_thin_glass_transmission_roughness(sqr(roughness),
ior);
return roughness_is_almost_specular(transmission_roughness, transmission_roughness);
}
return false;
}
bool PrincipledBsdfNode::is_thin_wall()

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9122ea34bc214553dc600265dd629debfd93df684994ff136aff20be67242ac6
size 33284
oid sha256:59f3ab7dd107fb2d0a340e38e35e7e7a19df6c2cfd3103a15f3b90e14a9b5019
size 33101