Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effect blending styles (recreated PR from #3877) #4158

Merged
merged 34 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
0c8d9d5
Mode blending styles
blazoncek Apr 3, 2024
f5199d2
Fix compile.
blazoncek Apr 3, 2024
c680527
Merge branch '0_15' into blending-styles
blazoncek Apr 8, 2024
a3a8fa1
Remove conditional fade/blend
blazoncek Apr 8, 2024
b3810a1
Merge branch '0_15' into blending-styles
blazoncek Apr 9, 2024
ef017fd
Revert FX.cpp
blazoncek Apr 14, 2024
9735d1c
Merge branch '0_15' into blending-styles
blazoncek Apr 14, 2024
8e8ffa3
Merge branch '0_15' into blending-styles
blazoncek Apr 26, 2024
f441ce9
Merge branch '0_15' into blending-styles
blazoncek May 12, 2024
ccce0f2
Merge branch '0_15' into blending-styles
blazoncek May 15, 2024
de5632b
Merge branch '0_15' into blending-styles
blazoncek Jun 1, 2024
20c0916
Merge branch '0_15' into blending-styles
blazoncek Jun 2, 2024
da484b0
Use transition style for palette and color change
blazoncek Jun 2, 2024
296df26
Merge branch '0_15' into blending-styles
blazoncek Jun 16, 2024
a4ac444
Merge branch '0_15' into blending-styles
blazoncek Jun 23, 2024
bee75a4
Hide 2D blending styles on non-2D set-up
blazoncek Jun 23, 2024
593970e
Merge branch '0_15' into blending-styles
blazoncek Jun 30, 2024
f3891c3
Merge branch '0_15' into blending-styles
blazoncek Jul 5, 2024
0275bd1
On/Off blending respected
blazoncek Jul 5, 2024
13ed78b
Merge branch '0_15' into blending-styles
blazoncek Jul 11, 2024
d88bb3c
Merge branch '0_15' into blending-styles
blazoncek Jul 18, 2024
1975c9c
Merge branch '0_15' into blending-styles
blazoncek Jul 24, 2024
c03422e
Push variants
blazoncek Jul 30, 2024
365c198
Missing clipping fix
blazoncek Aug 1, 2024
e1598a9
Merge branch '0_15' into blending-styles
blazoncek Aug 5, 2024
77723b6
Fix compiler warning
blazoncek Aug 8, 2024
011afd0
Merge branch '0_15' into blending-styles
blazoncek Aug 17, 2024
0430dc5
Merge branch '0_15' into blending-styles
blazoncek Aug 17, 2024
ebd8a10
Prevent styles on 1px segments
blazoncek Sep 3, 2024
1cee1c3
Merge branch '0_15' into blending-styles
blazoncek Sep 11, 2024
ce5ee65
Merge branch '0_15' into blending-styles
blazoncek Sep 15, 2024
fafb2eb
Merge branch '0_15' into blending-styles
blazoncek Sep 23, 2024
a65f97a
Merge branch 'main' into blending-styles
blazoncek Jan 14, 2025
3a426e2
Merge branch 'main' into blending-styles
blazoncek Jan 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
- v0.15.0-b2
- WS2805 support (RGB + WW + CW, 600kbps)
- Unified PSRAM use
- NeoPixelBus v2.7.9
- NeoPixelBus v2.7.9 (for future WS2805 support)
- Ubiquitous PSRAM mode for all variants of ESP32
- SSD1309_64 I2C Support for FLD Usermod (#3836 by @THATDONFC)
- Palette cycling fix (add support for `{"seg":[{"pal":"X~Y~"}]}` or `{"seg":[{"pal":"X~Yr"}]}`)
Expand Down
111 changes: 0 additions & 111 deletions usermods/stairway_wipe_basic/wled06_usermod.ino

This file was deleted.

40 changes: 35 additions & 5 deletions wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,30 @@ extern byte realtimeMode; // used in getMappedPixelIndex()

#define MODE_COUNT 187


#define BLEND_STYLE_FADE 0x00 // universal
#define BLEND_STYLE_FAIRY_DUST 0x01 // universal
#define BLEND_STYLE_SWIPE_RIGHT 0x02 // 1D or 2D
#define BLEND_STYLE_SWIPE_LEFT 0x03 // 1D or 2D
#define BLEND_STYLE_PINCH_OUT 0x04 // 1D or 2D
#define BLEND_STYLE_INSIDE_OUT 0x05 // 1D or 2D
#define BLEND_STYLE_SWIPE_UP 0x06 // 2D
#define BLEND_STYLE_SWIPE_DOWN 0x07 // 2D
#define BLEND_STYLE_OPEN_H 0x08 // 2D
#define BLEND_STYLE_OPEN_V 0x09 // 2D
// as there are many push variants to optimise if statements they are groupped together
#define BLEND_STYLE_PUSH_RIGHT 0x10 // 1D or 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_LEFT 0x11 // 1D or 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_UP 0x12 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_DOWN 0x13 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_TL 0x14 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_TR 0x15 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_BR 0x16 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_BL 0x17 // 2D (& 0b00010000)
#define BLEND_STYLE_PUSH_MASK 0x10
#define BLEND_STYLE_COUNT 18


typedef enum mapping1D2D {
M12_Pixels = 0,
M12_pBar = 1,
Expand All @@ -333,7 +357,7 @@ typedef enum mapping1D2D {
M12_sPinwheel = 4
} mapping1D2D_t;

// segment, 80 bytes
// segment, 68 bytes
typedef struct Segment {
public:
uint16_t start; // start index / start X coordinate 2D (left)
Expand Down Expand Up @@ -436,6 +460,9 @@ typedef struct Segment {
static uint16_t _transitionprogress; // current transition progress 0 - 0xFFFF
#ifndef WLED_DISABLE_MODE_BLEND
static bool _modeBlend; // mode/effect blending semaphore
// clipping
static uint16_t _clipStart, _clipStop;
static uint8_t _clipStartY, _clipStopY;
#endif

// transition data, valid only if transitional==true, holds values during transition (72 bytes)
Expand All @@ -446,6 +473,7 @@ typedef struct Segment {
#else
uint32_t _colorT[NUM_COLORS];
#endif
uint8_t _palTid; // previous palette
uint8_t _briT; // temporary brightness
uint8_t _cctT; // temporary CCT
CRGBPalette16 _palT; // temporary palette
Expand Down Expand Up @@ -607,6 +635,10 @@ typedef struct Segment {
inline void setPixelColor(float i, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0, bool aa = true) const { setPixelColor(i, RGBW32(r,g,b,w), aa); }
inline void setPixelColor(float i, CRGB c, bool aa = true) const { setPixelColor(i, RGBW32(c.r,c.g,c.b,0), aa); }
#endif
#ifndef WLED_DISABLE_MODE_BLEND
static inline void setClippingRect(int startX, int stopX, int startY = 0, int stopY = 1) { _clipStart = startX; _clipStop = stopX; _clipStartY = startY; _clipStopY = stopY; };
#endif
bool isPixelClipped(int i) const;
[[gnu::hot]] uint32_t getPixelColor(int i) const;
// 1D support functions (some implement 2D as well)
void blur(uint8_t, bool smear = false);
Expand Down Expand Up @@ -653,6 +685,7 @@ typedef struct Segment {
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) const { setPixelColorXY(x, y, RGBW32(r,g,b,w), aa); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) const { setPixelColorXY(x, y, RGBW32(c.r,c.g,c.b,0), aa); }
#endif
[[gnu::hot]] bool isPixelXYClipped(int x, int y) const;
[[gnu::hot]] uint32_t getPixelColorXY(int x, int y) const;
// 2D support functions
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); }
Expand Down Expand Up @@ -690,6 +723,7 @@ typedef struct Segment {
inline void setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w = 0, bool aa = true) { setPixelColor(x, RGBW32(r,g,b,w), aa); }
inline void setPixelColorXY(float x, float y, CRGB c, bool aa = true) { setPixelColor(x, RGBW32(c.r,c.g,c.b,0), aa); }
#endif
inline bool isPixelXYClipped(int x, int y) { return isPixelClipped(x); }
inline uint32_t getPixelColorXY(int x, int y) { return getPixelColor(x); }
inline void blendPixelColorXY(uint16_t x, uint16_t y, uint32_t c, uint8_t blend) { blendPixelColor(x, c, blend); }
inline void blendPixelColorXY(uint16_t x, uint16_t y, CRGB c, uint8_t blend) { blendPixelColor(x, RGBW32(c.r,c.g,c.b,0), blend); }
Expand Down Expand Up @@ -734,9 +768,7 @@ class WS2812FX { // 96 bytes
public:

WS2812FX() :
paletteFade(0),
paletteBlend(0),
cctBlending(0),
now(millis()),
timebase(0),
isMatrix(false),
Expand Down Expand Up @@ -824,7 +856,6 @@ class WS2812FX { // 96 bytes
inline void resume() { _suspend = false; } // will resume strip.service() execution

bool
paletteFade,
checkSegmentAlignment() const,
hasRGBWBus() const,
hasCCTBus() const,
Expand All @@ -839,7 +870,6 @@ class WS2812FX { // 96 bytes

uint8_t
paletteBlend,
cctBlending,
getActiveSegmentsNum() const,
getFirstSelectedSegId() const,
getLastActiveSegmentId() const,
Expand Down
66 changes: 62 additions & 4 deletions wled00/FX_2Dfcn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(const int& x, const int& y, uint
const int baseY = startY + y;
#ifndef WLED_DISABLE_MODE_BLEND
// if blending modes, blend with underlying pixel
if (_modeBlend) col = color_blend16(strip.getPixelColorXY(baseX, baseY), col, 0xFFFFU - progress());
if (_modeBlend && blendingStyle == BLEND_STYLE_FADE) col = color_blend16(strip.getPixelColorXY(baseX, baseY), col, 0xFFFFU - progress());
#endif
strip.setPixelColorXY(baseX, baseY, col);

Expand All @@ -179,14 +179,57 @@ void IRAM_ATTR_YN Segment::_setPixelColorXY_raw(const int& x, const int& y, uint
}
}

// pixel is clipped if it falls outside clipping range (_modeBlend==true) or is inside clipping range (_modeBlend==false)
// if clipping start > stop the clipping range is inverted
// _modeBlend==true -> old effect during transition
// _modeBlend==false -> new effect during transition
bool IRAM_ATTR_YN Segment::isPixelXYClipped(int x, int y) const {
#ifndef WLED_DISABLE_MODE_BLEND
if (_clipStart != _clipStop && blendingStyle != BLEND_STYLE_FADE) {
const bool invertX = _clipStart > _clipStop;
const bool invertY = _clipStartY > _clipStopY;
const int startX = invertX ? _clipStop : _clipStart;
const int stopX = invertX ? _clipStart : _clipStop;
const int startY = invertY ? _clipStopY : _clipStartY;
const int stopY = invertY ? _clipStartY : _clipStopY;
if (blendingStyle == BLEND_STYLE_FAIRY_DUST) {
const unsigned width = stopX - startX; // assumes full segment width (faster than virtualWidth())
const unsigned len = width * (stopY - startY); // assumes full segment height (faster than virtualHeight())
if (len < 2) return false;
const unsigned shuffled = hashInt(x + y * width) % len;
const unsigned pos = (shuffled * 0xFFFFU) / len;
return progress() > pos;
}
bool xInside = (x >= startX && x < stopX); if (invertX) xInside = !xInside;
bool yInside = (y >= startY && y < stopY); if (invertY) yInside = !yInside;
const bool clip = (invertX && invertY) ? !_modeBlend : _modeBlend;
if (xInside && yInside) return clip; // covers window & corners (inverted)
return !clip;
}
#endif
return false;
}

void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) const
{
if (!isActive()) return; // not active

const int vW = vWidth(); // segment width in logical pixels (can be 0 if segment is inactive)
const int vH = vHeight(); // segment height in logical pixels (is always >= 1)
// negative values of x & y cast into unsigend will become very large values and will therefore be greater than vW/vH
if (unsigned(x) >= unsigned(vW) || unsigned(y) >= unsigned(vH)) return; // if pixel would fall out of virtual segment just exit

#ifndef WLED_DISABLE_MODE_BLEND
unsigned prog = 0xFFFF - progress();
if (!prog && !_modeBlend && (blendingStyle & BLEND_STYLE_PUSH_MASK)) {
unsigned dX = (blendingStyle == BLEND_STYLE_PUSH_UP || blendingStyle == BLEND_STYLE_PUSH_DOWN) ? 0 : prog * vW / 0xFFFF;
unsigned dY = (blendingStyle == BLEND_STYLE_PUSH_LEFT || blendingStyle == BLEND_STYLE_PUSH_RIGHT) ? 0 : prog * vH / 0xFFFF;
if (blendingStyle == BLEND_STYLE_PUSH_LEFT || blendingStyle == BLEND_STYLE_PUSH_TL || blendingStyle == BLEND_STYLE_PUSH_BL) x += dX;
else x -= dX;
if (blendingStyle == BLEND_STYLE_PUSH_DOWN || blendingStyle == BLEND_STYLE_PUSH_TL || blendingStyle == BLEND_STYLE_PUSH_TR) y -= dY;
else y += dY;
}
#endif

if (x >= vW || y >= vH || x < 0 || y < 0 || isPixelXYClipped(x,y)) return; // if pixel would fall out of virtual segment just exit

// if color is unscaled
if (!_colorScaled) col = color_fade(col, _segBri);
Expand Down Expand Up @@ -259,9 +302,24 @@ void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa) const
// returns RGBW values of pixel
uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const {
if (!isActive()) return 0; // not active

const int vW = vWidth();
const int vH = vHeight();
if (unsigned(x) >= unsigned(vW) || unsigned(y) >= unsigned(vH)) return 0; // if pixel would fall out of virtual segment just exit

#ifndef WLED_DISABLE_MODE_BLEND
unsigned prog = 0xFFFF - progress();
if (!prog && !_modeBlend && (blendingStyle & BLEND_STYLE_PUSH_MASK)) {
unsigned dX = (blendingStyle == BLEND_STYLE_PUSH_UP || blendingStyle == BLEND_STYLE_PUSH_DOWN) ? 0 : prog * vW / 0xFFFF;
unsigned dY = (blendingStyle == BLEND_STYLE_PUSH_LEFT || blendingStyle == BLEND_STYLE_PUSH_RIGHT) ? 0 : prog * vH / 0xFFFF;
if (blendingStyle == BLEND_STYLE_PUSH_LEFT || blendingStyle == BLEND_STYLE_PUSH_TL || blendingStyle == BLEND_STYLE_PUSH_BL) x -= dX;
else x += dX;
if (blendingStyle == BLEND_STYLE_PUSH_DOWN || blendingStyle == BLEND_STYLE_PUSH_TL || blendingStyle == BLEND_STYLE_PUSH_TR) y -= dY;
else y += dY;
}
#endif

if (x >= vW || y >= vH || x<0 || y<0 || isPixelXYClipped(x,y)) return 0; // if pixel would fall out of virtual segment just exit

if (reverse ) x = vW - x - 1;
if (reverse_y) y = vH - y - 1;
if (transpose) { std::swap(x,y); } // swap X & Y if segment transposed
Expand Down
Loading
Loading