vizz

Realtime generative visuals for VJing. Native Rust and wgpu, feeding Resolume, TouchDesigner and MadMapper over Syphon and NDI, played live over OSC and MIDI.

Apple Silicon and Intel. signed & notarized — it opens with a normal double-click, checked with spctl in CI before every release. Windows builds from source and is tested in CI; there is no Windows installer yet.

Install

Or one line in a terminal, which puts it in Applications:

curl -fsSL https://raw.githubusercontent.com/legofsalmon/vizz/main/scripts/install.sh | bash

Syphon is embedded in the bundle — nothing else to install. Double-clicking runs 1280×720 with OSC on udp/7000 and Syphon on.

What it does

Built to survive a live set: the render thread never waits on anything.

Out to your VJ software

Syphon on macOS, zero-copy on the same Metal queue. NDI on the network, with frames dropped rather than awaited — losing an NDI frame is survivable, missing vsync is not.

Played, not configured

OSC and MIDI on every parameter. Sixteen assignable faders on the performance layout, each with MIDI learn and a ghost mark showing where modulation has actually pushed it.

Looks become scenes

Design a look, save it as a preset, put it on one of sixteen pads, and fire it mid-set — the blend takes musical time and moves the parameters, not a crossfade. Edit a preset once and every pad playing it follows.

A gravity layer above them

Four attractors and repulsors bend the cloud from a layer over the scenes, with their own presets and their own sixteen-pad grid. Looks and wells compose instead of overwriting each other.

Modulation as a node graph

LFOs, a beat clock, and four configurable audio bands with tempo detection, wired on a pannable canvas. Modulation is an offset on top of your value, so a fader you set stays where you set it.

Geometry

Eight morphing modes including two strange attractors. Drop a PLY, XYZ, PTS or CSV onto the window to load a scan, colour included. A real camera with depth of field, and a wireframe room sized to the frame for forced perspective.

Live point clouds

Stream PLY in over TCP, or watch a file that gets rewritten. Frames morph against loaded scans and attractors like any other cloud. No wrapper protocol — a PLY header is its own frame length.

Honest about failure

Every external dependency fails soft. Health monitoring with frame-time percentiles, and a headless mode that renders the same frame path as a live set for benchmarking.

The presets it ships with

Nine built in, on the number keys — the six particle looks shown here, and three prints on 7, 8 and 9. Every one of these is a real frame, rendered headlessly from the preset itself.

A wide, warm sphere of particles
1 · Slow bloom
The Lorenz attractor drawn in particles
2 · Butterfly
A grid plane driven into a feedback vortex
3 · Tunnel
A particle sphere inside a wireframe room in forced perspective
4 · Stage
Dense multicoloured particle speckle
5 · Confetti
A mirrored torus sheared into ribbons
6 · Ribbon

Changelog

