This chapter links to the course’s interactive demos and to original papers on the open web, and it uses MathJax for its formulas. Read it through the course website (or download the file and open it in a browser); a Canvas inline preview will reach neither the demos nor the math. All chapters.

Light Transport and PBR

Radiosity came to graphics from heat-transfer engineering, in the same 1984 paper that introduced the Cornell box. Goral, Torrance, Greenberg and Battaile, SIGGRAPH 1984

The illumination chapter computes a point’s color from the lights, the normal, and the eye, and nothing else in the scene. This chapter writes down the equation that balances the light energy instead, the rendering equation, reads it term by term in the radiometric units of the color chapter, and rebuilds the material term on physical foundations: the BRDF and its two laws, microfacets with the exact Fresnel equations for glass and for gold, the furnace test that measures how much energy a model loses, and the two sliders every modern engine exposes. It then does what a renderer must do with such a model: draw directions from it, evaluate it under a whole sky by the split-sum trick, and extend it past opaque surfaces to glass and skin. Every formula is evaluated by hand at least once, and every figure is computed from the same formulas. The history, from Whitted’s rays to Kajiya’s equation, is in the history chapter; the algorithms that solve the equation are in the ray-tracing chapter.

Contents
  1. What the local model gets wrong
  2. Radiance, and the rendering equation term by term
  3. The BRDF, its laws, and why Phong is not one
  4. Microfacets: D, G and F
  5. Fresnel exactly: dielectrics and conductors
  6. Energy: the furnace test and multiple scattering
  7. Metallic and roughness, and the principled model
  8. Sampling the BRDF
  9. A whole sky at once: image-based lighting and the split sum
  10. Beyond opaque surfaces
  11. Solving the equation: path tracing and real time
  12. Exercises

1 · What the local model gets wrong

A local illumination model (Phong, as the illumination chapter builds it) lights a point from the lights, the normal, and the eye, and nothing else in the scene; the ambient constant stands in for all the light that bounces. Three things follow that no patch can fix.

They are one gap: the local model never balances the light energy at a point. The equation that does was written down by Kajiya in 1986 (the history chapter).

2 · Radiance, and the rendering equation term by term

The equation is a statement about radiance, so the unit comes first. The color chapter defines the radiometric quantities; three of them appear here. Radiant flux is power, in watts. Irradiance \(E\) is the flux arriving per unit area of a surface, in watts per square meter; it is what a light meter held against the surface reads, and it already includes the cosine factor, because a beam at a grazing angle spreads its watts over more square meters (Lambert’s argument). Radiance \(L\) is flux per unit area per unit solid angle, in watts per square meter per steradian: the amount of light traveling along one ray, in one direction, through one small patch. Radiance is the quantity a camera pixel or a retinal cell measures, it does not change along a ray through empty space, and it is what a renderer computes for every pixel. The two are related by the cosine: the irradiance at a point is the incoming radiance summed over the hemisphere with each direction weighted by \(\mathbf{n}\cdot\omega_i\), \(E = \int_\Omega L_i(\omega_i)\,(\mathbf{n}\cdot\omega_i)\,d\omega_i\).

Hemisphere above a surface point x with the normal n, an incoming light direction omega-i at angle theta-i, the outgoing direction omega-o toward the eye at angle theta-o, and the half-vector h between them.
The vocabulary of one point. \(\Omega\) is the hemisphere above \(\mathbf{x}\); \(\omega_i\) is any direction light can arrive from, \(\omega_o\) the direction toward the eye, \(\mathbf{h}\) the unit vector halfway between them. A microfacet reflects \(\omega_i\) into \(\omega_o\) exactly when its normal is \(\mathbf{h}\), which is why \(\mathbf{h}\) appears in every microfacet term of Section 4.
Definition (the rendering equation) With \(\omega_o\) the direction toward the eye, \(\omega_i\) a direction light arrives from, and \(\mathbf{n}\) the surface normal, \[ L_o(\mathbf{x}, \omega_o) \;=\; L_e(\mathbf{x}, \omega_o) \;+\; \int_{\Omega} f_r(\mathbf{x}, \omega_i, \omega_o)\, L_i(\mathbf{x}, \omega_i)\, (\mathbf{n}\cdot\omega_i)\, d\omega_i . \]

Read it in words, one factor at a time.

SymbolNameMeaning
\(L_o(\mathbf{x},\omega_o)\)outgoing radiancethe light leaving \(\mathbf{x}\) toward the eye: the number the pixel will show
\(L_e(\mathbf{x},\omega_o)\)emitted radiancenonzero only on light sources; the ceiling panel of the Cornell box
\(L_i(\mathbf{x},\omega_i)\)incoming radiancethe light arriving at \(\mathbf{x}\) from direction \(\omega_i\); it is some other point’s \(L_o\)
\(f_r\)BRDFthe material: what fraction of light from \(\omega_i\) leaves toward \(\omega_o\) (Section 3)
\(\mathbf{n}\cdot\omega_i\)cosine factorlight arriving at a grazing angle is spread over more surface, so each unit of surface gets less
\(\int_\Omega \dots d\omega_i\)the hemisphere integraladd up the contributions of every incoming direction

It is hard for one reason: \(L_i\) on the right is some other point’s \(L_o\). Light bounces, so the equation refers to itself, and the unknown appears on both sides. That self-reference is exactly the indirect light the local model lacks: the red wall’s \(L_o\) is the white box’s \(L_i\).

