8.2 Specular Reflection and Transmission

The behavior of light at perfectly smooth surfaces is relatively easy to characterize analytically using both the physical and geometric optics models. These surfaces exhibit perfect specular reflection and transmission of incident light; for a given omega Subscript normal i direction, all light is scattered in a single outgoing direction omega Subscript normal o . For specular reflection, this direction is the outgoing direction that makes the same angle with the normal as the incoming direction:

theta Subscript normal i Baseline equals theta Subscript normal o Baseline comma

and where phi Subscript normal o Baseline equals phi Subscript normal i Baseline plus pi . For transmission, we again have phi Subscript normal o Baseline equals phi Subscript normal i Baseline plus pi , and the outgoing direction theta Subscript t is given by Snell’s law, which relates the angle theta Subscript normal t between the transmitted direction and the surface normal bold n Subscript to the angle theta Subscript normal i between the incident ray and the surface normal bold n Subscript . (One of the exercises at the end of this chapter is to derive Snell’s law using Fermat’s principle from optics.) Snell’s law is based on the index of refraction for the medium that the incident ray is in and the index of refraction for the medium it is entering. The index of refraction describes how much more slowly light travels in a particular medium than in a vacuum. We will use the Greek letter eta , pronounced “eta,” to denote the index of refraction. Snell’s law is

eta Subscript normal i Baseline sine theta Subscript normal i Baseline equals eta Subscript normal t Baseline sine theta Subscript normal t Baseline period
(8.2)

In general, the index of refraction varies with the wavelength of light. Thus, incident light generally scatters in multiple directions at the boundary between two different media, an effect known as dispersion. This effect can be seen when incident white light is split into spectral components by a prism. Common practice in graphics is to ignore this wavelength dependence, since this effect is generally not crucial for visual accuracy and ignoring it simplifies light transport calculations substantially. Alternatively, the paths of multiple beams of light (e.g., at a series of discrete wavelengths) can be tracked through the environment in which a dispersive object is found. The “Further Reading” section at the end of Chapter 14 has pointers to more information on this topic.

Figure 8.4: Dragon model rendered with (1) perfect specular reflection and (2) perfect specular refraction. Image (2) excludes the effects of external and internal reflection; the resulting energy loss produces conspicuous dark regions. (Model courtesy of Christian Schüller.)

Figure 8.4 shows the effect of perfect specular reflection and transmission.

8.2.1 Fresnel Reflectance

In addition to the reflected and transmitted directions, it is also necessary to compute the fraction of incoming light that is reflected or transmitted. For physically accurate reflection or refraction, these terms are directionally dependent and cannot be captured by constant per-surface scaling amounts. The Fresnel equations describe the amount of light reflected from a surface; they are the solution to Maxwell’s equations at smooth surfaces.

Given the index of refraction and the angle which the incident ray makes with the surface normal, the Fresnel equations specify the material’s corresponding reflectance for two different polarization states of the incident illumination. Because the visual effect of polarization is limited in most environments, in pbrt we will make the common assumption that light is unpolarized; that is, it is randomly oriented with respect to the light wave. With this simplifying assumption, the Fresnel reflectance is the average of the squares of the parallel and perpendicular polarization terms.

At this point, it is necessary to draw a distinction among several important classes of materials:

  1. The first class is dielectrics, which are materials that don’t conduct electricity. They have real-valued indices of refraction (usually in the range 1-3) and transmit a portion of the incident illumination. Examples of dielectrics are glass, mineral oil, water, and air.
  2. The second class consists of conductors such as metals. Valence electrons can freely move within the their atomic lattice, allowing electric currents to flow from one place to another. This fundamental atomic property translates into a profoundly different behavior when a conductor is subjected to electromagnetic radiation such as visible light: the material is opaque and reflects back a significant portion of the illumination. A portion of the light is also transmitted into the interior of the conductor, where it is rapidly absorbed: total absorption typically occurs within the top 0.1 mu m of the material, hence only extremely thin metal films are capable of transmitting appreciable amounts of light. We ignore this effect in pbrt and only model the reflection component of conductors. In contrast to dielectrics, conductors have a complex-valued index of refraction eta overbar equals eta plus normal i k .
  3. Semiconductors such as silicon or germanium are the third class though we will not consider them in this book.

Both conductors and dielectrics are governed by the same set of Fresnel equations. Despite this, we prefer to create a special evaluation function for dielectrics to benefit from the particularly simple form that these equations take on when the indices of refraction are guaranteed to be real-valued.

Table 8.1: Indices of refraction for a variety of objects, giving the ratio of the speed of light in a vacuum to the speed of light in the medium. These are generally wavelength-dependent quantities; these values are averages over the visible wavelengths.

Medium Index of refraction eta
Vacuum 1.0
Air at sea level 1.00029
Ice 1.31
Water ( 20 Superscript ring C) 1.333
Fused quartz 1.46
Glass 1.5–1.6
Sapphire 1.77
Diamond 2.42

To compute the Fresnel reflectance at the interface of two dielectric media, we need to know the indices of refraction for the two media. Table 8.1 has the indices of refraction for a number of dielectric materials. The Fresnel reflectance formulae for dielectrics are

