Porthole
Fisheye and defish for Resolume

What it does
A lens projection warp for Resolume Arena and Avenue. Every output pixel stands for a ray at some angle off the optical axis; the lens model says where a ray at that angle lands on the image, and the picture is resampled accordingly. That is a different thing from bending the picture until it looks about right, and the difference is the whole point.
It means the Projection control is not a strength knob — it is which lens. The slider is one continuous family that passes exactly through the five projections that have names: rectilinear, stereographic, equidistant, equisolid and orthographic. Everything in between is a real projection too.
Three behaviours fall out of modelling it that way rather than being features anyone added. Rectilinear does nothing at all, at any field of view, because a flat picture re-photographed through a flat lens is the same picture. Defish exactly undoes fish, because it is the same formula with source and destination swapped. And the frame always stays full, because the reference radius is a fixed point of the map — only the interior is redistributed, so the strength control changes the character of the warp instead of shrinking the picture into a black field.
There is deliberately no wet/dry mix. Cross-fading two different geometries double-exposes the picture rather than easing between them, and Field of View at zero is already the null, where every projection agrees.
- Projection — one continuous family through rectilinear, stereographic, equidistant, equisolid and orthographic
- Field of View up to 178°, which is the strength: at zero every projection agrees and nothing happens
- Defish — the same lens run backwards, to take an existing fisheye picture flat again
- Chromatic aberration modelled separately from distortion, growing with the square of the radius the way real glass does
- Fit (diagonal, width, height or stretch), off-centre optical axis and two stops of zoom either way
- Edge handling — transparent, black, clamp, mirror or wrap — and 1, 4 or 16 samples per pixel on a rotated grid, because a wide fisheye minifies its outer band hard
- Universal macOS bundle and a Windows DLL
Where it stands
Built, measured and released as v0.1.0. A warp is unusually testable — where a pixel went is a number rather than a matter of taste — so the GLSL is measured against an independent C++ implementation of the same maths across 120 combinations of fit, projection, field of view and direction, agreeing to 0.6 of an 8-bit level, which is the quantisation of the test ramp rather than the maths. The fish-to-defish round trip lands within 0.001 of a level at moderate settings, and 16 of the 64 combinations are too extreme to judge and say so rather than claiming a pass. All ten parameters are swept and shown to affect the output. It has since been run inside Resolume on real content. Still open against that: performance has never been measured, and while Windows binaries are built and shipped in the release, the plugin has only been exercised in Resolume on macOS.
Watch it running
Nothing loads from YouTube until you press play.Watch it there instead