New pattern: Oasis - relaxing light on water

I just posted a new pattern - Oasis - to the library.

A few people have recently brought up porting FASTLed’s Pacifica effect – it’s a lovely pattern, but the implementation is very idiomatic to FASTLed. So I thought I’d see if I could do something similar, and similarly peaceful, in a Pixelblaze friendly way.

This is the result – layers of blue/green waves with subtle shifts in hue, and occasional whitecaps where the waves collide. (All controlled by UI sliders, of course.) Runs reasonably fast too.

Also available from my GitHub repository here.


I normally wouldn’t post about a pattern update but –

While fixing an annoying occasional phase offset glitch I noticed that my math for scaling wavelength to strip size was totally broken. Oasis looked great on the 10 meter strips I built it for, but it wasn’t doing the right thing on anything smaller. Now it does.

I’ve also added a user “wavelength” slider so you can adjust to taste. There’s also a new “Hue” slider for sunrise/sunset effects. Short video below shows the new version on a 16x16 matrix.

Already updated in my pattern repository, will update in the main Pixelblaze library shortly.


First off I really like it! One thing I noticed with Pacifica and your Oasis is that it looks fantastic as a led strip but to me looks “off” on a 2d matrix. I really can’t explain how it looks off but it doesn’t feel like it is flowing in 2d more only in 1d. Perhaps I need to play with the sliders. Perhaps because the four layers are changing in 1d of an array… I guess it might take a lot more arrays if you wanted the wave movement to be in 2d. Just thinking out loud.

1 Like

It is a 1D pattern inherently and only has render, no render2D or render3D. Whipping up a 2D version that uses x and y would be a fun challenge :slight_smile:

@zranger1 has some interesting parametric wave generator functions going on in there!


@devoh, as @wizard says, it’s fundamentally a 1D thing for now. I’ve got 2D wave patterns in the works though. They should work particularly well on Pixelblaze 3!

1 Like

VERY cool @zranger1 ! I can’t wait to see that and play with it on my PB V3 when it arrives. Thanks for not taking what I said as a criticism. It is amazing what you did and looks really nice.

I wonder if in a 2d space a perlin like noise function might be more efficient… Is there a built in perlin noise function on the PB?

No but @jeff did some great porting

Perlin / Simplex Noise (plasma effect)

1 Like

Man… way too many projects, way too little time! I do want to play with procedural noise - bet there are a bunch of ways to generate an interesting pattern. But the physics thing… the interactions between waves can look really cool. I’m thinking about a sound-reactive ripple tank for starters, something like this: (click and drag the mouse around in the tank to see waves go everywhere.)

1 Like

It looks pretty good on my house, one of my favorite patterns. Thanks @zranger1!


@mnielsen, those lights look fantastic on your house! I bet it’s really stunning reflecting off new snow just after a storm!

1 Like

Not sure why, but I get this
I assume it has to do with my array length which is 1440 pixels long. It looks like the n term becomes negative which obviously will index poorly into an array.

Yeah, setting the wavelength slider at one end or the other (I forget which) on a long strip can cause that. The fix is to just change the line to:
``511 * abs(n%1)```
You only have to do it on layer1 – the rest should be fine as is.

This is a classic integer overflow bug - in the line above the one that generates the error, the calculated value of n winds up being larger than 32767, which flips its sign bit.

I’ve put the "abs(n%1) patch in the repository version, and I’ll shortly reorder the calculations to keep it from happening again.

Thanks for catching it, @scruffynerf!

Wasn’t me. :grinning:. Thanks should go to @spazzle

However, I question the use of abs, rather than just a simple limit function like [I said use min at first, forgetting that N would be negative, never mind that]

Aarrgh! Sorry – late night. Thank you, @spazzle!

abs() works because I need only the fractional part, and it is still valid, even after the overflow.

(also, as a complete sidenote, abs() is just a hair faster than min(), and pretty much everything you can get the vm to do is faster than the same thing done in user code. Here’s the short pattern I use as a testbed for timing individual operations.)

// NOTE: test with LED Type set to No LEDs and pixel count set to 1

export function beforeRender(delta) {
  for (i = 0; i < 3000; i++) {
    var a = random(100) - 50   // -50 to 50
//   a = a ^ (a >> 31)    // abs by xor vs bit mask  (43.4 fps @ 3000 iterations)
//   a = abs(a);          // system abs              (50.2 fps @ "      ")
//   a = min(0, a)        // system min              (48.9 fps @ "      ")

export function render(index) {
  hsv(0, 1, 1)

just a quick link to Translating from FastLED to PixelBlaze

because that didn’t link here to a PB version of Pacifica.

And yes, we need a real 2d version of this someday.

It’s on the way! I just need there to be a few more hours in the day…

1 Like

Beautiful pattern. Here’s my pseudo-2d version. Zig zag of 250 px wound around a single pane of window glass -


Oh, I like that idea! It’d be fun to build something like that into a fake skylight!