9.5 Dielectric BSDF

In the dielectric case, the relative index of refraction is real-valued, and specular transmission must be considered in addition to reflection. The DielectricBxDF handles this scenario for smooth and rough interfaces.

Figure 9.14 shows an image of an abstract model using this BxDF to model a glass material.

Figure 9.14: When the BRDF for specular reflection and the BTDF for specular transmission are modulated with the Fresnel formula for dielectrics, the realistic angle-dependent variation of the amount of reflection and transmission gives a visually accurate representation of the glass. (Scene courtesy of Beeple.)

<<DielectricBxDF Definition>>= 
class DielectricBxDF { public: <<DielectricBxDF Public Methods>> 
DielectricBxDF(Float eta, TrowbridgeReitzDistribution mfDistrib) : eta(eta), mfDistrib(mfDistrib) {} BxDFFlags Flags() const { BxDFFlags flags = (eta == 1) ? BxDFFlags::Transmission : (BxDFFlags::Reflection | BxDFFlags::Transmission); return flags | (mfDistrib.EffectivelySmooth() ? BxDFFlags::Specular : BxDFFlags::Glossy); } pstd::optional<BSDFSample> Sample_f(Vector3f wo, Float uc, Point2f u, TransportMode mode, BxDFReflTransFlags sampleFlags = BxDFReflTransFlags::All) const; SampledSpectrum f(Vector3f wo, Vector3f wi, TransportMode mode) const; Float PDF(Vector3f wo, Vector3f wi, TransportMode mode, BxDFReflTransFlags sampleFlags = BxDFReflTransFlags::All) const; PBRT_CPU_GPU static constexpr const char *Name() { return "DielectricBxDF"; } std::string ToString() const; void Regularize() { mfDistrib.Regularize(); }
private: <<DielectricBxDF Private Members>> 
Float eta; TrowbridgeReitzDistribution mfDistrib;
};

The constructor takes a single Float-valued eta parameter and a microfacet distribution mfDistrib. Spectrally varying IORs that disperse light into different directions are handled by randomly sampling a single wavelength to follow and then instantiating a corresponding DielectricBxDF. Section 10.5.1 discusses this topic in more detail.

<<DielectricBxDF Public Methods>>= 

<<DielectricBxDF Private Members>>= 
Float eta; TrowbridgeReitzDistribution mfDistrib;

The Flags() method handles three different cases. The first is when the dielectric interface is index-matched—that is, with an equal IOR on both sides (in which case eta equals 1 )—and light is only transmitted. Otherwise, in the other two cases, the BSDF has both reflected and transmitted components. In both of these cases, the TrowbridgeReitzDistribution’s EffectivelySmooth() method differentiates between specular and glossy scattering.

<<DielectricBxDF Public Methods>>+=  
BxDFFlags Flags() const { BxDFFlags flags = (eta == 1) ? BxDFFlags::Transmission : (BxDFFlags::Reflection | BxDFFlags::Transmission); return flags | (mfDistrib.EffectivelySmooth() ? BxDFFlags::Specular : BxDFFlags::Glossy); }

The Sample_f() method must choose between sampling perfect specular reflection or transmission. As before, we postpone handling of rough surfaces and only discuss the perfect specular case for now.

