Enhancement in effect functions.

- added color_add()
- fixed AA setPixelColor()
- added fadeToBlackBy() (FastLED)
- added hiding of * palettes if not all color selectors shown
This commit is contained in:
Blaz Kristan 2022-06-17 18:57:32 +02:00
parent 0df5221784
commit b00e038b33
7 changed files with 1889 additions and 1809 deletions

View File

@ -3976,7 +3976,7 @@ uint16_t WS2812FX::mode_chunchun(void)
{ {
counter -= span; counter -= span;
uint16_t megumin = sin16(counter) + 0x8000; uint16_t megumin = sin16(counter) + 0x8000;
uint32_t bird = (megumin * SEGLEN) >> 16; uint16_t bird = uint32_t(megumin * SEGLEN) >> 16;
uint32_t c = color_from_palette((i * 255)/ numBirds, false, false, 0); // no palette wrapping uint32_t c = color_from_palette((i * 255)/ numBirds, false, false, 0); // no palette wrapping
setPixelColor(bird, c); setPixelColor(bird, c);
} }

View File

@ -683,6 +683,7 @@ class WS2812FX {
blur(uint8_t), blur(uint8_t),
fill(uint32_t), fill(uint32_t),
fade_out(uint8_t r), fade_out(uint8_t r),
fadeToBlackBy(uint8_t fadeBy),
setMode(uint8_t segid, uint8_t m), setMode(uint8_t segid, uint8_t m),
setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setColor(uint8_t slot, uint32_t c), setColor(uint8_t slot, uint32_t c),
@ -701,12 +702,18 @@ class WS2812FX {
makeAutoSegments(bool forceReset = false), makeAutoSegments(bool forceReset = false),
fixInvalidSegments(), fixInvalidSegments(),
setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0),
setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = false),
show(void), show(void),
setTargetFps(uint8_t fps), setTargetFps(uint8_t fps),
deserializeMap(uint8_t n=0); deserializeMap(uint8_t n=0);
inline void setPixelColor(uint16_t n, uint32_t c) {setPixelColor(n, byte(c>>16), byte(c>>8), byte(c), byte(c>>24));} // satisfy compiler by providing multiple casts
inline void setPixelColor(uint16_t n, CRGB &c) {setPixelColor(n, c.red, c.green, c.blue);} inline void setPixelColor(int n, uint32_t c) {setPixelColor(n, byte(c>>16), byte(c>>8), byte(c), byte(c>>24));}
inline void setPixelColor(int n, byte r, byte g, byte b, byte w = 0) {setPixelColor(n, r, g, b, w);}
inline void setPixelColor(uint16_t n, uint32_t c) {setPixelColor(n, byte(c>>16), byte(c>>8), byte(c), byte(c>>24));}
inline void setPixelColor(uint16_t n, CRGB c) {setPixelColor(n, c.red, c.green, c.blue);}
inline void setPixelColor(float i, uint32_t c, bool aa = false) {setPixelColor(i, byte(c>>16), byte(c>>8), byte(c), byte(c>>24), aa);}
inline void setPixelColor(float i, CRGB c, bool aa = false) {setPixelColor(i, c.red, c.green, c.blue, 0, aa);}
bool bool
gammaCorrectBri = false, gammaCorrectBri = false,
@ -752,12 +759,15 @@ class WS2812FX {
getLengthPhysical(void), getLengthPhysical(void),
getFps(); getFps();
inline uint16_t getMinShowDelay() { return MIN_SHOW_DELAY; }
uint32_t uint32_t
now, now,
timebase, timebase,
color_wheel(uint8_t), color_wheel(uint8_t),
color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255), color_from_palette(uint16_t, bool mapping, bool wrap, uint8_t mcol, uint8_t pbri = 255),
color_blend(uint32_t,uint32_t,uint16_t,bool b16=false), color_blend(uint32_t,uint32_t,uint16_t,bool b16=false),
color_add(uint32_t,uint32_t),
currentColor(uint32_t colorNew, uint8_t tNr), currentColor(uint32_t colorNew, uint8_t tNr),
gamma32(uint32_t), gamma32(uint32_t),
getLastShow(void), getLastShow(void),
@ -956,36 +966,36 @@ class WS2812FX {
getPixelColorXY(uint16_t, uint16_t); getPixelColorXY(uint16_t, uint16_t);
// 2D modes // 2D modes
uint16_t uint16_t
mode_2DBlackHole(void), mode_2DBlackHole(void),
mode_2DColoredBursts(void), mode_2DColoredBursts(void),
mode_2Ddna(void), mode_2Ddna(void),
mode_2DDNASpiral(void), mode_2DDNASpiral(void),
mode_2DDrift(void), mode_2DDrift(void),
mode_2Dfirenoise(void), mode_2Dfirenoise(void),
mode_2DFrizzles(void), mode_2DFrizzles(void),
mode_2Dgameoflife(void), mode_2Dgameoflife(void),
mode_2DHiphotic(void), mode_2DHiphotic(void),
mode_2DJulia(void), mode_2DJulia(void),
mode_2DLissajous(void), mode_2DLissajous(void),
mode_2Dmatrix(void), mode_2Dmatrix(void),
mode_2Dmetaballs(void), mode_2Dmetaballs(void),
mode_2Dnoise(void), mode_2Dnoise(void),
mode_2DPlasmaball(void), mode_2DPlasmaball(void),
mode_2DPolarLights(void), mode_2DPolarLights(void),
mode_2DPulser(void), mode_2DPulser(void),
mode_2DSindots(void), mode_2DSindots(void),
mode_2Dsquaredswirl(void), mode_2Dsquaredswirl(void),
mode_2DSunradiation(void), mode_2DSunradiation(void),
mode_2Dtartan(void), mode_2Dtartan(void),
mode_2DWaverly(void), mode_2DWaverly(void),
mode_2DAkemi(void), mode_2DAkemi(void),
mode_2Dspaceships(void), mode_2Dspaceships(void),
mode_2Dcrazybees(void), mode_2Dcrazybees(void),
mode_2Dghostrider(void), mode_2Dghostrider(void),
mode_2Dfloatingblobs(void), mode_2Dfloatingblobs(void),
mode_2Dscrollingtext(void), mode_2Dscrollingtext(void),
mode_2Ddriftrose(void); mode_2Ddriftrose(void);
// end 2D support // end 2D support

View File

@ -193,10 +193,16 @@ void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(float x, float y, byte r, byte g, b
const uint16_t rows = SEGMENT.virtualHeight(); const uint16_t rows = SEGMENT.virtualHeight();
if (aa) { if (aa) {
uint16_t xL = floorf(x * (cols-1)); float fX = x * (cols-1);
uint16_t xR = ceilf(x * (cols-1)); float fL = floorf(x * (cols-1));
uint16_t yT = floorf(y * (rows-1)); float fR = ceilf(x * (cols-1));
uint16_t yB = ceilf(y * (rows-1)); float fY = y * (rows-1);
float fT = floorf(y * (rows-1));
float fB = ceilf(y * (rows-1));
uint16_t xL = fL;
uint16_t xR = fR;
uint16_t yT = fT;
uint16_t yB = fB;
uint32_t cXLYT = getPixelColorXY(xL, yT); uint32_t cXLYT = getPixelColorXY(xL, yT);
uint32_t cXRYT = getPixelColorXY(xR, yT); uint32_t cXRYT = getPixelColorXY(xR, yT);
uint32_t cXLYB = getPixelColorXY(xL, yB); uint32_t cXLYB = getPixelColorXY(xL, yB);
@ -204,30 +210,30 @@ void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(float x, float y, byte r, byte g, b
if (xL!=xR && yT!=yB) { if (xL!=xR && yT!=yB) {
// blend TL pixel // blend TL pixel
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, sqrtf((x - floor(x))*(y - floorf(y)))*UINT16_MAX, true); cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, sqrtf((fR - fX)*(fB - fY))*UINT16_MAX, true);
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT)); setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
// blend TR pixel // blend TR pixel
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, sqrtf((ceilf(x) - x)*(y - floorf(y)))*UINT16_MAX, true); cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, sqrtf((fX - fL)*(fB - fY))*UINT16_MAX, true);
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT)); setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
// blend BL pixel // blend BL pixel
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, sqrtf((x - floor(x))*(ceil(y) - y))*UINT16_MAX, true); cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, sqrtf((fR - fX)*(fY - fT))*UINT16_MAX, true);
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB)); setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
// blend BR pixel // blend BR pixel
cXRYB = color_blend(RGBW32(r,g,b,w), cXRYB, sqrtf((ceilf(x) - x)*(ceil(y) - y))*UINT16_MAX, true); cXRYB = color_blend(RGBW32(r,g,b,w), cXRYB, sqrtf((fX - fL)*(fY - fT))*UINT16_MAX, true);
setPixelColorXY(xR, yB, R(cXRYB), G(cXRYB), B(cXRYB), W(cXRYB)); setPixelColorXY(xR, yB, R(cXRYB), G(cXRYB), B(cXRYB), W(cXRYB));
} else if (xR!=xL && yT==yB) { } else if (xR!=xL && yT==yB) {
// blend L pixel // blend L pixel
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (x - floor(x))*UINT16_MAX, true); cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (fR - fX)*UINT16_MAX, true);
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT)); setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
// blend R pixel // blend R pixel
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, (ceilf(x) - x)*UINT16_MAX, true); cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, (fX - fL)*UINT16_MAX, true);
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT)); setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
} else if (xR==xL && yT!=yB) { } else if (xR==xL && yT!=yB) {
// blend T pixel // blend T pixel
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (y - floorf(y))*UINT16_MAX, true); cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, (fB - fY)*UINT16_MAX, true);
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT)); setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
// blend B pixel // blend B pixel
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, (ceil(y) - y)*UINT16_MAX, true); cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, (fY - fT)*UINT16_MAX, true);
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB)); setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
} else { } else {
// exact match (x & y land on a pixel) // exact match (x & y land on a pixel)

View File

@ -182,6 +182,35 @@ void WS2812FX::service() {
_triggered = false; _triggered = false;
} }
// anti-aliased normalized version of setPixelColor()
void /*IRAM_ATTR*/ WS2812FX::setPixelColor(float i, byte r, byte g, byte b, byte w, bool aa)
{
if (i<0.0f || i>1.0f) return; // not normalized
if (aa) {
float fC = i * (SEGLEN-1);
float fL = floorf(i * (SEGLEN-1));
float fR = ceilf(i * (SEGLEN-1));
uint16_t iL = fL;
uint16_t iR = fR;
uint32_t cIL = getPixelColor(iL);
uint32_t cIR = getPixelColor(iR);
if (iR!=iL) {
// blend L pixel
cIL = color_blend(RGBW32(r,g,b,w), cIL, (fR - fC)*UINT16_MAX, true);
setPixelColor(iL, R(cIL), G(cIL), B(cIL), W(cIL));
// blend R pixel
cIR = color_blend(RGBW32(r,g,b,w), cIR, (fC - fL)*UINT16_MAX, true);
setPixelColor(iR, R(cIR), G(cIR), B(cIR), W(cIR));
} else {
// exact match (x & y land on a pixel)
setPixelColor(iL, r, g, b, w);
}
} else {
setPixelColor((uint16_t)roundf(i * (SEGLEN-1)), r, g, b, w);
}
}
void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w) void IRAM_ATTR WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
{ {
uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment; uint8_t segIdx = SEGLEN ? _segment_index : _mainSegment;
@ -887,6 +916,24 @@ uint32_t IRAM_ATTR WS2812FX::color_blend(uint32_t color1, uint32_t color2, uint1
return RGBW32(r3, g3, b3, w3); return RGBW32(r3, g3, b3, w3);
} }
/*
* color add function that preserves ratio
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
*/
uint32_t WS2812FX::color_add(uint32_t c1, uint32_t c2)
{
uint32_t r = R(c1) + R(c2);
uint32_t g = G(c1) + G(c2);
uint32_t b = B(c1) + B(c2);
uint32_t w = W(c1) + W(c2);
uint16_t max = r;
if (g > max) max = g;
if (b > max) max = b;
if (w > max) max = w;
if (max < 256) return RGBW32(r, g, b, w);
else return RGBW32(r * 255 / max, g * 255 / max, b * 255 / max, w * 255 / max);
}
/* /*
* Fills segment with color * Fills segment with color
*/ */
@ -946,6 +993,13 @@ void WS2812FX::fade_out(uint8_t rate) {
} }
} }
// fades all pixels to black using nscale8()
void WS2812FX::fadeToBlackBy(uint8_t fadeBy) {
for (uint16_t i = 0; i < SEGLEN; i++) {
setPixelColor(i, col_to_crgb(getPixelColor(i)).nscale8(255-fadeBy));
}
}
/* /*
* blurs segment content, source: FastLED colorutils.cpp * blurs segment content, source: FastLED colorutils.cpp
*/ */

