Skip to content
Back to skills

Threejs Fish School Boids

ASecurity

Builds a school of swimming fish (koi) in three.js — one neutral Blender mesh with animation weights in COLOR_0, per-fish variety patterns (kohaku, sanke, showa, ogon, tancho, asagi, kigoi, ghost) painted in the fragment shader, vertex-shader swimming with a travelling tail wave, turn bend, flapping/tucking pectorals and fin flutter mirrored in the shadow depth material, and calm boids traffic with patrol homes, look-ahead shallows and obstacle avoidance, clamped steering, surface "kisses" th...

  • 2 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 27, 2026
ai-agentsgospringaws

Security analysis

A100/100

Pro scans all 3 files and shows the line behind each finding

Scanned September 27, 2026

npx -y skills add nicksonthc/ghibli-threejs --skill threejs-fish-school-boids --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Threejs Fish School Boids?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Threejs Fish School Boids
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/nicksonthc-threejs-fish-school-boids/badge)](https://www.skillsdirectory.com/skills/nicksonthc-threejs-fish-school-boids)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: threejs-fish-school-boids
description: Builds a school of swimming fish (koi) in three.js — one neutral Blender mesh with animation weights in COLOR_0, per-fish variety patterns (kohaku, sanke, showa, ogon, tancho, asagi, kigoi, ghost) painted in the fragment shader, vertex-shader swimming with a travelling tail wave, turn bend, flapping/tucking pectorals and fin flutter mirrored in the shadow depth material, and calm boids traffic with patrol homes, look-ahead shallows and obstacle avoidance, clamped steering, surface "kisses" that spawn ripples, and night bioluminescence. Use when adding fish, koi ponds, creature schools, flocking/boids, or swimming animation to WebGL/R3F.
---

# Fish school: koi with shader patterns, vertex swimming and calm boids

Produces vivid, wet-looking koi that swim with a believable body wave, bank into turns, spread
along the whole river instead of clumping, avoid shallows, rocks, a boat and a submerged camera,
and now and then rise to kiss the surface (spawning a ripple ring the water shader draws).

Stack: three.js `WebGLRenderer`, `MeshPhysicalMaterial` patched with `onBeforeCompile`, a
matching `MeshDepthMaterial` for shadows; the mesh comes from headless Blender. Vanilla or R3F.
Water surface at y = 0, bed height `terrainHeight(x, z)`.

## When to use
- Adding fish or any swimming creature school.
- Fish look grey or pattern edges stair-step; shadows don't move with the fish.
- Boids collapse into one crowd that looks stuck, or fish jitter / swim through the camera.

## Paste-ready prompt

> Add `{{n, e.g. 24}}` `{{creature, e.g. koi}}` to `{{entry file}}`.
> - **Mesh (Blender, headless):** one *neutral* mesh with body, fins, eyes and barbels, and **no
>   painted pattern**. Chunky from above. Fins are multi-segment sheets. Put animation data in
>   `COLOR_0`: **R** = pectoral weight (root → tip), **G** = side, **B** = flutter weight toward
>   free edges. Export with `export_vertex_color='ACTIVE'`. In three, rename the attribute to
>   `finData` so it doesn't tint the material.
> - **Patterns in the fragment shader** from object-space position: one variety uniform per fish
>   (kohaku, sanke, showa, ogon, tancho, asagi, kigoi…). Crisp noise patches biased to the back, a
>   pale belly, hex scale rows (`atan` around the body). `MeshPhysicalMaterial` with clearcoat 0.9;
>   ogon metalness 0.7. Fins translucent with rays, alpha fading to the edge.
> - **Vertex swimming:** a travelling wave growing toward the tail; a whole-body C-bend ∝ turn
>   rate; pectorals flap and tuck in when sprinting; free edges flutter. Give the
>   `customDepthMaterial` the same patch.
> - **Behaviour:** boids (cohesion, alignment, separation) plus wander; look ahead and turn away
>   from the shallows; avoid rocks; occasional bursts; turn-rate-limited heading; roll into turns
>   (Euler `YXZ`); a slow, natural tail beat (~0.65 Hz cruising, ~1 Hz in a burst) whose rate follows
>   speed but is integrated into a phase on the CPU; every few seconds one fish kisses the surface
>   and spawns a ripple. Give each fish a patrol home and expose count/speed/spacing/schooling/roam
>   in a Tune folder.

## Implementation

### Mesh and attributes
- Object space (metres): snout at +X (~0.28), tail tip ~−0.30, back +Y, fish-left −Z.
- COLOR_0 → `finData` on load: `geo.setAttribute('finData', geo.attributes.color); geo.deleteAttribute('color')`.
- Material split by mesh name: `/fin/` → translucent fin material, `/eye/` → black clearcoat, else body.

### Shaders ([`references/koi-shader.js`](references/koi-shader.js))
- **Swim:** `s = clamp((x + .30)/.58)` (0 tail, 1 snout); `amp = uAmp·(.010 + .085(1 − s)^2.2)`;
  `z += amp·sin(x·10.5 − uSwim + phase)`, where **`uSwim` is a phase** (see Behaviour); C-bend
  `z += uTurn·(x − .14)²·2.2`; pectorals `y += R·(sin(uFinBeat + sideOffset)·.016 − fold·.004)`
  (`uFinBeat` also a phase), tuck `z += R·side·fold·−.028`; flutter `z += B·sin(4.5t + 28x + 37y)·.0045`.
- **Pattern:** `top = smoothstep(−.02, .035, y)`, belly `smoothstep(−.012, −.05, y)`, two-fbm
  noise; patches `smoothstep(.465, .495, n + top·.2 + head·.22 − .1)·(1 − belly)` — a narrow
  smoothstep gives crisp edges. Scale rows: `(x·105, atan(z, y)·8.5)` with odd rows offset by .5,
  darken edges by 16 %. Fin rays `.86 + .14 sin(190·(…))`, alpha `mix(.95, .45, B)`.
- **Materials:** body `MeshPhysicalMaterial({ roughness .3, clearcoat .9, clearcoatRoughness .12,
  sheen .4 })`; fins `transparent, opacity .78, DoubleSide, depthWrite false`; ogon metalness 0.7.
- **Shadows:** only the body casts; `customDepthMaterial` = a `MeshDepthMaterial(RGBADepthPacking)`
  with the same vertex chunk and uniforms.
- If the scene has a toon-ramp light-loop replacement, opt the fish out so clearcoat/sheen stay on
  the stock path.

### Behaviour ([`references/koi-boids.js`](references/koi-boids.js))
- Neighbours within ~2.4 m (`d² < 5.8`): cohesion `.12·schooling/n`, alignment `.1 + .5·schooling`,
  separation **ramped** `(1 − d²/r²)²` inside `0.9 m × spacing` (not 1/d²).
- **Patrol home per fish:** even slots along the river, own side of the channel, drifting slowly
  (`sin(.05t)·2.5·roam`); a soft spring only beyond `reach = 2.5·roam + .5`. Keep cohesion small
  (`schooling` ≈ .25).
- **Wander = two slow sines per fish** (`sin(.23t + w) + .6 sin(.61t + 1.7w)`), not a per-frame
  random walk.
- Shallows: sample the bed 1.2 m ahead; if above −0.45 m, push toward the channel. Rocks: ramped
  push from 0.5 m out. A boat hull: a moving obstacle with a wider berth. A submerged camera:
  a ~1.6 m obstacle (widen to ~3.4 m for a cinematic that stages its own fish).
- **Clamp steering acceleration ≤ 0.9**, target speed `.20 + .06 sin(…)` + bursts (`.28 sin(π·b/1.4)`,
  rate ~0.04/s), speed and depth eased with `1 − exp(−dt·k)` (frame-rate independent).
- Heading: turn rate ≤ 1.5 rad/s; `turn` eased, bank `rotation.x = turn·.25` with Euler order `YXZ`;
  `uAmp = .55 + 1.2·speed + .8|turn|`, `uFold = smoothstep(speed, .3, .55)`.
- **Tail and fin beats are integrated phases:** rate `2.6 + 8·speed` rad/s (≈ 0.65 Hz cruising, ≈ 1 Hz
  in a burst; real koi cruise well under 1 Hz), pectorals `1.6 + 1.6·(1 − fold)`; ease the rate with
  `1 − exp(−1.5·dt)`, then `phase = (phase + rate·dt) mod 2000π` and upload the phase.
- **Surface kiss:** every 5–11 s a random fish rises to y ≈ −0.09 for 3.2 s; when above −0.12 it
  writes a ripple slot `(x, z, amp .9, startTime)` just ahead of its snout.

### Night
Clearcoat → 1.0, clearcoat roughness → 0.05. Bioluminescence: the colour function also outputs a
glow mask; add `mask × orange × (.55 + .45 sin(t·1.3 + phase)) × uBio` to
`totalEmissiveRadiance`; fin tips pale cyan from B. Ghost/silver variety: **metalness ≈ 0.35**,
faint steady silver emissive. See `threejs-ghibli-night-mode`.

## Pitfalls
- **Vertex-colour patterns stair-step** at this mesh density — paint in the fragment shader.
- **Translucent fins casting shadows** print dark streaks on the back.
- **In `onBeforeCompile`, inject helper GLSL before any code that calls it.**
- **Absorption from vertical depth** (not view-ray thickness) in the water makes fish look grey.
- **Flocking cohesion** makes koi collapse into one crowd that looks stuck — use patrol homes.
- **Random-walk wander + unclamped steering** looks nervous; use sines, clamps and eased speed.
- **`sin(uTime·rate)` with a speed-driven rate** makes the tail flick too fast and twitch: with page-time
  `uTime` in the thousands, each small rate change jumps the phase by `uTime·Δrate`. Integrate the phase
  on the CPU. A base rate above ~1 Hz also reads as frantic for a koi.
- **A fully metallic ghost koi goes black** when the environment map dims at night.
- **Tours/cinematics:** pointing the camera at a fish through hazy water fails and following one
  makes the camera jerk — stage fish instead (`threejs-camera-guided-tour`), flag them `scripted`
  so the flocking step skips them, and hand them a velocity on release.
- **Timers seeded at build with small absolute values** fire at once when the clock is page time.

## Verify
- Close up: the tail sweeps slowly and evenly, with no flicker when a fish speeds up or turns.
- Close up: patterns crisp and vividly coloured through the water, scales visible, fins translucent.
- Shadows on the bed swim with the bodies.
- Watch 60 s from above: fish spread along the river, no crowd, no jitter, no fish crossing the
  bank; occasional ripple rings from kisses. Dive the camera: fish curve around it.

## Related skills
`threejs-webgl-realistic-water` · `threejs-webgl-underwater-effect` · `threejs-ghibli-night-mode` ·
`threejs-blender-glb-pipeline` · `threejs-camera-guided-tour` · `threejs-boat-buoyancy-steering`

Files in this skill

  • SKILL.md8.7 KB
  • references/koi-boids.js6.3 KB
  • references/koi-shader.js6.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.