Building Nutfall's Tornado: From Flat Sprites to a GPU Vortex
Dev notes · June 2026
Nutfall has a modifier called the funnel: a swirling vortex that pulls falling nuts toward its column. On paper, simple. Making it actually look like a tornado — and run fast enough to have several on screen at once — turned into one of the more stubborn problems of the whole game. Here's the journey.
The cheap attempts
The first tries were all variations on "fake it with a texture." A flat cone mesh with a swirl texture looked like a paper party hat. An emoji 🌪 sprite was instantly readable but obviously a sticker, not part of the 3D scene. A particle system of little glowing dots read as "a spray of confetti," and when we tightened it into a column it became a wavy ribbon — more smoke-signal than storm. Each version was a little better, and each one still looked, in the bluntest possible review, bad.
The fix: raymarch the smoke
The thing that finally worked was a raymarched volumetric shader. Instead of drawing an object, the GPU marches a ray through a procedural "density field" shaped like a funnel — narrow rope at the bottom, billowing wall-cloud at the top — carved by animated noise so it churns and swirls, with a quick lighting pass so it has a bright side and a shadow side. That gives real volume: the smoke looks like it has depth because, mathematically, it does.
The lesson about working with AI tools
We build a lot of this with AI coding assistants, and the tornado was a clean experiment in how to use them well. We tried three ways to ask for the effect: a vague request (with some choice words thrown at the AI when it missed), a precise technical brief that named the exact technique, and a "maximum effort" mode left to figure it out itself. The precise brief won by a mile — it reached a good result in a fraction of the time and compute. The takeaway isn't "AI is magic" or "AI is useless"; it's that knowing the underlying tech — that the answer was a raymarch shader, not another sprite — is what lets you get there quickly. The tool is fast; the direction has to come from understanding.
Making it fast
Beautiful and unusable is still unusable. The first full-screen version ran at about 19fps — fine for a tech demo, a dealbreaker for a casual game that should be smooth on a phone. So we optimised hard:
- dropped the noise from 5 octaves to 3 (plenty for soft smoke);
- replaced the expensive self-shadow sampling with a cheap approximate one, and only ran it on the dense parts;
- cut the number of ray steps and rendered the effect at a slightly lower resolution;
- and stopped drawing it full-screen — each funnel is now a small camera-facing quad, so the shader only runs on the pixels it actually occupies.
The result: a smooth 60fps, holding up even with six tornadoes on the board at once (the march quality scales down gracefully as you add more). Same look, a fraction of the cost.
The real takeaway
Two things made the difference. First, look at what you're shipping — we kept rendering frames and judging them honestly until the effect actually read as a tornado, instead of trusting that the code "should" look right. Second, pick the right technique early: no amount of polish was going to make the sprite version great, but the raymarch approach was good almost immediately and just needed tuning.