Worked example (the integral as a sum) Replace the continuous sky by three small distant lights, so the integral becomes a sum, and take a matte (Lambertian) surface with albedo \(\rho = 0.6\), whose BRDF is the constant \(f_r = \rho/\pi = 0.191\) (Section 3 says why the \(\pi\) is there). The point does not emit.
light\(L_i\)angle to \(\mathbf{n}\)\(\mathbf{n}\cdot\omega_i\)\(f_r\, L_i\, (\mathbf{n}\cdot\omega_i)\)
12.020°0.940\(0.191\times2.0\times0.940 = 0.359\)
20.860°0.500\(0.191\times0.8\times0.500 = 0.076\)
30.575°0.259\(0.191\times0.5\times0.259 = 0.025\)
\(L_o\)0.460
Two things to notice. The cosine factor, not the BRDF, is what makes light 3 nearly irrelevant: it is grazing. And \(L_o\) does not depend on \(\omega_o\) at all, because a Lambertian BRDF is constant; that is the definition of matte. Add a glossy term and the third column would gain a factor that peaks near the mirror direction of each light. The three lights carry the units too: if \(L_i\) is in watts per square meter per steradian and each light subtends a small solid angle \(\Delta\omega\), the sum is really \(\sum f_r L_i (\mathbf{n}\cdot\omega_i)\,\Delta\omega\), and the table has set every \(\Delta\omega\) to 1.

3 · The BRDF, its laws, and why Phong is not one

Definition (BRDF) The bidirectional reflectance distribution function \(f_r(\omega_i, \omega_o)\) is the ratio of the radiance leaving toward \(\omega_o\) to the irradiance arriving from a small cone around \(\omega_i\). Its units are inverse steradians. A physically valid BRDF satisfies two laws: The integral in the second law is the directional albedo \(E(\omega_o)\): the fraction of light arriving from a uniform sky that leaves toward \(\omega_o\), or by reciprocity, the fraction of light arriving from \(\omega_o\) that leaves at all. Section 6 measures it.

The simplest BRDF is the constant one. If a matte surface reflects a fraction \(\rho\) of the light it receives, equally in all directions, then the energy law forces \(f_r = \rho/\pi\), because \(\int_\Omega (\mathbf{n}\cdot\omega_i)\,d\omega_i = \pi\) (the cosine integrated over the hemisphere). That is where the \(\pi\) in the worked example above came from, and it is a first sign of the difference between an ad hoc model and a physical one: in Phong, \(k_d\) is a free number; here, \(\rho/\pi\) is a number tied to a law.

Worked example (how much light a Phong lobe reflects) Take the Phong specular term with \(k_s = 1\) and exponent \(s\), light arriving straight down the normal, and ask how much of it leaves in total. The mirror direction is then the normal itself, so the lobe is \(\cos^s\theta\) and the outgoing energy is \[ \int_\Omega \cos^s\theta \,\cos\theta\, d\omega \;=\; 2\pi \int_0^{\pi/2} \cos^{s+1}\theta \,\sin\theta\, d\theta \;=\; \frac{2\pi}{s+2}. \]
\(s\)14832128
reflected / arriving2.0941.0470.6280.1850.048
A broad lobe (\(s \le 4\)) sends out more light than came in; a sharp one sends out almost none. Neither is what a real material does. “Normalized Phong” fixes this by multiplying the lobe by \((s+2)/2\pi\), and that normalization is the first step toward the physically based models below: a BRDF whose brightness and width are tied together, so an artist who makes a highlight sharper automatically makes it brighter, as a real surface does.

3.1 Measured BRDFs

A BRDF need not be a formula. A gonioreflectometer holds a flat sample, a light and a detector on motorized arms, and records the reflected radiance for every pair of directions; the MERL database (Matusik and others, 2003) did this for 100 materials at \(90\times90\times180\) direction pairs each, about 1.5 million values per color channel per material. A renderer can look such a table up directly, interpolating between samples, and it is the ground truth against which the analytic models below are judged: the model of Section 4 fits the measured metals and plastics well, and fails on fabrics and on layered materials (car paint, iridescent shells), which is why those get models of their own. The lesson to keep: a BRDF is a function of four angles that can be measured, and any formula is an approximation of a measurement.

4 · Microfacets: D, G and F

Physically based rendering (PBR) models a rough surface as a field of microscopic mirrors, the microfacets. Light arriving from \(\omega_i\) leaves toward \(\omega_o\) only off the facets whose normal is the half-vector \(\mathbf{h}\); the rest reflect elsewhere, are shadowed, or shadow their neighbors. The Cook–Torrance specular BRDF collects those three effects into three factors:

Definition (Cook–Torrance specular BRDF) \[ f_r^{\text{spec}}(\omega_i,\omega_o) \;=\; \frac{D(\mathbf{h})\, G(\omega_i,\omega_o)\, F(\omega_i,\mathbf{h})} {4\, (\mathbf{n}\cdot\omega_i)(\mathbf{n}\cdot\omega_o)} , \] where \(D\) is the fraction of facets facing \(\mathbf{h}\) (the normal distribution), \(G\) the fraction of those not shadowed or masked, \(F\) the fraction of light a facet actually reflects (Fresnel), and the denominator converts from facet area to surface area.

4.1 D: where the facets point

The modern default is GGX (also called Trowbridge–Reitz), with a single roughness parameter \(\alpha\):

\[ D(\mathbf{h}) \;=\; \frac{\alpha^2}{\pi\,\big((\mathbf{n}\cdot\mathbf{h})^2(\alpha^2 - 1) + 1\big)^2}. \]
Left: GGX D against the angle between n and h on a log scale for alpha 0.1, 0.3, 0.6 and 1; smaller alpha is a taller, narrower peak with a long tail. Right: Schlick Fresnel against the angle between v and h for plastic, diamond, iron and gold; all rise to 1 at grazing.
Left: \(D\) for four roughnesses. At \(\alpha = 0.1\) the peak is 31.8 and the curve has dropped below 0.01 by 25°; at \(\alpha = 1\) every facet direction is equally likely and \(D = 1/\pi\) everywhere. The area under each curve (weighted by the cosine) is 1: \(D\) is a distribution, and that is the normalization Phong lacked. Right: Schlick’s Fresnel curve. Plastic reflects 4 % head-on and 41 % at 80°; iron starts at 56 %; every material reaches 100 % at grazing.
Two polar plots of reflectance lobes around the mirror direction: Phong cosine-power lobes for s = 4, 32, 256 on the left, GGX-shaped lobes for alpha 0.6, 0.3, 0.1 on the right; GGX keeps a wider skirt at the same peak sharpness.
The same three sharpness levels as lobes around the mirror direction, each normalized to 1 at the peak. GGX keeps a longer tail than a cosine power of the same peak width, which is the visible difference between a Phong highlight (a bright dot with a hard edge) and a GGX one (a dot with a halo). This is the plot the BRDF-lobes demo draws.

