Award Site Teardowns
中文

Food for Fish

Food for Fish is a point-and-click adventure game for the browser that the Belgian graphics programmer Kris Temmerman made to test WebGPU, and every frame of it is drawn by a WebGPU engine the author wrote from scratch. The hero is a bald little man who builds websites all day and who collects one pair of underpants after another to find the golden underpants of Genghis Khan that his grandfather chased all his life. At the start, the little man stands in a photo studio holding a coffee while the title writes itself beside him stroke by stroke. Visitors click the floor to make him walk and click an outlined object to make him look at it or use it.

Kris Temmerman is the only name credited on the game, which won FWA of the Day, FWA of the Month for May 2024 and FWA of the Year for 2024.

A bald little man in red-trimmed white underpants holding a coffee cup in a grey photo studio, with a rash on his chest and the black hand-written title FOOD FOR FISH to his right
A bald little man in red-trimmed white underpants holding a coffee cup in a grey photo studio, with a rash on his chest and the black hand-written title FOOD FOR FISH to his right

01Concept

In the note inside the game's menu, Kris Temmerman writes that the aim was to see what WebGPU could do, which led to a little WebGPU engine and this "game" built with it. The FWA description is a single line calling it a WebGPU experiment. The author turned the experiment into a point-and-click adventure with a story, not a tech demo page. Visitors walk through every room to keep the story going, and so they see every kind of light the engine can draw. The game also turns this into a joke, because the job the little man takes is an "underwear simulator" for an ad agency, and each step of his work at the computer shows how a 3D picture is rendered.

The story begins with a short monologue in which the little man says that his grandfather died two years ago after a life spent hunting the golden underpants of Genghis Khan, while he himself only builds websites and nothing ever happens to him. He then reads an email in which the ad agency asks for the underwear simulator, and he decides to feed the fish first. Every clue after that leads to a pair of underpants, starting with the fish, which leave him a gift that turns out to be his grandfather's old underpants, and a pair a hunter lost in the woods. Once the simulator is delivered, the agency mails him a package with underpants inside, a bird house blown crooked by the wind drops a girl's underpants, and a glowing flower lets his invention make a pair that glows. With all of them collected, the little man has his milling machine cut a key, opens his grandfather's locked bookcase and finds a letter from his grandfather inside. He then digs up the grave at night, finds the golden underpants, and the game ends on "THANKS FOR PLAYING!!".

The game sets its pace with one small task after another, so visitors only ever need to work out the next step. The little man's lines say what comes next, for example that he should feed the fish before going out, or that he should make a key before he can open the bookcase. Tasks that take time never make visitors wait, and instead finish when visitors come back to the lab after doing something else, which is how the key and the invention machine work. The next thing to find gives off a small sparkle every three to six seconds, and when visitors are stuck, the little man mutters a reminder when he stops walking.

The game screen has only two fixed controls, a cardboard tag reading INVENTORY at the top left, which drops a tray holding the underpants collected so far, and a menu button at the top right. The menu holds volume sliders for music and sound effects, the author's note, a link to the source code on GitHub and a Develop checkbox labelled spoilers! crash warning!. Turning Develop on opens the engine's own developer panel at the top left, where visitors can step through the layers that make up the picture, tune the lighting and image quality, and change the progress of every quest line directly. The author has made the engine's debugging tools part of the site's content, handed to visitors who want to see how it works.

02Design

Every scene in Food for Fish looks like a miniature model sitting on a table. The living room and the lab both lack the wall facing the visitor, and the camera always looks straight in, like looking through glass into a cut-open dollhouse. The two rooms are in fact the left and right halves of one model. The garden is a long side view with the woods and the grandfather's grave on the left, the pond in the middle and the little man's house on the right, cut off at the front by a slice of soil. The opening and the ending take place in a grey photo studio that holds only the little man and hand-written words, kept apart from the rooms of the game.

