---
title: "Orca · generative art"
description: "A wind tunnel over a dark sea. Generative art plate #39 by Theodore Vorillas, drawn live in your browser from its code."
url: "https://vorillaz.com/lab/orca"
---

![](https://vorillaz.com/_astro/orca.DEUjUv9o_ZpmN7D.webp)

fig. #39 · rendered live in your browser from the code below

# #39 orca

A wind tunnel over a dark sea.

- date

  2026.10.13

- tags

  generative-art · javascript · webgl

A wind tunnel over a dark sea. A wing holds still in the air, its section a Joukowski airfoil: a circle pushed through z = ζ + 1/ζ until it has a rounded nose and a sharp tail. The flow around it is solved exactly. It is the flow around the circle, carried through the same map, with just enough circulation that the air leaves the trailing edge cleanly, which is what gives the wing its lift.

More than a thousand streamlines are traced through it, slice by slice along the span, each step shorter close to the wing so the line skims it. Every line is inked by the air’s speed: where it runs faster its pressure drops, as Bernoulli has it, and the line brightens. So the suction over the wing shows as a band of light, and the slow air under the nose goes dark. Smoke rakes, combs of evenly spaced lines released together as in a real tunnel, squeeze over the wing and spread behind it. The dividing streamline, the one that meets the nose and splits, is found by halving between a line that passes over and one that passes under, and its two halves hug the wing in signal orange. Every line thins away at its ends rather than stopping short.

Below, a Gerstner sea. Each of its waves moves the surface in small circles as well as up and down, so crests sharpen and troughs flatten, and the lowest streamlines ripple over the swell.

Play it and the tunnel turns. Every so often it clears and runs again, with another wing, another angle of attack and another sea. Switch the ground to paper to draw it in black on white.

## The wing

```javascript title="orca.js"
// flow round a circle through ζ = 1, with the circulation the Kutta condition asks for
const gamma = 4 * PI * a * sin(alpha + beta);
// dw/dζ = U·(e^{−iα} − a²·e^{iα}/(ζ−μ)²) + iΓ/(2π·(ζ−μ)), and dz/dζ = 1 − 1/ζ²
const dw = inflow - (a * a * back) / (zeta - mu) ** 2 + (i * gamma) / (TAU * (zeta - mu));
const dz = 1 - 1 / zeta ** 2;
const [u, v] = conjugate(dw / dz); // the velocity at z = ζ + 1/ζ
```

## The ink

```javascript title="orca.js"
// faster air, lower pressure, a brighter line; both ends thin away
const ink = 1 - clamp(base - gain * (speed[i] - 1), 0.04, 0.97);
const ends = smooth(min(i, n - 1 - i) / (0.15 * n));
fade[i] = 1 - ink * ends;
```

## The sea

```javascript title="orca.js"
// Gerstner: the surface moves in circles, so crests sharpen and troughs flatten
for (const w of waves) {
  const th = w.k * (w.dx * x + w.dz * z) + w.phase, q = w.steep / total;
  px -= q * w.amp * w.dx * sin(th);
  pz -= q * w.amp * w.dz * sin(th);
  py += w.amp * cos(th);
}
```

## References

- [Joukowsky transform](https://en.wikipedia.org/wiki/Joukowsky_transform)
- [Kutta condition](https://en.wikipedia.org/wiki/Kutta_condition)
- [Potential flow](https://en.wikipedia.org/wiki/Potential_flow)
- [Trochoidal wave](https://en.wikipedia.org/wiki/Trochoidal_wave), Gerstner’s wave
- [Bernoulli’s principle](https://en.wikipedia.org/wiki/Bernoulli%27s_principle)
- [Stagnation point](https://en.wikipedia.org/wiki/Stagnation_point), where the dividing streamline meets the nose
- [Flow visualization](https://en.wikipedia.org/wiki/Flow_visualization), and the smoke rakes of wind tunnels
- [Streamlines, streaklines, and pathlines](https://en.wikipedia.org/wiki/Streamlines,_streaklines,_and_pathlines)
