FastLED 3.9.3
Loading...
Searching...
No Matches
noisepalette.hpp
1
5
6#pragma once
7
8#include <stdint.h>
9
10#include "FastLED.h"
11#include "fx/fx2d.h"
12#include "lib8tion/random8.h"
13#include "noise.h"
14#include "ref.h"
15#include "xymap.h"
16
17FASTLED_NAMESPACE_BEGIN
18
19FASTLED_SMART_REF(NoisePalette);
20
21class NoisePalette : public FxGrid {
22 public:
23 NoisePalette(XYMap xyMap)
24 : FxGrid(xyMap), speed(0), scale(0), colorLoop(1) {
25 width = xyMap.getWidth();
26 height = xyMap.getHeight();
27
28 // Initialize our coordinates to some random values
29 mX = random16();
30 mY = random16();
31 mZ = random16();
32
33 setPalettePreset(0);
34
35 // Allocate memory for the noise array using scoped_ptr
36 noise = scoped_ptr<uint8_t>(new uint8_t[width * height]);
37 }
38
39 // No need for a destructor, scoped_ptr will handle memory deallocation
40
41 void lazyInit() override {}
42
43 void draw(DrawContext context) override {
44 fillnoise8();
45 mapNoiseToLEDsUsingPalette(context.leds);
46 }
47
48 const char *fxName(int which) const override { return "NoisePalette"; }
49
50 void mapNoiseToLEDsUsingPalette(CRGB *leds);
51
52 uint8_t changeToRandomPalette();
53
54 // There are 12 palette indexes but they don't have names. Use this to set
55 // which one you want.
56 uint8_t getPalettePresetCount() const { return 12; }
57 uint8_t getPalettePreset() const { return currentPaletteIndex; }
58 void setPalettePreset(int paletteIndex);
59 void setPalette(const CRGBPalette16 &palette, uint16_t speed,
60 uint16_t scale, bool colorLoop) {
61 currentPalette = palette;
62 this->speed = speed;
63 this->scale = scale;
64 this->colorLoop = colorLoop;
65 }
66 void setSpeed(uint16_t speed) { this->speed = speed; }
67 void setScale(uint16_t scale) { this->scale = scale; }
68
69 private:
70 uint16_t mX, mY, mZ;
71 uint16_t width, height;
72 uint16_t speed = 0;
73 uint16_t scale = 0;
75 CRGBPalette16 currentPalette = PartyColors_p;
76 bool colorLoop = 0;
77 int currentPaletteIndex = 0;
78
79 void fillnoise8();
80
81
82
83 uint16_t XY(uint8_t x, uint8_t y) const { return mXyMap.mapToIndex(x, y); }
84
85 void SetupRandomPalette() {
86 CRGBPalette16 newPalette;
87 do {
88 newPalette = CRGBPalette16(
89 CHSV(random8(), 255, 32), CHSV(random8(), 255, 255),
90 CHSV(random8(), 128, 255), CHSV(random8(), 255, 255));
91 } while (newPalette == currentPalette);
92 currentPalette = newPalette;
93 }
94
95 void SetupBlackAndWhiteStripedPalette() {
96 fill_solid(currentPalette, 16, CRGB::Black);
97 currentPalette[0] = CRGB::White;
98 currentPalette[4] = CRGB::White;
99 currentPalette[8] = CRGB::White;
100 currentPalette[12] = CRGB::White;
101 }
102
103 void SetupPurpleAndGreenPalette() {
104 CRGB purple = CHSV(HUE_PURPLE, 255, 255);
105 CRGB green = CHSV(HUE_GREEN, 255, 255);
106 CRGB black = CRGB::Black;
107
108 currentPalette = CRGBPalette16(
109 green, green, black, black, purple, purple, black, black, green,
110 green, black, black, purple, purple, black, black);
111 }
112};
113
114inline void NoisePalette::setPalettePreset(int paletteIndex) {
115 currentPaletteIndex = paletteIndex % 12; // Ensure the index wraps around
116 switch (currentPaletteIndex) {
117 case 0:
118 currentPalette = RainbowColors_p;
119 speed = 20;
120 scale = 30;
121 colorLoop = 1;
122 break;
123 case 1:
124 SetupPurpleAndGreenPalette();
125 speed = 10;
126 scale = 50;
127 colorLoop = 1;
128 break;
129 case 2:
130 SetupBlackAndWhiteStripedPalette();
131 speed = 20;
132 scale = 30;
133 colorLoop = 1;
134 break;
135 case 3:
136 currentPalette = ForestColors_p;
137 speed = 8;
138 scale = 120;
139 colorLoop = 0;
140 break;
141 case 4:
142 currentPalette = CloudColors_p;
143 speed = 4;
144 scale = 30;
145 colorLoop = 0;
146 break;
147 case 5:
148 currentPalette = LavaColors_p;
149 speed = 8;
150 scale = 50;
151 colorLoop = 0;
152 break;
153 case 6:
154 currentPalette = OceanColors_p;
155 speed = 20;
156 scale = 90;
157 colorLoop = 0;
158 break;
159 case 7:
160 currentPalette = PartyColors_p;
161 speed = 20;
162 scale = 30;
163 colorLoop = 1;
164 break;
165 case 8:
166 case 9:
167 case 10:
168 SetupRandomPalette();
169 speed = 20 + (currentPaletteIndex - 8) * 5;
170 scale = 20 + (currentPaletteIndex - 8) * 5;
171 colorLoop = 1;
172 break;
173 case 11:
174 currentPalette = RainbowStripeColors_p;
175 speed = 2;
176 scale = 20;
177 colorLoop = 1;
178 break;
179 }
180}
181
182inline void NoisePalette::mapNoiseToLEDsUsingPalette(CRGB *leds) {
183 static uint8_t ihue = 0;
184
185 for (uint16_t i = 0; i < width; i++) {
186 for (uint16_t j = 0; j < height; j++) {
187 // We use the value at the (i,j) coordinate in the noise
188 // array for our brightness, and the flipped value from (j,i)
189 // for our pixel's index into the color palette.
190
191 uint8_t index = noise.get()[i * height + j];
192 uint8_t bri = noise.get()[j * width + i];
193
194 // if this palette is a 'loop', add a slowly-changing base value
195 if (colorLoop) {
196 index += ihue;
197 }
198
199 // brighten up, as the color palette itself often contains the
200 // light/dark dynamic range desired
201 if (bri > 127) {
202 bri = 255;
203 } else {
204 bri = dim8_raw(bri * 2);
205 }
206
207 CRGB color = ColorFromPalette(currentPalette, index, bri);
208 leds[XY(i, j)] = color;
209 }
210 }
211
212 ihue += 1;
213}
214
215inline void NoisePalette::fillnoise8() {
216 // If we're running at a low "speed", some 8-bit artifacts become
217 // visible from frame-to-frame. In order to reduce this, we can do some
218 // fast data-smoothing. The amount of data smoothing we're doing depends
219 // on "speed".
220 uint8_t dataSmoothing = 0;
221 if (speed < 50) {
222 dataSmoothing = 200 - (speed * 4);
223 }
224
225 for (uint16_t i = 0; i < width; i++) {
226 int ioffset = scale * i;
227 for (int j = 0; j < height; j++) {
228 int joffset = scale * j;
229
230 uint8_t data = inoise8(mX + ioffset, mY + joffset, mZ);
231
232 // The range of the inoise8 function is roughly 16-238.
233 // These two operations expand those values out to roughly
234 // 0..255 You can comment them out if you want the raw noise
235 // data.
236 data = qsub8(data, 16);
237 data = qadd8(data, scale8(data, 39));
238
239 if (dataSmoothing) {
240 uint8_t olddata = noise.get()[i * height + j];
241 uint8_t newdata = scale8(olddata, dataSmoothing) +
242 scale8(data, 256 - dataSmoothing);
243 data = newdata;
244 }
245
246 noise.get()[i * height + j] = data;
247 }
248 }
249
250 mZ += speed;
251
252 // apply slow drift to X and Y, just for visual variation.
253 mX += speed / 8;
254 mY -= speed / 16;
255}
256
257inline uint8_t NoisePalette::changeToRandomPalette() {
258 while (true) {
259 uint8_t new_idx = random8() % 12;
260 if (new_idx == currentPaletteIndex) {
261 continue;
262 }
263 currentPaletteIndex = new_idx;
264 setPalettePreset(currentPaletteIndex);
265 return currentPaletteIndex;
266 }
267}
268
269FASTLED_NAMESPACE_END
central include file for FastLED, defines the CFastLED class/object
RGB color palette with 16 discrete values.
Definition colorutils.h:997
Definition fx2d.h:16
void draw(DrawContext context) override
Definition xymap.h:39
void fill_solid(struct CRGB *targetArray, int numToFill, const struct CRGB &color)
Fill a range of LEDs with a solid color.
LIB8STATIC uint8_t dim8_raw(uint8_t x)
Adjust a scaling value for dimming.
Definition scale8.h:703
LIB8STATIC_ALWAYS_INLINE uint8_t qadd8(uint8_t i, uint8_t j)
Add one byte to another, saturating at 0xFF.
Definition math8.h:31
LIB8STATIC_ALWAYS_INLINE uint8_t qsub8(uint8_t i, uint8_t j)
Subtract one byte from another, saturating at 0x00.
Definition math8.h:103
uint8_t inoise8(uint16_t x, uint16_t y, uint16_t z)
8-Bit, fixed point implementation of Perlin's noise.
Definition noise.cpp:512
CRGB ColorFromPalette(const CRGBPalette16 &pal, uint8_t index, uint8_t brightness, TBlendType blendType)
Get a color from a palette.
@ White
Definition crgb.h:615
@ Black
Definition crgb.h:479
const TProgmemRGBPalette16 RainbowStripeColors_p
HSV Rainbow colors with alternatating stripes of black.
const TProgmemRGBPalette16 OceanColors_p
Ocean colors, blues and whites.
const TProgmemRGBPalette16 CloudColors_p
Cloudy color palette.
const TProgmemRGBPalette16 ForestColors_p
Forest colors, greens.
const TProgmemRGBPalette16 LavaColors_p
Lava color palette.
const TProgmemRGBPalette16 PartyColors_p
HSV color ramp: blue, purple, pink, red, orange, yellow (and back).
const TProgmemRGBPalette16 RainbowColors_p
HSV Rainbow.
LIB8STATIC uint16_t random16()
Generate a 16-bit random number.
Definition random8.h:50
LIB8STATIC uint8_t random8()
Generate an 8-bit random number.
Definition random8.h:40
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:34
Functions to generate and fill arrays with noise.
Fast, efficient random number generators specifically designed for high-performance LED programming.
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Definition chsv.h:11
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:39