# Why the wall is 3D: click towers, a real sun, vanishing trees

> How Square Town's 3D favicon wall works: three.js, an orthographic camera, towers whose height is click count, hash-seeded trees and lakes, and a sun on local time.

Source: https://square.pov.town/blog/why-the-wall-is-3d

Square Town ([square.pov.town](/)) is 3D because a wall you can *read* is more useful than a wall you can only look at. Seen top-down it is a classic 2D favicon wall. Ctrl+drag (two-finger drag on touch) tilts it into a three.js scene where every favicon is a tower whose height is its click count, empty land has trees and lakes that disappear when someone buys the cell, and a shadow-casting sun sits where the real sun is at your local time. Nothing about it is required to buy a $1 square; all of it is a reason to come back and look.

> **TL;DR — the 3D wall in one table**
>
> | Thing | How it works |
> |---|---|
> | Camera | orthographic; yaw and tilt of 0 = straight top-down 2D wall |
> | Enter 3D | ctrl+drag (desktop); two-finger drag up, twist to rotate (touch) |
> | Tower height | = the square's click count; 0 clicks is a flat tile, capped at 8 cells tall |
> | Tower colour | sides tinted with the favicon's dominant colour; grey/black/white icons get a neutral slate |
> | Empty cells | deterministic (hash-seeded) trees and lakes — real geometry — that vanish when the cell is bought |
> | Life | a fish jumps from a lake now and then; a V-flock of birds every ~20–50 s, about one in six a hot-air balloon |
> | Sun | shadow-casting light that follows the viewer's local time: east 06:00, south noon, west 18:00; moonlight at night |
> | Sky | warm at dawn/dusk, blue at noon, near-black at night |
> | URL params | `?yaw=&tilt=&zoom=&hour=&theme=light\|dark` set the starting view |
> | Dependencies | three.js, vendored at `/vendor/three.module.min.js` — no CDN |

## The default view is still a 2D wall, on purpose

Every pixel-wall since 2005 has been a flat image, and everyone knows how to read one. Square Town keeps that. The camera is orthographic — no perspective, no vanishing point — and at yaw 0 / tilt 0 it looks straight down, so what you see is a grid of favicons, exactly the picture the phrase "favicon wall" suggests. Zoom is anchored on the centre square, drag pans, hover highlights an empty cell. If you never press ctrl, you never see a tower.

The choice of an orthographic camera is what makes this work. A perspective camera at a top-down angle would still show the sides of tall towers near the screen edges and distort the grid; orthographic keeps every cell the same size on screen regardless of where it is, so the flat view is a true 2D wall and the tilted view is a clean isometric-style city. Same scene, same meshes, one camera.

## Ctrl+drag tilts it — and then the wall becomes a chart

Ctrl+drag on desktop orbits the camera into 3D. On touch, a two-finger drag up tilts and a twist rotates. Tilt is capped so you can never look at the wall edge-on and lose the grid.

Once tilted, every favicon is a box with the icon on the top face and its **height equal to its click count** — Square Town calls these [click towers](/glossary/click-tower). The exact rule from the client: a square with zero clicks is a flat tile; from the first click it stands half a cell tall and grows a quarter of a cell per click, capped at eight cells. So thirty-odd clicks buys the maximum height, which keeps the skyline legible instead of letting one viral site become a spike a thousand cells tall. When a square's click count changes while you're watching, the tower eases from its old height to the new one rather than snapping.

That is the point of the whole thing: **the busiest sites are the tallest**. You can glance across a tilted wall and see where the attention is without opening a leaderboard. The 🏆 Boards in the side panel give you the same information as a top-5 list; the towers give it to you as terrain.

## Tower colour comes from the icon itself

