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