3 #include <color/color.hpp>
4 #include <color/colorable.hpp>
5 #include <color/pbr_spectrum.hpp>
6 #include <color/spd.hpp>
7 #include <color/specdata.hpp>
8 #include <color/specutils.hpp>
9 #include <color/wave.hpp>
11 #include <math3d/vec3.hpp>
14 using namespace ptracey;
17 spd FromRGB(
const vec3 &rgb, SpectrumType type) {
18 spd r = spd::zeros_like(rgbRefl2SpectWhite);
19 if (type == SpectrumType::Reflectance) {
21 if (rgb.x() <= rgb.y() && rgb.x() <= rgb.z()) {
24 r += rgb.x() * rgbRefl2SpectWhite.normalized();
25 if (rgb.y() <= rgb.z()) {
26 r += (rgb.y() - rgb.x()) *
27 rgbRefl2SpectCyan.normalized();
28 r += (rgb.z() - rgb.y()) *
29 rgbRefl2SpectBlue.normalized();
31 r += (rgb.z() - rgb.x()) *
32 rgbRefl2SpectCyan.normalized();
33 r += (rgb.y() - rgb.z()) *
34 rgbRefl2SpectGreen.normalized();
36 }
else if (rgb.y() <= rgb.x() && rgb.y() <= rgb.z()) {
39 r += rgb.y() * rgbRefl2SpectWhite.normalized();
40 if (rgb.x() <= rgb.z()) {
41 r += (rgb.x() - rgb.y()) *
42 rgbRefl2SpectMagenta.normalized();
43 r += (rgb.z() - rgb.x()) *
44 rgbRefl2SpectBlue.normalized();
46 r += (rgb.z() - rgb.y()) *
47 rgbRefl2SpectMagenta.normalized();
48 r += (rgb.x() - rgb.z()) *
49 rgbRefl2SpectRed.normalized();
54 r += rgb.z() * rgbRefl2SpectWhite.normalized();
55 if (rgb.x() <= rgb.y()) {
56 r += (rgb.x() - rgb.z()) *
57 rgbRefl2SpectYellow.normalized();
58 r += (rgb.y() - rgb.x()) *
59 rgbRefl2SpectGreen.normalized();
61 r += (rgb.y() - rgb.z()) *
62 rgbRefl2SpectYellow.normalized();
63 r += (rgb.x() - rgb.y()) *
64 rgbRefl2SpectRed.normalized();
70 if (rgb.x() <= rgb.y() && rgb.x() <= rgb.z()) {
73 r += rgb.x() * rgbIllum2SpectWhite.normalized();
74 if (rgb.y() <= rgb.z()) {
75 r += (rgb.y() - rgb.x()) *
76 rgbIllum2SpectCyan.normalized();
77 r += (rgb.z() - rgb.y()) *
78 rgbIllum2SpectBlue.normalized();
80 r += (rgb.z() - rgb.x()) *
81 rgbIllum2SpectCyan.normalized();
82 r += (rgb.y() - rgb.z()) *
83 rgbIllum2SpectGreen.normalized();
85 }
else if (rgb.y() <= rgb.x() && rgb.y() <= rgb.z()) {
88 r += rgb.y() * rgbIllum2SpectWhite.normalized();
89 if (rgb.x() <= rgb.z()) {
90 r += (rgb.x() - rgb.y()) *
91 rgbIllum2SpectMagenta.normalized();
92 r += (rgb.z() - rgb.x()) *
93 rgbIllum2SpectBlue.normalized();
95 r += (rgb.z() - rgb.y()) *
96 rgbIllum2SpectMagenta.normalized();
97 r += (rgb.x() - rgb.z()) *
98 rgbIllum2SpectRed.normalized();
103 r += rgb.z() * rgbIllum2SpectWhite.normalized();
104 if (rgb.x() <= rgb.y()) {
105 r += (rgb.x() - rgb.z()) *
106 rgbIllum2SpectYellow.normalized();
107 r += (rgb.y() - rgb.x()) *
108 rgbIllum2SpectGreen.normalized();
110 r += (rgb.y() - rgb.z()) *
111 rgbIllum2SpectYellow.normalized();
112 r += (rgb.x() - rgb.y()) *
113 rgbIllum2SpectRed.normalized();
119 auto minw = sp.min_wave();
120 auto maxw = sp.max_wave();
121 sp.resample(VISIBLE_LAMBDA_START, VISIBLE_LAMBDA_END,
145 : spect(
spd()), type(SpectrumType::Reflectance) {}
147 const path &csv_path,
148 const std::string &wave_col_name =
"wavelength",
149 const std::string &power_col_name =
"power",
150 const char &sep =
',',
151 const unsigned int stride = SPD_STRIDE,
152 SpectrumType stype = SpectrumType::Reflectance)
153 : spect(
spd(csv_path, wave_col_name, power_col_name,
159 : spect(s_lambda), type(stype) {}
161 const Real &r,
const Real &g,
const Real &b,
162 SpectrumType stype = SpectrumType::Reflectance)
169 SpectrumType stype = SpectrumType::Reflectance)
176 SpectrumType stype = SpectrumType::Reflectance)
178 spect = from_rgb(_rgb);
182 SpectrumType stype = SpectrumType::Reflectance)
184 spect = from_rgb(_rgb);
187 spd _from_rgb(
const vec3 &rgb) {
191 Real rgbm = rgb.max();
200 auto lr = interp<Real>(rgb.r(), ins, ine, 0.0, 1.0);
201 auto lg = interp<Real>(rgb.g(), ins, ine, 0.0, 1.0);
202 auto lb = interp<Real>(rgb.b(), ins, ine, 0.0, 1.0);
204 auto rho_r_wave = rho_r.powers();
205 auto rho_g_wave = rho_g.powers();
206 auto rho_b_wave = rho_b.powers();
207 auto rho = lr * rho_r_wave;
208 rho += lg * rho_g_wave;
209 rho += lb * rho_b_wave;
210 return spd(rho, rho_r.wavelengths());
213 spd from_rgb(
const vec3 &rgb) {
215 return FromRGB(rgb, type);
218 return from_rgb(
vec3(rgb.r(), rgb.g(), rgb.b()));
221 random(SpectrumType stype = SpectrumType::Reflectance) {
222 auto sp1 = spd::random();
226 random(Real mn, Real mx,
227 SpectrumType stype = SpectrumType::Reflectance) {
228 auto sp1 = spd::random(mn, mx);
231 void insert(
unsigned int wavelength, Real power) {
232 spect.insert(wavelength, power);
234 vec3 to_xyz()
const override {
236 auto waves = spect.wavelengths();
237 for (
auto wave : waves) {
238 xyz.e[0] += sX[wave] * spect[wave];
239 xyz.e[1] += sY[wave] * spect[wave];
240 xyz.e[2] += sZ[wave] * spect[wave];
242 auto wsize = (uint)waves.size();
243 auto scale = (spect.wave_end - spect.wave_start) /
244 Real(CIE_Y_integral * wsize);
248 vec3 _to_xyz()
const {
251 if (type == SpectrumType::Reflectance) {
252 get_cie_values(standard_d65, spect, xyz);
254 get_cie_values(spect, xyz);
258 Power evaluate(
const WaveLength &w)
const {
261 void add(
const color &r_color,
const WaveLength &w) {
262 spect.add(w, r_color.pdata);
264 void scale(Real coeff) { spect *= coeff; }
265 vec3 to_rgb()
const override {
267 vec3 rgb = xyz2rgb_pbr(xyz);
272 auto wsize = (uint)spect.wavelengths().size();
273 auto wstart = spect.wave_start;
274 auto wend = spect.wave_end;
275 sX = Xspd.resample_c(wstart, wend, wsize).normalized();
276 sY = Yspd.resample_c(wstart, wend, wsize).normalized();
277 sZ = Zspd.resample_c(wstart, wend, wsize).normalized();
321 inline std::ostream &
323 return out << ss.spect << std::endl;