I'm reading section 5.2 of pbrt 3rd edition and came across the part where they explain the concept of RGB colors.

When we display an RGB color on a display, the spectrum that is actually displayed is basically determined by the weighted sum of three spectral response curves, one for each of red, green, and blue, as emitted by the display’s phosphors, LED or LCD elements, or plasma cells.

Then there's also this part.

enter image description here

So my understanding so far is this.

Just like a SPD can be expressed from the weighted sum of spectral matching curves $X(\lambda), Y(\lambda), Z(\lambda)$ as in $S(\lambda) = x_{\lambda}X(\lambda) + y_{\lambda}Y(\lambda) + z_{\lambda}Z(\lambda)$, it can also be expressed with the weighted sum of spectral response curves: $S(\lambda) = rR(\lambda) + gG(\lambda) + bB(\lambda)$

Is my understanding correct? If it's so, the point I don't get is why the book is using all sorts of mixed, confusing terms like "spectral matching curves", "spectral power distribution", and "spectral response curves". I would really appreciate if someone could clear my confusion. Thanks in advance.


1 Answer 1


The book distinguishes a spectral power distribution from a spectral response curve because they are not the same, they are adjoint.

The thing about adjoints that makes them a little tricky to wrap your head around is that they typically have the same representation in software, but keeping them distinct is extremely important in computer graphics.

Another example is that the the adjoint of a photon is a ray. A photon and a ray have almost the same data: an origin, a direction, and something that represents a spectrum; in the case of a photon, it "carries" spectral power, but in the case of a ray, it "carries" importance, which is a spectral response curve.

(Note that PBRT's ray implementation doesn't actually "carry" importance, rather this is calculated in the integrators. See beta in pbrt-v3's PathIntegrator, for example.)

In the real world, photons are emitted from light sources, and bounce around the universe until some of them hit your eye or a camera. In modern ray tracing, we reverse this, emitting importance from the camera and bouncing it around the scene until we hit a light source.

The term "adjoint" comes from linear algebra. If $A$ is a matrix and $x$ and $y$ are vectors, then $A^\dagger$ is the adjoint of $A$. It has the property that:

$$ x \cdot (Ay) = (A^\dagger x) \cdot y$$

Intuitively, the adjoint lets you shift a transformation from one side of a dot product to the other, just like how ray tracing shifts the interaction calculations from the "light" side to the "camera" side.

This is covered in Per Christiansen's 2003 paper, which is worth a read and a re-read.

Just as an aside, one more example that occasionally comes up is from differential geometry: the adjoint of a vector is a 1-form. If you implemented this in code, a 1-form has exactly the same representation as a vector: it's three floats. But it means something different.

  • $\begingroup$ Thank you for your insight! Do you think my understanding is correct though? The one with the equations. $\endgroup$
    – Peter
    Jun 6, 2021 at 15:19
  • $\begingroup$ Your understanding is correct for points inside the gamut of both RGB and XYZ. For points outside, some of those coefficients may go negative. Essentially, this is a change of basis in a vector space, and $\int f(\lambda) g(\lambda)\,d\lambda$ is the inner product of that space. $\endgroup$
    – Pseudonym
    Jun 7, 2021 at 11:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.