A rotating 3D scene drawn in characters chosen by shape, not just brightness.
A small software rasterizer draws a trefoil knot, a kettle, a Greek temple or a gyroscope over a ray-traced grid floor at 4x6 samples per character cell. Each cell is described by six region averages of its shading plus a four-bin histogram of edge orientation from Sobel gradients of both luminance and depth, voted with cos-squared weights in doubled-angle space. Every glyph is rendered once and measured the same way (ink per region, Sobel orientation of its strokes), so choosing a character is a nearest-neighbour search in that feature space, cached on a quantized key. Silhouettes come out as slashes, pipes and underscores with no hand-written rules, and any glyph set you build works because the descriptors come from the bitmaps.
Try it. Drag to spin the model. Hover a cell to inspect its samples, feature vector and closest glyphs. Switch models, Color, Terminal and Paper modes, glyph sets and cell size with the buttons, edit the glyph set character by character, or Compare to see the raw render under a draggable divider (keys 1 to 4, C, G, E, [ ], S).
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a real-time 3D ASCII renderer with JavaScript and the HTML canvas element. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Render a rotating torus into a small brightness buffer: sample points on its surface, rotate them, project them with perspective, keep the nearest point per pixel with a depth buffer, and shade each with a simple diffuse light.
- Split the canvas into character cells about 8 by 14 pixels. Give each cell the average brightness of its pixels in the buffer and pick a character from a ramp such as " .:-=+*#%@".
- Draw the characters with fillText in a monospace font, light on a near-black background, and animate with requestAnimationFrame.
Once that works, make it edge-aware:
- Render the buffer at 4x6 samples per cell. Run a Sobel filter on brightness and on depth to get a gradient direction at each sample, and sum them per cell into four orientation bins (vertical, both diagonals, horizontal).
- Render every candidate character once into a small offscreen bitmap and measure it the same way: ink in a 2x3 grid of regions plus the Sobel orientation bins of its strokes.
- For each cell, choose the character whose measurements are closest, so silhouettes turn into / \ | and _ automatically. Cache the answer per quantized measurement.
- Add a color mode that tints each character with the cell's average color, and let me drag to rotate.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a glyph-set editor, a green terminal mode with phosphor glow, or rendering real meshes with a triangle rasterizer.