"Fairy" lights in a matrix on a clear vinyl sheet

I’m stuck dealing with non-fun IRL stuff for the next little while, but here’s a really simple SDF-based dancing tree pattern that should work on most 2D displays. (I left a little code for other shapes in so you could add stars and decorations and other stuff as you like!)

// Simple SDF Dancing Christmas Tree
// MIT License
// Take this code and use it to make cool things!
// 2021 ZRanger1

// UI control variables
export var objectSize = 0.4;
export var lineWidth = 0.1;
export var dance = 0;

export function sliderDance(v) {
  dance = (v >= 0.5);

function signum(a) {
  return (a > 0) - (a < 0)

// signed distance functions for various shapes, adapted for 2D. 
// Math from https://iquilezles.org/www/articles/distfunctions/distfunctions.htm
function circle(x,y,r) {
  return hypot(x,y) - r;

function square(x,y,size) {
  dx = abs(x) - size;  d1 = max(dx,0);
  dy = abs(y) - size;  d2 = max(dy,0);
	return min(max(dx, dy), 0.0) + hypot(d1,d2);

function triangle(x,y,r) {
	return max((abs(x) * 0.866025) - (y * 0.5), y) - r / 2;

function hexagon(x,y,r){
     x = abs(x); y = abs(y);
     return  max((x * 0.5 + y * 0.866025),x) - r;

function hexStar(x,y,r) {
  // rescale to pointy parts of star
  x = abs(x*1.73205); y = abs(y*1.73205); 
  dot = 2 * min(-0.5*x + 0.866025 * y,0);
  x -= dot * -0.5; y -= dot * 0.866025;
  dot = 2 * min(0.866025*x + -0.5 * y,0);
  x -= dot * 0.866025; y -= dot * -0.5;
  x -= clamp(x, r * 0.57735, r * 1.73205);
  y -= r;
  return signum(y) * hypot(x,y) / 1.73205;

// interior distance on this is slightly weird. Still
// looking for a reasonable fix.
function cross(x,y,size) {
  x = abs(x); y = abs(y);
  if (y > x) { tmp = x; x = y; y = tmp; }
  qx = x - size; qy = y - size / 5;
  k = max(qy,qx);
  if (k > 0) {
    wx = max(qx,0); wy = max(qy,0);
    return hypot(wx,wy);
  } else {
    wx = max(size - x,0); wy = max(-k,0);
    return -hypot(wx,wy);

function tree(x,y,r) {
  var d = triangle(x,y+.225,r*0.175);
  d = min(triangle(x,y,r*0.3),d);
  d = min(triangle(x,y-.2,r*.5),d);
  d = min(square(x,y-0.47,r*0.01),d)
  return d;


var t1, timebase;
export function beforeRender(delta) {
  timebase = (timebase + delta/1000) % 1000;
  t1 = timebase * 10;

export function render2D(index,x,y) {
  var d,radius,th;
  var v = 0;
  // Introduce a sinewave "wiggle" along the x axis. 
  // Caution: This is neither subtle nor tasteful!
  if (dance) {
    radius = 1.2-hypot(x,y)*2.4;
    th = radius * radius * sin(radius + t1);
    x = (cos(th) * x) - (sin(th)* y);      

  d = tree(x,y,objectSize);
  v = 1-(d/lineWidth);  
  h = (y < 0.41) ? 0.3333 : 0.0124;

  hsv(h, 1, v)

Actually, with this technique, you could pretty easily take some existing fairy wings (or make some) and hot glue fairy lights to them. I’d suggest not having wires sticking up/out. I’ll have to see if I’ve got some to do this to. (I have a large cheap costume collection)

Awesome! I had just started trying to adapt the geometry morphing demo to do exactly this but obviously having never written a pattern myself yet I ran up against some required learning and got pulled away before I could finish (or even make a dent? haha)

I will try yours out, thank you!

1 Like

I thought about asking for custom but figured they were probably selling so much in time for Christmas they wouldn’t be interested in my custom order.

My wife grabbed it from the fabric store I think it was 6mil and only a couple bucks a meter. It’s actually thin enough to “static cling” to the window however I did fasten it at the top anyway.

1 Like

It’s looks really good! Thanks again for this.

I added some yellow bands and tweaked the shapes. I learned a lot while trying to add “lights” as I wanted them to be fixed to the tree but still move with it. I know how I can’t achieve this effect now at least and discovered which way to go next but I’ve run out of time so this will have to do!

I did try a few other things like diagonal bands and rainbow colours etc but at the end of it I preferred this version.


I think just wrapping the renderer with a cartesian-to-polar transform should do the trick:

r = hypot(x, y)
phi = (atan2(y, x) + PI_2) % PI_2

Rainbow Color Alas Led Wing With Led Lights Isis Wing Glowing Isis Dancewear Remote Control Circus Led Light Luminous Costumes| | - AliExpress ← watch the video, these are clearly … somewhat addressable. The specifications don’t reveal much.

1 Like

Like this?


Exactly like that, wow. Perfect! I looked for so long haha. Okay so I want double density but I can interlace them for that.

Kudos to @Scruffynerf and @zranger1 for the work on SDF and seven segment functions. Got a new year’s pattern going.



Needs a good scrolling 2022… Adjusting the center of the shape should do that.

So $60+ for 20x20 (400pixel) grid with 10cm spacing… Good price point to keep in mind.

Since 2 200 strands would require a output expander, this ends up cheaper than DIY likely, and yes, you could interlace and get roughly 5cm spacing for 800 pixels with 2.

you can also email them for custom orders/sizes/spacing etc.

Don’t feel bad, these just came out like this week. Before this I was cutting strands and soldering T junctions by hand, more times than I’d like to admit or ever do again.

1 Like

Ahh okay I feel better now… Thanks so much for the link I’m most definitely going to try them and see what it’s like side-by-side with my DIY. And if it’s good I’ll use the other 400 fairy lights I have for something else!


OMG. Those are just looking great! Who’s gonna be first to try? I’m guessing @gmcmicken! I may be just behind you, tho!

I just emailed them to see if I can get 16x25 at 4cm to match my existing panel.

1 Like

Unfortunately they were unresponsive to my inquiries for customization but I bought one from the AliExpress listing to have a look at it anyway.

1 Like

That was my experience, also. I inquired with them some time ago and got no response… at least they are consistent.

I find it frustrating to have to buy from unresponsive vendors. Is there any reason why we could not produce these or something similar here in the USA?

@JustPete I’ve reported my findings in the other thread