WebGPU · three.js · React Three Fiber

threejs-city: Grow a whole town from a seed.

Settlements where people would live, placed and sized by a population model on an H3 hex grid, with roads that follow the terrain, blocks, lots and buildings that match the climate. One call to City.create() or one <City />, and the ground is flattened under all of it.

screenshot · city.html open ↗
Aerial view of a procedural city beside a river
~3,600buildings in a 1.5 km city
6size classes
6architectures
0texture assets
Getting started

Found a town in one call.

Plan where people live on a threejs-biomes world, then build the largest place. The city adds itself to the scene, updates its LOD whenever the scene renders, and registers terrain edits on the world so roads and buildings sit flat.

three.jsthreejs-city
import { World } from 'threejs-biomes'
import { City, generatePopulation, planCities } from 'threejs-city'

const world = new World({ seed: 11 })
const people = generatePopulation(world, { radius: 10_000 })
const [site] = planCities(people) // largest first

const city = await City.create({
  world, camera, scene,
  center: [site.x, site.z],
  size: site.size,
  radius: site.radius,
  seed: site.seed,
})

city.set({ facade: { night: 1 } })            // lights on
city.set({ weather: { roofs: { snow: 1 } } }) // snow on every roof
React Three Fiberthreejs-city/react
import { useWorld } from 'threejs-biomes/react'
import { City } from 'threejs-city/react'

function Town({ night, rain }) {
  const world = useWorld({ seed: 11 })
  return (
    <City
      world={world}
      size="village"
      center={[200, -50]}
      facade={{ night }}
      weather={{ roads: { wetness: rain } }}
    />
  )
}
Install npm i threejs-city threejs-biomes three Full API reference → React components →
What's in the box

Everything a settlement needs.

Placement, streets, plots, houses and the ground they stand on. Every feature below is live in the demo, and every setting can change at runtime.

01

Sited where people live

Planned by the population.

The settlement planner below decides where people live and how many. planCities turns each settlement into a size class and a radius from its head count, and each class builds its own way: farmsteads get a farm and its fields, hamlets a junction, villages a road of houses, towns a main street, cities and metropolises towers. <Settlements> builds them all.

A town on a river plain, with roads leading out over two bridges
02

Roads that grow

Along a tensor field.

Arterials grow from the centre and branch into collectors and local streets, following grid patches, a radial centre and the terrain gradient. They avoid water and steep grades, snap to junctions, refuse acute angles and bridge narrow rivers.

A radial town from above: a ring road, arterials and bridges over the river
03

Three street layouts

Grid, radial or organic.

Pick a style or let the size class choose. Each preset tunes the tensor field and road lengths; all of it stays open to override.

  • grid
  • radial
  • organic
  • farmstead
  • hamlet
  • village
  • town
  • city
  • metropolis
The town laid out as a gridgrid
The same town with organic streetsorganic
04

Blocks, lots and districts

Every building has a plot.

Blocks are faces of the road graph, inset by road and sidewalk, then split into lots that keep street frontage. Downtown, residential, industrial, park and farmland districts set block size, setbacks and floors.

A downtown of towers ringed by blocks of houses on their own lots
05

Buildings for the climate

Six architectures.

Towers, apartment blocks, houses and sheds, with gable, hip, skillion, flat and saw-tooth roofs, chimneys, balconies and stilts. Materials and roofs come from the climate at the centre, or set architecture yourself.

  • temperate
  • cold
  • arid
  • mediterranean
  • tropical
  • wetland
A town with the arid architecture: flat roofs and rooftop tanks
06

Procedural facades

Windows that light up at night.

Facades are a TSL shader: window grids, frames, shopfronts and procedural plaster, brick, wood, stone, glass and adobe. Window lights are hashed per window and glow with facade.night, a uniform you can fade every frame.

Looking up at downtown towers: window grids, frames and glass from the facade shader
07

Weather hooks

Wet, snowy, burnt or damaged.

