This is a combination of two effects sometimes used for creative coding animations. Motion blur does just as it’s name suggests: blurs the motion between frames so the animation is smooth. Chromatic aberration is a technique used to shift the red, green, and blue channels to add color with forced distortion. More on each below.
Chromatic aberration is a distortion in film and photography caused by a failure of a lens to focus all of the colors on the same point on the film or sensor. Wikipedia has a nice explanation.
This distortion is typically undesirable, and a lot of work is done to prevent it with hardware and or correct it with post processing. In creative coding, this effect has been used to create color and add flare to animations. The most predominant example of this is Dave Whyte’s work (aka @beesandbombs). And as far as I can tell, he’s the one that introduced it to the creative coding community. Here is a particularly exaggerated example of his:
Dave was generous enough to share his template for this several years ago. I was interested in implementing this effect in some of my sketches, but I’ve been working with p5js not processing, so it wasn’t as simple as
ctrl+c / ctrl+v. I got a little closer when I found Lionel Radisson’s (@makio135) utility for p5js sketches in an Obervable notebook, but I wanted to work directly with p5js, so I’ve taken Dave’s code, tried to understand it, and convert it for p5js.
Chromatic aberration animation effect
The chromatic aberration effect is achieved by separating the red, green, and blue channels. True chromatic aberration in photography and film occurs all over the image or in a certain region of the sensor. For creative coding animations, the convention has instead been to separate the color channels as a function of the velocity of an object. When objects are stationary, there is no chromatic aberration applied, and the color channels are offset more and more as the motion of an object increases. Here as an example with a white circle:
A couple things to note:
- The convention is to keep the red channel where the object is and to shift the green and blue channels backward away from the direction of motioon (trailing the object).
- The color shift is a function of the velocity of the object.
Because this effect is velocity-based, it’s not really representative of chromatic aberration in photography and film. It actually reminds me more of the red/blue doppler shift, which is a phenomenon that causes objects to appear blue when moving quickly toward the observer and red when moving away. So this effect could be called a reverse redshift (where red is leading instead of blue).
Motion blur can improve the smoothness of animations dramatically. Here is a nice example from Etienne Jacob (@etiennejcb). Note how much smoother the animation on the right looks compared to the left.
The way this has been achieved in processing is:
- Break the timestep to the next frame into multiple sub-steps
- Sketch the drawing at each substep
- Save the pixel data from the sketch into an array at each sub-steps with
- Average the pixel data after all sub-steps are complete
- Draw the the averaged pixel data onto the canvas with
I implemented this method in p5js. Pixel data is treated differently in p5js compared to processing. In processing, the rgba values are stored in a single variable, and bitshifts are used to retrieve the individual channels. In p5js, the rgba values are saved individually in separate variables. This amounts to more pixel data (4 times) with a larger pixel array in p5js compared to processing. An example of motion blur applied to a circles moving at differen velocities below. This example uses 5 sub-steps.
A couple things to note:
- The sub-steps are taken forward in time
- More sub-steps will create a smoother effect
Chromatic Aberration + Motion Blur
Both effects can be combined to create stunning results. The color channels are split and distanced based on velocity and the frames are blurred over each subsample. Here are the separate and combined effects.
Pixel averaging vs alpha blur
All of the pixel manipulation for the motion blur seemed like a lot of extra steps to me. I implemented an alternative method that achieves the same results. Rather than loading, averaging, and updating pixel data for each sketch, I change the transparency of each sub-step drawing. This provides the same result without having to save and average all of the pixel data.
- Pixel averaging: sketch -> read pixels -> repeat -> average pixels -> write pixels
- Alpha blur increase the transparency of the objects for each sub-step and overlay each sub-step over the previous
I implemented both methods with the same simple sketch of an oscillating circle. I used 20 sub-steps between each frame to capture the motion blur with red-leading chromatic aberration. The load/unload pixel requirements in p5js slow the pixel averaging method down significantly and I was only able to run the sketch at 10fps. The alpha blur method didn’t skip a beat and ran smoothly at 60fps. If these sketches were exported to png or gif, the results would be exactly the same, but the alpha blur method runs much quicker in a browser. It also requires much fewer lines of code. This technique might not work in processing (I’m not familiar enough with it to know), but it seems to be a much better alternative in p5js.
Load/Unload Pixel Method (bnb template converted to p5js):
Alpha blur method:
|Method||Pixel Avg.||Alpha Blur|
|RGBA pixel array||600k||none|
|Sketch time||100 ms||3 ms|
I also ran a test comparing more points in case one method was better as the number of objects being drawn changed. This was done on a 750 x 750 canvas with 10 sub-steps. Circles were drawn and oscillated from side-to-side for both methods. Results are in the table below.
Time to draw objects with chromatic aberration and 10 motion blur sub-steps:
|# Objects||Pixel Av (ms)||Alpha Blur (ms)|
These results will vary for each machine. They might also be very different with processing. I’m not sure. But in p5js, it seems best to stick with the Alpha Blur method - at least with the tests I’ve run. As the object count increases, the sketch time becomes unrealistically slow and and the number of sub-steps or objects would need to be decreased without excessive sketching time. Note: some (but not much) of this time is just iterating through the sketch loops and draw on the canvas. I also ran 10,000 points through both methods without any sub-steps and without any chromatic blur. The results are below.
Time to draw objects without any chromatic aberration or motion blur:
|# Objects||Pixel Av (ms)||Alpha Blur (ms)|
Summary and Templates
Chromatic aberration and motion blur is a nice way to add some color and fluidity to creative code animations. Two methods for implementing this filter have been described. A Pixel Averaging Method that reads and writes the sketch pixels for each sub-step and an Alpha Blur Method that makes uses the alpha color to add transparency to each sub-step. The alpha blur method performs faster and has quicker sketch times in p5js. There may be disadvantages for use in processing or other situations that I’m unaware of. If so, let me know!
I’ve posted templates of each method on OpenProcessing at the links below: