Skip to content

Releases: stoatworks-labs/stencil

Release list

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 25 Sep 17:44

Spray paint through a cut stencil, as an FFGL effect for Resolume Arena and Avenue, shown as SW Stencil. The plugin cuts the clip into a real stencil, and a stencil cannot hold a floating piece. The clip's tone is cut at one to four thresholds; each layer's sheet is labelled into pieces on the CPU (runs and union-find); every island gets the shortest bridge there is from it to another piece of sheet, found by a jump flood on the GPU that carries the nearest sheet of a different piece; and an island tied only to another island goes round again until nothing floats. Then the holes are sprayed through the disc of a nozzle's footprint, with creep under a lifted sheet and drips where the paint runs over.

What falls out: the gap in the O where its ring is thinnest; islands inside islands all hung off the frame; n layers sprayed lightest first, so n + 1 tones, dark over light, each layer with its own bridges; a halo in exact proportion to Distance; ghostly bridges when Lift is up; drips. Dark is paint, and Invert (a control beyond the spec) paints the light, for bright subjects on black or on transparency.

What is verified

By tools/verify.sh on an M4 Max, macOS 26.4, on 2026-09-25, at two rasters (320×180 and 1280×720), and again on Apple's software renderer (the one CI's runners fall back to):

  • No island floats. On letters (6 islands), rings nested four deep (4), squares in squares three deep (6), random blobs (22 / 23) and three layers of smoothed blobs (62 / 67), the harness's own flood fill of the OUTPUT finds 0 pieces of sheet cut off from the frame, and the plugin found exactly the islands the harness counts.
  • Every bridge is the shortest. 39 bridges at 320×180 and 40 at 720p, every one exactly the brute-force shortest gap of its pass (the spec allows a texel; none needed it).
  • Width. Exactly 2⌊W/2⌋ + 1 cells square to a gap, read off the output, and 2⌊W/√2⌋ + 1 at 45°; a bridge thinner than a cell stays 4-connected.
  • Overspray. Across a straight edge the paint is the chord fraction of the footprint's disc within one half-float step, and its width doubles with Distance.
  • Layers. 1 to 4 layers give 2 to 5 plateaus in order, darkest ink on top.
  • Stability and churn. Panned a whole cell a frame, the bridges translate exactly. On a slow sub-pixel pan, keeping last frame's bridges (while within a cell of the shortest) cuts the bridges changing frame to frame to 1–7%, against 2–90% without.
  • Resize keeps last frame's bridges. Nine perturbed models each fail their check; a one-character mutation of the shipped spray shader is caught by --islands and --width. All 14 controls change the picture; oxbow loads it as SW Stencil / SN01 / effect and renders 120 frames.
  • Windows, in Resolume Arena 7.27.1 (win-lab, Mesa llvmpipe, no GPU): the DLL release.yml built loads, registers as SW Stencil / SN01 / effect, all 20 host controls match the declaration, it renders, Arena's log stays clean, and all 14 valued controls and Opacity move the picture: 9 of the fleet gate's 9 checks, one run. The gate's picture is a still, so it says nothing about how the bridges move; software rendering says nothing about a GPU or speed. MSVC compiled it first time.

What is not

  • It is heavy for a VJ effect. On an M4 Max at 1080p the bench scene takes 14.9–16.3 ms a frame at the defaults (two layers), and Resolume's demo clips about 9 ms (three rings) to 22 ms (the skulls), more than a whole 60 fps frame on a busy clip; one layer about half that. The bridging is the cost: the jump floods (with a read-back stall) and the CPU cutter. Two layers stay the default because at one every palette sprays its near-black darkest can. Fewer layers, a 720p layer or more Smooth / a larger Min Island make it cheaper.
  • The stencil is cut on a lattice of at most 540 rows, so at 4K the sharpest edges step. One bridge per island per pass, always the shortest, never a second for strength. Kept bridges hold still in the frame, not on the content, so on moving footage they lag and step. The drips are static; the walls, cans, lift and drips are chosen by eye.
  • Filming the release video found that a bright subject on transparency paints nothing at the defaults (dark is paint: use Invert), that Invert at the default Threshold paints little on the dark demo loops, and that the default Pressure hangs a fringe of drips from the lower edges of solid paint.
  • Never loaded into Resolume on macOS. Footage has been seen only through the harness's --pipe, on Resolume's bundled demo clips. No presets, no OpenFX port.

There is a user guide at https://stoatworks-labs.com/software/stencil/guide/ and a browser demo at https://stencil-demo.stoatworks-labs.com/ (a port to a web page, not the plugin: the shaders are the plugin's own in WebGL2, jump flood included, and the CPU half — the union-find cutter — is a hand port to JavaScript that only a reader checks; compared once with the C++, it cut the same grids byte for byte). Video: https://www.youtube.com/watch?v=T6u7w-wOPwk

The macOS build is universal and Developer ID-signed and notarised: the downloaded .dmg and the bundle inside the .zip both read Notarized Developer ID. The Windows build is unsigned, so SmartScreen warns once.