Skip to content

Commit

Permalink
initial nod implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
profezzorn committed Sep 30, 2020
1 parent 1c757d9 commit cf9e561
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 13 deletions.
160 changes: 160 additions & 0 deletions common/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,19 @@ class Color16 {
uint16_t r, g, b;
};

struct SimpleColor {
SimpleColor() {}
SimpleColor(const Color16 &c_) : c(c_) {}
Color16 c;
void printTo(Print& p) {
c.printTo(p);
}
};

struct OverDriveColor {
OverDriveColor() {}
OverDriveColor(const Color16 &c_, bool o) : c(c_), overdrive(o) {}
OverDriveColor(const SimpleColor &c_) : c(c_.c), overdrive(false) {}
Color16 c;
bool overdrive;

Expand All @@ -304,6 +314,7 @@ struct OverDriveColor {
}
};


// SIMPLE
// Opaque.fade -> Opaque or Alpha?
// Alpha.fade -> Alpha
Expand Down Expand Up @@ -338,10 +349,27 @@ inline Color16 operator+(const Color16& a, const Color16 &b) {
return Color16(a.r + b.r, a.g + b.g, a.b + b.b);
}

// Unmultiplied RGBA (no overdrive), used as a temporary and makes optimization easier.
struct RGBA_um_nod {
constexpr RGBA_um_nod(Color16 c_, uint16_t a) : c(c_), alpha(a) {}
constexpr RGBA_um_nod(const SimpleColor& c_) : c(c_.c), alpha(32768) {}
static RGBA_um_nod Transparent() { return RGBA_um_nod(Color16(), 0); }
Color16 c;
uint16_t alpha;

void printTo(Print& p) {
c.printTo(p);
p.write(',');
p.print(alpha);
}
};

// Unmultiplied RGBA, used as a temporary and makes optimization easier.
struct RGBA_um {
constexpr RGBA_um(Color16 c_, bool od, uint16_t a) : c(c_), alpha(a), overdrive(od) {}
constexpr RGBA_um(const RGBA_um_nod& o) : c(o.c), alpha(32768), overdrive(false) {}
constexpr RGBA_um(const OverDriveColor& o) : c(o.c), alpha(32768), overdrive(o.overdrive) {}
constexpr RGBA_um(const SimpleColor& o) : c(o.c), alpha(32768), overdrive(false) {}
static RGBA_um Transparent() { return RGBA_um(Color16(), false, 0); }
Color16 c;
uint16_t alpha;
Expand All @@ -355,11 +383,28 @@ struct RGBA_um {
}
};

// Premultiplied ALPHA, no overdrive
struct RGBA_nod {
constexpr RGBA_nod(Color16 c_, uint16_t a) : c(c_), alpha(a) {}
RGBA_nod(const RGBA_um_nod& rgba) : c(rgba.c * rgba.alpha >> 15), alpha(rgba.alpha) {}
RGBA_nod(const SimpleColor& o) : c(o.c), alpha(32768) {}
Color16 c;
uint16_t alpha;
void printTo(Print& p) {
c.printTo(p);
p.write('*');
p.print(alpha);
}
};

// Premultiplied ALPHA
struct RGBA {
constexpr RGBA(Color16 c_, bool od, uint16_t a) : c(c_), alpha(a), overdrive(od) {}
RGBA(const RGBA_nod& rgba) : c(rgba.c * rgba.alpha >> 15), alpha(rgba.alpha), overdrive(false) {}
RGBA(const RGBA_um& rgba) : c(rgba.c * rgba.alpha >> 15), alpha(rgba.alpha), overdrive(rgba.overdrive) {}
RGBA(const RGBA_um_nod& rgba) : c(rgba.c * rgba.alpha >> 15), alpha(rgba.alpha), overdrive(false) {}
RGBA(const OverDriveColor& o) : c(o.c), alpha(32768), overdrive(o.overdrive) {}
RGBA(const SimpleColor& o) : c(o.c), alpha(32768), overdrive(false) {}
Color16 c;
uint16_t alpha;
bool overdrive;
Expand All @@ -371,6 +416,10 @@ struct RGBA {
}
};

