Browse Source

Use screen blending with alpha compositing for LightWidget rendering

tags/v0.6.0
Andrew Belt 6 years ago
parent
commit
ec52f1f121
4 changed files with 34 additions and 9 deletions
  1. +2
    -3
      include/app.hpp
  2. +22
    -0
      include/util/color.hpp
  3. +7
    -3
      src/app/LightWidget.cpp
  4. +3
    -3
      src/app/MultiLightWidget.cpp

+ 2
- 3
include/app.hpp View File

@@ -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<NVGcolor> baseColors;
void addBaseColor(NVGcolor baseColor);


+ 22
- 0
include/util/color.hpp View File

@@ -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

+ 7
- 3
src/app/LightWidget.cpp View File

@@ -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);


+ 3
- 3
src/app/MultiLightWidget.cpp View File

@@ -11,11 +11,11 @@ void MultiLightWidget::addBaseColor(NVGcolor baseColor) {

void MultiLightWidget::setValues(const std::vector<float> &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);
}


Loading…
Cancel
Save