New smooth effect: Color Clouds (#5268)

* New Effect: Color Clouds

ColorClouds: Random start points for clouds and color

ColorClouds: new config option 'More red'

* ColorClouds: Incorporated review comments

- Support for color palettes
- Use perlin16() instead of inoise16()
- Use cos8_t() instead of cos8()

* ColorClouds: incorporated more review comments

* ColorClouds: incorporated final review comment
This commit is contained in:
Joachim Dick
2026-03-11 08:19:42 +01:00
committed by Frank
parent 2dedbf469a
commit f96c2087d9
2 changed files with 82 additions and 1 deletions

View File

@@ -5036,6 +5036,85 @@ uint16_t mode_aurora(void) {
} }
static const char _data_FX_MODE_AURORA[] PROGMEM = "Aurora@!,!;1,2,3;!;;sx=24,pal=50"; static const char _data_FX_MODE_AURORA[] PROGMEM = "Aurora@!,!;1,2,3;!;;sx=24,pal=50";
/** Softly floating colorful clouds.
* This is a very smooth effect that moves colorful clouds randomly around the LED strip.
* It was initially intended for rather unobtrusive ambient lights (with very slow speed settings).
* Nevertheless, it appears completely different and quite vibrant when the sliders are moved near
* to their limits. No matter in which direction or in which combination...
* Ported to WLED from https://github.com/JoaDick/EyeCandy/blob/master/ColorClouds.h
*/
uint16_t mode_ColorClouds()
{
// Set random start points for clouds and color.
if (SEGENV.call == 0) {
SEGENV.aux0 = hw_random16();
SEGENV.aux1 = hw_random16();
}
const uint32_t volX0 = SEGENV.aux0;
const uint32_t hueX0 = SEGENV.aux1;
const uint8_t hueOffset0 = volX0 + hueX0; // derive a 3rd random number
// Makes a very soft wraparound of the color palette by putting more emphasis on the begin & end
// of the palette (or on the red'ish colors in case of a rainbow spectrum).
// This gives the effect oftentimes an even more calm perception.
const bool cozy = SEGMENT.check3;
// Higher values make the clouds move faster.
const uint32_t volSpeed = 1 + SEGMENT.speed;
// Higher values make the color change faster.
const uint32_t hueSpeed = 1 + SEGMENT.intensity;
// Higher values make more clouds (but smaller ones).
const uint32_t volSqueeze = 8 + SEGMENT.custom1;
// Higher values make the clouds more colorful.
const uint32_t hueSqueeze = SEGMENT.custom2;
// Higher values make larger gaps between the clouds.
const int32_t volCutoff = 12500 + SEGMENT.custom3 * 900;
const int32_t volSaturate = 52000;
// Note: When adjusting these calculations, ensure that volCutoff is always smaller than volSaturate.
const uint32_t now = strip.now;
const uint32_t volT = now * volSpeed / 8;
const uint32_t hueT = now * hueSpeed / 8;
const uint8_t hueOffset = beat88(64) >> 8;
bool doGammaCorrection = false; // WLEDMM gamma correction only needed when color is _not_ from a palette
if (SEGMENT.palette == 0) doGammaCorrection = true;
for (int i = 0; i < SEGLEN; i++) {
const uint32_t volX = i * volSqueeze * 64;
int32_t vol = perlin16(volX0 + volX, volT);
vol = map(vol, volCutoff, volSaturate, 0, 255);
vol = constrain(vol, 0, 255);
const uint32_t hueX = i * hueSqueeze * 8;
uint8_t hue = perlin16(hueX0 + hueX, hueT) >> 7;
hue += hueOffset0;
hue += hueOffset;
if (cozy) {
hue = cos8_t(128 + hue / 2);
}
uint32_t pixel;
if (SEGMENT.palette) { pixel = SEGMENT.color_from_palette(hue, false, true, 0, vol); }
else { hsv2rgb(CHSV32(hue, 255, vol), pixel); }
// Suppress extremely dark pixels to avoid flickering of plain r/g/b.
if (int(R(pixel)) + G(pixel) + B(pixel) <= 2) {
pixel = 0;
}
if (doGammaCorrection) pixel = gamma32(pixel);
SEGMENT.setPixelColor(i, pixel);
}
return FRAMETIME;
}
static const char _data_FX_MODE_COLORCLOUDS[] PROGMEM = "Color Clouds@!,!,Clouds,Colors,Distance,,,Cozy;;!;;sx=24,ix=32,c1=48,c2=64,c3=12,pal=0";
// WLED-SR effects // WLED-SR effects
///////////////////////// /////////////////////////
@@ -12155,6 +12234,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_COLOR_SWEEP_RANDOM, &mode_color_sweep_random, _data_FX_MODE_COLOR_SWEEP_RANDOM); addEffect(FX_MODE_COLOR_SWEEP_RANDOM, &mode_color_sweep_random, _data_FX_MODE_COLOR_SWEEP_RANDOM);
addEffect(FX_MODE_RUNNING_COLOR, &mode_running_color, _data_FX_MODE_RUNNING_COLOR); addEffect(FX_MODE_RUNNING_COLOR, &mode_running_color, _data_FX_MODE_RUNNING_COLOR);
addEffect(FX_MODE_AURORA, &mode_aurora, _data_FX_MODE_AURORA); addEffect(FX_MODE_AURORA, &mode_aurora, _data_FX_MODE_AURORA);
addEffect(FX_MODE_COLORCLOUDS, &mode_ColorClouds, _data_FX_MODE_COLORCLOUDS);
addEffect(FX_MODE_RUNNING_RANDOM, &mode_running_random, _data_FX_MODE_RUNNING_RANDOM); addEffect(FX_MODE_RUNNING_RANDOM, &mode_running_random, _data_FX_MODE_RUNNING_RANDOM);
addEffect(FX_MODE_LARSON_SCANNER, &mode_larson_scanner, _data_FX_MODE_LARSON_SCANNER); addEffect(FX_MODE_LARSON_SCANNER, &mode_larson_scanner, _data_FX_MODE_LARSON_SCANNER);
addEffect(FX_MODE_COMET, &mode_comet, _data_FX_MODE_COMET); addEffect(FX_MODE_COMET, &mode_comet, _data_FX_MODE_COMET);

View File

@@ -399,7 +399,8 @@ static uint8_t strip_getPaletteBlend(); // forward declaration: little helper t
#define FX_MODE_PS1DSPRINGY 227 #define FX_MODE_PS1DSPRINGY 227
#define FX_MODE_PARTICLEGALAXY 228 #define FX_MODE_PARTICLEGALAXY 228
#define MODE_COUNT 229 #define FX_MODE_COLORCLOUDS 229
#define MODE_COUNT 230
typedef enum mapping1D2D { typedef enum mapping1D2D {
M12_Pixels = 0, M12_Pixels = 0,