Walls, roofs and roads each take wetness, snow, burn and damage. Wet roads get puddles, snow stays out of tyre tracks, and setBuildingWeather sets one building on fire.

THREEJS-CITY
08

Ground that fits

Graded roads, level pads.

Each road gets a graded profile, and flatten modifiers along roads and under buildings are registered on the world in one batch. Terrain, grass and scatter follow; dispose() removes them.

Roads and building pads sitting flat on the ground beside a river
09

Data for everything else

Roads, lots and buildings as JSON.

city.data() returns road edges with lanes and speeds, lots with frontage and buildings with entrances. roadAnchors places street lights; graph.shortestPath with routeCost routes cars, bikes and people.

The road graph of a grid town from above
Settlement planner

Where people live.

A population model on H3's hexagonal grid, read from the world: habitability, settlements, density, land use and networks, all from a seed, as plain data plus a PopulationOverlay hex map. Everything below except the last row is live in the settlement planner demos.

01

Habitability from the world

Where people would choose to live.

Every fine cell reads the threejs-biomes world: biome fertility, gentle slope, a comfortable temperature, and a river valley or coast nearby. Water and avoided biomes (deep ocean, glacier, peaks, volcanic) score zero.

Habitability map in hexagons, bright along valleys and coasts
02

Central places

Christaller on H3.

At each tier's resolution, cells whose habitability is a local maximum become settlements. Each higher-tier place claims its market area, so towns fall between cities and villages between towns, one H3 resolution (about 7× the area) apart.

Settlements as bright cores spaced across the region, joined by roads
03

Sized by rank

Zipf, then classes.

The r-th settlement gets P₁ / rzipf people, scaled so they sum to the urban share of totalPopulation. Its class comes from thresholds; farmland cells may hold a farmstead. Classes map onto city size classes with citySize.

  • metropolis
  • city
  • town
  • village
  • hamlet
  • farmstead
The settlement planner sandbox: extruded density hexagons, a minimap and every option in a panel
04

Density that fades out

Integer people per cell.

Each settlement spreads its people over nearby cells with a Gaussian of its radius. Rural people fill habitable land, denser along rivers and coasts (corridor) and near towns (ruralDecay). Cell counts are integers that sum to the total.

Extruded density prisms rising over cities
05

Land use

Five classes per cell.

Urban and suburban by density, farmland by habitability, everything else wilderness, plus water from the world. Thresholds live in landUse.

  • urban
  • suburban
  • farmland
  • wilderness
  • water
Land-use map: urban cores, suburbs, farmland and wilderness
06

Night lights

Cities seen from orbit.

Brightness is 1 − exp(−density / lightDensity). nightLights(data, res) returns typed arrays of centres and intensities at any resolution, with sample(x, y, z) for a glow pass or an orbit view.

Night-light map with bright city cores and dim countryside
07

Roads, rail and power

Routed over the terrain.

A spanning tree reaches every settlement, plus gravity-model links where the tree forces a detour. Each link is an A* route over the hex graph, costed by slope and water and cheaper where earlier routes run, so roads merge into trunks. Rail avoids hills harder; power lines span straight.

  • highway
  • road
  • track
  • rail
  • powerline
Roads winding between settlements and straight power-line spans over density hexagons
08

Hexagons at every scale

Coarser cells are exact sums.

H3 nests resolutions, so the same people show at 400 m, 3 km or 22 km cells. With resolution: 'auto' the overlay steps coarser as the camera pulls away; aggregatePopulation(data, res) gives the sums as data. Flat worlds and planets both map onto H3.

Coarse, tall hexagon prisms over the same region
09

Data and maps without a GPU

Plain objects and RGBA.

generatePopulation and generateNetworks are pure and seeded. renderPopulationMap returns RGBA pixels for a minimap, a worker or a test, in the same colours as the overlay.

The demo minimap drawn by renderPopulationMap
10planned

Traffic from people

Sized by who lives where.

Next, the population will size the traffic on each road and railway, from the people at either end.

PLANNED

Found your town.

Try every size, layout and weather in the live demo, or go straight to the API reference.