add new effect: PS Galaxy

- parameters tuned to make it look good on most settings
This commit is contained in:
Damian Schneider 2025-05-09 18:53:16 +02:00
parent d9b086cbe9
commit 0fe722e478
2 changed files with 101 additions and 1 deletions

View File

@ -8958,6 +8958,104 @@ uint16_t mode_particleblobs(void) {
return FRAMETIME;
}
static const char _data_FX_MODE_PARTICLEBLOBS[] PROGMEM = "PS Blobs@Speed,Blobs,Size,Life,Blur,Wobble,Collide,Pulsate;;!;2v;sx=30,ix=64,c1=200,c2=130,c3=0,o3=1";
/*
Particle Galaxy, particles spiral like in a galaxy
Uses palette for particle color
by DedeHai (Damian Schneider)
*/
uint16_t mode_particlegalaxy(void) {
ParticleSystem2D *PartSys = nullptr;
PSsettings2D sourcesettings;
sourcesettings.asByte = 0b00001100; // PS settings for bounceY, bounceY used for source movement (it always bounces whereas particles do not)
if (SEGMENT.call == 0) { // initialization
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init using 1 source and advanced particle settings
return mode_static(); // allocation failed or not 2D
PartSys->sources[0].source.vx = -4; // will collide with wall and get random bounce direction
PartSys->sources[0].source.x = PartSys->maxX >> 1; // start in the center
PartSys->sources[0].source.y = PartSys->maxY >> 1;
PartSys->sources[0].sourceFlags.perpetual = true; //source does not age
PartSys->sources[0].maxLife = 4000; // lifetime in frames
PartSys->sources[0].minLife = 800;
PartSys->setWallHardness(255); //bounce forever
PartSys->setWallRoughness(200); //randomize wall bounce
}
else {
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
}
if (PartSys == nullptr)
return mode_static(); // something went wrong, no data!
// Particle System settings
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
uint8_t particlesize = SEGMENT.custom1;
if(SEGMENT.check3)
particlesize = SEGMENT.custom1 ? 1 : 0; // set size to 0 (single pixel) or 1 (quad pixel) so motion blur works and adds streaks
PartSys->setParticleSize(particlesize); // set size globally
PartSys->setMotionBlur(250 * SEGMENT.check3); // adds trails to single/quad pixel particles, no effect if size > 1
if ((SEGMENT.call % ((33 - SEGMENT.custom3) >> 1)) == 0) // change hue of emitted particles
PartSys->sources[0].source.hue+=2;
if (hw_random8() < (10 + (SEGMENT.intensity >> 1))) // 5%-55% chance to emit a particle in this frame
PartSys->sprayEmit(PartSys->sources[0]);
if ((SEGMENT.call & 0x3) == 0) // every 4th frame, move the emitter
PartSys->particleMoveUpdate(PartSys->sources[0].source, PartSys->sources[0].sourceFlags, &sourcesettings);
// move alive particles in a spiral motion (or almost straight in fast starfield mode)
for (uint32_t i = 0; i < PartSys->usedParticles; i++) { //check all particles
if (PartSys->particles[i].ttl == 0) continue; //skip dead particles
int32_t centerx = PartSys->maxX >> 1; // center of matrix in subpixel coordinates
int32_t centery = PartSys->maxY >> 1;
// (dx/dy): vector pointing from particle to center
int32_t dx = centerx - PartSys->particles[i].x;
int32_t dy = centery - PartSys->particles[i].y;
//speed towards center:
int32_t distance = sqrt32_bw(dx * dx + dy * dy); // absolute distance to center
if (distance < 20) distance = 20; // avoid division by zero, keep a minimum
int32_t speedfactor;
if (SEGMENT.check2) { // starfield mode
PartSys->setKillOutOfBounds(true);
PartSys->sources[0].source.hue = hw_random16(); // start with random color
PartSys->sources[0].var = 7; // emiting variation
PartSys->sources[0].source.x = PartSys->maxX >> 1; // set emitter to center
PartSys->sources[0].source.y = PartSys->maxY >> 1;
speedfactor = 1 + (1 + (SEGMENT.speed >> 1)) * distance; // speed increases towards edge
PartSys->particles[i].x += (-speedfactor * dx) / 400000 - (dy >> 6);
PartSys->particles[i].y += (-speedfactor * dy) / 400000 + (dx >> 6);
}
else {
PartSys->setKillOutOfBounds(false);
PartSys->sources[0].var = 1; // emiting variation
speedfactor = 2 + (((50 + SEGMENT.speed) << 6) / distance); // speed increases towards center
// rotate clockwise
int32_t tempVx = (-speedfactor * dy); // speed is orthogonal to center vector
int32_t tempVy = (speedfactor * dx);
//add speed towards center to make particles spiral in
int vxc = (dx << 9) / (distance - 19); // subtract value from distance to make the pull-in force a bit stronger (helps on faster speeds)
int vyc = (dy << 9) / (distance - 19);
//apply velocity
PartSys->particles[i].x += (tempVx + vxc) / 1024; // note: cannot use bit shift as that causes asymmetric rounding
PartSys->particles[i].y += (tempVy + vyc) / 1024;
if (distance < 128) { // close to center
if (PartSys->particles[i].ttl > 3)
PartSys->particles[i].ttl -= 4; //age fast
PartSys->particles[i].sat = distance << 1; // turn white towards center
}
}
if(SEGMENT.custom3 == 31) // color by age but mapped to 1024 as particles have a long life, since age is random, this gives more or less random colors
PartSys->particles[i].hue = PartSys->particles[i].ttl >> 2;
else if(SEGMENT.custom3 == 0) // color by distance
PartSys->particles[i].hue = map(distance, 20, (PartSys->maxX + PartSys->maxY) >> 2, 0, 180); // color by distance to center
}
PartSys->update(); // update and render
return FRAMETIME;
}
static const char _data_FX_MODE_PARTICLEGALAXY[] PROGMEM = "PS Galaxy@!,!,Size,,Color,,Starfield,Trace;;!;2;pal=59,sx=80,c1=2,c3=4";
#endif //WLED_DISABLE_PARTICLESYSTEM2D
#endif // WLED_DISABLE_2D
@ -10657,6 +10755,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECIRCULARGEQ);
addEffect(FX_MODE_PARTICLEGHOSTRIDER, &mode_particleghostrider, _data_FX_MODE_PARTICLEGHOSTRIDER);
addEffect(FX_MODE_PARTICLEBLOBS, &mode_particleblobs, _data_FX_MODE_PARTICLEBLOBS);
addEffect(FX_MODE_PARTICLEGALAXY, &mode_particlegalaxy, _data_FX_MODE_PARTICLEGALAXY);
#endif // WLED_DISABLE_PARTICLESYSTEM2D
#endif // WLED_DISABLE_2D

View File

@ -353,7 +353,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define FX_MODE_PS1DSONICSTREAM 214
#define FX_MODE_PS1DSONICBOOM 215
#define FX_MODE_PS1DSPRINGY 216
#define MODE_COUNT 217
#define FX_MODE_PARTICLEGALAXY 217
#define MODE_COUNT 218
#define BLEND_STYLE_FADE 0x00 // universal