From fc3a625d41c9836881e01af65229d7fd032df1c6 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Sun, 18 Mar 2018 01:34:19 -0400 Subject: [PATCH] Use screen blending with alpha compositing for LightWidget rendering --- include/app.hpp | 5 ++--- include/util/color.hpp | 22 ++++++++++++++++++++++ src/app/LightWidget.cpp | 10 +++++++--- src/app/MultiLightWidget.cpp | 6 +++--- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/include/app.hpp b/include/app.hpp index 03d63c66..08f225c4 100644 --- a/include/app.hpp +++ b/include/app.hpp @@ -408,8 +408,9 @@ struct MidiWidget : LedDisplay { //////////////////// struct LightWidget : TransparentWidget { - NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); + NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); NVGcolor color = nvgRGBA(0, 0, 0, 0); + NVGcolor borderColor = nvgRGBA(0, 0, 0, 0); void draw(NVGcontext *vg) override; virtual void drawLight(NVGcontext *vg); virtual void drawHalo(NVGcontext *vg); @@ -417,8 +418,6 @@ struct LightWidget : TransparentWidget { /** Mixes a list of colors based on a list of brightness values */ struct MultiLightWidget : LightWidget { - /** Color of the "off" state */ - NVGcolor bgColor = nvgRGBA(0, 0, 0, 0); /** Colors of each value state */ std::vector baseColors; void addBaseColor(NVGcolor baseColor); diff --git a/include/util/color.hpp b/include/util/color.hpp index 818671a1..85fc0fbf 100644 --- a/include/util/color.hpp +++ b/include/util/color.hpp @@ -26,11 +26,33 @@ inline NVGcolor colorPlus(NVGcolor a, NVGcolor b) { return a; } +inline NVGcolor colorMult(NVGcolor a, NVGcolor b) { + for (int i = 0; i < 3; i++) + a.rgba[i] *= b.rgba[i]; + return a; +} + inline NVGcolor colorMult(NVGcolor a, float x) { for (int i = 0; i < 3; i++) a.rgba[i] *= x; return a; } +/** Screen blending with alpha compositing */ +inline NVGcolor colorScreen(NVGcolor a, NVGcolor b) { + if (a.a == 0.0) + return b; + if (b.a == 0.0) + return a; + + a = colorMult(a, a.a); + b = colorMult(b, b.a); + NVGcolor c = colorMinus(colorPlus(a, b), colorMult(a, b)); + c.a = a.a + b.a - a.a * b.a; + c = colorMult(c, 1.f / c.a); + c = colorClip(c); + return c; +} + } // namespace rack diff --git a/src/app/LightWidget.cpp b/src/app/LightWidget.cpp index 1300b432..c49c520b 100644 --- a/src/app/LightWidget.cpp +++ b/src/app/LightWidget.cpp @@ -16,7 +16,11 @@ void LightWidget::drawLight(NVGcontext *vg) { nvgBeginPath(vg); nvgCircle(vg, radius, radius, radius); - // Solid color + // Background + nvgFillColor(vg, bgColor); + nvgFill(vg); + + // Foreground nvgFillColor(vg, color); nvgFill(vg); @@ -28,13 +32,13 @@ void LightWidget::drawLight(NVGcontext *vg) { void LightWidget::drawHalo(NVGcontext *vg) { float radius = box.size.x / 2.0; - float oradius = radius + 15.0; + float oradius = radius + 20.0; nvgBeginPath(vg); nvgRect(vg, radius - oradius, radius - oradius, 2*oradius, 2*oradius); NVGpaint paint; - NVGcolor icol = colorMult(color, 0.25); + NVGcolor icol = colorMult(color, 0.10); NVGcolor ocol = nvgRGB(0, 0, 0); paint = nvgRadialGradient(vg, radius, radius, radius, oradius, icol, ocol); nvgFillPaint(vg, paint); diff --git a/src/app/MultiLightWidget.cpp b/src/app/MultiLightWidget.cpp index b91e9d17..7a176748 100644 --- a/src/app/MultiLightWidget.cpp +++ b/src/app/MultiLightWidget.cpp @@ -11,11 +11,11 @@ void MultiLightWidget::addBaseColor(NVGcolor baseColor) { void MultiLightWidget::setValues(const std::vector &values) { assert(values.size() == baseColors.size()); - color = nvgRGBf(0, 0, 0); + color = nvgRGBAf(0, 0, 0, 0); for (size_t i = 0; i < baseColors.size(); i++) { NVGcolor c = baseColors[i]; - c = colorMult(c, values[i]); - color = colorPlus(color, c); + c.a *= clamp(values[i], 0.f, 1.f); + color = colorScreen(color, c); } color = colorClip(color); }