Newest first. Full notes on each release page.

  • 1.0. The first release sold from letissier.ie. Every build before this was numbered 0.x; the numbering starts again here, and the in-app updater on any 0.x build offers it.
  • A licence, with a 30-day trial. Start the trial or enter a key in the panel's licence section. A copy with neither sends nothing out until one is in; a licence arriving mid-set takes effect at once, and nothing about a licence ever stops a show that is already running.
  • A crash puts the show back. If vizz closes unexpectedly, the next launch restores the look that was playing and turns the NDI feed back on, and a frame that fails is skipped rather than taking the app down.
  • Crash reports, only if you say so. After a crash vizz asks once whether to send a report. Reports carry the version, the OS and the error with your user name taken out — never your shows, presets, sources, licence or email. Off unless you turn it on.
  • Send feedback from the app. help & feedback in the panel takes a bug, an idea, a question or praise, with an email if you want a reply. It waits for a network if there is none.
  • Open-source notices in the bundle. Every crate, framework and font vizz is built on is credited in THIRD_PARTY_NOTICES.md, inside the app.
  • Sharper by default. Outputs up to 1080p now render at twice their size and are filtered down, which takes out most of the shimmer in fine particle fields. The room's lines are drawn anti-aliased, one output pixel wide, and put the same light into the frame at every render scale. Sprites smaller than a pixel are widened and dimmed rather than left to flicker. A machine that can't hold 2× can set 1× in the output panel.
  • A graded finish. grade in the FX panel meters each frame and eases the exposure, rolls highlights off through AgX instead of clipping them to flat discs, and swaps the glow for a mip-chain bloom. At 0, the default, every frame is exactly what it was. The pictures on /clouds are now drawn by the same renderer the app uses, with the palette and the grade on.
  • Solid surfaces. surface in the particles panel draws the cloud as solid, lit discs instead of glowing sprites: they hide each other, the lamps light the side that faces them, the sun casts the cloud's shadow on the floor, and the room becomes lit walls with a glowing grid. It costs more than glow, so it is a switch, not the default.
  • Switch simulations without stopping. The simulate… menu is now on the live slot while a simulation is running, so picking another one replaces it in one press. rescan is no longer offered on a running simulation, where it swapped it for a network listener.
  • Four more clouds that are alive. cyclic is an automaton whose states chase each other round a ring: noise organises itself into scroll waves that turn for ever, because a spiral's own wave comes back round to feed it. tangle is one long elastic rod loose in a wind, with its length and its curvature both held as constraints and self-repulsion on a grid, so it cannot pass through itself — which is the difference between a tangle and a scribble. crystal is Reiter's snowflake on a hexagonal lattice, where the six-fold symmetry is imposed nowhere and the habit follows the vapour. vortex is the thin cores smoke rings are made of, moving each other by Biot–Savart, so rings catch the one in front and thread through it. polytope is a regular solid of four dimensions turning through the fourth, so it turns itself inside out as it goes. growth is a thread that buckles into coral as it grows, and scope is an oscilloscope in XY mode, drawing the left channel against the right.
  • Every look wears a picture of itself. The preset row on the performance layout is now a grid of tiles, and each one carries the master output as it was when that look was saved. A preset is a list of numbers under a name somebody typed at 2am; by the next gig the name is a guess, and the only thing that reliably says what a look is, is the look. Pictures are taken on save, and the first time a look is fired — a second after, so the morph has finished — which is what gives the built-ins and everything you saved last year a tile worth looking at, with no migration and nothing to ask for. update picture on a tile's menu takes a fresh one.
  • Looks are grouped by what they were built on. Clouds, shapes, attractors, built-ins — each with its own colour on the tile's leading edge and as the heading in front of its group, so the three looks you made on the scan sit together instead of alphabetically between two attractors. The slot number stays on every tile: grouping changes where a look sits on screen, never what fires it.
  • A first launch opens playing. Tunnel is on screen, the play screen is up, and one press of react makes the picture follow the music — the kick on the size, the loudness on the glow, the snare on the brightness. A card names the three keys that matter and gets out of the way. The window opens at a size the play screen can use and remembers it.
  • Every punch has a key. Space flashes, S strobes, B blacks out, F freezes, I inverts, and a held key no longer repeats itself. T taps the tempo, with a count. Alt-click fires a column. Escape asks twice.
  • What just happened is said on the screen you are watching. A recall names the look it fired, a capture names the look it made, a device that goes away is a notice rather than a log line, an output that did not start says why, and a file held over the window is answered before it lands.
  • Looks keep their names and their pads. The save field keeps its name and offers the current look; a look can be renamed from either list and every pad on every page follows; a controller's preset buttons follow their looks when the list re-sorts; storing over a look that other pads play forks it rather than changing them all. A tile can be dragged onto a pad. The recall ceiling is 512, not 64.
  • The desk says more, in fewer places. Every parameter's hover says what it does, in the README's own words. The depth slider says its swing in the parameter's units. The band meters carry the gate line, and a modulator whose band never crosses it says so. The bpm wears its source — MIDI, AUTO, or a question mark when it is set but not steering. The autopilot counts down to its next step. The audio input is a click target on the stage strip, and the MIDI section lists every binding.
  • Two buttons turn the pages. /deck/next and /deck/prev step through the set list and stop at the ends; the APC40 ships a blackout, a tap and its scene-launch row on the pages. The words on screen are accepted on the wire as OSC aliases.
  • A take says what it is. It records JPEG or PNG and says which, the chip says the size and rate, the folder is named for the look, a take.json sits beside the frames, reveal opens the folder, and a countdown can be cancelled from the stage. Bands, the recording setup and the screen you left on survive a restart.
  • Every cloud has a page, and a source. vizz.letissier.ie/clouds lists all seventy-two generators and twenty-two simulations with a picture of each, its knobs, and the paper it comes from. Almost none of this is ours — Thomas' circuits, Sprott's search, Stam's solver, Jones' slime mould, Bak, Tang and Wiesenfeld's sandpile — so the credit now sits on the catalogue entry itself, where the app can show it and it cannot drift away from the code. The page is generated from that catalogue and its pictures are drawn by the app's own code.
  • And so does everything else. Below the catalogue, the same page now carries where the rest of the picture came from: the shapes the shader draws with no slot filled, the wind over them, the pattern stack and its moiré, the cosine palettes and the tone shoulder, the normals estimated off a scan, the FFT, the onset detector and the tempo autocorrelation, the feedback trails. Lorenz, Amidror, Quilez, Reinhard, Hoppe, Harris, Dixon, Ellis, Sandin. Where nothing outside vizz is owed, the line says so instead of leaving a blank that reads like a citation somebody forgot. It was briefly two pages; two pages over the same ground diverge the moment one of them is easier to edit.
  • Ten more clouds and two more alive. The three-dimensional Hilbert curve, whose whole point here is that a cloud in Hilbert order crawls along a line that fills a cube; Lorenz-96, the toy atmosphere every weather forecasting scheme meets first; the forced Duffing oscillator, drawn on the cylinder of its own forcing phase; Gumowski–Mira from CERN; Newton's basins and the Markus–Hess Lyapunov fractal as reliefs; Dini's twisted pseudosphere and Enneper's minimal surface; a spirograph; and the figure-eight knot. Alive: sand, the Abelian sandpile, and spirals, the Belousov–Zhabotinsky reaction.
  • The automaton had stopped. sim:life shipped in the Clouds rule, which grows into masses and then holds them: sixty changed cells a generation out of a hundred and ten thousand, which in a live slot is a still image with a name on it. Every test passed, because they asked that it neither die nor flood. It now ships in Pyroclastic, which boils; a test measures the churn rather than the census; and any rule that stops is started again.
  • Fifty-six clouds from equations, in a menu that can hold them. The generate… menu groups them by what they are rather than by which shelf a look files under: flows, maps, searched, surfaces, curves, fractals, grown, patterns. New in the last of those: the gyroid with Schwarz' P and D, the triply periodic minimal surfaces that divide space into two labyrinths that never touch; an icosahedral quasicrystal, six plane waves sharing no period, so the pattern never repeats and is nowhere random; phyllotaxis, whose angle is the knob — the golden angle is the only one that never lines up, and a tenth of a degree off it the packing falls into spiral arms; the standard map drawn on its torus, a portrait of two hundred and fifty-six orbits rather than one; Hénon and Ikeda; a Klein bottle and Boy's surface; the Mandelbox, which is architecture where the Mandelbulb is organic; a quaternion Julia set; the Sierpinski gasket with a turn folded into every step; and an aggregate grown by diffusion, where nothing in the rules mentions branching and a dendrite comes out anyway.
  • Forty-four clouds from equations. The clouds section's generate… menu, or --cloud gen:thomas, fills a slot from a formula instead of a file: twenty-three strange attractors — Thomas, Halvorsen, Dadras, Rössler, four-wing, Chen, Sprott B, Nosé–Hoover, Arneodo, Burke–Shaw, Chua, Hadley, Rucklidge, three-scroll, Rabinovich–Fabrikant, Aizawa, Newton–Leipnik, Sakarya, the Rikitake dynamo, Shimizu–Morioka, the finance system, Coullet, Genesio–Tesi — traced in time order so the cloud crawls along itself; the Clifford and de Jong maps lifted into depth; a Gielis supershape; a real spherical harmonic drawn as an orbital; a Lissajous knot and a torus knot; the Hopf fibration; Chladni sand; four L-system plants; a Voronoi foam; a fractal flame, the Buddhabrot and a hyperbolic tiling; a seashell; the Sierpinski tetrahedron, the Menger sponge and the Mandelbulb; the Mandelbrot and a Julia set as reliefs. Each is a cloud like any other once made — chosen by name, crossed to with a scene change, captured as a look's source — and comes back on launch.
  • Two attractors that were not attractors. Every named flow is now tested for chaos rather than for looks: a test integrates all twenty-three and measures the largest Lyapunov exponent, following a neighbour and renormalising. Two failed. Halvorsen at a = 1.89 and the Hadley circulation at a = 0.2 had both fallen onto limit cycles — which fill the same box, crawl along themselves, and look in any still frame exactly like attractors. They are back on 1.4 and Lorenz' own 0.25, and both are chaotic again.
  • Wind on every form. /shape/wind blows through the field — an Arnold–Beltrami–Childress flow, a steady solution of Euler's equations, divergence-free and chaotic in its streamlines — read as a displacement of where each point already is, so it costs no state and works on a scan exactly as on a sphere. Zero by default; every look saved before it draws as it did.
  • Knobs on the generators. The supershape's exponents, a knot's windings, the Chladni mode numbers, the Julia constant, the plant's rule and angle, the automaton's rule: pick one and its row opens, and the spec carries what you set — gen:torus-knot?p=2;q=5. quadratic is Sprott's search for a chaotic quadratic map, and its one knob is the seed: roll is an attractor nobody has seen. quadratic flow is the same search with an integrator inside it — random quadratic vector fields rather than maps, which give smooth ribbons where the maps give dust.
  • Thirteen clouds that were alive before those. slime is Physarum: sixty-five thousand agents, one per point, that leave a trail and steer towards the strongest one they can see. Nothing in the three rules knows about paths, and a transport network comes out anyway — which is what the real organism does when it reproduces the Tokyo rail map out of oat flakes. swarmalators swarm and synchronise at once, each depending on the other: five states out of two numbers, with sharp transitions the audio walks between. cloth is a sheet of sixty-five thousand particles hung from its top edge in the same Arnold–Beltrami–Childress wind /shape/wind blows, with the links solved as constraints rather than springs, because a constraint pass cannot add energy.
  • Ten clouds that are alive. simulate… beside receive runs a simulation as the live cloud, driven by the audio: fluid, Stam's stable solver for the Navier–Stokes equations on an endless sheet, with vorticity confinement and sixty-five thousand tracers; reaction, Gray–Scott reaction–diffusion, where spots grow, split and heal; flock, four thousand boids drawing streaks; wind, tracers in curl noise; kuramoto, coupled oscillators that a loud passage locks into a ribbon; life, a three-dimensional cellular automaton; orbits, five hundred bodies pulling on each other round a heavy centre, each drawing its last two seconds as an arc; pendulum, four thousand double pendulums hung in a sheet that swings as one surface, creases, then tears; smoke, the fluid solver in three dimensions with heat, a plume that rises and rolls up; and liquid, four thousand particles of water in a box that tilts, gravity swinging round once a bar so it pours from corner to corner. The one running is remembered across launches.
  • The automaton grows a third field. A rule is survive/born/states now. Past two states a cell that fails to survive counts down instead of dying, one state a generation, and only the top of the ramp counts as a live neighbour — the ash left behind is drawn dimmer than the front, and turns a flat rule into a solid that grows, hollows and crusts. 4/4/5 is a spiking crystal, 4-7/6-8/10 boils.
  • A silent sender no longer holds the stream shut. The receiver took the first connection that arrived and read it until it closed or broke — and a sender that goes quiet without closing, which is what a phone that slept or an app sent to the background leaves behind, does neither. It kept the only reading slot for the life of the app while every later connection, including the sender restarting, queued behind it delivering nothing. Found with 408,952 bytes sitting unread in a socket. The listener now stays bound and the most recently arrived sender is the one being read, which needs no guess about how long a slow scan is allowed to think. A rescan button covers the case with nothing to react to: a sender attached and quiet, on an address that has not changed.
  • Crossing between clouds is what a scene change does. The cloud pair used to be three sliders in the parameter list — pick two slots by index, then ride the blend between them by hand. That was one control too many and one idea too many: the pair only exists in order to cross from one cloud to another, and the app already knows when a crossing is happening because it is the one running it. Choosing a cloud is now clicking its name, where the names are; a scene transition does the morph, and nothing else can reach it. A slot is an index, and an index is unreadable once anything has been loaded.
  • A modulator belongs to the parameter it drives. The row's control used to be a button labelled “LFO 1” that routed the first LFO in the rack at a fixed depth — so everything you modulated got the same LFO, and shaping it meant leaving the row to go and find it. Press ~ and the parameter gets a modulator of its own, opened underneath: source, shape, cycle length in beats, depth. Pointing several parameters at one shared LFO is still there, one step further in — where it belongs, since sharing is the special case.
  • Modulators can be given an in and an out point. Depth swings a parameter either side of wherever the fader is. An explicit range says where the value actually goes — set in the parameter's own units, not as a fraction of anything. The trade is that the fader stops moving that parameter, and the row says so rather than leaving you to wonder.
  • The parameter list is a third of the length. Two thirds of it was repeated structure: four identical copies of the sixteen vector-layer parameters, four gravity wells, two lamps, four inks. Those are now instances that open when something in them is off its default, so what you are not using costs one row instead of sixteen — 66 rows on opening instead of 176, with nothing removed. There is also a changed filter, for the question the name filter cannot answer.
  • The lighting controls were unfindable. 0.23.0 shipped them into a section headed MORE with a note meant for whoever was editing the panel. They are under STAGE, where they belong.
  • A live point-cloud stream ran at about twelve frames a second. 0.23.0 added normal fitting to the single path a cloud takes to the GPU — and a stream goes through that path once per arriving frame, so every frame fitted normals to sixty-five thousand points. That was 180 ms a frame; it is now under three. Three further faults found in the same area are fixed with it, including normals coming out wrong on any cloud smaller than a slot, which is most of them.
  • Light, for point clouds. Nothing in the renderer knew where a light was: a point's colour was its palette entry times the scan's own colour times a distance fade. Now there are two movable lamps — position, reach, level and colour — that fall off with distance and work on anything with a position, so you can walk one through a scan and have it reveal the scan. Alongside them a directional sun that lights surfaces: the wall facing it comes up, the wall facing away goes down. Torch puts a lamp on the camera. All of it is off by default, and off means the picture is exactly what it was — every preset you have saved renders identically.
  • Normals: read, estimated, or absent — never invented. A point cloud is points; whether it also knows which way its surface faces is up to whoever exported it, and most exports leave the field empty. vizz reads them from a PLY that has them and works them out from each point's neighbours when it does not, in about a tenth of a second as a cloud loads. A cloud with no surface at all — a procedural shape, a video frame — is left alone and the sun simply does nothing to it, rather than lighting it from a direction nobody measured.
  • Ten camera moves. Orbit, sway, push, pull, crane, spiral, look around, fly through, walkthrough — four legs and four corners at eye level, inside the cloud — and a slow drift for long ambient sections. Rate is in bars, so a move locks to the same clock as the sequencer. Every one is added to the camera your faders already describe rather than written back into it, so switching a move off puts you exactly where you were and a move running is never a reason you cannot still steer.
  • A big scan now shows all of itself. Loading a cloud kept the first sixty-five thousand points rather than a sample across the whole thing — and scanners write in scan order, so a five-million-point room was showing one corner of itself. It now strides the whole cloud. If you have a look built on a large scan it will render more of that scan than it used to.
  • Shows: one project per set, switched from the top of the app. Everything the app remembered sat in one flat directory, so a machine held exactly one show — fine for an instrument you set up once, wrong for one that goes to two gigs a week. A show is now a folder of its own holding both grids, the pages of pads, your looks, your patches, your fader layout and your slider ranges, and the name at the start of the panel and of the performance strip is which one is open. Its menu is the list, plus new show, save as, rename and delete. Your output size, audio device and controller map stay where they are: they describe the rig in front of you, not the set you are playing. There is still no save button, because everything is still written the moment it changes — “save as” means copy this show and carry on in the copy. Upgrading moves what you already have into Show 1, nothing copied and nothing left behind.
  • A full preset library no longer takes the row with it. The preset row drew one button per preset and was written when a library was a handful. The built-in set makes it a hundred and sixty, and the block ran past what the column could draw — so it vanished entirely rather than overflowing visibly, which is the confusing way round. It is bounded now and scrolls, so every preset stays reachable.
  • The built-in set could not actually be loaded. On a machine that already has a show the set does not install itself, so right-clicking the + beside the deck chips was the only route to it — and that route did not work. The confirm is an armed button, and clicking to arm it closed the menu it lived in, taking the second click's target with it. Deleting a page was broken the same way. Both now work, both driven by real clicks in a test.
  • Decks: the pads as pages, one per song. Sixteen scenes was a generous evening for one continuous set and nowhere near enough for twelve songs that each want their own looks. A deck is a page of both grids together, switched live. Looks stay in one pool, so the same one can sit on a pad in every song and refining it improves all twelve. Turning a page fires nothing and moves no parameter: whatever is on screen stays until you press a pad, because every page turn happens in front of an audience.
  • vizz follows Resolume. With OSC Output on in Arena, launching a column fires the scene pad and the gravity pad of that number together, and choosing a deck picks the song here. A deck is the song, a column is the section — so one launch moves the video, the lights and the field to the same place. Off unless you ask for it: the listener binds every interface, and following hands anyone on venue wifi the scene transport.
  • A show in the box. A machine that has never had one set up opens on twenty songs of eight sections — Intro, Build, Break, Drop, Bridge, Peak, Outro, Blackout, the same eight a lighting rig uses. Hard-edged flat geometry on black paper, layers at close frequencies interfering into moiré. Every pad is an ordinary preset, so any of them is one store away from being yours.
  • A pattern's own movement is now a control. Vector layers drifted on their own, from a constant buried in the renderer — real, deliberate, and invisible to everything: no parameter held it, nothing could show it, and the only way to still a layer was to stop the whole particle field. It is /lN/drift now, so it takes a fader, learns a MIDI control, can be modulated, runs backwards, and zero is genuinely still. Existing looks are unchanged.
  • The panel's ~ means "this is moving". It used to mean "has a modulation route", which is a different question from the one you ask: a scene blend in flight or a preset still arriving moved the picture and lit nothing. When something moves with nothing routed to it, the hover says so.
  • Assigning a fader looks like a gesture. The name and the "assign" placeholder are buttons now; the picker opens under the fader that opened it, and has a filter box focused on arrival — type a few letters and press Enter.
  • Resync and lock for the two sequencers. Put the scene and gravity grids back on their first pad on the same step, and optionally keep them on the same rate and curve so they cannot drift apart again.
  • Loaded pads on a controller are brighter. They were lit one step above off, which on real hardware reads as dim orange rather than the neutral grey the palette table claims. The three colours can also be set at launch with VIZZ_PAD_COLOURS.
  • Update checking stopped costing frames. With an update available, vizz was running a signature check sixty times a second on the render thread to re-answer a question whose answer cannot change.
  • The faders no longer disappear on a short window. At some window sizes the whole fader block — all sixteen and the master with them — was laid out below the bottom edge and thrown away, so the CONTROLS heading sat over nothing and the dim fader that recovers a black output was simply gone. When there is genuinely no room the sections above stand down instead: the faders are what you play, and they should be the last thing to give way rather than the first.
  • The master fader keeps its name. Its caption overhung its column at every size, invisibly, until the window was narrow enough to push it off the screen entirely — leaving the master looking like a nameless fader on the end of the row.
  • The vector layers can be found and started from the performance screen. The strip used to be invisible until a layer was already running, and nothing on that screen could start one — the only way in was the parameter list on the other screen. Now there is one line when nothing is on, and right-clicking a layer's generator or blend mode lists every choice instead of cycling backwards through them.
  • A stuck pointer is caught and corrected. If the interface ever missed a mouse release it went on believing the button was held, and the next move carried on dragging. Releases are now synthesised where they provably cannot arrive, and a genuinely stuck pointer says so in the log.
  • vizz updates itself. Download and install from the banner, without leaving the app — your patches, presets, palettes and mappings all live outside the bundle and are untouched. Every step is one you press: the check happens on its own, nothing else does, and the install refuses while a recording is running. Nothing is replaced while it is running either — the swap waits for vizz to quit, and puts the old copy back if it fails. A download has to be signed by the same Developer ID as the copy you are running, or it is refused.
  • Ready-made modulators, one click from a fader. Fourteen of them — sweeps, beat and bar pulses, rise, fall, steps, kick, snare, highs, loudness, wobble, random step, flicker. Click a fader's value to pick one. Each brings its own source, so two faders never fight over one oscillator, and what it builds stays on the modulation canvas to read and edit.
  • The APC40 mkII arrives mapped. Gravity on the top two rows of the clip grid, scenes on the bottom two, the middle row left clear as a landmark for the hand. The eight track faders take the eight parameters on the performance layout's first row; the master fader takes master dim. Nothing you have already mapped is overwritten.
  • And it lights up. vizz now sends MIDI out: a pad holding a preset glows, the one playing goes green, and the one the sequencer will fire next goes amber.
  • A zero blend time is a cut. It used to still animate — the grid finished instantly but each parameter's own smoothing kept easing — which made the one setting you reach for when you want a hard cut on a beat appear to do nothing.
  • Blank scenes. Right-click any pad to store a blank: every parameter that layer owns at the bottom of its range. An ending, or a hole to punch back out of.
  • Faster frames. Two per-frame system calls removed from the panel — one enumerated every mounted volume, the other re-read every saved preset from disk. The health log now also splits out how long the interface took, so a slow frame says which half to look at.
  • The faders, rebuilt. Each one is now a dark well milled into the deck, a column of light in it, and a near-white waterline at the surface of that light which is the value. A hole rather than a raised block, because when the output flashes white behind the interface a raised track closes on the lifting ground and vanishes at exactly the moment the screen matters — a hole opens away from it. Reference marks are engraved inside the well in two tones so they read against both the light and the dark.
  • They move properly too. A value that arrives from a controller or a preset glides to where it is; under your own hand there is none of that, because a fader that lags the hand on it is a fader you fight. Press far from the value to jump to it, near it to nudge from where it is, and hold Shift for a quarter-speed fine drag.
  • A mapped fader is a different shape, not a different word: a rail down the side, so a mapped deck and an unmapped one are different pictures from across a room.
  • Choose how many faders you want — four to twenty-four, saved with the rest of your set.
  • The performance view shows the performance. It used to be six sections stacked full-width over an opaque scrim, so the one thing the screen could not show you was the picture you were mixing. Now the controls take a column, the output takes the rest, and the pads and faders share a full-width deck along the bottom. Press V to stand the controls aside entirely and watch the output.
  • The preview is the real frame. The output is drawn into its pane and letterboxed to the master's aspect, rather than being glimpsed through a hole in the interface — which showed whichever part of the render happened to sit behind the gap.
  • Presets group by what they were built on — your scan, your typed words, the live stream — recorded when the look is saved. Existing presets keep working and group under “other” until re-saved.
  • A panel you can scan. Ten sections became three clusters; parameter names lead their rows in a proper column; and the narrow, route and learn buttons appear on hover instead of sitting on all 157 rows at once.
  • Scene and gravity pads are told apart by colour, each grid's controls fit one grouped row, and a loaded cloud can be put on screen by clicking it.
  • No change to the app itself — same build as 0.15.2. Releases are now built against the committed lockfile rather than whatever resolves on the day, so a signed download contains the dependency versions that were actually reviewed, and a version bump that forgets the lockfile stops the release instead of slipping past it.
  • Syphon output is the right way up. Metal renders with the origin at the top left and Syphon's convention is OpenGL's, origin at the bottom, so published frames needed a flip flag that defaulted to off — every receiver showed vizz upside down, and the only remedy was a command-line flag nobody double-clicking the app can reach.
  • Live point clouds hold still. A streamed cloud was re-measured and re-fitted every frame, so one stray LiDAR return at the back of the room rescaled everything and a subject leaning slid everything — steady geometry arriving visibly swimming. Streams now use an outlier-resistant fit that eases rather than snapping.
  • Streaming waits for the sender by default, which is the direction apps like LOTA actually work: they push to a receiver address rather than serving. The app also asks for local network access, which macOS 15 gates and which fails silently without it.
  • Receive a live point cloud from LOTA. vizz read only concatenated PLY files — a header declaring the vertex count, then the body. Apps that stream point clouds often send no header at all, just a count and then fixed-size points, so there was nothing to parse and the stream was refused. Both wire formats are now read, and which one is on the socket is worked out from the bytes rather than chosen from a menu.
  • A stream can be started from the panel. Receiving used to be a launch flag: set before startup, by someone who knew it existed, silent afterwards. The clouds section now takes an address, and once running shows whether a sender is attached and how many points are arriving — the number that tells a quiet socket from a working one mid-set.
  • Recording that cannot quietly eat the disk. A take used to be lossless PNG of every rendered frame at full size — about 800 MB a second at 1080p60, with nothing said before or during. Now the panel shows the rate, the free space and how long that gives you before you start; the take stops itself at a disk floor or an optional duration, keeping everything written. New settings: a record frame rate independent of the render rate, JPEG at quality 92 by default (roughly a tenth of PNG, with lossless one click away), and a countdown so a take does not open on the hand that started it.
  • Camera input actually works. A bundled app needs both a usage description and a hardened-runtime entitlement to open a capture device, and 0.14.0 shipped neither — AVFoundation refused with “add new input: Rejected”, an error that names the input rather than the permission.
  • Loaded clouds have a way in. Click a cloud in the list to put it on screen, or its “b” button to make it the far end of the morph. The mechanism was three parameters apart and only ever set by the drop itself.
  • Live input you can find. A video in section in the panel, beside audio: it lists every NDI sender on the network, every Syphon server on the Mac and every camera or capture card, and connects to one with a click. Syphon input and camera capture are new; NDI receive existed but only as a command-line flag, which is a feature nobody finds. The built-in test pattern sits at the top of the list, because it is the thing to reach for when nothing appears.
  • The panel reads as what it does. The parameter list was generated from OSC addresses, so it showed the network namespace — pal, vec and four peers called l1…l4. It is now organised into SHAPE, LOOK, PRINT, STAGE and OUTPUT, in the order a look gets built, with a caption on every group saying what it is for.
  • The gravity sequencer had no way in. Its row only appeared once a pad was filled — but the row held the only button that could fill it, so on a fresh install the layer was unreachable from every screen. The empty state now offers a one-click capture.
  • Downloads carry their version. Releases are now vizz-0.14.0.app.zip, so a Downloads folder holding several of them can be told apart without unzipping each one.
  • Vector layers. The print side of the app: four layers of hard-edged procedural pattern — rings, stripes, checker, polygon, star, rays, dots — in flat ink colours from a shared four-slot palette, composited with multiply/screen/difference blends. Two layers at near frequencies interfere into moiré, which is the whole point. Edges are analytically antialiased, so they stay razor-sharp at any resolution, and blending happens in encoded space the way print does. Three looks ship on the preset row: Interference, Poster and Signal.
  • Play them like everything else. The layers are ordinary parameters, so OSC, MIDI learn, presets, scene morphing and the modulation canvas all work on them unwired. A dedicated LAYERS strip on the performance layout cycles generator and blend mode without leaving the screen, and the shipped Pulse patch makes a layer breathe on the kick out of the box. /vec/place switches the stack between living inside the feedback chain and printing clean over the top.
  • An interaction review of the whole instrument. Nineteen fixes against Nielsen's heuristics. Every destructive click now arms before it fires — including the canvas new button, which used to erase a patch on one press with no undo. Latched punch buttons look different from held ones, the recalled preset is marked on both screens, right-click reset finally works on the performance faders as the overlay always promised, and the shortcuts list learned the mouse gestures nobody could discover.
  • One design language. Colour, type, spacing, radii, motion timings and the shared widgets moved into a vizz-design crate — one meaning, one colour, everywhere, enforced by a test that fails if a screen restates a state colour by hand.
  • Live video as a point cloud. An incoming NDI feed becomes particles: each pixel a point, with the z axis offset by luminance or colour so a face turns into relief you can orbit, morph against any other cloud, and drive with everything else. /video/depth sets how far the relief pushes and /video/relief chooses what drives it.
  • A test pattern that needs no network. The built-in source proves the whole video path with no NDI runtime and no sender on the wire — which is also what lets CI run the video shader on real Metal hardware and check the pixels, not just the exit code.
  • A documentation site. Every OSC address, held to the parameter registry by a test, so the reference cannot drift from the app.
  • Punch FX. The things you do on the drop: flash, blackout, invert and a real frame-freeze, plus a beat-synced strobe with its own division. Hold-buttons on the performance layout (shift-click latches), Space is the flash key, and MIDI bindings are momentary for free. Gestures live outside presets — no recall can leave the output inverted.
  • Rhythm tools. Three new graph nodes — Beat trigger, Gate with hysteresis, and a retriggerable Envelope — so "kick in, size punches out" is three nodes and two wires. The beat clock can follow MIDI clock from a DJ mixer, with a tempo estimator that shrugs off USB jitter; tap and auto always win back control.
  • Words and pictures as clouds. Type a word and the particles form it, morphable like any shape and still there after a restart. Drop a PNG or JPEG for a coloured relief that keeps a logo's silhouette. The cloud bank grows to eight slots so files, words, images and the live stream stop evicting each other.
  • Fullscreen and a recorder. F11 fills the monitor the window is on, Esc steps back out, and --fullscreen starts venues that way. New /record/active captures the master as a PNG sequence that never stalls the show — drops are counted on the red REC chip, and a full disk stops the take with one notice.
  • Recall always wins. A preset recalled during a scene transition is no longer silently overwritten by the blend, and pressing its number again snaps back after hand-tweaking. The autopilot walks past a pad whose preset was deleted instead of wedging on it every bar.
  • The canvas tells the truth. A Param node aimed at nothing says missing; a wire refused for making a loop says why; save and load failures read red, not green. The canvas also remembers its pan, zoom and patch name across launches.
  • State files survive a second instance. Atomic writes no longer share temp names between processes, the MIDI map follows XDG_CONFIG_HOME like everything else, re-dropping an edited palette reloads it in place, and quitting flushes the newest MIDI binding.
  • Fullscreen earns its pixels. At 1080p the faders grow to thumb size and fill the window; duplicate labels disambiguate ("color spread" vs "particles spread"); a live-set's worth of copy now tells one story per control.
  • The OSC reference is complete and enforced. Every one of the 76 addresses, with ranges checked against the running registry by a test — plus honest --width precedence, a title bar that only claims what bound, and quit without the two-second stall.
  • The gravity layer. Four attractors and repulsors that bend the cloud, sitting over the scenes with their own presets and their own sixteen-pad grid — a look firing cannot disturb the wells, and a well cannot disturb the look.
  • Drop files onto the window. Point clouds as PLY, XYZ, PTS or CSV; your own colour palettes as GIMP .gpl or a list of hex colours. Both come back on the next launch.
  • Output size and render size are separate, with a 16-bit float master behind a toggle. Render above 1× for free anti-aliasing, below it for frame rate on a struggling machine.
  • A MIDI button can fire one pad. A binding can carry a slot, so sixteen buttons address sixteen scenes instead of all firing the last one. Existing midi.json files load unchanged.
  • Fixed: the field collapsed at high counts. A float hash ran out of precision above ~50k particles, so bigger counts drew repeats on top of each other. The count slider buys density all the way up now — every preset's look shifts slightly.
  • Escape asks before it quits, saving over a preset says so first, and a pre-1.0 review's worth of smaller fixes — full notes on the release.
  • Scenes name presets. A pad references a saved look rather than owning a copy of it, which is what makes the workflow work: prepare any number of looks at a desk, load sixteen into the grid at performance time.
  • The performance layout, rebuilt. Sixteen faders with MIDI learn and modulation marks, the grid and transport beside them, and text contrast chosen for a dark room rather than a desk.
  • Background colour, down to fully transparent — vizz as a layer in someone else's mix rather than the whole picture.
  • An audio input picker, camera panning with a reset to centre, and the control panel cut back to its one job: building a look.
  • The scene grid. Sixteen pads, and moving between two of them takes musical time rather than a frame. The blend is in the parameters and the point-cloud geometry, not a dissolve between two renders — one field moving, not two at half opacity. Beat-synced autopilot walks the filled pads on its own.
  • Audio sensitivity in decibels, and much higher by default — the top band barely moved before. fit sets every band from what is actually arriving.
  • An app icon, rendered by vizz itself.
  • Fixed: the Syphon output was a white box. The frame was published as sRGB, so the receiver read it a second time. It now goes out through a linear view of the same texture.
  • Fixed: mod would not turn off. Each press added another route on top of the last, so the modulation only ever got deeper. It is a toggle now.
  • Slider ranges can be narrowed. Zoom a parameter in to the part of its range you are actually performing in.
  • The frame rate readout no longer nudges the status line when it crosses 100.
  • Live point clouds. Stream PLY over TCP, listen for a sender, or watch a file rewritten in place.
  • NDI video input. Discovery, connection and capture. Not drawn to screen yet.
  • Windows built and tested in CI, on all three platforms now.
  • The ? shortcut list now opens with the panel hidden and from the performance layout — the two places you would ask for it.
  • Fixed: the picture saturated to white within seconds. With the room off — the default — the frame was never cleared. Present in 0.3.0 and 0.4.0.
  • Presets. Six built in, your own saved alongside, any of the first ten on a number key, OSC or a MIDI button.
  • Control panel rework. Status collapsed to one line, parameters grouped and filterable with /, modulated ones marked, stepped ones named rather than numbered.
  • Presets on the performance layout; fit on the node canvas.
  • First signed and notarized release — no more right-click → Open.
  • Steerable room perspective. Depth, convergence and a vanishing point that moves, with the opening staying locked to the frame edge.
  • The point cloud can sit inside the room and take its forced perspective.
  • Point clouds. PLY and XYZ import with colour, and morphing between two clouds.
  • A real camera with orbit, field of view and depth of field, and the wireframe room.
  • Patch storage, the node palette, and the performance layout.
  • The node canvas for modulation, and the release preflight.
  • First release: the particle field, Syphon and NDI output, OSC.