4.2 G: shadowing and masking

Facets hide one another. \(G\) is the fraction of facets that are both lit (not shadowed from \(\omega_i\)) and visible (not masked from \(\omega_o\)); the Smith form assumes the two are independent and multiplies one factor per direction. For GGX the exact per-direction factor is

\[ G_1(\mathbf{x}) \;=\; \frac{2\,(\mathbf{n}\cdot\mathbf{x})}{(\mathbf{n}\cdot\mathbf{x}) + \sqrt{\alpha^2 + (1-\alpha^2)(\mathbf{n}\cdot\mathbf{x})^2}}, \qquad G = G_1(\omega_i)\, G_1(\omega_o). \]

Near the normal \(G_1 \approx 1\); at grazing angles on rough surfaces it falls toward 0, which is what keeps the denominator’s \(1/(\mathbf{n}\cdot\omega)\) from blowing up at the silhouette.

4.3 F: Fresnel

A dielectric reflects a few percent head-on and almost everything at grazing incidence (look along a table top toward a window). Schlick’s approximation captures it with one number per material, the reflectance at normal incidence \(F_0\):

\[ F(\omega_i, \mathbf{h}) \;=\; F_0 + (1 - F_0)\,\big(1 - \mathbf{v}\cdot\mathbf{h}\big)^5 . \]
material\(F_0\) (R, G, B)type
water0.02dielectric
plastic, glass, skin, wood, stone0.02 to 0.05 (0.04 is the universal default)dielectric
diamond0.17dielectric
iron0.56, 0.57, 0.58metal
aluminum0.91, 0.92, 0.92metal
copper0.95, 0.64, 0.54metal
gold1.00, 0.71, 0.29metal
silver0.95, 0.93, 0.88metal

The table is the physics behind the metallic slider. Every dielectric has nearly the same gray \(F_0\) of about 0.04 and gets its color from light that enters the surface, scatters, and leaves diffusely. A metal has a large, colored \(F_0\) and no diffuse term at all, because the conduction electrons absorb whatever is not reflected. Where the numbers come from is Section 5.

Worked example (a full evaluation) Put the normal along \(z\), the light at \(30^\circ\) on one side and the eye at \(30^\circ\) on the other, a plastic (\(F_0 = 0.04\)) with \(\alpha = 0.3\).
  1. \(\omega_i = (-0.500, 0, 0.866)\), \(\omega_o = (0.500, 0, 0.866)\), so \(\mathbf{n}\cdot\omega_i = \mathbf{n}\cdot\omega_o = 0.866\).
  2. \(\mathbf{h} = \text{normalize}(\omega_i + \omega_o) = (0, 0, 1) = \mathbf{n}\): the eye sits exactly in the mirror direction, so \(\mathbf{n}\cdot\mathbf{h} = 1\) and \(\omega_o\cdot\mathbf{h} = 0.866\).
  3. \(D = \alpha^2/\pi = 0.09/\pi = \) 3.537 (the peak of the \(\alpha = 0.3\) curve).
  4. \(G_1(\omega_i) = 2(0.866)/(0.866 + \sqrt{0.09 + 0.91\cdot0.750}) = 0.9926\); the same for \(\omega_o\); \(G = 0.9926^2 = \) 0.985.
  5. \(F = 0.04 + 0.96\,(1 - 0.866)^5 = 0.04 + 0.96\times4.3\times10^{-5} = \) 0.0400: at this angle Fresnel adds nothing.
  6. \(f_r^{\text{spec}} = \dfrac{3.537 \times 0.985 \times 0.040}{4 \times 0.866 \times 0.866} = \dfrac{0.1394}{3.0} = \) 0.0465.
Compare the Lambertian term of a mid-gray plastic, \(0.6/\pi = 0.191\): at the mirror direction the highlight adds about a quarter of the diffuse value. Now move the light out to \(45^\circ\), leaving the eye at \(30^\circ\). Then \(\mathbf{h} = (-0.131, 0, 0.991)\), tilted \(7.5^\circ\) from the normal; \(D\) drops to 2.574, \(G\) to 0.971, \(F\) rises slightly to 0.0404, and \(f_r^{\text{spec}} = 0.0412\). And at the original geometry with a rougher surface, \(\alpha = 0.6\): \(D = 0.884\), \(G = 0.944\), \(f_r^{\text{spec}} = 0.0111\), a quarter of the smooth value. The highlight got dimmer as it got wider, with no separate brightness knob to set: that is energy conservation doing the artist’s bookkeeping.
Hands-on The three factors are ten lines of code. Run each from a terminal with node -e (paste the whole snippet as the argument), or in the browser console.
  1. Evaluate the BRDF at a geometry the text did not: light at \(20^\circ\) on one side, eye at \(50^\circ\) on the other, \(\alpha = 0.3\), plastic.
    const PI=Math.PI;const D=(nh,a)=>a*a/(PI*((nh*nh*(a*a-1)+1)**2));
    const G1=(nx,a)=>2*nx/(nx+Math.sqrt(a*a+(1-a*a)*nx*nx));const F=(F0,vh)=>F0+(1-F0)*(1-vh)**5;
    const n=[0,0,1];const dir=(deg)=>[Math.sin(deg*PI/180),0,Math.cos(deg*PI/180)];
    const dot=(a,b)=>a[0]*b[0]+a[1]*b[1]+a[2]*b[2];const norm=(v)=>{const L=Math.hypot(...v);return v.map(x=>x/L);};
    const l=dir(-20),v=dir(50),h=norm([l[0]+v[0],l[1]+v[1],l[2]+v[2]]);const a=0.3;
    const f=D(dot(n,h),a)*G1(dot(n,l),a)*G1(dot(n,v),a)*F(0.04,dot(v,h))/(4*dot(n,l)*dot(n,v));
    console.log('h angle',(Math.acos(dot(n,h))*180/PI).toFixed(1),'D',D(dot(n,h),a).toFixed(4),'f',f.toFixed(5));
    Expected output: h angle 15.0 D 1.2571 f 0.02022. The half-vector sits halfway between the two directions, \(15^\circ\) off the normal, and the highlight is less than half the mirror-configuration value 0.0465.
  2. Check the Phong energy table by numerical integration instead of the closed form:
    let s=0;const N=2000;for(let i=0;i<N;i++){const th=(i+0.5)/N*Math.PI/2;
      s+=Math.cos(th)**32*Math.cos(th)*Math.sin(th)*(Math.PI/2/N);}
    console.log((2*Math.PI*s).toFixed(4),'vs',(2*Math.PI/34).toFixed(4));
    Expected: 0.1848 vs 0.1848. Change 32 to 4 and the integral exceeds 1.
  3. In the BRDF-lobes demo, set roughness to 0.3 and switch the model between Phong and GGX: the GGX lobe keeps the skirt the figure above shows, and the teapot’s highlight gains a halo.

