Touch Grass
grassmeadow
OpusSol
Winner
CheapestFastest
Opus wins. Opus paints the meadow the prompt asked for: a low golden-hour sun, backlit blades of every height and a hand wake you can see at a glance; Sol built a working field for a tenth of the price in a third of the time, but its hazy, flat light and far-off view make it read like a lawn.
Who won? You pick
Pick the build you liked best to see what everyone else thinks.
Scorecard
Opus3Sol0
| Criterion | Opus | Sol |
|---|---|---|
| Golden-hour light | Warm low sun, blades glow where it shines through them, tree silhouettes on the horizon. | Grey-green haze and a pale sun: correct, but flat. |
| The field | Tall seed heads, short tufts and sun-bleached tips mixed in patches. | Dense and even, closer to a mown lawn than a meadow. |
| Demo: hand wake and gust | The S-curve wake and the gust read clearly, even small. | The wake is hard to spot at card size. |
| Cost | $10.10 | $0.96 |
| Time | 1h06m00s | 24m00s |
| Overall | Winner | – |
The prompt
Build **"Touch Grass"**: a real-time, interactive 3D meadow of **tens of thousands of grass blades** that people **brush through with their hand**, **mow**, **plant flowers in**, **blow** and **set on fire**, alive with wind, light, critters and **synthesised sound**, rendered with native **WebGPU** and **WGSL**. It should feel like the calmest, most satisfying thing on the internet: you move your hand and the grass answers. No score, no levels, no tutorial screens. The only goal is a hidden one (see Easter egg). ## Priorities Build it in this order, and finish each tier properly before starting the next. A polished tier 1 beats a broken everything. 1. **Must be excellent:** the dense field, the hand brushing the blades (bend away, spring back with a little wobble), the wind waves and the golden-hour light; the demo mode. 2. **Must work:** the five tools (Hand, Mower, Seeds, Blower, Fire) with regrowth, the critters, day / night, sound, the control card, the Easter egg. 3. **Polish:** dandelion seeds, the hidden cat, fireflies following the hand, depth of field, pollen motes. Never ship a feature half-working: if something from tier 3 can't be done well, leave it out cleanly. ## Deliverable - One self-contained `.html` file with all JavaScript, WGSL and CSS inline. - **No external requests of any kind**: no libraries, CDNs, web fonts, images, textures or audio files. Generate everything procedurally in code (sound included, see Sound). Use system font stacks. - It must run inside a sandboxed iframe (`sandbox="allow-scripts allow-pointer-lock"`). Do not use `localStorage`, cookies, `alert`, pop-ups or top-level navigation, and wrap any storage access in `try/catch`. - This must be a live simulation, not a video, a pre-baked animation, a static render or a 2D fake. ## The meadow - A gently rolling meadow on a small hill under a wide sky, seen from a low three-quarter view, as if you are kneeling at the edge of it. The field fills most of a square frame, with a soft horizon, a few distant trees as silhouettes and light haze. - **Grass:** about **60,000 to 150,000 blades** on desktop (scale down automatically on phones and slow GPUs, never below about 20,000). Each blade is a tapered, slightly curved strip with its own height, width, lean, stiffness and colour, from fresh green to sun-bleached yellow, with darker roots and brighter tips. Mix in some taller seed-head grasses and clover so it doesn't look like a lawn carpet. - Density and height vary in natural patches; the field never shows a visible grid or tiling. - A few wildflowers and **dandelions** already grow in the field. ## Physics - Every blade is simulated, not just shader-swayed: a **spring per blade** (bend direction, bend amount and velocity, stored in GPU buffers and updated in a compute shader) pulled back towards upright by its stiffness, with damping, so blades **overshoot and wobble** a little when released. - **The hand:** the pointer projects onto the ground as a soft round hand of influence. Blades inside it bend **away from the hand and along its direction of motion**, harder when the hand moves faster, then spring back after it passes, leaving a fading trail you can see for a second. A slow pass parts the grass like running fingers through it; a fast swipe makes a wave. - **Wind:** constant gentle sway plus **gusts that roll across the field as visible waves** (bright sheen bands where blades bend and catch the light), from a slowly changing direction. Wind and hand forces add together. - Blades never pass through the ground, never stretch, and never jitter at rest. - **Fixed simulation timestep** with bounded substeps, decoupled from frame rate. On a slow frame, drop simulation time rather than exploding. ## Tools A tool picker with **Hand**, **Mower**, **Seeds**, **Blower** and **Fire**. Dragging the empty sky orbits within limits. The default tool is Hand. ### Hand - As described in Physics. A tap pats the grass down in a small circle that springs back up. ### Mower - Dragging pushes a small mower across the field that **cuts the grass short** in a clean stripe, throwing up a little spray of clippings. Cut stripes have the classic light / dark lawn sheen depending on direction. - **You can write in the grass**: cutting is precise enough to draw letters and shapes. - Cut grass **slowly grows back** over about 20 to 30 seconds (faster with the Regrowth slider), so the canvas always resets itself. ### Seeds - Tapping plants a flower: it **sprouts, grows and blooms** in about a second (a few procedural varieties: daisies, poppies, cornflowers, buttercups), and sways with the grass. Holding scatters several. Cap at about 300 flowers, removing the oldest gracefully. - A butterfly sometimes lands on a new flower. ### Blower - Holding blows a strong stream of air from the hand: a **shockwave** pushes the blades flat in a cone that ripples outward, lifts loose clippings and dandelion seeds, and sends nearby butterflies tumbling away. Releasing lets everything spring back with a big, satisfying wave. ### Fire - Tapping lights a small fire: it **spreads outward in a ragged ring** through the grass, with flickering flames, glowing embers, rising smoke and a black ash scar behind it. Mowed stripes and flowers act as natural firebreaks or fuel (cut grass burns slowly, tall grass fast). - The fire **burns out by itself** within a few seconds and never takes the whole field. Then fresh green shoots sprout through the ash and the meadow regrows in about 20 to 30 seconds. - Cap the number of fires burning at once (about 5). Use pointer events with **pointer capture** so drags never drop, and support mouse, pen and touch (including a second finger on mobile without breaking the first drag). ## Life - **Grasshoppers** hidden in the grass leap away in arcs when the hand or mower comes near, then land and disappear again. - **Butterflies** (a handful) flutter over the field, rest on flowers, and scatter from the Blower. - **Dandelions:** poking one makes its seed head burst into parachute seeds that drift away on the current wind, then the stem slowly grows a new puff. - **A sleepy cat** is hidden somewhere in the tall grass (only its ears and a tail tip show). Brushing near it makes it lift its head, blink slowly and stretch; brushing it again makes it roll over. It never runs away. - **Pollen motes** float in the sunlight, swirling around the hand. ## Day and night - A **Time of day** slider runs from dawn through golden hour (the default) to night. - At night the sky deepens with **stars**, the grass turns silvery blue in moonlight, and **fireflies** rise from the grass, blink, and drift lazily **towards the hand**, gathering around it when it stays still. ## Easter egg - If the hand stays **resting in the grass** (pointer down on the field, or hovering over it, barely moving) for **10 seconds**, birdsong swells, the light warms, and a small badge gently appears: **"✓ Grass touched. You may return to the internet."** with a short soft chime. It stays a few seconds, then fades. Never hint at it in the UI. ## Sound Every action has a **synthesised sound effect**, generated live with the **Web Audio API** (oscillators, filtered noise, envelopes). **No audio files, no samples, no external requests.** - **Brushing:** a soft, airy rustle (band-passed noise) that follows the hand's speed and how much grass it is moving; silent when the hand is still. - **Wind gusts:** a low whoosh that swells as each gust wave passes. - **Mower:** a gentle buzzing hum (not harsh) with a soft chopping texture while cutting. - **Seeds:** a small pop and a soft rising "bloom" tone as each flower opens, pitched slightly differently each time. - **Blower:** a breathy rush that swells while held. - **Fire:** crackles and a low roar that grows and fades with the flames. - **Life:** quick clicks for grasshoppers, a soft purr from the cat, a faint shimmer for fireflies. - **Ambience:** distant birdsong by day, crickets at night, both very quiet. - **Easter egg:** a short, warm, gentle chime. Rules: - Create the `AudioContext` only after the first user gesture (browsers block it before that). Handle a `suspended` context by resuming it on interaction, and wrap every audio call in `try/catch` so a failure can never break the toy. - A **mute button** with a speaker icon, **sound on by default**, and the `M` key toggles it. A master gain, a limiter / compressor and no clipping. - Limit simultaneous voices (about 12) so rapid actions never turn into noise or glitch. ## Camera and keys - **Camera:** dragging the empty sky orbits within limits; the wheel or a pinch zooms within limits (from the default kneeling view down to a close-up at blade level); double-clicking the sky resets the view. - **Keyboard:** `1` Hand, `2` Mower, `3` Seeds, `4` Blower, `5` Fire, `N` toggles night / day, `C` Cinema, `M` mute, Space pauses or resumes, R resets the meadow. ## Rendering (WebGPU and WGSL) Aim for the look of a sunny nature film at golden hour, not a video-game lawn. - **Instanced blades** drawn from GPU buffers, bent by the simulation in the vertex shader, with smooth curved normals so blades shade like real leaves. - **Translucency:** blades glow warm yellow-green when the sun is behind them (strong backlit subsurface), with a soft specular sheen along their length and darker self-shadowed bases (ambient occlusion towards the ground). - **Sky and light:** a procedural sky gradient with a low warm sun, soft atmospheric haze towards the horizon, long soft shadows from the trees and flowers, and a gentle sun glow. - **Fire:** emissive flames and embers that light the nearby grass, smoke that drifts with the wind, and an ash texture that regrows to green. - **Post-processing:** HDR with filmic tone mapping, light bloom on the sun, flowers, fireflies and fire, a subtle **depth of field** when zoomed in close, and a light vignette. Keep the image crisp. - Level of detail: fewer, wider blades in the distance so the far field stays dense without the cost. - Build pipelines once at start-up and preallocate buffers for every cap (blades, flowers, particles, critters). Never create shaders, pipelines or geometry during interaction. Handle resize and device-pixel ratio (cap at 2). - Include an automatic **quality scaler**: if the frame rate drops, reduce blade count, shadow and post-effect resolution before ever touching the physics feel. - If WebGPU is not available, show a clear, well-designed message explaining that the piece needs a WebGPU browser (for example recent Chrome, Edge or Safari) and why. Do not fall back to WebGL or fake it. ## Interface A calm, light interface that stays out of the way. The meadow is the hero, and UI must never cover it on desktop or mobile (on narrow screens, controls collapse into a compact bottom sheet). **Top left** - Small caps: `POKEABLE · SPECIMEN 006` - A large italic serif heading on two lines: *Touch* / *Grass.* - Caption lines: "Go on." / "Nobody's watching." / "It grows back." **Top right:** a small live status dot with `WEBGPU · LIVE`, a **speaker icon button** for sound (with `ON` / `MUTED`), and `PAUSED` when paused or `WEBGPU UNAVAILABLE` on fallback. **Right panel: control card "Meadow"** Style it as a **floating control card**: a rounded card (about 20px corners) in a soft off-white, with a soft drop shadow and no hairline borders, about 240px wide, in the plain system sans-serif font. A bold sentence-case card title, bold sentence-case section labels, tools as rounded pills or tiles (the active tool tinted and ringed in a fresh green accent), chunky sliders (a 6px rounded track filled with the accent up to the value and a round white thumb), live values in small rounded monospace chips, secondary buttons as rounded light-grey chips without borders, toggles as on/off switches (label on the left, switch on the right), and **Pause / Resume** as a solid dark full-width pill. The card can be collapsed to a small button. On narrow screens it becomes the bottom sheet with rounded top corners. - The tool picker: **Hand**, **Mower**, **Seeds**, **Blower**, **Fire**, each with a small drawn icon and its key number. - **Wind** slider (calm to stormy) with its live value. - **Time of day** slider (dawn, golden hour, night) with its live value. - **Grass height** slider with its live value. - **Regrowth** slider (how fast cut and burnt grass grows back) with its live value. - **Sound** slider (master volume) with its live value. - Buttons: **Reset meadow**, **Mute**. - Switches: **Critters** (on by default), **Slow motion** (¼ speed) and **Cinema** (`C`: hides every piece of UI and the cursor for clean screen recordings; a tap or `C` brings everything back). - A **Pause / Resume** button. **Bottom left:** a one-line hint that changes with the tool: - Hand: "Run your hand through the grass." - Mower: "Drag to mow. Try writing your name." - Seeds: "Tap to plant a flower. Hold to scatter." - Blower: "Hold to blow. Let go for the wave." - Fire: "Tap to light it. It always grows back." Under it, live readouts computed from the simulation: **blades**, **flowers**, **grass cut** (% of the field) and **wind** (km/h, illustrative). Values update smoothly, not every frame. **Bottom right:** a collapsible **"How it grows"** section, 4 to 6 plain-English lines explaining the per-blade springs, how the hand and wind push them, how mowing and regrowth work, how the fire spreads, and how the sounds are synthesised. Respect `prefers-reduced-motion`: soften UI transitions and calm the default wind. The grass still responds fully to the user. ## Demo mode (required) If the URL has `?demo=1`, auto-play a 4-second loop with no user input: the object drops in, wobbles, gets poked or sliced once, then settles. For this toy that means: - **Hide all UI** (text, panel, status, hint, readouts, cursor). Only the meadow, sky and critters are visible. Show an invisible hand: only its effect on the grass is visible. - Use one **fixed demo quality preset** (no automatic quality scaler, so every frame looks the same), golden hour, no fire. - **Sound is completely off in demo mode:** never create an `AudioContext`, play nothing. - A fixed camera at the default kneeling view, the field filling the square frame. - A deterministic loop that restarts every 4.0 s of real time from the identical state: - **0.0 to 0.6 s:** the meadow at rest, swaying gently; a little pollen in the light. - **0.6 to 2.0 s:** the hand sweeps in a smooth S-curve through the middle of the field, parting the grass in a clear visible wake. - **1.4 s:** a grasshopper leaps out of the hand's path in a high arc and lands. - **2.0 to 3.0 s:** a wind gust rolls across the field as a bright wave from left to right; a butterfly lifts off a flower. - **3.0 to 4.0 s:** everything springs back and settles to the same gentle sway as at 0.0 s, so the loop restarts cleanly. - Use no randomness in demo mode (fixed seed for the field). Drive the simulation from real elapsed time with the fixed timestep, so the loop lasts 4 s even at low frame rates. - The demo is recorded in a slow software renderer: **the wake and the gust must still read clearly at 15 fps**. If needed, use fewer blades in demo mode (but keep the field looking dense). - Start moving within 1 second of the page loading.