Convert CColor back to floating point

This commit is contained in:
Phillip Stephens 2015-11-25 17:26:23 -08:00
parent 8d54a3c7b5
commit b172f023fb
2 changed files with 186 additions and 134 deletions

View File

@ -1,23 +1,29 @@
#ifndef CCOLOR_HPP #ifndef CCOLOR_HPP
#define CCOLOR_HPP #define CCOLOR_HPP
#include "Global.hpp" #include "MathLib.hpp"
#include "Math.hpp" #include <iostream>
#if ZE_ATHENA_TYPES
#include <Athena/IStreamReader.hpp>
#endif
#if BYTE_ORDER == __ORDER_LITTLE_ENDIAN__ #if BYTE_ORDER == __ORDER_LITTLE_ENDIAN__
#define COLOR(rgba) (unsigned long)( ( (rgba) & 0x000000FF ) << 24 | ( (rgba) & 0x0000FF00 ) << 8 \ #define COLOR(rgba) ( ( (rgba) & 0x000000FF ) << 24 | ( (rgba) & 0x0000FF00 ) << 8 \
| ( (rgba) & 0x00FF0000 ) >> 8 | ( (rgba) & 0xFF000000 ) >> 24 ) | ( (rgba) & 0x00FF0000 ) >> 8 | ( (rgba) & 0xFF000000 ) >> 24 )
#else #else
#define COLOR(rgba) (unsigned long)rgba #define COLOR(rgba) rgba
#endif #endif
namespace Zeus namespace Zeus
{ {
typedef unsigned char Comp8; typedef union
typedef unsigned long Comp32; {
struct
{
unsigned char r, g, b, a;
};
unsigned int rgba;
} RGBA32;
typedef uint8_t Comp8;
typedef uint32_t Comp32;
class alignas(16) CColor class alignas(16) CColor
{ {
@ -34,126 +40,176 @@ public:
static const CColor skYellow; static const CColor skYellow;
static const CColor skWhite; static const CColor skWhite;
#if __SSE__
CColor(const __m128& mVec128) : mVec128(mVec128) {}
#endif
CColor() : rgba(~0u) {} CColor() : r(1.0f), g(1.0f), b(1.0f), a(1.0f) {}
CColor(float rgb, float a = 1.0) { splat(rgb, a); } CColor(float rgb, float a = 1.0) { splat(rgb, a); }
CColor(float r, float g, float b, float a = 1.0f) CColor(float r, float g, float b, float a = 1.0f) {v[0] = r; v[1] = g; v[2] = b; v[3] = a; }
: r(Comp8(255*r)),
g(Comp8(255*g)),
b(Comp8(255*b)),
a(Comp8(255*a))
{}
#if ZE_ATHENA_TYPES #if ZE_ATHENA_TYPES
CColor(Athena::io::IStreamReader& reader) {readRGBA(reader);} CColor(Athena::io::IStreamReader& reader) {readRGBA(reader);}
#endif #endif
CColor(Comp32 rgba) { fromRGBA32(rgba); } CColor(Comp32 rgba) { fromRGBA32(rgba); }
CColor(const Comp8 rgba[4]) : r(rgba[0]), g(rgba[1]), b(rgba[2]), a(rgba[3]) {} CColor(const Comp8* rgba) { fromRGBA8(rgba[0], rgba[1], rgba[2], rgba[3]); }
CColor(Comp8 r, Comp8 g, Comp8 b, Comp8 a = 255)
: r(r), g(g), b(b), a(a) {}
#if ZE_ATHENA_TYPES #if ZE_ATHENA_TYPES
inline void readRGBA(Athena::io::IStreamReader& reader) inline void readRGBA(Athena::io::IStreamReader& reader)
{ {
r = Comp8(255 * reader.readFloat()); r = reader.readFloat();
g = Comp8(255 * reader.readFloat()); g = reader.readFloat();
b = Comp8(255 * reader.readFloat()); b = reader.readFloat();
a = Comp8(255 * reader.readFloat()); a = reader.readFloat();
} }
inline void readBGRA(Athena::io::IStreamReader& reader) inline void readBGRA(Athena::io::IStreamReader& reader)
{ {
b = Comp8(255 * reader.readFloat()); b = reader.readFloat();
g = Comp8(255 * reader.readFloat()); g = reader.readFloat();
r = Comp8(255 * reader.readFloat()); r = reader.readFloat();
a = Comp8(255 * reader.readFloat()); a = reader.readFloat();
} }
#endif #endif
inline bool operator==(const CColor& rhs) const inline bool operator==(const CColor& rhs) const
{ return (rgba == rhs.rgba); } { return (r == rhs.r && g == rhs.g && b == rhs.b && a == rhs.a); }
inline bool operator!=(const CColor& rhs) const inline bool operator!=(const CColor& rhs) const
{ return !(*this == rhs); } { return !(*this == rhs); }
inline CColor operator+(const CColor& rhs) const inline CColor operator+(const CColor& rhs) const
{ {
CColor ret; ret.r = r + rhs.r; ret.g = g + rhs.g; ret.b = b + rhs.b; ret.a = a + rhs.a; #if __SSE__
return ret; return CColor(_mm_add_ps(mVec128, rhs.mVec128));
#else
return CColor(r + rhs.r, g + rhs.g, b + rhs.b, a + rhs.a);
#endif
} }
inline CColor operator-(const CColor& rhs) const inline CColor operator-(const CColor& rhs) const
{ {
CColor ret; ret.r = r - rhs.r; ret.g = g - rhs.g; ret.b = b - rhs.b; ret.a = a - rhs.a; #if __SSE__
return ret; return CColor(_mm_sub_ps(mVec128, rhs.mVec128));
#else
return CColor(r - rhs.r, g - rhs.g, b - rhs.b, a - rhs.a);
#endif
} }
inline CColor operator*(const CColor& rhs) const inline CColor operator*(const CColor& rhs) const
{ {
CColor ret; ret.r = r * rhs.r; ret.g = g * rhs.g; ret.b = b * rhs.b; ret.a = a * rhs.a; #if __SSE__
return ret; return CColor(_mm_mul_ps(mVec128, rhs.mVec128));
#else
return CColor(r * rhs.r, g * rhs.g, b * rhs.b, a * rhs.a);
#endif
} }
inline CColor operator/(const CColor& rhs) const inline CColor operator/(const CColor& rhs) const
{ {
CColor ret; ret.r = r / rhs.r; ret.g = g / rhs.g; ret.b = b / rhs.b; ret.a = a / rhs.a; #if __SSE__
return ret; return CColor(_mm_div_ps(mVec128, rhs.mVec128));
#else
return CColor(r / rhs.r, g / rhs.g, b / rhs.b, a / rhs.a);
#endif
} }
inline CColor operator+(float val) const inline CColor operator+(float val) const
{ {
CColor ret; #if __SSE__
ret.r = r + Comp8(255 * val); ret.g = g + Comp8(255 * val); ret.b = b + Comp8(255 * val); ret.a = a + Comp8(255 * val); TVectorUnion splat = {{val, val, val, val}};
return ret; return CColor(_mm_add_ps(mVec128, splat.mVec128));
#else
return CColor(r + val, g + val, b + val, a + val);
#endif
} }
inline CColor operator-(float val) const inline CColor operator-(float val) const
{ {
CColor ret; #if __SSE__
ret.r = r - Comp8(255 * val); ret.g = g - Comp8(255 * val); ret.b = b - Comp8(255 * val); ret.a = a - Comp8(255 * val); TVectorUnion splat = {{val, val, val, val}};
return ret; return CColor(_mm_sub_ps(mVec128, splat.mVec128));
#else
return CColor(r - val, g - val, b - val, a - val);
#endif
} }
inline CColor operator*(float val) const inline CColor operator*(float val) const
{ {
CColor ret; #if __SSE__
ret.r = r * Comp8(255 * val); ret.g = g * Comp8(255 * val); ret.b = b * Comp8(255 * val); ret.a = a * Comp8(255 * val); TVectorUnion splat = {{val, val, val, val}};
return ret; return CColor(_mm_mul_ps(mVec128, splat.mVec128));
#else
return CColor(r * val, g * val, b * val, a * val);
#endif
} }
inline CColor operator/(float val) const inline CColor operator/(float val) const
{ {
CColor ret; #if __SSE__
ret.r = r / Comp8(255 * val); ret.g = g / Comp8(255 * val); ret.b = b / Comp8(255 * val); ret.a = a / Comp8(255 * val); TVectorUnion splat = {{val, val, val, val}};
return ret; return CColor(_mm_div_ps(mVec128, splat.mVec128));
#else
return CColor(r / val, g / val, b / val, a / val);
#endif
} }
inline const CColor& operator+=(const CColor& rhs) inline const CColor& operator+=(const CColor& rhs)
{ {
r += rhs.r; g += rhs.g; b += rhs.b; #if __SSE__
a += rhs.a; return *this; mVec128 = _mm_add_ps(mVec128, rhs.mVec128);
#else
r += rhs.r; g += rhs.g; b += rhs.b; a += rhs.a;
#endif
return *this;
} }
inline const CColor& operator-=(const CColor& rhs) inline const CColor& operator-=(const CColor& rhs)
{ {
#if __SSE__
mVec128 = _mm_sub_ps(mVec128, rhs.mVec128);
#else
r -= rhs.r; g -= rhs.g; b -= rhs.b; a -= rhs.a; r -= rhs.r; g -= rhs.g; b -= rhs.b; a -= rhs.a;
#endif
return *this; return *this;
} }
inline const CColor& operator *=(const CColor& rhs) inline const CColor& operator *=(const CColor& rhs)
{ {
#if __SSE__
mVec128 = _mm_mul_ps(mVec128, rhs.mVec128);
#else
r *= rhs.r; g *= rhs.g; b *= rhs.b; a *= rhs.a; r *= rhs.r; g *= rhs.g; b *= rhs.b; a *= rhs.a;
#endif
return *this; return *this;
} }
inline const CColor& operator /=(const CColor& rhs) inline const CColor& operator /=(const CColor& rhs)
{ {
#if __SSE__
mVec128 = _mm_div_ps(mVec128, rhs.mVec128);
#else
r /= rhs.r; g /= rhs.g; b /= rhs.b; a /= rhs.a; r /= rhs.r; g /= rhs.g; b /= rhs.b; a /= rhs.a;
#endif
return *this; return *this;
} }
inline void normalize() inline void normalize()
{ {
float mag = magnitude(); float mag = magnitude();
assert(mag != 0.0);
mag = 1.0 / mag;
*this *= mag; *this *= mag;
} }
inline CColor normalized() inline CColor normalized()
{ {
float mag = magnitude(); float mag = magnitude();
assert(mag != 0.0);
mag = 1.0 / mag;
return *this * mag; return *this * mag;
} }
inline float magSquared() const inline float magSquared() const
{ return ((r * r + g * g + b * b + a * a) / 255.f); } {
#if __SSE4_1__
TVectorUnion result;
result.mVec128 = _mm_dp_ps(mVec128, mVec128, 0xF1);
return result.v[0];
#elif __SSE__
TVectorUnion result;
result.mVec128 = _mm_mul_ps(mVec128, mVec128);
return result.v[0] + result.v[1] + result.v[2] + result.v[3];
#else
return r * r + g * g + b * b + a * a;
#endif
}
inline float magnitude() const inline float magnitude() const
{ {
return Math::sqrtF(magSquared()); return sqrtf(magSquared());
} }
static inline CColor lerp(const CColor& a, const CColor& b, float t) static inline CColor lerp(const CColor& a, const CColor& b, float t)
{ {
@ -163,29 +219,43 @@ public:
{ {
return lerp(a, b, t).normalized(); return lerp(a, b, t).normalized();
} }
inline float& operator[](const size_t& idx) {return (&r)[idx];}
inline Comp8& operator[](size_t idx) {return (&r)[idx];} inline const float& operator[](const size_t& idx) const { return (&r)[idx]; }
inline const Comp8& operator[](size_t idx) const { return (&r)[idx]; }
inline void splat(float rgb, float a) inline void splat(float rgb, float a)
{ {
r = Comp8(255 * rgb); #if __SSE__
g = Comp8(255 * rgb); TVectorUnion splat = {{rgb, rgb, rgb, a}};
b = Comp8(255 * rgb); mVec128 = splat.mVec128;
this->a = Comp8(255 * a); #else
v[0] = rgb; v[1] = rgb; v[2] = rgb; v[3] = a;
#endif
} }
union union
{ {
struct { Comp8 r, g, b, a; }; struct
Comp32 rgba; {
float r, g, b, a;
};
float v[4];
#if __SSE__
__m128 mVec128;
#endif
}; };
void fromRGBA8(unsigned char r, unsigned char g, unsigned char b, unsigned char a) void fromRGBA8(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{ {
this->r = r; this->r = r / 255.f;
this->g = g; this->g = g / 255.f;
this->b = b; this->b = b / 255.f;
this->a = a; this->a = a / 255.f;
}
void fromRGBA32(unsigned int rgba)
{
static RGBA32 tmp;
tmp.rgba = COLOR(rgba);
fromRGBA8(tmp.r, tmp.g, tmp.b, tmp.a);
} }
/** /**
@ -210,51 +280,47 @@ public:
void fromHSL(float h, float s, float l, float _a = 1.0); void fromHSL(float h, float s, float l, float _a = 1.0);
void toHSL(float& h, float& s, float& l); void toHSL(float& h, float& s, float& l);
void fromRGBA32(unsigned int rgba)
{ this->rgba = COLOR(rgba); }
}; };
static inline CColor operator+(float lhs, const CColor& rhs) static inline CColor operator+(float lhs, const CColor& rhs)
{ {
CColor ret; #if __SSE__
ret.r = Comp8(255 * lhs) + rhs.r; TVectorUnion splat = {{lhs, lhs, lhs, lhs}};
ret.g = Comp8(255 * lhs) + rhs.g; return CColor(_mm_add_ps(splat.mVec128, rhs.mVec128));
ret.b = Comp8(255 * lhs) + rhs.b; #else
ret.a = Comp8(255 * lhs) + rhs.a; return CColor(lhs + rhs.r, lhs + rhs.g, lhs + rhs.b, lhs + rhs.a);
return ret; #endif
} }
static inline CColor operator-(float lhs, const CColor& rhs) static inline CColor operator-(float lhs, const CColor& rhs)
{ {
CColor ret; #if __SSE__
ret.r = Comp8(255 * lhs) - rhs.r; TVectorUnion splat = {{lhs, lhs, lhs, lhs}};
ret.g = Comp8(255 * lhs) - rhs.g; return CColor(_mm_sub_ps(splat.mVec128, rhs.mVec128));
ret.b = Comp8(255 * lhs) - rhs.b; #else
ret.a = Comp8(255 * lhs) - rhs.a; return CColor(lhs - rhs.r, lhs - rhs.g, lhs - rhs.b, lhs - rhs.a);
return ret; #endif
} }
static inline CColor operator*(float lhs, const CColor& rhs) static inline CColor operator*(float lhs, const CColor& rhs)
{ {
CColor ret; #if __SSE__
ret.r = Comp8(255 * lhs) * rhs.r; TVectorUnion splat = {{lhs, lhs, lhs, lhs}};
ret.g = Comp8(255 * lhs) * rhs.g; return CColor(_mm_mul_ps(splat.mVec128, rhs.mVec128));
ret.b = Comp8(255 * lhs) * rhs.b; #else
ret.a = Comp8(255 * lhs) * rhs.a; return CColor(lhs * rhs.r, lhs * rhs.g, lhs * rhs.b, lhs * rhs.a);
return ret; #endif
} }
static inline CColor operator/(float lhs, const CColor& rhs) static inline CColor operator/(float lhs, const CColor& rhs)
{ {
CColor ret; #if __SSE__
ret.r = Comp8(255 * lhs) / rhs.r; TVectorUnion splat = {{lhs, lhs, lhs, lhs}};
ret.g = Comp8(255 * lhs) / rhs.g; return CColor(_mm_div_ps(splat.mVec128, rhs.mVec128));
ret.b = Comp8(255 * lhs) / rhs.b; #else
ret.a = Comp8(255 * lhs) / rhs.a; return CColor(lhs / rhs.r, lhs / rhs.g, lhs / rhs.b, lhs / rhs.a);
return ret; #endif
} }
} }
#endif // CCOLOR_HPP #endif // CCOLOR_HPP

View File

@ -46,20 +46,16 @@ void CColor::fromHSV(float h, float s, float v, float _a)
case 5: _r = v, _g = p, _b = q; break; case 5: _r = v, _g = p, _b = q; break;
} }
r = _r * 255; r = _r;
g = _g * 255; g = _g;
b = _b * 255; b = _b;
a = _a * 255; a = _a;
} }
void CColor::toHSV(float &h, float &s, float &v) const void CColor::toHSV(float &h, float &s, float &v) const
{ {
float rf = r/255.f; float min = Math::min(r, Math::min(g, b));
float gf = g/255.f; float max = Math::max(r, Math::max(g, b));
float bf = b/255.f;
float min = Math::min(rf, Math::min(gf, bf));
float max = Math::max(rf, Math::max(gf, bf));
v = max; v = max;
float delta = max - min; float delta = max - min;
@ -69,45 +65,35 @@ void CColor::toHSV(float &h, float &s, float &v) const
h = 0; h = 0;
else else
{ {
if (max == rf) if (max == r)
h = (gf - bf) / delta + (gf < bf ? 6 : 0); h = (g - b) / delta + (g < b ? 6 : 0);
else if (max == gf) else if (max == g)
h = (bf - rf) / delta + 2; h = (b - r) / delta + 2;
else if (max == bf) else if (max == b)
h = (rf - gf) / delta + 4; h = (r - g) / delta + 4;
h /= 6; h /= 6;
} }
} }
void CColor::fromHSL(float h, float s, float l, float _a) void CColor::fromHSL(float h, float s, float l, float _a)
{ {
float _r, _g, _b;
if (s == 0.0f) if (s == 0.0f)
r = g = b = l; r = g = b = l;
else else
{ {
const float q = l < 0.5f ? l * (1.f + s) : l + s - 1.f * s; const float q = l < 0.5f ? l * (1.f + s) : l + s - 1.f * s;
const float p = 2 * l - q; const float p = 2 * l - q;
_r = hueToRgb(p, q, h + 1.f/3); r = hueToRgb(p, q, h + 1.f/3);
_g = hueToRgb(p, q, h); g = hueToRgb(p, q, h);
_b = hueToRgb(p, q, h - 1.f/3); b = hueToRgb(p, q, h - 1.f/3);
} }
a = _a;
r = _r * 255.f;
g = _g * 255.f;
b = _b * 255.f;
a = _a * 255.f;
} }
void CColor::toHSL(float &h, float &s, float &l) void CColor::toHSL(float &h, float &s, float &l)
{ {
const float rf = r / 255.f; const float min = Math::min(r, Math::min(g, b));
const float gf = g / 255.f; const float max = Math::max(r, Math::max(g, b));
const float bf = b / 255.f;
const float min = Math::min(rf, Math::min(gf, bf));
const float max = Math::max(rf, Math::max(gf, bf));
const float d = max - min; const float d = max - min;
if (max == min) if (max == min)
@ -115,12 +101,12 @@ void CColor::toHSL(float &h, float &s, float &l)
else else
{ {
s = l > 0.5f ? d / (2.f - max - min) : d / (max + min); s = l > 0.5f ? d / (2.f - max - min) : d / (max + min);
if (max == rf) if (max == r)
h = (gf - bf) / d + (gf < bf ? 6.f : 0.f); h = (g - b) / d + (g < b ? 6.f : 0.f);
else if (max == gf) else if (max == g)
h = (bf - rf) / d + 2.f; h = (b - r) / d + 2.f;
else if (max == bf) else if (max == b)
h = (rf - gf) / d + 4.f; h = (r - g) / d + 4.f;
h /= 6; h /= 6;
} }