5 · Fresnel exactly: dielectrics and conductors

Schlick’s curve is a fit. The quantity it fits is given exactly by Fresnel’s equations, which follow from the wave theory of light at a boundary between two media, and knowing them explains the \(F_0\) table, tells where the fit is wrong, and separates the two kinds of material by physics rather than by slider.

Fresnel’s equations Light arriving at angle \(\theta_i\) from a medium of refractive index \(n_1\) onto one of index \(n_2\) refracts at \(\theta_t\) with \(n_1\sin\theta_i = n_2\sin\theta_t\) (Snell, as in the ray-tracing chapter) and reflects a fraction that depends on the polarization: \[ \begin{gathered} R_s = \left(\frac{n_1\cos\theta_i - n_2\cos\theta_t}{n_1\cos\theta_i + n_2\cos\theta_t}\right)^{2}, \qquad R_p = \left(\frac{n_1\cos\theta_t - n_2\cos\theta_i}{n_1\cos\theta_t + n_2\cos\theta_i}\right)^{2}, \\[4pt] F = \tfrac12 (R_s + R_p) \end{gathered} \] for unpolarized light. At normal incidence both reduce to \(F_0 = \big((n_1 - n_2)/(n_1 + n_2)\big)^2\). A conductor has a complex index \(n + ik\), whose imaginary part \(k\) is absorption; the same formulas apply with complex arithmetic, and at normal incidence \(F_0 = \big((n-1)^2 + k^2\big)/\big((n+1)^2 + k^2\big)\).
Worked example (glass at 60°, exactly) Air to glass, \(n_2 = 1.5\): \(F_0 = (0.5/2.5)^2 = 0.04\), the table’s default. At \(\theta_i = 60^\circ\): \(\sin\theta_t = 0.866/1.5 = 0.577\), \(\cos\theta_t = 0.8165\); \(R_s = \big((0.5 - 1.5\cdot0.8165)/(0.5 + 1.5\cdot0.8165)\big)^2 = (0.7247/1.7247)^2 = 0.1766\); \(R_p = \big((0.8165 - 0.75)/(0.8165 + 0.75)\big)^2 = (0.0665/1.5665)^2 = 0.0018\); \(F = 0.0892\). Schlick gives \(0.04 + 0.96\,(0.5)^5 = 0.0700\), 21 % low. The two polarizations differ by a factor of a hundred here: at Brewster’s angle \(\arctan 1.5 = 56.3^\circ\), \(R_p\) is exactly zero, which is why polarized sunglasses remove the glare off water and glass near that angle. The table below is the whole curve.
\(\theta_i\)0°30°45°56.3°60°75°85°
\(R_s\)0.0400.0580.0920.1480.1770.3990.732
\(R_p\)0.0400.0250.0090.0000.0020.1070.493
exact \(F\)0.0400.0420.0500.0740.0890.2530.613
Schlick0.0400.0400.0420.0570.0700.2550.649
Left: reflectance of glass against angle of incidence, the exact average in blue, Schlick in dashed red, and the two polarizations in gray with the p curve touching zero at Brewster's angle 56.3 degrees. Right: gold's exact reflectance per color channel, red near 0.97 throughout, green near 0.80 rising at grazing, blue from 0.32 rising to 1, each with a dashed Schlick curve beside it.
Left: glass. Schlick underestimates the middle angles and slightly overestimates the last few degrees; the polarizations split widely, and the average is what an unpolarized renderer uses. Right: gold, from its measured complex index \(n = (0.143, 0.374, 1.442)\), \(k = (3.983, 2.386, 1.603)\) at red, green and blue wavelengths. \(F_0 = (0.967, 0.803, 0.324)\), close to the table’s \((1.00, 0.71, 0.29)\); the blue channel’s rise toward grazing is why gold looks whiter at the rim.
Worked example (gold at normal incidence) Red channel: \(n = 0.143\), \(k = 3.983\): \(F_0 = \big((0.143-1)^2 + 3.983^2\big)/\big((0.143+1)^2 + 3.983^2\big) = (0.734 + 15.86)/(1.306 + 15.86) = 0.967\). Blue: \(n = 1.442\), \(k = 1.603\): \((0.195 + 2.570)/(5.963 + 2.570) = 0.324\). A metal’s color is set by how its absorption varies with wavelength, and the reflected light is tinted because \(F_0\) is; a dielectric’s \(F_0\) hardly varies with wavelength (glass’s index changes by about 1 % across the visible range), so its reflection is white and its color must come from what happens under the surface.

So the two material recipes of Section 7 are not a convention. A dielectric has real \(n\) near 1.5, \(F_0 \approx 0.04\), and transmits what it does not reflect into a body that scatters it back diffusely. A conductor has large \(k\), colored \(F_0\) of 0.5 to 1, and absorbs within a few nanometers what it does not reflect, so it has no diffuse term. Everything in between (a dusty chrome, a metallic paint with flakes in a clear binder) is a mixture of the two kinds over the area of a pixel.

6 · Energy: the furnace test and multiple scattering

