threejs-fauna: Animals that live where they should.
Fish schools in rivers and seas, matched to water type, temperature and depth, and bird flocks over the biomes they like. Bodies, patterns, swimming and wing beats are all generated, and every group is a seeded flock that never leaves its habitat.
Stock a world in one call.
Give it your camera, scene, renderer and a threejs-biomes world. Groups spawn in tiles around the camera, nearest first, on a per-frame time budget, and update whenever the scene renders.
import { World } from 'threejs-biomes'
import { Fauna, Fish } from 'threejs-fauna'
const world = new World({ seed: 1 })
const fauna = await Fauna.create({ camera, scene, renderer, world, seed: 7 })
fauna.set({
birds: { density: 8 },
fish: { species: { shark: { habitat: { weight: 0 } } } },
predators: [{ object: camera, radius: 3 }], // fish scatter from the camera
})
const nemo = await Fish.create({ scene, renderer, preset: 'clownfish', seed: 3 })
nemo.set({ speed: 2, species: { pattern: { stripes: { count: 4 } } } })
import { Fauna, Fish } from 'threejs-fauna/react'
function Wildlife({ world }) {
return (
<>
<Fauna world={world} seed={7} birds={{ density: 6 }} fish={{ density: 250 }} />
<group position={[0, 1, 0]}>
<Fish preset="tang" speed={1.5} />
</group>
</>
)
}
Life in the water and the air.
Every animal is generated from a few numbers and a seed. Everything below is live in the two demos.
Twelve fish species
Rivers, reefs, cold seas and open water.
Freshwater, warm reef, cold sea and large open-water species, each plain JSON in FISH_SPECIES. Edit one live or pass new ones through species. Every fish varies its size, girth, hue and pattern from the seed.
- Trout
- Carp
- Perch
- Pike
- Clownfish
- Tang
- Parrotfish
- Cod
- Herring
- Mackerel
- Tuna
- Shark
gallery demoGenerated bodies
No textures, no models.
The body is lofted from superellipse sections along a spine and is watertight. Tails can be forked, lunate, rounded or truncate; dorsal, anal, pectoral and pelvic fins are two-sided sheets. Bars, stripes, spots, countershading and iridescence are drawn in the shader.

Swimming
A wave that runs to the tail.
Vertex animation on one InstancedMesh per species: a travelling wave that grows toward the tail, its beat set by speed, its phase integrated on the CPU so speed changes never jump. Turning bends the body and the paired fins flutter.
Schools that stay in the water
Placed by water type, temperature and depth.
Species are picked per spot from river or sea, temperature and depth. Each school is a seeded boids flock inside a small grid of its water, keeping clear of the bed and the surface so no fin breaks the water. Add predators and they scatter.

Bird flocks
Gulls, crows, swallows and vultures.
Flocks stream around the camera over the biomes each species likes: gulls over coasts, crows over forests and fields, swallows over meadows, vultures over savanna. Wings flap with a bend toward the tip, glide by turns and bank into curves.

Streaming and scale
Tiles around the camera, anywhere.
Groups spawn per tile, nearest first, within a buildBudget of milliseconds per frame. Far groups are drawn but not simulated. Matrices are relative to an anchor near the camera, so it works on planets and with a floating origin.
world demoSeeded, never random
The same seed, the same fish.
Placement and flocking come from the seed, the tile and the world, in fixed simulation steps. Leave and come back, and the same schools are where they were. The tests check every fish stays between the bed and the surface of the real world.
Weathered animals
Wet, snowy, burnt, damaged.
states takes the shared material states of threejs-weathering. Birds darken when wet and whiten on top in snow; burnt and damaged fish darken and dull.
Land wildlife
Herds on the ground.
Deer, cattle and other herds that graze where the biomes suit them. FaunaLayer is the slot: species, habitat, mesh, material and animation, with placement, streaming and boids shared.
Thousands per school
Boids on the GPU.
Boids run on the CPU today, which is deterministic and fine for hundreds per group. The next step is a WebGPU compute pass with storage buffers and a grid neighbour search for schools in the thousands.
Go fish.
Browse every species in the gallery, follow schools and flocks through a world, or go straight to the API reference.