StartLayout 1st Row 1st Column r Subscript parallel-to 2nd Column equals StartFraction eta Subscript normal t Baseline cosine theta Subscript normal i Baseline minus eta Subscript normal i Baseline cosine theta Subscript normal t Baseline Over eta Subscript normal t Baseline cosine theta Subscript normal i Baseline plus eta Subscript normal i Baseline cosine theta Subscript normal t Baseline EndFraction comma 2nd Row 1st Column r Subscript up-tack 2nd Column equals StartFraction eta Subscript normal i Baseline cosine theta Subscript normal i Baseline minus eta Subscript normal t Baseline cosine theta Subscript normal t Baseline Over eta Subscript normal i Baseline cosine theta Subscript normal i Baseline plus eta Subscript normal t Baseline cosine theta Subscript normal t Baseline EndFraction comma EndLayout

where r Subscript parallel-to is the Fresnel reflectance for parallel polarized light and r Subscript up-tack is the reflectance for perpendicular polarized light, eta Subscript normal i and eta Subscript normal t are the indices of refraction for the incident and transmitted media, and omega Subscript normal i and omega Subscript normal t are the incident and transmitted directions. omega Subscript normal t can be computed with Snell’s law (see Section 8.2.3).

The cosine terms should all be greater than or equal to zero; for the purposes of computing these values, the geometric normal should be flipped to be on the same side as omega Subscript normal i and omega Subscript normal t when computing cosine theta Subscript normal i and cosine theta Subscript normal t , respectively.

For unpolarized light, the Fresnel reflectance is

upper F Subscript normal r Baseline equals one-half left-parenthesis r Subscript parallel-to Superscript 2 Baseline plus r Subscript up-tack Superscript 2 Baseline right-parenthesis period

Due to conservation of energy, the energy transmitted by a dielectric is 1 minus upper F Subscript normal r .

The function FrDielectric() computes the Fresnel reflection formula for dielectric materials and unpolarized light. The quantity cosine theta Subscript normal i is passed in with the parameter cosThetaI.

<<BxDF Utility Functions>>= 
Float FrDielectric(Float cosThetaI, Float etaI, Float etaT) { cosThetaI = Clamp(cosThetaI, -1, 1); <<Potentially swap indices of refraction>> 
bool entering = cosThetaI > 0.f; if (!entering) { std::swap(etaI, etaT); cosThetaI = std::abs(cosThetaI); }
<<Compute cosThetaT using Snell’s law>> 
Float sinThetaI = std::sqrt(std::max((Float)0, 1 - cosThetaI * cosThetaI)); Float sinThetaT = etaI / etaT * sinThetaI; <<Handle total internal reflection>> 
if (sinThetaT >= 1) return 1;
Float cosThetaT = std::sqrt(std::max((Float)0, 1 - sinThetaT * sinThetaT));
Float Rparl = ((etaT * cosThetaI) - (etaI * cosThetaT)) / ((etaT * cosThetaI) + (etaI * cosThetaT)); Float Rperp = ((etaI * cosThetaI) - (etaT * cosThetaT)) / ((etaI * cosThetaI) + (etaT * cosThetaT)); return (Rparl * Rparl + Rperp * Rperp) / 2; }

To find the cosine of the transmitted angle, cosThetaT, it is first necessary to determine if the incident direction is on the outside of the medium or inside it, so that the two indices of refraction can be interpreted appropriately.

The sign of the cosine of the incident angle indicates on which side of the medium the incident ray lies (Figure 8.5). If the cosine is between 0 and 1 , the ray is on the outside, and if the cosine is between negative 1 and 0 , the ray is on the inside. The parameters etaI and etaT are adjusted such that etaI has the index of refraction of the incident medium, and thus it is ensured that cosThetaI is nonnegative.

Figure 8.5: The cosine of the angle theta between a direction omega Subscript and the geometric surface normal indicates whether the direction is pointing outside the surface (in the same hemisphere as the normal) or inside the surface. In the standard reflection coordinate system, this test just requires checking the  z component of the direction vector. Here, omega Subscript is in the upper hemisphere, with a positive-valued cosine, while omega prime Subscript is in the lower hemisphere.

<<Potentially swap indices of refraction>>= 
bool entering = cosThetaI > 0.f; if (!entering) { std::swap(etaI, etaT); cosThetaI = std::abs(cosThetaI); }

Once the indices of refraction are determined, we can compute the sine of the angle between the transmitted direction and the surface normal, sine theta Subscript normal t , using Snell’s law (Equation (8.2)). Finally, the cosine of this angle is found using the identity sine squared theta plus cosine squared theta equals 1 .

<<Compute cosThetaT using Snell’s law>>= 
Float sinThetaI = std::sqrt(std::max((Float)0, 1 - cosThetaI * cosThetaI)); Float sinThetaT = etaI / etaT * sinThetaI; <<Handle total internal reflection>> 
if (sinThetaT >= 1) return 1;
Float cosThetaT = std::sqrt(std::max((Float)0, 1 - sinThetaT * sinThetaT));

