blob effect improvements, and a dirty hack for HUB75 double buffer

* mode_2Dfloatingblobs() improvements for large panels
* Segment::fillCircle() speed optimizations
* HUB75 hack (disabled by default): skip first fill(BLACK) when using double buffering (as the buffer gets cleared after each frame)
This commit is contained in:
Frank
2024-08-06 15:53:46 +02:00
parent 9ee4165dad
commit 42919f9daf
5 changed files with 44 additions and 14 deletions

View File

@@ -6271,7 +6271,10 @@ uint16_t mode_2Dfloatingblobs(void) {
}
SEGMENT.fadeToBlackBy(20);
bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 5); //WLEDMM
bool drawAA = (SEGMENT.custom1 > 0) && (SEGMENT.custom1 < 6); //WLEDMM
const uint16_t minDim = min(cols, rows); // WLEDMM use smaller dimension to find good blob size
float max_grow = min(minDim/4.f,2.f);
if (minDim>=24) max_grow =(minDim/8.0f); // WLEDMM allow bigger blobs
// Bounce balls around
for (size_t i = 0; i < Amount; i++) {
@@ -6280,13 +6283,13 @@ uint16_t mode_2Dfloatingblobs(void) {
if (blob->grow[i]) {
// enlarge radius until it is >= 4
blob->r[i] += (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
if (blob->r[i] >= min(cols/4.f,2.f)) {
if (blob->r[i] >= max_grow) {
blob->grow[i] = false;
}
} else {
// reduce radius until it is < 1
blob->r[i] -= (fabsf(blob->sX[i]) > fabsf(blob->sY[i]) ? fabsf(blob->sX[i]) : fabsf(blob->sY[i])) * 0.05f;
if (blob->r[i] < 1.f) {
if (blob->r[i] < 0.8f) {
blob->grow[i] = true;
}
}

View File

@@ -439,6 +439,7 @@ typedef struct Segment {
bool _isSimpleSegment = false;
bool _isValid2D = false;
uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity
bool _firstFill = true; // dirty HACK support
uint16_t _2dWidth = 0; // virtualWidth
uint16_t _2dHeight = 0; // virtualHeight
@@ -741,8 +742,8 @@ typedef struct Segment {
void move(uint8_t dir, uint8_t delta, bool wrap = false);
void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
inline void drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { drawCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t c, bool soft = false);
inline void fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
void fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft);
inline void fillCircle(unsigned cx, unsigned cy, int radius, CRGB c, bool soft = false) { fillCircle(cx, cy, radius, RGBW32(c.r,c.g,c.b,0), soft); }
void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t c, bool soft = false, uint8_t depth = UINT8_MAX);
inline void drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, bool soft = false, uint8_t depth = UINT8_MAX) { drawLine(x0, y0, x1, y1, RGBW32(c.r,c.g,c.b,0), soft, depth); } // automatic inline
void drawArc(uint16_t x0, uint16_t y0, uint16_t radius, uint32_t color, uint32_t fillColor = 0);

View File

@@ -226,6 +226,9 @@ void Segment::startFrame(void) {
// if (reverse_y) _isSimpleSegment = false; // for A/B testing
_2dWidth = is2D() ? calc_virtualWidth() : virtualLength();
_2dHeight = calc_virtualHeight();
#if 0 && defined(WLED_ENABLE_HUB75MATRIX)
_firstFill = true; // dirty HACK
#endif
#endif
}
// WLEDMM end
@@ -651,19 +654,26 @@ void Segment::drawCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col,
}
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
void Segment::fillCircle(uint16_t cx, uint16_t cy, uint8_t radius, uint32_t col, bool soft) {
if (!isActive() || radius == 0) return; // not active
void Segment::fillCircle(unsigned cx, unsigned cy, int radius, uint32_t col, bool soft) {
if (!isActive() || radius <= 0) return; // not active
// draw soft bounding circle
if (soft) drawCircle(cx, cy, radius, col, soft);
// fill it
const int cols = virtualWidth();
const int rows = virtualHeight();
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
if (x * x + y * y <= radius * radius &&
int16_t(cx)+x>=0 && int16_t(cy)+y>=0 &&
int16_t(cx)+x<cols && int16_t(cy)+y<rows)
const int_fast32_t maxRadius2 = radius * radius - (((radius > 3) && !soft) ? 1:0); // WLEDMM pre-compute r^2; '-1' removes spikes from bigger blobs
// WLEDMM pre-compute boundaries
const int startx = max(-radius, -int(cx));
const int endx = min(radius, cols-1-int(cx));
const int starty = max(-radius, -int(cy));
const int endy = min(radius, rows-1-int(cy));
// fill it - WLEDMM optimized
for (int y = starty; y <= endy; y++) {
for (int x = startx; x <= endx; x++) {
if ((x * x + y * y) <= maxRadius2) {
setPixelColorXY(cx + x, cy + y, col);
}
}
}
}
@@ -690,7 +700,11 @@ void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint3
uint32_t scaled_col = c;
if (simpleSegment) {
// segment brightness must be pre-calculated for the "fast" setPixelColorXY variant!
#ifdef WLEDMM_FASTPATH
uint8_t _bri_t = _brightness;
#else
uint8_t _bri_t = currentBri(on ? opacity : 0);
#endif
if (!_bri_t && !transitional) return;
if (_bri_t < 255) scaled_col = color_fade(c, _bri_t);
}

View File

@@ -1347,6 +1347,18 @@ void Segment::refreshLightCapabilities() {
*/
void Segment::fill(uint32_t c) {
if (!isActive()) return; // not active
#if 0 && defined(WLED_ENABLE_HUB75MATRIX) && defined(WLEDMM_FASTPATH)
// DIRTY HACK - this ignores the first fill(black) in each frame, knowing that HUB75 has already blanked out the display.
if (_firstFill) {
_firstFill = false;
if (c == BLACK) {
if (ledsrgb && ledsrgbSize > 0) memset(ledsrgb, 0, ledsrgbSize);
return;
}
}
#endif
const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types
const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D

View File

@@ -8,7 +8,7 @@
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2408051
#define VERSION 2408060
// WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED.
#define _MoonModules_WLED_