<<DielectricBxDF Method Definitions>>= 
pstd::optional<BSDFSample> DielectricBxDF::Sample_f(Vector3f wo, Float uc, Point2f u, TransportMode mode, BxDFReflTransFlags sampleFlags) const { if (eta == 1 || mfDistrib.EffectivelySmooth()) { <<Sample perfect specular dielectric BSDF>> 
Float R = FrDielectric(CosTheta(wo), eta), T = 1 - R; <<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
if (uc < pr / (pr + pt)) { <<Sample perfect specular dielectric BRDF>> 
Vector3f wi(-wo.x, -wo.y, wo.z); SampledSpectrum fr(R / AbsCosTheta(wi)); return BSDFSample(fr, wi, pr / (pr + pt), BxDFFlags::SpecularReflection);
} else { <<Sample perfect specular dielectric BTDF>> 
<<Compute ray direction for specular transmission>> 
Vector3f wi; Float etap; bool valid = Refract(wo, Normal3f(0, 0, 1), eta, &etap, &wi); if (!valid) return {};
SampledSpectrum ft(T / AbsCosTheta(wi)); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);
return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission, etap);
}
} else { <<Sample rough dielectric BSDF>> 
Vector3f wm = mfDistrib.Sample_wm(wo, u); Float R = FrDielectric(Dot(wo, wm), eta); Float T = 1 - R; <<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
Float pdf; if (uc < pr / (pr + pt)) { <<Sample reflection at rough dielectric interface>> 
Vector3f wi = Reflect(wo, wm); if (!SameHemisphere(wo, wi)) return {}; <<Compute PDF of rough dielectric reflection>> 
pdf = mfDistrib.PDF(wo, wm) / (4 * AbsDot(wo, wm)) * pr / (pr + pt);
SampledSpectrum f(mfDistrib.D(wm) * mfDistrib.G(wo, wi) * R / (4 * CosTheta(wi) * CosTheta(wo))); return BSDFSample(f, wi, pdf, BxDFFlags::GlossyReflection);
} else { <<Sample transmission at rough dielectric interface>> 
Float etap; Vector3f wi; bool tir = !Refract(wo, (Normal3f)wm, eta, &etap, &wi); if (SameHemisphere(wo, wi) || wi.z == 0 || tir) return {}; <<Compute PDF of rough dielectric transmission>> 
Float denom = Sqr(Dot(wi, wm) + Dot(wo, wm) / etap); Float dwm_dwi = AbsDot(wi, wm) / denom; pdf = mfDistrib.PDF(wo, wm) * dwm_dwi * pt / (pr + pt);
<<Evaluate BRDF and return BSDFSample for rough transmission>> 
SampledSpectrum ft(T * mfDistrib.D(wm) * mfDistrib.G(wo, wi) * std::abs(Dot(wi, wm) * Dot(wo, wm) / (CosTheta(wi) * CosTheta(wo) * denom))); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);
return BSDFSample(ft, wi, pdf, BxDFFlags::GlossyTransmission, etap);
}
} }

Figure 9.15: Glass Object Rendered Using the DielectricBxDF. (a) Choosing between specular reflection and transmission with equal probability at each scattering event. (b) Choosing with probability based on the value of the Fresnel equations, as is implemented in the Sample_f() method. Choosing between scattering modes with probability proportional to their contribution significantly reduces error by following fewer paths with low contributions.

Since dielectrics are characterized by both reflection and transmission, the sampling scheme must randomly choose between these two components, which influences the density function. While any discrete distribution is in principle admissible, an efficient approach from a Monte Carlo variance standpoint is to sample according to the contribution that these two components make—in other words, proportional to the Fresnel reflectance R and the complementary transmittance 1-R. Figure 9.15 shows the benefit of sampling in this way compared to an equal split between reflection and transmission.

<<Sample perfect specular dielectric BSDF>>= 
Float R = FrDielectric(CosTheta(wo), eta), T = 1 - R; <<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
if (uc < pr / (pr + pt)) { <<Sample perfect specular dielectric BRDF>> 
Vector3f wi(-wo.x, -wo.y, wo.z); SampledSpectrum fr(R / AbsCosTheta(wi)); return BSDFSample(fr, wi, pr / (pr + pt), BxDFFlags::SpecularReflection);
} else { <<Sample perfect specular dielectric BTDF>> 
<<Compute ray direction for specular transmission>> 
Vector3f wi; Float etap; bool valid = Refract(wo, Normal3f(0, 0, 1), eta, &etap, &wi); if (!valid) return {};
SampledSpectrum ft(T / AbsCosTheta(wi)); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);
return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission, etap);
}

Because BSDF components can be selectively enabled or disabled via the sampleFlags argument, the component choice is based on adjusted probabilities pr and pt that take this into account.