When light is traveling from one medium to another medium with a lower index of refraction, none of the light at incident angles near grazing passes into the other medium. The largest angle at which this happens is called the critical angle; when theta Subscript normal i is greater than the critical angle, total internal reflection occurs, and all of the light is reflected. That case is detected here by a value of sine theta Subscript normal t greater than one; in that case, the Fresnel equations are unnecessary.

<<Handle total internal reflection>>= 
if (sinThetaT >= 1) return 1;

We now focus on the general case of a complex index of refraction eta overbar equals eta plus normal i k , where some of the incident light is potentially absorbed by the material and turned into heat. In addition to the real part, the general Fresnel formula now also depends on the imaginary part k that is referred to as the absorption coefficient.

Figure 8.6 shows a plot of the index of refraction and absorption coefficient for gold; both of these are wavelength-dependent quantities. The directory scenes/spds/metals in the pbrt distribution has wavelength-dependent data for eta and k for a variety of metals. Figure 9.4 in the next chapter shows a model rendered with a metal material.

Figure 8.6: Absorption Coefficient and Index of Refraction of Gold. This plot shows the spectrally varying values of the absorption coefficient k (solid line) and the index of refraction eta (dashed line) for gold, where the horizontal axis is wavelength in nm.

The Fresnel reflectance at the boundary between a conductor and a dielectric medium is given by

StartLayout 1st Row 1st Column r Subscript up-tack 2nd Column equals StartFraction a squared plus b squared minus 2 a cosine theta plus cosine squared theta Over a squared plus b squared plus 2 a cosine theta plus cosine squared theta EndFraction comma 2nd Row 1st Column r Subscript parallel-to 2nd Column equals r Subscript up-tack Baseline StartFraction cosine squared theta left-parenthesis a squared plus b squared right-parenthesis minus 2 a cosine theta sine squared theta plus sine Superscript 4 Baseline theta Over cosine squared theta left-parenthesis a squared plus b squared right-parenthesis plus 2 a cosine theta sine squared theta plus sine Superscript 4 Baseline theta EndFraction comma EndLayout
(8.3)

where

a squared plus b squared equals StartRoot left-parenthesis eta squared minus k squared minus sine squared theta right-parenthesis squared plus 4 eta squared k squared EndRoot comma

and eta plus normal i k equals eta overbar Subscript normal t Baseline slash eta overbar Subscript normal i is the relative index of refraction computed using a complex division operation. However, generally eta overbar Subscript normal i will be a dielectric so that a normal real division can be used instead.

This computation is implemented by the FrConductor() function ; its implementation corresponds directly to Equation (8.3) and so isn’t included here.

<<Reflection Declarations>>= 
Spectrum FrConductor(Float cosThetaI, const Spectrum &etaI, const Spectrum &etaT, const Spectrum &k);

For convenience, we will define an abstract Fresnel class that provides an interface for computing Fresnel reflection coefficients. Using implementations of this interface helps simplify the implementation of subsequent BRDFs that may need to support both forms.

<<BxDF Declarations>>+=  
class Fresnel { public: <<Fresnel Interface>> 
virtual ~Fresnel(); virtual Spectrum Evaluate(Float cosI) const = 0;
};

The only method provided by the Fresnel interface is Fresnel::Evaluate(). Given the cosine of the angle made by the incoming direction and the surface normal, it returns the amount of light reflected by the surface.

<<Fresnel Interface>>= 
virtual Spectrum Evaluate(Float cosI) const = 0;

Fresnel Conductors

FresnelConductor implements this interface for conductors.

<<BxDF Declarations>>+=  
class FresnelConductor : public Fresnel { public: <<FresnelConductor Public Methods>> 
Spectrum Evaluate(Float cosThetaI) const; FresnelConductor(const Spectrum &etaI, const Spectrum &etaT, const Spectrum &k) : etaI(etaI), etaT(etaT), k(k) { }
private: Spectrum etaI, etaT, k; };

Its constructor stores the given index of refraction eta and absorption coefficient k .

<<FresnelConductor Public Methods>>= 
FresnelConductor(const Spectrum &etaI, const Spectrum &etaT, const Spectrum &k) : etaI(etaI), etaT(etaT), k(k) { }

The evaluation routine for FresnelConductor is also simple; it just calls the FrConductor() function defined earlier. Note that it takes the absolute value of cosThetaI before calling FrConductor(), since FrConductor() expects that the cosine will be measured with respect to the normal on the same side of the surface as omega Subscript normal i , or, equivalently, that the absolute value of cosine theta Subscript normal i should be used.

<<BxDF Method Definitions>>+=  
Spectrum FresnelConductor::Evaluate(Float cosThetaI) const { return FrConductor(std::abs(cosThetaI), etaI, etaT, k); }

Fresnel Dielectrics

FresnelDielectric similarly implements the Fresnel interface for dielectric materials.

<<BxDF Declarations>>+=  
class FresnelDielectric : public Fresnel { public: <<FresnelDielectric Public Methods>> 
Spectrum Evaluate(Float cosThetaI) const; FresnelDielectric(Float etaI, Float etaT) : etaI(etaI), etaT(etaT) { }
private: Float etaI, etaT; };

Its constructor stores the indices of refraction on the exterior and interior sides of the surface.

<<FresnelDielectric Public Methods>>= 
FresnelDielectric(Float etaI, Float etaT) : etaI(etaI), etaT(etaT) { }