The energy law of Section 3 is a promise; the furnace test checks it. Put a surface with \(F = 1\) (a perfect mirror facet, nothing absorbed) inside a uniformly lit white sphere, a furnace. A model that conserves energy renders it invisible: it reflects everything, so it is exactly as bright as its surroundings. The directional albedo \(E(\omega_o) = \int f_r (\mathbf{n}\cdot\omega_i)\,d\omega_i\) is that brightness, and the figure below computes it for the GGX model by drawing 20,000 directions per point from the distribution of Section 8.

Directional albedo of GGX with Smith masking against roughness from 0.1 to 1, for four viewing angles and the hemisphere average: all start near 1 at low roughness and fall, to about 0.3 at normal incidence and 0.54 at grazing for alpha equal to 1.
The furnace test for GGX with Smith \(G\) and \(F = 1\). At \(\alpha = 0.1\) the model returns 99 % of the light; at \(\alpha = 0.5\), 68 % head-on; at \(\alpha = 1\), 30 % head-on and 38 % on average over the hemisphere. The missing energy is not absorbed by any physics in the model. It is light that bounced off one facet onto another, which the single-scattering model discards because \(G\) counts a shadowed facet as lost.
Worked example (how much a rough surface loses) At \(\alpha = 1\), \(\mathbf{n}\cdot\omega_o = 1\), the albedo is 0.302: a perfectly reflective, very rough surface renders at 30 % brightness, 70 % darker than it should. The average over the hemisphere is 0.379, 62 % lost. At \(\alpha = 0.5\) the average is 0.691, 31 % lost. Rough metals rendered with the plain model are visibly too dark, and the darkening grows with roughness, so a roughness texture also becomes a darkness texture, which no artist asked for.

The fix is multiple-scattering compensation (Kulla and Conty, 2017; Turquin, 2019). The energy lost from a single bounce is \(1 - E(\omega_o)\); a second lobe, shaped so that it integrates to exactly that missing fraction and weighted by the average Fresnel reflectance (a metal returns almost all of the inter-facet light, a dielectric only a few percent of it), is added to the BRDF, and the sum passes the furnace test to within a percent. The tables of \(E\) that the compensation needs are precomputed once per roughness and viewing angle; the figure above is that table’s first row. The same test catches a second, older sin: the diffuse and specular terms of a dielectric must share the energy, so the diffuse lobe of a physically careful model is scaled by \(1 - F\), or by \(1 - E_{\text{spec}}\), rather than added at full strength.

7 · Metallic and roughness, and the principled model

Every engine exposes the model above through two artist sliders on top of a base color:

\[ f_r \;=\; (1 - m)\,\frac{\text{base}}{\pi} \;+\; f_r^{\text{spec}}\big(F_0 = (1-m)\,0.04 + m\,\text{base}\big). \]
A five by five grid of shaded spheres, roughness increasing left to right from 0.1 to 0.9 and metallic increasing top to bottom from 0 to 1, lit by one directional light and a two-tone sky and ground environment.
The model of this chapter, rendered by a forty-line ray marcher in the figure generator: one directional light plus a two-tone environment (bright sky above the horizon, dark ground below), Lambert diffuse, GGX \(D\), Smith \(G\), Schlick \(F\), gamma 2.2. Across: roughness 0.1, 0.3, 0.5, 0.7, 0.9. Down: metallic 0, 0.25, 0.5, 0.75, 1. The dielectric row keeps its base color in the shadow side, because the diffuse term is there; the metal row goes dark except where it reflects the light and the sky, and those reflections are tinted by the base color, because \(F_0\) is. The horizon line visible on the plastic spheres is real: Fresnel makes even plastic a weak mirror.

These are the sliders in Unity’s Standard Shader, and the same parameterization is what glTF and every modern renderer exchange. That agreement is the practical result of PBR: a material authored once looks the same in every engine, under any lighting, because the numbers mean physical things rather than tuning constants for one scene.

Pitfall Two mistakes that survive in shipped shaders, with their size.

7.1 The principled model

Two sliders are not enough for every material, and the extension that the film industry standardized is Disney’s principled BRDF (Burley, 2012), built from the MERL measurements of Section 3 under the rule that every parameter is a number between 0 and 1 with a visible meaning. Its parameters, in the order an artist meets them:

parameterwhat it controlsphysics
baseColorthe surface colordiffuse albedo for dielectrics, \(F_0\) for metals
metallicdielectric to conductorthe blend of Section 7
roughnesshighlight width\(\alpha = \text{roughness}^2\) in GGX, for both lobes
specular, specularTintstrength and color of the dielectric reflection\(F_0\) from 0 to 0.08, optionally tinted toward the base color
anisotropicstretched highlightstwo roughnesses along the tangent and bitangent (brushed metal, hair)
sheen, sheenTintsoft glow at grazing anglesa retro-reflective lobe for cloth
clearcoat, clearcoatGlossa second, thin glossy layera fixed-index (1.5) dielectric lobe over the base: car paint, lacquer
subsurfacelight that enters and leaves nearbya blend toward a subsurface-like diffuse lobe (Section 10)

glTF’s material model is a subset of this table (base color, metallic, roughness, plus extensions for clear coat, sheen and transmission), and Blender’s Principled BSDF is the whole of it.

See it live BRDF lobes: the course’s Cornell scene with four material identities (a gold metal teapot, an aluminum metal box, a pastel plastic bunny, a glossy dielectric box) all wearing one plotted BRDF. Drop roughness and every highlight tightens toward a mirror while the inset lobe needles; switch Phong to GGX to compare the tails. The two mappings from roughness to lobe width are not calibrated to each other; the demo shows shape, not units.

8 · Sampling the BRDF

A path tracer (the ray-tracing chapter) estimates the hemisphere integral by drawing random directions and averaging \(f_r L_i (\mathbf{n}\cdot\omega_i)/p(\omega_i)\). Uniform directions waste nearly every sample on a glossy surface, whose \(f_r\) is negligible except near the mirror direction. The remedy is to draw directions from the BRDF’s own shape, and GGX was chosen partly because its \(D\) can be inverted in closed form.

