This week, I decided to continue along the lines of the flickering screens. But this time I would tackle complex neon sign / light animations.
The idea
The hypothesis I had was to use AI generated images with neon lights and use shader graph to add animation to the lights. I spend some hours just thinking about the solution before starting work on it. Trying to come up with a simple but powerful way to animate the lights. I came up with an UV-rotator based animation that would be very simple to set up.
The steps this would require are:
- Isolating the neon light shapes.
- Painting out the lights from the image.
- Creating a light UV texture map for reading the correct animation track.
- Creating an animation texture with separate tracks for all individual lights.
- Creating a shader graph that ties it all together
Now there was nothing left to do but do it!
Creating the masks
For the image, I chose the hamburger restaurant exterior as it had the most neon lights.

First, I used the “Black & White…” adjustment layer to get a clean as possible mask from the yellow lights. Not sure if this was the smartest way, but it worked great for this graphic.


After I had a decent starting point, I cleaned up the mask. This mask would be used to draw the lights on the image in Unreal later.
I would also need a version of the image without the lights, so that when the lights are shut off, the image would not look weird.

This version of the image would not need to be perfect. There would be lights on most of the time. I hoped that Unity’s bloom post process effect would blend in the neon light text on top of the image beautifully.

I left the neon lights on in the shadowed version of the image. I figured I could reveal the original letters from this version, as it would be loaded in VRAM anyway.
I also created a reflection mask in case I wanted to add planar 3D reflections to the location.
Now we get to the fun part! In After Effects I set up a 256×512 composition that had as many “lanes” as the image had animatable neon lights. In this case it was 34. Each lane would have its own V value ranging from 0 to 1. Lately I have been experimenting a lot with image based UV coordinates and I find it very interesting!

In this image, the R channel would be the U value of an UV map. So I can reconstruct UVs for the image using time for V and R channel for U. Creating a map that I can read an image as a layered animation file.

I created this image with shape layers in After Effects. Each shape has an expression in the fill channel that sets the color to match the desired UV coordinate based on the shape layer index. This allows me to later change the number of neon light elements and the UV mapping progress is automated.
division = thisComp.layer("Controller").effect("NeonLights")("Slider");
ID = thisLayer.index;
WidthOffset = (1/division)/2;
Multiplier = 1-ID/division;
OffsetValue = linear(Multiplier, WidthOffset, 1-WidthOffset);
[1,1,1,1]*OffsetValue
For the image to be usable as an UV map, the composition color depth needs to be set to 32 bits (float).
Creating the animations
So using this ID texture, not vertex UV data, I can turn the lights on and off based on the data in the animation texture. I am not sure if I can explain it properly, but it easier to show.
The weird black and white checkers image is one example of the animation file. Each neon light has its own track running up the image. Each time the pixel read is white, the light is on each time the pixel read is black, the light is off. This file then loops and this gives the illusion of an elaborate animation setup for the lights. When in reality it is just a simple image with some diagonal lines and checkerboards.

I added some fade out to the points when the lights are turned off so simulate the neon pipes cooling off. The left side of the image is the animation tracks for the lights around the burger shape and the windows, the right side is the animation of the text.
Creating the shader
The shader setup is mostly the same as always apart from the animated lights material. This is a very simple setup and explains the trick very well.

There are 3 main areas in the thing. The UV animation, the color and the flicker. The shader is set to additive unlit and is then layered on top of the background image.
The UV animation is built simply by using the red channel of the ID mask as the U channel and using time multiplied by speed as the V channel. This will produce an UV that crawls up the animation texture and haves each different neon light read it’s own line of the animation texture.
The flicker works the same, but instead of reading the animation file, we read a noise. Causing the letters to flicker.
The color is simply a version of the background image with the lights on that is multiplied by the alpha of the ID mask map. I then have a brightness multiplier I can use to overdrive the emissive value to introduce glow on the lights in the neon lights pass.

So there you have it yet another way to use simple shaders to easily add more life to the AI generated background images.
The 3D scene
The 3D scene generation was the same old. Use fSpy to get the camera data, model a simple scene in blender and import to Unity.

This camera data is then used to get a simple 3D model going in Blender.

That model is then sent to Unity where lighting and interactable hotspots are added.

Leave a Reply