Random Tiling (Latent)
Compose the field before you decode
- tiles
- tileset
- vae
- LATENT
The image-space RandomTiling node composes a big tiled field and then you decode it. This is the same thing in latent space: assemble the random Wang or Dual tiling while everything is still latent, and decode once at the end. If you're running a fully latent pipeline - LatentDualBoundaries → sampler → LatentTilePacking - this is the natural finale, and it saves you a pile of VAE round trips on what is often a very large output image.
What it does
Identical logic to RandomTiling: pick random tile placements that respect the edge-compatibility rules of the tileset (Wang edges or Dual corner scheme), lay them down in a height × width grid, and composite dual sets through the diamond mask - all on latent tensors. The only extra input is a vae, and it's there for a boring reason: the TILESET records resolution in pixels, but the latent tensors live at resolution // vae.downscale_ratio. The node asks for the VAE just to know that downscale factor, not to encode or decode anything. Give it the same VAE your pipeline already uses and it's correct.
Inputs and outputs
- tiles (LATENT) - your latent tile set
- tileset (TILESET, forceInput) - kind, colors, resolution, candidates; must come from an upstream node
- vae (VAE) - used for the latent downscale ratio
- width (INT, default 20), height (INT, default 20) - grid size in tiles
Output is a single LATENT. Slap a VAEDecode on it - one decode, and because it all happened in latent space, no accumulated decode/encode drift between stages.
Installing and notes
Standard pack install: git clone https://github.com/samsartor/content_aware_tiles into ComfyUI/custom_nodes (or ComfyUI Manager → "content_aware_tiles") and restart. No model downloads for the node itself.
Same constraints as the image version: a dual tileset must contain the full colors**4 * 2 interior + cross tiles, or you'll get a ValueError spelling out the expected count. And one latent-specific gotcha - a 20×20 field at 256px is a 5120px image, and in latent space that's still a fat tensor; the decode is the memory spike, so preview small (a 4×4) and only render the giant field when you're ready to commit. Expect no community troubleshooting threads on this research pack; the example workflow and the readable generation.py are your docs.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| tiles | LATENT | — | |
| tileset | TILESET | — | |
| vae | VAE | — | |
| width | INT | 20 | — |
| height | INT | 20 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| LATENT | LATENT | — |