The evaluation routine for FresnelDielectric analogously calls FrDielectric().

<<BxDF Method Definitions>>+=  
Spectrum FresnelDielectric::Evaluate(Float cosThetaI) const { return FrDielectric(cosThetaI, etaI, etaT); }

A Special Fresnel Interface

The FresnelNoOp implementation of the Fresnel interface returns 100% reflection for all incoming directions. Although this is physically implausible, it is a convenient capability to have available.

<<BxDF Declarations>>+=  
class FresnelNoOp : public Fresnel { public: Spectrum Evaluate(Float) const { return Spectrum(1.); } };

8.2.2 Specular Reflection

We can now implement the SpecularReflection class, which describes physically plausible specular reflection, using the Fresnel interface to compute the fraction of light that is reflected. First, we will derive the BRDF that describes specular reflection. Since the Fresnel equations give the fraction of light reflected, upper F Subscript normal r Baseline left-parenthesis omega Subscript Baseline right-parenthesis , then we need a BRDF such that

upper L Subscript normal o Superscript Baseline left-parenthesis omega Subscript normal o Baseline right-parenthesis equals integral f Subscript normal r Baseline left-parenthesis omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis upper L Subscript normal i Superscript Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis StartAbsoluteValue cosine theta Subscript i Baseline EndAbsoluteValue normal d omega Subscript normal i Baseline equals upper F Subscript normal r Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis upper L Subscript normal i Superscript Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis comma

where omega Subscript normal r Baseline equals normal upper R left-parenthesis omega Subscript normal o Baseline comma bold n Subscript Baseline right-parenthesis is the specular reflection vector for omega Subscript normal o reflected about the surface normal  bold n Subscript . (Recall that theta Subscript normal r Baseline equals theta Subscript normal o for specular reflection, and therefore upper F Subscript normal r Baseline left-parenthesis omega Subscript normal o Baseline right-parenthesis equals upper F Subscript normal r Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis .)

Such a BRDF can be constructed using the Dirac delta distribution. Recall from Section 7.1 that the delta distribution has the useful property that

integral f left-parenthesis x right-parenthesis delta left-parenthesis x minus x 0 right-parenthesis normal d x equals f left-parenthesis x 0 right-parenthesis period
(8.4)

The delta distribution requires special handling compared to standard functions, however. In particular, numerical integration of integrals with delta distributions must explicitly account for the delta distribution. Consider the integral in Equation (8.4): if we tried to evaluate it using the trapezoid rule or some other numerical integration technique, by definition of the delta distribution there would be zero probability that any of the evaluation points x Subscript i would have a nonzero value of delta left-parenthesis x Subscript i Baseline right-parenthesis . Rather, we must allow the delta distribution to determine the evaluation point itself. We will encounter delta distributions in light transport integrals both from specular BxDFs as well as from some of the light sources in Chapter 12.

Intuitively, we want the specular reflection BRDF to be zero everywhere except at the perfect reflection direction, which suggests the use of the delta distribution. A first guess might be to use delta functions to restrict the incident direction to the specular reflection direction omega Subscript normal r . This would yield a BRDF of

f Subscript normal r Baseline left-parenthesis omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals delta left-parenthesis omega Subscript normal i Baseline minus omega Subscript normal r Baseline right-parenthesis upper F Subscript normal r Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis period

Although this seems appealing, plugging it into the scattering equation, Equation (5.9), reveals a problem:

StartLayout 1st Row 1st Column upper L Subscript normal o Baseline left-parenthesis omega Subscript normal o Baseline right-parenthesis 2nd Column equals integral delta left-parenthesis omega Subscript normal i Baseline minus omega Subscript normal r Baseline right-parenthesis upper F Subscript normal r Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis upper L Subscript normal i Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis StartAbsoluteValue cosine theta Subscript normal i Baseline EndAbsoluteValue normal d omega Subscript normal i Baseline 2nd Row 1st Column Blank 2nd Column equals upper F Subscript normal r Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis upper L Subscript normal i Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis StartAbsoluteValue cosine theta Subscript normal r Baseline EndAbsoluteValue period EndLayout

This is not correct because it contains an extra factor of cosine theta Subscript normal r . However, we can divide out this factor to find the correct BRDF for perfect specular reflection:

f Subscript normal r Baseline left-parenthesis normal p Subscript Baseline comma omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals upper F Subscript normal r Baseline left-parenthesis omega Subscript normal r Baseline right-parenthesis StartFraction delta left-parenthesis omega Subscript normal i Baseline minus omega Subscript normal r Baseline right-parenthesis Over StartAbsoluteValue cosine theta Subscript normal r Baseline EndAbsoluteValue EndFraction comma

<<BxDF Declarations>>+=  
class SpecularReflection : public BxDF { public: <<SpecularReflection Public Methods>> 
SpecularReflection(const Spectrum &R, Fresnel *fresnel) : BxDF(BxDFType(BSDF_REFLECTION | BSDF_SPECULAR)), R(R), fresnel(fresnel) { } Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); } Spectrum Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &sample, Float *pdf, BxDFType *sampledType) const; Float Pdf(const Vector3f &wo, const Vector3f &wi) const { return 0; }
private: <<SpecularReflection Private Data>> 
const Spectrum R; const Fresnel *fresnel;
};