inline RGBA_um_nod operator*(const SimpleColor& a, uint16_t x) {
return RGBA_um_nod(a.c, x);
}

inline RGBA_um operator*(const OverDriveColor& a, uint16_t x) {
return RGBA_um(a.c, a.overdrive, x);
}
Expand All @@ -379,29 +428,86 @@ inline RGBA_um operator*(const RGBA_um& a, uint16_t x) {
return RGBA_um(a.c, a.overdrive, a.alpha * x >> 15);
}

inline RGBA_um_nod operator*(const RGBA_um_nod& a, uint16_t x) {
return RGBA_um_nod(a.c, a.alpha * x >> 15);
}

inline RGBA_nod operator*(const RGBA_nod& a, uint16_t x) {
return RGBA_nod(a.c * x >> 15, (a.alpha * x + 0x7fff) >> 15);
}

inline RGBA operator*(const RGBA& a, uint16_t x) {
return RGBA(a.c * x >> 15, a.overdrive, (a.alpha * x + 0x7fff) >> 15);
}

inline SimpleColor MixColors(SimpleColor a, SimpleColor b, int x, int shift) {
return SimpleColor((a.c * ((1 << shift) - x) + b.c * x) >> shift);
}

inline OverDriveColor MixColors(OverDriveColor a, OverDriveColor b, int x, int shift) {
return OverDriveColor( (a.c * ((1 << shift) - x) + b.c * x) >> shift,
x > (1 << (shift - 1)) ? b.overdrive : a.overdrive);
}
inline RGBA_nod MixColors(RGBA_nod a, RGBA_nod b, int x, int shift) {
return RGBA_nod( (a.c * ((1 << shift) - x) + b.c * x) >> shift,
(a.alpha * ((1 << shift) - x) + b.alpha * x + ((1<<shift) - 1)) >> shift);
}
inline RGBA MixColors(RGBA a, RGBA b, int x, int shift) {
return RGBA( (a.c * ((1 << shift) - x) + b.c * x) >> shift,
x > (1 << (shift - 1)) ? b.overdrive : a.overdrive,
(a.alpha * ((1 << shift) - x) + b.alpha * x + ((1<<shift) - 1)) >> shift);
}

#define OverDriveColor_nod SimpleColor

