Upgraded Pixelblaze Marquee: Gradients, Zoom, and Easy Text Tool

Hey everyone,

I just finished upgrading the standard 2D Marquee pattern and wanted to share the code. We rebuilt the rendering engine to be much more robust and added a bunch of live controls.

New Features:

  • Size Presets: Live buttons to switch between Small, Medium, Large, and “Full Height” text.

  • Advanced Colors: Switch between Solid, Rainbow, and a custom 3-Point Gradient.

  • Gradient Control: Full color pickers for the Top, Middle, and Bottom of the gradient so you can dial in sunset/fire/ice looks perfectly.

  • Helper Tool: Includes a local HTML tool that lets you type text and instantly generates the ASCII array code to paste into Pixelblaze.

You can grab the pattern code and the helper tool here: https://github.com/chromaglow/PixelBlaze-scrolling-text-upgrade

Enjoy!

function add(a,b) {
  return a+b;
}
2 Likes

Nice job! Thanks for updating to use some of the newer language features.

I originally wrote it for Pixelblaze v2, which was a lot slower.

I noticed you’re not using a circular buffer anymore - can I ask the FPS you’re getting on the largest matrix you’ve used it with? I see how you’re clearing and regenerating the bitmap every frame, and was wondering if that’s being performant for you?

If it is, and if you were willing to re-incorporate all the “teaching” comments I put in the original, I think this would be a decent upgrade to the version we ship on all new Pixelblazes!

One other suggestion - maybe export the message array. It’s really useful to be able to set it externally via websockets.

1 Like

For whatever reason, the letters appear upside down — mirrored over the Y axis — on my grid. Before I dig too deep into the code myself, got any quick suggestions for how I can flip it back over?

Can try flipping the y coordinate in your map, just add a minus.
In code: y=1-y

I’ve got dozens of other patterns I run on this grid. I’m worried I’d create a lot of new work for myself by editing the map. Maybe I did it wrong to begin with ¯\_(ツ)_/¯ but it’s too late now. I’m guessing I’ll be able to find a similar edit to the pattern.

For just this one pattern that’s upside down, invert the Y axis that’s giving you trouble by inserting a new line of:

y = 1 - y

Right at the top of the render() being used. This only flips that pattern and your others will be unaffected.

Oh yeah awesome. That’s a much simpler solution than I’d have arrived at, I’m sure. Thank you!

Thanks for the feedback Jeff! That circular buffer logic was super clever for v2.

For this version (running on v3), I switched to a stateless redraw every frame approach. It solved some sticky buffer sync bugs when dynamically zooming, and the v3 seems to handle the recalculation without breaking a sweat on my 21x27 matrix (~50 FPS).

I’ve re-added your educational comments and the ASCII table to the header, and exported the message array as requested. I pushed the updates to the repo: https://github.com/chromaglow/PixelBlaze-scrolling-text-upgrade

Quick question: I originally tried to add Up/Down scrolling direction, but I couldn’t get the orientation right—the text either looked mirrored or just garbled when trying to scroll vertically (like a Star Wars crawl). Since the font is 8x8, do you have any tips on how to map the drawChar logic for vertical crawling without rotating the whole matrix map?

One easy way to switch between vertical & horizontal with nearly 0 impact on performance relies on the fact that “render2D” winds up being a variable just like any other It just happens to contain a pointer to a render function. You can set it to any function you like, and you can change it whenever you want. So, to swap axes, something like this will work:

// create a fake empty render2D function so we have a variable we can use
export function render2D(index,x,y) {;}

// create a function that calls the actual renderer w/normal axis order
export function renderXY(index, x,y) {
  renderMain(index,x,y)
}

// and a function that swaps the axes
export function renderYX(index,x,y) {
  renderMain(index,y,x)
}

// and set render2D to whichever one you want to use.  You can do this from a control
render2D = renderYX;   // swaps x & y for vertical crawl

// rename the "real" render2D function renderMain so we can call it from our stubs.
function renderMain(index, x, y) {
  ... actual rendering logic (the "real" render2D fn)
}

If you need to, you can also flip the axes by using negative number in the scale() fn. For example, to flip y, scale(1,-1). If you want to do this, you’ll need to change the name of the scale variable in the pattern to something else, as it overrides the built-in.

1 Like

Awesome, thanks for taking the time to comment! When we cut the next base image I’d love to include this and credit you.

You know, for all this stuff about flipping or scaling or doing vertical scrolling … did you try playing with the coordinate transforms?

I wonder if you just provide the renderer for any given virtual layout of letters in space (like for vertical scrolling, left align and fill each line with characters as much as possible, then you’re implementing a carriage return essentially to get to the next line). Then it’s just translate() your way to whatever, with some clever modulus choices for repetition….

Hi Jeff,

Thanks so much for the kind words and the offer to include me in the credits! I’d be thrilled to be a part of it.

Sorry for the delay in getting back to you, I actually got laid off a couple of weeks ago from my tech job, so I’ve finally had some free time to dive back into this properly.

I just pushed a major update (V7) to the repo. Here’s a breakdown of what we changed:

**1. Vertical Stacking (Forum Suggestion to my Issue)**

You were spot on about the coordinate transforms. We tried rotating the viewport at first, but for vertical scrolling, it just made the letters sideways. We ended up taking your advice and modifying the buffer rendering logic (`beforeRender`) to chemically stack the letters vertically (row by row) instead of just spinning the world. Now the text reads “Upright” while scrolling Down, which is much more readable on tall skinny matrices.

**2. Orientation & Hardware Fixes**

My specific matrix was mounted upside down and backwards, so I added some hardcoded `1-x` / `1-y` logic to the render loop. I structured it so it’s easy for others to swap out if their wiring differs.

**3. Controls**

* **Speed**: Switched to a linear speed model so “0” actually means “Stop”.

* **Direction**: Renamed the buttons to be explicit (“Left To Right” vs “Right To Left”).

**4. Text Converter & Theme**

I gave the `text_converter.html` helper tool a facelift with a “Hacker Noir” (Black/Green) terminal theme and added a copy-to-clipboard button for convenience.

Thanks again for the original code base, it’s a blast to work with!

Best,

Ezra

1 Like