changed randomness and added optimizations

-added fully random palette function ('the old way', currently just used for initialization)
-changed randomness values to make it a little less random
-added 10% chance for pastel color palette
-now using swap() from std library for shuffeling
-changed function name
-moved update check from loadPalette() to handleRandomPalette() saving CPU cycles
This commit is contained in:
Damian Schneider 2024-01-30 22:28:40 +01:00
parent ef6fe43251
commit ca05aa84ff
3 changed files with 69 additions and 59 deletions

View File

@ -77,8 +77,8 @@ uint16_t Segment::_usedSegmentData = 0U; // amount of RAM all segments use for t
uint16_t Segment::maxWidth = DEFAULT_LED_COUNT;
uint16_t Segment::maxHeight = 1;
CRGBPalette16 Segment::_randomPalette = generateRandomPalette(_randomPalette);
CRGBPalette16 Segment::_newRandomPalette = generateRandomPalette(_randomPalette);
CRGBPalette16 Segment::_randomPalette = generateRandomPalette();
CRGBPalette16 Segment::_newRandomPalette = generateRandomPalette();
uint16_t Segment::_lastPaletteChange = 0; // perhaps it should be per segment
uint16_t Segment::_lastPaletteBlend = 0; //in millis (lowest 16 bits only)
@ -222,13 +222,7 @@ CRGBPalette16 IRAM_ATTR &Segment::loadPalette(CRGBPalette16 &targetPalette, uint
case 0: //default palette. Exceptions for specific effects above
targetPalette = PartyColors_p; break;
case 1: {//periodically replace palette with a random one
if ((millis()/1000U) - _lastPaletteChange > randomPaletteChangeTime) {
_newRandomPalette = generateRandomPalette(_randomPalette);
_lastPaletteChange = millis()/1000U;
_lastPaletteBlend = (uint16_t)(millis()&0xFFFF)-512; //starts blending immediately
handleRandomPalette(); // do a 1st pass of blend
}
targetPalette = _randomPalette;
targetPalette = _randomPalette; //random palette is generated at intervals in handleRandomPalette()
break;}
case 2: {//primary color only
CRGB prim = gamma32(colors[0]);
@ -463,11 +457,17 @@ void Segment::handleRandomPalette() {
// just do a blend; if the palettes are identical it will just compare 48 bytes (same as _randomPalette == _newRandomPalette)
// this will slowly blend _newRandomPalette into _randomPalette every 15ms or 8ms (depending on MIN_SHOW_DELAY)
// if palette transitions is enabled, blend it according to Transition Time (if longer than minimum given by service calls)
if(strip.paletteFade)
if ((millis()/1000U) - _lastPaletteChange > randomPaletteChangeTime) {
_newRandomPalette = generateHarmonicRandomPalette(_randomPalette);
_lastPaletteChange = millis()/1000U;
_lastPaletteBlend = (uint16_t)(millis()&0xFFFF)-512; //starts blending immediately
}
if (strip.paletteFade)
{
if((millis()&0xFFFF) - _lastPaletteBlend < strip.getTransition()>>7) //assumes that 128 updates are needed to blend a palette, so shift by 7 (can be more, can be less)
{
return; //not time to fade yet
if ((millis() & 0xFFFF) - _lastPaletteBlend < strip.getTransition() >> 7) {//assumes that 128 updates are needed to blend a palette, so shift by 7 (can be more, can be less)
return; //not time to fade yet, delay the update
}
_lastPaletteBlend = millis();
}

View File

@ -92,42 +92,33 @@ void setRandomColor(byte* rgb)
}
/*
*generates a random palette based on color theory
*generates a random palette based on harmonic color theory
*takes a base palette as the input, it will choose one color of the base palette and keep it
*/
CRGBPalette16 generateRandomPalette(CRGBPalette16 &basepalette)
CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette)
{
CHSV palettecolors[4]; //array of colors for the new palette
uint8_t keepcolorposition = random8(4); //color position of current random palette to keep
palettecolors[keepcolorposition] = rgb2hsv_approximate(basepalette.entries[keepcolorposition*5]); //read one of the base colors of the current palette
palettecolors[keepcolorposition].hue += random8(20)-10; // +/- 10 randomness
palettecolors[keepcolorposition].hue += random8(10)-5; // +/- 5 randomness of base color
//generate 4 saturation and brightness value numbers
//only one saturation is allowed to be below 200 creating mostly vibrant colors
//only one brightness value number is allowed below 200, creating mostly bright palettes
for (int i = 0; i<3; i++) { //generate three high values
palettecolors[i].saturation = random8(180,255);
palettecolors[i].value = random8(180,255);
for (int i = 0; i < 3; i++) { //generate three high values
palettecolors[i].saturation = random8(200,255);
palettecolors[i].value = random8(220,255);
}
//allow one to be lower
palettecolors[3].saturation = random8(80,255);
palettecolors[3].value = random8(50,255);
palettecolors[3].value = random8(80,255);
//shuffle the arrays using Fisher-Yates algorithm
for (int i = 3; i > 0; i--) {
uint8_t j = random8(0, i + 1);
//swap [i] and [j]
uint8_t temp = palettecolors[i].saturation;
palettecolors[i].saturation = palettecolors[j].saturation;
palettecolors[j].saturation = temp;
}
//shuffle the arrays
for (int i = 3; i > 0; i--) {
uint8_t j = random8(0, i + 1);
//swap [i] and [j]
uint8_t temp = palettecolors[i].value;
palettecolors[i].value = palettecolors[j].value;
palettecolors[j].value = temp;
std::swap(palettecolors[i].saturation, palettecolors[random8(i + 1)].saturation);
std::swap(palettecolors[i].value, palettecolors[random8(i + 1)].value);
}
//now generate three new hues based off of the hue of the chosen current color
@ -143,50 +134,58 @@ CRGBPalette16 generateRandomPalette(CRGBPalette16 &basepalette)
break;
case 1: // triadic
harmonics[0] = basehue + 110 + random8(20);
harmonics[1] = basehue + 230 + random8(20);
harmonics[2] = basehue + random8(30)-15;
harmonics[0] = basehue + 113 + random8(15);
harmonics[1] = basehue + 233 + random8(15);
harmonics[2] = basehue -7 + random8(15);
break;
case 2: // split-complementary
harmonics[0] = basehue + 140 + random8(20);
harmonics[1] = basehue + 200 + random8(20);
harmonics[2] = basehue + random8(30)-15;
harmonics[0] = basehue + 145 + random8(10);
harmonics[1] = basehue + 205 + random8(10);
harmonics[2] = basehue - 5 + random8(10);
break;
case 3: // square
harmonics[0] = basehue + 85 + random8(10);
harmonics[1] = basehue + 175 + random8(10);
harmonics[2] = basehue + 265 + random8(10);
break;
case 3: // tetradic
case 4: // tetradic
harmonics[0] = basehue + 80 + random8(20);
harmonics[1] = basehue + 170 + random8(20);
harmonics[2] = basehue + random8(30)-15;
break;
case 4: // square
harmonics[0] = basehue + 80 + random8(20);
harmonics[1] = basehue + 170 + random8(20);
harmonics[2] = basehue + 260 + random8(20);
break;
break;
}
//shuffle the hues:
for (int i = 2; i > 0; i--) {
uint8_t j = random8(0, i + 1);
//swap [i] and [j]
uint8_t temp = harmonics[i];
harmonics[i] = harmonics[j];
harmonics[j] = temp;
if (random8() < 128) //50:50 chance of shuffeling hues or keep the color order
{
//shuffle the hues:
for (int i = 2; i > 0; i--) {
std::swap(harmonics[i], harmonics[random8(i + 1)]);
}
}
//now set the hues
int j=0;
for (int i = 0; i<4; i++) {
int j = 0;
for (int i = 0; i < 4; i++) {
if(i==keepcolorposition) continue; //skip the base color
palettecolors[i].hue = harmonics[j];
j++;
}
//apply gamma correction
bool makepastelpalette = false;
if (random8() < 25) {//~10% chance of desaturated 'pastel' colors
makepastelpalette = true;
}
//apply saturation & gamma correction
CRGB RGBpalettecolors[4];
for (int i = 0; i<4; i++) {
for (int i = 0; i < 4; i++) {
if(makepastelpalette && palettecolors[i].saturation > 180) {
palettecolors[i].saturation -= 160; //desaturate all four colors
}
RGBpalettecolors[i] = (CRGB)palettecolors[i]; //convert to RGB
RGBpalettecolors[i] = gamma32((uint32_t)RGBpalettecolors[i]);
}
@ -195,7 +194,17 @@ CRGBPalette16 generateRandomPalette(CRGBPalette16 &basepalette)
RGBpalettecolors[1],
RGBpalettecolors[2],
RGBpalettecolors[3]);
}
CRGBPalette16 generateRandomPalette(void) //generate fully random palette
{
CRGBPalette16 random = CRGBPalette16(
CHSV(random8(), random8(160, 255), random8(128, 255)),
CHSV(random8(), random8(160, 255), random8(128, 255)),
CHSV(random8(), random8(160, 255), random8(128, 255)),
CHSV(random8(), random8(160, 255), random8(128, 255)));
return generateHarmonicRandomPalette(random);
}
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb

View File

@ -65,7 +65,8 @@ class NeoGammaWLEDMethod {
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
uint32_t color_add(uint32_t,uint32_t, bool fast=false);
uint32_t color_fade(uint32_t c1, uint8_t amount, bool video=false);
CRGBPalette16 generateRandomPalette(CRGBPalette16 &basepalette);
CRGBPalette16 generateHarmonicRandomPalette(CRGBPalette16 &basepalette);
CRGBPalette16 generateRandomPalette(void);
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
void colorKtoRGB(uint16_t kelvin, byte* rgb);