The SpecularReflection constructor takes a Spectrum that is used to scale the reflected color and a Fresnel object pointer that describes dielectric or conductor Fresnel properties.

<<SpecularReflection Public Methods>>= 
SpecularReflection(const Spectrum &R, Fresnel *fresnel) : BxDF(BxDFType(BSDF_REFLECTION | BSDF_SPECULAR)), R(R), fresnel(fresnel) { }

<<SpecularReflection Private Data>>= 
const Spectrum R; const Fresnel *fresnel;

The rest of the implementation is straightforward. No scattering is returned from SpecularReflection::f(), since for an arbitrary pair of directions the delta function returns no scattering.

<<SpecularReflection Public Methods>>+=  
Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); }

However, we do implement the Sample_f() method, which selects an appropriate direction according to the delta distribution. It sets the output variable wi to be the reflection of the supplied direction wo about the surface normal. The *pdf value is set to be one; Section 14.1.3 discusses some subtleties about the mathematical quantity that this value of one represents.

<<BxDF Method Definitions>>+=  
Spectrum SpecularReflection::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &sample, Float *pdf, BxDFType *sampledType) const { <<Compute perfect specular reflection direction>> 
*wi = Vector3f(-wo.x, -wo.y, wo.z);
*pdf = 1; return fresnel->Evaluate(CosTheta(*wi)) * R / AbsCosTheta(*wi); }

The desired incident direction is the reflection of omega Subscript normal o around the surface normal, normal upper R left-parenthesis omega Subscript normal o Baseline comma bold n Subscript Baseline right-parenthesis . This direction can be computed fairly easily using vector geometry. First, note that the incoming direction, the reflection direction, and the surface normal all lie in the same plane. We can decompose vectors omega Subscript that lie in a plane into a sum of two components: one parallel to bold n Subscript , which we’ll denote by omega Subscript parallel-to , and one perpendicular, omega Subscript up-tack .

These vectors are easily computed: if bold n Subscript and omega Subscript are normalized, then omega Subscript parallel-to is left-parenthesis cosine theta right-parenthesis bold n Subscript Baseline equals left-parenthesis bold n Subscript Baseline dot omega Subscript Baseline right-parenthesis bold n Subscript (Figure 8.7). Because omega Subscript parallel-to Baseline plus omega Subscript up-tack Baseline equals omega Subscript ,

omega Subscript up-tack Baseline equals omega Subscript Baseline minus omega Subscript parallel-to Baseline equals omega Subscript Baseline minus left-parenthesis bold n Subscript Baseline dot omega Subscript Baseline right-parenthesis bold n Subscript Baseline period

Figure 8.7: The parallel projection of a vector omega Subscript on to the normal bold n Subscript is given by omega Subscript parallel-to Baseline equals left-parenthesis cosine theta right-parenthesis bold n Subscript Baseline equals left-parenthesis bold n Subscript Baseline dot omega Subscript Baseline right-parenthesis bold n Subscript . The perpendicular component is given by omega Subscript up-tack Baseline equals left-parenthesis sine theta right-parenthesis bold n Subscript but is more easily computed by omega Subscript up-tack Baseline equals omega Subscript Baseline minus omega Subscript parallel-to .

Figure 8.8 shows the setting for computing the reflected direction omega Subscript normal r . We can see that both vectors have the same omega Subscript parallel-to component, and the value of omega Subscript normal r up-tack is the negation of omega Subscript normal o up-tack . Therefore, we have

StartLayout 1st Row 1st Column omega Subscript normal r Baseline equals omega Subscript normal r up-tack Baseline plus omega Subscript normal r parallel-to Baseline 2nd Column equals minus omega Subscript normal o up-tack Baseline plus omega Subscript normal o parallel-to Baseline 2nd Row 1st Column Blank 2nd Column equals minus left-parenthesis omega Subscript normal o Baseline minus left-parenthesis bold n Subscript Baseline dot omega Subscript normal o Baseline right-parenthesis bold n Subscript Baseline right-parenthesis plus left-parenthesis bold n Subscript Baseline dot omega Subscript normal o Baseline right-parenthesis bold n Subscript Baseline 3rd Row 1st Column Blank 2nd Column equals minus omega Subscript normal o Baseline plus 2 left-parenthesis bold n Subscript Baseline dot omega Subscript normal o Baseline right-parenthesis bold n Subscript Baseline period EndLayout
(8.5)

Figure 8.8: Because the angles theta Subscript normal o and theta Subscript normal r are equal, the parallel component of the perfect reflection direction omega Subscript normal r parallel-to is the same as the incident direction’s: omega Subscript normal r parallel-to Baseline equals omega Subscript normal o parallel-to . Its perpendicular component is just the incident direction’s perpendicular component, negated.

The Reflect() function implements this computation.

<<BSDF Inline Functions>>+=  
inline Vector3f Reflect(const Vector3f &wo, const Vector3f &n) { return -wo + 2 * Dot(wo, n) * n; }

In the BRDF coordinate system, bold n Subscript Baseline equals left-parenthesis 0 comma 0 comma 1 right-parenthesis , and this expression is substantially simpler.

