DDraceNetwork Documentation
Loading...
Searching...
No Matches
color.h
Go to the documentation of this file.
1
2#ifndef BASE_COLOR_H
3#define BASE_COLOR_H
4
5#include <base/math.h>
6
7#include <optional>
8#include <type_traits>
9
10/*
11 Title: Color handling
12*/
13/*
14 Function: RgbToHue
15 Determines the hue from RGB values
16*/
17constexpr float RgbToHue(float r, float g, float b)
18{
19 float h_min = minimum(r, g, b);
20 float h_max = maximum(r, g, b);
21
22 float hue = 0.0f;
23 if(h_max != h_min)
24 {
25 float c = h_max - h_min;
26 if(h_max == r)
27 hue = (g - b) / c + (g < b ? 6 : 0);
28 else if(h_max == g)
29 hue = (b - r) / c + 2;
30 else
31 hue = (r - g) / c + 4;
32 }
33
34 return hue / 6.0f;
35}
36
37// Curiously Recurring Template Pattern for type safety
38template<typename DerivedT>
40{
41public:
42 union
43 {
44 float x, r, h;
45 };
46 union
47 {
48 float y, g, s;
49 };
50 union
51 {
52 float z, b, l, v;
53 };
54 union
55 {
56 float w, a;
57 };
58
59 constexpr color4_base() :
60 x(), y(), z(), a()
61 {
62 }
63
64 constexpr color4_base(float nx, float ny, float nz, float na) :
65 x(nx), y(ny), z(nz), a(na)
66 {
67 }
68
69 constexpr color4_base(float nx, float ny, float nz) :
70 x(nx), y(ny), z(nz), a(1.0f)
71 {
72 }
73
74 constexpr color4_base(unsigned col, bool alpha = false)
75 {
76 a = alpha ? ((col >> 24) & 0xFF) / 255.0f : 1.0f;
77 x = ((col >> 16) & 0xFF) / 255.0f;
78 y = ((col >> 8) & 0xFF) / 255.0f;
79 z = ((col >> 0) & 0xFF) / 255.0f;
80 }
81
82 // Disallow casting between different instantiations of the color4_base template.
83 // The color_cast functions below should be used to convert between colors.
84 template<typename OtherDerivedT>
85 requires(!std::is_same_v<DerivedT, OtherDerivedT>)
87
88 constexpr float &operator[](int index)
89 {
90 return ((float *)this)[index];
91 }
92
93 constexpr bool operator==(const color4_base &col) const { return x == col.x && y == col.y && z == col.z && a == col.a; }
94 constexpr bool operator!=(const color4_base &col) const { return x != col.x || y != col.y || z != col.z || a != col.a; }
95
96 constexpr unsigned Pack(bool Alpha = true) const
97 {
98 return (Alpha ? ((unsigned)round_to_int(a * 255.0f) << 24) : 0) + ((unsigned)round_to_int(x * 255.0f) << 16) + ((unsigned)round_to_int(y * 255.0f) << 8) + (unsigned)round_to_int(z * 255.0f);
99 }
100
101 constexpr unsigned PackAlphaLast(bool Alpha = true) const
102 {
103 if(Alpha)
104 return ((unsigned)round_to_int(x * 255.0f) << 24) + ((unsigned)round_to_int(y * 255.0f) << 16) + ((unsigned)round_to_int(z * 255.0f) << 8) + (unsigned)round_to_int(a * 255.0f);
105 return ((unsigned)round_to_int(x * 255.0f) << 16) + ((unsigned)round_to_int(y * 255.0f) << 8) + (unsigned)round_to_int(z * 255.0f);
106 }
107
108 constexpr DerivedT WithAlpha(float alpha) const
109 {
110 DerivedT col(static_cast<const DerivedT &>(*this));
111 col.a = alpha;
112 return col;
113 }
114
115 constexpr DerivedT WithMultipliedAlpha(float alpha) const
116 {
117 DerivedT col(static_cast<const DerivedT &>(*this));
118 col.a *= alpha;
119 return col;
120 }
121
122 template<typename UnpackT>
123 constexpr static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha = true)
124 {
125 UnpackT Result;
126 if(Alpha)
127 {
128 Result.x = ((Color >> 24) & 0xFF) / 255.0f;
129 Result.y = ((Color >> 16) & 0xFF) / 255.0f;
130 Result.z = ((Color >> 8) & 0xFF) / 255.0f;
131 Result.a = ((Color >> 0) & 0xFF) / 255.0f;
132 }
133 else
134 {
135 Result.x = ((Color >> 16) & 0xFF) / 255.0f;
136 Result.y = ((Color >> 8) & 0xFF) / 255.0f;
137 Result.z = ((Color >> 0) & 0xFF) / 255.0f;
138 Result.a = 1.0f;
139 }
140 return Result;
141 }
142};
143
144class ColorHSLA : public color4_base<ColorHSLA>
145{
146public:
148 constexpr ColorHSLA() = default;
149
150 constexpr static const float DARKEST_LGT = 0.5f;
151 constexpr static const float DARKEST_LGT7 = 61.0f / 255.0f;
152
153 constexpr ColorHSLA UnclampLighting(float Darkest) const
154 {
155 ColorHSLA col = *this;
156 col.l = Darkest + col.l * (1.0f - Darkest);
157 return col;
158 }
159
160 constexpr unsigned Pack(bool Alpha = true) const
161 {
162 return color4_base::Pack(Alpha);
163 }
164
165 constexpr unsigned Pack(float Darkest, bool Alpha = false) const
166 {
167 ColorHSLA col = *this;
168 col.l = (l - Darkest) / (1 - Darkest);
169 col.l = std::clamp(col.l, 0.0f, 1.0f);
170 return col.Pack(Alpha);
171 }
172};
173
174class ColorHSVA : public color4_base<ColorHSVA>
175{
176public:
178 constexpr ColorHSVA() = default;
179};
180
181class ColorRGBA : public color4_base<ColorRGBA>
182{
183public:
185 constexpr ColorRGBA() = default;
186
187 constexpr ColorRGBA Multiply(const ColorRGBA &Other) const
188 {
189 ColorRGBA Color = *this;
190 Color.r *= Other.r;
191 Color.g *= Other.g;
192 Color.b *= Other.b;
193 Color.a *= Other.a;
194 return Color;
195 }
196
197 template<Numeric T>
198 constexpr ColorRGBA Multiply(const T &Factor) const
199 {
200 ColorRGBA Color = *this;
201 Color.r *= Factor;
202 Color.g *= Factor;
203 Color.b *= Factor;
204 Color.a *= Factor;
205 return Color;
206 }
207};
208
209template<typename T, typename F>
210constexpr T color_cast(const F &) = delete;
211
212template<>
213constexpr ColorHSLA color_cast(const ColorRGBA &rgb)
214{
215 float Min = minimum(rgb.r, rgb.g, rgb.b);
216 float Max = maximum(rgb.r, rgb.g, rgb.b);
217
218 float c = Max - Min;
219 float h = RgbToHue(rgb.r, rgb.g, rgb.b);
220 float l = 0.5f * (Max + Min);
221 float s = (Max != 0.0f && Min != 1.0f) ? (c / (1 - (absolute(2 * l - 1)))) : 0;
222
223 return ColorHSLA(h, s, l, rgb.a);
224}
225
226template<>
227constexpr ColorRGBA color_cast(const ColorHSLA &hsl)
228{
229 float h1 = hsl.h * 6;
230 float c = (1.f - absolute(2 * hsl.l - 1)) * hsl.s;
231 float x = c * (1.f - absolute(std::fmod(h1, 2) - 1.f));
232
233 float r = 0.0f;
234 float g = 0.0f;
235 float b = 0.0f;
236 switch(round_truncate(h1))
237 {
238 case 0:
239 r = c;
240 g = x;
241 break;
242 case 1:
243 r = x;
244 g = c;
245 break;
246 case 2:
247 g = c;
248 b = x;
249 break;
250 case 3:
251 g = x;
252 b = c;
253 break;
254 case 4:
255 r = x;
256 b = c;
257 break;
258 case 5:
259 case 6:
260 r = c;
261 b = x;
262 break;
263 }
264
265 float m = hsl.l - (c / 2);
266 return ColorRGBA(r + m, g + m, b + m, hsl.a);
267}
268
269template<>
270constexpr ColorHSLA color_cast(const ColorHSVA &hsv)
271{
272 float l = hsv.v * (1 - hsv.s * 0.5f);
273 return ColorHSLA(hsv.h, (l == 0.0f || l == 1.0f) ? 0 : (hsv.v - l) / minimum(l, 1 - l), l, hsv.a);
274}
275
276template<>
277constexpr ColorHSVA color_cast(const ColorHSLA &hsl)
278{
279 float v = hsl.l + hsl.s * minimum(hsl.l, 1 - hsl.l);
280 return ColorHSVA(hsl.h, v == 0.0f ? 0 : 2 - (2 * hsl.l / v), v, hsl.a);
281}
282
283template<>
284constexpr ColorRGBA color_cast(const ColorHSVA &hsv)
285{
287}
288
289template<>
290constexpr ColorHSVA color_cast(const ColorRGBA &rgb)
291{
293}
294
295template<typename T>
296constexpr T color_scale(const T &col, float s)
297{
298 return T(col.x * s, col.y * s, col.z * s, col.a * s);
299}
300
301template<typename T>
302constexpr T color_invert(const T &col)
303{
304 return T(1.0f - col.x, 1.0f - col.y, 1.0f - col.z, 1.0f - col.a);
305}
306
307template<typename T>
308std::optional<T> color_parse(const char *pStr);
309
310#endif
Definition color.h:145
static constexpr const float DARKEST_LGT7
Definition color.h:151
static constexpr const float DARKEST_LGT
Definition color.h:150
constexpr unsigned Pack(float Darkest, bool Alpha=false) const
Definition color.h:165
constexpr color4_base()
Definition color.h:59
constexpr unsigned Pack(bool Alpha=true) const
Definition color.h:160
constexpr ColorHSLA()=default
constexpr ColorHSLA UnclampLighting(float Darkest) const
Definition color.h:153
Definition color.h:175
constexpr color4_base()
Definition color.h:59
constexpr ColorHSVA()=default
Definition color.h:182
constexpr ColorRGBA Multiply(const T &Factor) const
Definition color.h:198
constexpr color4_base()
Definition color.h:59
constexpr ColorRGBA()=default
constexpr ColorRGBA Multiply(const ColorRGBA &Other) const
Definition color.h:187
static constexpr UnpackT UnpackAlphaLast(unsigned Color, bool Alpha=true)
Definition color.h:123
float h
Definition color.h:44
float b
Definition color.h:52
float x
Definition color.h:44
constexpr color4_base(float nx, float ny, float nz, float na)
Definition color.h:64
color4_base(const color4_base< OtherDerivedT > &Other)=delete
constexpr bool operator!=(const color4_base &col) const
Definition color.h:94
constexpr color4_base(unsigned col, bool alpha=false)
Definition color.h:74
float z
Definition color.h:52
float r
Definition color.h:44
float l
Definition color.h:52
float w
Definition color.h:56
float s
Definition color.h:48
constexpr unsigned Pack(bool Alpha=true) const
Definition color.h:96
constexpr color4_base()
Definition color.h:59
float a
Definition color.h:56
constexpr DerivedT WithMultipliedAlpha(float alpha) const
Definition color.h:115
constexpr color4_base(float nx, float ny, float nz)
Definition color.h:69
constexpr float & operator[](int index)
Definition color.h:88
constexpr DerivedT WithAlpha(float alpha) const
Definition color.h:108
constexpr bool operator==(const color4_base &col) const
Definition color.h:93
float v
Definition color.h:52
constexpr unsigned PackAlphaLast(bool Alpha=true) const
Definition color.h:101
float y
Definition color.h:48
float g
Definition color.h:48
constexpr T color_invert(const T &col)
Definition color.h:302
constexpr float RgbToHue(float r, float g, float b)
Definition color.h:17
std::optional< T > color_parse(const char *pStr)
Definition color.cpp:6
constexpr T color_cast(const F &)=delete
constexpr T color_scale(const T &col, float s)
Definition color.h:296
static SHA256_DIGEST s(const char *pSha256)
Definition mapbugs.cpp:37
constexpr T minimum(T a, T b)
Definition math.h:137
constexpr int round_to_int(float f)
Definition math.h:16
constexpr T maximum(T a, T b)
Definition math.h:147
constexpr int round_truncate(float f)
Definition math.h:21
constexpr T absolute(T a)
Definition math.h:157