Nodes/LF Nodes/Seamless tile
ComfyUI Node

Seamless tile

Fix a non-tiling texture without a diffusion pass

By lucafoscili·Created 2 years ago·Updated 23 days ago· 36
Seamless tile
  • image
  • ui_widget
  • image
  • receipt
  • image_list
◄blend_fraction0.25►

The community's standard advice on tileable textures is blunt and correct: fix it at generation time. Set the model's convolutions to circular padding and the output tiles by construction. That's a checkbox in some UIs and a dedicated node in ComfyUI, and the corpus's own summary is "you cannot reliably add seamlessness afterward."

LF_SeamlessTile is the footnote to that advice. It adds seamlessness afterward, deterministically, in plain tensor math. Not by mirroring. Not by blurring the edges until the seam is a vibe. It's a specific trick that happens to work well on organic and noise-like textures, and it's the first step of the pack's own Iso Ground Tiles recipe.

How it works

Roll the image by half its width and half its height. Now the output's outer edges were the centre of the original - so they wrap perfectly, which is the property you wanted. But the original's edges are now a cross through the middle of the image, which is the seam you were trying to hide, relocated.

So the node blends the untouched original back in over a soft band around that centre cross, then fades that blend out again toward the output edges so the wrap at the border is never disturbed. A max of two 1-D ramps: one horizontal, one vertical, each multiplied by an edge fade. No diffusion pass, no randomness, no seed. Same input, same output, every time - which is worth more than it sounds when you're rebuilding a tileset you shipped last month.

It's honest about the trade. The blend band has to soften a stripe of the texture near the middle of the image. Narrow band, less softening, more visible residual seam; wide band, seam gone, more of the picture subtly mushed. That's the dial.

The inputs and outputs that matter

  • image - one or more textures. Batch in, batch out, same size as the input, no resizing anywhere.
  • blend_fraction - default 0.25, range 0.02 to 0.5. The width of the blend band as a fraction of the image size. This is the only real decision.

Outputs: image (the wrapped batch), receipt (blend fraction, per-image dimensions, the band widths in pixels and the method string), and image_list (the same as an authoritative list). Feed image straight into whatever needs a tileable texture - which, in this pack, usually means LF_IsoDiamondTiles.

How to install it

ComfyUI Manager → search LF Nodes → install → restart. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes
python -m pip install -r lf-nodes/requirements.txt

Pip with ComfyUI's interpreter. Requirements are the pack's usual heavy list (torch, opencv, rembg, av, transformers), so expect a chunky download even though this node needs little more than torch. lucafoscili/comfyui-lf is the archived predecessor repo - lf-nodes is the live one, and older forum links point at the wrong URL.

The pack ships an Iso Ground Tiles Workflow Runner card that wires this node in front of the diamond-tile cutter. It's opt-in: set WORKFLOW_RUNNER_ENABLED=true before starting ComfyUI.

Common issues & troubleshooting

You can see a faint cross or halo in the middle. That's the mechanism showing through. Widen blend_fraction to hide it better - and accept the softer centre. If the texture has strong directional structure (bricks, planks, a strong diagonal), no blend fraction will look clean, and this is the wrong tool for that texture.

The edges still don't match. Check what the input actually was. The node assumes the image was generated normally; if it already had a border - a vignette, a frame, a UI chrome edge - the roll relocates that border into the middle and nothing lines up. Crop first.

The output is 8×8 or smaller and errors. Minimum size is 8×8; below that the blend bands collapse. Not a realistic problem.

It broke my pixel art. Sharp-edged, hard-contrast art gets visibly ghosted by any blend. For tilesets at a fixed palette, generate with circular padding, or accept the ghost. This is the case where the KB's "fix it at generation" rule wins.

Nothing looks different. At low blend_fraction on a busy, high-frequency texture, the change can be subtle - the seam was already mostly masked by detail. Check the receipt to confirm the band widths, and test by tiling the result 3×3 in a viewer rather than judging a single tile on screen.

Category✨ LF Nodes/Image

Inputs (3)

NameTypeDefaultDescription
imageIMAGETexture(s) to make tileable. Output keeps the input size.
blend_fractionFLOAT0.250.02–0.5Width of the blend band as a fraction of the image size. Wider hides the seam better and softens more of the centre.
ui_widgetoptLF_MASONRY[object Object]—

Outputs (3)

NameTypeDescription
imageIMAGESeamlessly wrapping texture batch at the source size.
receiptJSONReceipt with the blend fraction and per-image dimensions.
image_listIMAGEThe same wrapped textures as an authoritative list.