ddnet/src/base/color.h

242 lines
4.1 KiB
C
Raw Normal View History

#ifndef BASE_COLOR_H
#define BASE_COLOR_H
#include "math.h"
#include "vmath.h"
/*
Title: Color handling
*/
2019-04-26 12:06:32 +00:00
/*
Function: RgbToHue
Determines the hue from RGB values
*/
inline float RgbToHue(float r, float g, float b)
{
float h_min = minimum(r, g, b);
float h_max = maximum(r, g, b);
float hue = 0.0f;
2019-04-21 16:20:53 +00:00
if(h_max != h_min)
{
float c = h_max - h_min;
if(h_max == r)
hue = (g - b) / c + (g < b ? 6 : 0);
else if(h_max == g)
hue = (b - r) / c + 2;
2019-04-21 16:20:53 +00:00
else
hue = (r - g) / c + 4;
2019-04-21 16:20:53 +00:00
}
2019-04-21 16:20:53 +00:00
return hue / 6.0f;
}
class color4_base
2019-04-25 11:48:53 +00:00
{
2019-04-25 15:21:35 +00:00
public:
union { float x, r, h; };
union { float y, g, s; };
union { float z, b, l, v; };
union { float w, a; };
2019-04-25 15:21:35 +00:00
2019-04-25 17:38:11 +00:00
color4_base() {}
2019-04-25 16:59:04 +00:00
2019-04-25 15:21:35 +00:00
color4_base(const vec4 &v4)
{
x = v4.x;
y = v4.y;
z = v4.z;
a = v4.w;
}
2019-04-26 12:06:32 +00:00
color4_base(const vec3 &v3)
{
x = v3.x;
y = v3.y;
z = v3.z;
a = 1.0f;
}
2019-04-25 15:21:35 +00:00
color4_base(float nx, float ny, float nz, float na)
{
x = nx;
y = ny;
z = nz;
a = na;
}
color4_base(float nx, float ny, float nz)
{
x = nx;
y = ny;
z = nz;
a = 1.0f;
}
2019-04-26 22:34:20 +00:00
color4_base(unsigned col, bool alpha = false)
2019-04-25 15:21:35 +00:00
{
2019-04-26 22:34:20 +00:00
a = alpha ? ((col >> 24) & 0xFF) / 255.0f : 1.0f;
2019-04-25 15:21:35 +00:00
x = ((col >> 16) & 0xFF) / 255.0f;
y = ((col >> 8) & 0xFF) / 255.0f;
z = ((col >> 0) & 0xFF) / 255.0f;
}
vec4 v4() { return vec4(x, y, z, a); };
2019-04-26 12:06:32 +00:00
unsigned Pack()
2019-04-25 15:21:35 +00:00
{
2019-04-26 12:06:32 +00:00
return ((unsigned)(a * 255.0f) << 24) + ((unsigned)(x * 255.0f) << 16) + ((unsigned)(y * 255.0f) << 8) + (unsigned)(z * 255.0f);
2019-04-25 15:21:35 +00:00
}
color4_base SetAlpha(float alpha)
{
color4_base col;
col = *this;
col.a = alpha;
return col;
}
2019-04-25 15:21:35 +00:00
};
class ColorHSLA : public color4_base
{
2019-04-26 13:38:16 +00:00
public:
2019-05-01 20:35:29 +00:00
bool m_Lit = false;
2019-04-25 15:21:35 +00:00
using color4_base::color4_base;
2019-04-26 23:07:11 +00:00
ColorHSLA() {};
ColorHSLA(color4_base b): color4_base(b) {};
2019-04-26 13:38:16 +00:00
ColorHSLA Lighten()
2019-04-25 20:29:31 +00:00
{
2019-05-01 20:35:29 +00:00
if(m_Lit)
return *this;
2019-04-26 13:38:16 +00:00
ColorHSLA col = *this;
col.l = 0.5f + l * 0.5f;
2019-05-01 20:35:29 +00:00
col.m_Lit = true;
2019-04-26 13:38:16 +00:00
return col;
};
2019-05-01 20:35:29 +00:00
ColorHSLA Darken()
{
2019-05-01 20:35:29 +00:00
if(!m_Lit)
return *this;
ColorHSLA col = *this;
col.l = (l - 0.5f) * 2;
col.m_Lit = false;
return col;
}
int Pack()
{
if(m_Lit)
return Darken().color4_base::Pack();
else
return color4_base::Pack();
}
2019-04-25 15:21:35 +00:00
};
2019-04-26 12:06:32 +00:00
class ColorHSVA : public color4_base
{
public:
2019-04-26 12:06:32 +00:00
using color4_base::color4_base;
2019-04-26 23:07:11 +00:00
ColorHSVA() {};
ColorHSVA(color4_base b): color4_base(b) {};
2019-04-26 12:06:32 +00:00
};
2019-04-25 15:21:35 +00:00
class ColorRGBA : public color4_base
{
public:
2019-04-25 15:21:35 +00:00
using color4_base::color4_base;
2019-04-26 23:07:11 +00:00
ColorRGBA() {};
ColorRGBA(color4_base b): color4_base(b) {};
2019-04-25 15:21:35 +00:00
};
2019-04-26 12:06:32 +00:00
template <typename T, typename F> T color_cast(const F &f) = delete;
2019-04-25 15:21:35 +00:00
template <>
inline ColorHSLA color_cast(const ColorRGBA &rgb)
{
2019-04-26 19:36:49 +00:00
float Min = minimum(rgb.r, rgb.g, rgb.b);
float Max = maximum(rgb.r, rgb.g, rgb.b);
2019-04-25 15:21:35 +00:00
float c = Max - Min;
float h = RgbToHue(rgb.r, rgb.g, rgb.b);
2019-04-25 15:21:35 +00:00
float l = 0.5f * (Max + Min);
float s = (Max != 0.0f && Min != 1.0f) ? (c/(1 - (absolute(2 * l - 1)))) : 0;
return ColorHSLA(h, s, l, rgb.a);
2019-04-25 11:48:53 +00:00
}
2019-04-25 15:21:35 +00:00
template <>
inline ColorRGBA color_cast(const ColorHSLA &hsl)
2019-04-21 16:20:53 +00:00
{
2019-04-25 15:21:35 +00:00
vec3 rgb = vec3(0, 0, 0);
float h1 = hsl.h * 6;
float c = (1 - absolute(2 * hsl.l - 1)) * hsl.s;
float x = c * (1 - absolute(fmod(h1, 2) - 1));
switch(round_truncate(h1)) {
case 0:
rgb.r = c, rgb.g = x;
break;
case 1:
rgb.r = x, rgb.g = c;
break;
case 2:
rgb.g = c, rgb.b = x;
break;
case 3:
rgb.g = x, rgb.b = c;
break;
case 4:
rgb.r = x, rgb.b = c;
break;
case 5:
2019-04-26 18:01:41 +00:00
case 6:
2019-04-25 15:21:35 +00:00
rgb.r = c, rgb.b = x;
break;
}
float m = hsl.l - (c/2);
return ColorRGBA(rgb.r + m, rgb.g + m, rgb.b + m, hsl.a);
2019-04-21 16:20:53 +00:00
}
2019-04-26 12:06:32 +00:00
template <>
inline ColorHSLA color_cast(const ColorHSVA &hsv)
{
float l = hsv.v * (1 - hsv.s * 0.5f);
2019-04-26 19:36:49 +00:00
return ColorHSLA(hsv.h, (l == 0.0f || l == 1.0f) ? 0 : (hsv.v - l)/minimum(l, 1 - l), l);
2019-04-26 12:06:32 +00:00
}
template <>
inline ColorHSVA color_cast(const ColorHSLA &hsl)
{
2019-04-26 19:36:49 +00:00
float v = hsl.l + hsl.s * minimum(hsl.l, 1 - hsl.l);
2019-04-26 12:06:32 +00:00
return ColorHSVA(hsl.h, v == 0.0f ? 0 : 2 - (2 * hsl.l / v), v);
}
template <>
inline ColorRGBA color_cast(const ColorHSVA &hsv)
{
return color_cast<ColorRGBA>(color_cast<ColorHSLA>(hsv));
}
template <>
inline ColorHSVA color_cast(const ColorRGBA &rgb)
{
return color_cast<ColorHSVA>(color_cast<ColorHSLA>(rgb));
}
template <typename T>
T color_scale(const color4_base &col, float s)
{
return T(col.x * s, col.y * s, col.z * s, col.a * s);
}
#endif