Each scene has its own lighting, and the lighting is what changes most on screen. The living room has a ceiling lamp, a wall lamp and a table lamp in warm orange (#FF955C, #FF914A and #FFB574), which make the red armchair, the wooden bookcase and the potted plants glow warmly. The lab has a blue bulb (#103DF8), a red lamp and a cyan-green lamp, so its wall shades from rose to blue-violet to teal while a flask on the table glows fluorescent green. The garden has daylight under a sky that fades from deep blue at the top (#007ABD) to pale blue near the horizon (#8CD6EB), with the hills and trees in the distance blurred into soft colour. At night the garden turns deep blue, and most of the light comes from the lantern by the grave and the glowing underpants on the little man.

The art direction has the feel of a handmade model. The little man looks as if he were sculpted from clay, with fine bumps on his skin and a rash on his chest. His face is drawn with the fewest possible marks, two white round eyes, two black pupils and one line for a mouth, and he blinks every few seconds while his pupils glance to the side now and then. The props in the rooms tell the story. The lab has a poster reading The House off Gauss, and the living room has a map of the Mongol empire with a red dotted route and a framed photo of the golden underpants.

The whole interface looks hand-drawn on cardboard, which sets it against the polished 3D scenes. The INVENTORY tag and the menu button are two pieces of cardboard, and the menu is a ragged cardboard card with a drawing of a smiling fish. A line of small print at the bottom of the menu has the author asking visitors to excuse the developer-style writing and art. When the cursor rests on an object that can be used, a cream outline appears around the object together with a small cardboard icon. The icon tells visitors what a click will do. An eye means looking, a foot means walking over and an arrow means going to the other room, while a fish, a flower, a key or a shovel means using something the little man carries.

The lab lit in red, blue and teal, with a cream outline around the laptop on the desk, a cardboard eye icon beside it, a mail icon with a red number 1 on the laptop screen, and the bald little man standing on the left
The lab lit in red, blue and teal, with a cream outline around the laptop on the desk, a cardboard eye icon beside it, a mail icon with a red number 1 on the laptop screen, and the bald little man standing on the left

Each time the little man finds a pair of underpants, a cardboard package card drops into the middle of the screen, and these cards are the most playful designs in the interface. Each card parodies a kind of product packaging, so the grandfather's pair is "ORGANIC PANTS" next to a drawing of a cow labelled FREE RANGE, and the hunter's pair is "AR17-TACTICAL" military-grade underwear. The pair from the ad agency comes with a hand-drawn football star and the words "FANCY $$$ PANTSY", and the girl's pair carries "Live Laugh Buy now" and "dermatologically tested". Every card is put together the same way, with a halftone photo of the underpants cut out and stuck on cardboard. Marker doodles, blacked-out words and "MADE IN CHINA" surround the photo, and the same "USE PANTS" button sits at the bottom right.

Four cardboard package cards in a grid, ORGANIC PANTS with FREE RANGE at the top left, REAL MEN PANTS with AR17-TACTICAL at the top right, FANCY $$$ PANTSY at the bottom left and Live Laugh Buy now at the bottom right, each with a USE PANTS button in its corner and a blurred scene behind it
Four cardboard package cards in a grid, ORGANIC PANTS with FREE RANGE at the top left, REAL MEN PANTS with AR17-TACTICAL at the top right, FANCY $$$ PANTSY at the bottom left and Live Laugh Buy now at the bottom right, each with a USE PANTS button in its corner and a blurred scene behind it

The little man's lines are set beside him in Georgia, a serif typeface whose strokes end in small feet. The text is white, with key words in gold (#E6CC80) such as GRANDPA, GOLDEN UNDERPANTS and UNDERWEAR SIMULATOR. Every letter also carries a very dark brown edge, so the lines stay readable on a bright wall or in shadow. The lines always appear on the side of the little man that faces the middle of the screen, so the edge of the frame never cuts them off. The game title, the closing credits and the large words in the menu are hand-written strokes that match the cardboard interface.

The game is designed only for desktop browsers with WebGPU. On a laptop screen 1366 pixels wide, the scenes scale down and the layout stays the same as on desktop. On phones and tablets the game never starts, and the screen shows a single picture instead. The picture shows the little man with his coffee next to an apology that begins "Sorry, No mobile for now :(" and asks visitors to try a desktop browser with WebGPU, such as Chrome. When the browser window is very narrow, the game zooms the room out so that all of it fits on screen, and it hides a potted plant in the corner of the living room.

03Motion

When Food for Fish opens, the screen stays black for a little over two seconds, and then the little man appears out of the dark within a second, slowly at first and quickly at the end. Two seconds later the title FOOD FOR FISH starts writing itself stroke by stroke and finishes in about three seconds, slower at the first and last strokes than in the middle. A line is then drawn under the title, and this line is really the loading bar, growing with the download in the background and retracting from one end to the other once the download is done. Throughout this time, steam rises from the little man's coffee and sways gently.

The camera of Food for Fish follows the cursor for the whole game. Moving the cursor to the left turns the whole scene slightly to the left, and moving it to the right turns it to the right. The near and far objects shift against each other as if seen through a window from different angles. The camera chases the cursor quickly at first and then more slowly, and it has almost caught up less than a second after the cursor stops. In the garden the camera also follows the little man sideways with a slight lag, and it stops at the edge of the garden when he reaches either end.

After a click on the floor or on an object, the little man turns toward the target over half a second and starts walking halfway through the turn. He walks in a straight line at a constant speed, blends from standing to walking over half a second, and turns to face the target when he arrives. His lines slide out a little from beside him and fade in within half a second. The first ten characters of a line appear at once and the rest type out at about ninety characters per second, and each click turns to the next line with a soft click sound. When the little man goes to the other room, he walks to the door in the middle first, and the camera then pans to the next room in about two seconds, moving quickly at first and slowing down at the end. Going from the opening into the lab, the picture instead darkens over a second and a half, stays black for a second and brightens again over three seconds.

The underwear simulator sequence is where the game acts out the 3D rendering process for visitors. The little man stands at his computer and starts typing, and each click adds one more step in the air of the lab. A single glowing triangle appears first, then a cloud of glowing triangles, then the triangles join into a wireframe of underpants, which gets a pattern and then shading before the finished pair appears on the laptop screen. Each step comes with a line, from "Let's start with rendering a triangle!" to "and it's done", so visitors click their way through the whole rendering process themselves.

A wireframe of underpants made of glowing triangles floats in the air of the lab, the little man stands at the computer typing with his back to the camera, and the line and UNDERWEAR SIMULATORS. appears beside him with UNDERWEAR SIMULATORS in gold
A wireframe of underpants made of glowing triangles floats in the air of the lab, the little man stands at the computer typing with his back to the camera, and the line and UNDERWEAR SIMULATORS. appears beside him with UNDERWEAR SIMULATORS in gold

The scenes are full of small movements that need no input from visitors. Two fish swim along random paths in the pond with their tails swinging, leaves keep falling in the garden, and grass and leaves sway in the wind. Waveforms run across the oscilloscope screens in the lab, and the digital display of an instrument on the shelf shows the game's current frame rate. When the milling machine cuts the key, its head and table move back and forth, and the sparks from the cut flicker and light up the area around the machine. At night, the light from the lantern and the glowing underpants moves with the little man.

The cards and buttons of the interface all move with a slight bounce. The menu card and the package cards drop in from a little above with a whoosh sound, overshooting slightly within a third of a second before they settle. Closing a card sends it up and out within a tenth of a second. As a card drops in, the scene behind it blurs and darkens by half within half a second, so the eye goes straight to the card. After a click on USE PANTS, the little man hitches the underpants up, his underpants change to the new pair at once, and he says a line such as "Looks great on me!". The picture holds at 60 frames per second in the opening, the lab, the living room, the garden by day and by night, and with the menu open.

04Engineering

Food for Fish uses no ready-made engine such as three.js, and every frame is drawn by a WebGPU engine that Kris Temmerman wrote in TypeScript and published on GitHub. The page itself is a static Next.js export hosted on GitHub Pages, and it contains nothing but one WebGPU canvas. All animation timelines are handled by GSAP, sound by Howler, and matrix and vector maths by gl-matrix and math.gl. At startup the engine asks the browser for the high-performance GPU and requires two optional texture features. If the user agent is a phone or tablet, or the WebGPU request fails, the page draws the unsupported-device picture on a 2D canvas instead, with one picture for wide screens and one for tall ones.

The engine of Food for Fish uses deferred rendering, so each frame starts by writing the scene's colour, normals, metalness and roughness, emission and depth into a set of G-buffers. The engine then computes ambient occlusion in compute shaders, based on Intel's published XeGTAO, and denoises the result. Lighting is split into three passes, one each for the opening, the interiors and the garden, all using a GGX-based PBR model. Every point light has its own cube shadow map, and of the six lights indoors only those in the visible half of the room update their shadows. The sun outdoors uses two shadow maps, with the near one updated every frame and the far one every other frame, and at night the lantern by the grave adds one more cube shadow map.

One frame of the lab split into four layers, with the colour layer without lighting and white walls at the top left, the normal layer that shows surface directions as colours at the top right, the grey ambient occlusion layer with contact shadows at the bottom left, and the final lit frame with red, blue and green lights at the bottom right
One frame of the lab split into four layers, with the colour layer without lighting and white walls at the top left, the normal layer that shows surface directions as colours at the top right, the grey ambient occlusion layer with contact shadows at the bottom left, and the final lit frame with red, blue and green lights at the bottom right

After lighting, the engine runs a series of post-processing passes. Screen-space reflections add the reflections on the floor and the water, transparent objects get a pass of their own, and depth of field follows the composite. The blur amount for depth of field is computed from depth and stored in the alpha channel of the frame, and the blurred background behind the menu simply turns these depth-of-field settings up. Bloom only picks up the parts brighter than a threshold, and a grade for exposure, contrast, saturation and vignette follows. FXAA then smooths the edges, and the lines of text and the cardboard interface are drawn last on the same canvas. The opening scene runs about 66 render passes per frame, most of them for shadows, while the lab and the living room run about 50 to 56 and the garden about 35 to 40.

The cream outline around a hovered object is a separate pass of its own. The engine draws the hovered object alone into a black-and-white mask, blurs it horizontally and vertically, and subtracts the original mask, which leaves only a ring around the object. While drawing the mask, the engine compares the object's depth with the depth in the G-buffer, so the parts of the outline hidden behind other objects are drawn fainter. When an object is made of several models, such as the box, door and flag of the mailbox, the models are outlined together.

The hand-written words, the face and the small motions are all made with very cheap techniques. The author drew the strokes of the title, the credits and the loading bar with a mouse inside the engine, and each stroke is stored as a string of dots. Each dot is drawn as an instanced quad whose shader keeps only a circle, so the writing animation simply raises the number of dots drawn, and the strokes are written into the G-buffer along with the scene, which is why the lamps light them too. The lines of dialogue use a multi-channel signed distance field (MSDF) atlas of Georgia, which stays sharp at any size. The little man's eyes and mouth are computed in the face shader from a few circles and one line segment, and a blink only sets the radius of the eyes to zero. The fish follow paths from a noise function, and the plants sway by sampling a scrolling noise texture in world space, moving more the higher they are, with their shadows swaying along.

The gameplay is written as a set of simple state machines. Each quest line has its own sequence of states, so the fish line runs from start to taking the fish food, feeding the fish, the underpants appearing and taking them. Every clickable object in a scene has a trigger that reads the current state to decide which icon to show on hover and which scene to play on click. Picking the clicked object relies on a ray cast from the cursor against simplified collision models. All the scenes are sequenced with GSAP timelines, which is why the Go fast switch in the developer panel only needs to speed up GSAP's global timeline five times to speed up the whole game.

The game's assets are exported from Blender as glTF and converted by the engine into its own binary data. Opening the site downloads about 31.8 MB in total, and the largest file is the garden scene data at about 11 MB. The 566 WebP textures add up to about 12.1 MB, and every object has a colour map, a normal map and one texture packing metalness, roughness and ambient occlusion together, most of them 1024 pixels square. The 14 sound files take about 2.7 MB, about 2 MB of which is a recording of Variation 25 of Bach's Goldberg Variations. Loading happens in two batches, and the first holds only the little man, the opening scene, the font and the hand-written strokes, which is enough for the title screen. The rooms, the garden, the textures and the sound load in the second batch, hidden behind the seconds in which the title is being written.

The server of Food for Fish starts sending the page within 0.1 to 0.35 seconds, but the screen stays black until the first frame at 2.1 to 2.7 seconds. The little man appears at about three seconds, the title is fully written at about nine seconds, and the last textures arrive at around ten seconds. During loading the page freezes for at most about 0.2 seconds, and nothing on screen jumps. The engine can also lower its own quality. If the frame rate stays under 30 per second for 100 frames in a row, it renders its internal frames at CSS pixel resolution while the canvas on screen keeps its size. On screens with a pixel ratio of 1, this changes nothing.

Food for Fish can only be played with a mouse, and the page has no element that can take focus. Tab, Space, Enter, the arrow keys and Escape all reach the page, but the game responds to none of them. Screen readers only find the page title, and the page does not declare a language. The game's code never reads the system's reduced-motion setting, so every animation plays as usual when that setting is on.

05Scores and Team

Award Source Date Score
FWA of the Day The FWA 2024-05-07 87 POINTS, DAYS 4
FWA of the Month The FWA May 2024 Monthly award, no separate score
FWA of the Year The FWA 2024 Yearly award, no separate score

Food for Fish is the FWA of the Year for 2024, chosen by more than 500 jurors from the twelve FWA of the Month winners. Its FWA of the Day scored 87 points and was filed under the Experimental and Game categories.

Credit Who they are Track record
Kris Temmerman A freelance graphics programmer in Belgium specialising in WebGL and WebGPU FWA 4

Kris Temmerman made the engine, the game, the art and the writing of Food for Fish alone, and the closing credits add only a performer, since the music is a Bach recording played by Shelley Katz. As of this report, Kris Temmerman has won four FWA awards, three of them for this game. The fourth is an FWA of the Day in February 2026 for Stuff by Kris Temmerman, a personal portfolio built as a pirate game.

06Archive

Award date
2024-05-07
Awards
The FWA FOTD 2024-05-07, The FWA FOTM 2024-05, The FWA FOTY 2024
Site
https://foodforfish.org/
Credits
Kris Temmerman
Design
spatial
Build
realtime
The FWA
87 POINTS, DAYS 4. https://thefwa.com/cases/food-for-fish
Stack
Own WebGPU engine (TypeScript), deferred rendering, XeGTAO ambient occlusion, MSDF text, Next.js, GSAP, Howler, gl-matrix
Total assets
About 31.8 MB, of which scene and animation data is about 15.2 MB, WebP textures about 12.1 MB and sound about 2.7 MB
Speed
FCP 2,112 to 2,728 ms (black screen until then), title fully written at about 9 seconds, CLS 0. 60 fps in every scene