<<Compute probabilities pr and pt for sampling reflection and transmission>>= 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};

In the most common case where both reflection and transmission are sampled, the BSDF value and sample probability contain the common factor R or T, which cancels when their ratio is taken. Thus, all sampled rays end up making the same contribution, and the Fresnel factor manifests in the relative proportion of reflected and transmitted rays.

Putting all of this together, the only change in the following code compared to the analogous fragment <<Sample perfect specular conductor BRDF>> is the incorporation of the discrete probability of the sample.

<<Sample perfect specular dielectric BRDF>>= 
Vector3f wi(-wo.x, -wo.y, wo.z); SampledSpectrum fr(R / AbsCosTheta(wi)); return BSDFSample(fr, wi, pr / (pr + pt), BxDFFlags::SpecularReflection);

Specular transmission is handled along similar lines, though using the refracted ray direction for wi. The equation for the corresponding BTDF is similar to the case for perfect specular reflection, Equation (9.9), though there is an additional subtle technical detail: depending on the IOR eta , refraction either compresses or expands radiance in the angular domain, and the implementation must scale ft to account for this. This correction does not change the amount of radiant power in the scene—rather, it models how the same power is contained in a different solid angle. The details of this step differ depending on the direction of propagation in bidirectional rendering algorithms, and we therefore defer the corresponding fragment <<Account for non-symmetry with transmission to different medium>> to Section 9.5.2.

<<Sample perfect specular dielectric BTDF>>= 
<<Compute ray direction for specular transmission>> 
Vector3f wi; Float etap; bool valid = Refract(wo, Normal3f(0, 0, 1), eta, &etap, &wi); if (!valid) return {};
SampledSpectrum ft(T / AbsCosTheta(wi)); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);
return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission, etap);

The function Refract() computes the refracted direction wi via Snell’s law, which fails in the case of total internal reflection. In principle, this should never happen: the transmission case is sampled with probability T, which is zero in the case of total internal reflection. However, due to floating-point rounding errors, inconsistencies can occasionally arise here. We handle this corner case by returning an invalid sample.

<<Compute ray direction for specular transmission>>= 
Vector3f wi; Float etap; bool valid = Refract(wo, Normal3f(0, 0, 1), eta, &etap, &wi); if (!valid) return {};

As with the ConductorBxDF, zero is returned from the f() method if the interface is smooth and all scattering is perfect specular.

<<DielectricBxDF Method Definitions>>+=  
SampledSpectrum DielectricBxDF::f(Vector3f wo, Vector3f wi, TransportMode mode) const { if (eta == 1 || mfDistrib.EffectivelySmooth()) return SampledSpectrum(0.f); <<Evaluate rough dielectric BSDF>> 
<<Compute generalized half vector wm>> 
Float cosTheta_o = CosTheta(wo), cosTheta_i = CosTheta(wi); bool reflect = cosTheta_i * cosTheta_o > 0; float etap = 1; if (!reflect) etap = cosTheta_o > 0 ? eta : (1 / eta); Vector3f wm = wi * etap + wo; if (cosTheta_i == 0 || cosTheta_o == 0 || LengthSquared(wm) == 0) return {}; wm = FaceForward(Normalize(wm), Normal3f(0, 0, 1));
<<Discard backfacing microfacets>> 
if (Dot(wm, wi) * cosTheta_i < 0 || Dot(wm, wo) * cosTheta_o < 0) return {};
Float F = FrDielectric(Dot(wo, wm), eta); if (reflect) { <<Compute reflection at rough dielectric interface>> 
return SampledSpectrum(mfDistrib.D(wm) * mfDistrib.G(wo, wi) * F / std::abs(4 * cosTheta_i * cosTheta_o));
} else { <<Compute transmission at rough dielectric interface>> 
Float denom = Sqr(Dot(wi, wm) + Dot(wo, wm)/etap) * cosTheta_i * cosTheta_o; Float ft = mfDistrib.D(wm) * (1 - F) * mfDistrib.G(wo, wi) * std::abs(Dot(wi, wm) * Dot(wo, wm) / denom); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);
return SampledSpectrum(ft);
}
}