Each tower's sides are tinted with the favicon's dominant colour, sampled client-side: the icon is downscaled, pixels are binned by hue, and the strongest *chromatic* hue wins. Grey, black and white icons have no hue to borrow, so they get a neutral slate. While the image is still loading (or if it can't be read), a colour derived from a hash of the domain stands in.

The effect is that a tilted wall looks like a city built by its residents — a red tower next to a teal one next to a slate one — rather than a bar chart with a corporate palette. It also makes your own project findable from a distance: your icon's colour is your tower's colour.

## Empty land has trees and lakes, and buying the cell clears it

Cells nobody has bought are not blank. Each empty cell is hashed on its (x, y) — deterministic, so the landscape is stable across reloads and identical for every visitor — and roughly one in eight gets a tree (a conifer or a broadleaf, real geometry: trunk plus cone or blob), while a smooth value-noise field over the same coordinates decides where the lakes are. Trees cluster, lakes are irregular, and none of it is a sprite; it all casts and receives shadows like the towers.

When someone buys a cell, the tree or the patch of lake on it disappears and the favicon tile appears. That's the "trees that vanish when you buy the land" in the title, and it does two useful things. Practically, an unbought wall never looks empty — the locked outer rings of the 1024×1024 grid are never shown at all, and the live area is scenery until it's real estate. Emotionally, it makes buying a square feel like clearing a plot rather than filling a spreadsheet cell.

Now and then a small fish jumps out of a lake, with ripples. This is unnecessary and stays in.

## Birds, and the occasional balloon

Every 20 to 50 seconds a small V-flock of birds crosses the wall well above the towers, wings flapping, shadows sweeping the ground. About one crossing in six is a slow hot-air balloon instead — one of four colours, bobbing gently. There is one early crossing a few seconds after the page loads so a fresh visitor sees the sky is alive; after that it's sparse on purpose, and it pauses while the tab is hidden so it costs nothing in the background. Everything airborne rides the same on-demand effects loop as the fish, which only runs while something is actually moving — a plain pan or zoom never wakes it. (If you want one on demand: `fw.spawnFlyer()` or `fw.spawnFish()` in the console.)

## A real sun, at your local time

The scene has one shadow-casting directional light, and its position, colour and strength follow the viewer's local clock: in the east at 06:00, due south at noon, in the west at 18:00, warm and low at the horizon. After sunset the same arc is run by a cool, dim moon. Towers, trees and lakes cast shadows on the ground and on each other. The sky beyond the wall follows the same clock — warm at dawn and dusk, blue at noon, near-black at night — and the ground is a soft grass tone rather than grey.

So the wall someone in Tokyo sees at breakfast has long shadows pointing west and a warm sky; the wall you open at midnight is moonlit. Nobody's square gets *more* light for paying more; the sun is a clock, not a rank. It's the second reason (after the towers) that the wall is different every time you look, without anyone having done anything.

## URL params: send someone the exact view

Five query parameters set the starting view, so a link can carry a viewpoint:

| Param | What it does | Example |
|---|---|---|
| `yaw` | rotation around the vertical axis (radians); 0 = north up | `?yaw=0.6` |
| `tilt` | camera tilt (radians); 0 = top-down 2D, capped at 1.2 | `?tilt=0.9` |
| `zoom` | zoom level, anchored on the centre square | `?zoom=2` |
| `hour` | preview the sun at any hour, decimal | `?hour=7.5` |
| `theme` | force `light` or `dark` | `?theme=dark` |

`https://square.pov.town/?yaw=0.6&tilt=0.9&zoom=2&hour=7.5` opens a tilted, rotated, zoomed morning wall. There is also `?tab=boards` to open the side panel on the leaderboards. Handy for a screenshot, a share, or a "look at my tower" link.

## No CDN, no framework, one vendored file

The 3D is plain three.js, imported from `/vendor/three.module.min.js` on Square Town's own origin — no CDN, no build step, no framework around it. That was a deliberate choice for the same reason the whole site runs on Cloudflare's free tier: fewer things that can lapse, get rate-limited, or change under you. It also means the wall works with a strict content policy and keeps working if a third party's CDN doesn't. The wall needs JavaScript and WebGL; without them there's nothing to draw, but the public read API (`GET /api/state`) still returns the whole wall as JSON for anything that wants the data without the scene.

The one performance rule worth knowing: shadows are only re-rendered when something in the scene actually changes — a buy, a kiss burst, a tower growing, a bird — never for a plain camera move. Pan and zoom, the hot path, are cheap.

## Why bother? Two reasons

**A reason to come back.** The graveyard of pixel walls (Square Town's landscape file counts roughly 120 dead or dormant ones) has one pattern: a grid that never changes gives nobody a reason to return. Square Town's answer is a live feed and a wall that is physically different every visit — towers grow, land gets cleared, the light moves, something flies past. None of that is content anyone had to make.

**A wall you can read.** A 2D wall answers "who is here?". A tilted wall also answers "who is getting clicked?", "which colour is that project?", and "where's the empty land?" — at a glance, without a table. For someone with a block of adjacent squares it's a bar chart of their own projects; see [showcasing every project as favicons](/blog/showcase-all-your-projects-favicons).

## How this compares with other 3D walls

Square Town's landscape file lists several 3D takes on the genre, as of August 2026. [Million Dollar Homepage 3D](https://milliondollarhomepage3d.com) (2026, €1/pixel, minimum 5×5) puts one million pixels on a 3D-navigable wall but keeps the classic sell-out model — the third dimension is presentation, not information. Million Dollar Metropolis is a static WebGL city. [The City Mesh](https://thecitymesh.com/en) (hexes from €10) makes *payment* the height of a building; [SaaSCity](https://saascity.io) makes *traction* the number of floors; Steam City makes *playtime* the height. Nmap's Icons of the Web (2010) is the closest 2D ancestor: a favicon collage where icon *size* is proportional to traffic. Square Town's variant is height = **clicks on the wall itself**, tinted by the icon, on top of a wall where every square is $1 and evictable. The [pixel walls comparison](/vs/pixel-walls) has the broader field.

## FAQ

### How do I see Square Town's wall in 3D?
Hold ctrl and drag on desktop; on a phone or tablet, drag with two fingers upward to tilt and twist to rotate. Drag alone pans, scroll or pinch zooms. Yaw and tilt of zero is the plain top-down 2D wall.

### What decides how tall a tower is on Square Town?
The square's click count. Zero clicks is a flat tile; from the first click the tower is half a cell tall and grows a quarter of a cell per click, capped at eight cells. Clicks are counted server-side via the `/go/:id` redirect.

### Where do the tower colours come from?
From the favicon: the client samples the icon and picks its dominant chromatic hue. Grey, black or white icons get a neutral slate; a domain-hashed colour stands in while the image loads.

### Why are there trees and lakes on empty squares?
Empty cells get deterministic, hash-seeded trees and lakes so the live area never looks empty and every visitor sees the same landscape. Buying a cell clears it and puts the favicon tile in its place.

### Does the sun on Square Town follow real time?
Yes — the viewer's local time. The shadow-casting light is in the east at 06:00, south at noon, west at 18:00, warm near the horizon, and a cool dim moon takes the same arc at night. `?hour=7.5` previews any hour.

### Can I link to a specific 3D view of the wall?
Yes. `?yaw=`, `?tilt=`, `?zoom=`, `?hour=` and `?theme=light|dark` in the URL set the starting view, and `?tab=boards` opens the leaderboards panel.

### Does the 3D wall need anything special to run?
JavaScript and WebGL. three.js is served from Square Town's own origin (`/vendor/three.module.min.js`), with no CDN or framework. Anything that only needs the data can read `GET https://square.pov.town/api/state` instead.
