PBRT_V2 总结记录 <10> SPD, SampledSpectrum 和 RGBSpectrum

1. 什么是SPD

( 波长 对应 多少光 的 分布函数)

electromagnetic radiation:
flux, intensity, irradiance, and radiance. These radiometric quantities are each
described by their spectral power distribution (SPD)—a distribution function of wavelength
that describes the amount of light at each wavelength.

下面是 SPD的一个例子:

Spectral power distributions of a fluorescent light(荧光灯)

2.  怎么表示 SPD 

(RGBSpectrum 就直接用RGB来表示,SampledSpectrum 就用 采样点的方式来表示,那就是一段波长范围内,对应多少光)

we’ll introduce two representations that can be used for spectra in pbrt: RGBSpectrum,
which follows the typical computer graphics practice of representing SPDs with coefficients
representing red, green, and blue colors, and SampledSpectrum, which represents
the spectrum as a set of point samples over a range of wavelengths.

3.  XYZ COLOR

(这里主要 讲的是,SPD S(λ) 可以通过下面的公式,直接计算出 xλ, yλ, and zλ,这 xλ, yλ, and zλ,其实是可以表示人眼看到的颜色,也就是说,SPD 可以 通过下面的 公式,直接对应一个XYZ 颜色,但是需要注意的是,如果SPD要算术运算,不要直接用XYZ来代替SPD来计算,因为这样不准确,下面有提及,最好的方式是,SPD 自己经过算术运算,再转换为新的XYZ 

A remarkable property of the human visual system makes it possible to represent colors
for human perception with just three floating-point numbers.
The tristimulus theory
of color perception says that all visible SPDs can be accurately represented for human
observers with three values, xλ, yλ, and zλ.
Given an SPD S(λ), these values are computed
by integrating its product with the spectral matching curves X(λ), Y (λ), and Z(λ):

curves X(λ), Y (λ), and Z(λ):

These curves were determined by the Commission Internationale de l’E´ clairage (CIE)
standards body after a series of experiments with human test subjects and are graphed in
Figure 5.3. It is believed that these matching curves are generally similar to the responses
of the three types of color-sensitive cones in the human retina. Remarkably, SPDs with
substantially different distributions may have very similar xλ, yλ, and zλ values.To the
human observer, such SPDs actually appear the same visually. Pairs of such spectra are
called metamers.

This brings us to a subtle point about representations of spectral power distributions.
Most color spaces attempt to model colors that are visible to humans, and therefore use

only three coefficients, exploiting the tristimulus theory of color perception. Although
XYZ works well to represent a given SPD to be displayed for a human observer, it is not a
particularly good set of basis functions for spectral computation.
For example, although
XYZ values would work well to describe the perceived color of lemon skin or a fluorescent
light individually (recall Figure 5.1), the product of their respective XYZ values is likely to
give a noticeably different XYZ color than the XYZ value computed by multiplying more
accurate representations of their SPDs and then computing the XYZ value.

4. RGB COLOR

(XYZ 可以转换到RGB,但是需要注意的是,RGB的值是跟 显示器 相关的,因为不同的显示器的 R(λ), G(λ), and B(λ), 是不一样的,PBRT默认就使用了 高清电视的 R(λ), G(λ), and B(λ)值)

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.2 Figure 5.4 plots the red, green, and blue distributions emitted by a
LED display and a LCD display; note that they are remarkably different. Figure 5.5 in
turn shows the SPDs that result from displaying the RGB color (0.6, 0.3, 0.2) on those
displays. Not surprisingly, the resulting SPDs are quite different as well. This example
illustrates that using RGB values provided by the user to describe a particular color is
actually only meaningful given knowledge of the characteristics of the display they were
using when they selected the RGB values.

Given an (xλ, yλ, zλ) representation of an SPD, we can convert it to corresponding RGB
coefficients, given the choice of a particular set of SPDs that define red, green, and blue
for a display of interest. The conversion routines implemented in pbrt are based on a
standard set of these RGB spectra that has been defined for high-definition television.
Given the spectral response curves R(λ), G(λ), and B(λ), for a particular display,
RGB
coefficients can be computed by integrating the reponse curves with the SPD:

The integrals of the products of R(λ)X(λ) and so forth can be precomputed for given
response curves, making it possible to express the full conversion as a matrix:

Figure 5.4: Red, Green, and Blue Emission Curves for an LCD Display and a LED Display. The
top plot shows the curves for an LCD display and the bottom shows them for an LED. These two
displays have quite different emission profiles.

5. SampledSpectrum  类

static const int sampledLambdaStart = 400;
static const int sampledLambdaEnd = 700;
static const int nSpectralSamples = 30;

class SampledSpectrum : public CoefficientSpectrum<nSpectralSamples> {
public:
SampledSpectrum Public Methods
private:
SampledSpectrum Private Data 
};

类的作用:

(SampledSpectrum  类 表示 SPD 的方式是: 把波长 400~700 分成 30 段,每一段 都可以计算一个平均值出来,那么在 SampledSpectrum  中,只会保存 这 30 段 各自的 平均值。)

SampledSpectrum uses the CoefficientSpectrum infrastructure to represent a SPD with
uniformly spaced samples between a starting and an ending wavelength. The wavelength
range covers from400 nm to 700 nm—the range of the visual spectrum where the human
visual system is most sensitive. The number of samples, 30, is generally more than enough
to accurately represent complex SPDs for rendering. Thus, the first sample represents the
wavelength range [400, 410), the second represents [410, 420), and so forth. These values
can easily be changed here as needed.

a. 

void ToXYZ(float xyz[3]) const

void ToXYZ(float xyz[3]) const {
	xyz[0] = xyz[1] = xyz[2] = 0.f;
	for (int i = 0; i < nSpectralSamples; ++i) {
		xyz[0] += X.c[i] * c[i];
		xyz[1] += Y.c[i] * c[i];
		xyz[2] += Z.c[i] * c[i];
	}
	float scale = float(sampledLambdaEnd - sampledLambdaStart) /
		float(CIE_Y_integral * nSpectralSamples);
	xyz[0] *= scale;
	xyz[1] *= scale;
	xyz[2] *= scale;
}

作用:(直接把SPD 转为 XYZ,但是公式的积分变为 黎曼和 ,

All Spectrum implementations in pbrt must provide a method that converts their SPD to
(xλ, yλ, zλ) coefficients. This method is called, for example, in the process of updating
pixels in the image.When a Spectrum is provided to the ImageFilm, the ImageFilm converts
the SPD into XYZ coefficients as a first step in the process of finally turning them into
RGB values used for storage and/or display.

b.

float y() const

float y() const {
		float yy = 0.f;
		for (int i = 0; i < nSpectralSamples; ++i)
			yy += Y.c[i] * c[i];
		return yy * float(sampledLambdaEnd - sampledLambdaStart) /
			float(CIE_Y_integral * nSpectralSamples);
	}

作用:

(XYZ中的Y其实是可以表示一个颜色的亮度,所以直接提供一个接口出来)

The y coordinate of XYZ color is closely related to luminance, which measures the perceived
brightness of a color. Luminance is described in more detail in Section 5.4.3. We
provide a method to compute y alone in a separate method as often only the luminance
of a spectrum is desired. (For example, some of the light transport algorithms in Chapters
15–17 use luminance as a measure of relative importance of light-carrying paths
through the scene.)

c.

void ToRGB(float rgb[3]) const

void ToRGB(float rgb[3]) const {
	float xyz[3];
	ToXYZ(xyz);
	XYZToRGB(xyz, rgb);
}

inline void XYZToRGB(const float xyz[3], float rgb[3]) {
	rgb[0] = 3.240479f*xyz[0] - 1.537150f*xyz[1] - 0.498535f*xyz[2];
	rgb[1] = -0.969256f*xyz[0] + 1.875991f*xyz[1] + 0.041556f*xyz[2];
	rgb[2] = 0.055648f*xyz[0] - 0.204043f*xyz[1] + 1.057311f*xyz[2];
}

作用:

(直接把SPD 转为 RGB)

Given these functions, a SampledSpectrum can convert to RGB coefficients by first converting
to XYZ and then using the XYZToRGB() utility function.

6. RGBSpectrum

class RGBSpectrum : public CoefficientSpectrum<3> {
	using CoefficientSpectrum<3>::c;
public:
	// RGBSpectrum Public Methods
	RGBSpectrum(float v = 0.f) : CoefficientSpectrum<3>(v) { }
	RGBSpectrum(const CoefficientSpectrum<3> &v)
		: CoefficientSpectrum<3>(v) { }
	RGBSpectrum(const RGBSpectrum &s, SpectrumType type = SPECTRUM_REFLECTANCE) {
		*this = s;
	}
	static RGBSpectrum FromRGB(const float rgb[3],
		SpectrumType type = SPECTRUM_REFLECTANCE) {
		RGBSpectrum s;
		s.c[0] = rgb[0];
		s.c[1] = rgb[1];
		s.c[2] = rgb[2];
		Assert(!s.HasNaNs());
		return s;
	}
	void ToRGB(float *rgb) const {
		rgb[0] = c[0];
		rgb[1] = c[1];
		rgb[2] = c[2];
	}
	const RGBSpectrum &ToRGBSpectrum() const {
		return *this;
	}
	void ToXYZ(float xyz[3]) const {
		RGBToXYZ(c, xyz);
	}
	static RGBSpectrum FromXYZ(const float xyz[3],
		SpectrumType type = SPECTRUM_REFLECTANCE) {
		RGBSpectrum r;
		XYZToRGB(xyz, r.c);
		return r;
	}
	float y() const {
		const float YWeight[3] = { 0.212671f, 0.715160f, 0.072169f };
		return YWeight[0] * c[0] + YWeight[1] * c[1] + YWeight[2] * c[2];
	}
	static RGBSpectrum FromSampled(const float *lambda, const float *v,
		int n) {
		// Sort samples if unordered, use sorted for returned spectrum
		if (!SpectrumSamplesSorted(lambda, v, n)) {
			vector<float> slambda(&lambda[0], &lambda[n]);
			vector<float> sv(&v[0], &v[n]);
			SortSpectrumSamples(&slambda[0], &sv[0], n);
			return FromSampled(&slambda[0], &sv[0], n);
		}
		float xyz[3] = { 0, 0, 0 };
		float yint = 0.f;
		for (int i = 0; i < nCIESamples; ++i) {
			yint += CIE_Y[i];
			float val = InterpolateSpectrumSamples(lambda, v, n,
				CIE_lambda[i]);
			xyz[0] += val * CIE_X[i];
			xyz[1] += val * CIE_Y[i];
			xyz[2] += val * CIE_Z[i];
		}
		xyz[0] /= yint;
		xyz[1] /= yint;
		xyz[2] /= yint;
		return FromXYZ(xyz);
	}
};

类的作用:

(RGBSpectrum 用RGB,3个值来表示一个 SPD,值得注意的是,给两个不同的显示器,这两个显示器显示一样的RGB颜色,那么SPD肯定是不一样的,所以,如果要 一个RGB 对应一个 SPD的话,那么比较要先确定显示器,那就是R(λ), G(λ), and B(λ)值)

The RGBSpectrum implementation here represents SPDs with a weighted sum of red,
green, and blue components. Recall that this representation is ill defined: given two
different computer displays, having them display the same RGB value won’t cause them
to emit the same SPD. Thus, in order for a set of RGB values to specify an actual SPD, we
must know the monitor primaries that they are defined in terms of; this information is
generally not provided along with RGB values.


The RGB representation is nevertheless convenient: almost all 3D modeling and design
tools use RGB colors, and most 3D content is specified in terms of RGB. Furthermore, it’s
computationally and storage efficient, requiring just three floating-point values to represent.
Our implementation of RGBSpectrum inherits from CoefficientSpectrum, specifying
three components to store. Thus, all of the arithmetic operations defined earlier are automatically
available for the RGBSpectrum.

a. RGBSpectrum 的方法,基本上都比较好理解,FromSampled 复杂一点,主要的思想就是,先把Sample 变成 XYZ,再把XYZ变成RGB

猜你喜欢

转载自blog.csdn.net/aa20274270/article/details/82944862