Also, a PDF value of zero is returned if the BSDF is represented using delta distributions.

<<DielectricBxDF Method Definitions>>+= 
Float DielectricBxDF::PDF(Vector3f wo, Vector3f wi, TransportMode mode, BxDFReflTransFlags sampleFlags) const { if (eta == 1 || mfDistrib.EffectivelySmooth()) return 0; <<Evaluate sampling PDF of rough dielectric BSDF>> 
<<Compute generalized half vector wm>> 
Float cosTheta_o = CosTheta(wo), cosTheta_i = CosTheta(wi); bool reflect = cosTheta_i * cosTheta_o > 0; float etap = 1; if (!reflect) etap = cosTheta_o > 0 ? eta : (1 / eta); Vector3f wm = wi * etap + wo; if (cosTheta_i == 0 || cosTheta_o == 0 || LengthSquared(wm) == 0) return {}; wm = FaceForward(Normalize(wm), Normal3f(0, 0, 1));
<<Discard backfacing microfacets>> 
if (Dot(wm, wi) * cosTheta_i < 0 || Dot(wm, wo) * cosTheta_o < 0) return {};
<<Determine Fresnel reflectance of rough dielectric boundary>> 
Float R = FrDielectric(Dot(wo, wm), eta); Float T = 1 - R;
<<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
<<Return PDF for rough dielectric>> 
Float pdf; if (reflect) { <<Compute PDF of rough dielectric reflection>> 
pdf = mfDistrib.PDF(wo, wm) / (4 * AbsDot(wo, wm)) * pr / (pr + pt);
} else { <<Compute PDF of rough dielectric transmission>> 
Float denom = Sqr(Dot(wi, wm) + Dot(wo, wm) / etap); Float dwm_dwi = AbsDot(wi, wm) / denom; pdf = mfDistrib.PDF(wo, wm) * dwm_dwi * pt / (pr + pt);
} return pdf;
}

The missing three fragments—<<Sample rough dielectric BSDF>>, <<Evaluate rough dielectric BSDF>>, and <<Evaluate sampling PDF of rough dielectric BSDF>>—will be presented in Section 9.7.

9.5.1 Thin Dielectric BSDF

Dielectric interfaces rarely occur in isolation: a particularly common configuration involves two nearby index of refraction changes that are smooth, locally parallel, and mutually reciprocal—that is, with relative IOR eta and a corresponding interface with the inverse 1 slash eta . Examples include plate- and acrylic glass in windows or plastic foil used to seal and preserve food.

This important special case is referred to as a thin dielectric due to the spatial proximity of the two interfaces compared to the larger lateral dimensions. When incident light splits into a reflected and a transmitted component with two separate interfaces, it is scattered in a recursive process that traps some of the light within the two interfaces (though this amount progressively decays as it undergoes an increasing number of reflections).

While the internal scattering process within a general dielectric may be daunting, simple analytic solutions can fully describe what happens inside such a thin dielectric—that is, an interface pair satisfying the above simplifying conditions. pbrt provides a specialized BSDF named ThinDielectricBxDF that exploits these insights to efficiently represent an infinite number of internal interactions. It further allows such surfaces to be represented with a single interface, saving the ray intersection expense of tracing ray paths between the two surfaces.

