DJZ Parallax V1
2.5D parallax from three stills — cheap depth, no depth model needed
- background_image
- image_1
- mask_1
- image_2
- mask_2
- IMAGE
Parallax is the oldest trick in the animation book: layers moving at different speeds read as depth, and your brain does the rest. DJZ Parallax V1 packages that as a node - you hand it a background plus two foreground layers with masks, tell each one a speed and a direction, and it renders a frame sequence that looks like you pushed a camera through a diorama. No depth model, no video model, no latent space involved. Just compositing math, done per frame.
Why you'd reach for it
You want a Ken Burns plus depth effect on a still that's actually made of separate elements. Think of a generated scene where you've cut out a character or a foreground object with a mask - now the background slides slowly, the character drifts at a different rate, and suddenly the flat image has parallax. Feed the output batch to a video encoder and you've got an animation that didn't cost you a single extra diffusion pass.
How it works
Each layer moves on its own track. For every frame, the node computes an offset from speed × frame_index projected along the direction angle - 0° moves right, 90° down, 180° left, 270° up. Then it samples the layer at that offset with wrapping (tile-style), so content scrolls out one edge and reappears at the other instead of leaving holes. Finally it composites top to bottom: background first, then layer 1 masked on top, then layer 2.
The mask isn't optional decoration - it's what separates layer 1 from layer 2 and both from the background. Generate these with a segmentation or matting node, or paint them.
The inputs that matter
You're setting three groups:
- background_image, image_1/mask_1, image_2/mask_2 - the layers. Two foregrounds is a reasonable sweet spot; each gets independent
*_speedand*_direction. - height / width - output frame size (64–2048). Everything gets sampled into these dimensions.
- fps and max_frames - frame rate and length of the output sequence. 60 frames at 24 fps is a 2.5-second loop.
Speeds run −10 to 10. Negative speed just reverses direction, which is handy for ping-pong loops. Direction is in degrees, and it's a float here so you can do diagonal drift (e.g. 45°).
Output
A single IMAGE batch - one tensor with max_frames frames - ready for a video combine node (like VHS or FFmpeg encoders) or a frame save.
Installing it
One node in the DJZ-Nodes pack:
cd ComfyUI/custom_nodes
git clone https://github.com/MushroomFleet/DJZ-Nodes
cd DJZ-Nodes
pip install -r requirements.txt
Or ComfyUI Manager → search "DJZ-Nodes" → install. It needs opencv-python (already in the pack's requirements); no models.
Troubleshooting
- It's slow. The layer sampling runs as a per-pixel loop in Python, not vectorized torch. At 512×512 and short clips it's fine; at 1024×1024 with 300 frames you'll be waiting. Keep
max_framessmall while you dial in speeds, and render long sequences at modest resolution. - Layers show black gaps or hard edges. The wrapping only fills the moving layer - the mask scrolls with its image, so if the mask doesn't cover the object fully, you'll see the background through it. Give your masks a little padding.
- Everything moves together. If the scene looks like one rigid slide, increase the ratio between layer speeds. The effect lives in the difference, not the absolute numbers.
- Node missing after an update. DJZ's
__init__.pydrops nodes whose imports fail - reinstallrequirements.txtand check the console for "Unable to import".
Inputs (15)
| Name | Type | Default | Description |
|---|---|---|---|
| background_image | IMAGE | — | |
| image_1 | IMAGE | — | |
| mask_1 | MASK | — | |
| image_2 | IMAGE | — | |
| mask_2 | MASK | — | |
| fps | INT | 241–60 | — |
| max_frames | INT | 601–1000 | — |
| height | INT | 51264–2048 | — |
| width | INT | 51264–2048 | — |
| background_speed | FLOAT | 1.0-10–10 | — |
| background_direction | FLOAT | 0-360–360 | — |
| image_1_speed | FLOAT | 2.0-10–10 | — |
| image_1_direction | FLOAT | 0-360–360 | — |
| image_2_speed | FLOAT | 3.0-10–10 | — |
| image_2_direction | FLOAT | 0-360–360 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |