Fix illuminant for spectral reflectance data #294
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #293
Reflectance and illuminant spectral distributions are different and must be treated differently when converting to sRGB. The difference essentially stems from that emitted radiance with equal energy for all wavelengths is not considered to be white, while surfaces that reflects radiance equally for all wavelengths are.
More details
The D65 illuminant was chosen as the 'white illuminant' for the sRGB color space. Once integrated with the CIE color matching functions, the XYZ tristimulus value of this illuminant is
XYZ(0.9505, 1.0, 1.0888)
. This value therefore represents white in the sRGB color space, so by definitionXYZ(0.9505, 1.0, 1.0888)
is converted tosRGB(1.0, 1.0, 1.0)
.A white surface reflects all wavelengths equally, because the reflected radiance is then proportionally equal to the incoming radiance. In other words, the reflectance of a white surface as a function of wavelength is constant,
R(λ)=C
. Once integrated with the CIE color matching functions, the XYZ tristimulus values of this reflectance isXYZ(C, C, C)
. If we convert this to sRGB, which definesXYZ(0.9505, 1.0, 1.0888)
as white, this reflectance issRGB(1.2048·C, 0.9483·C, 0.9088·C)
≠ white.To correctly convert our white reflectance to the sRGB color space, we must account for the fact that the color space considers
XYZ(0.9505, 1.0, 1.0888)
to be white, which is done by multiplying the XYZ reflectance values with this white point before performing the conversion to sRGB:XYZ(0.9505·C, 1.0·C, 1.0888·C)
=>sRGB(C, C, C)
. This applies to all surfaces and not only white ones, but it's easier to illustrate with one.This PR uses the existing distinction between input illuminant and reflectance spectrums and applies the D65 white point to the integrated reflectance XYZ values before converting to sRGB.
I don't know of a scene where this makes much of a difference, because spectral reflectance distributions are only used for
eta
andk
in metals as far as I'm aware. The difference seems to be close to eliminated in the Fresnel function for conductives when botheta
andk
are modified in the same way:The color becomes a bit less greenish and more yellowish in places with lots of consecutive gold reflections, but it's barely noticeable. Gold is the only metal I've been able to see a slight difference with.
This is not the case if we specify
k=0
however, or if we for example specify the diffuse reflectance for a material as a gray reflectance distribution:Measured diffuse reflectance distributions exists and are useful for the spectral renderer, and this change should make sure that the result is the same when switching to
RGBSpectrum
.Edit:
Another option for a better approximation is to use the Bradford E to D65 chromatic adaption:
At that point it's probably best to just include the D65 data and use it to compute the proper reflectance integral though.