Texture Seamless
Making a texture tile after the fact — the node that actually tries
- image
- mask
- image
- mask
- seamless_info
Let me be honest with you up front: the clean way to get a tileable texture is to generate it tileable, by flipping on circular padding at generation time. The seam-removal-after-the-fact route is, in the words of the modidex KB, "the can-kicking move" - the fix only works up to a point. But when you have an already-generated texture and re-rolling the seed isn't an option, Texture Seamless is the best band-aid in this pack, and it's a much better band-aid than the naive blur-the-edges move most people try first.
How it works
The node implements a two-stage seam fix. First, edge_match_low_frequency samples the edges of the image and rebuilds the low-frequency shading across the seam band so the two sides agree tonally - this is what kills the bright/dark mismatch you usually see at a seam, not just the hard line. Then the image is rolled by half a tile and smooth_seams blends across the center seam with seam_blur, while detail_preserve keeps the fine texture detail from getting mushed into the blend. If your image has an alpha channel, the alpha gets the same treatment, which matters for textures with transparency.
That's the whole architecture: match the low-frequency lighting first, blend the seam, protect the detail. blend_width sets the seam band size, edge_match_strength and edge_match_blur control the matching, and the optional mask lets you restrict the whole operation to a region. The node also emits the seam mask, so you can see exactly where it worked.
The inputs that matter
Inputs are image plus one settings_json box, with an optional mask. The knobs you'll actually touch:
edge_match_strength- how hard to force the two edges to agree tonally (0.85 default)seam_blurandseam_softness- how much the seam is smeareddetail_preserve- how much fine detail survives the blend (0.65 default; lower it if the seam looks smudged, raise it if you see a line)blend_width- the seam band width in pixels
Outputs: image (the fixed texture), mask (the seam band it worked on), and seamless_info with resolved settings plus mask coverage.
Installing it
Ships in MKRShift Nodes from criskb. ComfyUI Manager → "MKRShift Nodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
Restart ComfyUI; it's under MKRShift Nodes → Surface → Texture. No models or extra deps - numpy/Pillow/torch.
Common gotchas
New pack, no community lore, so trust the code. Standard MKRShift traps: malformed settings_json silently reverts to defaults, and out-of-range values clamp. The real-world gotcha is expectation management: this fixes tonal mismatches and hard lines, but if your texture has a large-scale feature that simply doesn't continue across the edge (a big shadow, a blob), no amount of seam blending hides it - that's the "can't reliably add seamlessness afterward" limit. For those, the honest move is to offset-check with the pack's Texture Offset node, see exactly where the geometry breaks, and regenerate with a tileable base. Use this node on organic materials (rock, sand, noise) where it shines; don't expect miracles on structured ones.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| settings_json | STRING | {"blend_width":24.0,"edge_match_strength":0.85,"edge_match_blur":18.0,"detail_preserve":0.65,"seam_blur":12.0,"seam_softness":12.0,"mask_feather":8.0,"invert_mask":false} | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| seamless_info | STRING | — |