Light Transport, the Right Way

The familiar rendering equation is the basis of pathtracing, but it appears to lack a certain symmetry: the cosine term is only in one direction, and it is not clear how one would adapt it for bidirectional pathtracing.

The area form of the light transport equation is better, but the first point is privileged in the notation, and gives an output in radiance, which isn't the final radiometric quantity. To convert it, one needs to use the measurement equation, which mixes sample weights, importance, and reconstruction all together. These equations are less well known, and the measurement equation in particular is so rarely found that most graphics professionals don't even know it's supposed to exist.

In short, everything is all mixed up and confused. Putting it all together might be a lot to take in, but it would be all in one place and treated consistently!


The Fix

To fix this mess, you can take the area form of the light transport equation, substitute it into the measurement equation, converting the angular integration into an area integration. It turns out this magically fixes all the notational problems and makes everything intuitive.

Hence, I propose the following single equation that unifies everything[1]. Please don't be scared, even though it looks complex. It's actually extremely simple and more intuitive than any of the individual equations separately. I'll explain how, and give complete examples.

Here is the equation:

\begin{align*} \definecolor{colorbrdf}{RGB}{255,128,128} \definecolor{colorgeom}{RGB}{128,192,255} \definecolor{colorbrace}{RGB}{255,255,128} \definecolor{colordefl}{RGB}{221,221,221} \newcommand{pt}{ \vec{p} } \newcommand{qt}{ \vec{q} } \newcommand{A}[1]{ A(\pt_{#1}) } \newcommand{Gterm}[2]{ { \color{colorgeom} G(\pt_{#1} \leftrightarrow \pt_{#2}) } } \newcommand{fr}[3]{ { \color{colorbrdf} f_r(\pt_{#1} \leftarrow \pt_{#2} \rightarrow \pt_{#3}) } } \newcommand{cosdir}[2]{ \cos(\theta_{ \pt_{#1} \rightarrow \pt_{#2} }) } \newcommand{ub}[2]{ {\color{colorbrace} \underbrace{\color{colordefl} #1}_{#2} } } \Phi &= \sum_{n=1}^{\infty} \Phi_n\\ &= \sum_{n=1}^{\infty} \left[ \ub{ \int_{\A{0}} \int_{\A{1}} \cdots \int_{\A{n}} }{n+1} L_e( \pt_n \rightarrow \pt_{n-1} ) \left( \prod_{k=0}^{n-1} \Gterm{k}{k+1} \right) \left( \prod_{k=1}^{n-1} \fr{k-1}{k}{k+1} \right) \ub{ d\A{n} d\A{n-1} \cdots d\A{0} }{n+1} \right] \end{align*}

And here is the geometry for a given, arbitrary \(n\):

Mathematical diagram of quantities in surface-based light transport.

In case you're not familiar with it, \({\color{colorbrdf} f_r(\cdots)}\) is the bidirectional reflectance distribution function (BRDF). It is a property of the surface's material that describes how light reflects off of it. In more generality, we can consider all scattering (the BSDF), including light transmitted through the material.

\({\color{colorgeom} G(\cdots)}\) is a geometric coupling term, defined as:

\[ \Gterm{k}{k+1} := \frac{ | \cosdir{k}{k+1} | | \cosdir{k+1}{k} | }{ || \pt_{k+1} - \pt_k ||^2 } V(\pt_k \leftrightarrow \pt_{k+1}) \]

The term \(V(\cdots)\) is the visibility function, which is \(0\) if \(\pt_k\) and \(\pt_{k+1}\) can't see each other and \(1\) if they can. Let's assume it's always \(1\) for the rest of this page, since if it's ever \(0\), then the whole \(\Phi_n\) is also \(0\).

The equation basically says that the radiant power (\(\Phi\)) arriving on the leftmost surface is the sum of all the radiant power arriving along paths of different lengths (\(\Phi_1\), \(\Phi_2\), ...).

Then, to compute the radiant power \(\Phi_n\) arriving along all paths of length exactly \(n\), we integrate over the \(n+1\) surfaces involved in that path. What do we integrate? The product of:

  • The BRDF \({\color{colorbrdf} f_r(\cdots)}\) of all interior nodes.
  • The geometric coupling terms \({\color{colorgeom} G(\cdots)}\) on all spans.
  • The radiometric quantity in question, which can be either:
    • The radiance \(L_e(\cdots)\) emitted from a light.
    • Importance \(W_e(\cdots)\) emitted from a sensor.
    It takes the exact same place in the equation, because these are adjoint quantities (hey, symmetry!)

That's it. The power along a path is just the multiplied material and geometric terms, integrated over the surfaces involved.


Examples

Now, let's see how this can be used to derive some classic algorithms.


Simple Transport (\(\Phi_1\))


One-Bounce Pathtracing (\(\Phi_1 + \Phi_2\))


\(n\)-Bounce Pathtracing (\(\Phi_1 + \Phi_2 + \cdots + \Phi_{n+1}\))


\(n\)-Bounce Bidirectional Pathtracing (\(\Phi_1 + \Phi_2 + \cdots + \Phi_{n+1}\))


Notes