SPH
Spectrum.cpp
Go to the documentation of this file.
2 #include "objects/wrappers/Lut.h"
3 #include "physics/Constants.h"
4 
6 
7 class Xyz {
8 private:
10 
11 public:
12  Xyz() = default;
13 
14  Xyz(const float x, const float y, const float z)
15  : data(x, y, z) {}
16 
17  float& operator[](const int index) {
18  SPH_ASSERT(index < 3);
19  return data[index];
20  }
21 
22  Xyz& operator+=(const Xyz& other) {
23  *this = *this + other;
24  return *this;
25  }
26 
27  Xyz operator+(const Xyz& other) const {
28  Xyz sum;
29  sum.data = data + other.data;
30  return sum;
31  }
32 
33  Xyz operator*(const float factor) const {
34  Xyz result;
35  result.data = data * factor;
36  return result;
37  }
38 
39  Xyz operator/(const float factor) const {
40  Xyz result;
41  result.data = data / factor;
42  return result;
43  }
44 
45  float& x() {
46  return data[0];
47  }
48 
49  float x() const {
50  return data[0];
51  }
52 
53  float& y() {
54  return data[1];
55  }
56 
57  float y() const {
58  return data[1];
59  }
60 
61  float& z() {
62  return data[2];
63  }
64 
65  float z() const {
66  return data[2];
67  }
68 };
69 
70 inline Rgba xyzToRgb(const Xyz& c) {
71  const float r = 3.2404542f * c.x() - 1.5371385f * c.y() - 0.4985314f * c.z();
72  const float g = -0.9692660f * c.x() + 1.8760108f * c.y() + 0.0415560f * c.z();
73  const float b = 0.0556434f * c.x() - 0.2040259f * c.y() + 1.0572252f * c.z();
74  return Rgba(r, g, b);
75 }
76 
77 static Lut<Xyz, float> wavelengthToXyzLut = Lut<Xyz, float>(Interval(380, 780),
78  Array<Xyz>{
79  { 0.0014f, 0.0000f, 0.0065f },
80  { 0.0022f, 0.0001f, 0.0105f },
81  { 0.0042f, 0.0001f, 0.0201f },
82  { 0.0077f, 0.0002f, 0.0362f },
83  { 0.0143f, 0.0004f, 0.0679f },
84  { 0.0232f, 0.0006f, 0.1102f },
85  { 0.0435f, 0.0012f, 0.2074f },
86  { 0.0776f, 0.0022f, 0.3713f },
87  { 0.1344f, 0.0040f, 0.6456f },
88  { 0.2148f, 0.0073f, 1.0391f },
89  { 0.2839f, 0.0116f, 1.3856f },
90  { 0.3285f, 0.0168f, 1.6230f },
91  { 0.3483f, 0.0230f, 1.7471f },
92  { 0.3481f, 0.0298f, 1.7826f },
93  { 0.3362f, 0.0380f, 1.7721f },
94  { 0.3187f, 0.0480f, 1.7441f },
95  { 0.2908f, 0.0600f, 1.6692f },
96  { 0.2511f, 0.0739f, 1.5281f },
97  { 0.1954f, 0.0910f, 1.2876f },
98  { 0.1421f, 0.1126f, 1.0419f },
99  { 0.0956f, 0.1390f, 0.8130f },
100  { 0.0580f, 0.1693f, 0.6162f },
101  { 0.0320f, 0.2080f, 0.4652f },
102  { 0.0147f, 0.2586f, 0.3533f },
103  { 0.0049f, 0.3230f, 0.2720f },
104  { 0.0024f, 0.4073f, 0.2123f },
105  { 0.0093f, 0.5030f, 0.1582f },
106  { 0.0291f, 0.6082f, 0.1117f },
107  { 0.0633f, 0.7100f, 0.0782f },
108  { 0.1096f, 0.7932f, 0.0573f },
109  { 0.1655f, 0.8620f, 0.0422f },
110  { 0.2257f, 0.9149f, 0.0298f },
111  { 0.2904f, 0.9540f, 0.0203f },
112  { 0.3597f, 0.9803f, 0.0134f },
113  { 0.4334f, 0.9950f, 0.0087f },
114  { 0.5121f, 1.0000f, 0.0057f },
115  { 0.5945f, 0.9950f, 0.0039f },
116  { 0.6784f, 0.9786f, 0.0027f },
117  { 0.7621f, 0.9520f, 0.0021f },
118  { 0.8425f, 0.9154f, 0.0018f },
119  { 0.9163f, 0.8700f, 0.0017f },
120  { 0.9786f, 0.8163f, 0.0014f },
121  { 1.0263f, 0.7570f, 0.0011f },
122  { 1.0567f, 0.6949f, 0.0010f },
123  { 1.0622f, 0.6310f, 0.0008f },
124  { 1.0456f, 0.5668f, 0.0006f },
125  { 1.0026f, 0.5030f, 0.0003f },
126  { 0.9384f, 0.4412f, 0.0002f },
127  { 0.8544f, 0.3810f, 0.0002f },
128  { 0.7514f, 0.3210f, 0.0001f },
129  { 0.6424f, 0.2650f, 0.0000f },
130  { 0.5419f, 0.2170f, 0.0000f },
131  { 0.4479f, 0.1750f, 0.0000f },
132  { 0.3608f, 0.1382f, 0.0000f },
133  { 0.2835f, 0.1070f, 0.0000f },
134  { 0.2187f, 0.0816f, 0.0000f },
135  { 0.1649f, 0.0610f, 0.0000f },
136  { 0.1212f, 0.0446f, 0.0000f },
137  { 0.0874f, 0.0320f, 0.0000f },
138  { 0.0636f, 0.0232f, 0.0000f },
139  { 0.0468f, 0.0170f, 0.0000f },
140  { 0.0329f, 0.0119f, 0.0000f },
141  { 0.0227f, 0.0082f, 0.0000f },
142  { 0.0158f, 0.0057f, 0.0000f },
143  { 0.0114f, 0.0041f, 0.0000f },
144  { 0.0081f, 0.0029f, 0.0000f },
145  { 0.0058f, 0.0021f, 0.0000f },
146  { 0.0041f, 0.0015f, 0.0000f },
147  { 0.0029f, 0.0010f, 0.0000f },
148  { 0.0020f, 0.0007f, 0.0000f },
149  { 0.0014f, 0.0005f, 0.0000f },
150  { 0.0010f, 0.0004f, 0.0000f },
151  { 0.0007f, 0.0002f, 0.0000f },
152  { 0.0005f, 0.0002f, 0.0000f },
153  { 0.0003f, 0.0001f, 0.0000f },
154  { 0.0002f, 0.0001f, 0.0000f },
155  { 0.0002f, 0.0001f, 0.0000f },
156  { 0.0001f, 0.0000f, 0.0000f },
157  { 0.0001f, 0.0000f, 0.0000f },
158  { 0.0001f, 0.0000f, 0.0000f },
159  { 0.0000f, 0.0000f, 0.0000f },
160  });
161 
163 inline float getMaxEmissionWavelength(const float temperature) {
164  constexpr float b = 2.8977729e-3f;
165  return b / temperature;
166 }
167 
172 inline float spectralRadiance(const float wavelength, const float temperature) {
173  constexpr Float factor1 =
175  constexpr Float factor2 =
177  const Float denom = exp(factor2 / (wavelength * temperature)) - 1._f;
178  SPH_ASSERT(isReal(denom));
179  const Float result = factor1 / pow<5>(wavelength) * 1._f / denom;
180  SPH_ASSERT(isReal(result));
181  return float(result);
182 }
183 
184 inline Xyz getBlackBodyColor(const float temperature) {
185  const Interval range = wavelengthToXyzLut.getRange();
186  Xyz result(0.f, 0.f, 0.f);
187  float weight = 0.f;
188  for (float wavelength = float(range.lower()); wavelength < range.upper(); wavelength += 5.f) {
189  const Xyz xyz = wavelengthToXyzLut(wavelength);
190  const float B = spectralRadiance(wavelength, temperature);
191  result += xyz * B;
192  weight += B;
193  }
194  SPH_ASSERT(weight > 0.f);
195  return result / weight;
196 }
197 
199  Array<Palette::Point> points(256);
200  for (Size i = 0; i < points.size(); ++i) {
201  const float temperature = float(range.lower()) + float(i) / (points.size() - 1) * float(range.size());
202  const Xyz xyz = getBlackBodyColor(temperature);
203 
204  points[i].value = temperature;
205  const Rgba color = xyzToRgb(xyz);
206  // normalize so that max component is 1
207  points[i].color = color / max(color.r(), color.g(), color.b());
208  }
209  return Palette(std::move(points), PaletteScale::LINEAR);
210 }
211 
213  const float draperPoint = 798.f;
214  const float pureEmissionColor = draperPoint * 1.5f;
215  const Rgba darkColor = Rgba::gray(0.2f);
216  Array<Palette::Point> points(256);
217  for (Size i = 0; i < points.size(); ++i) {
218  const float temperature = float(range.lower()) + float(i) / (points.size() - 1) * float(range.size());
219  points[i].value = temperature;
220 
221  if (temperature < draperPoint) {
222  points[i].color = darkColor;
223  } else {
224  const Xyz xyz = getBlackBodyColor(temperature);
225  const Rgba color = xyzToRgb(xyz);
226  const Rgba normColor = color / max(color.r(), color.g(), color.b());
227  const float weight = min((temperature - draperPoint) / (pureEmissionColor - draperPoint), 1.f);
228  points[i].color = lerp(darkColor, normColor, weight);
229  }
230  }
231  return Palette(std::move(points), PaletteScale::LINEAR);
232 }
233 
INLINE bool isReal(const AntisymmetricTensor &t)
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
Definitions of physical constaints (in SI units).
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Approximation of generic function by look-up table.
INLINE Float weight(const Vector &r1, const Vector &r2)
constexpr INLINE T max(const T &f1, const T &f2)
Definition: MathBasic.h:20
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
constexpr INLINE Float pow< 5 >(const Float v)
Definition: MathUtils.h:140
INLINE T lerp(const T v1, const T v2, const TAmount amount)
Definition: MathUtils.h:341
constexpr INLINE T sqr(const T &f) noexcept
Return a squared value.
Definition: MathUtils.h:67
INLINE T exp(const T f)
Definition: MathUtils.h:269
#define NAMESPACE_SPH_END
Definition: Object.h:12
@ LINEAR
Control points are interpolated on linear scale.
Palette getEmissionPalette(const Interval range)
Definition: Spectrum.cpp:212
Xyz getBlackBodyColor(const float temperature)
Definition: Spectrum.cpp:184
float spectralRadiance(const float wavelength, const float temperature)
Planck law.
Definition: Spectrum.cpp:172
float getMaxEmissionWavelength(const float temperature)
Returns wavelength of maximum emission for given temperature, according to Wien's law.
Definition: Spectrum.cpp:163
Rgba xyzToRgb(const Xyz &c)
Definition: Spectrum.cpp:70
Palette getBlackBodyPalette(const Interval range)
Returns palette with colors for black body emission for given temperature.
Definition: Spectrum.cpp:198
Generic dynamically allocated resizable storage.
Definition: Array.h:43
INLINE TCounter size() const noexcept
Definition: Array.h:193
3-dimensional vector, float precision
Definition: Vector.h:57
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
INLINE Float lower() const
Returns lower bound of the interval.
Definition: Interval.h:74
INLINE Float upper() const
Returns upper bound of the interval.
Definition: Interval.h:79
INLINE Float size() const
Returns the size of the interval.
Definition: Interval.h:89
Callable representing a generic R->T function, approximated using look-up table.
Definition: Lut.h:61
Represents a color palette, used for mapping arbitrary number to a color.
Definition: Palette.h:25
Definition: Color.h:8
static Rgba gray(const float value=0.5f)
Definition: Color.h:198
float & g()
Definition: Color.h:47
float & r()
Definition: Color.h:39
float & b()
Definition: Color.h:55
Definition: Spectrum.cpp:7
Xyz operator+(const Xyz &other) const
Definition: Spectrum.cpp:27
float y() const
Definition: Spectrum.cpp:57
Xyz operator*(const float factor) const
Definition: Spectrum.cpp:33
float x() const
Definition: Spectrum.cpp:49
float z() const
Definition: Spectrum.cpp:65
Xyz operator/(const float factor) const
Definition: Spectrum.cpp:39
float & x()
Definition: Spectrum.cpp:45
Xyz & operator+=(const Xyz &other)
Definition: Spectrum.cpp:22
Xyz(const float x, const float y, const float z)
Definition: Spectrum.cpp:14
float & y()
Definition: Spectrum.cpp:53
Xyz()=default
float & operator[](const int index)
Definition: Spectrum.cpp:17
float & z()
Definition: Spectrum.cpp:61
constexpr Float planckConstant
Planck constant.
Definition: Constants.h:26
constexpr Float speedOfLight
Speed of light in vacuum (exactly)
Definition: Constants.h:32
constexpr Float boltzmann
Boltzmann constant.
Definition: Constants.h:20
constexpr Size sum()
Definition: Multipole.h:31