To make ASCII in webGL: First, you render your complete scene but in black and white (or in color if you are up for the challenge).
Then in a post-processing step, you take that white and black result and match it to an ASCII character. So, light/white pixels map to really dense characters like "@", and darker\black pixels might map to a less dense character like the dot. "."
- ThreeJS ASCII Effect example
- How to create ASCII Header (and much more)
- How to render a video into ASCII in threeJS
- Rendering ASCII images with p5
Meet new people and explore the world with Babbel
If you've always wanted to learn a new language, Babbel will be the most productive 10 minutes of your day. Trusted by over 10 million subscribers worldwide, the subscription-based language learning platform can get you confidently conversing in a new tongue in just three weeks. This isn't your grade school textbook: the bite-sized lessons, available in 14 languages, teach you localized vocabulary you'll actually use in the real world. Plus, speech recognition technology helps you perfect your accent. Sign up today and get up to 60 percent off your subscription.Learn More!
In this demo by Marco instead of changing the color of the ASCII, this site (mostly) lets the white space around the character give the impression of light/dark. Some characters like "w" cover more space than the "/", resulting in a darker/lighter impression.
Marco mentioned he creates the glyphs directly in the shader for this demo for fun's sake, like characters were designed in the Commodore64. However, the more performant and standard approach is to pre-create (with a canvas2D for example) a glyph texture used to sample the glyphs from.
Like a font spite sheet, but the texture should be evenly spaced and, for easy math in the shader, ordered from lighter to denser glyphs.
Once you have your texture ready, you need to sample it based on the lightness of the current cell. To get the cell lightness, you either need to render at a low resolution or lower the resolution in the shader like so:
vec2 grid = vec2(uResolution / 10.);
vec2 gridUV = floor(uv * grid)/grid;
float dist =step( distance( gridUV * aspect, uMouse * aspect), 0.1);
vec4 renderColor = texture2D(uTex, gridUV);
This site by 0+X as the shade gets darker, so does the color. You can see it more if you focus on dark to black transition. And there's even some blue light added to the result.
The mouse has some mouse trains like Nathan made in this article but rendered in ASCII.
Once you have your pixelated render, you need to sample the correct glyph based on the lightness of the cell, in this case I have 8 glyphs in my texture one next to the other. So depending on the red channel of the render, I'll jump to the next one:
float glyphCount = 8.;
vec2 fAsciiGrid = fract(uv * grid);
fAsciiGrid.x /= glyphCount;
vec2 jump = vec2(floor(renderColor.r * glyphCount) / glyphCount, 0.) ;
vec4 character = texture2D(uASCII, fAsciiGrid + jump );
vec4 result = character;
This site by STUDIO FREIGHT is the perfect example of a striking yet subtle ASCII effect. They've even made a great ASCII tool in React (which is also on the site) where you can lower the resolution and the glyphs real time.
I wanted to show Aino's agency website as an amazing combination of two WebGL effects, the ASCII rendering and a fluid dynamic. However, there is no WebGL on this website. This ASCII is pure HTML updated in every frame.
This approach can be used in other parts of the site where the canvas wouldn't work because of layering. Plus, you don't need to sync the canvas to the scroll.
James's portfolio/blog is beautiful, and loads instantly, and James even wrote an article on the step-by-step process of making a similar ASCII scene.