I have two somewhat related questions to ask:

  1. What is the most accurate way to get the colors of a spectrum, without having to go deep into physics and simulating the universe? ;) Right now, I'm using these color matching functions, and simply reading off the XYZ color of a particular wavelength and converting it to sRGB. I know sRGB can't represent most spectral colors, but let's ignore that.
  2. If I'm trying to make a color, say white, out of the spectral colors, how should I combine them? Should I add the color in XYZ space, or in RGB space, or is neither sufficient?

My plan is to experiment with spectral rendering, so it should be accurate enough to avoid biased renders. It'll most likely be on the GPU, and I need accuracy over speed.

  • $\begingroup$ What's best depends a lot on your application and what operations you want to do on these spectra. Could you edit your question to add some more about that? $\endgroup$
    – Dan Hulme
    Commented Jan 15, 2018 at 22:17
  • $\begingroup$ Just edited my question to add a bit of clarification. $\endgroup$ Commented Jan 15, 2018 at 22:40

1 Answer 1


Your way of calculating XYZ functions is probably the most efficient way to go about calculating accurate colors from a spectrum. It is standard practice afaik, for examples the books Physically Based Rendering (3rd) and Real-Time Rendering (3rd) both use this method.

You can add the colors in RGB space, but only if you convert from sRGB to linear RGB first. Otherwise you need to take into account, that sRGB sums will not lead to correct colors. The blogpost Adventures with Gamma-Correct Rendering by Naty Hoffman is a good read regarding this, topc:

Computing shading in sRGB space is like doing math in a world where 1+1=3.

This is the problem you have when adding colors in sRGB.

As to whether $XYZ$ can be summed, I think so. If we look at the definition of the coordinates (for $S$ is the spectral function and $x, y, z$ are the CIE functions):

$X = \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S(\lambda) x(\lambda) d\lambda$

Now two $X$ coordinates $X_1, X_2$ would have the same definition, only the spectrals are different ($S_1, S_2$).

Thus you have

$X_1 + X_2 = \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S_1(\lambda) x(\lambda) d\lambda + \frac{1}{\int_\lambda y(\lambda) d\lambda} \int_\lambda S_2(\lambda) x(\lambda) d\lambda\\ = \frac{1}{\int_\lambda y(\lambda) d\lambda} \left(\int_\lambda S_1(\lambda) x(\lambda) d\lambda + \int_\lambda S_2(\lambda) x(\lambda) d\lambda\right)\\ = \frac{1}{\int_\lambda y(\lambda) d\lambda}\int_\lambda S_1(\lambda) x(\lambda) + S_2(\lambda) x(\lambda) d\lambda \\ = \frac{1}{\int_\lambda y(\lambda) d\lambda}\int_\lambda (S_1(\lambda) + S_2(\lambda)) x(\lambda) d\lambda\\ =X$

The same holds for other coordinates.

Therefore, your best option is probably to sum your XYZ coordinates and convert them to sRGB space in the end.


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.