<<Compute perfect specular reflection direction>>= 
*wi = Vector3f(-wo.x, -wo.y, wo.z);

8.2.3 Specular Transmission

We will now derive the BTDF for specular transmission. Snell’s law is the basis of the derivation. Not only does Snell’s law give the direction for the transmitted ray, but it can also be used to show that radiance along a ray changes as the ray goes between media with different indices of refraction.

Consider incident radiance arriving at the boundary between two media, with indices of refraction eta Subscript normal i and eta Subscript normal o for the incoming and outgoing media, respectively (Figure 8.9).

Figure 8.9: 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.

We use  tau to denote the fraction of incident energy that is transmitted to the outgoing direction as given by the Fresnel equations, so tau equals 1 minus upper F Subscript normal r Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis . The amount of transmitted differential flux, then, is

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

If we use the definition of radiance, Equation (5.2), we 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 tau left-parenthesis upper L Subscript normal i Superscript Baseline cosine theta Subscript normal i Baseline normal d upper A Subscript Baseline normal d omega Subscript normal i Baseline right-parenthesis period

Expanding the solid angles to spherical angles, we have

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 tau 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
(8.6)

We can now differentiate Snell’s law with respect to theta , which gives the 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 period

Rearranging terms, we have

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 this relationship and Snell’s law into Equation (8.6) 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 tau upper L Subscript normal i Baseline eta Subscript normal o Superscript 2 Baseline normal d phi Subscript normal i Baseline period

Because phi Subscript normal i Baseline equals phi Subscript normal o Baseline plus pi and therefore normal d phi Subscript normal i Baseline equals normal d phi Subscript normal o , we have the final relationship:

upper L Subscript normal o Superscript Baseline equals tau upper L Subscript normal i Superscript Baseline StartFraction eta Subscript normal o Superscript 2 Baseline Over eta Subscript normal i Superscript 2 Baseline EndFraction period
(8.7)

As with the BRDF for specular reflection, we need to divide out a cosine theta Subscript normal i term to get the right BTDF for specular transmission:

f Subscript normal r Baseline left-parenthesis omega Subscript normal o Baseline comma omega Subscript normal i Baseline right-parenthesis equals StartFraction eta Subscript normal o Superscript 2 Baseline Over eta Subscript normal i Superscript 2 Baseline EndFraction left-parenthesis 1 minus upper F Subscript normal r Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis right-parenthesis StartFraction delta left-parenthesis omega Subscript normal i Baseline minus normal upper T left-parenthesis omega Subscript normal o Baseline comma bold n Subscript Baseline right-parenthesis right-parenthesis Over StartAbsoluteValue cosine theta Subscript normal i Baseline EndAbsoluteValue EndFraction comma

where normal upper T left-parenthesis omega Subscript normal o Baseline comma bold n Subscript Baseline right-parenthesis is the specular transmission vector that results from specular transmission of omega Subscript normal o through an interface with surface normal  bold n Subscript .

The 1 minus upper F Subscript normal r Baseline left-parenthesis omega Subscript normal i Baseline right-parenthesis term in this equation corresponds to an easily observed effect: transmission is stronger at near-perpendicular angles. For example, if you look straight down into a clear lake, you can see far into the water, but at grazing angles most of the light is reflected as if from a mirror.

The SpecularTransmission class is almost exactly the same as SpecularReflection except that the sampled direction is the direction for perfect specular transmission. Figure 8.10 shows an image of the dragon model using specular reflection and transmission BRDF and BTDF to model glass.

Figure 8.10: 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. (Model courtesy of Christian Schüller.)

<<BxDF Declarations>>+=  
class SpecularTransmission : public BxDF { public: <<SpecularTransmission Public Methods>> 
SpecularTransmission(const Spectrum &T, Float etaA, Float etaB, TransportMode mode) : BxDF(BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR)), T(T), etaA(etaA), etaB(etaB), fresnel(etaA, etaB), mode(mode) { } Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); } Spectrum Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &sample, Float *pdf, BxDFType *sampledType) const; Float Pdf(const Vector3f &wo, const Vector3f &wi) const { return 0; }
private: <<SpecularTransmission Private Data>> 
const Spectrum T; const Float etaA, etaB; const FresnelDielectric fresnel; const TransportMode mode;
};

The SpecularTransmission constructor stores the indices of refraction on both sides of the surface, where etaA is the index of refraction above the surface (where the side the surface normal lies in is “above”), etaB is the index of refraction below the surface, and T gives a transmission scale factor. The TransportMode parameter indicates whether the incident ray that intersected the point where the BxDF was computed started from a light source or whether it was started from the camera. This distinction has implications for how the BxDF’s contribution is computed.

<<SpecularTransmission Public Methods>>= 
SpecularTransmission(const Spectrum &T, Float etaA, Float etaB, TransportMode mode) : BxDF(BxDFType(BSDF_TRANSMISSION | BSDF_SPECULAR)), T(T), etaA(etaA), etaB(etaB), fresnel(etaA, etaB), mode(mode) { }

Because conductors do not transmit light, a FresnelDielectric object is always used for the Fresnel computations.

