“Digital Mirror” Artwork: Crappy Old TV Shader
Artistic/Design Inspirations
For my midterm assignment, I decided to go down the “digital mirror” route. When I was first learning how to bring my webcam feed from the .js file to the .frag file, I incorporated the code from my week 3 homework to test out how it would look. I ended up really liking how it looked and I thought about building upon it to strengthen the visual communication. I did some more research into retro shaders and came across Retro CRT Shader Breakdown by Cyanilux. This was really helpful at actually picking apart/deconstructing the different elements present in the display of CRT monitors and worked as a great place to start.
Aesthetic Goals for the Project + How I Achieved Them
This project involved a lot of trial and error, tweaking values little by little until I got what I wanted! However, referencing the Retro CRT Shader Breakdown guided me in the logic/approaches/steps I needed to take to slowly form each of the components of the shader.
I pretty much used exactly the same code for the CRT shader, apart from increasing the tiling size from 50.0 to 150.0. It seemed appropriate since the resolution of the webcam feed would be much more than the size of the canvas in the Book of Shaders editor. The scan lines effect is generated with a high frequency sin( ) wave that travels up slowly using uTime. Meanwhile, the static effect is made with simple digital randomness, interpolating based on uTime so that the randomness appears to dance around.


Below are screenshots of the scrolling effect, isolating the different layers that go into it. The left image is the base gradient that travels down based on uTime, the middle image is multiplied with the randomness static, and the right image is after it is sent through the hsb2rgb( ) function.

All of these vec3’s come together at the very end to apply onto the webcam feed! This is also where I learned of the difference between multiplying and dividing colours. For example, multiplying worked well with the scan lines effect since the vec3 was mostly white, but doing so with the scrolling effect would not work well since it would produce a darker image instead.
Creative Decisions Along the Way
I thought that this project would be more fun with a little bit of interactivity!
I used p5.AudioIn( ) which by default gets the audio input from your computer’s microphone. I then used the .getLevel( ) method to measure the volume of the audio input (which I learned gives an output ranging from 0 to 1) and used map( ) to increase that range by a little bit. I use that volume level to displace the webcam feed on the x-axis, so the louder you speak, the more crazily the video moves side to side.
I felt that it was too much going on when all of the different effects are applied together, so I decided to instead make two versions that the user can toggle between. Both versions use the scrolling effect with the webcam feed, but the first one includes the CRT shader while the second one includes the horizontal scan lines.
During the presentation, I had the interaction to toggle between shader effects set to mouseIsPressed. I forgot that the project had to run fullscreen in the browser, so I implemented that and switched the shader toggle to keyIsDown(32) instead (32 = key code for the spacebar). I also tweaked the fullscreen template code a little bit so that you can toggle back and forth between fullscreen and a regular sized window.
Final Result


Click here to go to the p5.js sketch!
Notes for interaction:
- Click on the canvas to toggle fullscreen mode.
- Hold spacebar to toggle between shader effects.
- Speak into your microphone to affect the displacement of the video.