Skip to content

Commit 73fc9ea

Browse files
authored
Merge pull request wled#4543 from DedeHai/soap-FX-optimization
Soap FX optimization
2 parents dd80919 + aba736c commit 73fc9ea

File tree

1 file changed

+65
-73
lines changed

1 file changed

+65
-73
lines changed

wled00/FX.cpp

Lines changed: 65 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7467,42 +7467,86 @@ static const char _data_FX_MODE_2DDISTORTIONWAVES[] PROGMEM = "Distortion Waves@
74677467
//Soap
74687468
//@Stepko
74697469
//Idea from https://www.youtube.com/watch?v=DiHBgITrZck&ab_channel=StefanPetrick
7470-
// adapted for WLED by @blazoncek
7470+
// adapted for WLED by @blazoncek, optimization by @dedehai
7471+
static void soapPixels(bool isRow, uint8_t *noise3d, CRGB *pixels) {
7472+
const int cols = SEG_W;
7473+
const int rows = SEG_H;
7474+
const auto XY = [&](int x, int y) { return x + y * cols; };
7475+
const auto abs = [](int x) { return x<0 ? -x : x; };
7476+
const int tRC = isRow ? rows : cols; // transpose if isRow
7477+
const int tCR = isRow ? cols : rows; // transpose if isRow
7478+
const int amplitude = max(1, (tCR - 8) >> 3) * (1 + (SEGMENT.custom1 >> 5));
7479+
const int shift = 0; //(128 - SEGMENT.custom2)*2;
7480+
7481+
CRGB ledsbuff[tCR];
7482+
7483+
for (int i = 0; i < tRC; i++) {
7484+
int amount = ((int)noise3d[isRow ? i*cols : i] - 128) * amplitude + shift; // use first row/column: XY(0,i)/XY(i,0)
7485+
int delta = abs(amount) >> 8;
7486+
int fraction = abs(amount) & 255;
7487+
for (int j = 0; j < tCR; j++) {
7488+
int zD, zF;
7489+
if (amount < 0) {
7490+
zD = j - delta;
7491+
zF = zD - 1;
7492+
} else {
7493+
zD = j + delta;
7494+
zF = zD + 1;
7495+
}
7496+
int yA = abs(zD)%tCR;
7497+
int yB = abs(zF)%tCR;
7498+
int xA = i;
7499+
int xB = i;
7500+
if (isRow) {
7501+
std::swap(xA,yA);
7502+
std::swap(xB,yB);
7503+
}
7504+
const int indxA = XY(xA,yA);
7505+
const int indxB = XY(xB,yB);
7506+
CRGB PixelA;
7507+
CRGB PixelB;
7508+
if ((zD >= 0) && (zD < tCR)) PixelA = pixels[indxA];
7509+
else PixelA = ColorFromPalette(SEGPALETTE, ~noise3d[indxA]*3);
7510+
if ((zF >= 0) && (zF < tCR)) PixelB = pixels[indxB];
7511+
else PixelB = ColorFromPalette(SEGPALETTE, ~noise3d[indxB]*3);
7512+
ledsbuff[j] = (PixelA.nscale8(ease8InOutApprox(255 - fraction))) + (PixelB.nscale8(ease8InOutApprox(fraction)));
7513+
}
7514+
for (int j = 0; j < tCR; j++) {
7515+
CRGB c = ledsbuff[j];
7516+
if (isRow) std::swap(j,i);
7517+
SEGMENT.setPixelColorXY(i, j, pixels[XY(i,j)] = c);
7518+
if (isRow) std::swap(j,i);
7519+
}
7520+
}
7521+
}
7522+
74717523
uint16_t mode_2Dsoap() {
74727524
if (!strip.isMatrix || !SEGMENT.is2D()) return mode_static(); // not a 2D set-up
74737525

74747526
const int cols = SEG_W;
74757527
const int rows = SEG_H;
7476-
const auto XY = [&](int x, int y) { return (x%cols) + (y%rows) * cols; };
7528+
const auto XY = [&](int x, int y) { return x + y * cols; };
74777529

7478-
const size_t dataSize = SEGMENT.width() * SEGMENT.height() * sizeof(uint8_t); // prevent reallocation if mirrored or grouped
7530+
const size_t segSize = SEGMENT.width() * SEGMENT.height(); // prevent reallocation if mirrored or grouped
7531+
const size_t dataSize = segSize * (sizeof(uint8_t) + sizeof(CRGB)); // pixels and noise
74797532
if (!SEGENV.allocateData(dataSize + sizeof(uint32_t)*3)) return mode_static(); //allocation failed
74807533

7481-
uint8_t *noise3d = reinterpret_cast<uint8_t*>(SEGENV.data);
7482-
uint32_t *noise32_x = reinterpret_cast<uint32_t*>(SEGENV.data + dataSize);
7483-
uint32_t *noise32_y = reinterpret_cast<uint32_t*>(SEGENV.data + dataSize + sizeof(uint32_t));
7484-
uint32_t *noise32_z = reinterpret_cast<uint32_t*>(SEGENV.data + dataSize + sizeof(uint32_t)*2);
7534+
uint8_t *noise3d = reinterpret_cast<uint8_t*>(SEGENV.data);
7535+
CRGB *pixels = reinterpret_cast<CRGB*>(SEGENV.data + segSize * sizeof(uint8_t));
7536+
uint32_t *noisecoord = reinterpret_cast<uint32_t*>(SEGENV.data + dataSize); // x, y, z coordinates
74857537
const uint32_t scale32_x = 160000U/cols;
74867538
const uint32_t scale32_y = 160000U/rows;
74877539
const uint32_t mov = MIN(cols,rows)*(SEGMENT.speed+2)/2;
74887540
const uint8_t smoothness = MIN(250,SEGMENT.intensity); // limit as >250 produces very little changes
74897541

7490-
// init
7491-
if (SEGENV.call == 0) {
7492-
*noise32_x = hw_random();
7493-
*noise32_y = hw_random();
7494-
*noise32_z = hw_random();
7495-
} else {
7496-
*noise32_x += mov;
7497-
*noise32_y += mov;
7498-
*noise32_z += mov;
7499-
}
7542+
if (SEGENV.call == 0) for (int i = 0; i < 3; i++) noisecoord[i] = hw_random(); // init
7543+
else for (int i = 0; i < 3; i++) noisecoord[i] += mov;
75007544

75017545
for (int i = 0; i < cols; i++) {
75027546
int32_t ioffset = scale32_x * (i - cols / 2);
75037547
for (int j = 0; j < rows; j++) {
75047548
int32_t joffset = scale32_y * (j - rows / 2);
7505-
uint8_t data = inoise16(*noise32_x + ioffset, *noise32_y + joffset, *noise32_z) >> 8;
7549+
uint8_t data = inoise16(noisecoord[0] + ioffset, noisecoord[1] + joffset, noisecoord[2]) >> 8;
75067550
noise3d[XY(i,j)] = scale8(noise3d[XY(i,j)], smoothness) + scale8(data, 255 - smoothness);
75077551
}
75087552
}
@@ -7517,64 +7561,12 @@ uint16_t mode_2Dsoap() {
75177561
}
75187562
}
75197563

