Skip to content

Slitscan

Stacks N time-shifted copies of the upstream along an axis — every row (or column) is a different moment in time. Produces the "waterfall of pixels" look popularised by François Vogel.

Category: Time Menu path: Time > Slitscan

Ports

PortTypeDirectionDescription
inimageRgba16finputUpstream animated content (typically a video chain).
outimageRgba16foutputSlitscan composite — each output pixel reads from a different time slice.

Parameters

Each mode reads a subset of these params — mode, axis, and direction apply in every mode; sampleLine applies in FrozenLine and Scan; samples, frameSpan, smooth, and gamma apply in FrozenLine and Smear. The Properties panel only shows the params the current mode reads (hiding is cosmetic — hidden params keep their values, keyframes, and expose-channel connections).

ParamTypeDefaultDescription
modeenumFrozenLineFrozenLine = Vogel-style. The current frame shows untouched up to the sample line; past the line, every row pulls the sample-line pixels at a progressively older moment. Smear = the whole image is time-warped row-by-row, no static portion. Scan = flatbed-scanner: animate sampleLine to sweep the frame — rows the head has passed freeze at the moment it crossed them, rows ahead stay live (see Scan mode below).
sampleLinescalar0.5Position of the sample line along axis, normalized 0–1 across the composition (0.25 = 25% across the comp, always — the position is unaffected by internal overscan). FrozenLine + Scan — ignored in Smear mode. Draggable directly in the viewport when the node is selected. In Scan mode this is the scan head — keyframe it (or drag it with auto-key on) to lay down the sweep.
samplesscalar24Number of time slices, K. Each slice is a full upstream re-evaluation. Clamped 2–32. FrozenLine/Smear only — Scan mode has continuous per-row time and ignores it.
frameSpanscalar60Total frames covered across the time axis. Slice 0 = current frame, slice K-1 = comp_frame - frameSpan. FrozenLine/Smear only — Scan's history depth is the sweep itself.
axisenumYAxis along which time runs. Y = vertical waterfall. X = horizontal smear. All modes.
directionenumForwardForward = newest at the start of the axis (top for Y, left for X). Reverse flips it. All modes.
smoothbooleantrueBilinear-blend between adjacent slices for smooth transitions. Off = banded, hard transitions. FrozenLine/Smear only — Scan writes whole rows, no inter-slice blending.
gammascalar1Distribution shaping. 1 = linear time-per-pixel. >1 = more axis-pixels spent on the older half (long tail of past). <1 = more spent near now (frozen near current frame, fast smear into the past). FrozenLine/Smear only.

Expose Channels

When enabled (E button on node header), adds input ports that override params via edge connections:

PortTypeOverrides
samples_inscalarsamples
frameSpan_inscalarframeSpan
sampleLine_inscalarsampleLine
gamma_inscalargamma

How It Works

For each of the K slices, the engine re-evaluates the upstream subgraph at comp_frame - i * (frameSpan / (K-1)), exactly the way Echo does. The K resulting frames are stacked into a 2D texture array on the GPU. The final fragment shader's behavior depends on mode:

  • FrozenLine (default, the Vogel look): for output pixels whose axis coordinate is on the "newest" side of sampleLine, sample slice 0 (the current frame) at the pixel's actual UV — pass-through. For pixels past the sample line, sample the K array based on the pixel's distance from the line, but read the source at (uv.x, sampleLine) instead of the pixel's own UV — every row in the drip region shows the sample-line pixels at a progressively older moment.
  • Smear: every output pixel reads from the array layer corresponding to its position along the axis, at its own UV. The whole image varies in time.

Both modes do bilinear blending between adjacent layers when smooth = true. The cost scales linearly with samples. On video chains this is unusable without a FileCache between the source and Slitscan — random-frame access on a video decoder is orders of magnitude slower than reading cached frames from disk.

The time axis is comp-relative: sampleLine and the gamma distribution are measured against the composition, not the internal render canvas, so the frozen line stays put even when another branch of the layer inflates the render canvas (overscan). Canvas regions outside the comp continue the same mapping.

Viewport gizmo: When a Slitscan node in FrozenLine or Scan mode is selected, the sample line appears as a draggable dashed line in the viewer (horizontal for axis Y, vertical for axis X, flipped by direction). Drag the line or its midpoint handle to set sampleLine. If sampleLine_in is wired, the line renders read-only in the driven color — edit the upstream value instead. In Smear mode there is no line, so nothing is shown.

Scan mode (the photocopier drag-smear)

Scan turns the sample line into a scan head. As the animated sampleLine sweeps across the frame, every row (or column, axis X) the head passes is captured from that exact frame's upstream and stays frozen; rows the head hasn't reached yet show the live current input. When the upstream moves while the head sweeps — a T2D drag, a video subject shifting — the re-captured rows stretch into the classic xerox smear. When the subject holds still, it scans clean.

The workflow (moving your face on a photocopier):

  1. Wire an image or video through a Transform2D into Slitscan, set mode = Scan.
  2. Keyframe sampleLine from 0 to 1 across the shot (or select the node and drag the line in the viewport with auto-key on while scrubbing — each drag lays down a sweep keyframe).
  3. Keyframe the upstream Transform2D position so the subject moves while the head sweeps.
  4. Play. Rows captured while the subject moved smear into liquid streaks; rows captured while it held still stay crisp.