#define DISAMBIGUATE_MIXCOLORS1(A, B, C) \
inline auto MixColors(A a, B b, int x, int shift) -> decltype(MixColors(C(a), C(b), x, shift)) { return MixColors(C(a), C(b), x, shift); }
#define DISAMBIGUATE_MIXCOLORS2(A, B, C) \
DISAMBIGUATE_MIXCOLORS1(A##_nod, B, C) \
DISAMBIGUATE_MIXCOLORS1(A, B##_nod, C)

#define DISAMBIGUATE_MIXCOLORS3(A, B, C) \
DISAMBIGUATE_MIXCOLORS1(A, B, C) \
DISAMBIGUATE_MIXCOLORS2(A, B, C)

DISAMBIGUATE_MIXCOLORS2(OverDriveColor, OverDriveColor, OverDriveColor)
DISAMBIGUATE_MIXCOLORS3(OverDriveColor, RGBA_um, RGBA_um)
DISAMBIGUATE_MIXCOLORS3(OverDriveColor, RGBA, RGBA)
DISAMBIGUATE_MIXCOLORS3(RGBA_um, OverDriveColor, RGBA)
DISAMBIGUATE_MIXCOLORS3(RGBA_um, RGBA_um, RGBA)
DISAMBIGUATE_MIXCOLORS3(RGBA_um, RGBA, RGBA)
DISAMBIGUATE_MIXCOLORS3(RGBA, OverDriveColor, RGBA)
DISAMBIGUATE_MIXCOLORS3(RGBA, RGBA_um, RGBA)
DISAMBIGUATE_MIXCOLORS2(RGBA, RGBA, RGBA)

DISAMBIGUATE_MIXCOLORS1(RGBA_um_nod, SimpleColor, RGBA_nod)
DISAMBIGUATE_MIXCOLORS1(RGBA_nod, SimpleColor, RGBA_nod)
DISAMBIGUATE_MIXCOLORS1(SimpleColor, RGBA_um_nod, RGBA_nod)
DISAMBIGUATE_MIXCOLORS1(SimpleColor, RGBA_nod, RGBA_nod)
DISAMBIGUATE_MIXCOLORS1(RGBA_um_nod, RGBA_um_nod, RGBA_nod)

// Paint over operators
// There is probably a better way to do this.
inline SimpleColor operator<<(const SimpleColor& base, const RGBA_um_nod& over) {
SCOPED_PROFILER();
if (!over.alpha) return base;
return SimpleColor((base.c * (32768 - over.alpha) + over.c * over.alpha) >> 15);
}

inline OverDriveColor operator<<(const OverDriveColor& base, const RGBA_um& over) {
SCOPED_PROFILER();
if (!over.alpha) return base;
uint16_t ac = 32768 - over.alpha;
return OverDriveColor((base.c * ac + over.c * over.alpha) >> 15,
over.alpha >= 16384 ? over.overdrive : base.overdrive);
}

inline SimpleColor operator<<(const SimpleColor& base, const RGBA_nod& over) {
SCOPED_PROFILER();
if (!over.alpha) return base;
return (base.c * (32768 - over.alpha) >> 15) + over.c;
}

inline OverDriveColor operator<<(const OverDriveColor& base, const RGBA& over) {
SCOPED_PROFILER();
if (!over.alpha) return base;
Expand All @@ -410,6 +516,14 @@ inline OverDriveColor operator<<(const OverDriveColor& base, const RGBA& over) {
over.alpha >= 16384 ? over.overdrive : base.overdrive);
}

inline RGBA_nod operator<<(const RGBA_um_nod& base, const RGBA_um_nod& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
uint16_t ac = 32768 - over.alpha;
return RGBA_nod((base.c * (base.alpha * ac >> 15) + over.c * over.alpha) >> 15,
(base.alpha * ac >> 15) + over.alpha);
}

inline RGBA operator<<(const RGBA_um& base, const RGBA_um& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
Expand All @@ -419,6 +533,14 @@ inline RGBA operator<<(const RGBA_um& base, const RGBA_um& over) {
(base.alpha * ac >> 15) + over.alpha);
}

inline RGBA_nod operator<<(const RGBA_um_nod& base, const RGBA_nod& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
uint16_t ac = 32768 - over.alpha;
return RGBA_nod((base.c * (base.alpha * ac >> 15) >> 15) + over.c,
(base.alpha * ac >> 15) + over.alpha);
}

inline RGBA operator<<(const RGBA_um& base, const RGBA& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
Expand All @@ -428,6 +550,14 @@ inline RGBA operator<<(const RGBA_um& base, const RGBA& over) {
(base.alpha * ac >> 15) + over.alpha);
}

inline RGBA_nod operator<<(const RGBA_nod& base, const RGBA_um_nod& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
uint16_t ac = 32768 - over.alpha;
return RGBA_nod((base.c * ac + over.c * over.alpha) >> 15,
((base.alpha * ac + 0x7fff) >> 15) + over.alpha);
}

inline RGBA operator<<(const RGBA& base, const RGBA_um& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
Expand All @@ -437,6 +567,14 @@ inline RGBA operator<<(const RGBA& base, const RGBA_um& over) {
((base.alpha * ac + 0x7fff) >> 15) + over.alpha);
}

inline RGBA_nod operator<<(const RGBA_nod& base, const RGBA_nod& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
uint16_t ac = 32768 - over.alpha;
return RGBA_nod((base.c * ac >> 15) + over.c,
((base.alpha * ac + 0x7fff) >> 15) + over.alpha);
}

inline RGBA operator<<(const RGBA& base, const RGBA& over) {
SCOPED_PROFILER();
// if (!over.alpha) return base;
Expand All @@ -446,4 +584,26 @@ inline RGBA operator<<(const RGBA& base, const RGBA& over) {
((base.alpha * ac + 0x7fff) >> 15) + over.alpha);
}


// Disambiguation
#define DISAMBIGUATE_OVER(A, B) \
inline auto operator<<(const A##_nod & base, const B & over) ->decltype(A(base) << over) { return A(base) << over; } \
inline auto operator<<(const A & base, const B##_nod & over) ->decltype(base << B(over)) { return base << B(over); }

#define DISAMBIGUATE_OVER2(A) \
DISAMBIGUATE_OVER(OverDriveColor, A) \
DISAMBIGUATE_OVER(RGBA_um, A) \
DISAMBIGUATE_OVER(RGBA, A)

DISAMBIGUATE_OVER2(RGBA_um)
DISAMBIGUATE_OVER2(RGBA)

#define MAKE_OVERDRIVE(A) \
inline A OverDrive(A a) { a.overdrive = true; return a; } \
inline A OverDrive(A##_nod a) { return OverDrive(A(a)); }

MAKE_OVERDRIVE(OverDriveColor)
MAKE_OVERDRIVE(RGBA_um)
MAKE_OVERDRIVE(RGBA)

#endif
2 changes: 1 addition & 1 deletion styles/alpha.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class AlphaL {
auto getColor(int led) -> decltype(color_.getColor(led) * alpha_.getInteger(led)) {
// SCOPED_PROFILER();
int alpha = alpha_.getInteger(led);
if (alpha == 0) return RGBA_um::Transparent();
if (alpha == 0) return RGBA_um_nod::Transparent();
return color_.getColor(led) * alpha; // clamp?
}
};
Expand Down
9 changes: 4 additions & 5 deletions styles/clash.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,10 @@ class SimpleClashL {
CLASH_COLOR clash_color_;
STAB_SHAPE stab_shape_;
public:
auto getColor(int led) -> decltype(clash_color_.getColor(led) * stab_shape_.getInteger(led)) {
decltype(clash_color_.getColor(led) * stab_shape_.getInteger(led)) ret(Color16(), false, 0);
auto getColor(int led) -> decltype(OverDrive(clash_color_.getColor(led) * stab_shape_.getInteger(led))) {
decltype(OverDrive(clash_color_.getColor(led) * stab_shape_.getInteger(led))) ret = RGBA_um_nod::Transparent();
if (clash_) {
ret = clash_color_.getColor(led);
ret.overdrive = true;
ret = OverDrive(clash_color_.getColor(led));
if (stab_) {
ret = ret * stab_shape_.getInteger(led);
}
Expand Down Expand Up @@ -104,7 +103,7 @@ class LocalizedClashL {
CLASH_COLOR clash_color_;
public:
auto getColor(int led) -> decltype(clash_color_.getColor(led) * 1) {
decltype(clash_color_.getColor(led) * 1) ret(Color16(), false, 0);
decltype(clash_color_.getColor(led) * 1) ret = RGBA_um_nod::Transparent();
if (clash_) {
uint32_t dist = abs(led * mult_ - clash_location_) / 1024;
if (dist < NELEM(clash_hump)) {
Expand Down
7 changes: 2 additions & 5 deletions styles/rgb.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,8 @@ class Rgb {
if (R == 0 && G == 0 && B == 0) return LayerRunResult::OPAQUE_BLACK_UNTIL_IGNITION;
return LayerRunResult::UNKNOWN;
}
OverDriveColor getColor(int led) {
OverDriveColor ret;
ret.c = color();
ret.overdrive = false;
return ret;
SimpleColor getColor(int led) {
return SimpleColor(color());
}
};

Expand Down
4 changes: 2 additions & 2 deletions styles/transition_effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ void run(BladeBase* blade) {
for (int i = N - 1; i >= 0; i--) {
size_t x = (i + pos_) % N;
if (run_[x]) {
ret = ret << transitions_[x].getColor(RGBA_um::Transparent(),
RGBA_um::Transparent(), led);
ret = ret << transitions_[x].getColor(RGBA_um_nod::Transparent(),
RGBA_um_nod::Transparent(), led);
}
}
return ret;
Expand Down

0 comments on commit cf9e561

Please sign in to comment.