Sampling GGX Draw a facet normal \(\mathbf{h}\) from \(D(\mathbf{h})(\mathbf{n}\cdot\mathbf{h})\), which is a probability density over the hemisphere, with two uniform numbers \(u_1, u_2 \in [0,1)\): \[ \cos\theta_h = \sqrt{\frac{1 - u_1}{1 + (\alpha^2 - 1)\,u_1}}, \qquad \phi_h = 2\pi u_2, \] then reflect the view direction about it, \(\omega_i = 2(\omega_o\cdot\mathbf{h})\,\mathbf{h} - \omega_o\). The density of the resulting direction is \(p(\omega_i) = D(\mathbf{h})(\mathbf{n}\cdot\mathbf{h}) / \big(4\,(\omega_o\cdot\mathbf{h})\big)\), and the estimator’s weight simplifies: \[ \frac{f_r\,(\mathbf{n}\cdot\omega_i)}{p(\omega_i)} \;=\; \frac{F\,G\,(\omega_o\cdot\mathbf{h})}{(\mathbf{n}\cdot\omega_o)(\mathbf{n}\cdot\mathbf{h})}. \] \(D\) cancels: the sampler already accounted for it.
Worked example (one sample) \(\alpha = 0.3\), the eye at \(30^\circ\) from the normal, \(\omega_o = (0.5, 0, 0.866)\), random numbers \(u = (0.3, 0.25)\). \(\cos\theta_h = \sqrt{0.7/(1 - 0.91\cdot0.3)} = \sqrt{0.7/0.727} = 0.9813\), \(\theta_h = 11.1^\circ\), \(\phi_h = 90^\circ\), so \(\mathbf{h} = (0, 0.193, 0.981)\). Then \(\omega_o\cdot\mathbf{h} = 0.850\) and \(\omega_i = 2(0.850)\,\mathbf{h} - \omega_o = (-0.500, 0.328, 0.802)\), a direction \(36.7^\circ\) from the normal on the far side, sideways by the facet’s tilt. \(D(\mathbf{h}) = 1.869\), \(p(\mathbf{h}) = 1.834\), \(p(\omega_i) = 1.834/(4\cdot0.850) = 0.540\). The BRDF there is \(f_r = 0.0264\) (with \(G = 0.981\), \(F = 0.040\)), and the weight is \(0.0264 \times 0.802 / 0.540 = 0.0393\), the same as the short form \(0.040\times0.981\times0.850/(0.866\times0.981) = 0.0393\). Averaged over many such samples the weight converges to the directional albedo of Section 6 times the average Fresnel, which is what the estimator is for.
A histogram of 20,000 sampled facet angles for alpha 0.3 as blue bars, peaking near 10 degrees and tailing off past 60, with the predicted density drawn as a red curve on top and matching it; the worked draw at 11.1 degrees is marked.
Twenty thousand draws of \(\theta_h\) from the formula against the density \(D(\mathbf{h})\cos\theta_h\cdot2\pi\sin\theta_h\) they should follow. The match is the proof that the inversion is right; the tail past \(45^\circ\) is where GGX differs from a Gaussian lobe, and the sampler visits it in proportion.

Sampling \(D\) still wastes the draws that reflect below the horizon (\(\mathbf{n}\cdot\omega_i < 0\)) and the ones that a facet would mask; sampling the visible normals instead (Heitz, 2018) removes both and is what production path tracers use. Diffuse lobes are sampled with cosine-weighted directions, as in the ray-tracing chapter, and a material with both lobes picks one per sample in proportion to its albedo. The general principle, importance sampling, is the same everywhere: draw from something shaped like the integrand, and divide by its density.

9 · A whole sky at once: image-based lighting and the split sum

Real-time engines cannot integrate over the hemisphere per pixel, but their light is often a whole environment: a captured panorama, or the sky and ground of the sphere grid above. Image-based lighting treats every texel of that panorama as a distant light. For the diffuse term the integral is a blur of the environment by the cosine lobe, precomputed once into a small map indexed by the normal. For the specular term the integrand depends on the view direction and the roughness as well, and the trick that made it affordable is the split sum (Karis, 2013):

Definition (the split-sum approximation) \[ \int_\Omega f_r\, L_i\,(\mathbf{n}\cdot\omega_i)\,d\omega_i \;\approx\; \underbrace{\Big(\int_\Omega D\text{-weighted } L_i\, d\omega_i\Big)}_{\text{prefiltered environment}} \cdot \underbrace{\Big(\int_\Omega f_r\,(\mathbf{n}\cdot\omega_i)\,d\omega_i\Big)}_{F_0\,A + B}. \] The first factor is the environment blurred by the GGX lobe at each roughness, stored as the mip levels of a cube map and looked up along the reflected direction. The second is the directional albedo of Section 6 with Schlick’s Fresnel factored out, \(E = F_0 A(\mathbf{n}\cdot\omega_o, \alpha) + B(\mathbf{n}\cdot\omega_o, \alpha)\), stored as a two-channel \(32\times32\) texture that every material shares.
A 32 by 32 texture with the scale term A in red rising toward the upper right and the bias term B in green concentrated at the lower left where the view is grazing and the surface smooth.
The BRDF integration table, computed here by importance sampling with 256 draws per texel: horizontal axis \(\mathbf{n}\cdot\omega_o\) from grazing (left) to head-on (right), vertical axis roughness from smooth (bottom) to rough (top); red is \(A\), green is \(B\). Every real-time engine carries this same picture.
Worked example (one table entry) At \(\mathbf{n}\cdot\omega_o = 0.5\) (the surface seen at \(60^\circ\)) and \(\alpha = 0.5\), 20,000 samples give \(A = 0.679\), \(B = 0.010\). For plastic, \(E = 0.04\times0.679 + 0.010 = 0.037\): the environment reflection is 3.7 % of the prefiltered radiance. For gold with \(F_0 = (1.00, 0.71, 0.29)\), \(E = (0.689, 0.492, 0.207)\): the sky reflects strongly and tinted. \(A + B = 0.689\) is the furnace albedo of Section 6 at this angle and roughness (\(E = 0.68\) for \(\mathbf{n}\cdot\omega_o = 0.7\), \(0.71\) for \(0.4\)), and the split has simply pulled \(F_0\) out of the integral.