<<ThinDielectricBxDF Definition>>= 
class ThinDielectricBxDF { public: <<ThinDielectricBxDF Public Methods>> 
ThinDielectricBxDF(Float eta) : eta(eta) {} SampledSpectrum f(Vector3f wo, Vector3f wi, TransportMode mode) const { return SampledSpectrum(0); } pstd::optional<BSDFSample> Sample_f(Vector3f wo, Float uc, Point2f u, TransportMode mode, BxDFReflTransFlags sampleFlags) const { Float R = FrDielectric(AbsCosTheta(wo), eta), T = 1 - R; <<Compute R and T accounting for scattering between interfaces>> 
if (R < 1) { R += Sqr(T) * R / (1 - Sqr(R)); T = 1 - R; }
<<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
if (uc < pr / (pr + pt)) { <<Sample perfect specular dielectric BRDF>> 
Vector3f wi(-wo.x, -wo.y, wo.z); SampledSpectrum fr(R / AbsCosTheta(wi)); return BSDFSample(fr, wi, pr / (pr + pt), BxDFFlags::SpecularReflection);
} else { <<Sample perfect specular transmission at thin dielectric interface>> 
Vector3f wi = -wo; SampledSpectrum ft(T / AbsCosTheta(wi)); return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission);
} } PBRT_CPU_GPU Float PDF(Vector3f wo, Vector3f wi, TransportMode mode, BxDFReflTransFlags sampleFlags) const { return 0; } PBRT_CPU_GPU static constexpr const char *Name() { return "ThinDielectricBxDF"; } std::string ToString() const; PBRT_CPU_GPU void Regularize() { /* TODO */ } PBRT_CPU_GPU BxDFFlags Flags() const { return (BxDFFlags::Reflection | BxDFFlags::Transmission | BxDFFlags::Specular); }
private: Float eta; };

The only parameter to this BxDF is the relative index of refraction of the interior medium.

<<ThinDielectricBxDF Public Methods>>= 
ThinDielectricBxDF(Float eta) : eta(eta) {}

Since this BxDF models only perfect specular scattering, both its f() and PDF() methods just return zero and are therefore not included here.

Figure 9.16: Light Paths in a Thin Plane-Parallel Dielectric Medium. An incident light ray (red) gives rise to an infinite internal scattering process that occurs within the glass plate (blue). At each scattering event, some fraction of the light manages to escape, causing a successive decay of the trapped energy.

The theory of the thin dielectric BSDF goes back to seminal work by Stokes (1860), who investigated light propagation in stacks of glass plates. Figure 9.16 illustrates the most common case involving only a single glass plate: an incident light ray (red) reflects and transmits in proportions upper R and upper T equals 1 minus upper R . When the transmitted ray encounters the bottom interface, reciprocity causes it to reflect and transmit according to the same proportions. This process repeats in perpetuity.

Of course, rays beyond the first interaction are displaced relative to the entrance point. Due to the assumption of a thin dielectric, this spatial shift is considered to be negligible; only the total amount of reflected or transmitted light matters. By making this simplification, it is possible to aggregate the effect of the infinite number of scattering events into a simple modification of the reflectance and transmittance factors.

Consider the paths that are reflected out from the top layer. Their aggregate reflectance upper R prime is given by a geometric series that can be converted into an explicit form:

upper R prime equals upper R plus upper T upper R upper T plus upper T upper R upper R upper R upper T plus midline-horizontal-ellipsis equals upper R plus StartFraction upper T squared upper R Over 1 minus upper R squared EndFraction period

A similar series gives how much light is transmitted, but it can be just as easily computed as upper T prime equals 1 minus upper R prime , due to energy conservation. Figure 9.17 plots upper R prime and upper R as a function of incident angle theta . The second interface has the effect of increasing the overall amount of reflection compared to a single Fresnel interaction.

Figure 9.17: Reflectance of a Fresnel Interface and a Thin Dielectric. This plot compares the reflectance of a single dielectric interface with eta equals 1.5 as determined by the Fresnel equations (9.6) to that of a matching thin dielectric according to Equation (9.10).

The Sample_f() method computes the upper R prime and upper T prime coefficients and then computes probabilities for sampling reflection and transmission, just as the DielectricBxDF did, reusing the corresponding code fragment.