<<SpecularTransmission Private Data>>= 
const Spectrum T; const Float etaA, etaB; const FresnelDielectric fresnel; const TransportMode mode;

As with SpecularReflection, zero is always returned from SpecularTransmission::f(), since the BTDF is a scaled delta distribution.

<<SpecularTransmission Public Methods>>+=  
Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); }

Equation (8.7) describes how radiance changes as a ray passes from one medium to another. However, it turns out that while this scaling should be applied for rays starting at light sources, it must not be applied for rays starting from the camera. This issue is discussed in more detail in Section 16.1, and the fragment that applies this scaling, <<Account for non-symmetry with transmission to different medium>>, is defined there.

<<BxDF Method Definitions>>+=  
Spectrum SpecularTransmission::Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &sample, Float *pdf, BxDFType *sampledType) const { <<Figure out which eta is incident and which is transmitted>> 
bool entering = CosTheta(wo) > 0; Float etaI = entering ? etaA : etaB; Float etaT = entering ? etaB : etaA;
<<Compute ray direction for specular transmission>> 
if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi)) return 0;
*pdf = 1; Spectrum ft = T * (Spectrum(1.) - fresnel.Evaluate(CosTheta(*wi))); <<Account for non-symmetry with transmission to different medium>> 
if (mode == TransportMode::Radiance) ft *= (etaI * etaI) / (etaT * etaT);
return ft / AbsCosTheta(*wi); }

The method first determines whether the incident ray is entering or exiting the refractive medium. pbrt uses the convention that the surface normal, and thus the left-parenthesis 0 comma 0 comma 1 right-parenthesis direction in local reflection space, is oriented such that it points toward the outside of the object. Therefore, if the z component of the omega Subscript normal o direction is greater than zero, the incident ray is coming from outside of the object.

<<Figure out which eta is incident and which is transmitted>>= 
bool entering = CosTheta(wo) > 0; Float etaI = entering ? etaA : etaB; Float etaT = entering ? etaB : etaA;

<<Compute ray direction for specular transmission>>= 
if (!Refract(wo, Faceforward(Normal3f(0, 0, 1), wo), etaI / etaT, wi)) return 0;

To derive the expression that gives the transmitted direction vector, we can follow a similar approach to the one we used earlier for specular reflection. Figure 8.11 shows the setting.

Figure 8.11: The Geometry of Specular Transmission. Given an incident direction omega Subscript normal i and surface normal bold n Subscript with angle theta Subscript normal i between them, the specularly transmitted direction makes an angle theta Subscript normal t with the surface normal. This direction, omega Subscript normal t , can be computed by using Snell’s law to find its perpendicular component omega Subscript normal t up-tack and then computing the omega Subscript normal t parallel-to that gives a normalized result omega Subscript normal t .

This time, however, we’ll start with the perpendicular component: if the incident vector is normalized and has perpendicular component omega Subscript normal i up-tack , then we know from trigonometry and the definition of omega Subscript up-tack that the length of omega Subscript normal i up-tack is equal to sine theta Subscript normal i . Snell’s law tells us that sine theta Subscript normal t Baseline equals eta Subscript normal i Baseline slash eta Subscript normal t Baseline sine theta Subscript normal i . Negating the direction of omega Subscript normal i up-tack and adjusting the length accordingly, we have

omega Subscript normal t up-tack Baseline equals StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis minus omega Subscript normal i up-tack Baseline right-parenthesis period

Equivalently, because omega Subscript up-tack Baseline equals omega Subscript Baseline minus omega Subscript parallel-to ,

omega Subscript normal t up-tack Baseline equals StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis minus omega Subscript normal i Baseline plus left-parenthesis omega Subscript normal i Baseline dot bold n Subscript Baseline right-parenthesis bold n Subscript Baseline right-parenthesis period

Now for omega Subscript normal t parallel-to : we know that omega Subscript normal t parallel-to is parallel to bold n Subscript but facing in the opposite direction, and we also know that omega Subscript normal t should be normalized. Putting these together,

omega Subscript normal t parallel-to Baseline equals minus left-parenthesis StartRoot 1 minus double-vertical-bar omega Subscript normal t up-tack Baseline double-vertical-bar squared EndRoot right-parenthesis bold n Subscript Baseline period

The full vector omega Subscript normal t , then, is

omega Subscript normal t Baseline equals omega Subscript normal t up-tack Baseline plus omega Subscript normal t parallel-to Baseline equals StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis minus omega Subscript normal i Baseline right-parenthesis plus left-bracket StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis omega Subscript normal i Baseline dot bold n Subscript Baseline right-parenthesis minus StartRoot 1 minus double-vertical-bar omega Subscript normal t up-tack Baseline double-vertical-bar squared EndRoot right-bracket bold n Subscript Baseline period

Because double-vertical-bar omega Subscript normal t up-tack Baseline double-vertical-bar equals sine theta Subscript normal t , the term under the square root is 1 minus sine squared theta Subscript normal t Baseline equals cosine squared theta Subscript normal t , which gives the final result:

omega Subscript normal t Baseline equals StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis minus omega Subscript normal i Baseline right-parenthesis plus left-bracket StartFraction eta Subscript normal i Baseline Over eta Subscript normal t Baseline EndFraction left-parenthesis omega Subscript normal i Baseline dot bold n Subscript Baseline right-parenthesis minus cosine theta Subscript normal t Baseline right-bracket bold n Subscript Baseline period
(8.8)