What the approximation drops is the correlation between the environment’s brightness and the BRDF’s shape inside the integral: a bright sun just outside the lobe is treated as if the lobe were centered on it. At high roughness and grazing angles the error is visible as a slightly wrong reflection shape; it is the price of a two-texture-lookup specular term, and the reason the sphere grid of Section 7 could be rendered by a forty-line marcher with a blurred two-tone sky rather than by a path tracer.

10 · Beyond opaque surfaces

The rendering equation as written integrates over the hemisphere above the surface. Light also goes in.

Transmission. For glass, water and gems the BRDF gets a partner, the BTDF, over the hemisphere below, and the two together (a BSDF) share the energy through Fresnel: a fraction \(F\) reflects, and \(1 - F\) refracts along the direction Snell gives, as the ray-tracing chapter’s glass sphere does. A rough glass uses the same microfacet machinery with refraction through each facet (Walter and others, 2007). Inside a colored medium the light is absorbed along its path by the Beer–Lambert law, \(T = e^{-\sigma_a d}\), the same exponential as the transmittance of the learned-scenes chapter.

Worked example (colored glass) A glass with absorption \(\sigma_a = (0.5, 2.0, 4.0)\) per centimeter in red, green and blue. Through 1 cm the transmitted fractions are \((e^{-0.5}, e^{-2}, e^{-4}) = (0.607, 0.135, 0.018)\): a red tint. Through 3 cm, \((0.223, 0.002, 0.000)\): a deep red that has lost all its blue. Color in a transmissive medium depends on the path length, which is why a glass bottle is darker at its thick base and why the same dye is pink in a thin layer and red in a thick one.

Subsurface scattering. Skin, marble, wax, milk and leaves are dielectrics whose “diffuse” term is not local: light enters at one point, scatters many times in the body, and leaves at another point some millimeters away. The Lambertian term of Section 3 is the limit in which that distance is zero. A subsurface model replaces \(f_r\) by a function of two points as well as two directions (a BSSRDF), and in practice by a diffusion profile: the exiting light is the entering irradiance blurred over the surface with a kernel whose width is the mean free path in the material. Skin’s kernel is about a millimeter and reddish, because red light travels farthest in tissue; the soft, warm look of a backlit ear is that blur. Real-time engines approximate the blur in screen space; path tracers random-walk inside the volume. The principled model’s subsurface slider blends toward this behavior.

Participating media. Fog, smoke and clouds scatter light everywhere along a ray rather than at a surface, and the rendering equation becomes the volume rendering equation, with a density, an absorption and a scattering phase function at every point. That equation is the one the learned-scenes chapter integrates along a ray, with the scattering term replaced by a learned color; a NeRF is a participating medium that has learned to look like a solid.

11 · Solving the equation: path tracing and real time

The rendering equation is an integral equation with the unknown on both sides, so it is solved by iteration or by sampling. Path tracing estimates the integral at a pixel by Monte Carlo: shoot a ray, at the hit point pick a random \(\omega_i\) (from the BRDF, as in Section 8), weight the bounce by \(f_r\,(\mathbf{n}\cdot\omega_i)\) divided by the probability of having picked that direction, and recurse until the path reaches a light or is terminated. Average many paths per pixel and the noise falls as \(1/\sqrt{N}\). Every bounce is a sample of the same integral, so indirect light, soft shadows, color bleeding and caustics come out with no special cases; the price is hundreds of samples per pixel. The ray-tracing chapter builds the algorithm from its parts and renders a Cornell box with it.

Real-time engines keep the local term (one BRDF evaluation per light, exactly the worked example of Section 4) and approximate the rest: the split sum of Section 9 for the sky, screen-space or ray-traced reflections for the mirror term, and a precomputed ambient-occlusion or irradiance volume for the diffuse bounce. Since 2018 hardware ray tracing has moved parts of that list back toward honest sampling, denoised, at a few samples per pixel. Both routes evaluate the same \(f_r\); they differ in how much of the hemisphere they can afford to look at.

Papers J. Kajiya, “The Rendering Equation,” SIGGRAPH 1986. R. Cook and K. Torrance, “A Reflectance Model for Computer Graphics,” ACM Transactions on Graphics 1(1), 1982. B. Walter, S. Marschner, H. Li and K. Torrance, “Microfacet Models for Refraction through Rough Surfaces,” Eurographics Symposium on Rendering 2007 (the GGX distribution and its sampling). C. Schlick, “An Inexpensive BRDF Model for Physically-based Rendering,” Computer Graphics Forum 13(3), 1994. W. Matusik, H. Pfister, M. Brand and L. McMillan, “A Data-Driven Reflectance Model,” SIGGRAPH 2003 (the MERL database). B. Burley, “Physically Based Shading at Disney,” SIGGRAPH 2012 course notes. B. Karis, “Real Shading in Unreal Engine 4,” SIGGRAPH 2013 course notes (the split sum). C. Kulla and A. Conty, “Revisiting Physically Based Shading at Imageworks,” SIGGRAPH 2017 course notes (multiple-scattering compensation). E. Heitz, “Sampling the GGX Distribution of Visible Normals,” Journal of Computer Graphics Techniques 7(4), 2018.

12 · Exercises