Exact semantics:

  • Between consecutive frames the head position is interpolated linearly and every row whose center was crossed is re-captured from the new frame, as whole rows. (Sub-frame supersampling of the crossing time is future work — fast sweeps quantize to one frame per band.)
  • The sweep may move non-monotonically: wiggle the head backward and re-crossed rows are RE-scanned — the latest crossing wins, like dragging the original backward on a real copier glass.
  • First frame rule: at the layer's first frame, rows on the already-passed side of the head's initial position (before it along the axis, after the direction flip) are captured from that first frame. Since that capture is the first frame's content, the layer's first rendered frame is always identical to its input — a static head degenerates to "frozen at layer start behind the line, live ahead of it".
  • Rows the head has never reached always show the live current input, matching FrozenLine's passthrough feel.
  • The scan state covers the comp rect: canvas regions outside the comp (overscan margins, only visible when a downstream node pulls them into frame) always show the live input — frozen history exists only inside the comp.
  • Time is layer-relative: the scan seeds at the layer's first frame, so sliding the clip on the timeline (which slides its keyframes with it) reproduces the identical scan relative to the clip.

Determinism: the output at frame N is a pure function of the upstream at every frame from layer start to N plus the head position at each of those frames. Scrub anywhere, export from any frame — the result is exactly what sequential playback produces, with no pre-roll. Sequential playback costs one upstream evaluation per frame; cold scrubs rebuild history from an internal checkpoint (kept every 16 frames, VRAM-budgeted) via the same upstream re-evaluation Echo uses. resetSimulation (the same reset that clears particle sims) drops the scan state; it rebuilds automatically on the next render.

Edits invalidate across layers too: when the scan watches another layer through a LayerSource, editing that layer (typing in its Text node, changing any param or keyframe) rebuilds the scan history just like an upstream edit in the scan's own layer — frozen rows never show stale content from before the edit. An animated source layer does not re-invalidate per frame; only definition changes do. Known limitation: a cold-scrub rebuild samples referenced layers at the current frame, so a scan over an animated LayerSource is exact during sequential playback and export, but a rebuild (scrub-in, post-edit) re-derives history from the source's current look.

Performance note: the accumulation lives on a comp-aligned canvas, independent of the layer's overscan render canvas — dragging the subject outside the frame (the photocopier move) can resize the render canvas freely without touching the scan history. Sequential playback and export cost one upstream evaluation per frame; cold scrubs rebuild from the nearest internal checkpoint (kept every 16 frames, VRAM-budgeted). The rebuild cost of a cold scrub scales with the distance from the layer's first frame, so trimming the layer to the section being scanned keeps worst-case scrubs cheap. Editing anything upstream of the Slitscan (or its own sweep keyframes) still invalidates the accumulation — the next render replays history from the layer start, deterministically.

Usage Examples

Vogel-style frozen waterfall (default look)

VideoSource → FileCache → Slitscan → Output. Default params: FrozenLine, sampleLine=0.5, axis Y, forward. The top half of the frame plays normally; below the midline, the pixels at the midline drip downward through time. New content "falls" out of the sample line as time advances. Move the camera or have something cross the sample line to see the most dramatic drips.

Vogel near the bottom edge

Same chain with sampleLine = 0.85. Most of the image plays normally; only the bottom 15% of the frame becomes the time-drip region — a much more subtle effect that reads as "the floor is frozen in time."

Smear mode (no static portion)

Set mode = Smear. Whole image is time-warped — every row is a different historical frame, no pass-through region. Useful for abstract / liquid looks rather than figurative time-photography.

Frozen-with-tail

gamma = 2.0 in either mode. Most of the time-axis is spent on the recent past, with a long compressed tail of older content at the far edge.

Horizontal time-drip

axis = X, direction = Forward, sampleLine = 0.5. Left half of the frame plays normally; right half drips horizontally — pixels at the midline column smear rightward through time.

Animated sample line

Drive sampleLine_in from a Time-driven Math node. Watch the boundary between live and frozen content sweep across the frame. Works in Scan mode too — the driven value is the scan head, resolved per frame.

Photocopier face smear (Scan mode)

ImageSource (portrait) → Transform2D → Slitscan (Scan) → Output. Keyframe sampleLine 0→1 over the shot; keyframe the T2D position to drag the portrait sideways during the middle of the sweep. The rows scanned during the drag stretch into streaks; the rows before and after stay clean — the classic xerox-while-moving artifact.

Tips

  • Always pair with FileCache. Without one, every frame re-decodes the video K times. With a FileCache between VideoSource and Slitscan, the K slices read straight from disk.
  • Memory budget. Slitscan allocates a texture array of size width × height × K at Rgba16Float = 8 bytes/pixel. At 1080p × 32 ≈ 130 MB. Drop samples for tighter machines.
  • Sub-frame distribution. frameSpan / (samples - 1) is the time step between adjacent slices. To get one slice per source frame, set frameSpan = samples - 1.
  • High samples + low frameSpan = ultra-smooth, short-history smear (great for liquid motion). Low samples + high frameSpan = punchy, banded chronophotography look — turn smooth off to lean into it.
  • For a stop-motion strobe within the smear, sandwich with PosterizeTime upstream of Slitscan.
  • Echo — same multi-time eval primitive, but blends the K frames temporally instead of stacking them spatially.
  • Time Shift — single-offset re-eval. Slitscan is N TimeShifts demuxed along an axis.
  • FileCache — the indispensable performance pivot for any time-warp on video.
  • Posterize Time — discrete-step playback. Stop-motion + Slitscan = strobed waterfall.