Concept: Retro 3D Art
I was inspired by old school computer graphics that you would see in movies like The Matrix. Because of this, I knew that I wanted to make some ASCII art in the signature green color that most retro graphics used. After some experimenting, I decided to make an ASCII representation of a Menger Sponge, which is a fractal geometry that I thought would be very interesting to look at.
Process
I began by creating a sample video that I could use to turn into ASCII art. To do this, I created a 3D cube in Processing, which is a predecessor of P5.js. I attempted to do this in P5.js, but found the saveFrame()
function too limiting. I created a simple box using the 3D renderer in Processing, and added some lighting to give the sketch some dynamic range. This is important as I needed to use the difference in brightness later on when converting the video to ASCII, and the greater the dynamic range is the easier it is to perceive the ASCII video.
void setup() { size(600, 600, P3D); } float a = 0; void draw() { background(0); noStroke(); spotLight(10, 80, 240, width/2, height/2, 400, 0, 0, -1, PI/4, 2); pointLight(255, 0, 0, width/2, height/2, height/2); ambientLight(100, 0, 100); fill(255); translate(width/2, height/2); rotateX(a/2); rotateY(a/2); rotateZ(a/3); box(280); a+=PI/100; saveFrame("src/box-######.png"); }
I incremented the rotation angle by a fraction of pi because I wanted to be able to count when the cube resets to its original position. This made it easier to create a video that could be looped seamlessly.
Once I had the output frames, I combined them together using Microsoft Movie Maker. The final result was this video:
Next, I wanted to work on converting this footage to ASCII art. I followed Daniel Schiffman’s coding challenge on creating ASCII text images. After experimenting with the video size and character density arrays, the following sketch was the result I got:
However, I wanted to create something a bit more complex. This is when I remembered an old project that I worked on by following another one of The Coding Train‘s challenges, which was the Menger Sponge coding challenge. After generating the frames and compiling them into a video, this was the result:
All I had to do then is to insert this video into the original code and play around with different parameters until I got the desired result.
Code Highlights
I’m really proud of the code that makes the animation look like its being built up slowly using ASCII characters. The way I achieved this is basically by filtering out the highlights on the Menger sponge. When I compiled the video, I saw that the lower right corner of the sponge had a bright highlight on it that was blocky.
//finding the right character based on brightness of pixel let len = charArray.length; let charIndex; //playing with map values for the building up effect charIndex = floor(map(apparentBrightness, 0, 100, len, 0));
When I filtered the brightest points of the sponge out, I essentially removed the lower left corner until it got a bit darker later in the animation, which created the building-up effect.
Reflection
Compared to the first assignment, I had a more solid idea of what I wanted to achieve. Because of this, I had planned out my workflow beforehand and that streamlined the entire creative process. I knew I had to create source animation and then convert it to ASCII characters. This made my code more readable, and I had better control of the sketch overall.
However, the building-up animation that I am most proud of is dependent on the source video. It looks the way it is because in the source animation the highlights are blocky as well. If I wanted to recreate this project, I want to work on some logic that allows the effect to be more generalizable. Maybe I could filter out sections of the object based on a distance function instead of the brightness levels. That way I can substitute different source videos and still get the cool effect.
Sources
- Retro Computer Graphics – Behance
- ASCII Text Images – The Coding Train
- Menger Sponge Fractal – The Coding Train
- Relative luminance – Wikipedia