DDraceNetwork Docs
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#include <base/vmath.h>
7
8#include <optional>
9
10/*
11 Title: Color handling
12*/
13/*
14 Function: RgbToHue
15 Determines the hue from RGB values
16*/
17inline 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
60 x(), y(), z(), a()
61 {
62 }
63
65 {
66 x = v4.x;
67 y = v4.y;
68 z = v4.z;
69 a = v4.w;
70 }
71
72 color4_base(const vec3 &v3)
73 {
74 x = v3.x;
75 y = v3.y;
76 z = v3.z;
77 a = 1.0f;
78 }
79
80 color4_base(float nx, float ny, float nz, float na)
81 {
82 x = nx;
83 y = ny;
84 z = nz;
85 a = na;
86 }
87
88 color4_base(float nx, float ny, float nz)
89 {
90 x = nx;
91 y = ny;
92 z = nz;
93 a = 1.0f;
94 }
95
96 color4_base(unsigned col, bool alpha = false)
97 {
98 a = alpha ? ((col >> 24) & 0xFF) / 255.0f : 1.0f;
99 x = ((col >> 16) & 0xFF) / 255.0f;
100 y = ((col >> 8) & 0xFF) / 255.0f;
101 z = ((col >> 0) & 0xFF) / 255.0f;
102 }
103
104 vec4 v4() const { return vec4(x, y, z, a); }
105 operator vec4() const { return vec4(x, y, z, a); }
106 float &operator[](int index)
107 {
108 return ((float *)this)[index];
109 }
110
111 bool operator==(const color4_base &col) const { return x == col.x && y == col.y && z == col.z && a == col.a; }
112 bool operator!=(const color4_base &col) const { return x != col.x || y != col.y || z != col.z || a != col.a; }
113
114 unsigned Pack(bool Alpha = true) const
115 {
116 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);
117 }
118
119 unsigned PackAlphaLast(bool Alpha = true) const
120 {
121 if(Alpha)
122 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);
123 return ((unsigned)round_to_int(x * 255.0f) << 16) + ((unsigned)round_to_int(y * 255.0f) << 8) + (unsigned)round_to_int(z * 255.0f);
124 }
125
126 DerivedT WithAlpha(float alpha) const
127 {
128 DerivedT col(static_cast<const DerivedT &>(*this));
129 col.a = alpha;
130 return col;
131 }
132
133 DerivedT WithMultipliedAlpha(float alpha) const
134 {
135 DerivedT col(static_cast<const DerivedT &>(*this));
136 col.a *= alpha;
137 return col;
138 }
139
140 DerivedT Multiply(const DerivedT &Other) const
141 {
142 DerivedT Color(static_cast<const DerivedT &>(*this));
143 Color.x *= Other.x;
144 Color.y *= Other.y;
145 Color.z *= Other.z;
146 Color.a *= Other.a;
147 return Color;
148 }
149
150 template<typename UnpackT>
151 static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha = true)
152 {
153 UnpackT Result;
154 if(Alpha)
155 {
156 Result.x = ((Color >> 24) & 0xFF) / 255.0f;
157 Result.y = ((Color >> 16) & 0xFF) / 255.0f;
158 Result.z = ((Color >> 8) & 0xFF) / 255.0f;
159 Result.a = ((Color >> 0) & 0xFF) / 255.0f;
160 }
161 else
162 {
163 Result.x = ((Color >> 16) & 0xFF) / 255.0f;
164 Result.y = ((Color >> 8) & 0xFF) / 255.0f;
165 Result.z = ((Color >> 0) & 0xFF) / 255.0f;
166 Result.a = 1.0f;
167 }
168 return Result;
169 }
170};
171
172class ColorHSLA : public color4_base<ColorHSLA>
173{
174public:
177
178 constexpr static const float DARKEST_LGT = 0.5f;
179 constexpr static const float DARKEST_LGT7 = 61.0f / 255.0f;
180
181 ColorHSLA UnclampLighting(float Darkest) const
182 {
183 ColorHSLA col = *this;
184 col.l = Darkest + col.l * (1.0f - Darkest);
185 return col;
186 }
187
188 unsigned Pack(bool Alpha = true) const
189 {
190 return color4_base::Pack(Alpha);
191 }
192
193 unsigned Pack(float Darkest, bool Alpha = false) const
194 {
195 ColorHSLA col = *this;
196 col.l = (l - Darkest) / (1 - Darkest);
197 col.l = clamp(col.l, 0.0f, 1.0f);
198 return col.Pack(Alpha);
199 }
200};
201
202class ColorHSVA : public color4_base<ColorHSVA>
203{
204public:
207};
208
209class ColorRGBA : public color4_base<ColorRGBA>
210{
211public:
214};
215
216template<typename T, typename F>
217T color_cast(const F &) = delete;
218
219template<>
221{
222 float Min = minimum(rgb.r, rgb.g, rgb.b);
223 float Max = maximum(rgb.r, rgb.g, rgb.b);
224
225 float c = Max - Min;
226 float h = RgbToHue(rgb.r, rgb.g, rgb.b);
227 float l = 0.5f * (Max + Min);
228 float s = (Max != 0.0f && Min != 1.0f) ? (c / (1 - (absolute(2 * l - 1)))) : 0;
229
230 return ColorHSLA(h, s, l, rgb.a);
231}
232
233template<>
235{
236 vec3 rgb = vec3(0, 0, 0);
237
238 float h1 = hsl.h * 6;
239 float c = (1.f - absolute(2 * hsl.l - 1)) * hsl.s;
240 float x = c * (1.f - absolute(std::fmod(h1, 2) - 1.f));
241
242 switch(round_truncate(h1))
243 {
244 case 0:
245 rgb.r = c;
246 rgb.g = x;
247 break;
248 case 1:
249 rgb.r = x;
250 rgb.g = c;
251 break;
252 case 2:
253 rgb.g = c;
254 rgb.b = x;
255 break;
256 case 3:
257 rgb.g = x;
258 rgb.b = c;
259 break;
260 case 4:
261 rgb.r = x;
262 rgb.b = c;
263 break;
264 case 5:
265 case 6:
266 rgb.r = c;
267 rgb.b = x;
268 break;
269 }
270
271 float m = hsl.l - (c / 2);
272 return ColorRGBA(rgb.r + m, rgb.g + m, rgb.b + m, hsl.a);
273}
274
275template<>
277{
278 float l = hsv.v * (1 - hsv.s * 0.5f);
279 return ColorHSLA(hsv.h, (l == 0.0f || l == 1.0f) ? 0 : (hsv.v - l) / minimum(l, 1 - l), l, hsv.a);
280}
281
282template<>
284{
285 float v = hsl.l + hsl.s * minimum(hsl.l, 1 - hsl.l);
286 return ColorHSVA(hsl.h, v == 0.0f ? 0 : 2 - (2 * hsl.l / v), v, hsl.a);
287}
288
289template<>
291{
292 return color_cast<ColorRGBA>(color_cast<ColorHSLA>(hsv));
293}
294
295template<>
297{
298 return color_cast<ColorHSVA>(color_cast<ColorHSLA>(rgb));
299}
300
301template<typename T>
302T color_scale(const T &col, float s)
303{
304 return T(col.x * s, col.y * s, col.z * s, col.a * s);
305}
306
307template<typename T>
308T color_invert(const T &col)
309{
310 return T(1.0f - col.x, 1.0f - col.y, 1.0f - col.z, 1.0f - col.a);
311}
312
313template<typename T>
314std::optional<T> color_parse(const char *pStr);
315
316#endif
Definition: color.h:173
ColorHSLA UnclampLighting(float Darkest) const
Definition: color.h:181
static constexpr const float DARKEST_LGT7
Definition: color.h:179
static constexpr const float DARKEST_LGT
Definition: color.h:178
ColorHSLA()
Definition: color.h:176
unsigned Pack(bool Alpha=true) const
Definition: color.h:188
unsigned Pack(float Darkest, bool Alpha=false) const
Definition: color.h:193
Definition: color.h:203
ColorHSVA()
Definition: color.h:206
Definition: color.h:210
ColorRGBA()
Definition: color.h:213
Definition: color.h:40
color4_base(float nx, float ny, float nz)
Definition: color.h:88
DerivedT WithAlpha(float alpha) const
Definition: color.h:126
float h
Definition: color.h:44
unsigned PackAlphaLast(bool Alpha=true) const
Definition: color.h:119
color4_base()
Definition: color.h:59
float b
Definition: color.h:52
float x
Definition: color.h:44
float z
Definition: color.h:52
static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha=true)
Definition: color.h:151
float & operator[](int index)
Definition: color.h:106
float r
Definition: color.h:44
float l
Definition: color.h:52
bool operator!=(const color4_base &col) const
Definition: color.h:112
float w
Definition: color.h:56
color4_base(const vec4 &v4)
Definition: color.h:64
color4_base(const vec3 &v3)
Definition: color.h:72
float s
Definition: color.h:48
float a
Definition: color.h:56
unsigned Pack(bool Alpha=true) const
Definition: color.h:114
bool operator==(const color4_base &col) const
Definition: color.h:111
vec4 v4() const
Definition: color.h:104
float v
Definition: color.h:52
DerivedT Multiply(const DerivedT &Other) const
Definition: color.h:140
float y
Definition: color.h:48
float g
Definition: color.h:48
color4_base(float nx, float ny, float nz, float na)
Definition: color.h:80
DerivedT WithMultipliedAlpha(float alpha) const
Definition: color.h:133
color4_base(unsigned col, bool alpha=false)
Definition: color.h:96
Definition: vmath.h:182
T z
Definition: vmath.h:194
T x
Definition: vmath.h:186
T y
Definition: vmath.h:190
T r
Definition: vmath.h:186
T g
Definition: vmath.h:190
T b
Definition: vmath.h:194
Definition: vmath.h:302
T w
Definition: vmath.h:318
T z
Definition: vmath.h:314
T y
Definition: vmath.h:310
T x
Definition: vmath.h:306
float RgbToHue(float r, float g, float b)
Definition: color.h:17
T color_invert(const T &col)
Definition: color.h:308
T color_cast(const F &)=delete
std::optional< T > color_parse(const char *pStr)
Definition: color.cpp:5
T color_scale(const T &col, float s)
Definition: color.h:302
static SHA256_DIGEST s(const char *pSha256)
Definition: mapbugs.cpp:37
constexpr T minimum(T a, T b)
Definition: math.h:135
constexpr int round_to_int(float f)
Definition: math.h:14
constexpr T maximum(T a, T b)
Definition: math.h:145
constexpr int round_truncate(float f)
Definition: math.h:19
constexpr T absolute(T a)
Definition: math.h:155
vector3_base< float > vec3
Definition: vmath.h:294
vector4_base< float > vec4
Definition: vmath.h:388