<<ThinDielectricBxDF Public Methods>>+= 
pstd::optional<BSDFSample> Sample_f(Vector3f wo, Float uc, Point2f u, TransportMode mode, BxDFReflTransFlags sampleFlags) const { Float R = FrDielectric(AbsCosTheta(wo), eta), T = 1 - R; <<Compute R and T accounting for scattering between interfaces>> 
if (R < 1) { R += Sqr(T) * R / (1 - Sqr(R)); T = 1 - R; }
<<Compute probabilities pr and pt for sampling reflection and transmission>> 
Float pr = R, pt = T; if (!(sampleFlags & BxDFReflTransFlags::Reflection)) pr = 0; if (!(sampleFlags & BxDFReflTransFlags::Transmission)) pt = 0; if (pr == 0 && pt == 0) return {};
if (uc < pr / (pr + pt)) { <<Sample perfect specular dielectric BRDF>> 
Vector3f wi(-wo.x, -wo.y, wo.z); SampledSpectrum fr(R / AbsCosTheta(wi)); return BSDFSample(fr, wi, pr / (pr + pt), BxDFFlags::SpecularReflection);
} else { <<Sample perfect specular transmission at thin dielectric interface>> 
Vector3f wi = -wo; SampledSpectrum ft(T / AbsCosTheta(wi)); return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission);
} }

The updated reflection and transmission coefficients are easily computed using Equation (9.10), though care must be taken to avoid a division by zero in the case of upper R equals 1 .

<<Compute R and T accounting for scattering between interfaces>>= 
if (R < 1) { R += Sqr(T) * R / (1 - Sqr(R)); T = 1 - R; }

The DielectricBxDF fragment that samples perfect specular reflection is also reused in this method’s implementation, inheriting the computed R value. The transmission case slightly deviates from the DielectricBxDF, as the transmitted direction is simply the negation of wo.

<<Sample perfect specular transmission at thin dielectric interface>>= 
Vector3f wi = -wo; SampledSpectrum ft(T / AbsCosTheta(wi)); return BSDFSample(ft, wi, pt / (pr + pt), BxDFFlags::SpecularTransmission);

9.5.2 Non-Symmetric Scattering and Refraction

Figure 9.18: Snell’s Window. If one looks upward when underwater in a swimming pool, the sky is only visible through a circular window because no light is refracted beyond the critical angle. Outside of the window, only the reflection of the pool bottom is seen.

All physically based BRDFs are symmetric: the incident and outgoing directions can be interchanged without changing the function’s value. However, the same is not generally true for BTDFs. Non-symmetry with BTDFs is due to the fact that when light refracts into a material with a higher index of refraction than the incident medium’s index of refraction, energy is compressed into a smaller set of angles (and vice versa, when going in the opposite direction). This effect is easy to see yourself, for instance, by looking at the sky from underwater in a quiet outdoor swimming pool. Because no light can be refracted above the critical angle ( tilde 48.6 Superscript ring for water), the incident hemisphere of light is squeezed into a considerably smaller subset of the hemisphere, which covers the remaining set of angles (Figure 9.18). Radiance along rays that do refract therefore must increase so that energy is preserved when light passes through the interface.

Figure 9.19: The amount of transmitted radiance at the boundary between media with different indices of refraction is scaled by the squared ratio of the two indices of refraction. Intuitively, this can be understood as the result of the radiance’s differential solid angle being compressed or expanded as a result of transmission.

More formally, consider incident radiance arriving at the boundary between two media, with indices of refraction eta Subscript normal i and eta Subscript normal o (Figure 9.19). Assuming for now that all the incident light is transmitted, the amount of transmitted differential flux is then

normal d squared normal upper Phi Subscript normal o Baseline equals normal d squared normal upper Phi Subscript normal i Baseline period

If we use the definition of radiance, Equation (4.3), we equivalently have

upper L Subscript normal o Baseline cosine theta Subscript normal o Baseline normal d upper A Subscript Baseline normal d omega Subscript normal o Baseline equals upper L Subscript normal i Baseline cosine theta Subscript normal i Baseline normal d upper A Subscript Baseline omega Subscript normal i Baseline period

Expanding the solid angles to spherical angles gives

upper L Subscript normal o Baseline cosine theta Subscript normal o Baseline normal d upper A Subscript Baseline sine theta Subscript normal o Baseline normal d theta Subscript normal o Baseline normal d phi Subscript normal o Baseline equals upper L Subscript normal i Baseline cosine theta Subscript normal i Baseline normal d upper A Subscript Baseline sine theta Subscript normal i Baseline normal d theta Subscript normal i Baseline normal d phi Subscript normal i Baseline period