Exercise 1 (the cosine factor) Redo the three-light example with the same lights but a darker surface, \(\rho = 0.3\). Then move light 1 to \(70^\circ\). Which change reduced \(L_o\) more?
Solution Halving \(\rho\) halves everything: \(L_o = 0.230\). Moving light 1 to \(70^\circ\) (with \(\rho = 0.6\) again) changes its cosine from 0.940 to 0.342, its term from 0.359 to 0.131, and \(L_o\) from 0.460 to 0.232, about the same loss. A grazing angle costs as much as a surface half as reflective.
Exercise 2 (D is a distribution) Evaluate GGX \(D\) at \(\mathbf{n}\cdot\mathbf{h} = 1\) for \(\alpha = 0.1\) and \(\alpha = 1\). Explain why the second is \(1/\pi\).
Solution At \(\mathbf{n}\cdot\mathbf{h} = 1\) the bracket is \((\alpha^2 - 1) + 1 = \alpha^2\), so \(D = \alpha^2/(\pi\alpha^4) = 1/(\pi\alpha^2)\): 31.8 for \(\alpha = 0.1\) and \(1/\pi = 0.318\) for \(\alpha = 1\). With \(\alpha = 1\) the bracket is 1 for every \(\mathbf{h}\), so \(D\) is the constant \(1/\pi\): all facet directions equally likely, and the constant that integrates to 1 against the cosine over the hemisphere is \(1/\pi\), the same constant as the Lambertian BRDF.
Exercise 3 (Fresnel at the rim) For plastic (\(F_0 = 0.04\)), at what angle between \(\mathbf{v}\) and \(\mathbf{h}\) does Schlick’s \(F\) reach 0.5? Compare with the exact table of Section 5.
Solution \(0.04 + 0.96\,(1 - c)^5 = 0.5\) gives \((1-c)^5 = 0.479\), \(1 - c = 0.863\), \(c = 0.137\), an angle of \(82^\circ\). The exact curve reaches 0.5 a little later, between \(75^\circ\) (0.253) and \(85^\circ\) (0.613), near \(83^\circ\). Plastic is half a mirror only within about seven degrees of grazing, which is why the reflection of a window on a table top appears only when you look along the table.
Exercise 4 (Brewster) Water has \(n = 1.33\). Compute \(F_0\), Brewster’s angle, and \(R_s\) at that angle.
Solution \(F_0 = (0.33/2.33)^2 = 0.020\), the table’s value. Brewster: \(\arctan 1.33 = 53.1^\circ\), where \(\theta_i + \theta_t = 90^\circ\) so \(\cos\theta_t = \sin\theta_i = 0.800\). \(R_s = \big((0.600 - 1.33\cdot0.800)/(0.600 + 1.33\cdot0.800)\big)^2 = (0.464/1.664)^2 = 0.078\), and \(R_p = 0\): the reflection off a lake at \(53^\circ\) is entirely s-polarized, which a polarizing filter turned the right way removes completely.
Exercise 5 (metallic in between) A slider value of metallic 0.5 is common in beginners’ materials. Using the blend formula of Section 7, say what such a surface is physically, and why real materials are almost always at 0 or 1.
Solution It is half a dielectric and half a metal: a diffuse term at half strength under a specular whose \(F_0\) is the average of 0.04 and the base color. No homogeneous material behaves so, because Section 5 divides materials by whether \(k\) is negligible or large; the value is meaningful only as an average over a surface that is partly metal and partly not (dust on chrome, paint over steel), which is how texture artists use it. A clean material is 0 or 1.
Exercise 6 (the furnace) From the figure of Section 6, a rough gold (\(\alpha = 0.8\), \(F_0 \approx 0.9\)) seen head-on under a uniform sky of radiance 1. What does the single-scattering model render, and what should it render?
Solution \(E(1, 0.8) = 0.421\), so the model returns \(0.9\times0.42 \approx 0.38\) of the sky’s radiance. A real gold surface returns nearly all the light that is not absorbed, and since each inter-facet bounce loses only 10 %, the true value is close to \(0.9\) minus a small multiple-bounce absorption, about 0.85. The render is less than half as bright as it should be; compensation adds the missing 0.47.
Exercise 7 (a sample by hand) Repeat the sampling example with \(u = (0.9, 0.5)\) and \(\alpha = 0.3\). Where does the facet point, and where does the reflected direction go?
Solution \(\cos\theta_h = \sqrt{0.1/(1 - 0.91\cdot0.9)} = \sqrt{0.1/0.181} = 0.743\), \(\theta_h = 42^\circ\), \(\phi_h = 180^\circ\): a facet tilted far over, toward the \(-x\) side, \(\mathbf{h} = (-0.669, 0, 0.743)\). \(\omega_o\cdot\mathbf{h} = -0.335 + 0.644 = 0.309\), and \(\omega_i = 2(0.309)\mathbf{h} - \omega_o = (-0.913, 0, -0.407)\): below the horizon. This sample is wasted (weight 0), which is the case the visible-normal sampler avoids; at \(\alpha = 0.3\) about a tenth of draws at this view angle end this way.
Exercise 8 (the split sum, with code) Write a Monte Carlo estimate of the split-sum entry \((A, B)\) at \(\mathbf{n}\cdot\omega_o = 1\), \(\alpha = 0.1\), using the sampling formula of Section 8 and the weight \(G\,(\omega_o\cdot\mathbf{h})/((\mathbf{n}\cdot\mathbf{h})(\mathbf{n}\cdot\omega_o))\) split into \((1 - (1 - \omega_o\cdot\mathbf{h})^5)\) and \((1 - \omega_o\cdot\mathbf{h})^5\) parts. What should \(A + B\) be?
Solution Head-on and nearly smooth, every sampled facet points nearly along the normal, \(\omega_o\cdot\mathbf{h} \approx 1\), the Fresnel factor \((1 - \omega_o\cdot\mathbf{h})^5 \approx 0\), and \(G \approx 1\): \(A \approx 0.99\), \(B \approx 0\), and \(A + B\) equals the furnace albedo \(E(1, 0.1) = 0.988\) from Section 6. The estimate converges to it within a percent at a few thousand samples; a run of the generator’s code with these parameters is the check.
Exercise 9 (transmission) A stained-glass window is 4 mm thick with \(\sigma_a = (0.5, 2.0, 4.0)\) per cm as in Section 10. What color does white light become, and how thick must the glass be for the green channel to fall to 10 %?
Solution \(d = 0.4\) cm: \((e^{-0.2}, e^{-0.8}, e^{-1.6}) = (0.819, 0.449, 0.202)\), an orange-red. Green at 10 %: \(e^{-2d} = 0.1\), \(d = \ln 10 / 2 = 1.15\) cm. Beer–Lambert is exponential, so each doubling of thickness squares the transmitted fraction.