View File

@ -1328,6 +1328,7 @@ function setSliderAndColorControl(idx, applyDef=false)
var cslLabel = ''; var cslLabel = '';
var sep = ''; var sep = '';
var hide = true; var hide = true;
var cslCnt = 0;
for (let i=0; i<gId("csl").children.length; i++) { for (let i=0; i<gId("csl").children.length; i++) {
var btn = gId("csl" + i); var btn = gId("csl" + i);
// if no controlDefined or coOnOff has a value // if no controlDefined or coOnOff has a value
@ -1345,10 +1346,12 @@ function setSliderAndColorControl(idx, applyDef=false)
else if (i==1) btn.innerHTML = "Bg"; else if (i==1) btn.innerHTML = "Bg";
else btn.innerHTML = "Cs"; else btn.innerHTML = "Cs";
hide = false; hide = false;
cslCnt++;
} else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3 } else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3
btn.style.display = "inline"; btn.style.display = "inline";
btn.innerHTML = `${i+1}`; btn.innerHTML = `${i+1}`;
hide = false; hide = false;
cslCnt++;
} else { } else {
btn.style.display = "none"; btn.style.display = "none";
if (i>0 && csel==i) selectSlot(0); if (i>0 && csel==i) selectSlot(0);
@ -1382,6 +1385,10 @@ function setSliderAndColorControl(idx, applyDef=false)
// if numeric set as selected palette // if numeric set as selected palette
if (paOnOff.length>0 && paOnOff[0]!="" && !isNaN(paOnOff[0]) && parseInt(paOnOff[0])!=selectedPal) obj.seg.pal = parseInt(paOnOff[0]); if (paOnOff.length>0 && paOnOff[0]!="" && !isNaN(paOnOff[0]) && parseInt(paOnOff[0])!=selectedPal) obj.seg.pal = parseInt(paOnOff[0]);
} }
// not all color selectors shown, hide palettes created from color selectors
for (let e of (gId('pallist').querySelectorAll('.lstI')||[])) {
if (cslCnt < 3 && e.querySelector('.lstIname').innerText.indexOf("* ")>=0) e.classList.add('hide'); else e.classList.remove('hide');
}
if (!isEmpty(obj.seg) && applyDef) requestJson(obj); // update default values (may need throttling on ESP8266) if (!isEmpty(obj.seg) && applyDef) requestJson(obj); // update default values (may need throttling on ESP8266)
} }

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
*/ */
// version code in format yymmddb (b = daily build) // version code in format yymmddb (b = daily build)
#define VERSION 2206051 #define VERSION 2206171
//uncomment this if you have a "my_config.h" file you'd like to use //uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG //#define WLED_USE_MY_CONFIG