Stoatworks Labs

Vertigo

The dolly zoom, for Resolume

Releasedv0.1.6Plugin & ModuleC++ / GLSL
Vertigo — The dolly zoom, for Resolume
The plugin's geometry card put through a pull back — rendered by the plugin's own offline harness in a headless GL context, not a Resolume screen capture. The centre is locked and the grid opens out away from it, which is the shot: one surface holding still while everything at another distance moves. The grid bends because Radial invents its depth as a surface of revolution about the optical axis; a real depth map does not do that.

What it does

An FFGL effect for Resolume Arena and Avenue. A dolly zoom is one camera move and one lens move arranged to cancel: the camera tracks along its own axis while the focal length changes to hold one surface at exactly the size it already was. That surface does not move, everything at any other distance does, and the result reads as the ground giving way rather than as a zoom. Hitchcock's cameraman worked it out for a stairwell in 1958 and it has been the shorthand for vertigo ever since.

It is a depth effect, and a video clip has no depth — so the honest part of this plugin is where the depth comes from, and there are two answers that differ in kind. Radial invents a field: near on the optical axis, falling away to the frame corners, or the reverse. Nothing is read out of the picture, so the geometry is a closed form with no failure cases and no dependence on what the clip contains — it works on any footage at all, and what it gives you is the look of the shot. Luma and Alpha read a field out of the clip instead. Given real depth, a rendered depth pass or a matte or a generated depth map baked into a channel, this is the actual reprojection and the picture comes apart in depth the way the real move does. Given an ordinary clip it turns brightness into geometry, which is either a mistake or an effect depending on the clip.

The model is written in disparity rather than depth, and that is what makes it safe rather than merely tidy. Written in depth, the magnification has a pole where the camera reaches a surface; written in disparity, with the field normalised into nought-to-one and the dolly kept below one by construction, the denominator is unconditionally positive. There is no divide-by-zero guard anywhere in the plugin and there does not need to be one, for any setting a host can produce.

Two of its behaviours are exact rather than approximate, and both are measured rather than asserted. The anchor surface does not move at any dolly setting — measured at nought travel while the rest of the frame travels a fifth of the frame. And a scene with no depth is the identity: a dolly zoom on a painted backdrop is nothing, however hard the camera is driven, and the maths says so without being told. The browser demo carries a preset for each so a visitor can check both without installing anything.

Also builds as an OpenFX plugin for DaVinci Resolve, Vegas Pro, Nuke and Natron, from the same model — the dolly maths is compiled into both builds from one file rather than reimplemented.

  • The real dolly-zoom reprojection, in disparity, with no pole for any setting a host can produce
  • Radial depth invents its field and works on any clip — closed form, one texture fetch, no holes
  • Luma and Alpha depth read a real field out of the picture, solved for with three fixed iterations per sample
  • The anchor surface holds still at any dolly setting, measured at nought travel
  • Two exact nulls: no camera move, and a scene with no depth — either returns the picture untouched
  • The Dolly control is geometric in the parallax ratio, so equal travel either side of centre gives reciprocal shots
  • Relief goes signed: past the middle it turns the depth inside out, which is the stairwell shot rather than the subject shot
  • Smooth blurs the depth field and not the picture — an inverse-mapped parallax smears at a depth step rather than tearing, and softening the step is the repair
  • Overscan buys back the frame that a push in gives away, with five edge modes for what shows past the picture
  • Seven factory presets, from Vertigo through Stairwell to Slam
  • Universal macOS bundle, a Windows x64 DLL, and an OpenFX build for macOS, Windows and Linux

Where it stands

Released, and now at v0.1.5; the point release changed nothing but the Windows installer, which no longer touches the system PATH — the earlier one could overwrite it. It runs in Resolume Arena — loaded and confirmed working on 2026-08-17, the day v0.1.0 shipped. What is checked is checked properly, by a harness that drives the real plugin class in a headless GL context: the GLSL is measured against an independent C++ implementation across 180 parameter combinations and agrees to within nine tenths of an 8-bit level; the effect's defining claim, that the anchor surface does not move, is measured at nought travel across 55 combinations while the rest of the frame travels a fifth of the frame; and the depth-map path, which has no closed form, has its fixed-point solve measured against the same solve in double across 45 more. All twelve controls are swept and shown to reach the picture, and the browser demo's copy of the shader is compared to the plugin's character for character. One bug worth recording found its way through the first of those and not the second: the relief control was scaling the depth field about the anchor rather than about the middle of its range, which made it silently do nothing over half its travel — the GPU and the C++ agreed perfectly, on the same wrong answer. Still open: it has never been loaded into Resolve or any other OpenFX host, so that build has only met a probe harness and its real texture sizes and premultiplication behaviour are unconfirmed; and whether the depth modes hold up on a genuine rendered depth pass, which they have never been given — only a radial card and a linear ramp. The Windows build is no longer only a build: an operator has been running it on Windows 11, and the first thing they reported — factory presets appearing not to stick, because Resolume does not act on the value events a plugin raises and keeps pushing its own values back down — is fixed in v0.1.2. Nothing has been timed at all.

Watch it running

Vertigo video thumbnail

Nothing loads from YouTube until you press play.Watch it there instead