The Refract() function computes the refracted direction wt given an incident direction wi, surface normal n in the same hemisphere as wi, and eta, the ratio of indices of refraction in the incident and transmitted media, respectively. The Boolean return value indicates whether a valid refracted ray was returned in *wt; it is false in the case of total internal reflection.

<<BSDF Inline Functions>>+=  
inline bool Refract(const Vector3f &wi, const Normal3f &n, Float eta, Vector3f *wt) { <<Compute cosine theta Subscript normal t using Snell’s law>> 
Float cosThetaI = Dot(n, wi); Float sin2ThetaI = std::max(0.f, 1.f - cosThetaI * cosThetaI); Float sin2ThetaT = eta * eta * sin2ThetaI; <<Handle total internal reflection for transmission>> 
if (sin2ThetaT >= 1) return false;
Float cosThetaT = std::sqrt(1 - sin2ThetaT);
*wt = eta * -wi + (eta * cosThetaI - cosThetaT) * Vector3f(n); return true; }

Squaring both sides of Snell’s law lets us compute cosine theta Subscript normal t :

StartLayout 1st Row 1st Column eta Subscript normal i Superscript 2 Baseline sine squared theta Subscript normal i 2nd Column equals eta Subscript normal t Superscript 2 Baseline sine squared theta Subscript normal t Baseline 3rd Column sine squared theta Subscript normal t 4th Column equals StartFraction eta Subscript normal i Superscript 2 Baseline Over eta Subscript normal t Superscript 2 Baseline EndFraction sine squared theta Subscript normal i Baseline 2nd Row 1st Column 1 minus cosine squared theta Subscript normal t 2nd Column equals StartFraction eta Subscript normal i Superscript 2 Baseline Over eta Subscript normal t Superscript 2 Baseline EndFraction sine squared theta Subscript normal i Baseline 3rd Column cosine theta Subscript normal t 4th Column equals StartRoot 1 minus StartFraction eta Subscript normal i Superscript 2 Baseline Over eta Subscript normal t Superscript 2 Baseline EndFraction sine squared theta Subscript normal i Baseline EndRoot EndLayout

<<Compute cosine theta Subscript normal t using Snell’s law>>= 
Float cosThetaI = Dot(n, wi); Float sin2ThetaI = std::max(0.f, 1.f - cosThetaI * cosThetaI); Float sin2ThetaT = eta * eta * sin2ThetaI; <<Handle total internal reflection for transmission>> 
if (sin2ThetaT >= 1) return false;
Float cosThetaT = std::sqrt(1 - sin2ThetaT);

We need to handle the case of total internal reflection here as well. If the squared value of sine theta Subscript normal t is greater than or equal to one, total internal reflection has occurred, so false is returned.

<<Handle total internal reflection for transmission>>= 
if (sin2ThetaT >= 1) return false;

8.2.4 Fresnel-Modulated Specular Reflection and Transmission

For better efficiency in some of the Monte Carlo light transport algorithms to come in Chapters 14, 15, and 16, it’s useful to have a single BxDF that represents both specular reflection and specular transmission together, where the relative weightings of the types of scattering are modulated by the dielectric Fresnel equations. Such a BxDF is provided in FresnelSpecular.

<<BxDF Declarations>>+=  
class FresnelSpecular : public BxDF { public: <<FresnelSpecular Public Methods>> 
FresnelSpecular(const Spectrum &R, const Spectrum &T, Float etaA, Float etaB, TransportMode mode) : BxDF(BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_SPECULAR)), R(R), T(T), etaA(etaA), etaB(etaB), fresnel(etaA, etaB), mode(mode) { } Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); } Spectrum Sample_f(const Vector3f &wo, Vector3f *wi, const Point2f &u, Float *pdf, BxDFType *sampledType) const; Float Pdf(const Vector3f &wo, const Vector3f &wi) const { return 0; }
private: <<FresnelSpecular Private Data>> 
const Spectrum R, T; const Float etaA, etaB; const FresnelDielectric fresnel; const TransportMode mode;
};

<<FresnelSpecular Public Methods>>= 
FresnelSpecular(const Spectrum &R, const Spectrum &T, Float etaA, Float etaB, TransportMode mode) : BxDF(BxDFType(BSDF_REFLECTION | BSDF_TRANSMISSION | BSDF_SPECULAR)), R(R), T(T), etaA(etaA), etaB(etaB), fresnel(etaA, etaB), mode(mode) { }

Since we only focus on the dielectric case, a FresnelDielectric object is always used for the Fresnel computations.

<<FresnelSpecular Private Data>>= 
const Spectrum R, T; const Float etaA, etaB; const FresnelDielectric fresnel; const TransportMode mode;

<<FresnelSpecular Public Methods>>+= 
Spectrum f(const Vector3f &wo, const Vector3f &wi) const { return Spectrum(0.f); }

Because some of the implementation details depend on principles of Monte Carlo integration that are introduced in Chapter 13, the implementation of the Sample_f() method is in Section 14.1.3.