Differentiating Snell’s law, Equation (9.2), with respect to theta gives the useful relation

eta Subscript normal o Baseline cosine theta Subscript normal o Baseline normal d theta Subscript normal o Baseline equals eta Subscript normal i Baseline cosine theta Subscript normal i Baseline normal d theta Subscript normal i Baseline comma

or

StartFraction cosine theta Subscript normal o Baseline normal d theta Subscript normal o Baseline Over cosine theta Subscript normal i Baseline normal d theta Subscript normal i Baseline EndFraction equals StartFraction eta Subscript normal i Baseline Over eta Subscript normal o Baseline EndFraction period

Substituting both Snell’s law and this relationship into Equation (9.11) and then simplifying, we have

upper L Subscript normal o Baseline eta Subscript normal i Superscript 2 Baseline normal d phi Subscript normal o Baseline equals upper L Subscript normal i Baseline eta Subscript normal o Superscript 2 Baseline normal d phi Subscript normal i Baseline period

Finally, normal d phi Subscript normal i Baseline equals normal d phi Subscript normal o , which gives the final relationship between incident and transmitted radiance:

upper L Subscript normal o Superscript Baseline equals upper L Subscript normal i Baseline StartFraction eta Subscript normal o Superscript 2 Baseline Over eta Subscript normal i Superscript 2 Baseline EndFraction period

The symmetry relationship satisfied by a BTDF is thus

eta Subscript normal o Superscript 2 Baseline f Subscript normal t Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals eta Subscript normal i Superscript 2 Baseline f Subscript normal t Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal i Baseline comma omega Subscript normal o Baseline right-parenthesis period

Non-symmetric scattering can be particularly problematic for bidirectional light transport algorithms that sample light paths starting both from the camera and from the lights. If non-symmetry is not accounted for, then such algorithms may produce incorrect results, since the design of such algorithms is fundamentally based on the principle of symmetry.

We will say that light paths sampled starting from the lights carry importance while paths starting from the camera carry radiance. These terms correspond to the quantity that is recorded at a path’s starting point. With importance transport, the incident and outgoing direction arguments of the BSDFs will be (incorrectly) reversed unless special precautions are taken.

We thus define the adjoint BSDF f Superscript asterisk , whose only role is to evaluate the original BSDF with swapped arguments:

f Superscript asterisk Baseline left-parenthesis normal p comma omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals f left-parenthesis normal p comma omega Subscript normal i Baseline comma omega Subscript normal o Baseline right-parenthesis period

All sampling steps based on importance transport use the adjoint form of the BSDF rather than its original version. Most BSDFs in pbrt are symmetric so that there is no actual difference between f and f Superscript asterisk . However, non-symmetric cases require additional attention.

The TransportMode enumeration is used to inform such non-symmetric BSDFs about the transported quantity so that they can correctly switch between the adjoint and non-adjoint forms.

<<TransportMode Definition>>= 
enum class TransportMode { Radiance, Importance };

The adjoint BTDF is then

f Subscript normal t Superscript asterisk Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals f Subscript normal t Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal i Baseline comma omega Subscript normal o Baseline right-parenthesis equals StartFraction eta Subscript normal i Superscript 2 Baseline Over eta Subscript normal o Superscript 2 Baseline EndFraction f Subscript normal t Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis comma

which effectively cancels out the scale factor in Equation (9.12).

With these equations, we can now define the remaining missing piece in the implementation of the DielectricBxDF evaluation and sampling methods. Whenever radiance is transported over a refractive boundary, we apply the scale factor from Equation (9.12). For importance transport, we use the adjoint BTDF, which lacks the scaling factor due to the combination of Equations (9.12) and (9.13).

<<Account for non-symmetry with transmission to different medium>>= 
if (mode == TransportMode::Radiance) ft /= Sqr(etap);