REFERENCE
- Gallery page: https://magpui.com/en/i/tilt-shift-ascii-shrine-diorama-e35198
- First frame (image): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/tilt-shift-ascii-shrine-diorama-e35198/shot.jpg
- Clip (mp4): https://dnioievkvxejjbxgwvko.supabase.co/storage/v1/object/public/media/tilt-shift-ascii-shrine-diorama-e35198/clip.mp4
- Original post: https://x.com/dhruvtwt_/status/2116932748250321023 by @dhruvtwt_
Before building, download the first frame and look at it. If ffmpeg is available, download the clip and extract frames (ffmpeg -i clip.mp4 -vf fps=2 frame-%02d.png), then study the motion frame by frame. Match what you see; the text below describes it, the frames are the truth.
BUILD: Build a full-screen, endlessly looping WebGL scene that looks like a tiny living scale model drawn entirely in coloured monospace text. A 3D diorama is seen from steeply above: a line of red torii-style gates runs down a green grassy cliff along a dark stone path, ending at a turquoise sea with white foam at the shoreline. Clusters of gold and red trees sit on the sides, small white flower patches and grey stone lanterns dot the path. The camera sweeps slowly left and right while the top and bottom of the frame blur away like a miniature photograph. Every pixel of the render is replaced by a glyph, so it reads as text up close and as a painting from a distance.
DESIGN SYSTEM: Square canvas filling the viewport (1:1 in the reference), no UI chrome. The scene is converted to a grid of about 200 columns by 100 rows, each cell a monospace glyph on a dim, blurred copy of the underlying render (about 25 percent brightness). Glyph colour is sampled from the graded 3D render. Palette estimates: grass #4f7a2a to #2f5a1c, torii red #d1342a, tree gold #c9a227, tree red #b8352b, sea #1f8a9a with foam #e8f1f2, path and cliff edge #3b2a20, lantern stone #bdb8b0, background shadows #101a10. Glyph rules per surface class: grass as slanted strokes / | \ that lean with a wind noise, water as ~ and - with # for foam, stone and wood as - = #, tree canopies as clusters of o * +. Faint horizontal scanlines (1px dark line every 3px, about 15 percent opacity) add a CRT feel.
MOTION: (1) Camera sweep: the camera orbits a few degrees back and forth around the scene centre, roughly 8 degrees amplitude over a 24 second loop, easing sinusoidally (ease-in-out sine, cubic-bezier(0.37, 0, 0.63, 1)), always looking steeply down at about 60 degrees. (2) Wind: grass glyphs choose their slant from a noise field that scrolls slowly, period about 4 seconds. (3) Water: wave glyphs shift by one cell every 300 to 500 ms and foam # characters roll toward the shore on a 3 second loop. (4) Small details: petals or leaves drift across the frame, and a tiny animal walks along the path. (5) The whole animation loops seamlessly with no cut. Space pauses it.
SECTIONS: Single scene, no layout sections. Parts: the 3D render target (half-float, with the surface class written into the alpha channel), the glyph pass (full-screen shader plus a canvas-generated glyph atlas), the tilt-shift pass (blur on the top 25 percent and bottom 25 percent of the frame, ramping linearly, sampled on a golden-angle disc of about 24 taps), and the optional pause control.
IMPLEMENTATION: Three.js with a custom full-screen post-processing shader (WebGL2). Render the scene to a half-float render target, with each material writing a surface class id into alpha. In the glyph shader, divide the screen into the grid, sample the render at the matching mip level, read the class, measure the brightness gradient for edge direction, and pick a glyph from the atlas by class, brightness and wind noise. Use instanced meshes for grass, flowers and leaves, a small water shader for the sea, and baked terrain from tiled textures. Respect prefers-reduced-motion by freezing the camera and wind and showing a single static frame. Keep it at 60fps on a laptop: cap the device pixel ratio at 1.5, keep the glyph grid at or below 200 by 100 cells, and pause rendering when the tab is hidden. Add a visible focus state and keyboard shortcut (Space) for pause.
ADAPT TO THE PROJECT: Reuse the project's existing fonts, colour tokens and canvas or WebGL setup where they exist, map the palette to the closest existing tokens, and never copy logos, brand names, photos or the original scene art; build the world from simple primitives and your own textures or placeholders instead.
SUCCESS CHECK:
- Up close the frame reads as coloured text glyphs, and from a distance as a painted miniature, with grass, water, stone and trees each visibly using a different glyph set.
- The top and bottom bands are clearly blurred while the middle stays sharp, and the camera sweeps smoothly and loops with no visible jump.
- It holds about 60fps at 1440 by 1440, and freezes cleanly with prefers-reduced-motion.