7520-
int zD;
7521-
int zF;
7522-
int amplitude;
7523-
int shiftX = 0; //(SEGMENT.custom1 - 128) / 4;
7524-
int shiftY = 0; //(SEGMENT.custom2 - 128) / 4;
7525-
CRGB ledsbuff[MAX(cols,rows)];
7526-
7527-
amplitude = (cols >= 16) ? (cols-8)/8 : 1;
7528-
for (int y = 0; y < rows; y++) {
7529-
int amount = ((int)noise3d[XY(0,y)] - 128) * 2 * amplitude + 256*shiftX;
7530-
int delta = abs(amount) >> 8;
7531-
int fraction = abs(amount) & 255;
7532-
for (int x = 0; x < cols; x++) {
7533-
if (amount < 0) {
7534-
zD = x - delta;
7535-
zF = zD - 1;
7536-
} else {
7537-
zD = x + delta;
7538-
zF = zD + 1;
7539-
}
7540-
CRGB PixelA = CRGB::Black;
7541-
if ((zD >= 0) && (zD < cols)) PixelA = SEGMENT.getPixelColorXY(zD, y);
7542-
else PixelA = ColorFromPalette(SEGPALETTE, ~noise3d[XY(abs(zD),y)]*3);
7543-
CRGB PixelB = CRGB::Black;
7544-
if ((zF >= 0) && (zF < cols)) PixelB = SEGMENT.getPixelColorXY(zF, y);
7545-
else PixelB = ColorFromPalette(SEGPALETTE, ~noise3d[XY(abs(zF),y)]*3);
7546-
ledsbuff[x] = (PixelA.nscale8(ease8InOutApprox(255 - fraction))) + (PixelB.nscale8(ease8InOutApprox(fraction)));
7547-
}
7548-
for (int x = 0; x < cols; x++) SEGMENT.setPixelColorXY(x, y, ledsbuff[x]);
7549-
}
7550-
7551-
amplitude = (rows >= 16) ? (rows-8)/8 : 1;
7552-
for (int x = 0; x < cols; x++) {
7553-
int amount = ((int)noise3d[XY(x,0)] - 128) * 2 * amplitude + 256*shiftY;
7554-
int delta = abs(amount) >> 8;
7555-
int fraction = abs(amount) & 255;
7556-
for (int y = 0; y < rows; y++) {
7557-
if (amount < 0) {
7558-
zD = y - delta;
7559-
zF = zD - 1;
7560-
} else {
7561-
zD = y + delta;
7562-
zF = zD + 1;
7563-
}
7564-
CRGB PixelA = CRGB::Black;
7565-
if ((zD >= 0) && (zD < rows)) PixelA = SEGMENT.getPixelColorXY(x, zD);
7566-
else PixelA = ColorFromPalette(SEGPALETTE, ~noise3d[XY(x,abs(zD))]*3);
7567-
CRGB PixelB = CRGB::Black;
7568-
if ((zF >= 0) && (zF < rows)) PixelB = SEGMENT.getPixelColorXY(x, zF);
7569-
else PixelB = ColorFromPalette(SEGPALETTE, ~noise3d[XY(x,abs(zF))]*3);
7570-
ledsbuff[y] = (PixelA.nscale8(ease8InOutApprox(255 - fraction))) + (PixelB.nscale8(ease8InOutApprox(fraction)));
7571-
}
7572-
for (int y = 0; y < rows; y++) SEGMENT.setPixelColorXY(x, y, ledsbuff[y]);
7573-
}
7564+
soapPixels(true, noise3d, pixels); // rows
7565+
soapPixels(false, noise3d, pixels); // cols
75747566

75757567
return FRAMETIME;
75767568
}
7577-
static const char _data_FX_MODE_2DSOAP[] PROGMEM = "Soap@!,Smoothness;;!;2;pal=11";
7569+
static const char _data_FX_MODE_2DSOAP[] PROGMEM = "Soap@!,Smoothness,Density;;!;2;pal=11";
75787570

75797571

75807572
//Idea from https://www.youtube.com/watch?v=HsA-6KIbgto&ab_channel=GreatScott%21

0 commit comments

Comments
 (0)